pax_global_header00006660000000000000000000000064145163023250014513gustar00rootroot0000000000000052 comment=c32b0500108e956d365aaab331452c91f73b9c6f faraday-typhoeus-1.1.0/000077500000000000000000000000001451630232500147775ustar00rootroot00000000000000faraday-typhoeus-1.1.0/.github/000077500000000000000000000000001451630232500163375ustar00rootroot00000000000000faraday-typhoeus-1.1.0/.github/workflows/000077500000000000000000000000001451630232500203745ustar00rootroot00000000000000faraday-typhoeus-1.1.0/.github/workflows/ci.yml000066400000000000000000000014141451630232500215120ustar00rootroot00000000000000name: CI on: - push - pull_request env: GIT_COMMIT_SHA: ${{ github.sha }} GIT_BRANCH: ${{ github.ref }} jobs: lint: runs-on: ubuntu-latest steps: - uses: actions/checkout@v1 - name: Set up Ruby 2.7 uses: ruby/setup-ruby@v1 with: ruby-version: 2.7 bundler-cache: true - name: Rubocop run: bundle exec rubocop --format progress test: needs: [lint] runs-on: ubuntu-latest strategy: matrix: ruby: ['2.6', '2.7', '3.0', '3.1'] steps: - uses: actions/checkout@v1 - name: Set up Ruby uses: ruby/setup-ruby@v1 with: ruby-version: ${{ matrix.ruby }} bundler-cache: true - name: Test run: bundle exec rspec faraday-typhoeus-1.1.0/.gitignore000066400000000000000000000002011451630232500167600ustar00rootroot00000000000000.idea/ .bundle/ .yardoc _yardoc/ coverage/ doc/ pkg/ spec/reports/ tmp/ *.gem gemfile.lock .rvmrc .ruby-version .rspec_status faraday-typhoeus-1.1.0/.rspec000066400000000000000000000000641451630232500161140ustar00rootroot00000000000000--require spec_helper --format documentation --colorfaraday-typhoeus-1.1.0/.rubocop.yml000066400000000000000000000157131451630232500172600ustar00rootroot00000000000000inherit_from: .rubocop_todo.yml require: - rubocop-packaging - rubocop-performance AllCops: DisplayCopNames: true DisplayStyleGuide: true TargetRubyVersion: 2.6 SuggestExtensions: false Metrics/BlockLength: Exclude: - spec/**/*.rb - examples/**/*.rb Metrics/ClassLength: Max: 300 Metrics/AbcSize: Enabled: false Metrics/CyclomaticComplexity: Enabled: false Metrics/MethodLength: Max: 100 Metrics/PerceivedComplexity: Enabled: false Layout/EmptyLinesAroundAttributeAccessor: # (0.83) Enabled: true Layout/LineLength: Exclude: - spec/**/*.rb - examples/**/*.rb Layout/SpaceAroundMethodCallOperator: Enabled: true Lint/DeprecatedOpenSSLConstant: # (0.84) Enabled: true Lint/RaiseException: Enabled: true Lint/StructNewOverride: Enabled: true Style/DoubleNegation: Enabled: false Style/Documentation: AllowedConstants: - "Typhoeus" Exclude: - 'spec/**/*' - 'examples/**/*' Style/ExponentialNotation: Enabled: true Style/HashEachMethods: Enabled: true Style/HashTransformKeys: Enabled: true Style/HashTransformValues: Enabled: true Style/IfUnlessModifier: Enabled: false Style/Send: Enabled: true Style/SlicingWithRange: # (0.83) Enabled: true Layout/BeginEndAlignment: # (new in 0.91) Enabled: true Lint/BinaryOperatorWithIdenticalOperands: # (new in 0.89) Enabled: true Lint/ConstantDefinitionInBlock: # (new in 0.91) Enabled: true Lint/DuplicateElsifCondition: # (new in 0.88) Enabled: true Lint/DuplicateRequire: # (new in 0.90) Enabled: true Lint/DuplicateRescueException: # (new in 0.89) Enabled: true Lint/EmptyConditionalBody: # (new in 0.89) Enabled: true Lint/EmptyFile: # (new in 0.90) Enabled: true Lint/FloatComparison: # (new in 0.89) Enabled: true Lint/HashCompareByIdentity: # (new in 0.93) Enabled: true Lint/IdentityComparison: # (new in 0.91) Enabled: true Lint/MissingSuper: # (new in 0.89) Enabled: true Lint/MixedRegexpCaptureTypes: # (new in 0.85) Enabled: true Lint/OutOfRangeRegexpRef: # (new in 0.89) Enabled: true Lint/RedundantSafeNavigation: # (new in 0.93) Enabled: true Lint/SelfAssignment: # (new in 0.89) Enabled: true Lint/TopLevelReturnWithArgument: # (new in 0.89) Enabled: true Lint/TrailingCommaInAttributeDeclaration: # (new in 0.90) Enabled: true Performance/BlockGivenWithExplicitBlock: # (new in 1.9) Enabled: true Performance/CollectionLiteralInLoop: # (new in 1.8) Enabled: true Performance/ConstantRegexp: # (new in 1.9) Enabled: true Performance/MethodObjectAsBlock: # (new in 1.9) Enabled: true Performance/RedundantEqualityComparisonBlock: # (new in 1.10) Enabled: true Performance/RedundantSortBlock: # (new in 1.7) Enabled: true Performance/RedundantSplitRegexpArgument: # (new in 1.10) Enabled: true Performance/RedundantStringChars: # (new in 1.7) Enabled: true Performance/ReverseFirst: # (new in 1.7) Enabled: true Performance/SortReverse: # (new in 1.7) Enabled: true Performance/Squeeze: # (new in 1.7) Enabled: true Performance/StringInclude: # (new in 1.7) Enabled: true Performance/Sum: # (new in 1.8) Enabled: true Layout/LineEndStringConcatenationIndentation: # (new in 1.18) Enabled: true Layout/SpaceBeforeBrackets: # (new in 1.7) Enabled: true Lint/AmbiguousAssignment: # (new in 1.7) Enabled: true Lint/AmbiguousRange: # (new in 1.19) Enabled: true Lint/DeprecatedConstants: # (new in 1.8) Enabled: true Lint/DuplicateBranch: # (new in 1.3) Enabled: true Lint/DuplicateRegexpCharacterClassElement: # (new in 1.1) Enabled: true Lint/EmptyBlock: # (new in 1.1) Enabled: true Lint/EmptyClass: # (new in 1.3) Enabled: true Lint/EmptyInPattern: # (new in 1.16) Enabled: true Lint/LambdaWithoutLiteralBlock: # (new in 1.8) Enabled: true Lint/NoReturnInBeginEndBlocks: # (new in 1.2) Enabled: true Lint/NumberedParameterAssignment: # (new in 1.9) Enabled: true Lint/OrAssignmentToConstant: # (new in 1.9) Enabled: true Lint/RedundantDirGlobSort: # (new in 1.8) Enabled: true Lint/SymbolConversion: # (new in 1.9) Enabled: true Lint/ToEnumArguments: # (new in 1.1) Enabled: true Lint/TripleQuotes: # (new in 1.9) Enabled: true Lint/UnexpectedBlockArity: # (new in 1.5) Enabled: true Lint/UnmodifiedReduceAccumulator: # (new in 1.1) Enabled: true Naming/InclusiveLanguage: # (new in 1.18) Enabled: true Style/ArgumentsForwarding: # (new in 1.1) Enabled: true Style/CollectionCompact: # (new in 1.2) Enabled: true Style/DocumentDynamicEvalDefinition: # (new in 1.1) Enabled: true Style/EndlessMethod: # (new in 1.8) Enabled: true Style/HashConversion: # (new in 1.10) Enabled: true Style/HashExcept: # (new in 1.7) Enabled: true Style/IfWithBooleanLiteralBranches: # (new in 1.9) Enabled: true Style/InPatternThen: # (new in 1.16) Enabled: true Style/MultilineInPatternThen: # (new in 1.16) Enabled: true Style/NegatedIfElseCondition: # (new in 1.2) Enabled: true Style/NilLambda: # (new in 1.3) Enabled: true Style/QuotedSymbols: # (new in 1.16) Enabled: true Style/RedundantArgument: # (new in 1.4) Enabled: true Style/RedundantSelfAssignmentBranch: # (new in 1.19) Enabled: true Style/StringChars: # (new in 1.12) Enabled: true Style/SwapValues: # (new in 1.1) Enabled: true Performance/AncestorsInclude: # (new in 1.7) Enabled: true Performance/BigDecimalWithNumericArgument: # (new in 1.7) Enabled: true Gemspec/RequireMFA: # new in 1.23 Enabled: true Lint/AmbiguousOperatorPrecedence: # new in 1.21 Enabled: true Lint/IncompatibleIoSelectWithFiberScheduler: # new in 1.21 Enabled: true Lint/RefinementImportMethods: # new in 1.27 Enabled: true Lint/RequireRelativeSelfPath: # new in 1.22 Enabled: true Lint/UselessRuby2Keywords: # new in 1.23 Enabled: true Naming/BlockForwarding: # new in 1.24 Enabled: true Security/IoMethods: # new in 1.22 Enabled: true Style/FileRead: # new in 1.24 Enabled: true Style/FileWrite: # new in 1.24 Enabled: true Style/MapToHash: # new in 1.24 Enabled: true Style/NestedFileDirname: # new in 1.26 Enabled: true Style/NumberedParameters: # new in 1.22 Enabled: true Style/NumberedParametersLimit: # new in 1.22 Enabled: true Style/OpenStructUse: # new in 1.23 Enabled: true Style/RedundantInitialize: # new in 1.27 Enabled: true Style/SelectByRegexp: # new in 1.22 Enabled: true Performance/ConcurrentMonotonicTime: # new in 1.12 Enabled: true Performance/MapCompact: # new in 1.11 Enabled: true Performance/StringIdentifierArgument: # new in 1.13 Enabled: true Gemspec/DeprecatedAttributeAssignment: # new in 1.30 Enabled: true Layout/LineContinuationLeadingSpace: # new in 1.31 Enabled: true Layout/LineContinuationSpacing: # new in 1.31 Enabled: true Lint/ConstantOverwrittenInRescue: # new in 1.31 Enabled: true Lint/NonAtomicFileOperation: # new in 1.31 Enabled: true Security/CompoundHash: # new in 1.28 Enabled: true Style/EnvHome: # new in 1.29 Enabled: true Style/FetchEnvVar: # new in 1.28 Enabled: true Style/MapCompactWithConditionalBlock: # new in 1.30 Enabled: true Style/ObjectThen: # new in 1.28 Enabled: true faraday-typhoeus-1.1.0/.rubocop_todo.yml000066400000000000000000000010111451630232500202670ustar00rootroot00000000000000# This configuration was generated by # `rubocop --auto-gen-config` # on 2023-10-13 23:37:05 UTC using RuboCop version 1.31.1. # The point is for the user to remove these configuration records # one by one as the offenses are removed from the code base. # Note that changes in the inspected code, or installation of new # versions of RuboCop, may require this file to be generated again. # Offense count: 2 # Configuration parameters: MinBodyLength. Style/GuardClause: Exclude: - 'lib/faraday/adapter/typhoeus.rb' faraday-typhoeus-1.1.0/.vscode/000077500000000000000000000000001451630232500163405ustar00rootroot00000000000000faraday-typhoeus-1.1.0/.vscode/extensions.json000066400000000000000000000001151451630232500214270ustar00rootroot00000000000000{ "recommendations": [ "redhat.vscode-yaml", "ban.spellright" ] }faraday-typhoeus-1.1.0/.vscode/settings.json000066400000000000000000000014541451630232500210770ustar00rootroot00000000000000{ "ruby.lint": { "rubocop": true }, "ruby.format": "rubocop", "yaml.schemas": { "https://gist.githubusercontent.com/dleavitt/e6dbb12da833a0e967d1a289e9cc8da2/raw/8e638ac9fc4cce11d2935c93be8931a6f39d331f/rubocop-schema.json": [ ".rubocop.yml", ".rubocop_todo.yml" ] }, "[ruby]": { "editor.insertSpaces": true, "editor.tabSize": 2, "editor.defaultFormatter": "rebornix.ruby", "files.trimTrailingWhitespace": true, "files.insertFinalNewline": true }, "[yaml]": { "files.trimTrailingWhitespace": true, "files.insertFinalNewline": true, "editor.insertSpaces": true, "editor.tabSize": 2, "editor.autoIndent": "keep", "editor.quickSuggestions": { "other": true, "comments": false, "strings": true } }, }faraday-typhoeus-1.1.0/.vscode/spellright.dict000066400000000000000000000000551451630232500213620ustar00rootroot00000000000000Typhoeus Gemfile Ethon rubygems.org rubygems faraday-typhoeus-1.1.0/Gemfile000066400000000000000000000005661451630232500163010ustar00rootroot00000000000000# frozen_string_literal: true source 'https://rubygems.org' gemspec gem 'bundler', '~> 2.0' gem 'rack', '~> 2.2' gem 'rake', '~> 13.0' gem 'rspec', '~> 3.7' gem 'simplecov', '~> 0.21.2' gem 'multipart-parser', '~> 0.1.1' gem 'webmock', '~> 3.4' gem 'rubocop', '~> 1.31' gem 'rubocop-packaging', '~> 0.5' gem 'rubocop-performance', '~> 1.0' gem 'rubocop-rspec', '~> 2.9' faraday-typhoeus-1.1.0/LICENSE.md000066400000000000000000000020721451630232500164040ustar00rootroot00000000000000The MIT License (MIT) Copyright (c) 2020 Jan van der Pas 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-typhoeus-1.1.0/README.md000066400000000000000000000072471451630232500162700ustar00rootroot00000000000000# Faraday Typhoeus Adapter This is a [Faraday 2][faraday] adapter for the [Typhoeus][typhoeus] parallel HTTP client. It supports parallel HTTP requests and streaming. ## Installation Add this line to your application's Gemfile: ```ruby gem 'faraday-typhoeus' ``` And then execute: $ bundle install Or install it yourself with `gem install faraday-typhoeus` and require it in your ruby code with `require 'faraday/typhoeus'` ## Usage ### Basic ```ruby conn = Faraday.new(...) do |f| f.adapter :typhoeus end ``` ### Typhoeus Options You can also include options for [Typhoeus][typhoeus_options]/[Ethon][ethon_options] that will be used in every request: Note that block-style configuration for the adapter is not currently supported. ```ruby conn = Faraday.new(...) do |f| f.adapter :typhoeus, forbid_reuse: true, maxredirs: 1 end ``` ### Parallel Requests The adapter supports Typhoeus's parallel request functionality: ```ruby conn = Faraday.new(...) do |f| f.request :url_encoded f.response :logger f.adapter :typhoeus end responses = [] conn.in_parallel do # responses[0].body will be null here since the requests have not been # completed responses = [ conn.get('/first'), conn.get('/second'), ] end # after it has been completed the response information is fully available in # response[0].status, etc responses[0].body responses[1].body ``` ### Streaming Responses The adapter supports [streamed responses](faraday_streaming) via the `on_data` option: ```ruby conn = Faraday.new(...) do |f| f.adapter :typhoeus end # Streaming chunks = [] conn.get('/stream') do |req| req.options.on_data proc do |chunk, received_bytes| chunks << chunk end end body = chunks.join # Server-Sent Event Polling body = nil begin conn.get('/events') do |req| req.options.timeout = 30 req.options.on_data = proc do |chunk| # stop listening once we get some data (YMMV) if chunk.start_with?('data: ') body = chunk :abort # abort the request, we're done end end end rescue Faraday::ConnectionFailed => ex raise ex unless body end ``` ## Resources - See [Typhoeus Documentation][typhoeus] for more info. ## Development After checking out the repo, run `bin/setup` to install dependencies. Then, run `bin/test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](rubygems). ### TODO - [ ] Better tests for parallel functionality (can port them over from Typhoeus) - [ ] Support block-based configuration like other adapters - [ ] Refactor the adapter a bit to look more like other Faraday 2 adapters (use `connection` etc.) - [x] Compression support - [x] Reason-phrase parsing support ## Contributing Bug reports and pull requests are welcome on [GitHub][repo]. ## License The gem is available as open source under the terms of the [license][license]. [faraday]: https://github.com/lostisland/faraday [typhoeus]: https://github.com/typhoeus/typhoeus [typhoeus_options]: https://github.com/typhoeus/typhoeus/blob/3544111b76b95d13da7cc6bfe4eb07921d771d93/lib/typhoeus/easy_factory.rb#L13-L39 [ethon_options]: https://github.com/typhoeus/ethon/blob/5d9ddf8f609a6be4b5c60d55e1e338eeeb08f25f/lib/ethon/curls/options.rb#L214-L499 [faraday_streaming]: https://lostisland.github.io/faraday/usage/streaming [repo]: https://github.com/dleavitt/faraday-typhoeus [license]: LICENSE.md [rubygems]: https://github.com/dleavitt/faraday-typhoeus/blob/main/rubygems faraday-typhoeus-1.1.0/Rakefile000066400000000000000000000002211451630232500164370ustar00rootroot00000000000000# frozen_string_literal: true require 'bundler/gem_tasks' require 'rspec/core/rake_task' RSpec::Core::RakeTask.new(:spec) task default: :spec faraday-typhoeus-1.1.0/bin/000077500000000000000000000000001451630232500155475ustar00rootroot00000000000000faraday-typhoeus-1.1.0/bin/ci-lint000077500000000000000000000001411451630232500170300ustar00rootroot00000000000000#!/usr/bin/env bash set -euo pipefail IFS=$'\n\t' set -vx bundle exec rubocop --format progress faraday-typhoeus-1.1.0/bin/ci-test000077500000000000000000000001151451630232500170420ustar00rootroot00000000000000#!/usr/bin/env bash set -euo pipefail IFS=$'\n\t' set -vx bundle exec rspec faraday-typhoeus-1.1.0/bin/console000077500000000000000000000006171451630232500171430ustar00rootroot00000000000000#!/usr/bin/env ruby # frozen_string_literal: true require 'bundler/setup' require 'faraday' require 'faraday/typhoeus' # You can add fixtures and/or initialization code here to make experimenting # with your gem easier. You can also use a different console, if you like. # (If you use this, don't forget to add pry to your Gemfile!) # require "pry" # Pry.start require 'irb' IRB.start(__FILE__) faraday-typhoeus-1.1.0/bin/setup000077500000000000000000000001361451630232500166350ustar00rootroot00000000000000#!/usr/bin/env bash set -euo pipefail IFS=$'\n\t' set -vx gem install bundler bundle install faraday-typhoeus-1.1.0/bin/test000077500000000000000000000001661451630232500164570ustar00rootroot00000000000000#!/usr/bin/env bash set -euo pipefail IFS=$'\n\t' set -vx bundle exec rubocop -a --format progress bundle exec rspec faraday-typhoeus-1.1.0/faraday-typhoeus.gemspec000066400000000000000000000017161451630232500216360ustar00rootroot00000000000000# frozen_string_literal: true require_relative 'lib/faraday/typhoeus/version' Gem::Specification.new do |spec| spec.name = 'faraday-typhoeus' spec.version = Faraday::Typhoeus::VERSION spec.authors = ['Daniel Leavitt'] spec.email = ['daniel.leavitt@gmail.com'] spec.summary = 'Faraday adapter for Typhoeus' spec.description = 'Faraday adapter for Typhoeus' spec.homepage = 'https://github.com/dleavitt/faraday-typhoeus' spec.license = 'MIT' spec.required_ruby_version = Gem::Requirement.new('>= 2.6.0') spec.metadata['homepage_uri'] = spec.homepage spec.metadata['source_code_uri'] = 'https://github.com/dleavitt/faraday-typhoeus' spec.metadata['changelog_uri'] = 'https://github.com/dleavitt/faraday-typhoeus' spec.metadata['rubygems_mfa_required'] = 'true' spec.files = Dir.glob('lib/**/*') + %w[README.md LICENSE.md] spec.require_paths = ['lib'] spec.add_dependency 'faraday', '~> 2.0' spec.add_dependency 'typhoeus', '~> 1.4' end faraday-typhoeus-1.1.0/lib/000077500000000000000000000000001451630232500155455ustar00rootroot00000000000000faraday-typhoeus-1.1.0/lib/faraday/000077500000000000000000000000001451630232500171545ustar00rootroot00000000000000faraday-typhoeus-1.1.0/lib/faraday/adapter/000077500000000000000000000000001451630232500205745ustar00rootroot00000000000000faraday-typhoeus-1.1.0/lib/faraday/adapter/typhoeus.rb000066400000000000000000000126321451630232500230050ustar00rootroot00000000000000# frozen_string_literal: true require 'faraday' require 'typhoeus' module Faraday class Adapter class Typhoeus < Faraday::Adapter self.supports_parallel = true # Setup Hydra with provided options. # # @example Setup Hydra. # Faraday::Adapter::Typhoeus.setup_parallel_manager # #=> # # # @param (see Typhoeus::Hydra#initialize) # @option (see Typhoeus::Hydra#initialize) # # @return [ Typhoeus::Hydra ] The hydra. def self.setup_parallel_manager(options = {}) ::Typhoeus::Hydra.new(options) end # @param env [Faraday::Env] the environment of the request being processed def call(env) super perform_request env @app.call(env) # Finally, it's good practice to rescue client-specific exceptions (e.g. # Timeout, ConnectionFailed, etc...) and re-raise them as Faraday # Errors. Check `Faraday::Error` for a list of all errors. # # rescue MyAdapterTimeout => e # # Most errors allow you to provide the original exception and optionally (if available) the response, to # # make them available outside of the middleware stack. # raise Faraday::TimeoutError, e # end end private def perform_request(env) if parallel?(env) env[:parallel_manager].queue request(env) else request(env).run end end def request(env) read_body env req = typhoeus_request(env) configure_ssl req, env configure_proxy req, env configure_timeout req, env configure_socket req, env if env[:request][:on_data].is_a?(Proc) yielded = false size = 0 req.on_body do |chunk| if chunk.bytesize.positive? || size.positive? yielded = true size += chunk.bytesize env[:request][:on_data].call(chunk, size) end end req.on_complete do |_resp| env[:request][:on_data].call(+'', 0) unless yielded end end req.on_complete do |resp| if resp.timed_out? env[:typhoeus_timed_out] = true env[:typhoeus_return_message] = resp.return_message unless parallel?(env) raise Faraday::TimeoutError, resp.return_message end elsif resp.response_code.zero? || ((resp.return_code != :ok) && !resp.mock?) env[:typhoeus_connection_failed] = true env[:typhoeus_return_message] = resp.return_message unless parallel?(env) raise Faraday::ConnectionFailed, resp.return_message end end env[:typhoeus_timings] = %i[ appconnect connect namelookup pretransfer redirect starttransfer total ].to_h do |key| [key, resp.public_send("#{key}_time")] end save_response(env, resp.code, resp.body, nil, resp.status_message) do |response_headers| response_headers.parse resp.response_headers end # in async mode, :response is initialized at this point env[:response].finish(env) if parallel?(env) end req end def typhoeus_request(env) opts = { method: env[:method], body: env[:body], headers: env[:request_headers], # https://curl.se/libcurl/c/CURLOPT_ACCEPT_ENCODING.html accept_encoding: '' }.merge(@connection_options) ::Typhoeus::Request.new(env[:url].to_s, opts) end def read_body(env) env[:body] = env[:body].read if env[:body].respond_to? :read end def configure_ssl(req, env) ssl = env[:ssl] verify_p = ssl&.fetch(:verify, true) ssl_verifyhost = verify_p ? 2 : 0 req.options[:ssl_verifyhost] = ssl_verifyhost req.options[:ssl_verifypeer] = verify_p req.options[:sslversion] = ssl[:version] if ssl[:version] req.options[:sslcert] = ssl[:client_cert] if ssl[:client_cert] req.options[:sslkey] = ssl[:client_key] if ssl[:client_key] req.options[:cainfo] = ssl[:ca_file] if ssl[:ca_file] req.options[:capath] = ssl[:ca_path] if ssl[:ca_path] client_cert_passwd_key = %i[client_cert_passwd client_certificate_password].detect { |name| ssl.key?(name) } req.options[:keypasswd] = ssl[client_cert_passwd_key] if client_cert_passwd_key end def configure_proxy(req, env) proxy = env[:request][:proxy] return unless proxy req.options[:proxy] = "#{proxy[:uri].scheme}://#{proxy[:uri].host}:#{proxy[:uri].port}" if proxy[:user] && proxy[:password] req.options[:proxyauth] = :any req.options[:proxyuserpwd] = "#{proxy[:user]}:#{proxy[:password]}" end end def configure_timeout(req, env) env_req = env[:request] req.options[:timeout_ms] = (env_req[:timeout] * 1000).to_i if env_req[:timeout] req.options[:connecttimeout_ms] = (env_req[:open_timeout] * 1000).to_i if env_req[:open_timeout] end def configure_socket(req, env) if (bind = env[:request][:bind]) req.options[:interface] = bind[:host] end end def parallel?(env) !!env[:parallel_manager] end end end end faraday-typhoeus-1.1.0/lib/faraday/typhoeus.rb000066400000000000000000000006251451630232500213640ustar00rootroot00000000000000# frozen_string_literal: true require_relative 'adapter/typhoeus' require_relative 'typhoeus/version' module Faraday # Main Faraday::Typhoeus adapter namespace module Typhoeus # Register adapter so either of the following work # * conn.adapter Faraday::Adapter::Typhoeus # * conn.adapter :typhoeus Faraday::Adapter.register_middleware(typhoeus: Faraday::Adapter::Typhoeus) end end faraday-typhoeus-1.1.0/lib/faraday/typhoeus/000077500000000000000000000000001451630232500210345ustar00rootroot00000000000000faraday-typhoeus-1.1.0/lib/faraday/typhoeus/version.rb000066400000000000000000000001401451630232500230410ustar00rootroot00000000000000# frozen_string_literal: true module Faraday module Typhoeus VERSION = '1.1.0' end end faraday-typhoeus-1.1.0/spec/000077500000000000000000000000001451630232500157315ustar00rootroot00000000000000faraday-typhoeus-1.1.0/spec/faraday/000077500000000000000000000000001451630232500173405ustar00rootroot00000000000000faraday-typhoeus-1.1.0/spec/faraday/adapter/000077500000000000000000000000001451630232500207605ustar00rootroot00000000000000faraday-typhoeus-1.1.0/spec/faraday/adapter/typhoeus_spec.rb000066400000000000000000000231651451630232500242060ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe Faraday::Adapter::Typhoeus do features :request_body_on_query_methods, :reason_phrase_parse, # transparent compression IS supported but tests will fail b/c # webmock is unaware of this # :compression, :streaming, :trace_method # Runs the tests provide by Faraday, according to the features specified above. it_behaves_like 'an adapter' let(:base_url) { 'http://example.com' } let(:adapter) { described_class.new(nil) } let(:request) { Typhoeus::Request.new(base_url) } # TODO: context "when a response is stubbed" describe '#initialize' do let(:request) { adapter.method(:typhoeus_request).call({}) } context 'when no options specified' do let(:adapter) { described_class.new(nil) } it 'defers to curl on accepted encodings' do expect(request.options[:accept_encoding]).to eq('') end end context 'when typhoeus request options specified' do let(:adapter) { described_class.new(nil, { forbid_reuse: true, maxredirs: 1 }) } it 'should set options for request' do expect(request.options[:forbid_reuse]).to be_truthy expect(request.options[:maxredirs]).to eq(1) end end end describe '#perform_request' do let(:env) { {} } context 'when body' do let(:env) { { body: double(read: 'body') } } it 'reads body' do expect(adapter.method(:read_body).call(env)).to eq('body') end end context 'parallel_manager' do context 'when given' do let(:env) { { parallel_manager: double(queue: true), ssl: {}, request: {} } } it 'uses' do adapter.method(:perform_request).call(env) end end context 'when not given' do let(:env) { { method: :get, ssl: {}, request: {} } } it 'falls back to single' do expect(Typhoeus::Request).to receive(:new).and_return(double(options: {}, on_complete: [], run: true)) adapter.method(:perform_request).call(env) end end end end describe '#request' do let(:env) do { url: 'url', method: :get, body: 'body', request_headers: {}, ssl: {}, request: {} } end let(:request) { adapter.method(:request).call(env) } it 'returns request' do expect(request).to be_a(Typhoeus::Request) end it 'sets url' do expect(request.base_url).to eq('url') end it 'sets http method' do expect(request.original_options[:method]).to eq(:get) end it 'sets body' do expect(request.original_options[:body]).to eq('body') end it 'sets headers' do expect(request.original_options[:headers]).to eq({}) end it 'sets on_complete callback' do expect(request.on_complete.size).to eq(1) end end describe '#configure_socket' do let(:env) { { request: { bind: { host: 'interface' } } } } before { adapter.method(:configure_socket).call(request, env) } context 'when host' do it 'sets interface' do expect(request.options[:interface]).to eq('interface') end end end describe '#configure_timeout' do before { adapter.method(:configure_timeout).call(request, env) } context 'when timeout' do let(:env) { { request: { timeout: 1 } } } it 'sets timeout_ms' do expect(request.options[:timeout_ms]).to eq(1000) end end context 'when open_timeout' do let(:env) { { request: { open_timeout: 1 } } } it 'sets connecttimeout_ms' do expect(request.options[:connecttimeout_ms]).to eq(1000) end end end describe '#configure_proxy' do before { adapter.method(:configure_proxy).call(request, env) } context 'when proxy' do let(:env) { { request: { proxy: { uri: double(scheme: 'http', host: 'localhost', port: '3001') } } } } it 'sets proxy' do expect(request.options[:proxy]).to eq('http://localhost:3001') end context 'when username and password' do let(:env) do { request: { proxy: { uri: double(scheme: 'http', host: :a, port: :b), user: 'a', password: 'b' } } } end it 'sets proxyuserpwd' do expect(request.options[:proxyuserpwd]).to eq('a:b') end end end end describe '#configure_ssl' do before { adapter.method(:configure_ssl).call(request, env) } context 'when version' do let(:env) { { ssl: { version: 'a' } } } it 'sets sslversion' do expect(request.options[:sslversion]).to eq('a') end end context 'when client_cert' do let(:env) { { ssl: { client_cert: 'a' } } } it 'sets sslcert' do expect(request.options[:sslcert]).to eq('a') end end context 'when client_key' do let(:env) { { ssl: { client_key: 'a' } } } it 'sets sslkey' do expect(request.options[:sslkey]).to eq('a') end end context 'when ca_file' do let(:env) { { ssl: { ca_file: 'a' } } } it 'sets cainfo' do expect(request.options[:cainfo]).to eq('a') end end context 'when ca_path' do let(:env) { { ssl: { ca_path: 'a' } } } it 'sets capath' do expect(request.options[:capath]).to eq('a') end end context 'when client_cert_passwd' do let(:env) { { ssl: { client_cert_passwd: 'a' } } } it 'sets keypasswd to the value of client_cert_passwd' do expect(request.options[:keypasswd]).to eq('a') end end context 'when client_certificate_password' do let(:env) { { ssl: { client_certificate_password: 'a' } } } it 'sets keypasswd to the value of client_cert_passwd' do expect(request.options[:keypasswd]).to eq('a') end end context 'when no client_cert_passwd' do let(:env) { { ssl: {} } } it 'does not set keypasswd on options' do expect(request.options).not_to have_key :keypasswd end end context 'when verify is false' do let(:env) { { ssl: { verify: false } } } it 'sets ssl_verifyhost to 0' do expect(request.options[:ssl_verifyhost]).to eq(0) end it 'sets ssl_verifypeer to false' do expect(request.options[:ssl_verifypeer]).to be_falsey end end context 'when verify is true' do let(:env) { { ssl: { verify: true } } } it 'sets ssl_verifyhost to 2' do expect(request.options[:ssl_verifyhost]).to eq(2) end it 'sets ssl_verifypeer to true' do expect(request.options[:ssl_verifypeer]).to be_truthy end end end describe '#parallel?' do context 'when parallel_manager' do let(:env) { { parallel_manager: true } } it 'returns true' do expect(adapter.method(:parallel?).call(env)).to be_truthy end end context 'when no parallel_manager' do let(:env) { { parallel_manager: nil } } it 'returns false' do expect(adapter.method(:parallel?).call(env)).to be_falsey end end end context 'requests' do let(:http_method) { :get } let!(:request_stub) { stub_request(http_method, base_url) } let(:conn) do Faraday.new(url: base_url) do |faraday| faraday.adapter :typhoeus end end after do expect(request_stub).to have_been_requested unless request_stub.disabled? end context 'when parallel' do it 'returns a faraday response' do response = nil conn.in_parallel { response = conn.get('/') } expect(response).to be_a(Faraday::Response) end it 'succeeds' do response = nil conn.in_parallel { response = conn.get('/') } expect(response.status).to be(200) end end context 'when not parallel' do it 'returns a faraday response' do expect(conn.get('/')).to be_a(Faraday::Response) end it 'succeeds' do expect(conn.get('/').status).to be(200) end it 'sets timings' do response = conn.get('/') # TODO: make these not-nil after https://github.com/bblimke/webmock/pull/1038 lands expect(response.env.custom_members[:typhoeus_timings]).to eq({ appconnect: nil, connect: nil, namelookup: nil, pretransfer: nil, redirect: nil, starttransfer: nil, total: nil }) end end context 'failed connection' do before do request_stub.to_timeout end context 'when parallel' do it "isn't successful" do response = nil conn.in_parallel { response = conn.get('/') } expect(response.success?).to be_falsey end it 'translates the response code into an error message' do response = nil conn.in_parallel { response = conn.get('/') } expect(response.env[:typhoeus_timed_out]).to be true expect(response.env[:typhoeus_return_message]).to eq('Timeout was reached') end end context 'when not parallel' do it 'raises an error' do expect { conn.get('/') }.to raise_error(Faraday::TimeoutError, 'Timeout was reached') end end end end end faraday-typhoeus-1.1.0/spec/faraday/typhoeus_spec.rb000066400000000000000000000002431451630232500225560ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe Faraday::Typhoeus do it 'has a version number' do expect(Faraday::Typhoeus::VERSION).to be_a(String) end end faraday-typhoeus-1.1.0/spec/spec_helper.rb000066400000000000000000000010601451630232500205440ustar00rootroot00000000000000# frozen_string_literal: true require 'rack' require 'faraday/typhoeus' # This is the magic bit. It requires a tests suite from the Faraday gem that you can run against your adapter require 'faraday_specs_setup' RSpec.configure do |config| # Enable flags like --only-failures and --next-failure config.example_status_persistence_file_path = '.rspec_status' # Disable RSpec exposing methods globally on `Module` and `main` config.disable_monkey_patching! config.expect_with :rspec do |c| c.syntax = :expect end config.order = :random end