jersey 0.0.3 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: c73c2c478b36fbd1a0574323dcbb7f023264517d
4
- data.tar.gz: d7f9a1f7e5cd742a9de16d62c12b8b9cce788137
3
+ metadata.gz: 8917e3fd5a219b1f47d717b67c220309e0099e53
4
+ data.tar.gz: 877d58392cf2c2ed29f0c716be9ae96e013624d0
5
5
  SHA512:
6
- metadata.gz: 81638bfb73758bf758ae0245c163f88c2bf01c9214736a036c74f00e4a8f3a6309888588e07be9878783835f4ebad5bf02c348be1ec5dbb2adcdac72637d095e
7
- data.tar.gz: 49fc8716d35f5e8b8d1cffb85d912e391c5325b22e8e72a751b9aedebaee14a94f82d9e27727b92773808d660790bcd4f0f9f95914845ac1d002adb499efced3
6
+ metadata.gz: d79189492a2066fc625ad5b89c6fd68874d7c820d65a5def6f506b5de8a9f404cb5e8c1d2cb39db9d83db1c42dfae57668100f2f1883951e150d9c6b3105cc6c
7
+ data.tar.gz: b3321888bd62a38ea83d8552be66df3fc28ec1a64179340cfa1eced4f5ad0da42d9af13b7a0a53ba2dfcd9cd1acc9972a1c1add634471404b95de5f2dc8b48ac
@@ -0,0 +1,5 @@
1
+ language: ruby
2
+ cache: bundler
3
+ rvm:
4
+ - 2.2.0
5
+ - 2.1.5
@@ -20,7 +20,7 @@ Gem::Specification.new do |spec|
20
20
 
21
21
  spec.add_dependency "sinatra", "~> 1.4"
22
22
  spec.add_dependency 'sinatra-contrib', "~> 1.4"
23
- spec.add_dependency 'env-conf'
23
+ spec.add_dependency 'env-conf', '0.0.4'
24
24
  spec.add_dependency 'request_store'
25
25
  spec.add_development_dependency "bundler", "~> 1.7"
26
26
  spec.add_development_dependency "rake", "~> 10.0"
@@ -1,3 +1,5 @@
1
+ require 'request_store'
2
+
1
3
  module Jersey
2
4
  module API
3
5
  module Middleware
@@ -8,5 +10,17 @@ module Jersey
8
10
 
9
11
  module Helpers
10
12
  end
13
+
14
+ module HTTP
15
+ end
11
16
  end
12
17
  end
18
+
19
+ # jersey
20
+ require 'jersey/http_errors'
21
+ require 'jersey/middleware/request_id'
22
+ require 'jersey/middleware/error_handler'
23
+ require 'jersey/middleware/request_logger'
24
+ require 'jersey/extensions/route_signature'
25
+ require 'jersey/helpers/log'
26
+ require 'jersey/helpers/success'
@@ -1,22 +1,17 @@
1
1
  require "sinatra/base"
2
2
  require 'sinatra/json'
3
3
  require 'json'
4
- require 'request_store'
5
4
 
6
- # jersey
7
- require 'jersey/http_errors'
8
- require 'jersey/middleware/request_id'
9
- require 'jersey/middleware/request_logger'
10
- require 'jersey/extensions/route_signature'
11
- require 'jersey/extensions/error_handler'
12
- require 'jersey/helpers/log'
5
+ # Take over Sinatra's NotFound so we don't have to deal with the
6
+ # not_found block and can raise our own NotFound error
7
+ ::Sinatra.send(:remove_const, :NotFound)
8
+ ::Sinatra.const_set(:NotFound, ::Jersey::HTTP::Errors::NotFound)
13
9
 
14
10
  module Jersey::API
15
11
  class Base < Sinatra::Base
16
12
  include Jersey::HTTP::Errors
17
13
 
18
14
  register Jersey::Extensions::RouteSignature
19
- register Jersey::Extensions::ErrorHandler
20
15
 
21
16
  use Rack::Deflater
22
17
  use Rack::ConditionalGet
@@ -24,8 +19,14 @@ module Jersey::API
24
19
 
25
20
  use Jersey::Middleware::RequestID
26
21
  use Jersey::Middleware::RequestLogger
22
+ use Jersey::Middleware::ErrorHandler
27
23
 
28
24
  helpers Sinatra::JSON
29
25
  helpers Jersey::Helpers::Log
26
+ helpers Jersey::Helpers::Success
27
+
28
+ set :dump_errors, false
29
+ set :raise_errors, true
30
+ set :show_exceptions, false
30
31
  end
31
32
  end
@@ -21,6 +21,7 @@ module Jersey::Extensions
21
21
 
