rest-man 1.0.0 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (133) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/{multi-matrix-test.yml → ci.yml} +10 -1
  3. data/.github/workflows/single-matrix-test.yml +1 -0
  4. data/.gitignore +2 -0
  5. data/.rubocop-disables.yml +4 -29
  6. data/AUTHORS +5 -1
  7. data/CHANGELOG.md +14 -0
  8. data/Gemfile +3 -0
  9. data/README.md +30 -37
  10. data/Rakefile +1 -59
  11. data/_doc/lib/restman/abstract_response/_follow_redirection.rdoc +7 -0
  12. data/_doc/lib/restman/abstract_response/beautify_headers.rdoc +24 -0
  13. data/_doc/lib/restman/abstract_response/cookie_jar.rdoc +4 -0
  14. data/_doc/lib/restman/abstract_response/cookies.rdoc +12 -0
  15. data/_doc/lib/restman/abstract_response/follow_get_redirection.rdoc +2 -0
  16. data/_doc/lib/restman/abstract_response/follow_redirection.rdoc +2 -0
  17. data/_doc/lib/restman/abstract_response/headers.rdoc +2 -0
  18. data/_doc/lib/restman/abstract_response/response_set_vars.rdoc +5 -0
  19. data/_doc/lib/restman/abstract_response/return.rdoc +9 -0
  20. data/_doc/lib/restman/add_before_execution_proc.rdoc +2 -0
  21. data/_doc/lib/restman/create_log.rdoc +2 -0
  22. data/_doc/lib/restman/exception.rdoc +6 -0
  23. data/_doc/lib/restman/exceptions/timeout.rdoc +4 -0
  24. data/_doc/lib/restman/exceptions.rdoc +4 -0
  25. data/_doc/lib/restman/log=.rdoc +3 -0
  26. data/_doc/lib/restman/params_array/new.rdoc +20 -0
  27. data/_doc/lib/restman/params_array/process_pair.rdoc +4 -0
  28. data/_doc/lib/restman/params_array.rdoc +11 -0
  29. data/_doc/lib/restman/platform/jruby?.rdoc +4 -0
  30. data/_doc/lib/restman/platform/mac_mri?.rdoc +5 -0
  31. data/_doc/lib/restman/proxy.rdoc +2 -0
  32. data/_doc/lib/restman/proxy_set?.rdoc +5 -0
  33. data/_doc/lib/restman/raw_response/new.rdoc +6 -0
  34. data/_doc/lib/restman/raw_response.rdoc +10 -0
  35. data/_doc/lib/restman/request/cookie_jar.rdoc +3 -0
  36. data/_doc/lib/restman/request/cookies.rdoc +11 -0
  37. data/_doc/lib/restman/request/default_headers.rdoc +5 -0
  38. data/_doc/lib/restman/request/default_ssl_cert_store.rdoc +8 -0
  39. data/_doc/lib/restman/request/init/cookie_jar.rdoc +55 -0
  40. data/_doc/lib/restman/request/init/http_method.rdoc +15 -0
  41. data/_doc/lib/restman/request/make_cookie_header.rdoc +8 -0
  42. data/_doc/lib/restman/request/make_headers.rdoc +25 -0
  43. data/_doc/lib/restman/request/maybe_convert_extension.rdoc +18 -0
  44. data/_doc/lib/restman/request/process_result.rdoc +4 -0
  45. data/_doc/lib/restman/request/proxy_uri.rdoc +7 -0
  46. data/_doc/lib/restman/request/stringify_headers.rdoc +9 -0
  47. data/_doc/lib/restman/request/use_ssl.rdoc +4 -0
  48. data/_doc/lib/restman/request.rdoc +46 -0
  49. data/_doc/lib/restman/reset_before_execution_procs.rdoc +1 -0
  50. data/_doc/lib/restman/resource/[].rdoc +25 -0
  51. data/_doc/lib/restman/resource.rdoc +33 -0
  52. data/_doc/lib/restman/response/body.rdoc +7 -0
  53. data/_doc/lib/restman/response/create.rdoc +10 -0
  54. data/_doc/lib/restman/response/fix_encoding.rdoc +2 -0
  55. data/_doc/lib/restman/statuses.rdoc +11 -0
  56. data/_doc/lib/restman/utils/cgi_parse_header.rdoc +6 -0
  57. data/_doc/lib/restman/utils/encode_query_string.rdoc +90 -0
  58. data/_doc/lib/restman/utils/escape.rdoc +11 -0
  59. data/_doc/lib/restman/utils/flatten_params.rdoc +16 -0
  60. data/_doc/lib/restman/utils/get_encoding_from_headers.rdoc +24 -0
  61. data/_doc/lib/restman.rdoc +43 -0
  62. data/bin/console +15 -0
  63. data/lib/restman/abstract_response.rb +13 -60
  64. data/lib/restman/exception.rb +43 -0
  65. data/lib/restman/exceptions/exception_with_response.rb +7 -0
  66. data/lib/restman/exceptions/exceptions_map.rb +26 -0
  67. data/lib/restman/exceptions/request_failed.rb +15 -0
  68. data/lib/restman/exceptions/server_broke_connection.rb +13 -0
  69. data/lib/restman/exceptions/timeout.rb +37 -0
  70. data/lib/restman/params_array/process_pair.rb +39 -0
  71. data/lib/restman/params_array.rb +3 -48
  72. data/lib/restman/payload/base.rb +57 -0
  73. data/lib/restman/payload/multipart/write_content_disposition.rb +88 -0
  74. data/lib/restman/payload/multipart.rb +56 -0
  75. data/lib/restman/payload/streamed.rb +22 -0
  76. data/lib/restman/payload/url_encoded.rb +14 -0
  77. data/lib/restman/payload.rb +14 -196
  78. data/lib/restman/platform.rb +2 -18
  79. data/lib/restman/raw_response.rb +2 -14
  80. data/lib/restman/request/default_ssl_cert_store.rb +13 -0
  81. data/lib/restman/request/fetch_body_to_tempfile.rb +58 -0
  82. data/lib/restman/request/init/cookie_jar.rb +65 -0
  83. data/lib/restman/request/init/ssl_opts.rb +70 -0
  84. data/lib/restman/request/init/url/add_query_from_headers.rb +51 -0
  85. data/lib/restman/request/init/url/normalize_url.rb +19 -0
  86. data/lib/restman/request/init/url.rb +40 -0
  87. data/lib/restman/request/init.rb +106 -0
  88. data/lib/restman/request/log_request.rb +46 -0
  89. data/lib/restman/request/make_cookie_header.rb +16 -0
  90. data/lib/restman/request/make_headers.rb +39 -0
  91. data/lib/restman/request/maybe_convert_extension.rb +28 -0
  92. data/lib/restman/request/net_http_object.rb +25 -0
  93. data/lib/restman/request/process_result.rb +36 -0
  94. data/lib/restman/request/proxy_uri.rb +31 -0
  95. data/lib/restman/request/stringify_headers.rb +36 -0
  96. data/lib/restman/request/transmit.rb +152 -0
  97. data/lib/restman/request.rb +60 -745
  98. data/lib/restman/resource.rb +2 -60
  99. data/lib/restman/response.rb +3 -21
  100. data/lib/restman/statuses.rb +75 -0
  101. data/lib/restman/statuses_compatibility.rb +18 -0
  102. data/lib/restman/utils.rb +10 -206
  103. data/lib/restman/version.rb +1 -1
  104. data/lib/restman.rb +24 -62
  105. data/matrixeval.yml +19 -1
  106. data/rest-man.gemspec +4 -10
  107. data/spec/integration/capath_digicert/ce5e74ef.0 +1 -1
  108. data/spec/integration/request_spec.rb +13 -1
  109. data/spec/spec_helper.rb +11 -0
  110. data/spec/unit/abstract_response_spec.rb +14 -0
  111. data/spec/unit/exception_spec.rb +64 -0
  112. data/spec/unit/exceptions/backwards_campatibility_spec.rb +29 -0
  113. data/spec/unit/exceptions/exceptions_map_spec.rb +89 -0
  114. data/spec/unit/exceptions/request_failed_spec.rb +51 -0
  115. data/spec/unit/exceptions/server_broke_connection_spec.rb +8 -0
  116. data/spec/unit/exceptions/timeout_spec.rb +59 -0
  117. data/spec/unit/params_array/process_pair_spec.rb +59 -0
  118. data/spec/unit/params_array_spec.rb +15 -10
  119. data/spec/unit/payload/multipart_spec.rb +116 -0
  120. data/spec/unit/payload/streamed_spec.rb +48 -0
  121. data/spec/unit/payload/url_encoded_spec.rb +65 -0
  122. data/spec/unit/payload_spec.rb +0 -208
  123. data/spec/unit/request/init/url/add_query_from_headers_spec.rb +40 -0
  124. data/spec/unit/request/init/url/normalize_url_spec.rb +25 -0
  125. data/spec/unit/request/init_spec.rb +83 -0
  126. data/spec/unit/request_spec.rb +143 -151
  127. data/spec/unit/utils_spec.rb +96 -104
  128. metadata +132 -16
  129. data/lib/restman/exceptions.rb +0 -238
  130. data/lib/restman/windows/root_certs.rb +0 -105
  131. data/lib/restman/windows.rb +0 -8
  132. data/spec/unit/exceptions_spec.rb +0 -108
  133. data/spec/unit/windows/root_certs_spec.rb +0 -22
