readme-metrics 1.0.0 → 1.1.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 +4 -4
- data/Gemfile.lock +2 -2
- data/README.md +12 -11
- data/lib/readme/content_type_helper.rb +17 -0
- data/lib/readme/errors.rb +1 -1
- data/lib/readme/filter.rb +56 -41
- data/lib/readme/http_request.rb +101 -0
- data/lib/readme/http_response.rb +45 -0
- data/lib/readme/metrics.rb +11 -8
- data/lib/readme/metrics/version.rb +1 -1
- data/lib/readme/payload.rb +2 -0
- data/readme-metrics.gemspec +2 -2
- metadata +8 -8
- data/lib/content_type_helper.rb +0 -15
- data/lib/http_request.rb +0 -99
- data/lib/http_response.rb +0 -43
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: df0dd7efcddca3f324e4e6f7b61fd70a1bee3d3d81571ffa1dc72e090bf2934e
|
4
|
+
data.tar.gz: b99811540e9195cecad5c8ee3cf7807fb3340e87353327d021a166af5f34a112
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6d39db68ce16afde0e0139a4e31bfac53f5bef2066972777165502eac78fd09ed292a23e945d7584385148e3375d72f8d254275a7367e7e07278a16a79b85819
|
7
|
+
data.tar.gz: c8e5b439466d50cbac88269d6036c22f7aa84864590cc28862976bf005ada580431b3e9a4a8e652a6ae5ecadb687b2bf59e6607f0cd87e15315f26b86a003d12
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
readme-metrics (
|
4
|
+
readme-metrics (1.1.0)
|
5
5
|
httparty (~> 0.18)
|
6
6
|
|
7
7
|
GEM
|
@@ -21,7 +21,7 @@ GEM
|
|
21
21
|
addressable (>= 2.4)
|
22
22
|
mime-types (3.3.1)
|
23
23
|
mime-types-data (~> 3.2015)
|
24
|
-
mime-types-data (3.
|
24
|
+
mime-types-data (3.2021.0225)
|
25
25
|
multi_xml (0.6.0)
|
26
26
|
parallel (1.19.2)
|
27
27
|
parser (2.7.1.4)
|
data/README.md
CHANGED
@@ -1,7 +1,8 @@
|
|
1
|
-
#
|
1
|
+
# readme-metrics
|
2
2
|
|
3
3
|
Track your API metrics within ReadMe.
|
4
4
|
|
5
|
+
[](https://rubygems.org/gems/readme-metrics)
|
5
6
|
[](https://github.com/readmeio/metrics-sdks)
|
6
7
|
|
7
8
|
[](https://readme.io)
|
@@ -26,8 +27,8 @@ current_user for a given request from the environment.
|
|
26
27
|
|
27
28
|
### Batching requests
|
28
29
|
|
29
|
-
By default, the middleware will batch requests to the ReadMe API in groups of
|
30
|
-
|
30
|
+
By default, the middleware will batch requests to the ReadMe API in groups of 10.
|
31
|
+
For every 10 requests made to your application, the middleware will make a
|
31
32
|
single request to ReadMe. If you wish to override this, provide a
|
32
33
|
`buffer_length` option when configuring the middleware.
|
33
34
|
|
@@ -51,7 +52,7 @@ You may only specify either `reject_params` or `allow_only` keys, not both.
|
|
51
52
|
require "readme/metrics"
|
52
53
|
|
53
54
|
options = {
|
54
|
-
api_key: "
|
55
|
+
api_key: "<<apiKey>>",
|
55
56
|
development: false,
|
56
57
|
reject_params: ["not_included", "dont_send"],
|
57
58
|
buffer_length: 5,
|
@@ -62,13 +63,13 @@ config.middleware.use Readme::Metrics, options do |env|
|
|
62
63
|
|
63
64
|
if current_user.present?
|
64
65
|
{
|
65
|
-
|
66
|
+
api_key: current_user.api_key, # Not the same as the ReadMe API Key
|
66
67
|
label: current_user.name,
|
67
68
|
email: current_user.email
|
68
69
|
}
|
69
70
|
else
|
70
71
|
{
|
71
|
-
|
72
|
+
api_key: "guest",
|
72
73
|
label: "Guest User",
|
73
74
|
email: "guest@example.com"
|
74
75
|
}
|
@@ -81,16 +82,16 @@ end
|
|
81
82
|
```ruby
|
82
83
|
# config.ru
|
83
84
|
options = {
|
84
|
-
api_key: "
|
85
|
+
api_key: "<<apiKey>>",
|
85
86
|
development: false,
|
86
87
|
reject_params: ["not_included", "dont_send"]
|
87
88
|
}
|
88
89
|
|
89
90
|
use Readme::Metrics, options do |env|
|
90
91
|
{
|
91
|
-
|
92
|
-
label: "
|
93
|
-
email: "
|
92
|
+
api_key: "owlbert_api_key"
|
93
|
+
label: "Owlbert",
|
94
|
+
email: "owlbert@example.com"
|
94
95
|
}
|
95
96
|
end
|
96
97
|
|
@@ -105,4 +106,4 @@ run YourApp.new
|
|
105
106
|
|
106
107
|
## License
|
107
108
|
|
108
|
-
[View our license here](https://github.com/readmeio/metrics-sdks/tree/
|
109
|
+
[View our license here](https://github.com/readmeio/metrics-sdks/tree/main/packages/ruby/LICENSE)
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Readme
|
2
|
+
module ContentTypeHelper
|
3
|
+
# Assumes the includer has a `content_type` method defined.
|
4
|
+
|
5
|
+
JSON_MIME_TYPES = [
|
6
|
+
"application/json",
|
7
|
+
"application/x-json",
|
8
|
+
"text/json",
|
9
|
+
"text/x-json",
|
10
|
+
"+json"
|
11
|
+
]
|
12
|
+
|
13
|
+
def json?
|
14
|
+
JSON_MIME_TYPES.any? { |mime_type| content_type.include?(mime_type) }
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
data/lib/readme/errors.rb
CHANGED
@@ -25,7 +25,7 @@ module Readme
|
|
25
25
|
middleware.
|
26
26
|
|
27
27
|
Expected a hash with the shape:
|
28
|
-
{
|
28
|
+
{ api_key: "Your user api key", label: "Your user label", email: "Your user email" }
|
29
29
|
|
30
30
|
Received value:
|
31
31
|
#{result}
|
data/lib/readme/filter.rb
CHANGED
@@ -1,58 +1,73 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
1
|
+
module Readme
|
2
|
+
class Filter
|
3
|
+
def self.for(reject: nil, allow_only: nil)
|
4
|
+
if !reject.nil? && !allow_only.nil?
|
5
|
+
raise FilterArgsError
|
6
|
+
elsif !reject.nil?
|
7
|
+
RejectParams.new(reject)
|
8
|
+
elsif !allow_only.nil?
|
9
|
+
AllowOnly.new(allow_only)
|
10
|
+
else
|
11
|
+
None.new
|
12
|
+
end
|
11
13
|
end
|
12
|
-
end
|
13
14
|
|
14
|
-
|
15
|
-
|
16
|
-
|
15
|
+
def self.redact(rejected_params)
|
16
|
+
rejected_params.each_with_object({}) do |(k, v), hash|
|
17
|
+
# If it's a string then return the length of the redacted field
|
18
|
+
hash[k.to_str] = "[REDACTED#{v.is_a?(String) ? " #{v.length}" : ""}]"
|
19
|
+
end
|
17
20
|
end
|
18
21
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
+
class AllowOnly
|
23
|
+
def initialize(filter_fields)
|
24
|
+
@allowed_fields = filter_fields
|
25
|
+
end
|
22
26
|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
end
|
27
|
+
def filter(hash)
|
28
|
+
allowed_fields = @allowed_fields.map(&:downcase)
|
29
|
+
allowed_params, rejected_params = hash.partition { |key, _value| allowed_fields.include?(key.downcase) }.map(&:to_h)
|
27
30
|
|
28
|
-
|
29
|
-
|
30
|
-
@filter_values = filter_values.map(&:downcase)
|
31
|
-
end
|
31
|
+
allowed_params.merge(Filter.redact(rejected_params))
|
32
|
+
end
|
32
33
|
|
33
|
-
|
34
|
-
|
34
|
+
def pass_through?
|
35
|
+
false
|
36
|
+
end
|
35
37
|
end
|
36
38
|
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
39
|
+
class RejectParams
|
40
|
+
def initialize(filter_fields)
|
41
|
+
@rejected_fields = filter_fields
|
42
|
+
end
|
43
|
+
|
44
|
+
def filter(hash)
|
45
|
+
rejected_fields = @rejected_fields.map(&:downcase)
|
46
|
+
rejected_params, allowed_params = hash.partition { |key, _value| rejected_fields.include?(key.downcase) }.map(&:to_h)
|
47
|
+
|
48
|
+
allowed_params.merge(Filter.redact(rejected_params))
|
49
|
+
end
|
41
50
|
|
42
|
-
|
43
|
-
|
44
|
-
|
51
|
+
def pass_through?
|
52
|
+
false
|
53
|
+
end
|
45
54
|
end
|
46
55
|
|
47
|
-
|
48
|
-
|
56
|
+
class None
|
57
|
+
def filter(hash)
|
58
|
+
hash
|
59
|
+
end
|
60
|
+
|
61
|
+
def pass_through?
|
62
|
+
true
|
63
|
+
end
|
49
64
|
end
|
50
|
-
end
|
51
65
|
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
66
|
+
class FilterArgsError < StandardError
|
67
|
+
def initialize
|
68
|
+
msg = "Can only supply either reject_params or allow_only, not both."
|
69
|
+
super(msg)
|
70
|
+
end
|
56
71
|
end
|
57
72
|
end
|
58
73
|
end
|
@@ -0,0 +1,101 @@
|
|
1
|
+
require "rack"
|
2
|
+
require "rack/request"
|
3
|
+
require_relative "content_type_helper"
|
4
|
+
|
5
|
+
module Readme
|
6
|
+
class HttpRequest
|
7
|
+
include ContentTypeHelper
|
8
|
+
|
9
|
+
HTTP_NON_HEADERS = [
|
10
|
+
Rack::HTTP_COOKIE,
|
11
|
+
Rack::HTTP_VERSION,
|
12
|
+
Rack::HTTP_HOST,
|
13
|
+
Rack::HTTP_PORT
|
14
|
+
]
|
15
|
+
|
16
|
+
def initialize(env)
|
17
|
+
@request = Rack::Request.new(env)
|
18
|
+
end
|
19
|
+
|
20
|
+
def url
|
21
|
+
@request.url
|
22
|
+
end
|
23
|
+
|
24
|
+
def query_params
|
25
|
+
@request.GET
|
26
|
+
end
|
27
|
+
|
28
|
+
def cookies
|
29
|
+
@request.cookies
|
30
|
+
end
|
31
|
+
|
32
|
+
def http_version
|
33
|
+
@request.get_header(Rack::HTTP_VERSION)
|
34
|
+
end
|
35
|
+
|
36
|
+
def request_method
|
37
|
+
@request.request_method
|
38
|
+
end
|
39
|
+
|
40
|
+
def content_type
|
41
|
+
@request.content_type
|
42
|
+
end
|
43
|
+
|
44
|
+
def form_data?
|
45
|
+
@request.form_data?
|
46
|
+
end
|
47
|
+
|
48
|
+
def content_length
|
49
|
+
@request.content_length.to_i
|
50
|
+
end
|
51
|
+
|
52
|
+
def options?
|
53
|
+
@request.request_method == "OPTIONS"
|
54
|
+
end
|
55
|
+
|
56
|
+
def headers
|
57
|
+
@request
|
58
|
+
.each_header
|
59
|
+
.select { |key, _| http_header?(key) }
|
60
|
+
.to_h
|
61
|
+
.transform_keys { |header| normalize_header_name(header) }
|
62
|
+
.merge unprefixed_headers
|
63
|
+
end
|
64
|
+
|
65
|
+
def body
|
66
|
+
@request.body.rewind
|
67
|
+
content = @request.body.read
|
68
|
+
@request.body.rewind
|
69
|
+
|
70
|
+
content
|
71
|
+
end
|
72
|
+
|
73
|
+
def parsed_form_data
|
74
|
+
@request.POST
|
75
|
+
end
|
76
|
+
|
77
|
+
private
|
78
|
+
|
79
|
+
# "headers" in Rack::Request just means any key in the env. The HTTP headers
|
80
|
+
# are all the headers prefixed with `HTTP_` as per the spec:
|
81
|
+
# https://github.com/rack/rack/blob/master/SPEC.rdoc#the-environment-
|
82
|
+
# Other "headers" like version and host are prefixed with `HTTP_` by Rack but
|
83
|
+
# don't seem to be considered legit HTTP headers.
|
84
|
+
def http_header?(name)
|
85
|
+
name.start_with?("HTTP") && !HTTP_NON_HEADERS.include?(name)
|
86
|
+
end
|
87
|
+
|
88
|
+
# Headers like `Content-Type: application/json` come into rack like
|
89
|
+
# `"HTTP_CONTENT_TYPE" => "application/json"`.
|
90
|
+
def normalize_header_name(header)
|
91
|
+
header.delete_prefix("HTTP_").split("_").map(&:capitalize).join("-")
|
92
|
+
end
|
93
|
+
|
94
|
+
# These special headers are explicitly _not_ prefixed with HTTP_ in the Rack
|
95
|
+
# env so we need to add them in manually
|
96
|
+
def unprefixed_headers
|
97
|
+
{"Content-Type" => @request.content_type,
|
98
|
+
"Content-Length" => @request.content_length}.compact
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require "rack"
|
2
|
+
require "rack/response"
|
3
|
+
require_relative "content_type_helper"
|
4
|
+
|
5
|
+
module Readme
|
6
|
+
class HttpResponse < SimpleDelegator
|
7
|
+
include ContentTypeHelper
|
8
|
+
|
9
|
+
def self.from_parts(status, headers, body)
|
10
|
+
new(Rack::Response.new(body, status, headers))
|
11
|
+
end
|
12
|
+
|
13
|
+
def body
|
14
|
+
if raw_body.respond_to?(:rewind)
|
15
|
+
raw_body.rewind
|
16
|
+
content = raw_body.each.reduce("", :+)
|
17
|
+
raw_body.rewind
|
18
|
+
|
19
|
+
content
|
20
|
+
else
|
21
|
+
raw_body.each.reduce("", :+)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def content_length
|
26
|
+
if empty_body_status?
|
27
|
+
0
|
28
|
+
elsif !headers["Content-Length"]
|
29
|
+
body.bytesize
|
30
|
+
else
|
31
|
+
headers["Content-Length"].to_i
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
def raw_body
|
38
|
+
__getobj__.body
|
39
|
+
end
|
40
|
+
|
41
|
+
def empty_body_status?
|
42
|
+
Rack::Utils::STATUS_WITH_NO_ENTITY_BODY.include?(status.to_i)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
data/lib/readme/metrics.rb
CHANGED
@@ -4,8 +4,8 @@ require "readme/filter"
|
|
4
4
|
require "readme/payload"
|
5
5
|
require "readme/request_queue"
|
6
6
|
require "readme/errors"
|
7
|
-
require "http_request"
|
8
|
-
require "http_response"
|
7
|
+
require "readme/http_request"
|
8
|
+
require "readme/http_response"
|
9
9
|
require "httparty"
|
10
10
|
require "logger"
|
11
11
|
|
@@ -14,7 +14,8 @@ module Readme
|
|
14
14
|
SDK_NAME = "Readme.io Ruby SDK"
|
15
15
|
DEFAULT_BUFFER_LENGTH = 10
|
16
16
|
ENDPOINT = "https://metrics.readme.io/v1/request"
|
17
|
-
USER_INFO_KEYS = [:
|
17
|
+
USER_INFO_KEYS = [:api_key, :label, :email]
|
18
|
+
USER_INFO_KEYS_DEPRECATED = [:id, :label, :email]
|
18
19
|
|
19
20
|
def self.logger
|
20
21
|
@@logger
|
@@ -65,7 +66,7 @@ module Readme
|
|
65
66
|
har = Har::Serializer.new(request, response, start_time, end_time, @filter)
|
66
67
|
user_info = @get_user_info.call(env)
|
67
68
|
|
68
|
-
if
|
69
|
+
if !user_info_valid?(user_info)
|
69
70
|
Readme::Metrics.logger.warn Errors.bad_block_message(user_info)
|
70
71
|
elsif request.options?
|
71
72
|
Readme::Metrics.logger.info "OPTIONS request omitted from ReadMe API logging"
|
@@ -132,10 +133,12 @@ module Readme
|
|
132
133
|
arg == true || arg == false
|
133
134
|
end
|
134
135
|
|
135
|
-
def
|
136
|
-
user_info.
|
137
|
-
|
138
|
-
|
136
|
+
def user_info_valid?(user_info)
|
137
|
+
sorted_user_info_keys = user_info.keys.sort
|
138
|
+
!user_info.nil? &&
|
139
|
+
!user_info.values.any?(&:nil?) &&
|
140
|
+
(sorted_user_info_keys === USER_INFO_KEYS.sort ||
|
141
|
+
sorted_user_info_keys === USER_INFO_KEYS_DEPRECATED.sort)
|
139
142
|
end
|
140
143
|
end
|
141
144
|
end
|
data/lib/readme/payload.rb
CHANGED
data/readme-metrics.gemspec
CHANGED
@@ -13,8 +13,8 @@ Gem::Specification.new do |spec|
|
|
13
13
|
spec.required_ruby_version = Gem::Requirement.new(">= 2.7.0")
|
14
14
|
|
15
15
|
spec.metadata["homepage_uri"] = spec.homepage
|
16
|
-
spec.metadata["source_code_uri"] = "https://github.com/readmeio/metrics-sdks/blob/
|
17
|
-
spec.metadata["changelog_uri"] = "https://github.com/readmeio/metrics-sdks/blob/
|
16
|
+
spec.metadata["source_code_uri"] = "https://github.com/readmeio/metrics-sdks/blob/main/packages/ruby"
|
17
|
+
spec.metadata["changelog_uri"] = "https://github.com/readmeio/metrics-sdks/blob/main/packages/ruby/CHANGELOG.md"
|
18
18
|
|
19
19
|
# Specify which files should be added to the gem when it is released.
|
20
20
|
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: readme-metrics
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- ReadMe
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2021-06-29 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: httparty
|
@@ -40,15 +40,15 @@ files:
|
|
40
40
|
- Rakefile
|
41
41
|
- bin/console
|
42
42
|
- bin/setup
|
43
|
-
- lib/content_type_helper.rb
|
44
|
-
- lib/http_request.rb
|
45
|
-
- lib/http_response.rb
|
43
|
+
- lib/readme/content_type_helper.rb
|
46
44
|
- lib/readme/errors.rb
|
47
45
|
- lib/readme/filter.rb
|
48
46
|
- lib/readme/har/collection.rb
|
49
47
|
- lib/readme/har/request_serializer.rb
|
50
48
|
- lib/readme/har/response_serializer.rb
|
51
49
|
- lib/readme/har/serializer.rb
|
50
|
+
- lib/readme/http_request.rb
|
51
|
+
- lib/readme/http_response.rb
|
52
52
|
- lib/readme/metrics.rb
|
53
53
|
- lib/readme/metrics/version.rb
|
54
54
|
- lib/readme/payload.rb
|
@@ -59,8 +59,8 @@ licenses:
|
|
59
59
|
- ISC
|
60
60
|
metadata:
|
61
61
|
homepage_uri: https://docs.readme.com/metrics/docs/getting-started-with-api-metrics
|
62
|
-
source_code_uri: https://github.com/readmeio/metrics-sdks/blob/
|
63
|
-
changelog_uri: https://github.com/readmeio/metrics-sdks/blob/
|
62
|
+
source_code_uri: https://github.com/readmeio/metrics-sdks/blob/main/packages/ruby
|
63
|
+
changelog_uri: https://github.com/readmeio/metrics-sdks/blob/main/packages/ruby/CHANGELOG.md
|
64
64
|
post_install_message:
|
65
65
|
rdoc_options: []
|
66
66
|
require_paths:
|
@@ -76,7 +76,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
76
76
|
- !ruby/object:Gem::Version
|
77
77
|
version: '0'
|
78
78
|
requirements: []
|
79
|
-
rubygems_version: 3.1.
|
79
|
+
rubygems_version: 3.1.4
|
80
80
|
signing_key:
|
81
81
|
specification_version: 4
|
82
82
|
summary: SDK for Readme's metrics API
|
data/lib/content_type_helper.rb
DELETED
@@ -1,15 +0,0 @@
|
|
1
|
-
module ContentTypeHelper
|
2
|
-
# Assumes the includer has a `content_type` method defined.
|
3
|
-
|
4
|
-
JSON_MIME_TYPES = [
|
5
|
-
"application/json",
|
6
|
-
"application/x-json",
|
7
|
-
"text/json",
|
8
|
-
"text/x-json",
|
9
|
-
"+json"
|
10
|
-
]
|
11
|
-
|
12
|
-
def json?
|
13
|
-
JSON_MIME_TYPES.any? { |mime_type| content_type.include?(mime_type) }
|
14
|
-
end
|
15
|
-
end
|
data/lib/http_request.rb
DELETED
@@ -1,99 +0,0 @@
|
|
1
|
-
require "rack"
|
2
|
-
require "rack/request"
|
3
|
-
require "content_type_helper"
|
4
|
-
|
5
|
-
class HttpRequest
|
6
|
-
include ContentTypeHelper
|
7
|
-
|
8
|
-
HTTP_NON_HEADERS = [
|
9
|
-
Rack::HTTP_COOKIE,
|
10
|
-
Rack::HTTP_VERSION,
|
11
|
-
Rack::HTTP_HOST,
|
12
|
-
Rack::HTTP_PORT
|
13
|
-
]
|
14
|
-
|
15
|
-
def initialize(env)
|
16
|
-
@request = Rack::Request.new(env)
|
17
|
-
end
|
18
|
-
|
19
|
-
def url
|
20
|
-
@request.url
|
21
|
-
end
|
22
|
-
|
23
|
-
def query_params
|
24
|
-
@request.GET
|
25
|
-
end
|
26
|
-
|
27
|
-
def cookies
|
28
|
-
@request.cookies
|
29
|
-
end
|
30
|
-
|
31
|
-
def http_version
|
32
|
-
@request.get_header(Rack::HTTP_VERSION)
|
33
|
-
end
|
34
|
-
|
35
|
-
def request_method
|
36
|
-
@request.request_method
|
37
|
-
end
|
38
|
-
|
39
|
-
def content_type
|
40
|
-
@request.content_type
|
41
|
-
end
|
42
|
-
|
43
|
-
def form_data?
|
44
|
-
@request.form_data?
|
45
|
-
end
|
46
|
-
|
47
|
-
def content_length
|
48
|
-
@request.content_length.to_i
|
49
|
-
end
|
50
|
-
|
51
|
-
def options?
|
52
|
-
@request.request_method == "OPTIONS"
|
53
|
-
end
|
54
|
-
|
55
|
-
def headers
|
56
|
-
@request
|
57
|
-
.each_header
|
58
|
-
.select { |key, _| http_header?(key) }
|
59
|
-
.to_h
|
60
|
-
.transform_keys { |header| normalize_header_name(header) }
|
61
|
-
.merge unprefixed_headers
|
62
|
-
end
|
63
|
-
|
64
|
-
def body
|
65
|
-
@request.body.rewind
|
66
|
-
content = @request.body.read
|
67
|
-
@request.body.rewind
|
68
|
-
|
69
|
-
content
|
70
|
-
end
|
71
|
-
|
72
|
-
def parsed_form_data
|
73
|
-
@request.POST
|
74
|
-
end
|
75
|
-
|
76
|
-
private
|
77
|
-
|
78
|
-
# "headers" in Rack::Request just means any key in the env. The HTTP headers
|
79
|
-
# are all the headers prefixed with `HTTP_` as per the spec:
|
80
|
-
# https://github.com/rack/rack/blob/master/SPEC.rdoc#the-environment-
|
81
|
-
# Other "headers" like version and host are prefixed with `HTTP_` by Rack but
|
82
|
-
# don't seem to be considered legit HTTP headers.
|
83
|
-
def http_header?(name)
|
84
|
-
name.start_with?("HTTP") && !HTTP_NON_HEADERS.include?(name)
|
85
|
-
end
|
86
|
-
|
87
|
-
# Headers like `Content-Type: application/json` come into rack like
|
88
|
-
# `"HTTP_CONTENT_TYPE" => "application/json"`.
|
89
|
-
def normalize_header_name(header)
|
90
|
-
header.delete_prefix("HTTP_").split("_").map(&:capitalize).join("-")
|
91
|
-
end
|
92
|
-
|
93
|
-
# These special headers are explicitly _not_ prefixed with HTTP_ in the Rack
|
94
|
-
# env so we need to add them in manually
|
95
|
-
def unprefixed_headers
|
96
|
-
{"Content-Type" => @request.content_type,
|
97
|
-
"Content-Length" => @request.content_length}.compact
|
98
|
-
end
|
99
|
-
end
|
data/lib/http_response.rb
DELETED
@@ -1,43 +0,0 @@
|
|
1
|
-
require "rack"
|
2
|
-
require "rack/response"
|
3
|
-
require "content_type_helper"
|
4
|
-
|
5
|
-
class HttpResponse < SimpleDelegator
|
6
|
-
include ContentTypeHelper
|
7
|
-
|
8
|
-
def self.from_parts(status, headers, body)
|
9
|
-
new(Rack::Response.new(body, status, headers))
|
10
|
-
end
|
11
|
-
|
12
|
-
def body
|
13
|
-
if raw_body.respond_to?(:rewind)
|
14
|
-
raw_body.rewind
|
15
|
-
content = raw_body.each.reduce("", :+)
|
16
|
-
raw_body.rewind
|
17
|
-
|
18
|
-
content
|
19
|
-
else
|
20
|
-
raw_body.each.reduce("", :+)
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
|
-
def content_length
|
25
|
-
if empty_body_status?
|
26
|
-
0
|
27
|
-
elsif !headers["Content-Length"]
|
28
|
-
body.bytesize
|
29
|
-
else
|
30
|
-
headers["Content-Length"].to_i
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
|
-
private
|
35
|
-
|
36
|
-
def raw_body
|
37
|
-
__getobj__.body
|
38
|
-
end
|
39
|
-
|
40
|
-
def empty_body_status?
|
41
|
-
Rack::Utils::STATUS_WITH_NO_ENTITY_BODY.include?(status.to_i)
|
42
|
-
end
|
43
|
-
end
|