22
22
  json(error: {
23
23
  type: e.class.name.split('::').last,
24
+ request_id: env['REQUEST_ID'],
24
25
  message: e.message,
25
26
  backtrace: e.backtrace
26
27
  })
@@ -0,0 +1,17 @@
1
+ module Jersey::Helpers
2
+ module Success
3
+ def created(*args)
4
+ status(201)
5
+ json(*args)
6
+ end
7
+
8
+ def accepted(*args)
9
+ status(202)
10
+ json(*args)
11
+ end
12
+
13
+ def no_content(*args)
14
+ status(204)
15
+ end
16
+ end
17
+ end
@@ -1,62 +1,57 @@
1
- module Jersey
2
- module HTTP
3
- module Errors
4
- HTTPError = Class.new(StandardError)
5
- ClientError = Class.new(HTTPError)
6
- ServerError = Class.new(HTTPError)
1
+ module Jersey::HTTP
2
+ module Errors
3
+ HTTPError = Class.new(StandardError)
4
+ ClientError = Class.new(HTTPError)
5
+ ServerError = Class.new(HTTPError)
7
6
 
8
- # Define ALL the HTTP errors as constants
9
- FOUR_HUNDRED = [
10
- [400, 'BadRequest', :bad_request],
11
- [401, 'Unauthorized', :unauthorized],
12
- [402, 'PaymentRequired', :payment_required],
13
- [403, 'Forbidden', :forbidden],
14
- [404, 'NotFound', :not_found],
15
- [405, 'MethodNotAllowed', :method_not_allowed],
16
- [406, 'NotAcceptable', :not_acceptable],
17
- [407, 'ProxyAuthenticationRequired', :proxy_authentication_required],
18
- [408, 'RequestTimeout', :request_timeout],
19
- [409, 'Conflict', :conflict],
20
- [410, 'Gone', :gone],
21
- [411, 'LengthRequired', :length_required],
22
- [412, 'PreconditionFailed', :precondition_failed],
23
- [413, 'RequestEntityTooLarge', :request_entity_too_large],
24
- [414, 'RequestURITooLong', :request_uri_too_long],
25
- [415, 'UnsupportedMediaType', :unsupported_media_type],
26
- [416, 'RequestedRangeNotSatisfiable', :requested_range_not_satisfiable],
27
- [417, 'ExpectationFailed', :expectation_failed],
28
- [422, 'UnprocessableEntity', :unprocessable_entity],
29
- [423, 'Locked', :locked],
30
- [424, 'FailedDependency', :failed_dependency],
31
- [426, 'UpgradeRequired', :upgrade_required],
32
- ]
7
+ # Define ALL the HTTP errors as constants
8
+ FOUR_HUNDRED = [
9
+ [400, 'BadRequest', :bad_request],
10
+ [401, 'Unauthorized', :unauthorized],
11
+ [402, 'PaymentRequired', :payment_required],
12
+ [403, 'Forbidden', :forbidden],
13
+ [404, 'NotFound', :not_found],
14
+ [405, 'MethodNotAllowed', :method_not_allowed],
15
+ [406, 'NotAcceptable', :not_acceptable],
16
+ [407, 'ProxyAuthenticationRequired', :proxy_authentication_required],
17
+ [408, 'RequestTimeout', :request_timeout],
18
+ [409, 'Conflict', :conflict],
19
+ [410, 'Gone', :gone],
20
+ [411, 'LengthRequired', :length_required],
21
+ [412, 'PreconditionFailed', :precondition_failed],
22
+ [413, 'RequestEntityTooLarge', :request_entity_too_large],
23
+ [414, 'RequestURITooLong', :request_uri_too_long],
24
+ [415, 'UnsupportedMediaType', :unsupported_media_type],
25
+ [416, 'RequestedRangeNotSatisfiable', :requested_range_not_satisfiable],
26
+ [417, 'ExpectationFailed', :expectation_failed],
27
+ [422, 'UnprocessableEntity', :unprocessable_entity],
28
+ [423, 'Locked', :locked],
29
+ [424, 'FailedDependency', :failed_dependency],
30
+ [426, 'UpgradeRequired', :upgrade_required],
31
+ ]
33
32
 
34
- FIVE_HUNDRED = [
35
- [500, 'InternalServerError', :internal_server_error],
36
- [501, 'NotImplemented', :not_implemented],
37
- [502, 'BadGateway', :bad_gateway],
38
- [503, 'ServiceUnavailable', :service_unavailable],
39
- [504, 'GatewayTimeout', :gateway_timeout],
40
- [505, 'HTTPVersionNotSupported', :http_version_not_supported],
41
- [507, 'InsufficientStorage', :insufficient_storage],
42
- [510, 'NotExtended', :not_extended],
43
- ]
33
+ FIVE_HUNDRED = [
34
+ [500, 'InternalServerError', :internal_server_error],
35
+ [501, 'NotImplemented', :not_implemented],
36
+ [502, 'BadGateway', :bad_gateway],
37
+ [503, 'ServiceUnavailable', :service_unavailable],
38
+ [504, 'GatewayTimeout', :gateway_timeout],
39
+ [505, 'HTTPVersionNotSupported', :http_version_not_supported],
40
+ [507, 'InsufficientStorage', :insufficient_storage],
41
+ [510, 'NotExtended', :not_extended],
42
+ ]
44
43
 
