jersey 0.1.0 → 0.2.0

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 8917e3fd5a219b1f47d717b67c220309e0099e53
4
- data.tar.gz: 877d58392cf2c2ed29f0c716be9ae96e013624d0
3
+ metadata.gz: 7a603102ad901084bf1d4c48b44d4cd7327af468
4
+ data.tar.gz: 4cb8799276e6a144c644fcc7158c114bf1a0eabc
5
5
  SHA512:
6
- metadata.gz: d79189492a2066fc625ad5b89c6fd68874d7c820d65a5def6f506b5de8a9f404cb5e8c1d2cb39db9d83db1c42dfae57668100f2f1883951e150d9c6b3105cc6c
7
- data.tar.gz: b3321888bd62a38ea83d8552be66df3fc28ec1a64179340cfa1eced4f5ad0da42d9af13b7a0a53ba2dfcd9cd1acc9972a1c1add634471404b95de5f2dc8b48ac
6
+ metadata.gz: e74e901b329082e4571ad3624164c57fc620648fa2663e64b74d11bde87200bcfd9ee56df6efcf1238dd0fa1d6be3ce3ecb06f155a27ff44ec0ae27514b63085
7
+ data.tar.gz: 440010607190f4152d45eb196fcfec8f2ca81841c8a3e299ed4eacf688a8370447647c8e0b0a969a0e545d0c0bf358d08ee809ebff11d49aa807c71e25a5063b
data/README.md CHANGED
@@ -149,6 +149,51 @@ class API < Sinatra::Base
149
149
  end
