summaryrefslogtreecommitdiff
path: root/lib/chef_zero/rest_base.rb
blob: a6e76320bdb9cce0639f36b14d531f909bacf3c1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
require 'chef_zero/rest_request'
require 'chef_zero/rest_error_response'
require 'chef/log'

module ChefZero
  class RestBase
    def initialize(server)
      @server = server
    end

    attr_reader :server

    def data
      server.data
    end

    def call(env)
      begin
        rest_path = env['PATH_INFO'].split('/').select { |part| part != "" }
        method = env['REQUEST_METHOD'].downcase.to_sym
        if !self.respond_to?(method)
          accept_methods = [:get, :put, :post, :delete].select { |m| self.respond_to?(m) }
          accept_methods_str = accept_methods.map { |m| m.to_s.upcase }.join(', ')
          return [405, {"Content-Type" => "text/plain", "Allow" => accept_methods_str}, "Bad request method for '#{env['REQUEST_PATH']}': #{env['REQUEST_METHOD']}"]
        end
        if json_only && !env['HTTP_ACCEPT'].split(';').include?('application/json')
          return [406, {"Content-Type" => "text/plain"}, "Must accept application/json"]
        end
        # Dispatch to get()/post()/put()/delete()
        begin
          self.send(method, RestRequest.new(env))
        rescue RestErrorResponse => e
          error(e.response_code, e.error)
        end
      rescue
        Chef::Log.error("#{$!.inspect}\n#{$!.backtrace.join("\n")}")
        raise
      end
    end

    def json_only
      true
    end

    def get_data(request, rest_path=nil)
      rest_path ||= request.rest_path
      # Grab the value we're looking for
      value = data
      rest_path.each do |path_part|
        if !value.has_key?(path_part)
          raise RestErrorResponse.new(404, "Object not found: #{build_uri(request.base_uri, rest_path)}")
        end
        value = value[path_part]
      end
      value
    end

    def error(response_code, error)
      json_response(response_code, {"error" => [error]})
    end

    def json_response(response_code, json)
      already_json_response(response_code, JSON.pretty_generate(json))
    end

    def already_json_response(response_code, json_text)
      [response_code, {"Content-Type" => "application/json"}, json_text]
    end

    def build_uri(base_uri, rest_path)
      RestBase::build_uri(base_uri, rest_path)
    end

    def self.build_uri(base_uri, rest_path)
      "#{base_uri}/#{rest_path.join('/')}"
    end

    def populate_defaults(request, response)
      response
    end
  end
end