pacto 0.4.0.rc1 → 0.4.0.rc2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +1 -1
- data/Gemfile +2 -7
- data/Rakefile +0 -5
- data/appveyor.yml +12 -0
- data/features/configuration/strict_matchers.feature +4 -4
- data/features/generate/generation.feature +8 -10
- data/features/support/env.rb +3 -7
- data/features/validate/validation.feature +3 -3
- data/lib/pacto.rb +5 -4
- data/lib/pacto/actors/json_generator.rb +1 -1
- data/lib/pacto/body_parsing.rb +42 -0
- data/lib/pacto/consumer/faraday_driver.rb +5 -2
- data/lib/pacto/contract.rb +23 -24
- data/lib/pacto/contract_factory.rb +4 -4
- data/lib/pacto/core/configuration.rb +18 -10
- data/lib/pacto/core/http_middleware.rb +1 -1
- data/lib/pacto/core/pacto_request.rb +3 -15
- data/lib/pacto/core/pacto_response.rb +3 -13
- data/lib/pacto/errors.rb +68 -0
- data/lib/pacto/formats/legacy/contract.rb +49 -0
- data/lib/pacto/formats/legacy/contract_builder.rb +129 -0
- data/lib/pacto/formats/legacy/contract_factory.rb +63 -0
- data/lib/pacto/formats/legacy/contract_generator.rb +77 -0
- data/lib/pacto/formats/legacy/generator/filters.rb +46 -0
- data/lib/pacto/formats/legacy/generator_hint.rb +36 -0
- data/lib/pacto/formats/legacy/request_clause.rb +39 -0
- data/lib/pacto/formats/legacy/response_clause.rb +31 -0
- data/lib/pacto/formats/swagger/contract.rb +86 -0
- data/lib/pacto/formats/swagger/contract_factory.rb +45 -0
- data/lib/pacto/formats/swagger/request_clause.rb +53 -0
- data/lib/pacto/formats/swagger/response_clause.rb +31 -0
- data/lib/pacto/generator.rb +4 -4
- data/lib/pacto/handlers/json_handler.rb +19 -0
- data/lib/pacto/handlers/text_handler.rb +17 -0
- data/lib/pacto/request_clause.rb +9 -19
- data/lib/pacto/response_clause.rb +4 -4
- data/lib/pacto/server.rb +41 -2
- data/lib/pacto/stubs/uri_pattern.rb +5 -5
- data/lib/pacto/stubs/webmock_adapter.rb +4 -1
- data/lib/pacto/test_helper.rb +16 -13
- data/lib/pacto/version.rb +1 -1
- data/pacto-server.gemspec +1 -3
- data/pacto.gemspec +1 -1
- data/sample_apis/user_api.rb +16 -0
- data/samples/contracts/user.json +51 -0
- data/samples/cops.rb +3 -0
- data/samples/server_cli.sh +3 -3
- data/spec/fabricators/contract_fabricator.rb +17 -8
- data/spec/fixtures/{deprecated_contracts → contracts/deprecated}/deprecated_contract.json +2 -2
- data/spec/fixtures/contracts/{contract.json → legacy/contract.json} +0 -0
- data/spec/fixtures/contracts/{contract_with_examples.json → legacy/contract_with_examples.json} +0 -0
- data/spec/fixtures/contracts/{simple_contract.json → legacy/simple_contract.json} +1 -1
- data/spec/fixtures/contracts/{strict_contract.json → legacy/strict_contract.json} +0 -0
- data/spec/fixtures/contracts/{templating_contract.json → legacy/templating_contract.json} +0 -0
- data/spec/fixtures/{swagger → contracts/swagger}/petstore.yaml +0 -0
- data/spec/integration/e2e_spec.rb +6 -12
- data/spec/integration/forensics/integration_matcher_spec.rb +5 -11
- data/spec/integration/rspec_spec.rb +12 -12
- data/spec/integration/templating_spec.rb +1 -1
- data/spec/spec_helper.rb +14 -2
- data/spec/unit/pacto/contract_factory_spec.rb +1 -2
- data/spec/unit/pacto/contract_spec.rb +44 -70
- data/spec/unit/pacto/core/investigation_spec.rb +4 -3
- data/spec/unit/pacto/formats/legacy/contract_builder_spec.rb +93 -0
- data/spec/unit/pacto/formats/legacy/contract_factory_spec.rb +29 -0
- data/spec/unit/pacto/formats/legacy/contract_generator_spec.rb +173 -0
- data/spec/unit/pacto/formats/legacy/contract_spec.rb +41 -0
- data/spec/unit/pacto/formats/legacy/generator/filters_spec.rb +104 -0
- data/spec/unit/pacto/formats/legacy/request_clause_spec.rb +79 -0
- data/spec/unit/pacto/formats/legacy/response_clause_spec.rb +45 -0
- data/spec/unit/pacto/formats/swagger/contract_factory_spec.rb +58 -0
- data/spec/unit/pacto/formats/swagger/contract_spec.rb +47 -0
- data/spec/unit/pacto/investigation_registry_spec.rb +1 -2
- data/spec/unit/pacto/pacto_spec.rb +6 -4
- data/spec/unit/pacto/stubs/uri_pattern_spec.rb +7 -8
- data/spec/unit/pacto/stubs/webmock_adapter_spec.rb +2 -4
- data/tasks/release.rake +1 -1
- metadata +53 -53
- data/lib/pacto/contract_builder.rb +0 -125
- data/lib/pacto/exceptions/invalid_contract.rb +0 -12
- data/lib/pacto/generator/filters.rb +0 -42
- data/lib/pacto/generator/hint.rb +0 -26
- data/lib/pacto/generator/native_contract_generator.rb +0 -74
- data/lib/pacto/native_contract_factory.rb +0 -60
- data/lib/pacto/swagger_contract_factory.rb +0 -90
- data/spec/pacto/dummy_server.rb +0 -4
- data/spec/pacto/dummy_server/dummy.rb +0 -51
- data/spec/pacto/dummy_server/jruby_workaround_helper.rb +0 -23
- data/spec/pacto/dummy_server/playback_servlet.rb +0 -22
- data/spec/unit/pacto/contract_builder_spec.rb +0 -89
- data/spec/unit/pacto/generator/filters_spec.rb +0 -100
- data/spec/unit/pacto/generator/native_contract_generator_spec.rb +0 -171
- data/spec/unit/pacto/native_contract_factory_spec.rb +0 -26
- data/spec/unit/pacto/request_clause_spec.rb +0 -75
- data/spec/unit/pacto/response_clause_spec.rb +0 -41
- data/spec/unit/pacto/server/playback_servlet_spec.rb +0 -27
- data/spec/unit/pacto/swagger_contract_factory_spec.rb +0 -56
@@ -0,0 +1,46 @@
|
|
1
|
+
# -*- encoding : utf-8 -*-
|
2
|
+
module Pacto
|
3
|
+
module Formats
|
4
|
+
module Legacy
|
5
|
+
module Generator
|
6
|
+
class Filters
|
7
|
+
CONNECTION_CONTROL_HEADERS = %w(
|
8
|
+
Via
|
9
|
+
Server
|
10
|
+
Connection
|
11
|
+
Transfer-Encoding
|
12
|
+
Content-Length
|
13
|
+
)
|
14
|
+
|
15
|
+
FRESHNESS_HEADERS =
|
16
|
+
%w(
|
17
|
+
Date
|
18
|
+
Last-Modified
|
19
|
+
ETag
|
20
|
+
)
|
21
|
+
|
22
|
+
HEADERS_TO_FILTER = CONNECTION_CONTROL_HEADERS + FRESHNESS_HEADERS
|
23
|
+
|
24
|
+
def filter_request_headers(request, response)
|
25
|
+
# FIXME: Do we need to handle all these cases in real situations, or just because of stubbing?
|
26
|
+
vary_headers = response.headers['vary'] || response.headers['Vary'] || []
|
27
|
+
vary_headers = [vary_headers] if vary_headers.is_a? String
|
28
|
+
vary_headers = vary_headers.map do |h|
|
29
|
+
h.split(',').map(&:strip)
|
30
|
+
end.flatten
|
31
|
+
|
32
|
+
request.headers.select do |header|
|
33
|
+
vary_headers.map(&:downcase).include? header.downcase
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def filter_response_headers(_request, response)
|
38
|
+
Pacto::Extensions.normalize_header_keys(response.headers).reject do |header|
|
39
|
+
(HEADERS_TO_FILTER.include? header) || (header.start_with?('X-'))
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
# -*- encoding : utf-8 -*-
|
2
|
+
module Pacto
|
3
|
+
module Formats
|
4
|
+
module Legacy
|
5
|
+
class GeneratorHint < Pacto::Dash
|
6
|
+
extend Forwardable
|
7
|
+
|
8
|
+
property :request_clause
|
9
|
+
coerce_key :request_clause, RequestClause
|
10
|
+
property :service_name, required: true
|
11
|
+
property :target_file
|
12
|
+
|
13
|
+
def_delegators :request_clause, *RequestClause::Data.properties.map(&:to_sym)
|
14
|
+
|
15
|
+
def initialize(data)
|
16
|
+
data[:request_clause] = RequestClause::Data.properties.each_with_object({}) do | prop, hash |
|
17
|
+
hash[prop] = data.delete prop
|
18
|
+
end
|
19
|
+
super
|
20
|
+
self.target_file ||= "#{slugify(service_name)}.json"
|
21
|
+
end
|
22
|
+
|
23
|
+
def matches?(pacto_request)
|
24
|
+
return false if pacto_request.nil?
|
25
|
+
Pacto::RequestPattern.for(request_clause).matches?(pacto_request)
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
def slugify(path)
|
31
|
+
path.downcase.gsub(' ', '_')
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
# -*- encoding : utf-8 -*-
|
2
|
+
module Pacto
|
3
|
+
module Formats
|
4
|
+
module Legacy
|
5
|
+
class RequestClause < Pacto::Dash
|
6
|
+
include Pacto::RequestClause
|
7
|
+
extend Forwardable
|
8
|
+
attr_reader :data
|
9
|
+
def_delegators :data, :to_hash
|
10
|
+
def_delegators :data, :host, :http_method, :schema, :path, :headers, :params
|
11
|
+
def_delegators :data, :host=, :http_method=, :schema=, :path=, :headers=, :params=
|
12
|
+
|
13
|
+
class Data < Pacto::Dash
|
14
|
+
property :host # required?
|
15
|
+
property :http_method, required: true
|
16
|
+
property :schema, default: {}
|
17
|
+
property :path, default: '/'
|
18
|
+
property :headers, default: {}
|
19
|
+
property :params, default: {}
|
20
|
+
end
|
21
|
+
|
22
|
+
def initialize(data)
|
23
|
+
skip_freeze = data.delete(:skip_freeze)
|
24
|
+
mash = Hashie::Mash.new data
|
25
|
+
mash['http_method'] = normalize(mash['http_method'])
|
26
|
+
@data = Data.new(mash)
|
27
|
+
freeze unless skip_freeze
|
28
|
+
super({})
|
29
|
+
@pattern = Pacto::RequestPattern.for(self)
|
30
|
+
end
|
31
|
+
|
32
|
+
def freeze
|
33
|
+
@data.freeze
|
34
|
+
self
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module Pacto
|
2
|
+
module Formats
|
3
|
+
module Legacy
|
4
|
+
class ResponseClause
|
5
|
+
include Pacto::ResponseClause
|
6
|
+
extend Forwardable
|
7
|
+
attr_reader :data
|
8
|
+
def_delegators :data, :to_hash
|
9
|
+
def_delegators :data, :status, :headers, :schema
|
10
|
+
def_delegators :data, :status=, :headers=, :schema=
|
11
|
+
|
12
|
+
class Data < Pacto::Dash
|
13
|
+
property :status
|
14
|
+
property :headers, default: {}
|
15
|
+
property :schema, default: {}
|
16
|
+
end
|
17
|
+
|
18
|
+
def initialize(data)
|
19
|
+
skip_freeze = data.delete(:skip_freeze)
|
20
|
+
@data = Data.new(data)
|
21
|
+
freeze unless skip_freeze
|
22
|
+
end
|
23
|
+
|
24
|
+
def freeze
|
25
|
+
@data.freeze
|
26
|
+
self
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,86 @@
|
|
1
|
+
# -*- encoding : utf-8 -*-
|
2
|
+
|
3
|
+
require 'pacto/formats/swagger/request_clause'
|
4
|
+
require 'pacto/formats/swagger/response_clause'
|
5
|
+
|
6
|
+
module Pacto
|
7
|
+
module Formats
|
8
|
+
module Swagger
|
9
|
+
class Contract < Pacto::Dash
|
10
|
+
include Pacto::Contract
|
11
|
+
|
12
|
+
attr_reader :swagger_api_operation
|
13
|
+
|
14
|
+
property :id
|
15
|
+
property :file
|
16
|
+
property :request, required: true
|
17
|
+
# Although I'd like response to be required, it complicates
|
18
|
+
# the partial contracts used the rake generation task...
|
19
|
+
# yet another reason I'd like to deprecate that feature
|
20
|
+
property :response # , required: true
|
21
|
+
property :values, default: {}
|
22
|
+
# Gotta figure out how to use test doubles w/ coercion
|
23
|
+
coerce_key :request, RequestClause
|
24
|
+
coerce_key :response, ResponseClause
|
25
|
+
property :examples
|
26
|
+
property :name, required: true
|
27
|
+
property :adapter, default: proc { Pacto.configuration.adapter }
|
28
|
+
property :consumer, default: proc { Pacto.configuration.default_consumer }
|
29
|
+
property :provider, default: proc { Pacto.configuration.default_provider }
|
30
|
+
|
31
|
+
def initialize(swagger_api_operation, base_data = {}) # rubocop:disable Metrics/MethodLength
|
32
|
+
if base_data[:file]
|
33
|
+
base_data[:file] = Addressable::URI.convert_path(File.expand_path(base_data[:file])).to_s
|
34
|
+
base_data[:name] ||= base_data[:file]
|
35
|
+
end
|
36
|
+
base_data[:id] ||= (base_data[:summary] || base_data[:file])
|
37
|
+
|
38
|
+
@swagger_api_operation = swagger_api_operation
|
39
|
+
host = base_data.delete(:host) || swagger_api_operation.host
|
40
|
+
default_response = swagger_api_operation.default_response
|
41
|
+
request_clause = Pacto::Formats::Swagger::RequestClause.new(swagger_api_operation, host: host)
|
42
|
+
|
43
|
+
if default_response.nil?
|
44
|
+
logger.warn("No response defined for #{swagger_api_operation.full_name}")
|
45
|
+
response_clause = ResponseClause.new(status: 200)
|
46
|
+
else
|
47
|
+
response_clause = ResponseClause.new(default_response)
|
48
|
+
end
|
49
|
+
|
50
|
+
examples = build_examples(default_response)
|
51
|
+
super base_data.merge(
|
52
|
+
id: swagger_api_operation.operationId,
|
53
|
+
name: swagger_api_operation.full_name,
|
54
|
+
request: request_clause, response: response_clause,
|
55
|
+
examples: examples
|
56
|
+
)
|
57
|
+
end
|
58
|
+
|
59
|
+
private
|
60
|
+
|
61
|
+
def build_examples(response)
|
62
|
+
return nil if response.nil? || response.examples.nil? || response.examples.empty?
|
63
|
+
|
64
|
+
if response.examples.empty?
|
65
|
+
response_body = nil
|
66
|
+
else
|
67
|
+
response_body = response.examples.values.first
|
68
|
+
end
|
69
|
+
|
70
|
+
{
|
71
|
+
default: {
|
72
|
+
request: {}, # Swagger doesn't have a clear way to capture request examples
|
73
|
+
response: {
|
74
|
+
body: response_body
|
75
|
+
}
|
76
|
+
}
|
77
|
+
}
|
78
|
+
rescue => e # FIXME: Only parsing errors?
|
79
|
+
logger.warn("Error while trying to parse response example for #{swagger_api_operation.full_name}")
|
80
|
+
logger.debug(" Error details: #{e.inspect}")
|
81
|
+
nil
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
# -*- encoding : utf-8 -*-
|
2
|
+
require 'swagger'
|
3
|
+
require 'pacto/formats/swagger/contract'
|
4
|
+
|
5
|
+
module Pacto
|
6
|
+
module Formats
|
7
|
+
module Swagger
|
8
|
+
# Builds {Pacto::Formats::Swagger::Contract} instances from Swagger documents
|
9
|
+
class ContractFactory
|
10
|
+
include Logger
|
11
|
+
|
12
|
+
def load_hints(_contract_path, _host = nil)
|
13
|
+
fail NotImplementedError, 'Contract generation from hints is not currently supported for Swagger'
|
14
|
+
end
|
15
|
+
|
16
|
+
def build_from_file(contract_path, host = nil)
|
17
|
+
app = ::Swagger.load(contract_path)
|
18
|
+
app.operations.map do |op|
|
19
|
+
Contract.new(op,
|
20
|
+
file: contract_path,
|
21
|
+
host: host
|
22
|
+
)
|
23
|
+
end
|
24
|
+
rescue ArgumentError => e
|
25
|
+
logger.error(e)
|
26
|
+
raise "Could not load #{contract_path}: #{e.message}"
|
27
|
+
end
|
28
|
+
|
29
|
+
def files_for(contracts_dir)
|
30
|
+
full_path = Pathname.new(contracts_dir).realpath
|
31
|
+
|
32
|
+
if full_path.directory?
|
33
|
+
all_json_files = "#{full_path}/**/*.{json,yaml,yml}"
|
34
|
+
Dir.glob(all_json_files).map do |f|
|
35
|
+
Pathname.new(f)
|
36
|
+
end
|
37
|
+
else
|
38
|
+
[full_path]
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
Pacto::ContractFactory.add_factory(:swagger, ContractFactory.new)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
# -*- encoding : utf-8 -*-
|
2
|
+
module Pacto
|
3
|
+
module Formats
|
4
|
+
module Swagger
|
5
|
+
class RequestClause
|
6
|
+
include Pacto::RequestClause
|
7
|
+
|
8
|
+
extend Forwardable
|
9
|
+
attr_writer :host
|
10
|
+
attr_reader :swagger_api_operation
|
11
|
+
def_delegator :swagger_api_operation, :verb, :http_method
|
12
|
+
def_delegators :swagger_api_operation, :path
|
13
|
+
|
14
|
+
def initialize(swagger_api_operation, base_data = {})
|
15
|
+
@swagger_api_operation = swagger_api_operation
|
16
|
+
@host = base_data[:host] || swagger_api_operation.host
|
17
|
+
@pattern = Pacto::RequestPattern.for(self)
|
18
|
+
end
|
19
|
+
|
20
|
+
def schema
|
21
|
+
return nil if body_parameter.nil?
|
22
|
+
return nil if body_parameter.schema.nil?
|
23
|
+
body_parameter.schema.parse
|
24
|
+
end
|
25
|
+
|
26
|
+
def params
|
27
|
+
return {} if swagger_api_operation.parameters.nil?
|
28
|
+
|
29
|
+
swagger_api_operation.parameters.select { |p| p.in == 'query' }
|
30
|
+
end
|
31
|
+
|
32
|
+
def headers
|
33
|
+
return {} if swagger_api_operation.parameters.nil?
|
34
|
+
|
35
|
+
swagger_api_operation.parameters.select { |p| p.in == 'header' }
|
36
|
+
end
|
37
|
+
|
38
|
+
def to_hash
|
39
|
+
[:http_method, :schema, :path, :headers, :params].each_with_object({}) do | key, hash |
|
40
|
+
hash[key.to_s] = send key
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
private
|
45
|
+
|
46
|
+
def body_parameter
|
47
|
+
return nil if swagger_api_operation.parameters.nil?
|
48
|
+
swagger_api_operation.parameters.find { |p| p.in == 'body' }
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# -*- encoding : utf-8 -*-
|
2
|
+
module Pacto
|
3
|
+
module Formats
|
4
|
+
module Swagger
|
5
|
+
class ResponseClause
|
6
|
+
extend Forwardable
|
7
|
+
include Pacto::ResponseClause
|
8
|
+
attr_reader :swagger_response
|
9
|
+
|
10
|
+
def_delegators :swagger_response, :schema
|
11
|
+
|
12
|
+
def initialize(swagger_response, _base_data = {})
|
13
|
+
@swagger_response = swagger_response
|
14
|
+
end
|
15
|
+
|
16
|
+
def status
|
17
|
+
swagger_response.status_code || 200
|
18
|
+
end
|
19
|
+
|
20
|
+
def headers
|
21
|
+
swagger_response.headers || {}
|
22
|
+
end
|
23
|
+
|
24
|
+
def schema
|
25
|
+
return nil unless swagger_response.schema
|
26
|
+
swagger_response.schema.parse
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
data/lib/pacto/generator.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# -*- encoding : utf-8 -*-
|
2
|
-
require 'pacto/
|
3
|
-
require 'pacto/
|
2
|
+
require 'pacto/formats/legacy/contract_generator'
|
3
|
+
require 'pacto/formats/legacy/generator_hint'
|
4
4
|
|
5
5
|
module Pacto
|
6
6
|
module Generator
|
@@ -9,7 +9,7 @@ module Pacto
|
|
9
9
|
class << self
|
10
10
|
# Factory method to return the active contract generator implementation
|
11
11
|
def contract_generator
|
12
|
-
|
12
|
+
Pacto::Formats::Legacy::ContractGenerator.new
|
13
13
|
end
|
14
14
|
|
15
15
|
# Factory method to return the active contract generator implementation
|
@@ -38,7 +38,7 @@ module Pacto
|
|
38
38
|
end
|
39
39
|
|
40
40
|
def hint(name, hint_data)
|
41
|
-
@hints <<
|
41
|
+
@hints << Formats::Legacy::GeneratorHint.new(hint_data.merge(service_name: name))
|
42
42
|
end
|
43
43
|
end
|
44
44
|
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'json'
|
2
|
+
|
3
|
+
module Pacto
|
4
|
+
module Handlers
|
5
|
+
module JSONHandler
|
6
|
+
class << self
|
7
|
+
def raw(body)
|
8
|
+
JSON.dump(body)
|
9
|
+
end
|
10
|
+
|
11
|
+
def parse(body)
|
12
|
+
JSON.parse(body)
|
13
|
+
end
|
14
|
+
|
15
|
+
# TODO: Something like validate(contract, body)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
data/lib/pacto/request_clause.rb
CHANGED
@@ -1,33 +1,23 @@
|
|
1
1
|
# -*- encoding : utf-8 -*-
|
2
2
|
module Pacto
|
3
|
-
|
3
|
+
module RequestClause
|
4
4
|
include Logger
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
def initialize(definition)
|
14
|
-
mash = Hashie::Mash.new definition
|
15
|
-
mash['http_method'] = normalize(mash['http_method'])
|
16
|
-
super mash
|
17
|
-
end
|
5
|
+
attr_reader :host
|
6
|
+
attr_reader :http_method
|
7
|
+
attr_reader :schema
|
8
|
+
attr_reader :path
|
9
|
+
attr_reader :headers
|
10
|
+
attr_reader :params
|
11
|
+
attr_reader :pattern
|
18
12
|
|
19
13
|
def http_method=(method)
|
20
14
|
normalize(method)
|
21
15
|
end
|
22
16
|
|
23
|
-
def pattern
|
24
|
-
@pattern ||= request_pattern_provider.for(self)
|
25
|
-
end
|
26
|
-
|
27
17
|
def uri(values = {})
|
28
18
|
values ||= {}
|
29
19
|
uri_template = pattern.uri_template
|
30
|
-
missing_keys = uri_template.keys - values.keys
|
20
|
+
missing_keys = uri_template.keys.map(&:to_sym) - values.keys.map(&:to_sym)
|
31
21
|
values[:scheme] = 'http' if missing_keys.delete(:scheme)
|
32
22
|
values[:server] = 'localhost' if missing_keys.delete(:server)
|
33
23
|
logger.warn "Missing keys for building a complete URL: #{missing_keys.inspect}" unless missing_keys.empty?
|