salestation 3.5.1 → 3.9.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 +5 -5
- data/.travis.yml +1 -3
- data/README.md +25 -3
- data/lib/salestation/app.rb +1 -1
- data/lib/salestation/app/errors.rb +17 -9
- data/lib/salestation/web.rb +1 -1
- data/lib/salestation/web/error_mapper.rb +8 -7
- data/lib/salestation/web/responses.rb +18 -8
- data/lib/salestation/web/statsd_middleware.rb +4 -3
- data/salestation.gemspec +2 -2
- metadata +8 -9
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
|
-
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: c185cbbf51aa9e484fad4fc0099a9b518d11954f5c5c2f11d03f9d086fdeee08
|
|
4
|
+
data.tar.gz: a8c356c5559e1ee1f02da859513badc848003d35cea3167ae66488c631309fca
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: c028e25b401034206c66be282335e78e903edac248adaabecd0041bd5a187397f7bda59d894ed35ded3132aed762e3c8596d4aeeee92f6c5b93fbb9549245ec6
|
|
7
|
+
data.tar.gz: 4dc319fd28ae97aff269c0a6594a2cb271721da31c2ae48d7afd8927ccc352df1526fcfc486146ef55571788bca954de5649ce36a53b73c09767fb28eae99fb1
|
data/.travis.yml
CHANGED
data/README.md
CHANGED
|
@@ -75,6 +75,28 @@ Salestation allows and recommends you to define your own custom errors. This is
|
|
|
75
75
|
})
|
|
76
76
|
```
|
|
77
77
|
|
|
78
|
+
### Providing custom error fields
|
|
79
|
+
|
|
80
|
+
If you need to specify additional error fields you can use `from` method.
|
|
81
|
+
`from` accepts base error on which the rest of the response is built.
|
|
82
|
+
Base error must be a hash or implement `to_h` method.
|
|
83
|
+
|
|
84
|
+
Example:
|
|
85
|
+
|
|
86
|
+
```
|
|
87
|
+
App::Errors::Conflict.from({details: 'details'}, message: 'message', debug_message: 'debug_message')
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
Response:
|
|
91
|
+
|
|
92
|
+
```javascript
|
|
93
|
+
{
|
|
94
|
+
"details": "details",
|
|
95
|
+
"message": "message",
|
|
96
|
+
"debug_message": "debug_message"
|
|
97
|
+
}
|
|
98
|
+
```
|
|
99
|
+
|
|
78
100
|
### Using Extractors
|
|
79
101
|
|
|
80
102
|
Salestation provides extractors to fetch parameters from the request and pass them to the chain.
|
|
@@ -142,14 +164,14 @@ end
|
|
|
142
164
|
|
|
143
165
|
Salestation provides a StatsD middleware which can be used record request
|
|
144
166
|
execution time. A `timing` call with elapsed seconds is made to the provided
|
|
145
|
-
StatsD instance with `path`, `method`, `status` tags.
|
|
167
|
+
StatsD instance with `path`, `method`, `status` and `status_class` tags.
|
|
146
168
|
|
|
147
169
|
```ruby
|
|
148
170
|
class Webapp < Sinatra::Base
|
|
149
171
|
# ...
|
|
150
172
|
use Salestation::Web::StatsdMiddleware,
|
|
151
173
|
Statsd.new(host, port),
|
|
152
|
-
metric: '
|
|
174
|
+
metric: 'my_service.response.time'
|
|
153
175
|
end
|
|
154
176
|
```
|
|
155
177
|
|
|
@@ -157,7 +179,7 @@ You can configure per-request tags by defining `salestation.statsd.tags` in sina
|
|
|
157
179
|
|
|
158
180
|
```ruby
|
|
159
181
|
def my_handler(env)
|
|
160
|
-
env['salestation.statsd.tags'] = ['foo
|
|
182
|
+
env['salestation.statsd.tags'] = ['foo:bar']
|
|
161
183
|
# ...
|
|
162
184
|
end
|
|
163
185
|
```
|
data/lib/salestation/app.rb
CHANGED
|
@@ -3,43 +3,51 @@
|
|
|
3
3
|
module Salestation
|
|
4
4
|
class App
|
|
5
5
|
module Errors
|
|
6
|
-
class
|
|
6
|
+
class Error < Dry::Struct
|
|
7
|
+
attribute? :base_error, Types::Coercible::Hash
|
|
8
|
+
|
|
9
|
+
def self.from(base_error, overrides = {})
|
|
10
|
+
new(**overrides, base_error: base_error.to_h)
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
class InvalidInput < Error
|
|
7
15
|
attribute :errors, Types::Strict::Hash
|
|
8
|
-
attribute :hints, Types::Coercible::Hash.default({})
|
|
16
|
+
attribute :hints, Types::Coercible::Hash.default({}.freeze)
|
|
9
17
|
attribute? :debug_message, Types::Strict::String
|
|
10
18
|
end
|
|
11
19
|
|
|
12
|
-
class DependencyCurrentlyUnavailable <
|
|
20
|
+
class DependencyCurrentlyUnavailable < Error
|
|
13
21
|
attribute :message, Types::Strict::String
|
|
14
22
|
attribute? :debug_message, Types::Strict::String
|
|
15
23
|
end
|
|
16
24
|
|
|
17
|
-
class RequestedResourceNotFound <
|
|
25
|
+
class RequestedResourceNotFound < Error
|
|
18
26
|
attribute :message, Types::Strict::String
|
|
19
27
|
attribute? :debug_message, Types::Strict::String
|
|
20
28
|
end
|
|
21
29
|
|
|
22
|
-
class Forbidden <
|
|
30
|
+
class Forbidden < Error
|
|
23
31
|
attribute :message, Types::Strict::String
|
|
24
32
|
attribute? :debug_message, Types::Strict::String
|
|
25
33
|
end
|
|
26
34
|
|
|
27
|
-
class Conflict <
|
|
35
|
+
class Conflict < Error
|
|
28
36
|
attribute :message, Types::Strict::String
|
|
29
37
|
attribute :debug_message, Types::Strict::String
|
|
30
38
|
end
|
|
31
39
|
|
|
32
|
-
class NotAcceptable <
|
|
40
|
+
class NotAcceptable < Error
|
|
33
41
|
attribute :message, Types::Strict::String
|
|
34
42
|
attribute :debug_message, Types::Strict::String
|
|
35
43
|
end
|
|
36
44
|
|
|
37
|
-
class UnsupportedMediaType <
|
|
45
|
+
class UnsupportedMediaType < Error
|
|
38
46
|
attribute :message, Types::Strict::String
|
|
39
47
|
attribute :debug_message, Types::Strict::String
|
|
40
48
|
end
|
|
41
49
|
|
|
42
|
-
class RequestEntityTooLarge <
|
|
50
|
+
class RequestEntityTooLarge < Error
|
|
43
51
|
attribute :message, Types::Strict::String
|
|
44
52
|
attribute? :debug_message, Types::Strict::String
|
|
45
53
|
end
|
data/lib/salestation/web.rb
CHANGED
|
@@ -12,26 +12,27 @@ module Salestation
|
|
|
12
12
|
App::Errors::DependencyCurrentlyUnavailable => -> (error) {
|
|
13
13
|
Responses::ServiceUnavailable.new(
|
|
14
14
|
message: error.message,
|
|
15
|
-
debug_message: "Please try again later"
|
|
15
|
+
debug_message: "Please try again later",
|
|
16
|
+
base_error: error.base_error
|
|
16
17
|
)
|
|
17
18
|
},
|
|
18
19
|
App::Errors::RequestedResourceNotFound => -> (error) {
|
|
19
|
-
Responses::NotFound.new(message: error.message, debug_message: error.debug_message)
|
|
20
|
+
Responses::NotFound.new(message: error.message, debug_message: error.debug_message, base_error: error.base_error)
|
|
20
21
|
},
|
|
21
22
|
App::Errors::Forbidden => -> (error) {
|
|
22
|
-
Responses::Forbidden.new(message: error.message, debug_message: error.debug_message)
|
|
23
|
+
Responses::Forbidden.new(message: error.message, debug_message: error.debug_message, base_error: error.base_error)
|
|
23
24
|
},
|
|
24
25
|
App::Errors::Conflict => -> (error) {
|
|
25
|
-
Responses::Conflict.new(message: error.message, debug_message: error.debug_message)
|
|
26
|
+
Responses::Conflict.new(message: error.message, debug_message: error.debug_message, base_error: error.base_error)
|
|
26
27
|
},
|
|
27
28
|
App::Errors::NotAcceptable => -> (error) {
|
|
28
|
-
Responses::NotAcceptable.new(message: error.message, debug_message: error.debug_message)
|
|
29
|
+
Responses::NotAcceptable.new(message: error.message, debug_message: error.debug_message, base_error: error.base_error)
|
|
29
30
|
},
|
|
30
31
|
App::Errors::UnsupportedMediaType => -> (error) {
|
|
31
|
-
Responses::UnsupportedMediaType.new(message: error.message, debug_message: error.debug_message)
|
|
32
|
+
Responses::UnsupportedMediaType.new(message: error.message, debug_message: error.debug_message, base_error: error.base_error)
|
|
32
33
|
},
|
|
33
34
|
App::Errors::RequestEntityTooLarge => -> (error) {
|
|
34
|
-
Responses::RequestEntityTooLarge.new(message: error.message, debug_message: error.debug_message)
|
|
35
|
+
Responses::RequestEntityTooLarge.new(message: error.message, debug_message: error.debug_message, base_error: error.base_error)
|
|
35
36
|
}
|
|
36
37
|
}.freeze
|
|
37
38
|
|
|
@@ -32,27 +32,37 @@ module Salestation
|
|
|
32
32
|
class Error < Response
|
|
33
33
|
attribute :status, Types::Strict::Integer
|
|
34
34
|
attribute :message, Types::Strict::String
|
|
35
|
-
attribute :debug_message, Types::String.default('')
|
|
36
|
-
attribute :context, Types::Hash.default({})
|
|
37
|
-
attribute :headers, Types::Hash.default({})
|
|
35
|
+
attribute :debug_message, Types::Coercible::String.default('')
|
|
36
|
+
attribute :context, Types::Hash.default({}.freeze)
|
|
37
|
+
attribute :headers, Types::Hash.default({}.freeze)
|
|
38
|
+
attribute? :base_error, Types::Coercible::Hash
|
|
38
39
|
|
|
39
40
|
def body
|
|
40
|
-
|
|
41
|
+
# Merge into `base_error` to ensure standard fields are not overriden
|
|
42
|
+
(base_error || {}).merge(message: message, debug_message: debug_message)
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
class UnprocessableEntityError < Error
|
|
47
|
+
attribute :form_errors, Types::Hash.default({}.freeze)
|
|
48
|
+
|
|
49
|
+
def body
|
|
50
|
+
super.merge(form_errors: form_errors)
|
|
41
51
|
end
|
|
42
52
|
end
|
|
43
53
|
|
|
44
54
|
class Success < Response
|
|
45
55
|
attribute :status, Types::Strict::Integer
|
|
46
56
|
attribute :body, Types::Strict::Hash | Types::Strict::Array
|
|
47
|
-
attribute :headers, Types::Hash.default({})
|
|
57
|
+
attribute :headers, Types::Hash.default({}.freeze)
|
|
48
58
|
end
|
|
49
59
|
|
|
50
60
|
class UnprocessableEntityFromSchemaErrors
|
|
51
|
-
def self.create(errors:, hints:)
|
|
61
|
+
def self.create(errors:, hints:, base_error: nil)
|
|
52
62
|
message = parse_errors(errors)
|
|
53
63
|
debug_message = parse_hints(hints)
|
|
54
64
|
|
|
55
|
-
UnprocessableEntity.new(message: message, debug_message: debug_message)
|
|
65
|
+
UnprocessableEntity.new(message: message, debug_message: debug_message, form_errors: errors, base_error: base_error)
|
|
56
66
|
end
|
|
57
67
|
|
|
58
68
|
def self.parse_errors(errors)
|
|
@@ -99,7 +109,7 @@ module Salestation
|
|
|
99
109
|
Conflict = Error.with_code(409)
|
|
100
110
|
RequestEntityTooLarge = Error.with_code(413)
|
|
101
111
|
UnsupportedMediaType = Error.with_code(415)
|
|
102
|
-
UnprocessableEntity =
|
|
112
|
+
UnprocessableEntity = UnprocessableEntityError.with_code(422)
|
|
103
113
|
|
|
104
114
|
InternalError = Error.with_code(500)
|
|
105
115
|
ServiceUnavailable = Error.with_code(503)
|
|
@@ -27,9 +27,10 @@ module Salestation
|
|
|
27
27
|
end
|
|
28
28
|
|
|
29
29
|
tags = [
|
|
30
|
-
"path:#{
|
|
31
|
-
"method:#{
|
|
32
|
-
"status:#{
|
|
30
|
+
"path:#{path}",
|
|
31
|
+
"method:#{method}",
|
|
32
|
+
"status:#{status}",
|
|
33
|
+
"status_class:#{status / 100}xx"
|
|
33
34
|
] + env.fetch(EXTRA_TAGS_ENV_KEY, [])
|
|
34
35
|
|
|
35
36
|
@statsd.timing(@metric, duration_ms(from: start), tags: tags)
|
data/salestation.gemspec
CHANGED
|
@@ -4,7 +4,7 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
|
4
4
|
|
|
5
5
|
Gem::Specification.new do |spec|
|
|
6
6
|
spec.name = "salestation"
|
|
7
|
-
spec.version = "3.
|
|
7
|
+
spec.version = "3.9.0"
|
|
8
8
|
spec.authors = ["Glia TechMovers"]
|
|
9
9
|
spec.email = ["techmovers@glia.com"]
|
|
10
10
|
|
|
@@ -19,7 +19,7 @@ Gem::Specification.new do |spec|
|
|
|
19
19
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
|
20
20
|
spec.require_paths = ["lib"]
|
|
21
21
|
|
|
22
|
-
spec.add_development_dependency "bundler", "~>
|
|
22
|
+
spec.add_development_dependency "bundler", "~> 2.0"
|
|
23
23
|
spec.add_development_dependency "rake", "~> 13.0"
|
|
24
24
|
spec.add_development_dependency "rspec", "~> 3.0"
|
|
25
25
|
spec.add_development_dependency "pry", "~> 0.10.4"
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: salestation
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 3.
|
|
4
|
+
version: 3.9.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Glia TechMovers
|
|
8
|
-
autorequire:
|
|
8
|
+
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date:
|
|
11
|
+
date: 2021-01-14 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: bundler
|
|
@@ -16,14 +16,14 @@ dependencies:
|
|
|
16
16
|
requirements:
|
|
17
17
|
- - "~>"
|
|
18
18
|
- !ruby/object:Gem::Version
|
|
19
|
-
version: '
|
|
19
|
+
version: '2.0'
|
|
20
20
|
type: :development
|
|
21
21
|
prerelease: false
|
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
|
23
23
|
requirements:
|
|
24
24
|
- - "~>"
|
|
25
25
|
- !ruby/object:Gem::Version
|
|
26
|
-
version: '
|
|
26
|
+
version: '2.0'
|
|
27
27
|
- !ruby/object:Gem::Dependency
|
|
28
28
|
name: rake
|
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -143,7 +143,7 @@ homepage: ''
|
|
|
143
143
|
licenses:
|
|
144
144
|
- MIT
|
|
145
145
|
metadata: {}
|
|
146
|
-
post_install_message:
|
|
146
|
+
post_install_message:
|
|
147
147
|
rdoc_options: []
|
|
148
148
|
require_paths:
|
|
149
149
|
- lib
|
|
@@ -158,9 +158,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
158
158
|
- !ruby/object:Gem::Version
|
|
159
159
|
version: '0'
|
|
160
160
|
requirements: []
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
signing_key:
|
|
161
|
+
rubygems_version: 3.0.6
|
|
162
|
+
signing_key:
|
|
164
163
|
specification_version: 4
|
|
165
164
|
summary: ''
|
|
166
165
|
test_files: []
|