Validate response headers based on specified header

Add validate_headers step in response validator.
Using JSON::Validator with validate header value with swagger header 
object.
This commit is contained in:
vinhbachsy 2016-10-18 21:45:55 +08:00
parent 10dd37896f
commit 5cf376891a
5 changed files with 79 additions and 1 deletions

View File

@ -13,6 +13,7 @@ module Rswag
def validate!(response) def validate!(response)
validate_code!(response.code) validate_code!(response.code)
validate_headers!(response.headers)
validate_body!(response.body) validate_body!(response.body)
end end
@ -24,6 +25,20 @@ module Rswag
end end
end end
def validate_headers!(headers)
header_schema = @api_metadata[:response][:headers]
return if header_schema.nil?
header_schema.each do |header_name, schema|
validate_header!(schema, header_name, headers[header_name.to_s])
end
end
def validate_header!(schema, header_name, header_value)
JSON::Validator.validate!(schema.merge(@global_metadata), header_value.to_json)
rescue JSON::Schema::ValidationError => ex
raise UnexpectedResponse, "Expected response headers #{header_name} to match schema: #{ex.message}"
end
def validate_body!(body) def validate_body!(body)
response_schema = @api_metadata[:response][:schema] response_schema = @api_metadata[:response][:schema]
return if response_schema.nil? return if response_schema.nil?
@ -34,7 +49,7 @@ module Rswag
.merge(@global_metadata.slice(:definitions)) .merge(@global_metadata.slice(:definitions))
JSON::Validator.validate!(validation_schema, body) JSON::Validator.validate!(validation_schema, body)
rescue JSON::Schema::ValidationError => ex rescue JSON::Schema::ValidationError => ex
raise UnexpectedResponse, "Expected response body to match schema: #{ex.message}" raise UnexpectedResponse, "Expected response body to match schema: #{ex.message}"
end end
end end
end end

View File

@ -66,6 +66,43 @@ module Rswag
it { expect { call }.to raise_error UnexpectedResponse } it { expect { call }.to raise_error UnexpectedResponse }
end end
end end
context "'headers' provided" do
before do
api_metadata[:response][:headers] = {
'X-Rate-Limit-Limit' => {
description: 'The number of allowed requests in the current period',
type: 'integer'
},
'X-Rate-Limit-Remaining' => {
description: 'The number of remaining requests in the current period',
type: 'integer'
},
'X-Rate-Limit-Reset' => {
description: 'The number of seconds left in the current period',
type: 'integer'
}
}
end
context 'response code & body matches' do
let(:response) { OpenStruct.new(code: 200, body: '{}', headers: {
'X-Rate-Limit-Limit' => 1,
'X-Rate-Limit-Remaining' => 1,
'X-Rate-Limit-Reset' => 1
}) }
it { expect { call }.to_not raise_error }
end
context 'response code matches & body does not' do
let(:response) { OpenStruct.new(code: 200, body: '{}', headers: {
'X-Rate-Limit-Limit' => 'invalid',
'X-Rate-Limit-Remaining' => 'invalid',
'X-Rate-Limit-Reset' => 'invalid'
}) }
it { expect { call }.to raise_error UnexpectedResponse }
end
end
end end
end end
end end

View File

@ -17,6 +17,10 @@ class BlogsController < ApplicationController
# GET /blogs/1 # GET /blogs/1
def show def show
@blog = Blog.find_by_id(params[:id]) @blog = Blog.find_by_id(params[:id])
fresh_when(@blog)
return unless stale?(@blog)
respond_with @blog, status: :not_found and return unless @blog respond_with @blog, status: :not_found and return unless @blog
respond_with @blog respond_with @blog
end end

View File

@ -50,6 +50,10 @@ describe 'Blogs API', type: :request, swagger_doc: 'v1/swagger.json' do
produces 'application/json' produces 'application/json'
response '200', 'blog found' do response '200', 'blog found' do
header 'ETag', type: :string
header 'Last-Modified', type: :string
header 'Cache-Control', type: :string
schema '$ref' => '#/definitions/blog' schema '$ref' => '#/definitions/blog'
response_examples 'application/json' => { response_examples 'application/json' => {

View File

@ -89,8 +89,26 @@
"responses": { "responses": {
"200": { "200": {
"description": "blog found", "description": "blog found",
"headers": {
"ETag": {
"type": "string"
},
"Last-Modified": {
"type": "string"
},
"Cache-Control": {
"type": "string"
}
},
"schema": { "schema": {
"$ref": "#/definitions/blog" "$ref": "#/definitions/blog"
},
"examples": {
"application/json": {
"id": 1,
"title": "Hello world!",
"content": "Hello world and hello universe. Thank you all very much!!!"
}
} }
}, },
"404": { "404": {