mirror of
https://github.com/rest-client/rest-client.git
synced 2022-11-09 13:49:40 -05:00
Add a lot of YARD docs to various classes.
Also switch to Markdown as the markup language, rather than rdoc.
This commit is contained in:
parent
3001348c8a
commit
f54f14398d
12 changed files with 403 additions and 128 deletions
|
@ -1,3 +1,4 @@
|
|||
--markup markdown
|
||||
-
|
||||
history.md
|
||||
LICENSE
|
||||
|
|
5
Rakefile
5
Rakefile
|
@ -123,3 +123,8 @@ end
|
|||
require 'yard'
|
||||
YARD::Rake::YardocTask.new do |t|
|
||||
end
|
||||
|
||||
desc 'Run YARD documentation server, reload with changes'
|
||||
task :yardserver do
|
||||
sh 'yard server --reload'
|
||||
end
|
||||
|
|
|
@ -18,47 +18,88 @@ require File.dirname(__FILE__) + '/restclient/windows'
|
|||
|
||||
# This module's static methods are the entry point for using the REST client.
|
||||
#
|
||||
# # GET
|
||||
# xml = RestClient.get 'http://example.com/resource'
|
||||
# jpg = RestClient.get 'http://example.com/resource', :accept => 'image/jpg'
|
||||
# These helpers provide a concise way to issue simple requests with headers. If
|
||||
# you need to set other options on a request (e.g. timeout, SSL options, etc.)
|
||||
# then use {RestClient::Request.execute}, which supports all of these options.
|
||||
#
|
||||
# # authentication and SSL
|
||||
# RestClient.get 'https://user:password@example.com/private/resource'
|
||||
# The {.get}, {.head}, {.delete}, and {.options} methods take a URL String and
|
||||
# optional HTTP headers Hash.
|
||||
#
|
||||
# # POST or PUT with a hash sends parameters as a urlencoded form body
|
||||
# RestClient.post 'http://example.com/resource', :param1 => 'one'
|
||||
# The {.post}, {.put}, and {.patch} methods take a URL String, a payload, and
|
||||
# an optional HTTP headers Hash.
|
||||
#
|
||||
# # nest hash parameters
|
||||
# RestClient.post 'http://example.com/resource', :nested => { :param1 => 'one' }
|
||||
# All of these helpers are just thin wrappers around
|
||||
# {RestClient::Request.execute RestClient::Request.execute}.
|
||||
#
|
||||
# # POST and PUT with raw payloads
|
||||
# RestClient.post 'http://example.com/resource', 'the post body', :content_type => 'text/plain'
|
||||
# RestClient.post 'http://example.com/resource.xml', xml_doc
|
||||
# RestClient.put 'http://example.com/resource.pdf', File.read('my.pdf'), :content_type => 'application/pdf'
|
||||
#
|
||||
# # DELETE
|
||||
# RestClient.delete 'http://example.com/resource'
|
||||
# ```ruby
|
||||
# # Simple GET request, potentially with headers.
|
||||
# RestClient.get('http://example.com/')
|
||||
# # => <RestClient::Response 200 "<!doctype h...">
|
||||
#
|
||||
# # retreive the response http code and headers
|
||||
# res = RestClient.get 'http://example.com/some.jpg'
|
||||
# res.code # => 200
|
||||
# res.headers[:content_type] # => 'image/jpg'
|
||||
# RestClient.get('http://example.com/resource', accept: 'image/jpg')
|
||||
#
|
||||
# # HEAD
|
||||
# RestClient.head('http://example.com').headers
|
||||
# RestClient.get('http://example.com', 'If-Modified-Since': 'Sat, 10 Aug 2013 10:23:00 GMT')
|
||||
# # raises RestClient::NotModified: 304 Not Modified
|
||||
#
|
||||
# # Basic authentication and SSL
|
||||
# RestClient.get 'https://user:password@example.com/private/resource'
|
||||
#
|
||||
# # POST or PUT with a hash sends parameters as a urlencoded form body
|
||||
# RestClient.post 'http://example.com/resource', :param1 => 'one'
|
||||
#
|
||||
# # nest hash parameters
|
||||
# RestClient.post 'http://example.com/resource', :nested => { :param1 => 'one' }
|
||||
#
|
||||
# # POST and PUT with raw payloads
|
||||
# RestClient.post 'http://example.com/resource', 'the post body', :content_type => 'text/plain'
|
||||
# RestClient.post 'http://example.com/resource.xml', xml_doc
|
||||
# RestClient.put 'http://example.com/resource.pdf', File.read('my.pdf'), :content_type => 'application/pdf'
|
||||
#
|
||||
# # DELETE
|
||||
# RestClient.delete 'http://example.com/resource'
|
||||
#
|
||||
# # Retrieve the response http code and headers
|
||||
# res = RestClient.get 'http://example.com/some.jpg'
|
||||
# res.code # => 200
|
||||
# res.headers[:content_type] # => 'image/jpg'
|
||||
#
|
||||
# # HEAD
|
||||
# RestClient.head('http://example.com').headers
|
||||
# ```
|
||||
#
|
||||
# To use with a proxy, just set RestClient.proxy to the proper http proxy:
|
||||
#
|
||||
# RestClient.proxy = "http://proxy.example.com/"
|
||||
# RestClient.proxy = "http://proxy.example.com/"
|
||||
#
|
||||
# Or inherit the proxy from the environment:
|
||||
# Proxies can also be set via the `http_proxy`/`https_proxy` environment
|
||||
# variables, or with the `:proxy` option on an individual {RestClient::Request}.
|
||||
#
|
||||
# RestClient.proxy = ENV['http_proxy']
|
||||
# For live tests of RestClient, try using https://httpbin.org/. This service
|
||||
# echoes back information about the HTTP request.
|
||||
#
|
||||
# For live tests of RestClient, try using http://rest-test.heroku.com, which echoes back information about the rest call:
|
||||
#
|
||||
# >> RestClient.put 'http://rest-test.heroku.com/resource', :foo => 'baz'
|
||||
# => "PUT http://rest-test.heroku.com/resource with a 7 byte payload, content type application/x-www-form-urlencoded {\"foo\"=>\"baz\"}"
|
||||
# r = RestClient.post('https://httpbin.org/post', foo: 'bar')
|
||||
# # => <RestClient::Response 200 "{\n \"args\":...">
|
||||
# puts r.body
|
||||
# {
|
||||
# "args": {},
|
||||
# "data": "",
|
||||
# "files": {},
|
||||
# "form": {
|
||||
# "foo": "bar"
|
||||
# },
|
||||
# "headers": {
|
||||
# "Accept": "*/*",
|
||||
# "Accept-Encoding": "gzip;q=1.0,deflate;q=0.6,identity;q=0.3",
|
||||
# "Connection": "close",
|
||||
# "Content-Length": "7",
|
||||
# "Content-Type": "application/x-www-form-urlencoded",
|
||||
# "Host": "httpbin.org",
|
||||
# "User-Agent": "rest-client/2.1.0 (linux-gnu x86_64) ruby/2.3.3p222"
|
||||
# },
|
||||
# "json": null,
|
||||
# "url": "https://httpbin.org/post"
|
||||
# }
|
||||
#
|
||||
module RestClient
|
||||
|
||||
|
@ -96,6 +137,10 @@ module RestClient
|
|||
@proxy ||= nil
|
||||
end
|
||||
|
||||
# Set a proxy URL to use for all requests.
|
||||
#
|
||||
# @param value [String] The proxy URL.
|
||||
#
|
||||
def self.proxy=(value)
|
||||
@proxy = value
|
||||
@proxy_set = true
|
||||
|
@ -113,12 +158,21 @@ module RestClient
|
|||
# Setup the log for RestClient calls.
|
||||
# Value should be a logger but can can be stdout, stderr, or a filename.
|
||||
# You can also configure logging by the environment variable RESTCLIENT_LOG.
|
||||
#
|
||||
# @param log [Logger, #<<, String] The log to write to. See {.create_log}
|
||||
#
|
||||
def self.log= log
|
||||
@@log = create_log log
|
||||
end
|
||||
|
||||
# Create a log that respond to << like a logger
|
||||
# param can be 'stdout', 'stderr', a string (then we will log to that file) or a logger (then we return it)
|
||||
# Create a log that responds to `<<` like a Logger.
|
||||
#
|
||||
# @param param [Logger, #<<, String, nil] The log to write to. Should be a
|
||||
# Logger, IO, or other object with a `<<` method. If param is a String, it
|
||||
# will be treated as a filename and that file will be opened as a log file.
|
||||
# The special Strings `"stdout"` and `"stderr"` will log to `STDOUT` and
|
||||
# `STDERR`.
|
||||
#
|
||||
def self.create_log param
|
||||
if param
|
||||
if param.is_a? String
|
||||
|
@ -158,10 +212,16 @@ module RestClient
|
|||
|
||||
@@log = nil
|
||||
|
||||
def self.log # :nodoc:
|
||||
# The RestClient global logger. This will be used for all requests unless a
|
||||
# `:log` option is set on the individual request.
|
||||
#
|
||||
# @see log=
|
||||
#
|
||||
def self.log
|
||||
@@env_log || @@log
|
||||
end
|
||||
|
||||
# Array of procs executed prior to each request.
|
||||
@@before_execution_procs = []
|
||||
|
||||
# Add a Proc to be called before each request in executed.
|
||||
|
@ -176,7 +236,8 @@ module RestClient
|
|||
@@before_execution_procs = []
|
||||
end
|
||||
|
||||
def self.before_execution_procs # :nodoc:
|
||||
# Array of procs executed prior to each request.
|
||||
def self.before_execution_procs
|
||||
@@before_execution_procs
|
||||
end
|
||||
|
||||
|
|
|
@ -3,6 +3,17 @@ require 'http-cookie'
|
|||
|
||||
module RestClient
|
||||
|
||||
# The AbstractResponse module provides common functionality for RestClient
|
||||
# responses. It is included by {RestClient::Response} and
|
||||
# {RestClient::RawResponse}.
|
||||
#
|
||||
# Classes that include AbstractResponse should call {response_set_vars} as
|
||||
# part of their `#initialize` method.
|
||||
#
|
||||
# Ideally this would have been a parent class, not a module. But the original
|
||||
# RestClient API made {Response} be a subclass of `String`, so we are
|
||||
# stuck with that for backwards compatibility.
|
||||
#
|
||||
module AbstractResponse
|
||||
|
||||
attr_reader :net_http_res, :request, :start_time, :end_time, :duration
|
||||
|
@ -12,10 +23,17 @@ module RestClient
|
|||
end
|
||||
|
||||
# Logger from the request, potentially nil.
|
||||
#
|
||||
# @see Request#log
|
||||
#
|
||||
def log
|
||||
request.log
|
||||
end
|
||||
|
||||
# Write log information about the response.
|
||||
#
|
||||
# @return [void]
|
||||
#
|
||||
def log_response
|
||||
return unless log
|
||||
|
||||
|
@ -27,21 +45,39 @@ module RestClient
|
|||
end
|
||||
|
||||
# HTTP status code
|
||||
#
|
||||
# @return [Integer]
|
||||
#
|
||||
def code
|
||||
@code ||= @net_http_res.code.to_i
|
||||
end
|
||||
|
||||
# An array of prior responses in the redirection chain, if any. If
|
||||
# RestClient followed any redirects, this provides a way to see each
|
||||
# individual response in the chain.
|
||||
#
|
||||
# @return [Array<Response>]
|
||||
#
|
||||
# @see Request#redirection_history
|
||||
#
|
||||
def history
|
||||
@history ||= request.redirection_history || []
|
||||
end
|
||||
|
||||
# A hash of the headers, beautified with symbols and underscores.
|
||||
# e.g. "Content-type" will become :content_type.
|
||||
# e.g. `"Content-type"` will become `:content_type`.
|
||||
#
|
||||
# @see beautify_headers
|
||||
#
|
||||
# @return [Hash]
|
||||
#
|
||||
def headers
|
||||
@headers ||= AbstractResponse.beautify_headers(@net_http_res.to_hash)
|
||||
end
|
||||
|
||||
# The raw headers.
|
||||
#
|
||||
# @return [Hash]
|
||||
def raw_headers
|
||||
@raw_headers ||= @net_http_res.to_hash
|
||||
end
|
||||
|
@ -49,6 +85,9 @@ module RestClient
|
|||
# @param [Net::HTTPResponse] net_http_res
|
||||
# @param [RestClient::Request] request
|
||||
# @param [Time] start_time
|
||||
#
|
||||
# @return [void]
|
||||
#
|
||||
def response_set_vars(net_http_res, request, start_time)
|
||||
@net_http_res = net_http_res
|
||||
@request = request
|
||||
|
@ -67,9 +106,9 @@ module RestClient
|
|||
|
||||
# Hash of cookies extracted from response headers.
|
||||
#
|
||||
# NB: This will return only cookies whose domain matches this request, and
|
||||
# may not even return all of those cookies if there are duplicate names.
|
||||
# Use the full cookie_jar for more nuanced access.
|
||||
# **Note:** This will return only cookies whose domain matches this
|
||||
# request, and may not even return all of those cookies if there are
|
||||
# duplicate names. Use the full cookie_jar for more nuanced access.
|
||||
#
|
||||
# @see #cookie_jar
|
||||
#
|
||||
|
@ -104,11 +143,20 @@ module RestClient
|
|||
#
|
||||
# For 20x status codes: return the response itself
|
||||
#
|
||||
# For 30x status codes:
|
||||
# 301, 302, 307: redirect GET / HEAD if there is a Location header
|
||||
# 303: redirect, changing method to GET, if there is a Location header
|
||||
# For 30x status codes, if there is a `Location` header and we have not yet
|
||||
# reached {Request#max_redirects}:
|
||||
#
|
||||
# For all other responses, raise a response exception
|
||||
# - 301, 302, 307: redirect GET / HEAD requests
|
||||
# - 303: redirect, changing method to GET
|
||||
#
|
||||
# For all other responses, raise a response exception, a subclass of
|
||||
# {ExceptionWithResponse} corresponding to the HTTP status code.
|
||||
#
|
||||
# For example, HTTP 404 => {RestClient::NotFound RestClient::NotFound}
|
||||
#
|
||||
# @raise [ExceptionWithResponse] for non-20x status codes, the exception
|
||||
# from {RestClient::Exceptions::EXCEPTIONS_MAP} based on
|
||||
# {RestClient::STATUSES} will be thrown.
|
||||
#
|
||||
def return!(&block)
|
||||
case code
|
||||
|
@ -130,11 +178,13 @@ module RestClient
|
|||
end
|
||||
end
|
||||
|
||||
# @deprecated Use {code} instead.
|
||||
def to_i
|
||||
warn('warning: calling Response#to_i is not recommended')
|
||||
warn('warning: calling Response#to_i is deprecated. Use .code instead.')
|
||||
super
|
||||
end
|
||||
|
||||
# @return [String]
|
||||
def description
|
||||
"#{code} #{STATUSES[code]} | #{(headers[:content_type] || '').gsub(/;.*$/, '')} #{size} bytes\n"
|
||||
end
|
||||
|
|
|
@ -2,18 +2,26 @@ module RestClient
|
|||
|
||||
# Hash of HTTP status code => message.
|
||||
#
|
||||
# 1xx: Informational - Request received, continuing process
|
||||
# 2xx: Success - The action was successfully received, understood, and
|
||||
# accepted
|
||||
# 3xx: Redirection - Further action must be taken in order to complete the
|
||||
# request
|
||||
# 4xx: Client Error - The request contains bad syntax or cannot be fulfilled
|
||||
# 5xx: Server Error - The server failed to fulfill an apparently valid
|
||||
# request
|
||||
# ### HTTP status code families:
|
||||
#
|
||||
# - 1xx: Informational --- Request received, continuing process
|
||||
# - 2xx: Success --- The action was successfully received, understood, and
|
||||
# accepted
|
||||
# - 3xx: Redirection --- Further action must be taken in order to complete
|
||||
# the request
|
||||
# - 4xx: Client Error --- The request contains bad syntax or cannot be
|
||||
# fulfilled
|
||||
# - 5xx: Server Error --- The server failed to fulfill an apparently valid
|
||||
# request
|
||||
#
|
||||
# This hash is used to populate all of the individual response exception
|
||||
# classes, which are collected in {RestClient::Exceptions::EXCEPTIONS_MAP}.
|
||||
#
|
||||
# @see
|
||||
# http://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml
|
||||
#
|
||||
# **TODO:** Move these out of the top-level namespace and into {Exceptions}.
|
||||
#
|
||||
STATUSES = {100 => 'Continue',
|
||||
101 => 'Switching Protocols',
|
||||
102 => 'Processing', #WebDAV
|
||||
|
@ -84,6 +92,11 @@ module RestClient
|
|||
511 => 'Network Authentication Required', # RFC6585
|
||||
}
|
||||
|
||||
# This Hash contains a mapping of aliases for the canonical HTTP status code
|
||||
# classes that are preserved for backwards compatibility. For example,
|
||||
# `RestClient::ResourceNotFound` is an alias for `RestClient::NotFound`.
|
||||
#
|
||||
# **TODO:** Move this out of the top-level namespace and into {Exceptions}.
|
||||
STATUSES_COMPATIBILITY = {
|
||||
# The RFCs all specify "Not Found", but "Resource Not Found" was used in
|
||||
# earlier RestClient releases.
|
||||
|
@ -101,16 +114,22 @@ module RestClient
|
|||
|
||||
|
||||
# This is the base RestClient exception class. Rescue it if you want to
|
||||
# catch any exception that your request might raise
|
||||
# You can get the status code by e.http_code, or see anything about the
|
||||
# response via e.response.
|
||||
# For example, the entire result body (which is
|
||||
# probably an HTML error page) is e.response.
|
||||
# catch any exception that your request might raise. Note that the underlying
|
||||
# network and socket libraries may raise other exceptions.
|
||||
#
|
||||
# You can get the status code with {#http_code}, or see anything about the
|
||||
# response via {#response}.
|
||||
#
|
||||
# For more detailed information from the response, just call the
|
||||
# corresponding methods on the response object (e.g. `e.response.history`).
|
||||
#
|
||||
class Exception < RuntimeError
|
||||
attr_accessor :response
|
||||
attr_accessor :original_exception
|
||||
attr_writer :message
|
||||
|
||||
# @param response [RestClient::Response, RestClient::RawResponse]
|
||||
#
|
||||
def initialize response = nil, initial_response_code = nil
|
||||
@response = response
|
||||
@message = nil
|
||||
|
@ -126,10 +145,14 @@ module RestClient
|
|||
end
|
||||
end
|
||||
|
||||
# @see Response#headers
|
||||
# @return [Hash, nil]
|
||||
def http_headers
|
||||
@response.headers if @response
|
||||
end
|
||||
|
||||
# @see Response#body
|
||||
# @return [String, nil]
|
||||
def http_body
|
||||
@response.body if @response
|
||||
end
|
||||
|
@ -169,7 +192,9 @@ module RestClient
|
|||
# http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html
|
||||
#
|
||||
module Exceptions
|
||||
# Map http status codes to the corresponding exception class
|
||||
# Map http status codes to the corresponding exception class.
|
||||
# This Hash is populated when the library is loaded, so values won't appear
|
||||
# in the YARD documentation.
|
||||
EXCEPTIONS_MAP = {}
|
||||
end
|
||||
|
||||
|
|
|
@ -10,6 +10,9 @@ rescue LoadError
|
|||
end
|
||||
|
||||
module RestClient
|
||||
|
||||
# The Payload module contains several different classes used to process and
|
||||
# represent different types of HTTP bodies / payloads.
|
||||
module Payload
|
||||
extend self
|
||||
|
||||
|
@ -56,6 +59,7 @@ module RestClient
|
|||
end
|
||||
end
|
||||
|
||||
# The base class for all the Payload classes.
|
||||
class Base
|
||||
def initialize(params)
|
||||
build_stream(params)
|
||||
|
|
|
@ -29,10 +29,20 @@ module RestClient
|
|||
RUBY_ENGINE == 'jruby'
|
||||
end
|
||||
|
||||
# Return the host architecture and CPU from `RbConfig::CONFIG`.
|
||||
#
|
||||
# @return [String]
|
||||
def self.architecture
|
||||
"#{RbConfig::CONFIG['host_os']} #{RbConfig::CONFIG['host_cpu']}"
|
||||
end
|
||||
|
||||
# Return information about the ruby version from `RUBY_ENGINE`,
|
||||
# `RUBY_VERSION`, and `RUBY_PATCHLEVEL`.
|
||||
#
|
||||
# When running in jruby, also return the jruby version.
|
||||
#
|
||||
# @return [String]
|
||||
#
|
||||
def self.ruby_agent_version
|
||||
case RUBY_ENGINE
|
||||
when 'jruby'
|
||||
|
@ -42,6 +52,17 @@ module RestClient
|
|||
end
|
||||
end
|
||||
|
||||
# Return a reasonable string for the `User-Agent` HTTP header.
|
||||
#
|
||||
# @example
|
||||
# "rest-client/2.1.0 (linux-gnu x86_64) ruby/2.3.3p222"
|
||||
#
|
||||
# @return [String]
|
||||
#
|
||||
# @see VERSION RestClient::VERSION
|
||||
# @see .architecture
|
||||
# @see .ruby_agent_version
|
||||
#
|
||||
def self.default_user_agent
|
||||
"rest-client/#{VERSION} (#{architecture}) #{ruby_agent_version}"
|
||||
end
|
||||
|
|
|
@ -1,14 +1,35 @@
|
|||
module RestClient
|
||||
# The response from RestClient on a raw request looks like a string, but is
|
||||
# actually one of these. 99% of the time you're making a rest call all you
|
||||
# care about is the body, but on the occassion you want to fetch the
|
||||
# headers you can:
|
||||
|
||||
# {RawResponse} is used to represent RestClient responses when
|
||||
# `:raw_response => true` is passed to the {Request}.
|
||||
#
|
||||
# RestClient.get('http://example.com').headers[:content_type]
|
||||
# Instead of processing the response data in various ways, the `RawResponse`
|
||||
# downloads the response body to a `Tempfile` and does little processing of
|
||||
# the underlying `Net::HTTPResponse` object. This is especially useful for
|
||||
# large downloads when you don't want to load the entire response into
|
||||
# memory.
|
||||
#
|
||||
# Use {#file} to access the `Tempfile` containing the raw response body. The
|
||||
# file path is accessible at `.file.path`.
|
||||
#
|
||||
# **Note that like all `Tempfile` objects, the {#file} will be deleted when
|
||||
# the object is dereferenced.**
|
||||
#
|
||||
# This class brings in all the common functionality from {AbstractResponse},
|
||||
# such as {AbstractResponse.headers}, etc.
|
||||
#
|
||||
# @example
|
||||
#
|
||||
# r = RestClient::Request.execute(method: :get, url: 'http://example.com', raw_response: true)
|
||||
# r.code
|
||||
# # => 200
|
||||
# puts r.file.inspect
|
||||
# # => #<Tempfile:/tmp/rest-client.20170102-15213-b8kgcj>
|
||||
# r.file.path
|
||||
# # => "/tmp/rest-client.20170102-15213-b8kgcj"
|
||||
# r.size
|
||||
# # => 1270
|
||||
#
|
||||
# In addition, if you do not use the response as a string, you can access
|
||||
# a Tempfile object at res.file, which contains the path to the raw
|
||||
# downloaded request body.
|
||||
class RawResponse
|
||||
|
||||
include AbstractResponse
|
||||
|
@ -36,11 +57,18 @@ module RestClient
|
|||
body
|
||||
end
|
||||
|
||||
# Read the response body from {#file} into memory and return as a String.
|
||||
#
|
||||
# @return [String]
|
||||
#
|
||||
def body
|
||||
@file.rewind
|
||||
@file.read
|
||||
end
|
||||
|
||||
# Return the response body file size.
|
||||
#
|
||||
# @return [Integer]
|
||||
def size
|
||||
file.size
|
||||
end
|
||||
|
|
|
@ -15,24 +15,27 @@ module RestClient
|
|||
# call it directly if you'd like to use a method not supported by the
|
||||
# main API.
|
||||
#
|
||||
# @example using {.execute} class method:
|
||||
# @example Using {.execute} class method:
|
||||
# RestClient::Request.execute(method: :head, url: 'http://example.com')
|
||||
#
|
||||
# @example initializing {#initialize} and then calling {#execute}:
|
||||
# @example Initializing {#initialize} and then calling {#execute}:
|
||||
# req = RestClient::Request.new(method: :get, url: 'http://example.com', timeout: 5)
|
||||
# req.execute
|
||||
#
|
||||
# The `:method` and `:url` parameters are required. All others are optional.
|
||||
#
|
||||
# @deprecated *Note:*
|
||||
# The RestClient API has a very ugly misfeature that dates to the original
|
||||
# design, where certain options are destructively pulled out of the
|
||||
# `:headers` hash that normally contains HTTP request headers. This is
|
||||
# because in the top-level helper shortcuts like {RestClient.get}, the only
|
||||
# hash argument permitted is the headers hash, so there is no place to put
|
||||
# options. For example, while it is currently allowed to pass options like
|
||||
# `:params` or `:cookies` as keys inside the `:headers` hash, this is
|
||||
# strongly discouraged.
|
||||
# **See {#initialize} for the full list of available options.**
|
||||
#
|
||||
# **Deprecation note:**
|
||||
# Certain options are accepted as keys in the headers hash, but doing so is
|
||||
# deprecated. This misfeature in the RestClient API dates to the original
|
||||
# design, where certain options are destructively pulled out of the
|
||||
# `:headers` hash that normally contains HTTP request headers. This is
|
||||
# because in the top-level helper shortcuts like {RestClient.get}, the only
|
||||
# hash argument permitted is the headers hash, so there is no place to put
|
||||
# options. For example, while it is currently allowed to pass options like
|
||||
# `:params` or `:cookies` as keys inside the `:headers` hash, this is
|
||||
# strongly discouraged.
|
||||
#
|
||||
class Request
|
||||
|
||||
|
@ -46,12 +49,18 @@ module RestClient
|
|||
|
||||
# Shorthand for initializing a Request and executing it.
|
||||
#
|
||||
# RestClient::Request.execute is a great way to pass complex options.
|
||||
# `RestClient::Request.execute` is the recommended way to pass complex
|
||||
# options. It is shorthand for `RestClient::Request.new(args).execute`.
|
||||
#
|
||||
# For example:
|
||||
# RestClient::Request.execute(method: get, url: 'http://example.com', timeout: 5)
|
||||
# @example
|
||||
# RestClient::Request.execute(method: :get, url: 'http://example.com', timeout: 5)
|
||||
#
|
||||
# @see RestClient::Request
|
||||
# @example
|
||||
# RestClient::Request.execute(method: :get, url: 'http://httpbin.org/redirect/2', max_redirects: 1)
|
||||
#
|
||||
# @see RestClient::Request#initialize
|
||||
#
|
||||
# @return [RestClient::Response, RestClient::RawResponse]
|
||||
#
|
||||
def self.execute(args, & block)
|
||||
new(args).execute(& block)
|
||||
|
@ -71,15 +80,15 @@ module RestClient
|
|||
#
|
||||
# @param [Hash] args
|
||||
#
|
||||
# @option args [String] :url *Required.* The HTTP URL to request.
|
||||
# @option args [String, Symbol] :method *Required.* The HTTP request method
|
||||
# or verb, such as "GET", "HEAD", or "POST".
|
||||
# @option args [String] :url **Required.** The HTTP URL to request.
|
||||
# @option args [String, Symbol] :method **Required.** The HTTP request method
|
||||
# or verb, such as `"GET"`, `"HEAD"`, or `"POST"`.
|
||||
#
|
||||
# @option args [Hash] :headers The HTTP request headers. Keys may be
|
||||
# Symbol or String. Symbol keys will be converted to String header names
|
||||
# by {#stringify_headers}. For backwards compatibility, this Hash
|
||||
# recognizes certain keys that will be pulled out as options, but relying
|
||||
# on this is deprecated and strongly discouraged.
|
||||
# on this behavior is deprecated and strongly discouraged.
|
||||
# @option args :cookies [HTTP::CookieJar, Hash{String, Symbol => String},
|
||||
# Array<HTTP::Cookie>] The cookies to be sent with the request. This can
|
||||
# be passed as a Hash, an array of HTTP::Cookie objects, or as a full
|
||||
|
@ -121,10 +130,10 @@ module RestClient
|
|||
# timeout on an individual network read, but does not limit the overall
|
||||
# duration of the request so long as the server continues sending data at
|
||||
# a trickle. Pass nil to disable the timeout. See
|
||||
# {Net::HTTP#read_timeout}.
|
||||
# `Net::HTTP#read_timeout`.
|
||||
# @option args [Numeric, nil] :open_timeout Number of seconds to wait for
|
||||
# the connection to be established. Pass nil to disable the timeout. See
|
||||
# {Net::HTTP#open_timeout}.
|
||||
# `Net::HTTP#open_timeout`.
|
||||
# @option args [Numeric, nil] :timeout Set both `:read_timeout` and
|
||||
# `:open_timeout`
|
||||
# @option args :ssl_client_cert
|
||||
|
@ -258,7 +267,7 @@ module RestClient
|
|||
|
||||
# Extract the query parameters and append them to the url
|
||||
#
|
||||
# Look through the headers hash for a :params option (case-insensitive,
|
||||
# Look through the headers hash for a `:params` option (case-insensitive,
|
||||
# may be string or symbol). If present and the value is a Hash or
|
||||
# RestClient::ParamsArray, *delete* the key/value pair from the headers
|
||||
# hash and encode the value into a query string. Append this query string
|
||||
|
@ -266,10 +275,12 @@ module RestClient
|
|||
#
|
||||
# @param [String] url
|
||||
# @param [Hash] headers An options/headers hash to process. Mutation
|
||||
# warning: the params key may be removed if present!
|
||||
# warning: the `params` key may be removed if present!
|
||||
#
|
||||
# @return [String] resulting url with query string
|
||||
#
|
||||
# @api private
|
||||
#
|
||||
def process_url_params(url, headers)
|
||||
url_params = nil
|
||||
|
||||
|
@ -342,19 +353,21 @@ module RestClient
|
|||
end
|
||||
|
||||
# Process cookies passed as hash or as HTTP::CookieJar. For backwards
|
||||
# compatibility, these may be passed as a :cookies option masquerading
|
||||
# inside the headers hash. To avoid confusion, if :cookies is passed in
|
||||
# both headers and Request#initialize, raise an error.
|
||||
# compatibility, these may be passed as a `:cookies` option masquerading
|
||||
# inside the headers hash. To avoid confusion, if `:cookies` is passed in
|
||||
# both headers and {#initialize}, raise an error.
|
||||
#
|
||||
# :cookies may be a:
|
||||
# - Hash{String/Symbol => String}
|
||||
# - Array<HTTP::Cookie>
|
||||
# - HTTP::CookieJar
|
||||
# `:cookies` may be a:
|
||||
#
|
||||
# - `Hash{String/Symbol => String}`
|
||||
# - `Array<HTTP::Cookie>`
|
||||
# - `HTTP::CookieJar`
|
||||
#
|
||||
# **Passing as a hash:**
|
||||
#
|
||||
# Passing as a hash:
|
||||
# Keys may be symbols or strings. Values must be strings.
|
||||
# Infer the domain name from the request URI and allow subdomains (as
|
||||
# though '.example.com' had been set in a Set-Cookie header). Assume a
|
||||
# though '.example.com' had been set in a `Set-Cookie` header). Assume a
|
||||
# path of '/'.
|
||||
#
|
||||
# RestClient::Request.new(url: 'http://example.com', method: :get,
|
||||
|
@ -362,28 +375,30 @@ module RestClient
|
|||
# )
|
||||
#
|
||||
# results in cookies as though set from the server by:
|
||||
#
|
||||
# Set-Cookie: foo=Value; Domain=.example.com; Path=/
|
||||
# Set-Cookie: bar=123; Domain=.example.com; Path=/
|
||||
#
|
||||
# which yields a client cookie header of:
|
||||
#
|
||||
# Cookie: foo=Value; bar=123
|
||||
#
|
||||
# Passing as HTTP::CookieJar, which will be passed through directly:
|
||||
# **Passing as HTTP::CookieJar, which will be passed through directly:**
|
||||
#
|
||||
# jar = HTTP::CookieJar.new
|
||||
# jar.add(HTTP::Cookie.new('foo', 'Value', domain: 'example.com',
|
||||
# path: '/', for_domain: false))
|
||||
#
|
||||
# RestClient::Request.new(..., :cookies => jar)
|
||||
# RestClient::Request.new('...', :cookies => jar)
|
||||
#
|
||||
# @param [URI::HTTP] uri The URI for the request. This will be used to
|
||||
# infer the domain name for cookies passed as strings in a hash. To avoid
|
||||
# this implicit behavior, pass a full cookie jar or use HTTP::Cookie hash
|
||||
# values.
|
||||
# @param [Hash] headers The headers hash from which to pull the :cookies
|
||||
# option. MUTATION NOTE: This key will be deleted from the hash if
|
||||
# present.
|
||||
# @param [Hash] args The options passed to Request#initialize. This hash
|
||||
# infer the domain name for cookies passed as strings in a hash. To avoid
|
||||
# this implicit behavior, pass a full cookie jar or use `HTTP::Cookie`
|
||||
# hash values.
|
||||
# @param [Hash] headers The headers hash from which to pull the `:cookies`
|
||||
# option. **MUTATION NOTE:** This key will be deleted from the hash if
|
||||
# present. Passing cookies in this way is deprecated.
|
||||
# @param [Hash] args The options passed to {Request#initialize}. This hash
|
||||
# will be used as another potential source for the :cookies key.
|
||||
# These args will not be mutated.
|
||||
#
|
||||
|
@ -439,19 +454,20 @@ module RestClient
|
|||
end
|
||||
|
||||
# Generate headers for use by a request. Header keys will be stringified
|
||||
# using `#stringify_headers` to normalize them as capitalized strings.
|
||||
# using {#stringify_headers} to normalize them as capitalized strings.
|
||||
#
|
||||
# The final headers consist of:
|
||||
# - default headers from #default_headers
|
||||
# - user_headers provided here
|
||||
# - headers from the payload object (e.g. Content-Type, Content-Lenth)
|
||||
# - cookie headers from #make_cookie_header
|
||||
#
|
||||
# BUG: stringify_headers does not alter the capitalization of headers that
|
||||
# are passed as strings, it only normalizes those passed as symbols. This
|
||||
# behavior will probably remain for a while for compatibility, but it means
|
||||
# that the warnings that attempt to detect accidental header overrides may
|
||||
# not always work.
|
||||
# - default headers from {#default_headers}
|
||||
# - `user_headers` provided here
|
||||
# - headers from the payload object (e.g. Content-Type, Content-Lenth)
|
||||
# - cookie headers from {#make_cookie_header}
|
||||
#
|
||||
# **BUG:** stringify_headers does not alter the capitalization of headers
|
||||
# that are passed as strings, it only normalizes those passed as symbols.
|
||||
# This behavior will probably remain for a while for compatibility, but it
|
||||
# means that the warnings that attempt to detect accidental header
|
||||
# overrides may not always work.
|
||||
# https://github.com/rest-client/rest-client/issues/599
|
||||
#
|
||||
# @param [Hash] user_headers User-provided headers to include
|
||||
|
@ -494,7 +510,7 @@ module RestClient
|
|||
end
|
||||
|
||||
# The proxy URI for this request. If `:proxy` was provided on this request,
|
||||
# use it over `RestClient.proxy`.
|
||||
# use it over {RestClient.proxy}.
|
||||
#
|
||||
# Return false if a proxy was explicitly set and is falsy.
|
||||
#
|
||||
|
@ -518,6 +534,17 @@ module RestClient
|
|||
end
|
||||
end
|
||||
|
||||
# Create a new Net::HTTP object representing a connection to a server
|
||||
# without actually opening the connection. This method will set up an HTTP
|
||||
# proxy according to {#proxy_uri}.
|
||||
#
|
||||
# @param hostname [String]
|
||||
# @param port [Integer]
|
||||
#
|
||||
# @return [Net::HTTP]
|
||||
#
|
||||
# @api private
|
||||
#
|
||||
def net_http_object(hostname, port)
|
||||
p_uri = proxy_uri
|
||||
|
||||
|
@ -534,10 +561,28 @@ module RestClient
|
|||
end
|
||||
end
|
||||
|
||||
# Find the Net::HTTPRequest subclass for a given HTTP method/verb.
|
||||
#
|
||||
# @param method [Symbol, String]
|
||||
#
|
||||
# @return [Class] A subclass of Net::HTTPRequest.
|
||||
#
|
||||
# @api private
|
||||
#
|
||||
def net_http_request_class(method)
|
||||
Net::HTTP.const_get(method.capitalize, false)
|
||||
end
|
||||
|
||||
# Actually execute the request with Net::HTTP.
|
||||
#
|
||||
# @param http [Net::HTTP]
|
||||
# @param req [Net::HTTPRequest]
|
||||
# @param body [String, IO, nil]
|
||||
#
|
||||
# @see https://ruby-doc.org/stdlib-2.4.0/libdoc/net/http/rdoc/Net/HTTP.html#method-i-request
|
||||
# Net::HTTP#request
|
||||
#
|
||||
# @api private
|
||||
def net_http_do_request(http, req, body=nil, &block)
|
||||
if body && body.respond_to?(:read)
|
||||
req.body_stream = body
|
||||
|
@ -557,6 +602,8 @@ module RestClient
|
|||
#
|
||||
# @return [String]
|
||||
#
|
||||
# @api private
|
||||
#
|
||||
def normalize_url(url)
|
||||
url = 'http://' + url unless url.match(%r{\A[a-z][a-z0-9+.-]*://}i)
|
||||
url
|
||||
|
@ -605,11 +652,20 @@ module RestClient
|
|||
redacted_uri.to_s
|
||||
end
|
||||
|
||||
# Default to the global logger if there's not a request-specific one
|
||||
# The log used for this request.
|
||||
#
|
||||
# Defaults to the global logger {RestClient.log} if there was no `:log`
|
||||
# option set on this request.
|
||||
#
|
||||
def log
|
||||
@log || RestClient.log
|
||||
end
|
||||
|
||||
# Write log information about the request. Called just prior to sending the
|
||||
# request to the server.
|
||||
#
|
||||
# @return [void]
|
||||
#
|
||||
def log_request
|
||||
return unless log
|
||||
|
||||
|
|
|
@ -4,34 +4,34 @@ module RestClient
|
|||
#
|
||||
# Example:
|
||||
#
|
||||
# resource = RestClient::Resource.new('http://some/resource')
|
||||
# jpg = resource.get(:accept => 'image/jpg')
|
||||
# resource = RestClient::Resource.new('http://some/resource')
|
||||
# jpg = resource.get(:accept => 'image/jpg')
|
||||
#
|
||||
# With HTTP basic authentication:
|
||||
#
|
||||
# resource = RestClient::Resource.new('http://protected/resource', :user => 'user', :password => 'password')
|
||||
# resource.delete
|
||||
# resource = RestClient::Resource.new('http://protected/resource', :user => 'user', :password => 'password')
|
||||
# resource.delete
|
||||
#
|
||||
# With a timeout (seconds):
|
||||
#
|
||||
# RestClient::Resource.new('http://slow', :read_timeout => 10)
|
||||
# RestClient::Resource.new('http://slow', :read_timeout => 10)
|
||||
#
|
||||
# With an open timeout (seconds):
|
||||
#
|
||||
# RestClient::Resource.new('http://behindfirewall', :open_timeout => 10)
|
||||
# RestClient::Resource.new('http://behindfirewall', :open_timeout => 10)
|
||||
#
|
||||
# You can also use resources to share common headers. For headers keys,
|
||||
# symbols are converted to strings. Example:
|
||||
#
|
||||
# resource = RestClient::Resource.new('http://some/resource', :headers => { :client_version => 1 })
|
||||
# resource = RestClient::Resource.new('http://some/resource', :headers => { :client_version => 1 })
|
||||
#
|
||||
# This header will be transported as X-Client-Version (notice the X prefix,
|
||||
# capitalization and hyphens)
|
||||
#
|
||||
# Use the [] syntax to allocate subresources:
|
||||
#
|
||||
# site = RestClient::Resource.new('http://example.com', :user => 'adam', :password => 'mypasswd')
|
||||
# site['posts/1/comments'].post 'Good article.', :content_type => 'text/plain'
|
||||
# site = RestClient::Resource.new('http://example.com', :user => 'adam', :password => 'mypasswd')
|
||||
# site['posts/1/comments'].post 'Good article.', :content_type => 'text/plain'
|
||||
#
|
||||
class Resource
|
||||
attr_reader :url, :options, :block
|
||||
|
|
|
@ -2,6 +2,17 @@ module RestClient
|
|||
|
||||
# A Response from RestClient, you can access the response body, the code or the headers.
|
||||
#
|
||||
# Response is a subclass of `String` for backwards compatibility. This may
|
||||
# change in a future major release of RestClient, so it is recommended to
|
||||
# explicitly call {#body} or {#to_s} before invoking `String` methods.
|
||||
#
|
||||
# The request that resulted in this response is accessible at {#request}.
|
||||
#
|
||||
# Much of the functionality is implemented on the {AbstractResponse} module.
|
||||
#
|
||||
# @see AbstractResponse
|
||||
# @see RawResponse
|
||||
#
|
||||
class Response < String
|
||||
|
||||
include AbstractResponse
|
||||
|
@ -38,14 +49,17 @@ module RestClient
|
|||
"<RestClient::Response #{code.inspect} #{body_truncated(10).inspect}>"
|
||||
end
|
||||
|
||||
# Initialize a Response object. Because RestClient::Response is
|
||||
# Initialize a Response object. Because `RestClient::Response` is
|
||||
# (unfortunately) a subclass of String for historical reasons,
|
||||
# Response.create is the preferred initializer.
|
||||
# `Response.create` is the preferred initializer.
|
||||
#
|
||||
# @param [String, nil] body The response body from the Net::HTTPResponse
|
||||
# @param [Net::HTTPResponse] net_http_res
|
||||
# @param [RestClient::Request] request
|
||||
# @param [Time] start_time
|
||||
#
|
||||
# @return [Response]
|
||||
#
|
||||
def self.create(body, net_http_res, request, start_time=nil)
|
||||
result = self.new(body || '')
|
||||
|
||||
|
@ -55,8 +69,13 @@ module RestClient
|
|||
result
|
||||
end
|
||||
|
||||
# Set the String encoding according to the 'Content-Type: charset' header,
|
||||
# Set the String encoding according to the `Content-Type: charset` header,
|
||||
# if possible.
|
||||
#
|
||||
# @param response [Response]
|
||||
#
|
||||
# @return [Response]
|
||||
#
|
||||
def self.fix_encoding(response)
|
||||
charset = RestClient::Utils.get_encoding_from_headers(response.headers)
|
||||
encoding = nil
|
||||
|
|
|
@ -1,7 +1,12 @@
|
|||
module RestClient
|
||||
|
||||
# The current RestClient version array
|
||||
VERSION_INFO = [2, 1, 0, 'rc1'] unless defined?(self::VERSION_INFO)
|
||||
|
||||
# The current RestClient version string
|
||||
VERSION = VERSION_INFO.map(&:to_s).join('.') unless defined?(self::VERSION)
|
||||
|
||||
# @return [String] The current RestClient version string
|
||||
def self.version
|
||||
VERSION
|
||||
end
|
||||
|
|
Loading…
Reference in a new issue