From f34c2686d2a4b7fe83f1449cc1c5cc38ac4b8a04 Mon Sep 17 00:00:00 2001 From: Andrew Brown Date: Thu, 13 Aug 2015 21:09:56 -0400 Subject: Further support for /server_api_version This adds checks to ensure that the requested API version is checked early on in the request cycle, to comply with RFC041. --- lib/chef_zero/rest_base.rb | 36 ++++++++++++++++++++++++++++++++---- lib/chef_zero/rest_request.rb | 4 ++++ 2 files changed, 36 insertions(+), 4 deletions(-) (limited to 'lib') diff --git a/lib/chef_zero/rest_base.rb b/lib/chef_zero/rest_base.rb index 48d423a..3036903 100644 --- a/lib/chef_zero/rest_base.rb +++ b/lib/chef_zero/rest_base.rb @@ -15,7 +15,29 @@ module ChefZero server.data_store end + def check_api_version(request) + version = request.api_version + return nil if version.nil? # Not present in headers + + if version.to_i.to_s != version # Version is not an Integer + return json_response(406, { "username" => request.requestor }, -1, -1) + elsif version.to_i > MAX_API_VERSION or version.to_i < MIN_API_VERSION + response = { + "error" => "invalid-x-ops-server-api-version", + "message" => "Specified version #{version} not supported", + "min_api_version" => MIN_API_VERSION, + "max_api_version" => MAX_API_VERSION + } + return json_response(406, response, version, -1) + else + return nil + end + end + def call(request) + response = check_api_version(request) + return response unless response.nil? + method = request.method.downcase.to_sym if !self.respond_to?(method) accept_methods = [:get, :put, :post, :delete].select { |m| self.respond_to?(m) } @@ -177,16 +199,22 @@ module ChefZero json_response(response_code, {"error" => [error]}) end - def json_response(response_code, json) - already_json_response(response_code, FFI_Yajl::Encoder.encode(json, :pretty => true)) + def json_response(response_code, json, request_version=0, response_version=0) + already_json_response(response_code, FFI_Yajl::Encoder.encode(json, :pretty => true), request_version, response_version) end def text_response(response_code, text) [response_code, {"Content-Type" => "text/plain"}, text] end - def already_json_response(response_code, json_text) - [response_code, {"Content-Type" => "application/json"}, json_text] + def already_json_response(response_code, json_text, request_version=0, response_version=0) + header = { "min_version" => MIN_API_VERSION, "max_version" => MAX_API_VERSION, + "request_version" => request_version, + "response_version" => response_version } + [ response_code, + { "Content-Type" => "application/json", + "X-Ops-Server-API-Version" => FFI_Yajl::Encoder.encode(header) }, + json_text ] end # To be called from inside rest endpoints diff --git a/lib/chef_zero/rest_request.rb b/lib/chef_zero/rest_request.rb index e79af7f..ea96110 100644 --- a/lib/chef_zero/rest_request.rb +++ b/lib/chef_zero/rest_request.rb @@ -18,6 +18,10 @@ module ChefZero @base_uri = value end + def api_version + @env['HTTP_X_OPS_SERVER_API_VERSION'] + end + def requestor @env['HTTP_X_OPS_USERID'] end -- cgit v1.2.1