Skip to content

Commit 1a75b28

Browse files
authored
Remove Grape::Http::Headers (#2554)
* Move HTTP_HEADERS in Grape::Request and renew known headers Use plain HTTP_ or real header name instead of referencing to Http::Headers:: Remove Grape::Util::Lazy::Object * Add few headers * Add other headers * Add other known headers and sort * CHANGELOG.md entry * Fix CHANGELOG.md Add UPGRADING notes Add X-Access-Token in list of headers
1 parent c42b66f commit 1a75b28

28 files changed

+307
-261
lines changed

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
* [#2540](https://github.com/ruby-grape/grape/pull/2540): Introduce Params builder with symbolized short name - [@ericproulx](https://github.com/ericproulx).
1010
* [#2550](https://github.com/ruby-grape/grape/pull/2550): Drop ActiveSupport 6.0 - [@ericproulx](https://github.com/ericproulx).
1111
* [#2549](https://github.com/ruby-grape/grape/pull/2549): Delegate cookies management to `Grape::Request` - [@ericproulx](https://github.com/ericproulx).
12+
* [#2554](https://github.com/ruby-grape/grape/pull/2554): Remove `Grape::Http::Headers` and `Grape::Util::Lazy::Object` - [@ericproulx](https://github.com/ericproulx).
1213
* Your contribution here.
1314

1415
#### Fixes

UPGRADING.md

+12-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,18 @@
11
Upgrading Grape
22
===============
33

4+
### Upgrading to >= 2.4.0
5+
6+
#### Grape::Http::Headers, Grape::Util::Lazy::Object
7+
8+
Both have been removed. See [2554](https://github.com/ruby-grape/grape/pull/2554).
9+
Here are the notable changes:
10+
11+
- Constants like `HTTP_ACCEPT` have been replaced by their literal value.
12+
- `SUPPORTED_METHODS` has been moved to `Grape` module.
13+
- `HTTP_HEADERS` has been moved to `Grape::Request` and renamed `KNOWN_HEADERS`. The last has been refreshed with new headers, and it's not lazy anymore.
14+
- `SUPPORTED_METHODS_WITHOUT_OPTIONS` and `find_supported_method` have been removed.
15+
416
### Grape::Middleware::Base
517

618
- Constant `TEXT_HTML` has been removed in favor of using literal string 'text/html'.
@@ -30,8 +42,6 @@ For the non provided case, 1.0 was automatically assigned and in a case of multi
3042
Excluding the [header versioning strategy](https://github.com/ruby-grape/grape?tab=readme-ov-file#header), whenever a media type with the [vendor tree](https://datatracker.ietf.org/doc/html/rfc6838#section-3.2) leading facet `vnd.` like `application/vnd.api+json` was provided, Grape would also consider its closest generic when negotiating. In that case, `application/json` was added to the negotiation. Now, it will just consider the provided media types without considering any closest generics, and you'll need to [register](https://github.com/ruby-grape/grape?tab=readme-ov-file#api-formats) it.
3143
You can find the official vendor tree registrations on [IANA](https://www.iana.org/assignments/media-types/media-types.xhtml)
3244

33-
### Upgrading to >= 2.4.0
34-
3545
#### Custom Validators
3646

3747
If you now receive an error of `'Grape::Validations.require_validator': unknown validator: your_custom_validation (Grape::Exceptions::UnknownValidator)` after upgrading to 2.4.0 then you will need to ensure that you require the `your_custom_validation` file before your Grape API code is loaded.

lib/grape.rb

+10
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,16 @@
5959
module Grape
6060
include ActiveSupport::Configurable
6161

62+
HTTP_SUPPORTED_METHODS = [
63+
Rack::GET,
64+
Rack::POST,
65+
Rack::PUT,
66+
Rack::PATCH,
67+
Rack::DELETE,
68+
Rack::HEAD,
69+
Rack::OPTIONS
70+
].freeze
71+
6272
def self.deprecator
6373
@deprecator ||= ActiveSupport::Deprecation.new('2.0', 'Grape')
6474
end

lib/grape/api/instance.rb

+1-1
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,7 @@ def call(env)
164164
status, headers, response = @router.call(env)
165165
unless cascade?
166166
headers = Grape::Util::Header.new.merge(headers)
167-
headers.delete(Grape::Http::Headers::X_CASCADE)
167+
headers.delete('X-Cascade')
168168
end
169169

170170
[status, headers, response]

lib/grape/dsl/headers.rb

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ module Headers
1010
# 4. Delete a specifc header key-value pair
1111
def header(key = nil, val = nil)
1212
if key
13-
val ? header[key.to_s] = val : header.delete(key.to_s)
13+
val ? header[key] = val : header.delete(key)
1414
else
1515
@header ||= Grape::Util::Header.new
1616
end

lib/grape/dsl/inside_route.rb

+3-3
Original file line numberDiff line numberDiff line change
@@ -213,7 +213,7 @@ def redirect(url, permanent: false, body: nil)
213213
status 302
214214
body_message ||= "This resource has been moved temporarily to #{url}."
215215
end
216-
header Grape::Http::Headers::LOCATION, url
216+
header 'Location', url
217217
content_type 'text/plain'
218218
body body_message
219219
end
@@ -330,7 +330,7 @@ def stream(value = nil)
330330
return if value.nil? && @stream.nil?
331331

332332
header Rack::CONTENT_LENGTH, nil
333-
header Grape::Http::Headers::TRANSFER_ENCODING, nil
333+
header 'Transfer-Encoding', nil
334334
header Rack::CACHE_CONTROL, 'no-cache' # Skips ETag generation (reading the response up front)
335335
if value.is_a?(String)
336336
file_body = Grape::ServeStream::FileBody.new(value)
@@ -439,7 +439,7 @@ def entity_representation_for(entity_class, object, options)
439439
end
440440

441441
def http_version
442-
env.fetch(Grape::Http::Headers::HTTP_VERSION) { env[Rack::SERVER_PROTOCOL] }
442+
env.fetch('HTTP_VERSION') { env[Rack::SERVER_PROTOCOL] }
443443
end
444444

445445
def api_format(format)

lib/grape/dsl/routing.rb

+1-1
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,7 @@ def route(methods, paths = ['/'], route_options = {}, &block)
158158
reset_validations!
159159
end
160160

161-
Grape::Http::Headers::SUPPORTED_METHODS.each do |supported_method|
161+
Grape::HTTP_SUPPORTED_METHODS.each do |supported_method|
162162
define_method supported_method.downcase do |*args, &block|
163163
options = args.extract_options!
164164
paths = args.first || ['/']

lib/grape/endpoint.rb

+1-1
Original file line numberDiff line numberDiff line change
@@ -257,7 +257,7 @@ def run
257257
header['Allow'] = env[Grape::Env::GRAPE_ALLOWED_METHODS].join(', ')
258258
raise Grape::Exceptions::MethodNotAllowed.new(header) unless options?
259259

260-
header Grape::Http::Headers::ALLOW, header['Allow']
260+
header 'Allow', header['Allow']
261261
response_object = ''
262262
status 204
263263
else

lib/grape/http/headers.rb

-56
This file was deleted.

lib/grape/middleware/formatter.rb

+2-2
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ def read_body_input?
119119
(rack_request.post? || rack_request.put? || rack_request.patch? || rack_request.delete?) &&
120120
!(rack_request.form_data? && rack_request.content_type) &&
121121
!rack_request.parseable_data? &&
122-
(rack_request.content_length.to_i.positive? || rack_request.env[Grape::Http::Headers::HTTP_TRANSFER_ENCODING] == 'chunked')
122+
(rack_request.content_length.to_i.positive? || rack_request.env['HTTP_TRANSFER_ENCODING'] == 'chunked')
123123
end
124124

125125
def negotiate_content_type
@@ -141,7 +141,7 @@ def format_from_extension
141141
end
142142

143143
def format_from_header
144-
accept_header = env[Grape::Http::Headers::HTTP_ACCEPT].try(:scrub)
144+
accept_header = env['HTTP_ACCEPT'].try(:scrub)
145145
return if accept_header.blank?
146146

147147
media_type = Rack::Utils.best_q_match(accept_header, mime_types.keys)

lib/grape/middleware/versioner/accept_version_header.rb

+1-3
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,7 @@ module Versioner
1818
# route.
1919
class AcceptVersionHeader < Base
2020
def before
21-
potential_version = env[Grape::Http::Headers::HTTP_ACCEPT_VERSION]
22-
potential_version = potential_version.scrub unless potential_version.nil?
23-
21+
potential_version = env['HTTP_ACCEPT_VERSION'].try(:scrub)
2422
not_acceptable!('Accept-Version header must be set.') if strict? && potential_version.blank?
2523

2624
return if potential_version.blank?

lib/grape/middleware/versioner/base.rb

+2-2
Original file line numberDiff line numberDiff line change
@@ -66,15 +66,15 @@ def vendor
6666
end
6767

6868
def error_headers
69-
cascade? ? { Grape::Http::Headers::X_CASCADE => 'pass' } : {}
69+
cascade? ? { 'X-Cascade' => 'pass' } : {}
7070
end
7171

7272
def potential_version_match?(potential_version)
7373
versions.blank? || versions.any? { |v| v.to_s == potential_version }
7474
end
7575

7676
def version_not_found!
77-
throw :error, status: 404, message: '404 API Version Not Found', headers: { Grape::Http::Headers::X_CASCADE => 'pass' }
77+
throw :error, status: 404, message: '404 API Version Not Found', headers: { 'X-Cascade' => 'pass' }
7878
end
7979
end
8080
end

lib/grape/middleware/versioner/header.rb

+1-1
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ def match_best_quality_media_type!
4949
end
5050

5151
def accept_header
52-
env[Grape::Http::Headers::HTTP_ACCEPT]
52+
env['HTTP_ACCEPT']
5353
end
5454

5555
def strict_header_checks!

lib/grape/request.rb

+135-7
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,139 @@
33
module Grape
44
class Request < Rack::Request
55
DEFAULT_PARAMS_BUILDER = :hash_with_indifferent_access
6-
HTTP_PREFIX = 'HTTP_'
6+
# Based on rack 3 KNOWN_HEADERS
7+
# https://github.com/rack/rack/blob/4f15e7b814922af79605be4b02c5b7c3044ba206/lib/rack/headers.rb#L10
8+
9+
KNOWN_HEADERS = %w[
10+
Accept
11+
Accept-CH
12+
Accept-Encoding
13+
Accept-Language
14+
Accept-Patch
15+
Accept-Ranges
16+
Accept-Version
17+
Access-Control-Allow-Credentials
18+
Access-Control-Allow-Headers
19+
Access-Control-Allow-Methods
20+
Access-Control-Allow-Origin
21+
Access-Control-Expose-Headers
22+
Access-Control-Max-Age
23+
Age
24+
Allow
25+
Alt-Svc
26+
Authorization
27+
Cache-Control
28+
Client-Ip
29+
Connection
30+
Content-Disposition
31+
Content-Encoding
32+
Content-Language
33+
Content-Length
34+
Content-Location
35+
Content-MD5
36+
Content-Range
37+
Content-Security-Policy
38+
Content-Security-Policy-Report-Only
39+
Content-Type
40+
Cookie
41+
Date
42+
Delta-Base
43+
Dnt
44+
ETag
45+
Expect-CT
46+
Expires
47+
Feature-Policy
48+
Forwarded
49+
Host
50+
If-Modified-Since
51+
If-None-Match
52+
IM
53+
Last-Modified
54+
Link
55+
Location
56+
NEL
57+
P3P
58+
Permissions-Policy
59+
Pragma
60+
Preference-Applied
61+
Proxy-Authenticate
62+
Public-Key-Pins
63+
Range
64+
Referer
65+
Referrer-Policy
66+
Refresh
67+
Report-To
68+
Retry-After
69+
Sec-Fetch-Dest
70+
Sec-Fetch-Mode
71+
Sec-Fetch-Site
72+
Sec-Fetch-User
73+
Server
74+
Set-Cookie
75+
Status
76+
Strict-Transport-Security
77+
Timing-Allow-Origin
78+
Tk
79+
Trailer
80+
Transfer-Encoding
81+
Upgrade
82+
Upgrade-Insecure-Requests
83+
User-Agent
84+
Vary
85+
Version
86+
Via
87+
Warning
88+
WWW-Authenticate
89+
X-Accel-Buffering
90+
X-Accel-Charset
91+
X-Accel-Expires
92+
X-Accel-Limit-Rate
93+
X-Accel-Mapping
94+
X-Accel-Redirect
95+
X-Access-Token
96+
X-Auth-Request-Access-Token
97+
X-Auth-Request-Email
98+
X-Auth-Request-Groups
99+
X-Auth-Request-Preferred-Username
100+
X-Auth-Request-Redirect
101+
X-Auth-Request-Token
102+
X-Auth-Request-User
103+
X-Cascade
104+
X-Client-Ip
105+
X-Content-Duration
106+
X-Content-Security-Policy
107+
X-Content-Type-Options
108+
X-Correlation-Id
109+
X-Download-Options
110+
X-Forwarded-Access-Token
111+
X-Forwarded-Email
112+
X-Forwarded-For
113+
X-Forwarded-Groups
114+
X-Forwarded-Host
115+
X-Forwarded-Port
116+
X-Forwarded-Preferred-Username
117+
X-Forwarded-Proto
118+
X-Forwarded-Scheme
119+
X-Forwarded-Ssl
120+
X-Forwarded-Uri
121+
X-Forwarded-User
122+
X-Frame-Options
123+
X-HTTP-Method-Override
124+
X-Permitted-Cross-Domain-Policies
125+
X-Powered-By
126+
X-Real-IP
127+
X-Redirect-By
128+
X-Request-Id
129+
X-Requested-With
130+
X-Runtime
131+
X-Sendfile
132+
X-Sendfile-Type
133+
X-UA-Compatible
134+
X-WebKit-CS
135+
X-XSS-Protection
136+
].each_with_object({}) do |header, response|
137+
response["HTTP_#{header.upcase.tr('-', '_')}"] = header
138+
end.freeze
7139

8140
alias rack_params params
9141
alias rack_cookies cookies
@@ -49,15 +181,11 @@ def make_params
49181

50182
def build_headers
51183
each_header.with_object(Grape::Util::Header.new) do |(k, v), headers|
52-
next unless k.start_with? HTTP_PREFIX
184+
next unless k.start_with? 'HTTP_'
53185

54-
transformed_header = Grape::Http::Headers::HTTP_HEADERS[k] || transform_header(k)
186+
transformed_header = KNOWN_HEADERS.fetch(k) { -k[5..].tr('_', '-').downcase }
55187
headers[transformed_header] = v
56188
end
57189
end
58-
59-
def transform_header(header)
60-
-header[5..].tr('_', '-').downcase
61-
end
62190
end
63191
end

0 commit comments

Comments
 (0)