diff --git a/lib/openapi_contracts/validators/headers.rb b/lib/openapi_contracts/validators/headers.rb index 0796710..f373f1f 100644 --- a/lib/openapi_contracts/validators/headers.rb +++ b/lib/openapi_contracts/validators/headers.rb @@ -19,6 +19,9 @@ def validate if value.blank? @errors << "Missing header #{header.name}" if header.required? else + # Header values arrive as strings; deserialize to the schema's type + # (per `style: simple`) before validating, as Doc::Parameter does. + value = OpenapiParameters::Converter.convert(value, header.schema) schemer = JSONSchemer.schema(header.schema) unless schemer.valid?(value) validation_errors = schemer.validate(value).to_a diff --git a/spec/fixtures/openapi/openapi.yaml b/spec/fixtures/openapi/openapi.yaml index fe1d888..103cc78 100644 --- a/spec/fixtures/openapi/openapi.yaml +++ b/spec/fixtures/openapi/openapi.yaml @@ -97,6 +97,10 @@ paths: responses: '200': description: Ok + headers: + x-rate-limit: + schema: + type: integer content: application/json: schema: diff --git a/spec/openapi_contracts/validators/headers_spec.rb b/spec/openapi_contracts/validators/headers_spec.rb index a27c81e..25feadb 100644 --- a/spec/openapi_contracts/validators/headers_spec.rb +++ b/spec/openapi_contracts/validators/headers_spec.rb @@ -70,4 +70,26 @@ end end end + + context 'with a non-string header type (style: simple)' do + include_context 'when using GET /pets' + + context 'when the value parses to the declared type' do + before { response_headers['x-rate-limit'] = '300' } + + it 'deserializes the value and has no errors' do + expect(subject.call).to be_empty + end + end + + context 'when the value does not parse to the declared type' do + before { response_headers['x-rate-limit'] = 'not-a-number' } + + it 'returns the error' do + expect(subject.call).to eq [ + 'Header x-rate-limit validation error: value at root is not an integer (value: not-a-number)' + ] + end + end + end end