45
- (FOUR_HUNDRED + FIVE_HUNDRED).each do |s|
46
- code, const_name, symbol = s[0],s[1],s[2]
47
- if code >= 500
48
- klass = Class.new(ServerError)
49
- else
50
- klass = Class.new(ClientError)
51
- end
52
- klass.const_set(:STATUS_CODE, code)
53
- const_set(const_name,klass)
44
+ # Dynamically Create all the necessary HTTP errors
45
+ # with appropriate status codes
46
+ (FOUR_HUNDRED + FIVE_HUNDRED).each do |s|
47
+ code, const_name, symbol = s[0],s[1],s[2]
48
+ if code >= 500
49
+ klass = Class.new(ServerError)
50
+ else
51
+ klass = Class.new(ClientError)
54
52
  end
55
-
56
- # Take over Sinatra's NotFound so we don't have to deal with the
57
- # not_found block and can raise our own NotFound error
58
- ::Sinatra.send(:remove_const, :NotFound)
59
- ::Sinatra.const_set(:NotFound, ::Jersey::HTTP::Errors::NotFound)
53
+ klass.const_set(:STATUS_CODE, code)
54
+ const_set(const_name,klass)
60
55
  end
61
56
  end
62
57
  end
@@ -9,6 +9,11 @@ module Jersey
9
9
  include Logging::LogError
10
10
  end
11
11
 
12
+ class JsonLogger < JSONLogger
13
+ include Logging::LogTime
14
+ include Logging::LogError
15
+ end
16
+
12
17
  module LoggingSingleton
13
18
  attr_writer :logger
14
19
 
@@ -0,0 +1,40 @@
1
+ module Jersey::Middleware
2
+ class ErrorHandler
3
+ def initialize(app, options = {})
4
+ @app = app
5
+ ib = options[:include_backtrace]
6
+ @include_backtrace = (ib.nil? && ENV['RACK_ENV'] == 'development') || ib
7
+ end
8
+
9
+ def call(env)
10
+ begin
11
+ @app.call(env)
12
+ rescue => e
13
+ # get status code from Jersey Errors
14
+ if e.class.const_defined?(:STATUS_CODE)
15
+ status = e.class::STATUS_CODE
16
+ elsif e.respond_to?(:status_code)
17
+ status = e.status_code
18
+ else
19
+ status = 500
20
+ end
21
+
22
+ headers = {
23
+ 'Content-Type' => 'application/json'
24
+ }
25
+
26
+ body = {error: {
27
+ type: e.class.name.split('::').last,
28
+ request_id: env['REQUEST_ID'] || env['HTTP_REQUEST_ID'],
29
+ message: e.message
30
+ }}
31
+
32
+ if @include_backtrace
33
+ body[:error][:backtrace] = e.backtrace
34
+ end
35
+
36
+ [status, headers, [body.to_json]]
37
+ end
38
+ end
39
+ end
40
+ end
@@ -1,3 +1,3 @@
1
1
  module Jersey
2
- VERSION = "0.0.3"
2
+ VERSION = "0.1.0"
3
3
  end
@@ -1,7 +1,7 @@
1
1
  require_relative 'helper'
2
2
 
3
3
  class ErrorsTest < ApiTest
4
- class SimpleApi < Jersey::API::Base
4
+ class App < Jersey::API::Base
5
5
  get '/test-409' do
6
6
  raise Conflict, "bad"
7
7
  end
@@ -15,10 +15,6 @@ class ErrorsTest < ApiTest
15
15
  end
16
16
  end
17
17
 
18
- def app
19
- SimpleApi
20
- end
21
-
22
18
  def test_not_found
23
19
  get '/not-found'
24
20
  assert_equal(404, last_response.status)
@@ -30,6 +26,7 @@ class ErrorsTest < ApiTest
30
26
  assert_equal(409, last_response.status)
31
27
  assert_equal('Conflict', json['error']['type'])
32
28
  assert_equal('bad', json['error']['message'])
29
+ assert(json['error']['request_id'])
33
30
  end
34
31
 
35
32
  def test_http_errors_500
@@ -37,6 +34,7 @@ class ErrorsTest < ApiTest
37
34
  assert_equal(500, last_response.status)
