faraday-follow-redirects-0.3.0/0000755000175100017510000000000014444023211015424 5ustar pravipravifaraday-follow-redirects-0.3.0/LICENSE.md0000644000175100017510000000207314444023211017032 0ustar pravipraviThe MIT License (MIT) Copyright (c) 2022 Sebastian Cohnen Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. faraday-follow-redirects-0.3.0/CHANGELOG.md0000644000175100017510000000036114444023211017235 0ustar pravipravi# Changelog ## Unreleased * … ## 0.3.0 (2022-04-02) * losen version constraint on faraday to support 1.x and 2.x (#4) ## 0.2.0 (2022-03-07) * require faraday explicitly when loading this gem ## 0.1.0 (2022-02-24) * initial release faraday-follow-redirects-0.3.0/faraday-follow_redirects.gemspec0000644000175100017510000000653614444023211023756 0ustar pravipravi######################################################### # This file has been automatically generated by gem2tgz # ######################################################### # -*- encoding: utf-8 -*- # stub: faraday-follow_redirects 0.3.0 ruby lib Gem::Specification.new do |s| s.name = "faraday-follow_redirects".freeze s.version = "0.3.0" s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version= s.metadata = { "bug_tracker_uri" => "https://github.com/tisba/faraday-follow-redirects/issues", "changelog_uri" => "https://github.com/tisba/faraday-follow-redirects/blob/v0.3.0/CHANGELOG.md", "documentation_uri" => "http://www.rubydoc.info/gems/faraday-follow_redirects/0.3.0", "homepage_uri" => "https://github.com/tisba/faraday-follow-redirects", "rubygems_mfa_required" => "true", "source_code_uri" => "https://github.com/tisba/faraday-follow-redirects", "wiki_uri" => "https://github.com/tisba/faraday-follow-redirects/wiki" } if s.respond_to? :metadata= s.require_paths = ["lib".freeze] s.authors = ["Sebastian Cohnen".freeze] s.date = "2022-04-02" s.description = "Faraday 2.x compatible extraction of FaradayMiddleware::FollowRedirects.\n".freeze s.email = ["tisba@users.noreply.github.com".freeze] s.files = ["CHANGELOG.md".freeze, "LICENSE.md".freeze, "README.md".freeze, "lib/faraday/follow_redirects.rb".freeze, "lib/faraday/follow_redirects/middleware.rb".freeze, "lib/faraday/follow_redirects/redirect_limit_reached.rb".freeze, "lib/faraday/follow_redirects/version.rb".freeze] s.homepage = "https://github.com/tisba/faraday-follow-redirects".freeze s.licenses = ["MIT".freeze] s.required_ruby_version = Gem::Requirement.new([">= 2.6".freeze, "< 4".freeze]) s.rubygems_version = "3.3.15".freeze s.summary = "Faraday 2.x compatible extraction of FaradayMiddleware::FollowRedirects".freeze if s.respond_to? :specification_version then s.specification_version = 4 end if s.respond_to? :add_runtime_dependency then s.add_development_dependency(%q.freeze, ["~> 2.4"]) s.add_development_dependency(%q.freeze, ["~> 2.0"]) s.add_runtime_dependency(%q.freeze, [">= 1", "< 3"]) s.add_development_dependency(%q.freeze, ["~> 13.0"]) s.add_development_dependency(%q.freeze, ["~> 3.0"]) s.add_development_dependency(%q.freeze, ["~> 1.25.0"]) s.add_development_dependency(%q.freeze, ["~> 0.5.0"]) s.add_development_dependency(%q.freeze, ["~> 1.13"]) s.add_development_dependency(%q.freeze, ["~> 2.8"]) s.add_development_dependency(%q.freeze, ["~> 0.21.0"]) s.add_development_dependency(%q.freeze, ["~> 3.14.0"]) else s.add_dependency(%q.freeze, ["~> 2.4"]) s.add_dependency(%q.freeze, ["~> 2.0"]) s.add_dependency(%q.freeze, [">= 1", "< 3"]) s.add_dependency(%q.freeze, ["~> 13.0"]) s.add_dependency(%q.freeze, ["~> 3.0"]) s.add_dependency(%q.freeze, ["~> 1.25.0"]) s.add_dependency(%q.freeze, ["~> 0.5.0"]) s.add_dependency(%q.freeze, ["~> 1.13"]) s.add_dependency(%q.freeze, ["~> 2.8"]) s.add_dependency(%q.freeze, ["~> 0.21.0"]) s.add_dependency(%q.freeze, ["~> 3.14.0"]) end end faraday-follow-redirects-0.3.0/lib/0000755000175100017510000000000014444023211016172 5ustar pravipravifaraday-follow-redirects-0.3.0/lib/faraday/0000755000175100017510000000000014444023211017601 5ustar pravipravifaraday-follow-redirects-0.3.0/lib/faraday/follow_redirects/0000755000175100017510000000000014444023211023147 5ustar pravipravifaraday-follow-redirects-0.3.0/lib/faraday/follow_redirects/version.rb0000644000175100017510000000014714444023211025163 0ustar pravipravi# frozen_string_literal: true module Faraday module FollowRedirects VERSION = '0.3.0' end end faraday-follow-redirects-0.3.0/lib/faraday/follow_redirects/redirect_limit_reached.rb0000644000175100017510000000063414444023211030151 0ustar pravipravi# frozen_string_literal: true require 'faraday' module Faraday module FollowRedirects # Exception thrown when the maximum amount of requests is # exceeded. class RedirectLimitReached < Faraday::ClientError attr_reader :response def initialize(response) super "too many redirects; last one to: #{response['location']}" @response = response end end end end faraday-follow-redirects-0.3.0/lib/faraday/follow_redirects/middleware.rb0000644000175100017510000001312514444023211025613 0ustar pravipravi# frozen_string_literal: true module Faraday module FollowRedirects # Public: Follow HTTP 301, 302, 303, 307, and 308 redirects. # # For HTTP 301, 302, and 303, the original GET, POST, PUT, DELETE, or PATCH # request gets converted into a GET. With `:standards_compliant => true`, # however, the HTTP method after 301/302 remains unchanged. This allows you # to opt into HTTP/1.1 compliance and act unlike the major web browsers. # # This middleware currently only works with synchronous requests; i.e. it # doesn't support parallelism. # # If you wish to persist cookies across redirects, you could use # the faraday-cookie_jar gem: # # Faraday.new(:url => url) do |faraday| # faraday.use FaradayMiddleware::FollowRedirects # faraday.use :cookie_jar # faraday.adapter Faraday.default_adapter # end class Middleware < Faraday::Middleware # HTTP methods for which 30x redirects can be followed ALLOWED_METHODS = Set.new %i[head options get post put patch delete] # HTTP redirect status codes that this middleware implements REDIRECT_CODES = Set.new [301, 302, 303, 307, 308] # Keys in env hash which will get cleared between requests ENV_TO_CLEAR = Set.new %i[status response response_headers] # Default value for max redirects followed FOLLOW_LIMIT = 3 # Regex that matches characters that need to be escaped in URLs, sans # the "%" character which we assume already represents an escaped sequence. URI_UNSAFE = %r{[^\-_.!~*'()a-zA-Z\d;/?:@&=+$,\[\]%]}.freeze AUTH_HEADER = 'Authorization' # Public: Initialize the middleware. # # options - An options Hash (default: {}): # :limit - A Numeric redirect limit (default: 3) # :standards_compliant - A Boolean indicating whether to respect # the HTTP spec when following 301/302 # (default: false) # :callback - A callable used on redirects # with the old and new envs # :cookies - An Array of Strings (e.g. # ['cookie1', 'cookie2']) to choose # cookies to be kept, or :all to keep # all cookies (default: []). # :clear_authorization_header - A Boolean indicating whether the request # Authorization header should be cleared on # redirects (default: true) def initialize(app, options = {}) super(app) @options = options @convert_to_get = Set.new [303] @convert_to_get << 301 << 302 unless standards_compliant? end def call(env) perform_with_redirection(env, follow_limit) end private def convert_to_get?(response) !%i[head options].include?(response.env[:method]) && @convert_to_get.include?(response.status) end def perform_with_redirection(env, follows) request_body = env[:body] response = @app.call(env) response.on_complete do |response_env| if follow_redirect?(response_env, response) raise RedirectLimitReached, response if follows.zero? new_request_env = update_env(response_env.dup, request_body, response) callback&.call(response_env, new_request_env) response = perform_with_redirection(new_request_env, follows - 1) end end response end def update_env(env, request_body, response) redirect_from_url = env[:url].to_s redirect_to_url = safe_escape(response['location'] || '') env[:url] += redirect_to_url ENV_TO_CLEAR.each { |key| env.delete key } if convert_to_get?(response) env[:method] = :get env[:body] = nil else env[:body] = request_body end clear_authorization_header(env, redirect_from_url, redirect_to_url) env end def follow_redirect?(env, response) ALLOWED_METHODS.include?(env[:method]) && REDIRECT_CODES.include?(response.status) end def follow_limit @options.fetch(:limit, FOLLOW_LIMIT) end def standards_compliant? @options.fetch(:standards_compliant, false) end def callback @options[:callback] end # Internal: escapes unsafe characters from an URL which might be a path # component only or a fully qualified URI so that it can be joined onto an # URI:HTTP using the `+` operator. Doesn't escape "%" characters so to not # risk double-escaping. def safe_escape(uri) uri = uri.split('#')[0] # we want to remove the fragment if present uri.to_s.gsub(URI_UNSAFE) do |match| "%#{match.unpack('H2' * match.bytesize).join('%').upcase}" end end def clear_authorization_header(env, from_url, to_url) return env if redirect_to_same_host?(from_url, to_url) return env unless @options.fetch(:clear_authorization_header, true) env[:request_headers].delete(AUTH_HEADER) end def redirect_to_same_host?(from_url, to_url) return true if to_url.start_with?('/') from_uri = URI.parse(from_url) to_uri = URI.parse(to_url) [from_uri.scheme, from_uri.host, from_uri.port] == [to_uri.scheme, to_uri.host, to_uri.port] end end end end faraday-follow-redirects-0.3.0/lib/faraday/follow_redirects.rb0000644000175100017510000000060614444023211023476 0ustar pravipravi# frozen_string_literal: true require 'faraday' require_relative 'follow_redirects/middleware' require_relative 'follow_redirects/redirect_limit_reached' require_relative 'follow_redirects/version' module Faraday # Main Faraday::FollowRedirects module. module FollowRedirects Faraday::Response.register_middleware(follow_redirects: Faraday::FollowRedirects::Middleware) end end faraday-follow-redirects-0.3.0/README.md0000644000175100017510000000507014444023211016705 0ustar pravipravi# Faraday Follow Redirects [![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) [![Gem](https://img.shields.io/gem/v/faraday-follow_redirects.svg?style=flat-square)](https://rubygems.org/gems/faraday-follow_redirects) [![License](https://img.shields.io/github/license/tisba/faraday-follow-redirects.svg?style=flat-square)](LICENSE.md) Faraday 2.x compatible extraction of `FaradayMiddleware::FollowRedirects`. This gem will also work with Faraday 1.x, to support gem codebases which can work with Faraday 1.x or 2.x. For the former standard version of this middleware for Faraday 1.x, check out https://github.com/lostisland/faraday_middleware. Faraday 1.x support is considered deprecated, please update to Faraday 2.x. 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). ## Installation Add this line to your application's Gemfile: ```ruby gem 'faraday-follow_redirects' ``` And then execute: ```shell bundle install ``` Or install it yourself as: ```shell gem install faraday-follow_redirects ``` ## Usage ```ruby require 'faraday/follow_redirects' Faraday.new(url: url) do |faraday| faraday.use Faraday::FollowRedirects::Middleware faraday.adapter Faraday.default_adapter end ``` ## Development After checking out the repo, run `bin/setup` to install dependencies. Then, run `bin/test` to run the tests. To install this gem onto your local machine, run `rake build`. To release a new version, make a commit with a message such as "Bumped to 0.0.2" and then run `rake release`. See how it works [here](https://bundler.io/guides/creating_gem.html#releasing-the-gem). We only supports non-EOL versions of Ruby. See [Ruby Maintenance Branches](https://www.ruby-lang.org/en/downloads/branches/) for the list of non-EOL Rubies. ### Appraisal for testing multiple versions of dependencies We use [appraisal](https://github.com/thoughtbot/appraisal) to test against both faraday 1.x and 2.x, and `./bin/test` will run tests against both. To run tests against just one you could: bundle exec appraisal faraday_1 rspec bundle exec appraisal faraday_2 rspec ## Contributing Bug reports and pull requests are welcome on [GitHub](https://github.com/tisba/faraday-follow_redirects). ## License The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).