diff --git a/CHANGELOG.md b/CHANGELOG.md index 478a6b4d5..e6b495d2f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ * [#2540](https://github.com/ruby-grape/grape/pull/2540): Introduce Params builder with symbolized short name - [@ericproulx](https://github.com/ericproulx). * [#2550](https://github.com/ruby-grape/grape/pull/2550): Drop ActiveSupport 6.0 - [@ericproulx](https://github.com/ericproulx). * [#2549](https://github.com/ruby-grape/grape/pull/2549): Delegate cookies management to `Grape::Request` - [@ericproulx](https://github.com/ericproulx). +* [#2554](https://github.com/ruby-grape/grape/pull/2554): Remove `Grape::Http::Headers` and `Grape::Util::Lazy::Object` - [@ericproulx](https://github.com/ericproulx). * Your contribution here. #### Fixes diff --git a/UPGRADING.md b/UPGRADING.md index 9e7b8ade2..2ace6622d 100644 --- a/UPGRADING.md +++ b/UPGRADING.md @@ -1,6 +1,18 @@ Upgrading Grape =============== +### Upgrading to >= 2.4.0 + +#### Grape::Http::Headers, Grape::Util::Lazy::Object + +Both have been removed. See [2554](https://github.com/ruby-grape/grape/pull/2554). +Here are the notable changes: + +- Constants like `HTTP_ACCEPT` have been replaced by their literal value. +- `SUPPORTED_METHODS` has been moved to `Grape` module. +- `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. +- `SUPPORTED_METHODS_WITHOUT_OPTIONS` and `find_supported_method` have been removed. + ### Grape::Middleware::Base - 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 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. You can find the official vendor tree registrations on [IANA](https://www.iana.org/assignments/media-types/media-types.xhtml) -### Upgrading to >= 2.4.0 - #### Custom Validators 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. diff --git a/lib/grape.rb b/lib/grape.rb index 91d3f3f8a..a1e6f511c 100644 --- a/lib/grape.rb +++ b/lib/grape.rb @@ -59,6 +59,16 @@ module Grape include ActiveSupport::Configurable + HTTP_SUPPORTED_METHODS = [ + Rack::GET, + Rack::POST, + Rack::PUT, + Rack::PATCH, + Rack::DELETE, + Rack::HEAD, + Rack::OPTIONS + ].freeze + def self.deprecator @deprecator ||= ActiveSupport::Deprecation.new('2.0', 'Grape') end diff --git a/lib/grape/api/instance.rb b/lib/grape/api/instance.rb index facd0f9f9..aa24263a6 100644 --- a/lib/grape/api/instance.rb +++ b/lib/grape/api/instance.rb @@ -164,7 +164,7 @@ def call(env) status, headers, response = @router.call(env) unless cascade? headers = Grape::Util::Header.new.merge(headers) - headers.delete(Grape::Http::Headers::X_CASCADE) + headers.delete('X-Cascade') end [status, headers, response] diff --git a/lib/grape/dsl/headers.rb b/lib/grape/dsl/headers.rb index a02bdd588..4c193364f 100644 --- a/lib/grape/dsl/headers.rb +++ b/lib/grape/dsl/headers.rb @@ -10,7 +10,7 @@ module Headers # 4. Delete a specifc header key-value pair def header(key = nil, val = nil) if key - val ? header[key.to_s] = val : header.delete(key.to_s) + val ? header[key] = val : header.delete(key) else @header ||= Grape::Util::Header.new end diff --git a/lib/grape/dsl/inside_route.rb b/lib/grape/dsl/inside_route.rb index c5861cc92..2d7568afa 100644 --- a/lib/grape/dsl/inside_route.rb +++ b/lib/grape/dsl/inside_route.rb @@ -213,7 +213,7 @@ def redirect(url, permanent: false, body: nil) status 302 body_message ||= "This resource has been moved temporarily to #{url}." end - header Grape::Http::Headers::LOCATION, url + header 'Location', url content_type 'text/plain' body body_message end @@ -330,7 +330,7 @@ def stream(value = nil) return if value.nil? && @stream.nil? header Rack::CONTENT_LENGTH, nil - header Grape::Http::Headers::TRANSFER_ENCODING, nil + header 'Transfer-Encoding', nil header Rack::CACHE_CONTROL, 'no-cache' # Skips ETag generation (reading the response up front) if value.is_a?(String) file_body = Grape::ServeStream::FileBody.new(value) @@ -439,7 +439,7 @@ def entity_representation_for(entity_class, object, options) end def http_version - env.fetch(Grape::Http::Headers::HTTP_VERSION) { env[Rack::SERVER_PROTOCOL] } + env.fetch('HTTP_VERSION') { env[Rack::SERVER_PROTOCOL] } end def api_format(format) diff --git a/lib/grape/dsl/routing.rb b/lib/grape/dsl/routing.rb index c2738f933..8c32db364 100644 --- a/lib/grape/dsl/routing.rb +++ b/lib/grape/dsl/routing.rb @@ -158,7 +158,7 @@ def route(methods, paths = ['/'], route_options = {}, &block) reset_validations! end - Grape::Http::Headers::SUPPORTED_METHODS.each do |supported_method| + Grape::HTTP_SUPPORTED_METHODS.each do |supported_method| define_method supported_method.downcase do |*args, &block| options = args.extract_options! paths = args.first || ['/'] diff --git a/lib/grape/endpoint.rb b/lib/grape/endpoint.rb index a97181fe3..2e5136fda 100644 --- a/lib/grape/endpoint.rb +++ b/lib/grape/endpoint.rb @@ -257,7 +257,7 @@ def run header['Allow'] = env[Grape::Env::GRAPE_ALLOWED_METHODS].join(', ') raise Grape::Exceptions::MethodNotAllowed.new(header) unless options? - header Grape::Http::Headers::ALLOW, header['Allow'] + header 'Allow', header['Allow'] response_object = '' status 204 else diff --git a/lib/grape/http/headers.rb b/lib/grape/http/headers.rb deleted file mode 100644 index eb4d38915..000000000 --- a/lib/grape/http/headers.rb +++ /dev/null @@ -1,56 +0,0 @@ -# frozen_string_literal: true - -module Grape - module Http - module Headers - HTTP_ACCEPT_VERSION = 'HTTP_ACCEPT_VERSION' - HTTP_ACCEPT = 'HTTP_ACCEPT' - HTTP_TRANSFER_ENCODING = 'HTTP_TRANSFER_ENCODING' - HTTP_VERSION = 'HTTP_VERSION' - - ALLOW = 'Allow' - LOCATION = 'Location' - X_CASCADE = 'X-Cascade' - TRANSFER_ENCODING = 'Transfer-Encoding' - - SUPPORTED_METHODS = [ - Rack::GET, - Rack::POST, - Rack::PUT, - Rack::PATCH, - Rack::DELETE, - Rack::HEAD, - Rack::OPTIONS - ].freeze - - SUPPORTED_METHODS_WITHOUT_OPTIONS = (SUPPORTED_METHODS - [Rack::OPTIONS]).freeze - - HTTP_HEADERS = Grape::Util::Lazy::Object.new do - common_http_headers = %w[ - Version - Host - Connection - Cache-Control - Dnt - Upgrade-Insecure-Requests - User-Agent - Sec-Fetch-Dest - Accept - Sec-Fetch-Site - Sec-Fetch-Mode - Sec-Fetch-User - Accept-Encoding - Accept-Language - Cookie - ].freeze - common_http_headers.each_with_object({}) do |header, response| - response["HTTP_#{header.upcase.tr('-', '_')}"] = header - end.freeze - end - - def self.find_supported_method(route_method) - Grape::Http::Headers::SUPPORTED_METHODS.detect { |supported_method| supported_method.casecmp(route_method).zero? } - end - end - end -end diff --git a/lib/grape/middleware/formatter.rb b/lib/grape/middleware/formatter.rb index 73b12b454..359792a40 100644 --- a/lib/grape/middleware/formatter.rb +++ b/lib/grape/middleware/formatter.rb @@ -119,7 +119,7 @@ def read_body_input? (rack_request.post? || rack_request.put? || rack_request.patch? || rack_request.delete?) && !(rack_request.form_data? && rack_request.content_type) && !rack_request.parseable_data? && - (rack_request.content_length.to_i.positive? || rack_request.env[Grape::Http::Headers::HTTP_TRANSFER_ENCODING] == 'chunked') + (rack_request.content_length.to_i.positive? || rack_request.env['HTTP_TRANSFER_ENCODING'] == 'chunked') end def negotiate_content_type @@ -141,7 +141,7 @@ def format_from_extension end def format_from_header - accept_header = env[Grape::Http::Headers::HTTP_ACCEPT].try(:scrub) + accept_header = env['HTTP_ACCEPT'].try(:scrub) return if accept_header.blank? media_type = Rack::Utils.best_q_match(accept_header, mime_types.keys) diff --git a/lib/grape/middleware/versioner/accept_version_header.rb b/lib/grape/middleware/versioner/accept_version_header.rb index aa7a8b353..1d24388f1 100644 --- a/lib/grape/middleware/versioner/accept_version_header.rb +++ b/lib/grape/middleware/versioner/accept_version_header.rb @@ -18,9 +18,7 @@ module Versioner # route. class AcceptVersionHeader < Base def before - potential_version = env[Grape::Http::Headers::HTTP_ACCEPT_VERSION] - potential_version = potential_version.scrub unless potential_version.nil? - + potential_version = env['HTTP_ACCEPT_VERSION'].try(:scrub) not_acceptable!('Accept-Version header must be set.') if strict? && potential_version.blank? return if potential_version.blank? diff --git a/lib/grape/middleware/versioner/base.rb b/lib/grape/middleware/versioner/base.rb index 68604f14e..4cd18a8c0 100644 --- a/lib/grape/middleware/versioner/base.rb +++ b/lib/grape/middleware/versioner/base.rb @@ -66,7 +66,7 @@ def vendor end def error_headers - cascade? ? { Grape::Http::Headers::X_CASCADE => 'pass' } : {} + cascade? ? { 'X-Cascade' => 'pass' } : {} end def potential_version_match?(potential_version) @@ -74,7 +74,7 @@ def potential_version_match?(potential_version) end def version_not_found! - throw :error, status: 404, message: '404 API Version Not Found', headers: { Grape::Http::Headers::X_CASCADE => 'pass' } + throw :error, status: 404, message: '404 API Version Not Found', headers: { 'X-Cascade' => 'pass' } end end end diff --git a/lib/grape/middleware/versioner/header.rb b/lib/grape/middleware/versioner/header.rb index a34a80fc7..5470fe170 100644 --- a/lib/grape/middleware/versioner/header.rb +++ b/lib/grape/middleware/versioner/header.rb @@ -49,7 +49,7 @@ def match_best_quality_media_type! end def accept_header - env[Grape::Http::Headers::HTTP_ACCEPT] + env['HTTP_ACCEPT'] end def strict_header_checks! diff --git a/lib/grape/request.rb b/lib/grape/request.rb index 45ee801e7..06c389b75 100644 --- a/lib/grape/request.rb +++ b/lib/grape/request.rb @@ -3,7 +3,139 @@ module Grape class Request < Rack::Request DEFAULT_PARAMS_BUILDER = :hash_with_indifferent_access - HTTP_PREFIX = 'HTTP_' + # Based on rack 3 KNOWN_HEADERS + # https://github.com/rack/rack/blob/4f15e7b814922af79605be4b02c5b7c3044ba206/lib/rack/headers.rb#L10 + + KNOWN_HEADERS = %w[ + Accept + Accept-CH + Accept-Encoding + Accept-Language + Accept-Patch + Accept-Ranges + Accept-Version + Access-Control-Allow-Credentials + Access-Control-Allow-Headers + Access-Control-Allow-Methods + Access-Control-Allow-Origin + Access-Control-Expose-Headers + Access-Control-Max-Age + Age + Allow + Alt-Svc + Authorization + Cache-Control + Client-Ip + Connection + Content-Disposition + Content-Encoding + Content-Language + Content-Length + Content-Location + Content-MD5 + Content-Range + Content-Security-Policy + Content-Security-Policy-Report-Only + Content-Type + Cookie + Date + Delta-Base + Dnt + ETag + Expect-CT + Expires + Feature-Policy + Forwarded + Host + If-Modified-Since + If-None-Match + IM + Last-Modified + Link + Location + NEL + P3P + Permissions-Policy + Pragma + Preference-Applied + Proxy-Authenticate + Public-Key-Pins + Range + Referer + Referrer-Policy + Refresh + Report-To + Retry-After + Sec-Fetch-Dest + Sec-Fetch-Mode + Sec-Fetch-Site + Sec-Fetch-User + Server + Set-Cookie + Status + Strict-Transport-Security + Timing-Allow-Origin + Tk + Trailer + Transfer-Encoding + Upgrade + Upgrade-Insecure-Requests + User-Agent + Vary + Version + Via + Warning + WWW-Authenticate + X-Accel-Buffering + X-Accel-Charset + X-Accel-Expires + X-Accel-Limit-Rate + X-Accel-Mapping + X-Accel-Redirect + X-Access-Token + X-Auth-Request-Access-Token + X-Auth-Request-Email + X-Auth-Request-Groups + X-Auth-Request-Preferred-Username + X-Auth-Request-Redirect + X-Auth-Request-Token + X-Auth-Request-User + X-Cascade + X-Client-Ip + X-Content-Duration + X-Content-Security-Policy + X-Content-Type-Options + X-Correlation-Id + X-Download-Options + X-Forwarded-Access-Token + X-Forwarded-Email + X-Forwarded-For + X-Forwarded-Groups + X-Forwarded-Host + X-Forwarded-Port + X-Forwarded-Preferred-Username + X-Forwarded-Proto + X-Forwarded-Scheme + X-Forwarded-Ssl + X-Forwarded-Uri + X-Forwarded-User + X-Frame-Options + X-HTTP-Method-Override + X-Permitted-Cross-Domain-Policies + X-Powered-By + X-Real-IP + X-Redirect-By + X-Request-Id + X-Requested-With + X-Runtime + X-Sendfile + X-Sendfile-Type + X-UA-Compatible + X-WebKit-CS + X-XSS-Protection + ].each_with_object({}) do |header, response| + response["HTTP_#{header.upcase.tr('-', '_')}"] = header + end.freeze alias rack_params params alias rack_cookies cookies @@ -49,15 +181,11 @@ def make_params def build_headers each_header.with_object(Grape::Util::Header.new) do |(k, v), headers| - next unless k.start_with? HTTP_PREFIX + next unless k.start_with? 'HTTP_' - transformed_header = Grape::Http::Headers::HTTP_HEADERS[k] || transform_header(k) + transformed_header = KNOWN_HEADERS.fetch(k) { -k[5..].tr('_', '-').downcase } headers[transformed_header] = v end end - - def transform_header(header) - -header[5..].tr('_', '-').downcase - end end end diff --git a/lib/grape/router.rb b/lib/grape/router.rb index 99065b6e4..6a9e3f5df 100644 --- a/lib/grape/router.rb +++ b/lib/grape/router.rb @@ -42,7 +42,7 @@ def compile! @union = Regexp.union(@neutral_regexes) @neutral_regexes = nil - (Grape::Http::Headers::SUPPORTED_METHODS + ['*']).each do |method| + (Grape::HTTP_SUPPORTED_METHODS + ['*']).each do |method| next unless map.key?(method) routes = map[method] @@ -156,7 +156,7 @@ def with_optimization end def default_response - headers = Grape::Util::Header.new.merge(Grape::Http::Headers::X_CASCADE => 'pass') + headers = Grape::Util::Header.new.merge('X-Cascade' => 'pass') [404, headers, ['404 Not Found']] end @@ -180,7 +180,7 @@ def prepare_env_from_route(env, route) end def cascade?(response) - response && response[1][Grape::Http::Headers::X_CASCADE] == 'pass' + response && response[1]['X-Cascade'] == 'pass' end def string_for(input) diff --git a/lib/grape/router/route.rb b/lib/grape/router/route.rb index 48599610c..64105be9c 100644 --- a/lib/grape/router/route.rb +++ b/lib/grape/router/route.rb @@ -55,7 +55,7 @@ def params_without_input def upcase_method(method) method_s = method.to_s - Grape::Http::Headers::SUPPORTED_METHODS.detect { |m| m.casecmp(method_s).zero? } || method_s.upcase + Grape::HTTP_SUPPORTED_METHODS.detect { |m| m.casecmp(method_s).zero? } || method_s.upcase end end end diff --git a/lib/grape/util/lazy/object.rb b/lib/grape/util/lazy/object.rb deleted file mode 100644 index 6c10dadfc..000000000 --- a/lib/grape/util/lazy/object.rb +++ /dev/null @@ -1,45 +0,0 @@ -# frozen_string_literal: true - -# Based on https://github.com/HornsAndHooves/lazy_object - -module Grape - module Util - module Lazy - class Object < BasicObject - attr_reader :callable - - def initialize(&callable) - @callable = callable - end - - def __target_object__ - @__target_object__ ||= callable.call - end - - def ==(other) - __target_object__ == other - end - - def !=(other) - __target_object__ != other - end - - def ! - !__target_object__ - end - - def method_missing(method_name, *args, &block) - if __target_object__.respond_to?(method_name) - __target_object__.send(method_name, *args, &block) - else - super - end - end - - def respond_to_missing?(method_name, include_priv = false) - __target_object__.respond_to?(method_name, include_priv) - end - end - end - end -end diff --git a/spec/grape/api/patch_method_helpers_spec.rb b/spec/grape/api/patch_method_helpers_spec.rb index f91f028a5..ad0a162ba 100644 --- a/spec/grape/api/patch_method_helpers_spec.rb +++ b/spec/grape/api/patch_method_helpers_spec.rb @@ -49,12 +49,12 @@ def app context 'patch' do it 'public' do - patch '/', {}, Grape::Http::Headers::HTTP_ACCEPT => 'application/vnd.grape-public-v1+json' + patch '/', {}, 'HTTP_ACCEPT' => 'application/vnd.grape-public-v1+json' expect(last_response.status).to eq 405 end it 'private' do - patch '/', {}, Grape::Http::Headers::HTTP_ACCEPT => 'application/vnd.grape-private-v1+json' + patch '/', {}, 'HTTP_ACCEPT' => 'application/vnd.grape-private-v1+json' expect(last_response.status).to eq 405 end @@ -66,13 +66,13 @@ def app context 'default' do it 'public' do - get '/', {}, Grape::Http::Headers::HTTP_ACCEPT => 'application/vnd.grape-public-v1+json' + get '/', {}, 'HTTP_ACCEPT' => 'application/vnd.grape-public-v1+json' expect(last_response.status).to eq 200 expect(last_response.body).to eq({ ok: 'public' }.to_json) end it 'private' do - get '/', {}, Grape::Http::Headers::HTTP_ACCEPT => 'application/vnd.grape-private-v1+json' + get '/', {}, 'HTTP_ACCEPT' => 'application/vnd.grape-private-v1+json' expect(last_response.status).to eq 200 expect(last_response.body).to eq({ ok: 'private' }.to_json) end diff --git a/spec/grape/api_spec.rb b/spec/grape/api_spec.rb index 013e0741b..f16b31ee2 100644 --- a/spec/grape/api_spec.rb +++ b/spec/grape/api_spec.rb @@ -510,7 +510,7 @@ def to_txt subject.send(verb) do env[Grape::Env::API_REQUEST_INPUT] end - send verb, '/', Grape::Json.dump(object), 'CONTENT_TYPE' => 'application/json', Grape::Http::Headers::HTTP_TRANSFER_ENCODING => 'chunked' + send verb, '/', Grape::Json.dump(object), 'CONTENT_TYPE' => 'application/json', 'HTTP_TRANSFER_ENCODING' => 'chunked' expect(last_response.status).to eq(verb == :post ? 201 : 200) expect(last_response.body).to eql Grape::Json.dump(object).to_json end @@ -1307,7 +1307,7 @@ def to_txt expect(last_response.content_type).to eq('text/plain') expect(last_response.content_length).to be_nil expect(last_response.headers[Rack::CACHE_CONTROL]).to eq('no-cache') - expect(last_response.headers[Grape::Http::Headers::TRANSFER_ENCODING]).to eq('chunked') + expect(last_response.headers['Transfer-Encoding']).to eq('chunked') expect(last_response.body).to eq("c\r\nThis is some\r\nd\r\n file content\r\n0\r\n\r\n") end @@ -2886,7 +2886,7 @@ def self.call(message, _backtrace, _options, _env, _original_exception) end it 'uses custom formatter' do - get '/simple.custom', Grape::Http::Headers::HTTP_ACCEPT => 'application/custom' + get '/simple.custom', 'HTTP_ACCEPT' => 'application/custom' expect(last_response.body).to eql '{"custom_formatter":"hash"}' end end @@ -2915,7 +2915,7 @@ def self.call(object, _env) end it 'uses custom formatter' do - get '/simple.custom', Grape::Http::Headers::HTTP_ACCEPT => 'application/custom' + get '/simple.custom', 'HTTP_ACCEPT' => 'application/custom' expect(last_response.body).to eql '{"custom_formatter":"hash"}' end end @@ -3558,7 +3558,7 @@ def self.call(object, _env) it 'is able to cascade' do subject.mount lambda { |env| headers = {} - headers[Grape::Http::Headers::X_CASCADE] == 'pass' if env[Rack::PATH_INFO].exclude?('boo') + headers['X-Cascade'] == 'pass' if env[Rack::PATH_INFO].exclude?('boo') [200, headers, ['Farfegnugen']] } => '/' @@ -4058,7 +4058,7 @@ def my_method end it 'forces txt from a non-accepting header' do - get '/meaning_of_life', {}, Grape::Http::Headers::HTTP_ACCEPT => 'application/json' + get '/meaning_of_life', {}, 'HTTP_ACCEPT' => 'application/json' expect(last_response.body).to eq({ meaning_of_life: 42 }.to_s) end end @@ -4087,7 +4087,7 @@ def my_method end it 'forces txt from a non-accepting header' do - get '/meaning_of_life', {}, Grape::Http::Headers::HTTP_ACCEPT => 'application/json' + get '/meaning_of_life', {}, 'HTTP_ACCEPT' => 'application/json' expect(last_response.body).to eq({ meaning_of_life: 42 }.to_s) end end @@ -4112,7 +4112,7 @@ def my_method end it 'forces json from a non-accepting header' do - get '/meaning_of_life', {}, Grape::Http::Headers::HTTP_ACCEPT => 'text/html' + get '/meaning_of_life', {}, 'HTTP_ACCEPT' => 'text/html' expect(last_response.body).to eq({ meaning_of_life: 42 }.to_json) end @@ -4336,14 +4336,14 @@ def before subject.version 'v1', using: :path, cascade: true get '/v1/hello' expect(last_response).to be_not_found - expect(last_response.headers[Grape::Http::Headers::X_CASCADE]).to eq('pass') + expect(last_response.headers['X-Cascade']).to eq('pass') end it 'does not cascade' do subject.version 'v2', using: :path, cascade: false get '/v2/hello' expect(last_response).to be_not_found - expect(last_response.headers.keys).not_to include Grape::Http::Headers::X_CASCADE + expect(last_response.headers.keys).not_to include 'X-Cascade' end end @@ -4352,14 +4352,14 @@ def before subject.cascade true get '/hello' expect(last_response).to be_not_found - expect(last_response.headers[Grape::Http::Headers::X_CASCADE]).to eq('pass') + expect(last_response.headers['X-Cascade']).to eq('pass') end it 'does not cascade' do subject.cascade false get '/hello' expect(last_response).to be_not_found - expect(last_response.headers.keys).not_to include Grape::Http::Headers::X_CASCADE + expect(last_response.headers.keys).not_to include 'X-Cascade' end end end diff --git a/spec/grape/dsl/inside_route_spec.rb b/spec/grape/dsl/inside_route_spec.rb index 9e72e8087..5e5b8b5d0 100644 --- a/spec/grape/dsl/inside_route_spec.rb +++ b/spec/grape/dsl/inside_route_spec.rb @@ -69,7 +69,7 @@ def initialize end it 'sets location header' do - expect(subject.header[Grape::Http::Headers::LOCATION]).to eq '/' + expect(subject.header['Location']).to eq '/' end end @@ -83,7 +83,7 @@ def initialize end it 'sets location header' do - expect(subject.header[Grape::Http::Headers::LOCATION]).to eq '/' + expect(subject.header['Location']).to eq '/' end end end @@ -205,7 +205,7 @@ def initialize before do subject.header Rack::CACHE_CONTROL, 'cache' subject.header Rack::CONTENT_LENGTH, 123 - subject.header Grape::Http::Headers::TRANSFER_ENCODING, 'base64' + subject.header 'Transfer-Encoding', 'base64' subject.sendfile file_path end @@ -217,7 +217,7 @@ def initialize expect(subject.header).to match( Rack::CACHE_CONTROL => 'cache', Rack::CONTENT_LENGTH => 123, - Grape::Http::Headers::TRANSFER_ENCODING => 'base64' + 'Transfer-Encoding' => 'base64' ) end end @@ -249,7 +249,7 @@ def initialize before do subject.header Rack::CACHE_CONTROL, 'cache' subject.header Rack::CONTENT_LENGTH, 123 - subject.header Grape::Http::Headers::TRANSFER_ENCODING, 'base64' + subject.header 'Transfer-Encoding', 'base64' subject.stream file_path end @@ -272,7 +272,7 @@ def initialize before do subject.header Rack::CACHE_CONTROL, 'cache' subject.header Rack::CONTENT_LENGTH, 123 - subject.header Grape::Http::Headers::TRANSFER_ENCODING, 'base64' + subject.header 'Transfer-Encoding', 'base64' subject.stream stream_object end diff --git a/spec/grape/endpoint_spec.rb b/spec/grape/endpoint_spec.rb index bcdf5f62e..3f98aacb6 100644 --- a/spec/grape/endpoint_spec.rb +++ b/spec/grape/endpoint_spec.rb @@ -1021,12 +1021,12 @@ def memoized end it 'result in a 406 response if they are invalid' do - get '/test', {}, Grape::Http::Headers::HTTP_ACCEPT => 'application/vnd.ohanapi.v1+json' + get '/test', {}, 'HTTP_ACCEPT' => 'application/vnd.ohanapi.v1+json' expect(last_response.status).to eq(406) end it 'result in a 406 response if they cannot be parsed' do - get '/test', {}, Grape::Http::Headers::HTTP_ACCEPT => 'application/vnd.ohanapi.v1+json; version=1' + get '/test', {}, 'HTTP_ACCEPT' => 'application/vnd.ohanapi.v1+json; version=1' expect(last_response.status).to eq(406) end end diff --git a/spec/grape/exceptions/invalid_accept_header_spec.rb b/spec/grape/exceptions/invalid_accept_header_spec.rb index a0bf11139..29884f0dd 100644 --- a/spec/grape/exceptions/invalid_accept_header_spec.rb +++ b/spec/grape/exceptions/invalid_accept_header_spec.rb @@ -19,7 +19,7 @@ shared_examples_for 'a not-cascaded request' do it 'does not include the X-Cascade=pass header' do - expect(last_response.headers).not_to have_key(Grape::Http::Headers::X_CASCADE) + expect(last_response.headers).not_to have_key('X-Cascade') end it 'does not accept the request' do @@ -29,7 +29,7 @@ shared_examples_for 'a rescued request' do it 'does not include the X-Cascade=pass header' do - expect(last_response.headers[Grape::Http::Headers::X_CASCADE]).to be_nil + expect(last_response.headers['X-Cascade']).to be_nil end it 'does show rescue handler processing' do @@ -56,7 +56,7 @@ def app end context 'that received a request with correct vendor and version' do - before { get '/beer', {}, Grape::Http::Headers::HTTP_ACCEPT => 'application/vnd.vendorname-v99' } + before { get '/beer', {}, 'HTTP_ACCEPT' => 'application/vnd.vendorname-v99' } it_behaves_like 'a valid request' end @@ -64,7 +64,7 @@ def app context 'that receives' do context 'an invalid vendor in the request' do before do - get '/beer', {}, Grape::Http::Headers::HTTP_ACCEPT => 'application/vnd.invalidvendor-v99', + get '/beer', {}, 'HTTP_ACCEPT' => 'application/vnd.invalidvendor-v99', 'CONTENT_TYPE' => 'application/json' end @@ -88,20 +88,20 @@ def app end context 'that received a request with correct vendor and version' do - before { get '/beer', {}, Grape::Http::Headers::HTTP_ACCEPT => 'application/vnd.vendorname-v99' } + before { get '/beer', {}, 'HTTP_ACCEPT' => 'application/vnd.vendorname-v99' } it_behaves_like 'a valid request' end context 'that receives' do context 'an invalid version in the request' do - before { get '/beer', {}, Grape::Http::Headers::HTTP_ACCEPT => 'application/vnd.vendorname-v77' } + before { get '/beer', {}, 'HTTP_ACCEPT' => 'application/vnd.vendorname-v77' } it_behaves_like 'a not-cascaded request' end context 'an invalid vendor in the request' do - before { get '/beer', {}, Grape::Http::Headers::HTTP_ACCEPT => 'application/vnd.invalidvendor-v99' } + before { get '/beer', {}, 'HTTP_ACCEPT' => 'application/vnd.invalidvendor-v99' } it_behaves_like 'a not-cascaded request' end @@ -131,7 +131,7 @@ def app end context 'that received a request with correct vendor and version' do - before { get '/beer', {}, Grape::Http::Headers::HTTP_ACCEPT => 'application/vnd.vendorname-v99' } + before { get '/beer', {}, 'HTTP_ACCEPT' => 'application/vnd.vendorname-v99' } it_behaves_like 'a valid request' end @@ -139,7 +139,7 @@ def app context 'that receives' do context 'an invalid vendor in the request' do before do - get '/beer', {}, Grape::Http::Headers::HTTP_ACCEPT => 'application/vnd.invalidvendor-v99', + get '/beer', {}, 'HTTP_ACCEPT' => 'application/vnd.invalidvendor-v99', 'CONTENT_TYPE' => 'application/json' end @@ -168,20 +168,20 @@ def app end context 'that received a request with correct vendor and version' do - before { get '/beer', {}, Grape::Http::Headers::HTTP_ACCEPT => 'application/vnd.vendorname-v99' } + before { get '/beer', {}, 'HTTP_ACCEPT' => 'application/vnd.vendorname-v99' } it_behaves_like 'a valid request' end context 'that receives' do context 'an invalid version in the request' do - before { get '/beer', {}, Grape::Http::Headers::HTTP_ACCEPT => 'application/vnd.vendorname-v77' } + before { get '/beer', {}, 'HTTP_ACCEPT' => 'application/vnd.vendorname-v77' } it_behaves_like 'a not-cascaded request' end context 'an invalid vendor in the request' do - before { get '/beer', {}, Grape::Http::Headers::HTTP_ACCEPT => 'application/vnd.invalidvendor-v99' } + before { get '/beer', {}, 'HTTP_ACCEPT' => 'application/vnd.invalidvendor-v99' } it_behaves_like 'a not-cascaded request' end @@ -206,7 +206,7 @@ def app end context 'that received a request with correct vendor and version' do - before { get '/beer', {}, Grape::Http::Headers::HTTP_ACCEPT => 'application/vnd.vendorname-v99' } + before { get '/beer', {}, 'HTTP_ACCEPT' => 'application/vnd.vendorname-v99' } it_behaves_like 'a valid request' end @@ -214,7 +214,7 @@ def app context 'that receives' do context 'an invalid version in the request' do before do - get '/beer', {}, Grape::Http::Headers::HTTP_ACCEPT => 'application/vnd.vendorname-v77', + get '/beer', {}, 'HTTP_ACCEPT' => 'application/vnd.vendorname-v77', 'CONTENT_TYPE' => 'application/json' end @@ -223,7 +223,7 @@ def app context 'an invalid vendor in the request' do before do - get '/beer', {}, Grape::Http::Headers::HTTP_ACCEPT => 'application/vnd.invalidvendor-v99', + get '/beer', {}, 'HTTP_ACCEPT' => 'application/vnd.invalidvendor-v99', 'CONTENT_TYPE' => 'application/json' end @@ -247,20 +247,20 @@ def app end context 'that received a request with correct vendor and version' do - before { get '/beer', {}, Grape::Http::Headers::HTTP_ACCEPT => 'application/vnd.vendorname-v99' } + before { get '/beer', {}, 'HTTP_ACCEPT' => 'application/vnd.vendorname-v99' } it_behaves_like 'a valid request' end context 'that receives' do context 'an invalid version in the request' do - before { get '/beer', {}, Grape::Http::Headers::HTTP_ACCEPT => 'application/vnd.vendorname-v77' } + before { get '/beer', {}, 'HTTP_ACCEPT' => 'application/vnd.vendorname-v77' } it_behaves_like 'a cascaded request' end context 'an invalid vendor in the request' do - before { get '/beer', {}, Grape::Http::Headers::HTTP_ACCEPT => 'application/vnd.invalidvendor-v99' } + before { get '/beer', {}, 'HTTP_ACCEPT' => 'application/vnd.invalidvendor-v99' } it_behaves_like 'a cascaded request' end @@ -290,7 +290,7 @@ def app end context 'that received a request with correct vendor and version' do - before { get '/beer', {}, Grape::Http::Headers::HTTP_ACCEPT => 'application/vnd.vendorname-v99' } + before { get '/beer', {}, 'HTTP_ACCEPT' => 'application/vnd.vendorname-v99' } it_behaves_like 'a valid request' end @@ -298,7 +298,7 @@ def app context 'that receives' do context 'an invalid version in the request' do before do - get '/beer', {}, Grape::Http::Headers::HTTP_ACCEPT => 'application/vnd.vendorname-v77', + get '/beer', {}, 'HTTP_ACCEPT' => 'application/vnd.vendorname-v77', 'CONTENT_TYPE' => 'application/json' end @@ -307,7 +307,7 @@ def app context 'an invalid vendor in the request' do before do - get '/beer', {}, Grape::Http::Headers::HTTP_ACCEPT => 'application/vnd.invalidvendor-v99', + get '/beer', {}, 'HTTP_ACCEPT' => 'application/vnd.invalidvendor-v99', 'CONTENT_TYPE' => 'application/json' end @@ -336,20 +336,20 @@ def app end context 'that received a request with correct vendor and version' do - before { get '/beer', {}, Grape::Http::Headers::HTTP_ACCEPT => 'application/vnd.vendorname-v99' } + before { get '/beer', {}, 'HTTP_ACCEPT' => 'application/vnd.vendorname-v99' } it_behaves_like 'a valid request' end context 'that receives' do context 'an invalid version in the request' do - before { get '/beer', {}, Grape::Http::Headers::HTTP_ACCEPT => 'application/vnd.vendorname-v77' } + before { get '/beer', {}, 'HTTP_ACCEPT' => 'application/vnd.vendorname-v77' } it_behaves_like 'a cascaded request' end context 'an invalid vendor in the request' do - before { get '/beer', {}, Grape::Http::Headers::HTTP_ACCEPT => 'application/vnd.invalidvendor-v99' } + before { get '/beer', {}, 'HTTP_ACCEPT' => 'application/vnd.invalidvendor-v99' } it_behaves_like 'a cascaded request' end diff --git a/spec/grape/middleware/formatter_spec.rb b/spec/grape/middleware/formatter_spec.rb index af72f029d..807edaad4 100644 --- a/spec/grape/middleware/formatter_spec.rb +++ b/spec/grape/middleware/formatter_spec.rb @@ -11,7 +11,7 @@ context 'serialization' do let(:body) { { 'abc' => 'def' } } let(:env) do - { Rack::PATH_INFO => '/somewhere', Grape::Http::Headers::HTTP_ACCEPT => 'application/json' } + { Rack::PATH_INFO => '/somewhere', 'HTTP_ACCEPT' => 'application/json' } end it 'looks at the bodies for possibly serializable data' do @@ -22,7 +22,7 @@ context 'default format' do let(:body) { ['foo'] } let(:env) do - { Rack::PATH_INFO => '/somewhere', Grape::Http::Headers::HTTP_ACCEPT => 'application/json' } + { Rack::PATH_INFO => '/somewhere', 'HTTP_ACCEPT' => 'application/json' } end it 'calls #to_json since default format is json' do @@ -39,7 +39,7 @@ def to_json(*_args) context 'xml' do let(:body) { +'string' } let(:env) do - { Rack::PATH_INFO => '/somewhere.xml', Grape::Http::Headers::HTTP_ACCEPT => 'application/json' } + { Rack::PATH_INFO => '/somewhere.xml', 'HTTP_ACCEPT' => 'application/json' } end it 'calls #to_xml if the content type is xml' do @@ -57,7 +57,7 @@ def to_xml context 'error handling' do let(:formatter) { double(:formatter) } let(:env) do - { Rack::PATH_INFO => '/somewhere.xml', Grape::Http::Headers::HTTP_ACCEPT => 'application/json' } + { Rack::PATH_INFO => '/somewhere.xml', 'HTTP_ACCEPT' => 'application/json' } end before do @@ -76,7 +76,7 @@ def to_xml allow(formatter).to receive(:call) { raise StandardError } expect do - catch(:error) { subject.call(Rack::PATH_INFO => '/somewhere.xml', Grape::Http::Headers::HTTP_ACCEPT => 'application/json') } + catch(:error) { subject.call(Rack::PATH_INFO => '/somewhere.xml', 'HTTP_ACCEPT' => 'application/json') } end.to raise_error(StandardError) end end @@ -109,12 +109,12 @@ def to_xml end it 'uses the requested format if provided in headers' do - subject.call(Rack::PATH_INFO => '/info', Grape::Http::Headers::HTTP_ACCEPT => 'application/json') + subject.call(Rack::PATH_INFO => '/info', 'HTTP_ACCEPT' => 'application/json') expect(subject.env[Grape::Env::API_FORMAT]).to eq(:json) end it 'uses the file extension format if provided before headers' do - subject.call(Rack::PATH_INFO => '/info.txt', Grape::Http::Headers::HTTP_ACCEPT => 'application/json') + subject.call(Rack::PATH_INFO => '/info.txt', 'HTTP_ACCEPT' => 'application/json') expect(subject.env[Grape::Env::API_FORMAT]).to eq(:txt) end end @@ -122,47 +122,47 @@ def to_xml context 'accept header detection' do context 'when header contains invalid byte sequence' do it 'does not raise an exception' do - expect { subject.call(Rack::PATH_INFO => '/info', Grape::Http::Headers::HTTP_ACCEPT => "Hello \x80") }.not_to raise_error + expect { subject.call(Rack::PATH_INFO => '/info', 'HTTP_ACCEPT' => "Hello \x80") }.not_to raise_error end end it 'detects from the Accept header' do - subject.call(Rack::PATH_INFO => '/info', Grape::Http::Headers::HTTP_ACCEPT => 'application/xml') + subject.call(Rack::PATH_INFO => '/info', 'HTTP_ACCEPT' => 'application/xml') expect(subject.env[Grape::Env::API_FORMAT]).to eq(:xml) end it 'uses quality rankings to determine formats' do - subject.call(Rack::PATH_INFO => '/info', Grape::Http::Headers::HTTP_ACCEPT => 'application/json; q=0.3,application/xml; q=1.0') + subject.call(Rack::PATH_INFO => '/info', 'HTTP_ACCEPT' => 'application/json; q=0.3,application/xml; q=1.0') expect(subject.env[Grape::Env::API_FORMAT]).to eq(:xml) - subject.call(Rack::PATH_INFO => '/info', Grape::Http::Headers::HTTP_ACCEPT => 'application/json; q=1.0,application/xml; q=0.3') + subject.call(Rack::PATH_INFO => '/info', 'HTTP_ACCEPT' => 'application/json; q=1.0,application/xml; q=0.3') expect(subject.env[Grape::Env::API_FORMAT]).to eq(:json) end it 'handles quality rankings mixed with nothing' do - subject.call(Rack::PATH_INFO => '/info', Grape::Http::Headers::HTTP_ACCEPT => 'application/json,application/xml; q=1.0') + subject.call(Rack::PATH_INFO => '/info', 'HTTP_ACCEPT' => 'application/json,application/xml; q=1.0') expect(subject.env[Grape::Env::API_FORMAT]).to eq(:xml) - subject.call(Rack::PATH_INFO => '/info', Grape::Http::Headers::HTTP_ACCEPT => 'application/xml; q=1.0,application/json') + subject.call(Rack::PATH_INFO => '/info', 'HTTP_ACCEPT' => 'application/xml; q=1.0,application/json') expect(subject.env[Grape::Env::API_FORMAT]).to eq(:json) end it 'handles quality rankings that have a default 1.0 value' do - subject.call(Rack::PATH_INFO => '/info', Grape::Http::Headers::HTTP_ACCEPT => 'application/json,application/xml;q=0.5') + subject.call(Rack::PATH_INFO => '/info', 'HTTP_ACCEPT' => 'application/json,application/xml;q=0.5') expect(subject.env[Grape::Env::API_FORMAT]).to eq(:json) - subject.call(Rack::PATH_INFO => '/info', Grape::Http::Headers::HTTP_ACCEPT => 'application/xml;q=0.5,application/json') + subject.call(Rack::PATH_INFO => '/info', 'HTTP_ACCEPT' => 'application/xml;q=0.5,application/json') expect(subject.env[Grape::Env::API_FORMAT]).to eq(:json) end it 'parses headers with other attributes' do - subject.call(Rack::PATH_INFO => '/info', Grape::Http::Headers::HTTP_ACCEPT => 'application/json; abc=2.3; q=1.0,application/xml; q=0.7') + subject.call(Rack::PATH_INFO => '/info', 'HTTP_ACCEPT' => 'application/json; abc=2.3; q=1.0,application/xml; q=0.7') expect(subject.env[Grape::Env::API_FORMAT]).to eq(:json) end it 'ensures that a quality of 0 is less preferred than any other content type' do - subject.call(Rack::PATH_INFO => '/info', Grape::Http::Headers::HTTP_ACCEPT => 'application/json;q=0.0,application/xml') + subject.call(Rack::PATH_INFO => '/info', 'HTTP_ACCEPT' => 'application/json;q=0.0,application/xml') expect(subject.env[Grape::Env::API_FORMAT]).to eq(:xml) - subject.call(Rack::PATH_INFO => '/info', Grape::Http::Headers::HTTP_ACCEPT => 'application/xml,application/json;q=0.0') + subject.call(Rack::PATH_INFO => '/info', 'HTTP_ACCEPT' => 'application/xml,application/json;q=0.0') expect(subject.env[Grape::Env::API_FORMAT]).to eq(:xml) end @@ -171,21 +171,21 @@ def to_xml subject { described_class.new(app, content_types: { custom: 'application/vnd.test+json' }) } it 'uses the custom type' do - subject.call(Rack::PATH_INFO => '/info', Grape::Http::Headers::HTTP_ACCEPT => 'application/vnd.test+json') + subject.call(Rack::PATH_INFO => '/info', 'HTTP_ACCEPT' => 'application/vnd.test+json') expect(subject.env[Grape::Env::API_FORMAT]).to eq(:custom) end end context 'when unregistered' do it 'returns the default content type text/plain' do - r = Rack::MockResponse[*subject.call(Rack::PATH_INFO => '/info', Grape::Http::Headers::HTTP_ACCEPT => 'application/vnd.test+json')] + r = Rack::MockResponse[*subject.call(Rack::PATH_INFO => '/info', 'HTTP_ACCEPT' => 'application/vnd.test+json')] expect(r.headers[Rack::CONTENT_TYPE]).to eq('text/plain') end end end it 'parses headers with symbols as hash keys' do - subject.call(Rack::PATH_INFO => '/info', Grape::Http::Headers::HTTP_ACCEPT => 'application/xml', system_time: '091293') + subject.call(Rack::PATH_INFO => '/info', 'HTTP_ACCEPT' => 'application/xml', system_time: '091293') expect(subject.env[:system_time]).to eq('091293') end end @@ -214,7 +214,7 @@ def to_xml it 'is set for vendored with registered type' do s = described_class.new(app, content_types: { custom: 'application/vnd.test+json' }) - _, headers, = s.call(Rack::PATH_INFO => '/info', Grape::Http::Headers::HTTP_ACCEPT => 'application/vnd.test+json') + _, headers, = s.call(Rack::PATH_INFO => '/info', 'HTTP_ACCEPT' => 'application/vnd.test+json') expect(headers[Rack::CONTENT_TYPE]).to eq('application/vnd.test+json') end end @@ -362,7 +362,7 @@ def to_xml Rack::REQUEST_METHOD => method, 'CONTENT_TYPE' => 'application/json', Rack::RACK_INPUT => io, - Grape::Http::Headers::HTTP_TRANSFER_ENCODING => 'chunked' + 'HTTP_TRANSFER_ENCODING' => 'chunked' ) expect(subject.env[Rack::RACK_REQUEST_FORM_HASH]['is_boolean']).to be true expect(subject.env[Rack::RACK_REQUEST_FORM_HASH]['string']).to eq('thing') @@ -376,7 +376,7 @@ def to_xml Rack::REQUEST_METHOD => method, 'CONTENT_TYPE' => 'application/json', Rack::RACK_INPUT => io, - Grape::Http::Headers::HTTP_TRANSFER_ENCODING => 'chunked' + 'HTTP_TRANSFER_ENCODING' => 'chunked' ) expect(subject.env[Rack::RACK_REQUEST_FORM_HASH]['is_boolean']).to be true expect(subject.env[Rack::RACK_REQUEST_FORM_HASH]['string']).to eq('thing') @@ -420,7 +420,7 @@ def to_xml let(:app) { ->(_env) { [200, {}, file_body] } } let(:body) { 'data' } let(:env) do - { Rack::PATH_INFO => '/somewhere', Grape::Http::Headers::HTTP_ACCEPT => 'application/json' } + { Rack::PATH_INFO => '/somewhere', 'HTTP_ACCEPT' => 'application/json' } end let(:headers) do if Gem::Version.new(Rack.release) < Gem::Version.new('3.1') @@ -452,7 +452,7 @@ def self.call(_, _) let(:app) { ->(_env) { [200, {}, ['']] } } let(:env) do - Rack::MockRequest.env_for('/hello.invalid', Grape::Http::Headers::HTTP_ACCEPT => 'application/x-invalid') + Rack::MockRequest.env_for('/hello.invalid', 'HTTP_ACCEPT' => 'application/x-invalid') end it 'returns response by invalid formatter' do diff --git a/spec/grape/middleware/versioner/accept_version_header_spec.rb b/spec/grape/middleware/versioner/accept_version_header_spec.rb index 491abe6f9..7693cb92d 100644 --- a/spec/grape/middleware/versioner/accept_version_header_spec.rb +++ b/spec/grape/middleware/versioner/accept_version_header_spec.rb @@ -20,8 +20,8 @@ it 'does not raise an error' do expect do - subject.call(Grape::Http::Headers::HTTP_ACCEPT_VERSION => "\x80") - end.to throw_symbol(:error, status: 406, headers: { Grape::Http::Headers::X_CASCADE => 'pass' }, message: 'The requested version is not supported.') + subject.call('HTTP_ACCEPT_VERSION' => "\x80") + end.to throw_symbol(:error, status: 406, headers: { 'X-Cascade' => 'pass' }, message: 'The requested version is not supported.') end end @@ -31,37 +31,37 @@ end it 'is set' do - status, _, env = subject.call(Grape::Http::Headers::HTTP_ACCEPT_VERSION => 'v1') + status, _, env = subject.call('HTTP_ACCEPT_VERSION' => 'v1') expect(env[Grape::Env::API_VERSION]).to eql 'v1' expect(status).to eq(200) end it 'is set if format provided' do - status, _, env = subject.call(Grape::Http::Headers::HTTP_ACCEPT_VERSION => 'v1') + status, _, env = subject.call('HTTP_ACCEPT_VERSION' => 'v1') expect(env[Grape::Env::API_VERSION]).to eql 'v1' expect(status).to eq(200) end it 'fails with 406 Not Acceptable if version is not supported' do expect do - subject.call(Grape::Http::Headers::HTTP_ACCEPT_VERSION => 'v2').last + subject.call('HTTP_ACCEPT_VERSION' => 'v2').last end.to throw_symbol( :error, status: 406, - headers: { Grape::Http::Headers::X_CASCADE => 'pass' }, + headers: { 'X-Cascade' => 'pass' }, message: 'The requested version is not supported.' ) end end it 'succeeds if :strict is not set' do - expect(subject.call(Grape::Http::Headers::HTTP_ACCEPT_VERSION => '').first).to eq(200) + expect(subject.call('HTTP_ACCEPT_VERSION' => '').first).to eq(200) expect(subject.call({}).first).to eq(200) end it 'succeeds if :strict is set to false' do @options[:version_options][:strict] = false - expect(subject.call(Grape::Http::Headers::HTTP_ACCEPT_VERSION => '').first).to eq(200) + expect(subject.call('HTTP_ACCEPT_VERSION' => '').first).to eq(200) expect(subject.call({}).first).to eq(200) end @@ -77,24 +77,24 @@ end.to throw_symbol( :error, status: 406, - headers: { Grape::Http::Headers::X_CASCADE => 'pass' }, + headers: { 'X-Cascade' => 'pass' }, message: 'Accept-Version header must be set.' ) end it 'fails with 406 Not Acceptable if header is empty' do expect do - subject.call(Grape::Http::Headers::HTTP_ACCEPT_VERSION => '').last + subject.call('HTTP_ACCEPT_VERSION' => '').last end.to throw_symbol( :error, status: 406, - headers: { Grape::Http::Headers::X_CASCADE => 'pass' }, + headers: { 'X-Cascade' => 'pass' }, message: 'Accept-Version header must be set.' ) end it 'succeeds if proper header is set' do - expect(subject.call(Grape::Http::Headers::HTTP_ACCEPT_VERSION => 'v1').first).to eq(200) + expect(subject.call('HTTP_ACCEPT_VERSION' => 'v1').first).to eq(200) end end @@ -118,7 +118,7 @@ it 'fails with 406 Not Acceptable if header is empty' do expect do - subject.call(Grape::Http::Headers::HTTP_ACCEPT_VERSION => '').last + subject.call('HTTP_ACCEPT_VERSION' => '').last end.to throw_symbol( :error, status: 406, @@ -128,7 +128,7 @@ end it 'succeeds if proper header is set' do - expect(subject.call(Grape::Http::Headers::HTTP_ACCEPT_VERSION => 'v1').first).to eq(200) + expect(subject.call('HTTP_ACCEPT_VERSION' => 'v1').first).to eq(200) end end end diff --git a/spec/grape/middleware/versioner/header_spec.rb b/spec/grape/middleware/versioner/header_spec.rb index 12fd837e0..230133cba 100644 --- a/spec/grape/middleware/versioner/header_spec.rb +++ b/spec/grape/middleware/versioner/header_spec.rb @@ -16,21 +16,21 @@ context 'api.type and api.subtype' do it 'sets type and subtype to first choice of content type if no preference given' do - status, _, env = subject.call(Grape::Http::Headers::HTTP_ACCEPT => '*/*') + status, _, env = subject.call('HTTP_ACCEPT' => '*/*') expect(env[Grape::Env::API_TYPE]).to eql 'application' expect(env[Grape::Env::API_SUBTYPE]).to eql 'vnd.vendor+xml' expect(status).to eq(200) end it 'sets preferred type' do - status, _, env = subject.call(Grape::Http::Headers::HTTP_ACCEPT => 'application/*') + status, _, env = subject.call('HTTP_ACCEPT' => 'application/*') expect(env[Grape::Env::API_TYPE]).to eql 'application' expect(env[Grape::Env::API_SUBTYPE]).to eql 'vnd.vendor+xml' expect(status).to eq(200) end it 'sets preferred type and subtype' do - status, _, env = subject.call(Grape::Http::Headers::HTTP_ACCEPT => 'text/plain') + status, _, env = subject.call('HTTP_ACCEPT' => 'text/plain') expect(env[Grape::Env::API_TYPE]).to eql 'text' expect(env[Grape::Env::API_SUBTYPE]).to eql 'plain' expect(status).to eq(200) @@ -39,13 +39,13 @@ context 'api.format' do it 'is set' do - status, _, env = subject.call(Grape::Http::Headers::HTTP_ACCEPT => 'application/vnd.vendor+json') + status, _, env = subject.call('HTTP_ACCEPT' => 'application/vnd.vendor+json') expect(env[Grape::Env::API_FORMAT]).to eql 'json' expect(status).to eq(200) end it 'is nil if not provided' do - status, _, env = subject.call(Grape::Http::Headers::HTTP_ACCEPT => 'application/vnd.vendor') + status, _, env = subject.call('HTTP_ACCEPT' => 'application/vnd.vendor') expect(env[Grape::Env::API_FORMAT]).to be_nil expect(status).to eq(200) end @@ -57,13 +57,13 @@ end it 'is set' do - status, _, env = subject.call(Grape::Http::Headers::HTTP_ACCEPT => 'application/vnd.vendor-v1+json') + status, _, env = subject.call('HTTP_ACCEPT' => 'application/vnd.vendor-v1+json') expect(env[Grape::Env::API_FORMAT]).to eql 'json' expect(status).to eq(200) end it 'is nil if not provided' do - status, _, env = subject.call(Grape::Http::Headers::HTTP_ACCEPT => 'application/vnd.vendor-v1') + status, _, env = subject.call('HTTP_ACCEPT' => 'application/vnd.vendor-v1') expect(env[Grape::Env::API_FORMAT]).to be_nil expect(status).to eq(200) end @@ -73,22 +73,22 @@ context 'api.vendor' do it 'is set' do - status, _, env = subject.call(Grape::Http::Headers::HTTP_ACCEPT => 'application/vnd.vendor') + status, _, env = subject.call('HTTP_ACCEPT' => 'application/vnd.vendor') expect(env[Grape::Env::API_VENDOR]).to eql 'vendor' expect(status).to eq(200) end it 'is set if format provided' do - status, _, env = subject.call(Grape::Http::Headers::HTTP_ACCEPT => 'application/vnd.vendor+json') + status, _, env = subject.call('HTTP_ACCEPT' => 'application/vnd.vendor+json') expect(env[Grape::Env::API_VENDOR]).to eql 'vendor' expect(status).to eq(200) end it 'fails with 406 Not Acceptable if vendor is invalid' do - expect { subject.call(Grape::Http::Headers::HTTP_ACCEPT => 'application/vnd.othervendor+json').last } + expect { subject.call('HTTP_ACCEPT' => 'application/vnd.othervendor+json').last } .to raise_exception do |exception| expect(exception).to be_a(Grape::Exceptions::InvalidAcceptHeader) - expect(exception.headers).to eql(Grape::Http::Headers::X_CASCADE => 'pass') + expect(exception.headers).to eql('X-Cascade' => 'pass') expect(exception.status).to be 406 expect(exception.message).to include 'API vendor not found' end @@ -100,22 +100,22 @@ end it 'is set' do - status, _, env = subject.call(Grape::Http::Headers::HTTP_ACCEPT => 'application/vnd.vendor-v1') + status, _, env = subject.call('HTTP_ACCEPT' => 'application/vnd.vendor-v1') expect(env[Grape::Env::API_VENDOR]).to eql 'vendor' expect(status).to eq(200) end it 'is set if format provided' do - status, _, env = subject.call(Grape::Http::Headers::HTTP_ACCEPT => 'application/vnd.vendor-v1+json') + status, _, env = subject.call('HTTP_ACCEPT' => 'application/vnd.vendor-v1+json') expect(env[Grape::Env::API_VENDOR]).to eql 'vendor' expect(status).to eq(200) end it 'fails with 406 Not Acceptable if vendor is invalid' do - expect { subject.call(Grape::Http::Headers::HTTP_ACCEPT => 'application/vnd.othervendor-v1+json').last } + expect { subject.call('HTTP_ACCEPT' => 'application/vnd.othervendor-v1+json').last } .to raise_exception do |exception| expect(exception).to be_a(Grape::Exceptions::InvalidAcceptHeader) - expect(exception.headers).to eql(Grape::Http::Headers::X_CASCADE => 'pass') + expect(exception.headers).to eql('X-Cascade' => 'pass') expect(exception.status).to be 406 expect(exception.message).to include('API vendor not found') end @@ -129,21 +129,21 @@ end it 'is set' do - status, _, env = subject.call(Grape::Http::Headers::HTTP_ACCEPT => 'application/vnd.vendor-v1') + status, _, env = subject.call('HTTP_ACCEPT' => 'application/vnd.vendor-v1') expect(env[Grape::Env::API_VERSION]).to eql 'v1' expect(status).to eq(200) end it 'is set if format provided' do - status, _, env = subject.call(Grape::Http::Headers::HTTP_ACCEPT => 'application/vnd.vendor-v1+json') + status, _, env = subject.call('HTTP_ACCEPT' => 'application/vnd.vendor-v1+json') expect(env[Grape::Env::API_VERSION]).to eql 'v1' expect(status).to eq(200) end it 'fails with 406 Not Acceptable if version is invalid' do - expect { subject.call(Grape::Http::Headers::HTTP_ACCEPT => 'application/vnd.vendor-v2+json').last }.to raise_exception do |exception| + expect { subject.call('HTTP_ACCEPT' => 'application/vnd.vendor-v2+json').last }.to raise_exception do |exception| expect(exception).to be_a(Grape::Exceptions::InvalidVersionHeader) - expect(exception.headers).to eql(Grape::Http::Headers::X_CASCADE => 'pass') + expect(exception.headers).to eql('X-Cascade' => 'pass') expect(exception.status).to be 406 expect(exception.message).to include('API version not found') end @@ -151,19 +151,19 @@ end it 'succeeds if :strict is not set' do - expect(subject.call(Grape::Http::Headers::HTTP_ACCEPT => '').first).to eq(200) + expect(subject.call('HTTP_ACCEPT' => '').first).to eq(200) expect(subject.call({}).first).to eq(200) end it 'succeeds if :strict is set to false' do @options[:version_options][:strict] = false - expect(subject.call(Grape::Http::Headers::HTTP_ACCEPT => '').first).to eq(200) + expect(subject.call('HTTP_ACCEPT' => '').first).to eq(200) expect(subject.call({}).first).to eq(200) end it 'succeeds if :strict is set to false and given an invalid header' do @options[:version_options][:strict] = false - expect(subject.call(Grape::Http::Headers::HTTP_ACCEPT => 'yaml').first).to eq(200) + expect(subject.call('HTTP_ACCEPT' => 'yaml').first).to eq(200) expect(subject.call({}).first).to eq(200) end @@ -176,23 +176,23 @@ it 'fails with 406 Not Acceptable if header is not set' do expect { subject.call({}).last }.to raise_exception do |exception| expect(exception).to be_a(Grape::Exceptions::InvalidAcceptHeader) - expect(exception.headers).to eql(Grape::Http::Headers::X_CASCADE => 'pass') + expect(exception.headers).to eql('X-Cascade' => 'pass') expect(exception.status).to be 406 expect(exception.message).to include('Accept header must be set.') end end it 'fails with 406 Not Acceptable if header is empty' do - expect { subject.call(Grape::Http::Headers::HTTP_ACCEPT => '').last }.to raise_exception do |exception| + expect { subject.call('HTTP_ACCEPT' => '').last }.to raise_exception do |exception| expect(exception).to be_a(Grape::Exceptions::InvalidAcceptHeader) - expect(exception.headers).to eql(Grape::Http::Headers::X_CASCADE => 'pass') + expect(exception.headers).to eql('X-Cascade' => 'pass') expect(exception.status).to be 406 expect(exception.message).to include('Accept header must be set.') end end it 'succeeds if proper header is set' do - expect(subject.call(Grape::Http::Headers::HTTP_ACCEPT => 'application/vnd.vendor-v1+json').first).to eq(200) + expect(subject.call('HTTP_ACCEPT' => 'application/vnd.vendor-v1+json').first).to eq(200) end end @@ -213,7 +213,7 @@ end it 'fails with 406 Not Acceptable if header is application/xml' do - expect { subject.call(Grape::Http::Headers::HTTP_ACCEPT => 'application/xml').last } + expect { subject.call('HTTP_ACCEPT' => 'application/xml').last } .to raise_exception do |exception| expect(exception).to be_a(Grape::Exceptions::InvalidAcceptHeader) expect(exception.headers).to eql({}) @@ -223,7 +223,7 @@ end it 'fails with 406 Not Acceptable if header is empty' do - expect { subject.call(Grape::Http::Headers::HTTP_ACCEPT => '').last }.to raise_exception do |exception| + expect { subject.call('HTTP_ACCEPT' => '').last }.to raise_exception do |exception| expect(exception).to be_a(Grape::Exceptions::InvalidAcceptHeader) expect(exception.headers).to eql({}) expect(exception.status).to be 406 @@ -232,7 +232,7 @@ end it 'fails with 406 Not Acceptable if header contains a single invalid accept' do - expect { subject.call(Grape::Http::Headers::HTTP_ACCEPT => 'application/json;application/vnd.vendor-v1+json').first } + expect { subject.call('HTTP_ACCEPT' => 'application/json;application/vnd.vendor-v1+json').first } .to raise_exception do |exception| expect(exception).to be_a(Grape::Exceptions::InvalidAcceptHeader) expect(exception.headers).to eql({}) @@ -242,7 +242,7 @@ end it 'succeeds if proper header is set' do - expect(subject.call(Grape::Http::Headers::HTTP_ACCEPT => 'application/vnd.vendor-v1+json').first).to eq(200) + expect(subject.call('HTTP_ACCEPT' => 'application/vnd.vendor-v1+json').first).to eq(200) end end @@ -252,17 +252,17 @@ end it 'succeeds with v1' do - expect(subject.call(Grape::Http::Headers::HTTP_ACCEPT => 'application/vnd.vendor-v1+json').first).to eq(200) + expect(subject.call('HTTP_ACCEPT' => 'application/vnd.vendor-v1+json').first).to eq(200) end it 'succeeds with v2' do - expect(subject.call(Grape::Http::Headers::HTTP_ACCEPT => 'application/vnd.vendor-v2+json').first).to eq(200) + expect(subject.call('HTTP_ACCEPT' => 'application/vnd.vendor-v2+json').first).to eq(200) end it 'fails with another version' do - expect { subject.call(Grape::Http::Headers::HTTP_ACCEPT => 'application/vnd.vendor-v3+json') }.to raise_exception do |exception| + expect { subject.call('HTTP_ACCEPT' => 'application/vnd.vendor-v3+json') }.to raise_exception do |exception| expect(exception).to be_a(Grape::Exceptions::InvalidVersionHeader) - expect(exception.headers).to eql(Grape::Http::Headers::X_CASCADE => 'pass') + expect(exception.headers).to eql('X-Cascade' => 'pass') expect(exception.status).to be 406 expect(exception.message).to include('API version not found') end diff --git a/spec/integration/rack_3_0/headers_spec.rb b/spec/integration/rack_3_0/headers_spec.rb index bd270e129..735807c7e 100644 --- a/spec/integration/rack_3_0/headers_spec.rb +++ b/spec/integration/rack_3_0/headers_spec.rb @@ -1,12 +1,12 @@ # frozen_string_literal: true -describe Grape::Http::Headers do +describe Grape::API do subject { last_response.headers } describe 'returned headers should all be in lowercase' do context 'when setting an header in an API' do let(:app) do - Class.new(Grape::API) do + Class.new(described_class) do get do header['GRAPE'] = '1' return_no_content @@ -21,7 +21,7 @@ context 'when error!' do let(:app) do - Class.new(Grape::API) do + Class.new(described_class) do rescue_from ArgumentError do error!('error!', 500, { 'GRAPE' => '1' }) end @@ -37,7 +37,7 @@ context 'when redirect' do let(:app) do - Class.new(Grape::API) do + Class.new(described_class) do get do redirect 'https://www.ruby-grape.org/' end @@ -51,7 +51,7 @@ context 'when options' do let(:app) do - Class.new(Grape::API) do + Class.new(described_class) do get { return_no_content } end end @@ -63,7 +63,7 @@ context 'when cascade' do let(:app) do - Class.new(Grape::API) do + Class.new(described_class) do version 'v0', using: :path, cascade: true get { return_no_content } end diff --git a/spec/support/chunked_response.rb b/spec/support/chunked_response.rb index c74f18f09..4c66e9384 100644 --- a/spec/support/chunked_response.rb +++ b/spec/support/chunked_response.rb @@ -58,9 +58,9 @@ def call(env) if !Rack::Utils::STATUS_WITH_NO_ENTITY_BODY.key?(status.to_i) && !headers[Rack::CONTENT_LENGTH] && - !headers[Grape::Http::Headers::TRANSFER_ENCODING] + !headers['Transfer-Encoding'] - headers[Grape::Http::Headers::TRANSFER_ENCODING] = 'chunked' + headers['Transfer-Encoding'] = 'chunked' response[2] = if headers['trailer'] TrailerBody.new(body) else diff --git a/spec/support/versioned_helpers.rb b/spec/support/versioned_helpers.rb index c4e841249..ce682e0d7 100644 --- a/spec/support/versioned_helpers.rb +++ b/spec/support/versioned_helpers.rb @@ -23,14 +23,14 @@ def versioned_headers(options) {} when :header { - Grape::Http::Headers::HTTP_ACCEPT => [ + 'HTTP_ACCEPT' => [ "application/vnd.#{options[:vendor]}-#{options[:version]}", options[:format] ].compact.join('+') } when :accept_version_header { - Grape::Http::Headers::HTTP_ACCEPT_VERSION => options[:version].to_s + 'HTTP_ACCEPT_VERSION' => options[:version].to_s } else raise ArgumentError.new("unknown versioning strategy: #{options[:using]}")