faraday-follow_redirects 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 7e496bdd1ac0161f28c7d2aadd510df36acd4f3e53957f45d5ad1362c4c24fca
4
+ data.tar.gz: f96e61f56296d999223f1c4b7f358bf9824e4f900bf3b1cabf94a98e7bba0be6
5
+ SHA512:
6
+ metadata.gz: 9a2a6d486e1ab5109073d41ddfc8489bcafcd860e063d8b3d2169f83757ca62eeed76348769ebdfa9fcae5eb9221f860bd5173969a9d77f9b7031dc64940dcd5
7
+ data.tar.gz: e879e1d501b2bbf4085a87fc4439722d376689e9767a624582d2523b1b4d16611094bbee1645ad7ec8eafe50bf7a97aca4aed39897ad4f6c8dd8e10103abeb52
data/CHANGELOG.md ADDED
@@ -0,0 +1,9 @@
1
+ # Changelog
2
+
3
+ ## Unreleased
4
+
5
+ * …
6
+
7
+ ## 0.1.0 (2022-02-24)
8
+
9
+ * Initial release
data/LICENSE.md ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2022 Sebastian Cohnen
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,60 @@
1
+ # Faraday Follow Redirects
2
+
3
+ [![GitHub Workflow Status](https://img.shields.io/github/workflow/status/tisba/faraday-follow-redirects/CI)](https://github.com/tisba/faraday-follow-redirects/actions?query=branch%3Amain)
4
+ [![Gem](https://img.shields.io/gem/v/faraday-follow-redirects.svg?style=flat-square)](https://rubygems.org/gems/faraday-follow-redirects)
5
+ [![License](https://img.shields.io/github/license/tisba/faraday-follow-redirects.svg?style=flat-square)](LICENSE.md)
6
+
7
+ Faraday 2.x compatible extraction of `FaradayMiddleware::FollowRedirects`. If you are still using Faraday 1.x, check out https://github.com/lostisland/faraday_middleware.
8
+
9
+ This gem is based on the deprecated [`FaradayMiddleware::FollowRedirects` (v1.2.0)](https://github.com/lostisland/faraday_middleware/blob/v1.2.0/lib/faraday_middleware/response/follow_redirects.rb).
10
+
11
+ ## Installation
12
+
13
+ Add this line to your application's Gemfile:
14
+
15
+ ```ruby
16
+ gem 'faraday-follow_redirects'
17
+ ```
18
+
19
+ And then execute:
20
+
21
+ ```shell
22
+ bundle install
23
+ ```
24
+
25
+ Or install it yourself as:
26
+
27
+ ```shell
28
+ gem install faraday-follow_redirects
29
+ ```
30
+
31
+ ## Usage
32
+
33
+ ```ruby
34
+ require 'faraday/follow_redirects'
35
+
36
+ Faraday.new(url: url) do |faraday|
37
+ faraday.use Faraday::FollowRedirects::Middleware
38
+
39
+ faraday.adapter Faraday.default_adapter
40
+ end
41
+ ```
42
+
43
+ ## Development
44
+
45
+ After checking out the repo, run `bin/setup` to install dependencies.
46
+
47
+ Then, run `bin/test` to run the tests.
48
+
49
+ To install this gem onto your local machine, run `rake build`.
50
+
51
+ To release a new version, make a commit with a message such as "Bumped to 0.0.2" and then run `rake release`.
52
+ See how it works [here](https://bundler.io/guides/creating_gem.html#releasing-the-gem).
53
+
54
+ ## Contributing
55
+
56
+ Bug reports and pull requests are welcome on [GitHub](https://github.com/tisba/faraday-follow_redirects).
57
+
58
+ ## License
59
+
60
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
@@ -0,0 +1,156 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Faraday
4
+ module FollowRedirects
5
+ # Public: Follow HTTP 301, 302, 303, 307, and 308 redirects.
6
+ #
7
+ # For HTTP 301, 302, and 303, the original GET, POST, PUT, DELETE, or PATCH
8
+ # request gets converted into a GET. With `:standards_compliant => true`,
9
+ # however, the HTTP method after 301/302 remains unchanged. This allows you
10
+ # to opt into HTTP/1.1 compliance and act unlike the major web browsers.
11
+ #
12
+ # This middleware currently only works with synchronous requests; i.e. it
13
+ # doesn't support parallelism.
14
+ #
15
+ # If you wish to persist cookies across redirects, you could use
16
+ # the faraday-cookie_jar gem:
17
+ #
18
+ # Faraday.new(:url => url) do |faraday|
19
+ # faraday.use FaradayMiddleware::FollowRedirects
20
+ # faraday.use :cookie_jar
21
+ # faraday.adapter Faraday.default_adapter
22
+ # end
23
+ class Middleware < Faraday::Middleware
24
+ # HTTP methods for which 30x redirects can be followed
25
+ ALLOWED_METHODS = Set.new %i[head options get post put patch delete]
26
+ # HTTP redirect status codes that this middleware implements
27
+ REDIRECT_CODES = Set.new [301, 302, 303, 307, 308]
28
+ # Keys in env hash which will get cleared between requests
29
+ ENV_TO_CLEAR = Set.new %i[status response response_headers]
30
+
31
+ # Default value for max redirects followed
32
+ FOLLOW_LIMIT = 3
33
+
34
+ # Regex that matches characters that need to be escaped in URLs, sans
35
+ # the "%" character which we assume already represents an escaped sequence.
36
+ URI_UNSAFE = %r{[^\-_.!~*'()a-zA-Z\d;/?:@&=+$,\[\]%]}.freeze
37
+
38
+ AUTH_HEADER = 'Authorization'
39
+
40
+ # Public: Initialize the middleware.
41
+ #
42
+ # options - An options Hash (default: {}):
43
+ # :limit - A Numeric redirect limit (default: 3)
44
+ # :standards_compliant - A Boolean indicating whether to respect
45
+ # the HTTP spec when following 301/302
46
+ # (default: false)
47
+ # :callback - A callable used on redirects
48
+ # with the old and new envs
49
+ # :cookies - An Array of Strings (e.g.
50
+ # ['cookie1', 'cookie2']) to choose
51
+ # cookies to be kept, or :all to keep
52
+ # all cookies (default: []).
53
+ # :clear_authorization_header - A Boolean indicating whether the request
54
+ # Authorization header should be cleared on
55
+ # redirects (default: true)
56
+ def initialize(app, options = {})
57
+ super(app)
58
+ @options = options
59
+
60
+ @convert_to_get = Set.new [303]
61
+ @convert_to_get << 301 << 302 unless standards_compliant?
62
+ end
63
+
64
+ def call(env)
65
+ perform_with_redirection(env, follow_limit)
66
+ end
67
+
68
+ private
69
+
70
+ def convert_to_get?(response)
71
+ !%i[head options].include?(response.env[:method]) &&
72
+ @convert_to_get.include?(response.status)
73
+ end
74
+
75
+ def perform_with_redirection(env, follows)
76
+ request_body = env[:body]
77
+ response = @app.call(env)
78
+
79
+ response.on_complete do |response_env|
80
+ if follow_redirect?(response_env, response)
81
+ raise RedirectLimitReached, response if follows.zero?
82
+
83
+ new_request_env = update_env(response_env.dup, request_body, response)
84
+ callback&.call(response_env, new_request_env)
85
+ response = perform_with_redirection(new_request_env, follows - 1)
86
+ end
87
+ end
88
+ response
89
+ end
90
+
91
+ def update_env(env, request_body, response)
92
+ redirect_from_url = env[:url].to_s
93
+ redirect_to_url = safe_escape(response['location'] || '')
94
+ env[:url] += redirect_to_url
95
+
96
+ ENV_TO_CLEAR.each { |key| env.delete key }
97
+
98
+ if convert_to_get?(response)
99
+ env[:method] = :get
100
+ env[:body] = nil
101
+ else
102
+ env[:body] = request_body
103
+ end
104
+
105
+ clear_authorization_header(env, redirect_from_url, redirect_to_url)
106
+
107
+ env
108
+ end
109
+
110
+ def follow_redirect?(env, response)
111
+ ALLOWED_METHODS.include?(env[:method]) &&
112
+ REDIRECT_CODES.include?(response.status)
113
+ end
114
+
115
+ def follow_limit
116
+ @options.fetch(:limit, FOLLOW_LIMIT)
117
+ end
118
+
119
+ def standards_compliant?
120
+ @options.fetch(:standards_compliant, false)
121
+ end
122
+
123
+ def callback
124
+ @options[:callback]
125
+ end
126
+
127
+ # Internal: escapes unsafe characters from an URL which might be a path
128
+ # component only or a fully qualified URI so that it can be joined onto an
129
+ # URI:HTTP using the `+` operator. Doesn't escape "%" characters so to not
130
+ # risk double-escaping.
131
+ def safe_escape(uri)
132
+ uri = uri.split('#')[0] # we want to remove the fragment if present
133
+ uri.to_s.gsub(URI_UNSAFE) do |match|
134
+ "%#{match.unpack('H2' * match.bytesize).join('%').upcase}"
135
+ end
136
+ end
137
+
138
+ def clear_authorization_header(env, from_url, to_url)
139
+ return env if redirect_to_same_host?(from_url, to_url)
140
+ return env unless @options.fetch(:clear_authorization_header, true)
141
+
142
+ env[:request_headers].delete(AUTH_HEADER)
143
+ end
144
+
145
+ def redirect_to_same_host?(from_url, to_url)
146
+ return true if to_url.start_with?('/')
147
+
148
+ from_uri = URI.parse(from_url)
149
+ to_uri = URI.parse(to_url)
150
+
151
+ [from_uri.scheme, from_uri.host, from_uri.port] ==
152
+ [to_uri.scheme, to_uri.host, to_uri.port]
153
+ end
154
+ end
155
+ end
156
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'faraday'
4
+
5
+ module Faraday
6
+ module FollowRedirects
7
+ # Exception thrown when the maximum amount of requests is
8
+ # exceeded.
9
+ class RedirectLimitReached < Faraday::ClientError
10
+ attr_reader :response
11
+
12
+ def initialize(response)
13
+ super "too many redirects; last one to: #{response['location']}"
14
+ @response = response
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Faraday
4
+ module FollowRedirects
5
+ VERSION = '0.1.0'
6
+ end
7
+ end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'follow_redirects/middleware'
4
+ require_relative 'follow_redirects/redirect_limit_reached'
5
+ require_relative 'follow_redirects/version'
6
+
7
+ module Faraday
8
+ # Main Faraday::FollowRedirects module.
9
+ module FollowRedirects
10
+ Faraday::Response.register_middleware(follow_redirects: Faraday::FollowRedirects::Middleware)
11
+ end
12
+ end
metadata ADDED
@@ -0,0 +1,208 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: faraday-follow_redirects
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Sebastian Cohnen
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2022-02-24 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: faraday
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '2'
20
+ - - "<"
21
+ - !ruby/object:Gem::Version
22
+ version: '3'
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ version: '2'
30
+ - - "<"
31
+ - !ruby/object:Gem::Version
32
+ version: '3'
33
+ - !ruby/object:Gem::Dependency
34
+ name: bundler
35
+ requirement: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - "~>"
38
+ - !ruby/object:Gem::Version
39
+ version: '2.0'
40
+ type: :development
41
+ prerelease: false
42
+ version_requirements: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - "~>"
45
+ - !ruby/object:Gem::Version
46
+ version: '2.0'
47
+ - !ruby/object:Gem::Dependency
48
+ name: rake
49
+ requirement: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - "~>"
52
+ - !ruby/object:Gem::Version
53
+ version: '13.0'
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - "~>"
59
+ - !ruby/object:Gem::Version
60
+ version: '13.0'
61
+ - !ruby/object:Gem::Dependency
62
+ name: rspec
63
+ requirement: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - "~>"
66
+ - !ruby/object:Gem::Version
67
+ version: '3.0'
68
+ type: :development
69
+ prerelease: false
70
+ version_requirements: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - "~>"
73
+ - !ruby/object:Gem::Version
74
+ version: '3.0'
75
+ - !ruby/object:Gem::Dependency
76
+ name: simplecov
77
+ requirement: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - "~>"
80
+ - !ruby/object:Gem::Version
81
+ version: 0.21.0
82
+ type: :development
83
+ prerelease: false
84
+ version_requirements: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - "~>"
87
+ - !ruby/object:Gem::Version
88
+ version: 0.21.0
89
+ - !ruby/object:Gem::Dependency
90
+ name: webmock
91
+ requirement: !ruby/object:Gem::Requirement
92
+ requirements:
93
+ - - "~>"
94
+ - !ruby/object:Gem::Version
95
+ version: 3.14.0
96
+ type: :development
97
+ prerelease: false
98
+ version_requirements: !ruby/object:Gem::Requirement
99
+ requirements:
100
+ - - "~>"
101
+ - !ruby/object:Gem::Version
102
+ version: 3.14.0
103
+ - !ruby/object:Gem::Dependency
104
+ name: rubocop
105
+ requirement: !ruby/object:Gem::Requirement
106
+ requirements:
107
+ - - "~>"
108
+ - !ruby/object:Gem::Version
109
+ version: 1.25.0
110
+ type: :development
111
+ prerelease: false
112
+ version_requirements: !ruby/object:Gem::Requirement
113
+ requirements:
114
+ - - "~>"
115
+ - !ruby/object:Gem::Version
116
+ version: 1.25.0
117
+ - !ruby/object:Gem::Dependency
118
+ name: rubocop-packaging
119
+ requirement: !ruby/object:Gem::Requirement
120
+ requirements:
121
+ - - "~>"
122
+ - !ruby/object:Gem::Version
123
+ version: 0.5.0
124
+ type: :development
125
+ prerelease: false
126
+ version_requirements: !ruby/object:Gem::Requirement
127
+ requirements:
128
+ - - "~>"
129
+ - !ruby/object:Gem::Version
130
+ version: 0.5.0
131
+ - !ruby/object:Gem::Dependency
132
+ name: rubocop-performance
133
+ requirement: !ruby/object:Gem::Requirement
134
+ requirements:
135
+ - - "~>"
136
+ - !ruby/object:Gem::Version
137
+ version: '1.13'
138
+ type: :development
139
+ prerelease: false
140
+ version_requirements: !ruby/object:Gem::Requirement
141
+ requirements:
142
+ - - "~>"
143
+ - !ruby/object:Gem::Version
144
+ version: '1.13'
145
+ - !ruby/object:Gem::Dependency
146
+ name: rubocop-rspec
147
+ requirement: !ruby/object:Gem::Requirement
148
+ requirements:
149
+ - - "~>"
150
+ - !ruby/object:Gem::Version
151
+ version: '2.8'
152
+ type: :development
153
+ prerelease: false
154
+ version_requirements: !ruby/object:Gem::Requirement
155
+ requirements:
156
+ - - "~>"
157
+ - !ruby/object:Gem::Version
158
+ version: '2.8'
159
+ description: 'Faraday 2.x compatible extraction of FaradayMiddleware::FollowRedirects.
160
+
161
+ '
162
+ email:
163
+ - tisba@users.noreply.github.com
164
+ executables: []
165
+ extensions: []
166
+ extra_rdoc_files: []
167
+ files:
168
+ - CHANGELOG.md
169
+ - LICENSE.md
170
+ - README.md
171
+ - lib/faraday/follow_redirects.rb
172
+ - lib/faraday/follow_redirects/middleware.rb
173
+ - lib/faraday/follow_redirects/redirect_limit_reached.rb
174
+ - lib/faraday/follow_redirects/version.rb
175
+ homepage: https://github.com/tisba/faraday-follow_redirects
176
+ licenses:
177
+ - MIT
178
+ metadata:
179
+ bug_tracker_uri: https://github.com/tisba/faraday-follow_redirects/issues
180
+ changelog_uri: https://github.com/tisba/faraday-follow_redirects/blob/v0.1.0/CHANGELOG.md
181
+ documentation_uri: http://www.rubydoc.info/gems/faraday-follow_redirects/0.1.0
182
+ homepage_uri: https://github.com/tisba/faraday-follow_redirects
183
+ rubygems_mfa_required: 'true'
184
+ source_code_uri: https://github.com/tisba/faraday-follow_redirects
185
+ wiki_uri: https://github.com/tisba/faraday-follow_redirects/wiki
186
+ post_install_message:
187
+ rdoc_options: []
188
+ require_paths:
189
+ - lib
190
+ required_ruby_version: !ruby/object:Gem::Requirement
191
+ requirements:
192
+ - - ">="
193
+ - !ruby/object:Gem::Version
194
+ version: '2.6'
195
+ - - "<"
196
+ - !ruby/object:Gem::Version
197
+ version: '4'
198
+ required_rubygems_version: !ruby/object:Gem::Requirement
199
+ requirements:
200
+ - - ">="
201
+ - !ruby/object:Gem::Version
202
+ version: '0'
203
+ requirements: []
204
+ rubygems_version: 3.3.3
205
+ signing_key:
206
+ specification_version: 4
207
+ summary: Faraday 2.x compatible extraction of FaradayMiddleware::FollowRedirects
208
+ test_files: []