150
150
  ```
151
151
 
152
+ #### `Jersey::Middleware::AutoJson`
153
+
154
+ Uses content type matching regex `/json/` or a request body that
155
+ begins with a `{` to detect and parse json. Exposes json
156
+ via `request.body` and `params` so you can transparently
157
+ accept form-encoded and json bodies.
158
+
159
+ Adds a `#json` method to the `Rack::Request` object.
160
+
161
+ #### Usage
162
+ Use as a Rack middleware
163
+
164
+ ```ruby
165
+ class API < Sinatra::Base
166
+ use Jersey::Middleware::AutoJson
167
+
168
+ post '/test-json' do
169
+ request.json == env['rack.json']
170
+ end
171
+ end
172
+ ```
173
+
174
+ #### `Jersey::Helpers::AutoJsonParams`
175
+ Merges sinatra params Hash with json data parsed by a rack middleware
176
+ that has set `rack.json` on the rack env.
177
+
178
+ If the parsed data is an array, merges by using the array index as a hash key.
179
+
180
+ Json data gets precendence in naming collisions.
181
+
182
+ #### Usage
183
+ Use as a Sinatra Helper
184
+
185
+ Note: works with any Rack middleware that populates `env['rack.json']`
186
+
187
+ ```ruby
188
+ class API < Sinatra::Base
189
+ helpers Jersey::Helpers::AutoJsonParams
190
+
191
+ post "/test-array-params" do
192
+ params[0]
193
+ end
194
+ end
195
+ ```
196
+
152
197
  #### `Jersey::Middleware::RequestID`
153
198
 
154
199
  Creates a random request id for every http request, stored both in thread local storage
@@ -21,6 +21,8 @@ require 'jersey/http_errors'
21
21
  require 'jersey/middleware/request_id'
22
22
  require 'jersey/middleware/error_handler'
23
23
  require 'jersey/middleware/request_logger'
24
+ require 'jersey/middleware/auto_json'
24
25
  require 'jersey/extensions/route_signature'
26
+ require 'jersey/helpers/auto_json_params'
25
27
  require 'jersey/helpers/log'
26
28
  require 'jersey/helpers/success'
@@ -20,10 +20,12 @@ module Jersey::API
20
20
  use Jersey::Middleware::RequestID
21
21
  use Jersey::Middleware::RequestLogger
22
22
  use Jersey::Middleware::ErrorHandler
23
+ use Jersey::Middleware::AutoJson
23
24
 
24
25
  helpers Sinatra::JSON
25
26
  helpers Jersey::Helpers::Log
26
27
  helpers Jersey::Helpers::Success
28
+ helpers Jersey::Helpers::AutoJsonParams
27
29
 
28
30
  set :dump_errors, false
29
31
  set :raise_errors, true
@@ -0,0 +1,29 @@
1
+ module Jersey::Helpers
2
+ module AutoJsonParams
3
+ # Merges sinatra @params Hash with
4
+ # json data parsed by a rack middleware
5
+ # that has set `rack.json` on the rack env.
6
+ #
7
+ # If the parsed data is an array, merges by
8
+ # using the array index as a hash key.
9
+ #
10
+ # Json data gets precendence in naming collisions
11
+ def params
12
+ # we have parsed json!
13
+ if @env['rack.json']
14
+ json = @env['rack.json']
15
+ if json.is_a?(Hash)
16
+ # merge with params
17
+ super.merge(json)
18
+ else
19
+ # covert array to hash by index
20
+ zipped = json.each_with_index
21
+ zipped = zipped.to_a.map(&:reverse)
22
+ super.merge(Hash[zipped])
23
+ end
24
+ else
25
+ super
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,50 @@
1
+ # Detects json by customizable regex and
2
+ # by looking for request bodies that being with
3
+ # '{' or '['
4
+ #
5
+ # Sets `rack.json` on rack env, but leaves
6
+ # other vars alone.
7
+ module Jersey::Middleware
8
+ class AutoJson
9
+ JSON_PARSER = lambda { |data| JSON.parse(data) }
10
+ JSON_REGEX = /json/
11
+
12
+ # Configure the :porser and the :json_regex though
13
+ # if you're going to be strict about this you
14
+ # probably shouldn't be using this middleware
15
+ def initialize(app, options = {})
16
+ @app = app
17
+ @parser = options.delete(:parser) || JSON_PARSER
18
+ @json_regex = options.delete(:json_regex) || JSON_REGEX
19
+ end
20
+
21
+ # Make json happen.
22
+ def call(env)
23
+ req = Rack::Request.new(env)
24
+ type = req.media_type
25
+ if type && type.match(@json_regex)
26
+ # raise error if parsing declared json
27
+ begin
28
+ env['rack.json'] = @parser.call(req.body.read)
29
+ rescue => ex
30
+ raise BadRequest, "json parse error in AutoJson: #{ex.message}"
31
+ end
32
+ elsif ["{","["].include?(req.body.read(1))
33
+ # make best effort to parse what looks like json
34
+ req.body.rewind
35
+ env['rack.json'] = @parser.call(req.body.read) rescue nil
36
+ end
37
+ req.body.rewind
38
+ @app.call(env)
39
+ end
40
+ end
41
+ end
42
+
43
+ ## Let's enable folks to use request.json
44
+ ## in their rack apps
45
+ require 'rack/request'
46
+ class Rack::Request
47
+ def json
48
+ env['rack.json']
49
+ end
50
+ end
@@ -1,3 +1,3 @@
1
1
  module Jersey
2
- VERSION = "0.1.0"
2
+ VERSION = "0.2.0"
3
3
  end
@@ -0,0 +1,79 @@
1
+ require_relative 'helper'
2
+
3
+ class AutoJsonTest < ApiTest
4
+ class App < Jersey::API::Base
5
+ post '/test-params' do
6
+ "#{params['one']}:#{params['two']}"
7
+ end
8
+
9
+ post '/test-json' do
10
+ "#{request.json['one']}:#{request.json['two']}"
11
+ end
12
+
13
+ post "/test-array" do
14
+ request.json.join(":")
15
+ end
16
+
17
+ post "/test-array-params" do
18
+ params[0]
19
+ end
20
+
21
+ post "/test-auto-parse-fail" do
22
+ request.body.read
23
+ end
24
+ end
25
+
26
+ def test_form_encoded
27
+ post('/test-params', one: "bar")
28
+ assert_equal(200, last_response.status)
29
+ assert_equal("bar:", last_response.body)
30
+ end
31
+
32
+ def test_json
33
+ post('/test-params', {one: "bar"}.to_json)
34
+ assert_equal(200, last_response.status)
35
+ assert_equal("bar:", last_response.body)
36
+ end
37
+
38
+ def test_precedence
39
+ post('/test-params?one=foo', one: "bar")
40
+ assert_equal(200, last_response.status)
41
+ assert_equal("bar:", last_response.body)
42
+ end
43
+
44
+ def test_body_with_json
45
+ post('/test-params?two=foo', {one: "bar"}.to_json)
46
+ assert_equal(200, last_response.status)
47
+ assert_equal("bar:foo", last_response.body)
48
+ end
49
+
50
+ def test_query_string
51
+ post('/test-params?one=bar')
52
+ assert_equal(200, last_response.status)
53
+ assert_equal("bar:", last_response.body)
54
+ end
55
+
56
+ def test_an_array
57
+ post('/test-array', ['foo', 'bar'].to_json)
58
+ assert_equal(200, last_response.status)
59
+ assert_equal("foo:bar", last_response.body)
60
+ end
61
+
62
+ def test_an_array_from_params
63
+ post('/test-array-params', ['foo', 'bar'].to_json)
64
+ assert_equal(200, last_response.status)
65
+ assert_equal("foo", last_response.body)
66
+ end
67
+
68
+ def test_passes_through_auto_parse_fails
69
+ post('/test-auto-parse-fail', "{ HAHA")
70
+ assert_equal(200, last_response.status)
71
+ assert_equal("{ HAHA", last_response.body)
72
+ end
73
+
74
+ def test_query_string_and_body
75
+ post('/test-params?one=bar', {two: "foo"}.to_json)
76
+ assert_equal(200, last_response.status)
77
+ assert_equal("bar:foo", last_response.body)
78
+ end
79
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: jersey
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - csquared
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-02-14 00:00:00.000000000 Z
11
+ date: 2015-02-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: sinatra
@@ -114,6 +114,7 @@ files:
114
114
  - lib/jersey/base.rb
115
115
  - lib/jersey/extensions/error_handler.rb
116
116
  - lib/jersey/extensions/route_signature.rb
117
+ - lib/jersey/helpers/auto_json_params.rb
117
118
  - lib/jersey/helpers/log.rb
118
119
  - lib/jersey/helpers/success.rb
119
120
  - lib/jersey/http_errors.rb
@@ -122,12 +123,14 @@ files:
122
123
  - lib/jersey/logging/json_logger.rb
123
124
  - lib/jersey/logging/logfmt_logger.rb
124
125
  - lib/jersey/logging/mixins.rb
126
+ - lib/jersey/middleware/auto_json.rb
125
127
  - lib/jersey/middleware/error_handler.rb
126
128
  - lib/jersey/middleware/request_id.rb
127
129
  - lib/jersey/middleware/request_logger.rb
128
130
  - lib/jersey/setup.rb
129
131
  - lib/jersey/time.rb
130
132
  - lib/jersey/version.rb
133
+ - test/auto_json_test.rb
131
134
  - test/errors_test.rb
132
135
  - test/helper.rb
133
136
  - test/log_test.rb
@@ -154,11 +157,12 @@ required_rubygems_version: !ruby/object:Gem::Requirement
154
157
  version: '0'
155
158
  requirements: []
156
159
  rubyforge_project:
157
- rubygems_version: 2.2.2
160
+ rubygems_version: 2.2.0
158
161
  signing_key:
159
162
  specification_version: 4
160
163
  summary: Write APIs in the New Jersey Style
161
164
  test_files:
165
+ - test/auto_json_test.rb
162
166
  - test/errors_test.rb
163
167
  - test/helper.rb
164
168
  - test/log_test.rb