38
35
  assert_equal('InternalServerError', json['error']['type'])
39
36
  assert_equal('bad', json['error']['message'])
37
+ assert(json['error']['request_id'])
40
38
  end
41
39
 
42
40
  def test_http_errors_Undefined
@@ -44,5 +42,18 @@ class ErrorsTest < ApiTest
44
42
  assert_equal(500, last_response.status)
45
43
  assert_equal('RuntimeError', json['error']['type'])
46
44
  assert_equal('boom!', json['error']['message'])
45
+ assert(json['error']['request_id'])
46
+ end
47
+
48
+ def test_errors_are_logged
49
+ Jersey.logger.stream = StringIO.new
50
+ get '/test-500'
51
+ loglines = logs.lines
52
+ assert_equal(2, loglines.size)
53
+ logdata = Logfmt.parse(loglines[0])
54
+ assert(logdata['at'], 'started')
55
+ logdata = Logfmt.parse(loglines[1])
56
+ assert(logdata['at'], 'finished')
57
+ assert(logdata['status'], '500')
47
58
  end
48
59
  end
@@ -0,0 +1,35 @@
1
+ require_relative 'helper'
2
+
3
+ class SuccessTest < ApiTest
4
+ class App < Jersey::API::Base
5
+ get '/test-201' do
6
+ created({foo: 'baz'})
7
+ end
8
+
9
+ get '/test-202' do
10
+ accepted({foo: 'bar'})
11
+ end
12
+
13
+ get '/test-204' do
14
+ no_content
15
+ end
16
+ end
17
+
18
+ def test_created
19
+ get '/test-201'
20
+ assert_equal(201, last_response.status)
21
+ assert_equal('baz', json['foo'])
22
+ end
23
+
24
+ def test_accepted
25
+ get '/test-202'
26
+ assert_equal(202, last_response.status)
27
+ assert_equal('bar', json['foo'])
28
+ end
29
+
30
+ def test_no_content
31
+ get '/test-204'
32
+ assert_equal(204, last_response.status)
33
+ assert_equal('', last_response.body)
34
+ end
35
+ 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.0.3
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - csquared
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-11-12 00:00:00.000000000 Z
11
+ date: 2015-02-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: sinatra
@@ -42,16 +42,16 @@ dependencies:
42
42
  name: env-conf
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
- - - ">="
45
+ - - '='
46
46
  - !ruby/object:Gem::Version
47
- version: '0'
47
+ version: 0.0.4
48
48
  type: :runtime
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
- - - ">="
52
+ - - '='
53
53
  - !ruby/object:Gem::Version
54
- version: '0'
54
+ version: 0.0.4
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: request_store
57
57
  requirement: !ruby/object:Gem::Requirement
@@ -102,6 +102,7 @@ extensions: []
102
102
  extra_rdoc_files: []
103
103
  files:
104
104
  - ".gitignore"
105
+ - ".travis.yml"
105
106
  - Gemfile
106
107
  - LICENSE.txt
107
108
  - README.md
@@ -114,12 +115,14 @@ files:
114
115
  - lib/jersey/extensions/error_handler.rb
115
116
  - lib/jersey/extensions/route_signature.rb
116
117
  - lib/jersey/helpers/log.rb
118
+ - lib/jersey/helpers/success.rb
117
119
  - lib/jersey/http_errors.rb
118
120
  - lib/jersey/log.rb
119
121
  - lib/jersey/logging/base_logger.rb
120
122
  - lib/jersey/logging/json_logger.rb
121
123
  - lib/jersey/logging/logfmt_logger.rb
122
124
  - lib/jersey/logging/mixins.rb
125
+ - lib/jersey/middleware/error_handler.rb
123
126
  - lib/jersey/middleware/request_id.rb
124
127
  - lib/jersey/middleware/request_logger.rb
125
128
  - lib/jersey/setup.rb
@@ -130,6 +133,7 @@ files:
130
133
  - test/log_test.rb
131
134
  - test/request_logger_test.rb
132
135
  - test/setup_test.rb
136
+ - test/success_test.rb
133
137
  homepage: ''
134
138
  licenses:
135
139
  - MIT
@@ -150,7 +154,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
150
154
  version: '0'
151
155
  requirements: []
152
156
  rubyforge_project:
153
- rubygems_version: 2.2.0
157
+ rubygems_version: 2.2.2
154
158
  signing_key:
155
159
  specification_version: 4
156
160
  summary: Write APIs in the New Jersey Style
@@ -160,3 +164,4 @@ test_files:
160
164
  - test/log_test.rb
161
165
  - test/request_logger_test.rb
162
166
  - test/setup_test.rb
167
+ - test/success_test.rb