From 951eabdcf2f0a8c8b0f23904b65bbaf93cde8d82 Mon Sep 17 00:00:00 2001 From: BurdetteLamar Date: Tue, 15 Nov 2022 18:07:46 +0000 Subject: [ruby/net-http] Enhanced RDoc for Net::HTTP https://github.com/ruby/net-http/commit/6b30c5310b --- lib/net/http.rb | 675 ++++++++++++++++++++++++++--------------------- lib/net/http/request.rb | 83 +++++- lib/net/http/response.rb | 158 ++++++++++- 3 files changed, 596 insertions(+), 320 deletions(-) (limited to 'lib') diff --git a/lib/net/http.rb b/lib/net/http.rb index 16137cebf2..535ca10a0e 100644 --- a/lib/net/http.rb +++ b/lib/net/http.rb @@ -32,110 +32,290 @@ module Net #:nodoc: class HTTPHeaderSyntaxError < StandardError; end # :startdoc: - # == An HTTP client API for Ruby. + # \Class \Net::HTTP provides a rich library that implements the client + # in a client-server model that uses the \HTTP request-response protocol. + # For information about \HTTP, see + # + # - {Hypertext Transfer Protocol}[https://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol]. + # - {Technical overview}[https://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol#Technical_overview]. + # + # Note: If you are performing only a few GET requests, consider using + # {OpenURI}[rdoc-ref:OpenURI]; + # otherwise, read on. + # + # == Synopsis + # + # If you are already familiar with \HTTP, this synopsis may be helpful. + # + # {Session}[rdoc-ref:Net::HTTP@Sessions] with multiple requests for + # {HTTP methods}[https://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol#Request_methods]: + # + # Net::HTTP.start(hostname) do |http| + # # Session started automatically before block execution. + # http.get(path_or_uri, headers = {}) + # http.head(path_or_uri, headers = {}) + # http.post(path_or_uri, data, headers = {}) # Can also have a block. + # http.put(path_or_uri, data, headers = {}) + # http.delete(path_or_uri, headers = {Depth: 'Infinity'}) + # http.options(path_or_uri, headers = {}) + # http.trace(path_or_uri, headers = {}) + # http.patch(path_or_uri, data, headers = {}) # Can also have a block. + # # Session finished automatically at block exit. + # end + # + # {Session}[rdoc-ref:Net::HTTP@Sessions] with multiple requests for + # {WebDAV methods}[https://en.wikipedia.org/wiki/WebDAV#Implementation]: + # + # Net::HTTP.start(hostname) do |http| + # # Session started automatically before block execution. + # http.copy(path_or_uri, headers = {}) + # http.lock(path_or_uri, body, headers = {}) + # http.mkcol(path_or_uri, body = nil, headers = {}) + # http.move(path_or_uri, headers = {}) + # http.propfind(path_or_uri, body = nil, headers = {'Depth' => '0'}) + # http.proppatch(path_or_uri, body, headers = {}) + # http.unlock(path_or_uri, body, headers = {}) + # # Session finished automatically at block exit. + # end + # + # Each of the following methods automatically starts and finishes + # a {session}[rdoc-ref:Net::HTTP@Sessions] that sends a single request: # - # Net::HTTP provides a rich library which can be used to build HTTP - # user-agents. For more details about HTTP see - # [RFC2616](http://www.ietf.org/rfc/rfc2616.txt). + # # Return string response body. + # Net::HTTP.get(hostname, path, port = 80) + # Net::HTTP.get(uri, headers = {}, port = 80) # - # Net::HTTP is designed to work closely with URI. URI::HTTP#host, - # URI::HTTP#port and URI::HTTP#request_uri are designed to work with - # Net::HTTP. + # # Write string response body to $stdout. + # Net::HTTP.get_print(hostname, path_or_uri, port = 80) + # Net::HTTP.get_print(uri, headers = {}, port = 80) # - # If you are only performing a few GET requests you should try OpenURI. + # # Return response as Net::HTTPResponse object. + # Net::HTTP.get_response(hostname, path_or_uri, port = 80) + # Net::HTTP.get_response(uri, headers = {}, port = 80) # - # == Simple Examples + # Net::HTTP.post(uri, data, headers = {}) + # Net::HTTP.post_form(uri, params) # - # All examples assume you have loaded Net::HTTP with: + # == About the Examples + # + # Examples here assume that net/http has been required + # (which also requires +uri+): # # require 'net/http' # - # This will also require 'uri' so you don't need to require it separately. + # Many code examples here use these example websites: # - # The Net::HTTP methods in the following section do not persist - # connections. They are not recommended if you are performing many HTTP - # requests. + # - https://jsonplaceholder.typicode.com. + # - http:example.com. # - # === GET + # Some examples also assume these variables: # - # Net::HTTP.get('example.com', '/index.html') # => String + # uri = URI('https://jsonplaceholder.typicode.com') + # uri.freeze # Examples may not modify. + # hostname = uri.hostname # => "jsonplaceholder.typicode.com" + # port = uri.port # => 443 # - # === GET by URI + # So that example requests may be written as: # - # uri = URI('http://example.com/index.html?count=10') - # Net::HTTP.get(uri) # => String + # Net::HTTP.get(uri) + # Net::HTTP.get(hostname, '/index.html') + # Net::HTTP.start(hostname) do |http| + # http.get('/todos/1') + # http.get('/todos/2') + # end # - # === GET with Dynamic Parameters + # An example that needs a modified URI first duplicates +uri+, then modifies: # - # uri = URI('http://example.com/index.html') - # params = { :limit => 10, :page => 3 } - # uri.query = URI.encode_www_form(params) + # _uri = uri.dup + # _uri.path = '/todos/1' # - # res = Net::HTTP.get_response(uri) - # puts res.body if res.is_a?(Net::HTTPSuccess) + # == URIs # - # === POST + # On the internet, a URI + # ({Universal Resource Identifier}[https://en.wikipedia.org/wiki/Uniform_Resource_Identifier]) + # is a string that identifies a particular resource. + # It consists of some or all of: scheme, hostname, path, query, and fragment; + # see {URI syntax}[https://en.wikipedia.org/wiki/Uniform_Resource_Identifier#Syntax]. # - # uri = URI('http://www.example.com/search.cgi') - # res = Net::HTTP.post_form(uri, 'q' => 'ruby', 'max' => '50') - # puts res.body + # A Ruby {URI::Generic}[]https://docs.ruby-lang.org/en/master/URI/Generic.html] object + # represents an internet URI. + # It provides, among others, methods + # +scheme+, +hostname+, +path+, +query+, and +fragment+. # - # === POST with Multiple Values + # === Schemes # - # uri = URI('http://www.example.com/search.cgi') - # res = Net::HTTP.post_form(uri, 'q' => ['ruby', 'perl'], 'max' => '50') - # puts res.body + # An internet \URI has + # a {scheme}[https://en.wikipedia.org/wiki/List_of_URI_schemes]. # - # == How to use Net::HTTP + # The two schemes supported in \Net::HTTP are 'https' and 'http': # - # The following example code can be used as the basis of an HTTP user-agent - # which can perform a variety of request types using persistent - # connections. + # uri.scheme # => "https" + # URI('http://example.com').scheme # => "http" # - # uri = URI('http://example.com/some_path?query=string') + # === Hostnames # - # Net::HTTP.start(uri.host, uri.port) do |http| - # request = Net::HTTP::Get.new uri + # A hostname identifies a server (host) to which requests may be sent: # - # response = http.request request # Net::HTTPResponse object + # hostname = uri.hostname # => "jsonplaceholder.typicode.com" + # Net::HTTP.start(hostname) do |http| + # # Some HTTP stuff. # end # - # Net::HTTP::start immediately creates a connection to an HTTP server which - # is kept open for the duration of the block. The connection will remain - # open for multiple requests in the block if the server indicates it - # supports persistent connections. + # === Paths # - # If you wish to re-use a connection across multiple HTTP requests without - # automatically closing it you can use ::new and then call #start and - # #finish manually. + # A host-specific path identifies a resource on the host: # - # The request types Net::HTTP supports are listed below in the section "HTTP - # Request Classes". + # _uri = uri.dup + # _uri.path = '/todos/1' + # hostname = _uri.hostname + # path = _uri.path + # Net::HTTP.get(hostname, path) # - # For all the Net::HTTP request objects and shortcut request methods you may - # supply either a String for the request path or a URI from which Net::HTTP - # will extract the request path. + # === Queries # - # === Response Data + # A host-specific query adds name/value pairs to the URI: # - # uri = URI('http://example.com/index.html') - # res = Net::HTTP.get_response(uri) + # _uri = uri.dup + # params = {userId: 1, completed: false} + # _uri.query = URI.encode_www_form(params) + # _uri # => # + # Net::HTTP.get(_uri) # - # # Headers - # res['Set-Cookie'] # => String - # res.get_fields('set-cookie') # => Array - # res.to_hash['set-cookie'] # => Array - # puts "Headers: #{res.to_hash.inspect}" + # === Fragments # - # # Status - # puts res.code # => '200' - # puts res.message # => 'OK' - # puts res.class.name # => 'HTTPOK' + # A {URI fragment}[https://en.wikipedia.org/wiki/URI_fragment] has no effect + # in \Net::HTTP; + # the same data is returned, regardless of whether a fragment is included. # - # # Body - # puts res.body + # == Request Headers + # + # Request headers may be used to pass additional information to the host, + # similar to arguments passed in a method call; + # each header is a name/value pair. + # + # Each of the \Net::HTTP methods that sends a request to the host + # has optional argument +headers+, + # where the headers are expressed as a hash of field-name/value pairs: + # + # headers = {Accept: 'application/json', Connection: 'Keep-Alive'} + # Net::HTTP.get(uri, headers) + # + # See lists of both standard request fields and common request fields at + # {Request Fields}[https://en.wikipedia.org/wiki/List_of_HTTP_header_fields#Request_fields]. + # A host may also accept other custom fields. + # + # The following example performs a conditional GET using the + # If-Modified-Since header: + # + # - If the file +cached_response+ has been modified since the time + # put into the header, + # the return is a \Net::HTTPSuccess object, + # and the file is overwritten with the response body. + # - Otherwise, the return is a \Net::HTTPNotModified object, + # and the file remains unchanged. + # + # The code: + # + # path = 'cached_response' + # File.write(path, '') unless File.exist?(path) + # file = File.stat(path) + # req = Net::HTTP::Get.new(uri) + # req['If-Modified-Since'] = file.mtime.rfc2822 + # res = Net::HTTP.start(hostname) do |http| + # http.request(req) + # end + # if res.is_a?(Net::HTTPSuccess) + # File.write(path, res.body) + # end + # + # == Sessions + # + # A _session_ is a connection between a server (host) and a client that: + # + # - Is begun by instance method Net::HTTP#start. + # - May contain any number of requests. + # - Is ended by instance method Net::HTTP#finish. + # + # See example sessions at the {Synopsis}[rdoc-ref:Net::HTTP@Synopsis]. + # + # === Session Using \Net::HTTP.start + # + # If you have many requests to make to a single host (and port), + # consider using singleton method Net::HTTP.start with a block; + # the method handles the session automatically by: + # + # - Calling #start before block execution. + # - Executing the block. + # - Calling #finish after block execution. + # + # In the block, you can use these instance methods, + # each of which that sends a single request: + # + # - {HTTP methods}[https://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol#Request_methods]: + # + # - #get, #request_get: GET. + # - #head, #request_head: HEAD. + # - #post, #request_post: POST. + # - #delete: DELETE. + # - #options: OPTIONS. + # - #trace: TRACE. + # - #patch: PATCH. + # + # - {WebDAV methods}[https://en.wikipedia.org/wiki/WebDAV#Implementation]: + # + # - #copy: COPY. + # - #lock: LOCK. + # - #mkcol: MKCOL. + # - #move: MOVE. + # - #propfind: PROPFIND. + # - #proppatch: PROPPATCH. + # - #unlock: UNLOCK. + # + # === Session Using \Net::HTTP.start and \Net::HTTP.finish + # + # You can manage a session manually using methods #start and #finish: + # + # http = Net::HTTP.new(hostname) + # http.start + # http.get('/todos/1') + # http.get('/todos/2') + # http.delete('/posts/1') + # http.finish # Needed to free resources. + # + # === Single-Request Session + # + # Certain convenience methods automatically handle a session by: + # + # - Creating an \HTTP object + # - Starting a session. + # - Sending a single request. + # - Finishing the session. + # - Destroying the object. + # + # Such methods that send GET requests: + # + # - ::get: Returns the string response body. + # - ::get_print: Writes the string response body to $stdout. + # - ::get_response: Returns a Net::HTTPResponse object. + # + # Such methods that send POST requests: + # + # - ::post: Posts data to the host. + # - ::post_form: Posts form data to the host. + # + # == \HTTP Requests and Responses + # + # Many of the methods above are convenience methods, + # each of which sends a request and returns a string + # without directly using \Net::HTTPRequest and \Net::HTTPResponse objects. + # + # You can, however, directly create a request object, send the request, + # and retrieve the response object; see: + # + # - Net::HTTPRequest. + # - Net::HTTPResponse. # - # === Following Redirection + # == Following Redirection # # Each Net::HTTPResponse object belongs to a class for its response code. # @@ -167,56 +347,7 @@ module Net #:nodoc: # # print fetch('http://www.ruby-lang.org') # - # === POST - # - # A POST can be made using the Net::HTTP::Post request class. This example - # creates a URL encoded POST body: - # - # uri = URI('http://www.example.com/todo.cgi') - # req = Net::HTTP::Post.new(uri) - # req.set_form_data('from' => '2005-01-01', 'to' => '2005-03-31') - # - # res = Net::HTTP.start(uri.hostname, uri.port) do |http| - # http.request(req) - # end - # - # case res - # when Net::HTTPSuccess, Net::HTTPRedirection - # # OK - # else - # res.value - # end - # - # To send multipart/form-data use Net::HTTPHeader#set_form: - # - # req = Net::HTTP::Post.new(uri) - # req.set_form([['upload', File.open('foo.bar')]], 'multipart/form-data') - # - # Other requests that can contain a body such as PUT can be created in the - # same way using the corresponding request class (Net::HTTP::Put). - # - # === Setting Headers - # - # The following example performs a conditional GET using the - # If-Modified-Since header. If the files has not been modified since the - # time in the header a Not Modified response will be returned. See RFC 2616 - # section 9.3 for further details. - # - # uri = URI('http://example.com/cached_response') - # file = File.stat 'cached_response' - # - # req = Net::HTTP::Get.new(uri) - # req['If-Modified-Since'] = file.mtime.rfc2822 - # - # res = Net::HTTP.start(uri.hostname, uri.port) {|http| - # http.request(req) - # } - # - # open 'cached_response', 'w' do |io| - # io.write res.body - # end if res.is_a?(Net::HTTPSuccess) - # - # === Basic Authentication + # == Basic Authentication # # Basic authentication is performed according to # [RFC2617](http://www.ietf.org/rfc/rfc2617.txt). @@ -231,7 +362,7 @@ module Net #:nodoc: # } # puts res.body # - # === Streaming Response Bodies + # == Streaming Response Bodies # # By default Net::HTTP reads an entire response into memory. If you are # handling large files or wish to implement a progress bar you can instead @@ -251,7 +382,7 @@ module Net #:nodoc: # end # end # - # === HTTPS + # == HTTPS # # HTTPS is enabled for an HTTP connection by Net::HTTP#use_ssl=. # @@ -272,7 +403,7 @@ module Net #:nodoc: # In previous versions of Ruby you would need to require 'net/https' to use # HTTPS. This is no longer true. # - # === Proxies + # == Proxies # # Net::HTTP will automatically create a proxy from the +http_proxy+ # environment variable if it is present. To disable use of +http_proxy+, @@ -290,7 +421,7 @@ module Net #:nodoc: # See Net::HTTP.new for further details and examples such as proxies that # require a username and password. # - # === Compression + # == Compression # # Net::HTTP automatically adds Accept-Encoding for compression of response # bodies and automatically decompresses gzip and deflate responses unless a @@ -298,114 +429,6 @@ module Net #:nodoc: # # Compression can be disabled through the Accept-Encoding: identity header. # - # == \HTTP Request Classes - # - # Here is the hierarchy of \HTTP request classes - # - # - Net::HTTPRequest - # - # - Net::HTTP::Get - # - Net::HTTP::Head - # - Net::HTTP::Post - # - Net::HTTP::Patch - # - Net::HTTP::Put - # - Net::HTTP::Proppatch - # - Net::HTTP::Lock - # - Net::HTTP::Unlock - # - Net::HTTP::Options - # - Net::HTTP::Propfind - # - Net::HTTP::Delete - # - Net::HTTP::Move - # - Net::HTTP::Copy - # - Net::HTTP::Mkcol - # - Net::HTTP::Trace - # - # == \HTTP Response Classes - # - # Here is the \HTTP response class hierarchy (with status codes): - # - # - Net::HTTPResponse: - # - # - Net::HTTPUnknownResponse (for unhandled \HTTP extensions). - # - # - Net::HTTPInformation: - # - # - Net::HTTPContinue (100) - # - Net::HTTPSwitchProtocol (101) - # - Net::HTTPProcessing (102) - # - Net::HTTPEarlyHints (103) - # - # - Net::HTTPSuccess: - # - # - Net::HTTPOK (200) - # - Net::HTTPCreated (201) - # - Net::HTTPAccepted (202) - # - Net::HTTPNonAuthoritativeInformation (203) - # - Net::HTTPNoContent (204) - # - Net::HTTPResetContent (205) - # - Net::HTTPPartialContent (206) - # - Net::HTTPMultiStatus (207) - # - Net::HTTPAlreadyReported (208) - # - Net::HTTPIMUsed (226) - # - # - Net::HTTPRedirection: - # - # - Net::HTTPMultipleChoices (300) - # - Net::HTTPMovedPermanently (301) - # - Net::HTTPFound (302) - # - Net::HTTPSeeOther (303) - # - Net::HTTPNotModified (304) - # - Net::HTTPUseProxy (305) - # - Net::HTTPTemporaryRedirect (307) - # - Net::HTTPPermanentRedirect (308) - # - # - Net::HTTPClientError: - # - # - Net::HTTPBadRequest (400) - # - Net::HTTPUnauthorized (401) - # - Net::HTTPPaymentRequired (402) - # - Net::HTTPForbidden (403) - # - Net::HTTPNotFound (404) - # - Net::HTTPMethodNotAllowed (405) - # - Net::HTTPNotAcceptable (406) - # - Net::HTTPProxyAuthenticationRequired (407) - # - Net::HTTPRequestTimeOut (408) - # - Net::HTTPConflict (409) - # - Net::HTTPGone (410) - # - Net::HTTPLengthRequired (411) - # - Net::HTTPPreconditionFailed (412) - # - Net::HTTPRequestEntityTooLarge (413) - # - Net::HTTPRequestURITooLong (414) - # - Net::HTTPUnsupportedMediaType (415) - # - Net::HTTPRequestedRangeNotSatisfiable (416) - # - Net::HTTPExpectationFailed (417) - # - Net::HTTPMisdirectedRequest (421) - # - Net::HTTPUnprocessableEntity (422) - # - Net::HTTPLocked (423) - # - Net::HTTPFailedDependency (424) - # - Net::HTTPUpgradeRequired (426) - # - Net::HTTPPreconditionRequired (428) - # - Net::HTTPTooManyRequests (429) - # - Net::HTTPRequestHeaderFieldsTooLarge (431) - # - Net::HTTPUnavailableForLegalReasons (451) - # - # - Net::HTTPServerError: - # - # - Net::HTTPInternalServerError (500) - # - Net::HTTPNotImplemented (501) - # - Net::HTTPBadGateway (502) - # - Net::HTTPServiceUnavailable (503) - # - Net::HTTPGatewayTimeOut (504) - # - Net::HTTPVersionNotSupported (505) - # - Net::HTTPVariantAlsoNegotiates (506) - # - Net::HTTPInsufficientStorage (507) - # - Net::HTTPLoopDetected (508) - # - Net::HTTPNotExtended (510) - # - Net::HTTPNetworkAuthenticationRequired (511) - # - # There is also the Net::HTTPBadResponse exception which is raised when - # there is a protocol error. - # class HTTP < Protocol # :stopdoc: @@ -420,18 +443,17 @@ module Net #:nodoc: end # :startdoc: - # Turns on net/http 1.2 (Ruby 1.8) features. - # Defaults to ON in Ruby 1.8 or later. + # Returns +true+; retained for compatibility. def HTTP.version_1_2 true end - # Returns true if net/http is in version 1.2 mode. - # Defaults to true. + # Returns +true+; retained for compatibility. def HTTP.version_1_2? true end + # Returns +false+; retained for compatibility. def HTTP.version_1_1? #:nodoc: false end @@ -441,25 +463,12 @@ module Net #:nodoc: alias is_version_1_2? version_1_2? #:nodoc: end + # :call-seq: + # Net::HTTP.get_print(hostname, path, port = 80) -> nil + # Net::HTTP:get_print(uri, headers = {}, port = 80) -> nil # - # short cut methods - # - - # - # Gets the body text from the target and outputs it to $stdout. The - # target can either be specified as - # (+uri+, +headers+), or as (+host+, +path+, +port+ = 80); so: - # - # Net::HTTP.get_print URI('http://www.example.com/index.html') - # - # or: - # - # Net::HTTP.get_print 'www.example.com', '/index.html' - # - # you can also specify request headers: - # - # Net::HTTP.get_print URI('http://www.example.com/index.html'), { 'Accept' => 'text/html' } - # + # Like Net::HTTP.get, but writes the returned body to $stdout; + # returns +nil+. def HTTP.get_print(uri_or_host, path_or_headers = nil, port = nil) get_response(uri_or_host, path_or_headers, port) {|res| res.read_body do |chunk| @@ -469,40 +478,54 @@ module Net #:nodoc: nil end - # Sends a GET request to the target and returns the HTTP response - # as a string. The target can either be specified as - # (+uri+, +headers+), or as (+host+, +path+, +port+ = 80); so: - # - # print Net::HTTP.get(URI('http://www.example.com/index.html')) + # :call-seq: + # Net::HTTP.get(hostname, path, port = 80) -> body + # Net::HTTP:get(uri, headers = {}, port = 80) -> body # - # or: + # Sends a GET request and returns the \HTTP response body as a string. # - # print Net::HTTP.get('www.example.com', '/index.html') + # With string arguments +hostname+ and +path+: # - # you can also specify request headers: + # hostname = 'jsonplaceholder.typicode.com' + # path = '/todos/1' + # puts Net::HTTP.get(hostname, path) # - # Net::HTTP.get(URI('http://www.example.com/index.html'), { 'Accept' => 'text/html' }) + # Output: # - def HTTP.get(uri_or_host, path_or_headers = nil, port = nil) - get_response(uri_or_host, path_or_headers, port).body - end - - # Sends a GET request to the target and returns the HTTP response - # as a Net::HTTPResponse object. The target can either be specified as - # (+uri+, +headers+), or as (+host+, +path+, +port+ = 80); so: + # { + # "userId": 1, + # "id": 1, + # "title": "delectus aut autem", + # "completed": + # } # - # res = Net::HTTP.get_response(URI('http://www.example.com/index.html')) - # print res.body + # With URI object +uri+ and optional hash argument +headers+: # - # or: + # uri = URI('https://jsonplaceholder.typicode.com/todos/1') + # headers = {Accept: 'text/html'} + # puts Net::HTTP.get(uri, headers) # - # res = Net::HTTP.get_response('www.example.com', '/index.html') - # print res.body + # Output: # - # you can also specify request headers: + # { + # "userId": 1, + # "id": 1, + # "title": "delectus aut autem", + # "completed": false + # } # - # Net::HTTP.get_response(URI('http://www.example.com/index.html'), { 'Accept' => 'text/html' }) + # In either case, the third argument is an integer port number, + # which defaults to 80. + def HTTP.get(uri_or_host, path_or_headers = nil, port = nil) + get_response(uri_or_host, path_or_headers, port).body + end + + # :call-seq: + # Net::HTTP.get_response(hostname, path, port = 80) -> http_response + # Net::HTTP:get_response(uri, headers = {}, port = 80) -> http_response # + # Like Net::HTTP.get, but returns an Net::HTTPResponse object + # instead of the body string. def HTTP.get_response(uri_or_host, path_or_headers = nil, port = nil, &block) if path_or_headers && !path_or_headers.is_a?(Hash) host = uri_or_host @@ -588,36 +611,78 @@ module Net #:nodoc: BufferedIO end - # :call-seq: - # HTTP.start(address, port, p_addr, p_port, p_user, p_pass, &block) - # HTTP.start(address, port=nil, p_addr=:ENV, p_port=nil, p_user=nil, p_pass=nil, opt, &block) - # - # Creates a new Net::HTTP object, then additionally opens the TCP - # connection and HTTP session. - # - # Arguments are the following: - # _address_ :: hostname or IP address of the server - # _port_ :: port of the server - # _p_addr_ :: address of proxy - # _p_port_ :: port of proxy - # _p_user_ :: user of proxy - # _p_pass_ :: pass of proxy - # _opt_ :: optional hash - # - # _opt_ sets following values by its accessor. - # The keys are ipaddr, ca_file, ca_path, cert, cert_store, ciphers, keep_alive_timeout, - # close_on_empty_response, key, open_timeout, read_timeout, write_timeout, ssl_timeout, - # ssl_version, use_ssl, verify_callback, verify_depth and verify_mode. - # If you set :use_ssl as true, you can use https and default value of - # verify_mode is set as OpenSSL::SSL::VERIFY_PEER. - # - # If the optional block is given, the newly - # created Net::HTTP object is passed to it and closed when the - # block finishes. In this case, the return value of this method - # is the return value of the block. If no block is given, the - # return value of this method is the newly created Net::HTTP object - # itself, and the caller is responsible for closing it upon completion - # using the finish() method. + # Creates a new \Net::HTTP object, + # opens a TCP connection and \HTTP session. + # + # Argument +address+ is the hostname or IP address of the server. + # + # With a block given: + # + # - Passes the object to the given block, + # which may make any number of requests to the host. + # - Closes the \HTTP session on block exit. + # - Returns the block's value. + # + # Example: + # + # hostname = 'jsonplaceholder.typicode.com' + # Net::HTTP.start(hostname) do |http| + # puts http.get('/todos/1').body + # puts http.get('/todos/2').body + # end + # + # Output: + # + # { + # "userId": 1, + # "id": 1, + # "title": "delectus aut autem", + # "completed": false + # } + # { + # "userId": 1, + # "id": 2, + # "title": "quis ut nam facilis et officia qui", + # "completed": false + # } + # + # With no block given, returns the \Net::HTTP object; + # the caller should call #finish to close the session. + # + # Other arguments: + # + # - +port+: Server port number. + # - +p_addr+: Proxy address. + # - +p_port+: Proxy port. + # - +p_user+: Proxy user name. + # - +p_pass+: Proxy password. + # - +opts+: Optional options hash. + # + # The options hash +opts+ sets certain values, + # where each key is a method or accessor to be called, + # and its value is the value to be set. + # + # The keys may include: + # + # - #ca_file + # - #ca_path + # - #cert + # - #cert_store + # - #ciphers + # - #close_on_empty_response + # - +ipaddr+ (calls #ipaddr=) + # - #keep_alive_timeout + # - #key + # - #open_timeout + # - #read_timeout + # - #ssl_timeout + # - #ssl_version + # - +use_ssl+ (calls #use_ssl=) + # - #verify_callback + # - #verify_depth + # - #verify_mode + # - #write_timeout + # def HTTP.start(address, *arg, &block) # :yield: +http+ arg.pop if opt = Hash.try_convert(arg[-1]) port, p_addr, p_port, p_user, p_pass = *arg diff --git a/lib/net/http/request.rb b/lib/net/http/request.rb index 1e86f3e4b4..55099019d6 100644 --- a/lib/net/http/request.rb +++ b/lib/net/http/request.rb @@ -1,8 +1,83 @@ # frozen_string_literal: false -# HTTP request class. -# This class wraps together the request header and the request path. -# You cannot use this class directly. Instead, you should use one of its -# subclasses: Net::HTTP::Get, Net::HTTP::Post, Net::HTTP::Head. + +# This class is the base class for \Net::HTTP request classes; +# it wraps together the request path and the request headers. +# +# The class should not be used directly; +# instead you should use its subclasses, which are covered in the sections below. +# +# == About the Examples +# +# Examples here assume that net/http has been required +# (which also requires +uri+): +# +# require 'net/http' +# +# Many code examples here use these example websites: +# +# - https://jsonplaceholder.typicode.com. +# - http:example.com. +# +# Some examples also assume these variables: +# +# uri = URI('https://jsonplaceholder.typicode.com') +# uri.freeze # Examples may not modify. +# hostname = uri.hostname # => "jsonplaceholder.typicode.com" +# port = uri.port # => 443 +# +# An example that needs a modified URI first duplicates +uri+, then modifies: +# +# _uri = uri.dup +# _uri.path = '/todos/1' +# +# == Requests +# +# === \Net::HTTP::Get +# +# A GET request may be sent using request class \Net::HTTP::Get: +# +# req = Net::HTTP::Get.new(uri) # => # +# Net::HTTP.start(hostname) do |http| +# http.request(req) +# end # => # +# +# === \Net::HTTP::Head +# +# A HEAD request may be sent using request class \Net::HTTP::Head: +# +# req = Net::HTTP::Head.new(uri) # => # +# Net::HTTP.start(hostname) do |http| +# http.request(req) +# end # => # +# +# === \Net::HTTP::Post +# +# A POST request may be sent using request class \Net::HTTP::Post: +# +# require 'json' +# json = JSON.generate({title: 'foo', body: 'bar', userId: 1}) +# # => "{\"title\":\"foo\",\"body\":\"bar\",\"userId\":1}" +# _uri = uri.dup +# _uri.path = '/posts' +# req = Net::HTTP::Post.new(_uri) # => # +# req.body = json +# req['Content-type'] = 'application/json; charset=UTF-8' +# Net::HTTP.start(hostname) do |http| +# http.request(req) +# end # => # => # +# +# === \Net::HTTP::Patch +# === \Net::HTTP::Put +# === \Net::HTTP::Proppatch +# === \Net::HTTP::Lock +# === \Net::HTTP::Unlock +# === \Net::HTTP::Options +# === \Net::HTTP::Propfind +# === \Net::HTTP::Delete +# === \Net::HTTP::Move +# === \Net::HTTP::Copy +# === \Net::HTTP::Mkcol +# === \Net::HTTP::Trace # class Net::HTTPRequest < Net::HTTPGenericRequest # Creates an HTTP request object for +path+. diff --git a/lib/net/http/response.rb b/lib/net/http/response.rb index f8b522f1ff..043672d3e2 100644 --- a/lib/net/http/response.rb +++ b/lib/net/http/response.rb @@ -1,20 +1,156 @@ # frozen_string_literal: false -# HTTP response class. + +# This class is the base class for \Net::HTTP request classes. +# +# == About the Examples +# +# Examples here assume that net/http has been required +# (which also requires +uri+): +# +# require 'net/http' +# +# Many code examples here use these example websites: +# +# - https://jsonplaceholder.typicode.com. +# - http:example.com. +# +# Some examples also assume these variables: +# +# uri = URI('https://jsonplaceholder.typicode.com') +# uri.freeze # Examples may not modify. +# hostname = uri.hostname # => "jsonplaceholder.typicode.com" +# port = uri.port # => 443 +# +# An example that needs a modified URI first duplicates +uri+, then modifies: +# +# _uri = uri.dup +# _uri.path = '/todos/1' +# +# == Returned Responses +# +# \Method Net::HTTP.get_response returns +# an instance of one of the subclasses of \Net::HTTPResponse: +# +# Net::HTTP.get_response(uri) +# # => # +# Net::HTTP.get_response(hostname, '/nosuch') +# # => # +# +# As does method Net::HTTP#request: +# +# req = Net::HTTP::Get.new(uri) +# Net::HTTP.start(hostname) do |http| +# http.request(req) +# end # => # +# +# \Class \Net::HTTPResponse includes module Net::HTTPHeader, +# which provides access to response header values via (among others): +# +# - \Hash-like method []. +# - Specific reader methods, such as +content_type+. +# +# Examples: +# +# res = Net::HTTP.get_response(uri) # => # +# res['Content-Type'] # => "text/html; charset=UTF-8" +# res.content_type # => "text/html" +# +# == Response Subclasses +# +# \Class \Net::HTTPResponse has a subclass for each +# {HTTP status code}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes]. +# You can look up the response class for a given code: +# +# Net::HTTPResponse::CODE_TO_OBJ['200'] # => Net::HTTPOK +# Net::HTTPResponse::CODE_TO_OBJ['400'] # => Net::HTTPBadRequest +# Net::HTTPResponse::CODE_TO_OBJ['404'] # => Net::HTTPNotFound +# +# And you can retrieve the status code for a response object: +# +# Net::HTTP.get_response(uri).code # => "200" +# Net::HTTP.get_response(hostname, '/nosuch').code # => "404" +# +# The response subclasses (indentation shows class hierarchy): +# +# - Net::HTTPUnknownResponse (for unhandled \HTTP extensions). +# +# - Net::HTTPInformation: +# +# - Net::HTTPContinue (100) +# - Net::HTTPSwitchProtocol (101) +# - Net::HTTPProcessing (102) +# - Net::HTTPEarlyHints (103) +# +# - Net::HTTPSuccess: +# +# - Net::HTTPOK (200) +# - Net::HTTPCreated (201) +# - Net::HTTPAccepted (202) +# - Net::HTTPNonAuthoritativeInformation (203) +# - Net::HTTPNoContent (204) +# - Net::HTTPResetContent (205) +# - Net::HTTPPartialContent (206) +# - Net::HTTPMultiStatus (207) +# - Net::HTTPAlreadyReported (208) +# - Net::HTTPIMUsed (226) +# +# - HTTPRedirection: +# +# - Net::HTTPMultipleChoices (300) +# - Net::HTTPMovedPermanently (301) +# - Net::HTTPFound (302) +# - Net::HTTPSeeOther (303) +# - Net::HTTPNotModified (304) +# - Net::HTTPUseProxy (305) +# - Net::HTTPTemporaryRedirect (307) +# - Net::HTTPPermanentRedirect (308) # -# This class wraps together the response header and the response body (the -# entity requested). +# - Net::HTTPClientError: # -# It mixes in the HTTPHeader module, which provides access to response -# header values both via hash-like methods and via individual readers. +# - Net::HTTPBadRequest (400) +# - Net::HTTPUnauthorized (401) +# - Net::HTTPPaymentRequired (402) +# - Net::HTTPForbidden (403) +# - Net::HTTPNotFound (404) +# - Net::HTTPMethodNotAllowed (405) +# - Net::HTTPNotAcceptable (406) +# - Net::HTTPProxyAuthenticationRequired (407) +# - Net::HTTPRequestTimeOut (408) +# - Net::HTTPConflict (409) +# - Net::HTTPGone (410) +# - Net::HTTPLengthRequired (411) +# - Net::HTTPPreconditionFailed (412) +# - Net::HTTPRequestEntityTooLarge (413) +# - Net::HTTPRequestURITooLong (414) +# - Net::HTTPUnsupportedMediaType (415) +# - Net::HTTPRequestedRangeNotSatisfiable (416) +# - Net::HTTPExpectationFailed (417) +# - Net::HTTPMisdirectedRequest (421) +# - Net::HTTPUnprocessableEntity (422) +# - Net::HTTPLocked (423) +# - Net::HTTPFailedDependency (424) +# - Net::HTTPUpgradeRequired (426) +# - Net::HTTPPreconditionRequired (428) +# - Net::HTTPTooManyRequests (429) +# - Net::HTTPRequestHeaderFieldsTooLarge (431) +# - Net::HTTPUnavailableForLegalReasons (451) # -# Note that each possible HTTP response code defines its own -# HTTPResponse subclass. All classes are defined under the Net module. -# Indentation indicates inheritance. For a list of the classes see Net::HTTP. +# - Net::HTTPServerError: # -# Correspondence HTTP code => class is stored in CODE_TO_OBJ -# constant: +# - Net::HTTPInternalServerError (500) +# - Net::HTTPNotImplemented (501) +# - Net::HTTPBadGateway (502) +# - Net::HTTPServiceUnavailable (503) +# - Net::HTTPGatewayTimeOut (504) +# - Net::HTTPVersionNotSupported (505) +# - Net::HTTPVariantAlsoNegotiates (506) +# - Net::HTTPInsufficientStorage (507) +# - Net::HTTPLoopDetected (508) +# - Net::HTTPNotExtended (510) +# - Net::HTTPNetworkAuthenticationRequired (511) # -# Net::HTTPResponse::CODE_TO_OBJ['404'] #=> Net::HTTPNotFound +# There is also the Net::HTTPBadResponse exception which is raised when +# there is a protocol error. # class Net::HTTPResponse class << self -- cgit v1.2.3