class HTTP::Client::Request
Constants
- DEFAULT_HEADERS
- REDIRECT_WITH_GET
- REDIRECT_WITH_ORIGINAL
- VALID_PARAMETERS
- VALID_REDIRECT_CODES
- VALID_SSL_VERIFICATIONS
- VALID_VERBS
Public Class Methods
Create a new HTTP
Client
Request
.
@param [Symbol] verb HTTP
verb, one of :get, :head, :put, :post, :delete, :options, :trace. @param [String or URI] uri Remote URI. @param [Hash] args Options, see below. @option args [Hash] headers Net::HTTP headers, in key-value pairs. @option args [Hash] query Net::HTTP query-string in key-value pairs. @option args [Hash] files Multi-part file uploads, in key-value pairs of name & path or name & File object. @option args [String] body Request
body. @option args [Hash] auth Basic-Auth hash. Requires :username and :password. @option args [Integer] timeout Fixed timeout for connection, read and ssl handshake in seconds. @option args [Integer] open_timeout Connection timeout in seconds. @option args [Integer] read_timeout Read timeout in seconds. @option args [Integer] ssl_timeout SSL handshake timeout in seconds. @option args [Integer] max_redirects Max redirect follow, default: 0 @option args [Integer] ssl_verify OpenSSL verification, SSL_VERIFY_PEER (default) or SSL_VERIFY_NONE. @option args [HTTP::CookieJar] jar Optional cookie jar to use. Relies on HTTP::CookieJar from http-cookie gem.
@return [HTTP::Client::Request]
@example Retrieve a page using GET.
request = HTTP::Client::Request.new(:get, "http://www.example.org/", query: {q: "search something"}) response = request.execute
@example Handle redirects.
request = HTTP::Client::Request.new(:get, "http://www.example.org/", max_redirects: 3) response = request.execute
@example Perform request and return result in one go.
response = HTTP::Client.get("http://www.example.org/", max_redirects: 3)
@example Upload a few files in a POST request.
request = HTTP::Client::Request.new( :post, "http://www.example.org/", files: {"cats" => "cats.jpg", "dogs" => "dogs.jpg"}, query: {title: "cute pics"} ) response = request.execute
@example Pass in an external cookie jar.
jar = HTTP::CookieJar.new jar.load("mycookies.cky") response = HTTP::Client.get("http://www.example.org/", jar: jar)
# File lib/http/client.rb, line 84 def initialize verb, uri, args = {} args.each do |k, v| raise Error::Argument, "unknown argument #{k}" unless VALID_PARAMETERS.include?(k.to_s) end uri = parse_uri!(uri) @delegate = create_request_delegate(verb, uri, args) if body = args[:body] raise Error::Argument, "#{verb} cannot have body" unless @delegate.class.const_get(:REQUEST_HAS_BODY) @delegate.body = body end # if auth is passed as arguments. if auth = args[:auth] @delegate.basic_auth(auth.fetch(:username), auth.fetch(:password)) end # if auth is passed in uri. if uri.user && uri.password @delegate.basic_auth(uri.user, uri.password) end @open_timeout = HTTP::Client.open_timeout @read_timeout = HTTP::Client.read_timeout @ssl_timeout = HTTP::Client.ssl_timeout # generic timeout if timeout = args[:timeout] @open_timeout = timeout @read_timeout = timeout @ssl_timeout = timeout end # overrides @open_timeout = args[:open_timeout] if args[:open_timeout] @read_timeout = args[:read_timeout] if args[:read_timeout] @ssl_timeout = args[:ssl_timeout] if args[:ssl_timeout] @max_redirects = args.fetch(:max_redirects, 0) @ssl_verify = args.fetch(:ssl_verify, SSL_VERIFY_PEER) @jar = args.fetch(:jar, HTTP::CookieJar.new) end
Public Instance Methods
Executes a request.
@return [HTTP::Client::Response]
# File lib/http/client.rb, line 132 def execute last_effective_uri = uri cookie = HTTP::Cookie.cookie_value(@jar.cookies(uri)) if cookie && !cookie.empty? @delegate.add_field('Cookie', cookie) end response = request!(uri, @delegate) @jar.parse(response['set-cookie'].to_s, uri) redirects = 0 while redirects < @max_redirects && VALID_REDIRECT_CODES.include?(response.code.to_i) redirects += 1 last_effective_uri = parse_uri! response['location'] redirect_delegate = redirect_to(last_effective_uri, response.code.to_i) cookie = HTTP::Cookie.cookie_value(@jar.cookies(last_effective_uri)) if cookie && !cookie.empty? redirect_delegate.add_field('Cookie', cookie) end response = request!(last_effective_uri, redirect_delegate) @jar.parse(response['set-cookie'].to_s, last_effective_uri) end Response.new(response, last_effective_uri) end
Private Instance Methods
# File lib/http/client.rb, line 185 def create_request_delegate verb, uri, args klass = find_delegate_class(verb) headers = DEFAULT_HEADERS.merge(args.fetch(:headers, {})) files = args[:files] qs = args[:query] uri = uri.dup delegate = nil if files raise Error::Argument, "#{verb} cannot have body" unless klass.const_get(:REQUEST_HAS_BODY) multipart = Multipart.new(files, qs) delegate = klass.new(uri, headers) delegate.content_type = multipart.content_type delegate.body = multipart.body elsif qs if klass.const_get(:REQUEST_HAS_BODY) delegate = klass.new(uri, headers) delegate.set_form_data(qs) else uri.query = URI.encode_www_form(qs) delegate = klass.new(uri, headers) end else delegate = klass.new(uri, headers) end delegate end
# File lib/http/client.rb, line 263 def find_delegate_class verb if VALID_VERBS.include?(verb) verb else find_verb_class(verb.to_s) end end
# File lib/http/client.rb, line 271 def find_verb_class string case string when /^get$/i then GET when /^head$/i then HEAD when /^put$/i then PUT when /^post$/i then POST when /^delete$/i then DELETE else raise Error::Argument, "Invalid verb #{string}" end end
# File lib/http/client.rb, line 166 def parse_uri! uri uri = uri.kind_of?(URI) ? uri : URI.parse(uri) case uri when URI::HTTP, URI::HTTPS raise Error::URI, "Invalid URI #{uri}" if uri.host.nil? uri when URI::Generic if @delegate && @delegate.uri @delegate.uri.dup.tap {|s| s += uri } else raise Error::URI, "Invalid URI #{uri}" end else raise Error::URI, "Invalid URI #{uri}" end rescue URI::InvalidURIError => e raise Error::URI, "Invalid URI #{uri}" end
# File lib/http/client.rb, line 239 def redirect_to uri, code # NOTE request-uri with query string is not preserved. case code when *REDIRECT_WITH_GET GET.new(uri, {}).tap do |r| @delegate.each_header do |field, value| next if field.downcase == 'host' r[field] = value end end when *REDIRECT_WITH_ORIGINAL @delegate.class.new(uri, {}).tap do |r| @delegate.each_header do |field, value| next if field.downcase == 'host' r[field] = value end r.body = @delegate.body end else raise Error, "response #{code} should not result in redirection." end end
# File lib/http/client.rb, line 215 def request! uri, delegate http = Net::HTTP.new(uri.host, uri.port, :ENV) if uri.scheme == 'https' http.use_ssl = true http.verify_mode = @ssl_verify end http.open_timeout = @open_timeout if @open_timeout http.read_timeout = @read_timeout if @read_timeout http.ssl_timeout = @ssl_timeout if @ssl_timeout response = http.request(delegate) http.finish if http.started? response rescue URI::Error => e raise Error::URI.new(e.message, e) rescue Zlib::Error => e raise Error::Zlib.new(e.message, e) rescue Timeout::Error => e raise Error::Timeout.new(e.message, e) rescue Net::HTTPBadResponse, Net::HTTPHeaderSyntaxError, Net::ProtocolError => e raise Error::Transport.new(e.message, e) end
# File lib/http/client.rb, line 162 def uri @delegate.uri end