hyperdrive 0.0.15 → 0.0.16
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +1 -1
- data/lib/hyperdrive/dsl/resource.rb +8 -2
- data/lib/hyperdrive/dsl.rb +17 -2
- data/lib/hyperdrive/endpoint.rb +21 -6
- data/lib/hyperdrive/hateoas.rb +42 -26
- data/lib/hyperdrive/instrumenters/memory.rb +27 -0
- data/lib/hyperdrive/instrumenters/noop.rb +15 -0
- data/lib/hyperdrive/resource.rb +28 -4
- data/lib/hyperdrive/values.rb +3 -1
- data/lib/hyperdrive/version.rb +1 -1
- data/lib/hyperdrive.rb +4 -0
- data/spec/hyperdrive/dsl/resource_spec.rb +10 -3
- data/spec/hyperdrive/dsl_spec.rb +21 -1
- data/spec/hyperdrive/endpoint_spec.rb +207 -0
- data/spec/hyperdrive/filter_spec.rb +5 -1
- data/spec/hyperdrive/hateoas_spec.rb +4 -0
- data/spec/hyperdrive/instrumenters/memory_spec.rb +29 -0
- data/spec/hyperdrive/instrumenters/noop_spec.rb +21 -0
- data/spec/hyperdrive/middleware/required_params_spec.rb +4 -0
- data/spec/hyperdrive/param_spec.rb +5 -1
- data/spec/hyperdrive/resource_spec.rb +22 -0
- data/spec/hyperdrive/server_spec.rb +7 -7
- data/spec/hyperdrive/utils_spec.rb +5 -1
- data/spec/spec_helper.rb +16 -2
- metadata +8 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: b111cd2840e4210416ca5edbe340199dd206c1bb
|
|
4
|
+
data.tar.gz: 3b3ecb7863fbf7006e6584cbb7250ef261e49d67
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 9e461cd608d77b6cbbfb09c9851971c5bd4acdcb1ee4d25b1550db03a0b70c0ed996e104d2179331d91c9012b4eda73a9fda122ead6e5ca53bfaa42fcc38831c
|
|
7
|
+
data.tar.gz: f8d2e7ea4e3307596a1641d0e80d9275bb356e105fb15eb282cc7819568225fe0c1734eea337ae486391ca603c2916d12ea29da67db1150b6929c41c750fa052
|
data/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Hyperdrive
|
|
2
2
|
|
|
3
|
-
[](http://badge.fury.io/rb/hyperdrive) [](http://badge.fury.io/rb/hyperdrive) [](https://travis-ci.org/styleseek/hyperdrive) [](https://codeclimate.com/github/styleseek/hyperdrive) [](https://codeclimate.com/github/styleseek/hyperdrive) [](https://gemnasium.com/styleseek/hyperdrive)
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
Ruby DSL for defining self-documenting, HATEOAS™ complaint, Hypermedia endpoints.
|
|
@@ -26,11 +26,17 @@ module Hyperdrive
|
|
|
26
26
|
resource.register_filter(*args)
|
|
27
27
|
end
|
|
28
28
|
|
|
29
|
-
def request(request_method)
|
|
29
|
+
def request(request_method, version = 'v1')
|
|
30
30
|
unless definable_request_methods.include? request_method
|
|
31
31
|
raise Errors::DSL::UnknownArgument.new(request_method, 'request')
|
|
32
32
|
end
|
|
33
|
-
resource.register_request_handler(request_method, Proc.new)
|
|
33
|
+
resource.register_request_handler(request_method, Proc.new, version)
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def before(request_methods = [:get, :post, :put, :patch, :delete], version = 'v1')
|
|
37
|
+
Array(request_methods).each do |request_method|
|
|
38
|
+
resource.register_callback(:before, request_method, Proc.new, version)
|
|
39
|
+
end
|
|
34
40
|
end
|
|
35
41
|
end
|
|
36
42
|
end
|
data/lib/hyperdrive/dsl.rb
CHANGED
|
@@ -14,8 +14,13 @@ module Hyperdrive
|
|
|
14
14
|
self
|
|
15
15
|
end
|
|
16
16
|
|
|
17
|
+
def instrument(*args)
|
|
18
|
+
@config[:instrumenter] = @config[:instrumenter] || Hyperdrive::Instrumenters::Noop
|
|
19
|
+
@config[:instrumenter].instrument(*args)
|
|
20
|
+
end
|
|
21
|
+
|
|
17
22
|
private
|
|
18
|
-
|
|
23
|
+
|
|
19
24
|
def name(name)
|
|
20
25
|
@config[:name] = name
|
|
21
26
|
end
|
|
@@ -39,7 +44,17 @@ module Hyperdrive
|
|
|
39
44
|
end
|
|
40
45
|
|
|
41
46
|
def per_page(per_page)
|
|
42
|
-
|
|
47
|
+
per_page = per_page.to_i
|
|
48
|
+
per_page = default_config[:per_page] if per_page == 0
|
|
49
|
+
@config[:per_page] = per_page
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def ssl(force_ssl)
|
|
53
|
+
@config[:ssl] = force_ssl
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def instrumenter(instrumenter)
|
|
57
|
+
@config[:instrumenter] = instrumenter || Hyperdrive::Instrumenters::Noop
|
|
43
58
|
end
|
|
44
59
|
|
|
45
60
|
def resource(name)
|
data/lib/hyperdrive/endpoint.rb
CHANGED
|
@@ -11,7 +11,7 @@ module Hyperdrive
|
|
|
11
11
|
@resource = env['hyperdrive.resource']
|
|
12
12
|
@headers = Hyperdrive::Values.default_headers.dup
|
|
13
13
|
@headers.merge!('Allow' => resource.allowed_methods.join(', '), 'Content-Type' => @media_type)
|
|
14
|
-
|
|
14
|
+
before_response
|
|
15
15
|
response.finish
|
|
16
16
|
end
|
|
17
17
|
|
|
@@ -23,11 +23,16 @@ module Hyperdrive
|
|
|
23
23
|
end
|
|
24
24
|
|
|
25
25
|
def self.json?
|
|
26
|
-
media_type =~ /json$/
|
|
26
|
+
media_type =~ /json$/ ? true : false
|
|
27
27
|
end
|
|
28
28
|
|
|
29
29
|
def self.xml?
|
|
30
|
-
media_type =~ /xml$/
|
|
30
|
+
media_type =~ /xml$/ ? true : false
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def self.requested_version
|
|
34
|
+
regex = /.*\/vnd.#{hyperdrive.config[:vendor]}\..*\.(.*)\+.*$/
|
|
35
|
+
regex.match(media_type) { |version| version.captures.first } or resource.latest_version(env['REQUEST_METHOD'])
|
|
31
36
|
end
|
|
32
37
|
|
|
33
38
|
def self.page
|
|
@@ -44,13 +49,13 @@ module Hyperdrive
|
|
|
44
49
|
if json?
|
|
45
50
|
MultiJson.dump(body)
|
|
46
51
|
else
|
|
47
|
-
|
|
52
|
+
puts "Hyperdrive::Endpoint: Can't serialize response automatically"
|
|
48
53
|
raise Errors::NoResponse.new
|
|
49
54
|
end
|
|
50
55
|
when String
|
|
51
56
|
body
|
|
52
57
|
else
|
|
53
|
-
|
|
58
|
+
puts "Hyperdrive::Endpoint: Coerceing response to string. Probably not what you want"
|
|
54
59
|
body.to_s
|
|
55
60
|
end
|
|
56
61
|
end
|
|
@@ -59,6 +64,16 @@ module Hyperdrive
|
|
|
59
64
|
raise Errors::HTTPError.new(message, status)
|
|
60
65
|
end
|
|
61
66
|
|
|
67
|
+
def self.instrument(*args)
|
|
68
|
+
hyperdrive.instrument(*args)
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def self.before_response
|
|
72
|
+
if @resource.has_callback?(:before, env['REQUEST_METHOD'], requested_version)
|
|
73
|
+
instance_eval(&@resource.callback(:before, env['REQUEST_METHOD'], requested_version))
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
|
|
62
77
|
def self.status
|
|
63
78
|
case env['REQUEST_METHOD']
|
|
64
79
|
when 'POST'
|
|
@@ -71,7 +86,7 @@ module Hyperdrive
|
|
|
71
86
|
end
|
|
72
87
|
|
|
73
88
|
def self.body
|
|
74
|
-
body = instance_eval(&resource.request_handler(env['REQUEST_METHOD']))
|
|
89
|
+
body = instance_eval(&resource.request_handler(env['REQUEST_METHOD'], requested_version))
|
|
75
90
|
body = '' if env['REQUEST_METHOD'] == 'DELETE'
|
|
76
91
|
body
|
|
77
92
|
end
|
data/lib/hyperdrive/hateoas.rb
CHANGED
|
@@ -5,41 +5,57 @@ module Hyperdrive
|
|
|
5
5
|
extend Hyperdrive::Values
|
|
6
6
|
|
|
7
7
|
def self.call(env)
|
|
8
|
+
@env = env
|
|
8
9
|
if hyperdrive.resources.empty? || env['PATH_INFO'] != '/'
|
|
9
10
|
raise Hyperdrive::Errors::NotFound
|
|
10
11
|
end
|
|
11
12
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
end
|
|
13
|
+
[200, headers, [body]]
|
|
14
|
+
end
|
|
15
15
|
|
|
16
|
-
|
|
17
|
-
_links: { self: { href: '/' } },
|
|
18
|
-
name: hyperdrive.config[:name],
|
|
19
|
-
description: hyperdrive.config[:description],
|
|
20
|
-
vendor: hyperdrive.config[:vendor],
|
|
21
|
-
resources: endpoints
|
|
22
|
-
}
|
|
16
|
+
private
|
|
23
17
|
|
|
24
|
-
|
|
18
|
+
def self.media_types
|
|
19
|
+
%w(hal+json json).map do |media_type|
|
|
25
20
|
"application/vnd.#{hyperdrive.config[:vendor]}+#{media_type}"
|
|
21
|
+
end + %w(application/hal+json application/json)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def self.content_type
|
|
25
|
+
@env['hyperdrive.accept'].best_of(media_types)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def self.headers
|
|
29
|
+
{
|
|
30
|
+
'Access-Control-Allow-Origin' => '*',
|
|
31
|
+
'Access-Control-Allow-Methods' => 'GET, HEAD, OPTIONS',
|
|
32
|
+
'Allow' => 'GET, HEAD, OPTIONS',
|
|
33
|
+
'Content-Type' => content_type
|
|
34
|
+
}
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def self.endpoints
|
|
38
|
+
hyperdrive.resources.map do |_,resource|
|
|
39
|
+
resource.to_hash
|
|
26
40
|
end
|
|
41
|
+
end
|
|
27
42
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
+
def self.response
|
|
44
|
+
{
|
|
45
|
+
_links: { self: { href: '/' } },
|
|
46
|
+
name: hyperdrive.config[:name],
|
|
47
|
+
description: hyperdrive.config[:description],
|
|
48
|
+
vendor: hyperdrive.config[:vendor],
|
|
49
|
+
resources: endpoints
|
|
50
|
+
}
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def self.body
|
|
54
|
+
if content_type =~ /json$/
|
|
55
|
+
MultiJson.dump(response)
|
|
56
|
+
else
|
|
57
|
+
raise Errors::NotAcceptable.new(@env['HTTP_ACCEPT'])
|
|
58
|
+
end
|
|
43
59
|
end
|
|
44
60
|
end
|
|
45
61
|
end
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
|
|
3
|
+
module Hyperdrive
|
|
4
|
+
module Instrumenters
|
|
5
|
+
class Memory
|
|
6
|
+
Event = Struct.new(:name, :payload, :result)
|
|
7
|
+
|
|
8
|
+
attr_reader :events
|
|
9
|
+
|
|
10
|
+
def initialize
|
|
11
|
+
@events = []
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def instrument(name, payload = {})
|
|
15
|
+
result = if block_given?
|
|
16
|
+
yield payload
|
|
17
|
+
else
|
|
18
|
+
payload
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
@events << Event.new(name, payload, result)
|
|
22
|
+
|
|
23
|
+
result
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
data/lib/hyperdrive/resource.rb
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
module Hyperdrive
|
|
4
4
|
class Resource
|
|
5
5
|
include Hyperdrive::Values
|
|
6
|
-
attr_reader :id, :namespace, :endpoint, :params, :filters, :request_handlers, :version
|
|
6
|
+
attr_reader :id, :namespace, :endpoint, :params, :filters, :request_handlers, :callbacks, :version
|
|
7
7
|
attr_accessor :name, :description
|
|
8
8
|
|
|
9
9
|
def initialize(resource, options = {})
|
|
@@ -14,6 +14,7 @@ module Hyperdrive
|
|
|
14
14
|
@params = default_params
|
|
15
15
|
@filters = default_filters
|
|
16
16
|
@request_handlers = default_request_handlers
|
|
17
|
+
@callbacks = { before: {} }
|
|
17
18
|
@config = hyperdrive.config
|
|
18
19
|
@id = [@config[:vendor], @namespace].join(':')
|
|
19
20
|
end
|
|
@@ -26,6 +27,29 @@ module Hyperdrive
|
|
|
26
27
|
@filters[filter] = Filter.new(filter, description, options)
|
|
27
28
|
end
|
|
28
29
|
|
|
30
|
+
def register_callback(callback_type, request_method, callback, version = 'v1')
|
|
31
|
+
@callbacks[callback_type] ||={}
|
|
32
|
+
@callbacks[callback_type][request_method] ||= {}
|
|
33
|
+
@callbacks[callback_type][request_method].merge!({ version => callback })
|
|
34
|
+
if request_method == :get
|
|
35
|
+
@callbacks[callback_type][:head] ||= {}
|
|
36
|
+
@callbacks[callback_type][:head].merge!({ version => @callbacks[callback_type][:get][version] })
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def callback(callback_type, http_request_method, version = nil)
|
|
41
|
+
version ||= latest_version(http_request_method)
|
|
42
|
+
request_method = http_request_methods[http_request_method]
|
|
43
|
+
callbacks[callback_type][request_method][version]
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def has_callback?(callback_type, http_request_method, version = nil)
|
|
47
|
+
version ||= latest_version(http_request_method)
|
|
48
|
+
request_method = http_request_methods[http_request_method]
|
|
49
|
+
callbacks.has_key?(callback_type) and callbacks[callback_type].has_key?(request_method) and callbacks[callback_type][request_method].has_key?(version)
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
|
|
29
53
|
def register_request_handler(request_method, request_handler, version = 'v1')
|
|
30
54
|
@request_handlers[request_method] ||= {}
|
|
31
55
|
@request_handlers[request_method].merge!({ version => request_handler })
|
|
@@ -43,12 +67,12 @@ module Hyperdrive
|
|
|
43
67
|
|
|
44
68
|
def acceptable_content_types(http_request_method)
|
|
45
69
|
content_types = []
|
|
46
|
-
|
|
70
|
+
media_type_namespace = @resource.join('-')
|
|
47
71
|
@config[:media_types].each do |media_type|
|
|
48
72
|
available_versions(http_request_method).each do |version|
|
|
49
|
-
content_types << "application/vnd.#{@config[:vendor]}.#{
|
|
73
|
+
content_types << "application/vnd.#{@config[:vendor]}.#{media_type_namespace}.#{version}+#{media_type}"
|
|
50
74
|
end
|
|
51
|
-
content_types << "application/vnd.#{@config[:vendor]}.#{
|
|
75
|
+
content_types << "application/vnd.#{@config[:vendor]}.#{media_type_namespace}+#{media_type}"
|
|
52
76
|
content_types << "application/vnd.#{@config[:vendor]}+#{media_type}"
|
|
53
77
|
end
|
|
54
78
|
content_types
|
data/lib/hyperdrive/values.rb
CHANGED
data/lib/hyperdrive/version.rb
CHANGED
data/lib/hyperdrive.rb
CHANGED
|
@@ -16,6 +16,10 @@ require 'hyperdrive/version'
|
|
|
16
16
|
require 'hyperdrive/docs'
|
|
17
17
|
require 'hyperdrive/utils'
|
|
18
18
|
|
|
19
|
+
## instrumenters
|
|
20
|
+
require 'hyperdrive/instrumenters/memory'
|
|
21
|
+
require 'hyperdrive/instrumenters/noop'
|
|
22
|
+
|
|
19
23
|
## sugary syntax and state mangagement
|
|
20
24
|
require 'hyperdrive/dsl'
|
|
21
25
|
require 'hyperdrive/errors'
|
|
@@ -10,6 +10,9 @@ describe Hyperdrive::DSL::Resource do
|
|
|
10
10
|
description 'Thing Description'
|
|
11
11
|
param :name, 'Thing Name'
|
|
12
12
|
filter :parent_id, "Parent ID"
|
|
13
|
+
before do
|
|
14
|
+
'before'
|
|
15
|
+
end
|
|
13
16
|
request(:get) do
|
|
14
17
|
'ok'
|
|
15
18
|
end
|
|
@@ -37,12 +40,16 @@ describe Hyperdrive::DSL::Resource do
|
|
|
37
40
|
hyperdrive.resources[:thing].filters[:parent_id].description.must_equal "Parent ID"
|
|
38
41
|
end
|
|
39
42
|
|
|
40
|
-
it "
|
|
43
|
+
it "registers requests handlers" do
|
|
41
44
|
hyperdrive.resources[:thing].request_handlers[:get]['v1'].must_be :===, Proc
|
|
42
45
|
end
|
|
43
46
|
|
|
44
|
-
it "throws an error if request method is unknown" do
|
|
47
|
+
it "throws an error if request method is unknown" do
|
|
45
48
|
bad_resource = -> { hyperdrive { resource(:thing) { request(:verb) } } }
|
|
46
|
-
|
|
49
|
+
bad_resource.must_raise Hyperdrive::Errors::DSL::UnknownArgument
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
it "registers a before request callback" do
|
|
53
|
+
hyperdrive.resources[:thing].callbacks[:before][:get]['v1'].must_be :===, Proc
|
|
47
54
|
end
|
|
48
55
|
end
|
data/spec/hyperdrive/dsl_spec.rb
CHANGED
|
@@ -11,6 +11,9 @@ describe Hyperdrive::DSL do
|
|
|
11
11
|
media_types %w(json)
|
|
12
12
|
cors({ origins: '*', allow_headers: %w(Accept), test: 'test'})
|
|
13
13
|
resource(:thing) {}
|
|
14
|
+
per_page '0'
|
|
15
|
+
ssl true
|
|
16
|
+
instrumenter Hyperdrive::Instrumenters::Memory.new
|
|
14
17
|
end
|
|
15
18
|
end
|
|
16
19
|
|
|
@@ -38,7 +41,7 @@ describe Hyperdrive::DSL do
|
|
|
38
41
|
hyperdrive.resources[:thing].must_be_instance_of ::Hyperdrive::Resource
|
|
39
42
|
end
|
|
40
43
|
|
|
41
|
-
it "
|
|
44
|
+
it "configures cors options" do
|
|
42
45
|
hyperdrive.config[:cors][:allow_headers].must_equal ['Accept']
|
|
43
46
|
end
|
|
44
47
|
|
|
@@ -49,4 +52,21 @@ describe Hyperdrive::DSL do
|
|
|
49
52
|
it "removes unsupported cors options" do
|
|
50
53
|
hyperdrive.config[:cors].key?(:test).must_equal false
|
|
51
54
|
end
|
|
55
|
+
|
|
56
|
+
it "configures the default per_page option" do
|
|
57
|
+
hyperdrive.config[:per_page].must_equal 20
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
it "configures ssl option" do
|
|
61
|
+
hyperdrive.config[:ssl].must_equal true
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
it "configures instrumenter option" do
|
|
65
|
+
hyperdrive.config[:instrumenter].must_be_instance_of Hyperdrive::Instrumenters::Memory
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
it "can call the instrumenter" do
|
|
69
|
+
hyperdrive.instrument('instrumentation', 'measurement') { |payload| payload + '1' }
|
|
70
|
+
hyperdrive.config[:instrumenter].events.size.must_be :>, 0
|
|
71
|
+
end
|
|
52
72
|
end
|
|
@@ -20,6 +20,11 @@ describe Hyperdrive::Endpoint do
|
|
|
20
20
|
last_response.successful?.must_equal true
|
|
21
21
|
end
|
|
22
22
|
|
|
23
|
+
it "runs before callbacks" do
|
|
24
|
+
get '/', {}, default_rack_env(hyperdrive.resources[:thing])
|
|
25
|
+
last_response.headers['X-Resource'].must_equal 'Thing Resource'
|
|
26
|
+
end
|
|
27
|
+
|
|
23
28
|
it "can raise an HTTPError" do
|
|
24
29
|
hyperdrive do
|
|
25
30
|
resource(:thing) do
|
|
@@ -30,4 +35,206 @@ describe Hyperdrive::Endpoint do
|
|
|
30
35
|
end
|
|
31
36
|
->{ get '/', {}, default_rack_env(hyperdrive.resources[:thing]) }.must_raise Hyperdrive::Errors::HTTPError
|
|
32
37
|
end
|
|
38
|
+
|
|
39
|
+
it "can call the instrumenter" do
|
|
40
|
+
hyperdrive do
|
|
41
|
+
instrumenter Hyperdrive::Instrumenters::Memory.new
|
|
42
|
+
resource(:thing) do
|
|
43
|
+
request(:get) do
|
|
44
|
+
instrument('requests.GET', '1')
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
get '/', {}, default_rack_env(hyperdrive.resources[:thing])
|
|
49
|
+
hyperdrive.config[:instrumenter].events.size.must_be :>, 0
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
it "returns true if media type ends in json" do
|
|
53
|
+
hyperdrive do
|
|
54
|
+
resource(:thing) do
|
|
55
|
+
request(:get) do
|
|
56
|
+
json?.to_s
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
get '/', {}, default_rack_env(hyperdrive.resources[:thing]).merge('hyperdrive.media_type' => 'application/json')
|
|
61
|
+
last_response.body.must_equal 'true'
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
it "returns false if media type does not ends in json" do
|
|
65
|
+
hyperdrive do
|
|
66
|
+
resource(:thing) do
|
|
67
|
+
request(:get) do
|
|
68
|
+
json?.to_s
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
get '/', {}, default_rack_env(hyperdrive.resources[:thing]).merge('hyperdrive.media_type' => 'application/xml')
|
|
73
|
+
last_response.body.must_equal 'false'
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
it "returns true if media type ends in xml" do
|
|
77
|
+
hyperdrive do
|
|
78
|
+
resource(:thing) do
|
|
79
|
+
request(:get) do
|
|
80
|
+
xml?.to_s
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
get '/', {}, default_rack_env(hyperdrive.resources[:thing]).merge('hyperdrive.media_type' => 'application/xml')
|
|
85
|
+
last_response.body.must_equal 'true'
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
it "returns false if media type does not ends in xml" do
|
|
89
|
+
hyperdrive do
|
|
90
|
+
resource(:thing) do
|
|
91
|
+
request(:get) do
|
|
92
|
+
xml?.to_s
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
get '/', {}, default_rack_env(hyperdrive.resources[:thing]).merge('hyperdrive.media_type' => 'application/json')
|
|
97
|
+
last_response.body.must_equal 'false'
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
it "returns version if media type contains a version" do
|
|
101
|
+
hyperdrive do
|
|
102
|
+
resource(:thing) do
|
|
103
|
+
request(:get, 'v2') do
|
|
104
|
+
requested_version.to_s
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
get '/', {}, default_rack_env(hyperdrive.resources[:thing]).merge('hyperdrive.media_type' => 'application/vnd.hyperdrive.things.v2+json')
|
|
109
|
+
last_response.body.must_equal 'v2'
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
it "returns latest version if media type does not contain a version" do
|
|
113
|
+
hyperdrive do
|
|
114
|
+
resource(:thing) do
|
|
115
|
+
request(:get) do
|
|
116
|
+
requested_version.to_s
|
|
117
|
+
end
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
get '/', {}, default_rack_env(hyperdrive.resources[:thing]).merge('hyperdrive.media_type' => 'application/vnd.hyperdrive.things+json')
|
|
121
|
+
last_response.body.must_equal 'v1'
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
it "renders Arrays as json if media type is json" do
|
|
125
|
+
hyperdrive do
|
|
126
|
+
resource(:thing) do
|
|
127
|
+
request(:get) do
|
|
128
|
+
[]
|
|
129
|
+
end
|
|
130
|
+
end
|
|
131
|
+
end
|
|
132
|
+
get '/', {}, default_rack_env(hyperdrive.resources[:thing]).merge('hyperdrive.media_type' => 'application/vnd.hyperdrive.things+json')
|
|
133
|
+
last_response.body.must_equal '[]'
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
it "throws an error if media type is not json and response is an Array" do
|
|
137
|
+
hyperdrive do
|
|
138
|
+
resource(:thing) do
|
|
139
|
+
request(:get) do
|
|
140
|
+
[]
|
|
141
|
+
end
|
|
142
|
+
end
|
|
143
|
+
end
|
|
144
|
+
->{ get '/', {}, default_rack_env(hyperdrive.resources[:thing]).merge({'hyperdrive.media_type' => 'application/xml' }) }.must_raise Hyperdrive::Errors::NoResponse
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
it "renders Hashes as json if media type is json" do
|
|
148
|
+
hyperdrive do
|
|
149
|
+
resource(:thing) do
|
|
150
|
+
request(:get) do
|
|
151
|
+
{}
|
|
152
|
+
end
|
|
153
|
+
end
|
|
154
|
+
end
|
|
155
|
+
get '/', {}, default_rack_env(hyperdrive.resources[:thing]).merge('hyperdrive.media_type' => 'application/vnd.hyperdrive.things+json')
|
|
156
|
+
last_response.body.must_equal '{}'
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
it "throws an error if media type is not json and response is a Hash" do
|
|
160
|
+
hyperdrive do
|
|
161
|
+
resource(:thing) do
|
|
162
|
+
request(:get) do
|
|
163
|
+
{}
|
|
164
|
+
end
|
|
165
|
+
end
|
|
166
|
+
end
|
|
167
|
+
->{ get '/', {}, default_rack_env(hyperdrive.resources[:thing]).merge({'hyperdrive.media_type' => 'application/xml' }) }.must_raise Hyperdrive::Errors::NoResponse
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
it "renders other responses as a string" do
|
|
171
|
+
hyperdrive do
|
|
172
|
+
resource(:thing) do
|
|
173
|
+
request(:get) do
|
|
174
|
+
0
|
|
175
|
+
end
|
|
176
|
+
end
|
|
177
|
+
end
|
|
178
|
+
get '/', {}, default_rack_env(hyperdrive.resources[:thing]).merge('hyperdrive.media_type' => 'application/vnd.hyperdrive.things+json')
|
|
179
|
+
last_response.body.must_equal '0'
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
it "returns the current page" do
|
|
183
|
+
hyperdrive do
|
|
184
|
+
resource(:thing) do
|
|
185
|
+
request(:get) do
|
|
186
|
+
page
|
|
187
|
+
end
|
|
188
|
+
end
|
|
189
|
+
end
|
|
190
|
+
get '/', {}, default_rack_env(hyperdrive.resources[:thing]).merge('hyperdrive.page' => '2')
|
|
191
|
+
last_response.body.must_equal '2'
|
|
192
|
+
end
|
|
193
|
+
|
|
194
|
+
it "returns the number of results in each page" do
|
|
195
|
+
hyperdrive do
|
|
196
|
+
resource(:thing) do
|
|
197
|
+
request(:get) do
|
|
198
|
+
per_page
|
|
199
|
+
end
|
|
200
|
+
end
|
|
201
|
+
end
|
|
202
|
+
get '/', {}, default_rack_env(hyperdrive.resources[:thing]).merge('hyperdrive.per_page' => '20')
|
|
203
|
+
last_response.body.must_equal '20'
|
|
204
|
+
end
|
|
205
|
+
|
|
206
|
+
it "returns 200 when request is a GET" do
|
|
207
|
+
get '/', {}, default_rack_env(hyperdrive.resources[:thing])
|
|
208
|
+
last_response.status.must_equal 200
|
|
209
|
+
end
|
|
210
|
+
|
|
211
|
+
it "returns 201 when request is a POST" do
|
|
212
|
+
post '/', {}, default_rack_env(hyperdrive.resources[:thing]).merge('REQUEST_METHOD' => 'POST')
|
|
213
|
+
last_response.status.must_equal 201
|
|
214
|
+
end
|
|
215
|
+
|
|
216
|
+
it "returns 200 when request is a PUT" do
|
|
217
|
+
put '/', {}, default_rack_env(hyperdrive.resources[:thing]).merge('REQUEST_METHOD' => 'PUT')
|
|
218
|
+
last_response.status.must_equal 200
|
|
219
|
+
end
|
|
220
|
+
|
|
221
|
+
it "returns 200 when request is a PATCH" do
|
|
222
|
+
patch '/', {}, default_rack_env(hyperdrive.resources[:thing]).merge('REQUEST_METHOD' => 'PATCH')
|
|
223
|
+
last_response.status.must_equal 200
|
|
224
|
+
end
|
|
225
|
+
|
|
226
|
+
it "returns 200 when request is a OPTIONS" do
|
|
227
|
+
options '/', {}, default_rack_env(hyperdrive.resources[:thing]).merge('REQUEST_METHOD' => 'OPTIONS')
|
|
228
|
+
last_response.status.must_equal 200
|
|
229
|
+
end
|
|
230
|
+
|
|
231
|
+
it "returns 204 when request is a DELETE" do
|
|
232
|
+
delete '/', {}, default_rack_env(hyperdrive.resources[:thing]).merge('REQUEST_METHOD' => 'DELETE')
|
|
233
|
+
last_response.status.must_equal 204
|
|
234
|
+
end
|
|
235
|
+
|
|
236
|
+
it "returns an empty body when request is a DELETE" do
|
|
237
|
+
delete '/', {}, default_rack_env(hyperdrive.resources[:thing]).merge('REQUEST_METHOD' => 'DELETE')
|
|
238
|
+
last_response.body.must_equal ''
|
|
239
|
+
end
|
|
33
240
|
end
|
|
@@ -19,6 +19,10 @@ describe Hyperdrive::Filter do
|
|
|
19
19
|
@filter.required.must_equal %w(GET HEAD)
|
|
20
20
|
end
|
|
21
21
|
|
|
22
|
+
it "returns an array if only a single HTTP method is required" do
|
|
23
|
+
Hyperdrive::Filter.new(:filter, '', required: 'GET').required.must_equal ['GET']
|
|
24
|
+
end
|
|
25
|
+
|
|
22
26
|
it "returns true if the param is required for the given HTTP method" do
|
|
23
27
|
@filter.required?('GET').must_equal true
|
|
24
28
|
end
|
|
@@ -27,7 +31,7 @@ describe Hyperdrive::Filter do
|
|
|
27
31
|
@filter.required?('OPTIONS').must_equal false
|
|
28
32
|
end
|
|
29
33
|
|
|
30
|
-
it "converts itself
|
|
34
|
+
it "converts itself to a hash" do
|
|
31
35
|
constraints = { name: 'parent_id', description: 'Parent Identifier', type: 'String', constraints: 'Required for: GET, HEAD. Must be a valid BSON Object ID.' }
|
|
32
36
|
@filter.to_hash.must_equal constraints
|
|
33
37
|
end
|
|
@@ -38,5 +38,9 @@ describe Hyperdrive::HATEOAS do
|
|
|
38
38
|
it "responds with a description of all resources" do
|
|
39
39
|
last_response.body.must_equal %Q({"_links":{"self":{"href":"/"}},"name":"Hyperdrive API","description":"v#{Hyperdrive::VERSION}","vendor":"hyperdrive","resources":[{"_links":{"self":{"href":"/things"}},"id":"hyperdrive:things","name":"Thing Resource","description":"Description of Thing Resource","methods":["OPTIONS","GET","HEAD","POST","PUT","PATCH","DELETE"],"params":[{"name":"id","description":"Identifier","type":"String","constraints":"Required for: PUT, PATCH, DELETE. "},{"name":"name","description":"50 Chars or less","type":"String","constraints":"Required for: POST, PUT, PATCH. "}],"filters":[{"name":"id","description":"Resource Identifier","type":"String","constraints":" "},{"name":"parent_id","description":"Parent ID of Thing","type":"String","constraints":"Required for: GET, HEAD. "}],"media_types":[["application/vnd.hyperdrive.things.v1+hal+json","application/vnd.hyperdrive.things+hal+json","application/vnd.hyperdrive+hal+json","application/vnd.hyperdrive.things.v1+json","application/vnd.hyperdrive.things+json","application/vnd.hyperdrive+json"]]}]})
|
|
40
40
|
end
|
|
41
|
+
|
|
42
|
+
it "throws an error if request doesn't accept json" do
|
|
43
|
+
->{ get '/', {}, default_hyperdrive_env.merge({ 'Accept' => 'application/xml' }) }.must_raise Hyperdrive::Errors::NotAcceptable
|
|
44
|
+
end
|
|
41
45
|
end
|
|
42
46
|
end
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
|
|
3
|
+
require 'spec_helper'
|
|
4
|
+
|
|
5
|
+
describe Hyperdrive::Instrumenters::Memory do
|
|
6
|
+
before do
|
|
7
|
+
@instrumenter = Hyperdrive::Instrumenters::Memory.new
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
it "responds to instrument" do
|
|
11
|
+
@instrumenter.respond_to?(:instrument).must_equal true
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
it "returns the result" do
|
|
15
|
+
@instrumenter.instrument('instrumentation', 'measurement').must_equal 'measurement'
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
it "yields to the block and returns the result" do
|
|
19
|
+
@instrumenter.instrument('instrumentation', 'measurement') { |payload| payload + '1' }.must_equal 'measurement1'
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
it "returns events that have been instrumented" do
|
|
23
|
+
@instrumenter.instrument('instrumentation', 'measurement')
|
|
24
|
+
event = @instrumenter.events.first
|
|
25
|
+
event.name.must_equal 'instrumentation'
|
|
26
|
+
event.payload.must_equal 'measurement'
|
|
27
|
+
event.result.must_equal 'measurement'
|
|
28
|
+
end
|
|
29
|
+
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
|
|
3
|
+
require 'spec_helper'
|
|
4
|
+
|
|
5
|
+
describe Hyperdrive::Instrumenters::Noop do
|
|
6
|
+
before do
|
|
7
|
+
@instrumenter = Hyperdrive::Instrumenters::Noop
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
it "responds to instrument" do
|
|
11
|
+
@instrumenter.respond_to?(:instrument).must_equal true
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
it "returns the result" do
|
|
15
|
+
@instrumenter.instrument('instrumentation', 'measurement').must_equal 'measurement'
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
it "optionally takes a block" do
|
|
19
|
+
@instrumenter.instrument('instrumentation', 'measurement') { |payload| payload + '1' } .must_equal 'measurement1'
|
|
20
|
+
end
|
|
21
|
+
end
|
|
@@ -23,6 +23,10 @@ describe Hyperdrive::Middleware::RequiredParams do
|
|
|
23
23
|
it "raises an error if required filter is missing" do
|
|
24
24
|
->{ get '/', {}, @env }.must_raise Hyperdrive::Errors::MissingRequiredParam
|
|
25
25
|
end
|
|
26
|
+
|
|
27
|
+
it "raises an error if required filter is missing" do
|
|
28
|
+
->{ get '/', {}, @env.merge('hyperdrive.params' => { parent_id: '' }) }.must_raise Hyperdrive::Errors::MissingRequiredParam
|
|
29
|
+
end
|
|
26
30
|
end
|
|
27
31
|
|
|
28
32
|
context "Params" do
|
|
@@ -19,6 +19,10 @@ describe Hyperdrive::Param do
|
|
|
19
19
|
@param.required.must_equal %w(PUT PATCH DELETE)
|
|
20
20
|
end
|
|
21
21
|
|
|
22
|
+
it "returns an array if only a single HTTP method is required" do
|
|
23
|
+
Hyperdrive::Filter.new(:param, '', required: 'GET').required.must_equal ['GET']
|
|
24
|
+
end
|
|
25
|
+
|
|
22
26
|
it "returns true if the param is required for the given HTTP method" do
|
|
23
27
|
@param.required?('PUT').must_equal true
|
|
24
28
|
end
|
|
@@ -27,7 +31,7 @@ describe Hyperdrive::Param do
|
|
|
27
31
|
@param.required?('POST').must_equal false
|
|
28
32
|
end
|
|
29
33
|
|
|
30
|
-
it "converts itself
|
|
34
|
+
it "converts itself to a hash" do
|
|
31
35
|
constraints = { name: 'id', description: 'Identifier', type: 'String', constraints: 'Required for: PUT, PATCH, DELETE. Must be a valid BSON Object ID.' }
|
|
32
36
|
@param.to_hash.must_equal constraints
|
|
33
37
|
end
|
|
@@ -5,6 +5,8 @@ describe Hyperdrive::Resource do
|
|
|
5
5
|
@resource = Hyperdrive::Resource.new(:thing)
|
|
6
6
|
@resource.register_param(:name, 'Thing Name')
|
|
7
7
|
@resource.register_filter(:parent_id, 'Parent ID', required: true)
|
|
8
|
+
@resource.register_callback(:before, :get, Proc.new { |env| 'before v1' })
|
|
9
|
+
@resource.register_callback(:before, :get, Proc.new { |env| 'before v2' }, 'v2')
|
|
8
10
|
@resource.register_request_handler(:get, Proc.new { |env| 'v1' })
|
|
9
11
|
@resource.register_request_handler(:get, Proc.new { |env| 'v2' }, 'v2')
|
|
10
12
|
@media_types = ["application/vnd.hyperdrive.things.v2+hal+json",
|
|
@@ -87,6 +89,26 @@ describe Hyperdrive::Resource do
|
|
|
87
89
|
@resource.required?(:parent_id, 'DELETE').must_equal false
|
|
88
90
|
end
|
|
89
91
|
|
|
92
|
+
it "registers a before callback" do
|
|
93
|
+
@resource.callbacks[:before][:get]['v1'].must_be :===, Proc
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
it "auto-registers HEAD before callback when GET before callback is registered" do
|
|
97
|
+
@resource.callbacks[:before][:head]['v1'].must_be :===, Proc
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
it "returns the specified before callback" do
|
|
101
|
+
@resource.callback(:before, 'GET').must_be :===, Proc
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
it "returns true if the specified before callback exists" do
|
|
105
|
+
@resource.has_callback?(:before, 'GET').must_equal true
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
it "returns false if the specified before callback does not exist" do
|
|
109
|
+
@resource.has_callback?(:before, 'GET', 'v3').must_equal false
|
|
110
|
+
end
|
|
111
|
+
|
|
90
112
|
it "registers a request handler" do
|
|
91
113
|
@resource.request_handlers[:get]['v1'].must_be :===, Proc
|
|
92
114
|
end
|
|
@@ -16,37 +16,37 @@ describe Hyperdrive::Server do
|
|
|
16
16
|
end
|
|
17
17
|
|
|
18
18
|
it "responds to GET requests successfully" do
|
|
19
|
-
get '/things', { parent_id: 42 }
|
|
19
|
+
get '/things', { parent_id: 42 }, default_hyperdrive_env
|
|
20
20
|
last_response.successful?.must_equal true
|
|
21
21
|
end
|
|
22
22
|
|
|
23
23
|
it "responds to HEAD requests successfully" do
|
|
24
|
-
head '/things', { parent_id: 42 }
|
|
24
|
+
head '/things', { parent_id: 42 }, default_hyperdrive_env
|
|
25
25
|
last_response.successful?.must_equal true
|
|
26
26
|
end
|
|
27
27
|
|
|
28
28
|
it "responds to OPTIONS requests successfully" do
|
|
29
|
-
options '/things'
|
|
29
|
+
options '/things', {}, default_hyperdrive_env
|
|
30
30
|
last_response.successful?.must_equal true
|
|
31
31
|
end
|
|
32
32
|
|
|
33
33
|
it "responds to POST requests successfully" do
|
|
34
|
-
post '/things', { name: 'bender' }
|
|
34
|
+
post '/things', { name: 'bender' }, default_hyperdrive_env
|
|
35
35
|
last_response.successful?.must_equal true
|
|
36
36
|
end
|
|
37
37
|
|
|
38
38
|
it "responds to PUT requests successfully" do
|
|
39
|
-
put '/things', { id: 1, name: 'bender' }
|
|
39
|
+
put '/things', { id: 1, name: 'bender' }, default_hyperdrive_env
|
|
40
40
|
last_response.successful?.must_equal true
|
|
41
41
|
end
|
|
42
42
|
|
|
43
43
|
it "responds to PATCH requests successfully" do
|
|
44
|
-
patch '/things', { id: 1, name: 'bender' }
|
|
44
|
+
patch '/things', { id: 1, name: 'bender' }, default_hyperdrive_env
|
|
45
45
|
last_response.successful?.must_equal true
|
|
46
46
|
end
|
|
47
47
|
|
|
48
48
|
it "responds to DELETE requests successfully" do
|
|
49
|
-
delete '/things', { id: 1 }
|
|
49
|
+
delete '/things', { id: 1 }, default_hyperdrive_env
|
|
50
50
|
last_response.successful?.must_equal true
|
|
51
51
|
end
|
|
52
52
|
end
|
|
@@ -19,7 +19,7 @@ describe Hyperdrive::Utils do
|
|
|
19
19
|
|
|
20
20
|
context '.symbolize_keys' do
|
|
21
21
|
before do
|
|
22
|
-
@hash = { 'string' => 'cheese', 'collection' => [{'skylanders' => 155}], 'map' => { 'oceans' => 'blue' } }
|
|
22
|
+
@hash = { :symbol => 'symbol', 'string' => 'cheese', 'collection' => [{'skylanders' => 155}], 'map' => { 'oceans' => 'blue' } }
|
|
23
23
|
@subject = Hyperdrive::Utils.symbolize_keys(@hash)
|
|
24
24
|
end
|
|
25
25
|
|
|
@@ -27,6 +27,10 @@ describe Hyperdrive::Utils do
|
|
|
27
27
|
@subject[:string].must_equal 'cheese'
|
|
28
28
|
end
|
|
29
29
|
|
|
30
|
+
it "doesn't symbolize keys that aren't a string" do
|
|
31
|
+
@subject[:symbol].must_equal 'symbol'
|
|
32
|
+
end
|
|
33
|
+
|
|
30
34
|
it "can symbolize the keys of nested hashes" do
|
|
31
35
|
@subject[:map][:oceans].must_equal 'blue'
|
|
32
36
|
end
|
data/spec/spec_helper.rb
CHANGED
|
@@ -29,6 +29,15 @@ include Rack::Test::Methods
|
|
|
29
29
|
|
|
30
30
|
module Hyperdrive
|
|
31
31
|
module TestData
|
|
32
|
+
def default_hyperdrive_env
|
|
33
|
+
{
|
|
34
|
+
'HTTP_ACCEPT' => 'application/vnd.hyperdrive.things+hal+json',
|
|
35
|
+
'hyperdrive.accept' => Rack::Accept::MediaType.new('HTTP_ACCEPT' => 'application/vnd.hyperdrive.things+hal+json;q=0.8'),
|
|
36
|
+
'hyperdrive.resource' => hyperdrive.resources[:things],
|
|
37
|
+
'hyperdrive.media_type' => 'application/vnd.hyperdrive.things+hal+json'
|
|
38
|
+
}
|
|
39
|
+
end
|
|
40
|
+
|
|
32
41
|
def default_rack_env(resource = nil)
|
|
33
42
|
default_env = {
|
|
34
43
|
"rack.version" => Rack::VERSION,
|
|
@@ -41,7 +50,8 @@ module Hyperdrive
|
|
|
41
50
|
'HTTP_ACCEPT' => 'application/vnd.hyperdrive.things+hal+json;q=0.8, application/json;q=1',
|
|
42
51
|
'HTTP_ACCEPT_LANGUAGE' => 'en',
|
|
43
52
|
'REQUEST_METHOD' => 'GET',
|
|
44
|
-
'QUERY_STRING' => 'id=1001'
|
|
53
|
+
'QUERY_STRING' => 'id=1001',
|
|
54
|
+
'hyperdrive.media_type' => 'application/vnd.hyperdrive.things+hal+json'
|
|
45
55
|
}
|
|
46
56
|
default_env.merge!('hyperdrive.accept' => Rack::Accept::MediaType.new(default_env['HTTP_ACCEPT']))
|
|
47
57
|
default_env.merge!('hyperdrive.resource' => resource) if resource
|
|
@@ -72,6 +82,10 @@ module Hyperdrive
|
|
|
72
82
|
param :name, '50 Chars or less', required: true
|
|
73
83
|
filter :parent_id, 'Parent ID of Thing', required: true
|
|
74
84
|
|
|
85
|
+
before(:get) do
|
|
86
|
+
@headers.merge!('X-Resource' => resource.name)
|
|
87
|
+
end
|
|
88
|
+
|
|
75
89
|
request(:get) do
|
|
76
90
|
'ok'
|
|
77
91
|
end
|
|
@@ -89,7 +103,7 @@ module Hyperdrive
|
|
|
89
103
|
end
|
|
90
104
|
|
|
91
105
|
request(:delete) do
|
|
92
|
-
''
|
|
106
|
+
'ok'
|
|
93
107
|
end
|
|
94
108
|
end
|
|
95
109
|
end
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: hyperdrive
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.0.
|
|
4
|
+
version: 0.0.16
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- StyleSeek Engineering
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2014-05-
|
|
11
|
+
date: 2014-05-20 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: linguistics
|
|
@@ -147,6 +147,8 @@ files:
|
|
|
147
147
|
- lib/hyperdrive/errors/unknown_error.rb
|
|
148
148
|
- lib/hyperdrive/filter.rb
|
|
149
149
|
- lib/hyperdrive/hateoas.rb
|
|
150
|
+
- lib/hyperdrive/instrumenters/memory.rb
|
|
151
|
+
- lib/hyperdrive/instrumenters/noop.rb
|
|
150
152
|
- lib/hyperdrive/middleware.rb
|
|
151
153
|
- lib/hyperdrive/middleware/accept.rb
|
|
152
154
|
- lib/hyperdrive/middleware/content_negotiation.rb
|
|
@@ -183,6 +185,8 @@ files:
|
|
|
183
185
|
- spec/hyperdrive/errors/unknown_error_spec.rb
|
|
184
186
|
- spec/hyperdrive/filter_spec.rb
|
|
185
187
|
- spec/hyperdrive/hateoas_spec.rb
|
|
188
|
+
- spec/hyperdrive/instrumenters/memory_spec.rb
|
|
189
|
+
- spec/hyperdrive/instrumenters/noop_spec.rb
|
|
186
190
|
- spec/hyperdrive/middleware/accept_spec.rb
|
|
187
191
|
- spec/hyperdrive/middleware/content_negotiation_spec.rb
|
|
188
192
|
- spec/hyperdrive/middleware/cors_spec.rb
|
|
@@ -243,6 +247,8 @@ test_files:
|
|
|
243
247
|
- spec/hyperdrive/errors/unknown_error_spec.rb
|
|
244
248
|
- spec/hyperdrive/filter_spec.rb
|
|
245
249
|
- spec/hyperdrive/hateoas_spec.rb
|
|
250
|
+
- spec/hyperdrive/instrumenters/memory_spec.rb
|
|
251
|
+
- spec/hyperdrive/instrumenters/noop_spec.rb
|
|
246
252
|
- spec/hyperdrive/middleware/accept_spec.rb
|
|
247
253
|
- spec/hyperdrive/middleware/content_negotiation_spec.rb
|
|
248
254
|
- spec/hyperdrive/middleware/cors_spec.rb
|