@@ -0,0 +1,55 @@
1
+ :call-seq:
2
+ cookie_jar(uri, headers, args) -> HTTP::CookieJar
3
+
4
+ Process cookies passed as hash or as HTTP::CookieJar. For backwards
5
+ compatibility, these may be passed as a :cookies option masquerading
6
+ inside the headers hash. To avoid confusion, if :cookies is passed in
7
+ both headers and Request#initialize, raise an error.
8
+
9
+ [cookies may be a:]
10
+
11
+ - Hash{String/Symbol => String}
12
+ - Array<HTTP::Cookie>
13
+ - HTTP::CookieJar
14
+
15
+ Passing as a hash:
16
+ Keys may be symbols or strings. Values must be strings.
17
+ Infer the domain name from the request URI and allow subdomains (as
18
+ though '.example.com' had been set in a Set-Cookie header). Assume a
19
+ path of '/'.
20
+
21
+ RestMan::Request.new(url: 'http://example.com', method: :get,
22
+ :cookies => {:foo => 'Value', 'bar' => '123'}
23
+ )
24
+
25
+ results in cookies as though set from the server by:
26
+ Set-Cookie: foo=Value; Domain=.example.com; Path=/
27
+ Set-Cookie: bar=123; Domain=.example.com; Path=/
28
+
29
+ which yields a client cookie header of:
30
+ Cookie: foo=Value; bar=123
31
+
32
+ Passing as HTTP::CookieJar, which will be passed through directly:
33
+
34
+ jar = HTTP::CookieJar.new
35
+ jar.add(HTTP::Cookie.new('foo', 'Value', domain: 'example.com',
36
+ path: '/', for_domain: false))
37
+
38
+ RestMan::Request.new(..., :cookies => jar)
39
+
40
+ [Parameters:]
41
+
42
+ - *uri* (URI::HTTP) -- The URI for the request. This will be used to
43
+ infer the domain name for cookies passed as strings in a hash. To avoid
44
+ this implicit behavior, pass a full cookie jar or use HTTP::Cookie hash
45
+ values.
46
+ - *headers* (Hash) -- The headers hash from which to pull the :cookies
47
+ option. MUTATION NOTE: This key will be deleted from the hash if
48
+ present.
49
+ - *args* (Hash) -- The options passed to Request#initialize. This hash
50
+ will be used as another potential source for the :cookies key.
51
+ These args will not be mutated.
52
+
53
+ [Returns:]
54
+
55
+ - (HTTP::CookieJar) -- A cookie jar containing the parsed cookies.
@@ -0,0 +1,15 @@
1
+ :call-seq:
2
+ http_method(args) -> string
3
+
4
+ Parse `args[:method]` and return a normalized string version.
5
+
6
+ Raise ArgumentError if the `args[:method]` is falsy, but otherwise do no
7
+ validation.
8
+
9
+ [Parameters:]
10
+
11
+ - *args* (Hash)
12
+
13
+ [See Also:]
14
+
15
+ - net_http_request_class
@@ -0,0 +1,8 @@
1
+ :call-seq:
2
+ make_cookie_header -> string or nil
3
+
4
+ Render a Cookie HTTP request header from the contents of the @cookie_jar,
5
+ or nil if the jar is empty.
6
+
7
+ [See Also]
8
+ - Request#cookie_jar
@@ -0,0 +1,25 @@
1
+ :call-seq:
2
+ make_headers(user_headers) -> Hash<String, String>
3
+
4
+ Generate headers for use by a request. Header keys will be stringified
5
+ using `#stringify_headers` to normalize them as capitalized strings.
6
+
7
+ The final headers consist of:
8
+ - default headers from #default_headers
9
+ - user_headers provided here
10
+ - headers from the payload object (e.g. Content-Type, Content-Lenth)
11
+ - cookie headers from #make_cookie_header
12
+
13
+ BUG: stringify_headers does not alter the capitalization of headers that
14
+ are passed as strings, it only normalizes those passed as symbols. This
15
+ behavior will probably remain for a while for compatibility, but it means
16
+ that the warnings that attempt to detect accidental header overrides may
17
+ not always work.
18
+ https://github.com/rest-man/rest-man/issues/599
19
+
20
+ [Parameters:]
21
+
22
+ - user_headers (Hash) -- User-provided headers to include
23
+
24
+ [Returns]
25
+ - (Hash<String, String>) -- A hash of HTTP headers => values
@@ -0,0 +1,18 @@
1
+ :call-seq:
2
+ maybe_convert_extension(ext) -> string
3
+
4
+ Given a MIME type or file extension, return either a MIME type or, if
5
+ none is found, the input unchanged.
6
+
7
+ >> maybe_convert_extension('json')
8
+ => 'application/json'
9
+
10
+ >> maybe_convert_extension('unknown')
11
+ => 'unknown'
12
+
13
+ >> maybe_convert_extension('application/xml')
14
+ => 'application/xml'
15
+
16
+ [Parameters:]
17
+
18
+ - ext (String)
@@ -0,0 +1,4 @@
1
+ [Parameters:]
2
+
3
+ - *res* -- The Net::HTTP response object
4
+ - *start_time* (Time) -- Time of request start
@@ -0,0 +1,7 @@
1
+ :call-seq:
2
+ proxy_uri -> URI or boolean or nil
3
+
4
+ The proxy URI for this request. If `:proxy` was provided on this request,
5
+ use it over `RestMan.proxy`.
6
+
7
+ Return false if a proxy was explicitly set and is falsy.
@@ -0,0 +1,9 @@
1
+ :call-seq:
2
+ stringify_headers(headers) -> Object
3
+
4
+ Return a hash of headers whose keys are capitalized strings
5
+
6
+ BUG: stringify_headers does not fix the capitalization of headers that
7
+ are already Strings. Leaving this behavior as is for now for
8
+ backwards compatibility.
9
+ https://github.com/rest-man/rest-man/issues/599
@@ -0,0 +1,4 @@
1
+ :call-seq:
2
+ use_ssl? -> boolean
3
+
4
+ Return true if the request URI will use HTTPS.
@@ -0,0 +1,46 @@
1
+ This class is used internally by RestMan to send the request, but you can also
2
+ call it directly if you'd like to use a method not supported by the
3
+ main API. For example:
4
+
5
+ RestMan::Request.execute(:method => :head, :url => 'http://example.com')
6
+
7
+ Mandatory parameters:
8
+ * :method
9
+ * :url
10
+ Optional parameters (have a look at ssl and/or uri for some explanations):
11
+ * :headers a hash containing the request headers
12
+ * :cookies may be a Hash{String/Symbol => String} of cookie values, an
13
+ Array<HTTP::Cookie>, or an HTTP::CookieJar containing cookies. These
14
+ will be added to a cookie jar before the request is sent.
15
+ * :user and :password for basic auth, will be replaced by a user/password available in the :url
16
+ * :block_response call the provided block with the HTTPResponse as parameter
17
+ * :raw_response return a low-level RawResponse instead of a Response
18
+ * :log Set the log for this request only, overriding RestMan.log, if
19
+ any.
20
+ * :stream_log_percent (Only relevant with :raw_response => true) Customize
21
+ the interval at which download progress is logged. Defaults to every
22
+ 10% complete.
23
+ * :max_retries maximum number of times to retry an idempotent request (default to 1)
24
+ * :max_redirects maximum number of redirections (default to 10)
25
+ * :proxy An HTTP proxy URI to use for this request. Any value here
26
+ (including nil) will override RestMan.proxy.
27
+ * :verify_ssl enable ssl verification, possible values are constants from
28
+ OpenSSL::SSL::VERIFY_*, defaults to OpenSSL::SSL::VERIFY_PEER
29
+ * :read_timeout, :open_timeout and :write_timeout are how long to wait for a response and
30
+ to open a connection, in seconds. Pass nil to disable the timeout.
31
+ * :timeout can be used to set: read_timeout, open_timeout and write_timeout
32
+ * :keep_alive_timeout sets seconds to reuse the connection of the previous request. (default to 2 seconds)
33
+ * :ssl_client_cert, :ssl_client_key, :ssl_ca_file, :ssl_ca_path,
34
+ :ssl_cert_store, :ssl_verify_callback, :ssl_verify_callback_warnings
35
+ * :ssl_version specifies the SSL version for the underlying Net::HTTP connection
36
+ * :ssl_min_version specifies the minimum SSL version for the underlying Net::HTTP connection
37
+ * :ssl_max_version specifies the maximum SSL version for the underlying Net::HTTP connection
38
+ * :ssl_timeout sets the SSL timeout seconds
39
+ * :ssl_ciphers sets SSL ciphers for the connection. See
40
+ OpenSSL::SSL::SSLContext#ciphers=
41
+ * :before_execution_proc a Proc to call before executing the request. This
42
+ proc, like procs from RestMan.before_execution_procs, will be
43
+ called with the HTTP request and request params.
44
+ * :close_on_empty_response default to false
45
+ * :local_host sets the local address for the outgoing connection
46
+ * :local_port sets the local port for the outgoing connection
@@ -0,0 +1 @@
1
+ Reset the procs to be called before each request is executed.
@@ -0,0 +1,25 @@
1
+ Construct a subresource, preserving authentication.
2
+
3
+ Example:
4
+
5
+ site = RestMan::Resource.new('http://example.com', 'adam', 'mypasswd')
6
+ site['posts/1/comments'].post 'Good article.', :content_type => 'text/plain'
7
+
8
+ This is especially useful if you wish to define your site in one place and
9
+ call it in multiple locations:
10
+
11
+ def orders
12
+ RestMan::Resource.new('http://example.com/orders', 'admin', 'mypasswd')
13
+ end
14
+
15
+ orders.get # GET http://example.com/orders
16
+ orders['1'].get # GET http://example.com/orders/1
17
+ orders['1/items'].delete # DELETE http://example.com/orders/1/items
18
+
19
+ Nest resources as far as you want:
20
+
21
+ site = RestMan::Resource.new('http://example.com')
22
+ posts = site['posts']
23
+ first_post = posts['1']
24
+ comments = first_post['comments']
25
+ comments.post 'Hello', :content_type => 'text/plain'
@@ -0,0 +1,33 @@
1
+ A class that can be instantiated for access to a RESTful resource,
2
+ including authentication.
3
+
4
+ Example:
5
+
6
+ resource = RestMan::Resource.new('http://some/resource')
7
+ jpg = resource.get(:accept => 'image/jpg')
8
+
9
+ With HTTP basic authentication:
10
+
11
+ resource = RestMan::Resource.new('http://protected/resource', :user => 'user', :password => 'password')
12
+ resource.delete
13
+
14
+ With a timeout (seconds):
15
+
16
+ RestMan::Resource.new('http://slow', :read_timeout => 10)
17
+
18
+ With an open timeout (seconds):
19
+
20
+ RestMan::Resource.new('http://behindfirewall', :open_timeout => 10)
21
+
22
+ You can also use resources to share common headers. For headers keys,
23
+ symbols are converted to strings. Example:
24
+
25
+ resource = RestMan::Resource.new('http://some/resource', :headers => { :client_version => 1 })
26
+
27
+ This header will be transported as X-Client-Version (notice the X prefix,
28
+ capitalization and hyphens)
29
+
30
+ Use the [] syntax to allocate subresources:
31
+
32
+ site = RestMan::Resource.new('http://example.com', :user => 'adam', :password => 'mypasswd')
33
+ site['posts/1/comments'].post 'Good article.', :content_type => 'text/plain'
@@ -0,0 +1,7 @@
1
+ :call-seq:
2
+ body -> string
3
+
4
+ Return the HTTP response body.
5
+
6
+ Future versions of RestMan will deprecate treating response objects
7
+ directly as strings, so it will be necessary to call `.body`.
@@ -0,0 +1,10 @@
1
+ Initialize a Response object. Because RestMan::Response is
2
+ (unfortunately) a subclass of String for historical reasons,
3
+ Response.create is the preferred initializer.
4
+
5
+ [Parameters:]
6
+
7
+ - *body* (String, nil) -- The response body from the Net::HTTPResponse
8
+ - *net_http_res* (Net::HTTPResponse)
9
+ - *request* (RestMan::Request)
10
+ - *start_time* (Time)
@@ -0,0 +1,2 @@
1
+ Set the String encoding according to the 'Content-Type: charset' header,
2
+ if possible.
@@ -0,0 +1,11 @@
1
+ Hash of HTTP status code => message.
2
+
3
+ - *1xx*: Informational -- Request received, continuing process
4
+ - *2xx*: Success -- The action was successfully received, understood, and accepted
5
+ - *3xx*: Redirection -- Further action must be taken in order to complete the request
6
+ - *4xx*: Client Error -- The request contains bad syntax or cannot be fulfilled
7
+ - *5xx*: Server Error -- The server failed to fulfill an apparently valid request
8
+
9
+ [See Also:]
10
+
11
+ http://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml
@@ -0,0 +1,6 @@
1
+ :call-seq:
2
+ cgi_parse_header(line) -> Array(String, Hash)
3
+
4
+ Parse a Content-Type like header.
5
+
6
+ Return the main content-type and a hash of params.
@@ -0,0 +1,90 @@
1
+ :call-seq:
2
+ encode_query_string(object) -> string
3
+
4
+ Serialize a ruby object into HTTP query string parameters.
5
+
6
+ There is no standard for doing this, so we choose our own slightly
7
+ idiosyncratic format. The output closely matches the format understood by
8
+ Rails, Rack, and PHP.
9
+
10
+ If you don't want handling of complex objects and only want to handle
11
+ simple flat hashes, you may want to use `URI.encode_www_form` instead,
12
+ which implements HTML5-compliant URL encoded form data.
13
+
14
+ [Examples:]
15
+
16
+ Simple hashes
17
+
18
+ >> encode_query_string({foo: 123, bar: 456})
19
+ => 'foo=123&bar=456'
20
+
21
+ Simple arrays
22
+
23
+ >> encode_query_string({foo: [1,2,3]})
24
+ => 'foo[]=1&foo[]=2&foo[]=3'
25
+
26
+ Nested hashes
27
+
28
+ >> encode_query_string({outer: {foo: 123, bar: 456}})
29
+ => 'outer[foo]=123&outer[bar]=456'
30
+
31
+ Deeply nesting
32
+
33
+ >> encode_query_string({coords: [{x: 1, y: 0}, {x: 2}, {x: 3}]})
34
+ => 'coords[][x]=1&coords[][y]=0&coords[][x]=2&coords[][x]=3'
35
+
36
+ Null and empty values
37
+
38
+ >> encode_query_string({string: '', empty: nil, list: [], hash: {}})
39
+ => 'string=&empty&list&hash'
40
+
41
+ Nested nulls
42
+
43
+ >> encode_query_string({foo: {string: '', empty: nil}})
44
+ => 'foo[string]=&foo[empty]'
45
+
46
+ Multiple fields with the same name using ParamsArray
47
+
48
+ >> encode_query_string(RestMan::ParamsArray.new([[:foo, 1], [:foo, 2], [:foo, 3]]))
49
+ => 'foo=1&foo=2&foo=3'
50
+
51
+ Nested ParamsArray
52
+
53
+ >> encode_query_string({foo: RestMan::ParamsArray.new([[:a, 1], [:a, 2]])})
54
+ => 'foo[a]=1&foo[a]=2'
55
+
56
+ >> encode_query_string(RestMan::ParamsArray.new([[:foo, {a: 1}], [:foo, {a: 2}]]))
57
+ => 'foo[a]=1&foo[a]=2'
58
+
59
+
60
+
61
+ [Parameters:]
62
+
63
+ - object (Hash,ParamsArray) -- The object to serialize
64
+
65
+ [Returns:]
66
+
67
+ - (String) -- A string appropriate for use as an HTTP query string
68
+
69
+ [See Also:]
70
+
71
+ - flatten_params
72
+ - URI.encode_www_form
73
+ - Object#to_query in ActiveSupport
74
+ - http://php.net/manual/en/function.http-build-query.php
75
+ http_build_query in PHP
76
+ - Rack::Utils.build_nested_query in Rack
77
+
78
+ Notable differences from the ActiveSupport implementation:
79
+
80
+ - Empty hash and empty array are treated the same as nil instead of being
81
+ omitted entirely from the output. Rather than disappearing, they will
82
+ appear to be nil instead.
83
+
84
+ It's most common to pass a Hash as the object to serialize, but you can
85
+ also use a ParamsArray if you want to be able to pass the same key with
86
+ multiple values and not use the rack/rails array convention.
87
+
88
+ [since:]
89
+
90
+ - 2.0.0
@@ -0,0 +1,11 @@
1
+ Encode string for safe transport by URI or form encoding. This uses a CGI
2
+ style escape, which transforms ` ` into `+` and various special
3
+ characters into percent encoded forms.
4
+
5
+ This calls URI.encode_www_form_component for the implementation. The only
6
+ difference between this and CGI.escape is that it does not escape `*`.
7
+ http://stackoverflow.com/questions/25085992/
8
+
9
+ [See Also:]
10
+
11
+ - URI.encode_www_form_component
@@ -0,0 +1,16 @@
1
+ Transform deeply nested param containers into a flat array of [key,
2
+ value] pairs.
3
+
4
+ *Examples:*
5
+
6
+ >> flatten_params({key1: {key2: 123}})
7
+ => [["key1[key2]", 123]]
8
+
9
+ >> flatten_params({key1: {key2: 123, arr: [1,2,3]}})
10
+ => [["key1[key2]", 123], ["key1[arr][]", 1], ["key1[arr][]", 2], ["key1[arr][]", 3]]
11
+
12
+ [Parameters:]
13
+
14
+ - object (Hash, ParamsArray) -- The container to flatten
15
+ - uri_escape (Boolean) -- Whether to URI escape keys and values
16
+ - parent_key (String) -- Should not be passed (used for recursion)
@@ -0,0 +1,24 @@
1
+ :call-seq:
2
+ get_encoding_from_headers(headers) -> String or nil
3
+
4
+ Return encoding from an HTTP header hash.
5
+
6
+ We use the RFC 7231 specification and do not impose a default encoding on
7
+ text. This differs from the older RFC 2616 behavior, which specifies
8
+ using ISO-8859-1 for text/* content types without a charset.
9
+
10
+ Strings will use the default encoding when this method returns nil. This
11
+ default is likely to be UTF-8 for Ruby >= 2.0
12
+
13
+ [Parameters:]
14
+
15
+ - headers (Hash<Symbol, String>)
16
+
17
+ [Returns:]
18
+
19
+ - (String, nil) -- Return the string encoding or nil if no header is found.
20
+
21
+ Examples:
22
+
23
+ get_encoding_from_headers({:content_type => 'text/plain; charset=UTF-8'})
24
+ => "UTF-8"
@@ -0,0 +1,43 @@
1
+ This module's static methods are the entry point for using the REST client.
2
+
3
+ # GET
4
+ xml = RestMan.get 'http://example.com/resource'
5
+ jpg = RestMan.get 'http://example.com/resource', :accept => 'image/jpg'
6
+
7
+ # authentication and SSL
8
+ RestMan.get 'https://user:password@example.com/private/resource'
9
+
10
+ # POST or PUT with a hash sends parameters as a urlencoded form body
11
+ RestMan.post 'http://example.com/resource', :param1 => 'one'
12
+
13
+ # nest hash parameters
14
+ RestMan.post 'http://example.com/resource', :nested => { :param1 => 'one' }
15
+
16
+ # POST and PUT with raw payloads
17
+ RestMan.post 'http://example.com/resource', 'the post body', :content_type => 'text/plain'
18
+ RestMan.post 'http://example.com/resource.xml', xml_doc
19
+ RestMan.put 'http://example.com/resource.pdf', File.read('my.pdf'), :content_type => 'application/pdf'
20
+
21
+ # DELETE
22
+ RestMan.delete 'http://example.com/resource'
23
+
24
+ # retrieve the response http code and headers
25
+ res = RestMan.get 'http://example.com/some.jpg'
26
+ res.code # => 200
27
+ res.headers[:content_type] # => 'image/jpg'
28
+
29
+ # HEAD
30
+ RestMan.head('http://example.com').headers
31
+
32
+ To use with a proxy, just set RestMan.proxy to the proper http proxy:
33
+
34
+ RestMan.proxy = "http://proxy.example.com/"
35
+
36
+ Or inherit the proxy from the environment:
37
+
38
+ RestMan.proxy = ENV['http_proxy']
39
+
40
+ For live tests of RestMan, try using http://rest-test.heroku.com, which echoes back information about the rest call:
41
+
42
+ >> RestMan.put 'http://rest-test.heroku.com/resource', :foo => 'baz'
43
+ => "PUT http://rest-test.heroku.com/resource with a 7 byte payload, content type application/x-www-form-urlencoded {\"foo\"=>\"baz\"}"
data/bin/console ADDED
@@ -0,0 +1,15 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require "bundler/setup"
5
+ require "restman"
6
+
7
+ # You can add fixtures and/or initialization code here to make experimenting
8
+ # with your gem easier. You can also use a different console, if you like.
9
+
10
+ # (If you use this, don't forget to add pry to your Gemfile!)
11
+ # require "pry"
12
+ # Pry.start
13
+
14
+ require "irb"
15
+ IRB.start(__FILE__)
@@ -31,12 +31,15 @@ module RestMan
31
31
  @code ||= @net_http_res.code.to_i
32
32
  end
33
33
 
34
+ def success?
35
+ (200..299).include?(code)
36
+ end
37
+
34
38
  def history
35
39
  @history ||= request.redirection_history || []
36
40
  end
37
41
 
38
- # A hash of the headers, beautified with symbols and underscores.
39
- # e.g. "Content-type" will become :content_type.
42
+ # :include: _doc/lib/restman/abstract_response/headers.rdoc
40
43
  def headers
41
44
  @headers ||= AbstractResponse.beautify_headers(@net_http_res.to_hash)
42
45
  end
@@ -46,9 +49,7 @@ module RestMan
46
49
  @raw_headers ||= @net_http_res.to_hash
47
50
  end
48
51
 
49
- # @param [Net::HTTPResponse] net_http_res
50
- # @param [RestMan::Request] request
51
- # @param [Time] start_time
52
+ # :include: _doc/lib/restman/abstract_response/response_set_vars.rdoc
52
53
  def response_set_vars(net_http_res, request, start_time)
53
54
  @net_http_res = net_http_res
54
55
  @request = request
@@ -65,16 +66,7 @@ module RestMan
65
66
  history
66
67
  end
67
68
 
68
- # Hash of cookies extracted from response headers.
69
- #
70
- # NB: This will return only cookies whose domain matches this request, and
71
- # may not even return all of those cookies if there are duplicate names.
72
- # Use the full cookie_jar for more nuanced access.
73
- #
74
- # @see #cookie_jar
75
- #
76
- # @return [Hash]
77
- #
69
+ # :include: _doc/lib/restman/abstract_response/cookies.rdoc
78
70
  def cookies
79
71
  hash = {}
80
72
 
@@ -85,10 +77,7 @@ module RestMan
85
77
  hash
86
78
  end
87
79
 
88
- # Cookie jar extracted from response headers.
89
- #
90
- # @return [HTTP::CookieJar]
91
- #
80
+ # :include: _doc/lib/restman/abstract_response/cookie_jar.rdoc
92
81
  def cookie_jar
93
82
  return @cookie_jar if defined?(@cookie_jar) && @cookie_jar
94
83
 
@@ -100,16 +89,7 @@ module RestMan
100
89
  @cookie_jar = jar
101
90
  end
102
91
 
103
- # Return the default behavior corresponding to the response code:
104
- #
105
- # For 20x status codes: return the response itself
106
- #
107
- # For 30x status codes:
108
- # 301, 302, 307: redirect GET / HEAD if there is a Location header
109
- # 303: redirect, changing method to GET, if there is a Location header
110
- #
111
- # For all other responses, raise a response exception
112
- #
92
+ # :include: _doc/lib/restman/abstract_response/return.rdoc
113
93
  def return!(&block)
114
94
  case code
115
95
  when 200..207
@@ -139,14 +119,12 @@ module RestMan
139
119
  "#{code} #{STATUSES[code]} | #{(headers[:content_type] || '').gsub(/;.*$/, '')} #{size} bytes\n"
140
120
  end
141
121
 
142
- # Follow a redirection response by making a new HTTP request to the
143
- # redirection target.
122
+ # :include: _doc/lib/restman/abstract_response/follow_redirection.rdoc
144
123
  def follow_redirection(&block)
145
124
  _follow_redirection(request.args.dup, &block)
146
125
  end
147
126
 
148
- # Follow a redirection response, but change the HTTP method to GET and drop
149
- # the payload from the original request.
127
+ # :include: _doc/lib/restman/abstract_response/follow_get_redirection.rdoc
150
128
  def follow_get_redirection(&block)
151
129
  new_args = request.args.dup
152
130
  new_args[:method] = :get
@@ -155,27 +133,7 @@ module RestMan
155
133
  _follow_redirection(new_args, &block)
156
134
  end
157
135
 
158
- # Convert headers hash into canonical form.
159
- #
160
- # Header names will be converted to lowercase symbols with underscores
161
- # instead of hyphens.
162
- #
163
- # Headers specified multiple times will be joined by comma and space,
164
- # except for Set-Cookie, which will always be an array.
165
- #
166
- # Per RFC 2616, if a server sends multiple headers with the same key, they
167
- # MUST be able to be joined into a single header by a comma. However,
168
- # Set-Cookie (RFC 6265) cannot because commas are valid within cookie
169
- # definitions. The newer RFC 7230 notes (3.2.2) that Set-Cookie should be
170
- # handled as a special case.
171
- #
172
- # http://tools.ietf.org/html/rfc2616#section-4.2
173
- # http://tools.ietf.org/html/rfc7230#section-3.2.2
174
- # http://tools.ietf.org/html/rfc6265
175
- #
176
- # @param headers [Hash]
177
- # @return [Hash]
178
- #
136
+ # :include: _doc/lib/restman/abstract_response/beautify_headers.rdoc
179
137
  def self.beautify_headers(headers)
180
138
  headers.inject({}) do |out, (key, value)|
181
139
  key_sym = key.tr('-', '_').downcase.to_sym
@@ -193,12 +151,7 @@ module RestMan
193
151
 
194
152
  private
195
153
 
196
- # Follow a redirection
197
- #
198
- # @param new_args [Hash] Start with this hash of arguments for the
199
- # redirection request. The hash will be mutated, so be sure to dup any
200
- # existing hash that should not be modified.
201
- #
154
+ # :include: _doc/lib/restman/abstract_response/_follow_redirection.rdoc
202
155
  def _follow_redirection(new_args, &block)
203
156
 
204
157
  # parse location header and merge into existing URL