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
@@ -1,38 +1,5 @@
1
1
  module RestMan
2
- # A class that can be instantiated for access to a RESTful resource,
3
- # including authentication.
4
- #
5
- # Example:
6
- #
7
- # resource = RestMan::Resource.new('http://some/resource')
8
- # jpg = resource.get(:accept => 'image/jpg')
9
- #
10
- # With HTTP basic authentication:
11
- #
12
- # resource = RestMan::Resource.new('http://protected/resource', :user => 'user', :password => 'password')
13
- # resource.delete
14
- #
15
- # With a timeout (seconds):
16
- #
17
- # RestMan::Resource.new('http://slow', :read_timeout => 10)
18
- #
19
- # With an open timeout (seconds):
20
- #
21
- # RestMan::Resource.new('http://behindfirewall', :open_timeout => 10)
22
- #
23
- # You can also use resources to share common headers. For headers keys,
24
- # symbols are converted to strings. Example:
25
- #
26
- # resource = RestMan::Resource.new('http://some/resource', :headers => { :client_version => 1 })
27
- #
28
- # This header will be transported as X-Client-Version (notice the X prefix,
29
- # capitalization and hyphens)
30
- #
31
- # Use the [] syntax to allocate subresources:
32
- #
33
- # site = RestMan::Resource.new('http://example.com', :user => 'adam', :password => 'mypasswd')
34
- # site['posts/1/comments'].post 'Good article.', :content_type => 'text/plain'
35
- #
2
+ # :include: _doc/lib/restman/resource.rdoc
36
3
  class Resource
37
4
  attr_reader :url, :options, :block
38
5
 
@@ -131,32 +98,7 @@ module RestMan
131
98
  options[:log] || RestMan.log
132
99
  end
133
100
 
134
- # Construct a subresource, preserving authentication.
135
- #
136
- # Example:
137
- #
138
- # site = RestMan::Resource.new('http://example.com', 'adam', 'mypasswd')
139
- # site['posts/1/comments'].post 'Good article.', :content_type => 'text/plain'
140
- #
141
- # This is especially useful if you wish to define your site in one place and
142
- # call it in multiple locations:
143
- #
144
- # def orders
145
- # RestMan::Resource.new('http://example.com/orders', 'admin', 'mypasswd')
146
- # end
147
- #
148
- # orders.get # GET http://example.com/orders
149
- # orders['1'].get # GET http://example.com/orders/1
150
- # orders['1/items'].delete # DELETE http://example.com/orders/1/items
151
- #
152
- # Nest resources as far as you want:
153
- #
154
- # site = RestMan::Resource.new('http://example.com')
155
- # posts = site['posts']
156
- # first_post = posts['1']
157
- # comments = first_post['comments']
158
- # comments.post 'Hello', :content_type => 'text/plain'
159
- #
101
+ # :include: _doc/lib/restman/resource/[].rdoc
160
102
  def [](suburl, &new_block)
161
103
  case
162
104
  when block_given? then self.class.new(concat_urls(url, suburl), options, &new_block)
@@ -6,13 +6,7 @@ module RestMan
6
6
 
7
7
  include AbstractResponse
8
8
 
9
- # Return the HTTP response body.
10
- #
11
- # Future versions of RestMan will deprecate treating response objects
12
- # directly as strings, so it will be necessary to call `.body`.
13
- #
14
- # @return [String]
15
- #
9
+ # :include: _doc/lib/restman/response/body.rdoc
16
10
  def body
17
11
  # Benchmarking suggests that "#{self}" is fastest, and that caching the
18
12
  # body string in an instance variable doesn't make it enough faster to be
@@ -21,15 +15,11 @@ module RestMan
21
15
  end
22
16
 
23
17
  # Convert the HTTP response body to a pure String object.
24
- #
25
- # @return [String]
26
18
  def to_s
27
19
  body
28
20
  end
29
21
 
30
22
  # Convert the HTTP response body to a pure String object.
31
- #
32
- # @return [String]
33
23
  def to_str
34
24
  body
35
25
  end
@@ -38,14 +28,7 @@ module RestMan
38
28
  "<RestMan::Response #{code.inspect} #{body_truncated(10).inspect}>"
39
29
  end
40
30
 
41
- # Initialize a Response object. Because RestMan::Response is
42
- # (unfortunately) a subclass of String for historical reasons,
43
- # Response.create is the preferred initializer.
44
- #
45
- # @param [String, nil] body The response body from the Net::HTTPResponse
46
- # @param [Net::HTTPResponse] net_http_res
47
- # @param [RestMan::Request] request
48
- # @param [Time] start_time
31
+ # :include: _doc/lib/restman/response/create.rdoc
49
32
  def self.create(body, net_http_res, request, start_time=nil)
50
33
  result = self.new(body || '')
51
34
 
@@ -55,8 +38,7 @@ module RestMan
55
38
  result
56
39
  end
57
40
 
58
- # Set the String encoding according to the 'Content-Type: charset' header,
59
- # if possible.
41
+ # :include: _doc/lib/restman/response/fix_encoding.rdoc
60
42
  def self.fix_encoding(response)
61
43
  charset = RestMan::Utils.get_encoding_from_headers(response.headers)
62
44
  encoding = nil
@@ -0,0 +1,75 @@
1
+ module RestMan
2
+
3
+ # :include: _doc/lib/restman/statuses.rdoc
4
+ STATUSES = {
5
+ 100 => 'Continue',
6
+ 101 => 'Switching Protocols',
7
+ 102 => 'Processing', #WebDAV
8
+
9
+ 200 => 'OK',
10
+ 201 => 'Created',
11
+ 202 => 'Accepted',
12
+ 203 => 'Non-Authoritative Information', # http/1.1
13
+ 204 => 'No Content',
14
+ 205 => 'Reset Content',
15
+ 206 => 'Partial Content',
16
+ 207 => 'Multi-Status', #WebDAV
17
+ 208 => 'Already Reported', # RFC5842
18
+ 226 => 'IM Used', # RFC3229
19
+
20
+ 300 => 'Multiple Choices',
21
+ 301 => 'Moved Permanently',
22
+ 302 => 'Found',
23
+ 303 => 'See Other', # http/1.1
24
+ 304 => 'Not Modified',
25
+ 305 => 'Use Proxy', # http/1.1
26
+ 306 => 'Switch Proxy', # no longer used
27
+ 307 => 'Temporary Redirect', # http/1.1
28
+ 308 => 'Permanent Redirect', # RFC7538
29
+
30
+ 400 => 'Bad Request',
31
+ 401 => 'Unauthorized',
32
+ 402 => 'Payment Required',
33
+ 403 => 'Forbidden',
34
+ 404 => 'Not Found',
35
+ 405 => 'Method Not Allowed',
36
+ 406 => 'Not Acceptable',
37
+ 407 => 'Proxy Authentication Required',
38
+ 408 => 'Request Timeout',
39
+ 409 => 'Conflict',
40
+ 410 => 'Gone',
41
+ 411 => 'Length Required',
42
+ 412 => 'Precondition Failed',
43
+ 413 => 'Payload Too Large', # RFC7231 (renamed, see below)
44
+ 414 => 'URI Too Long', # RFC7231 (renamed, see below)
45
+ 415 => 'Unsupported Media Type',
46
+ 416 => 'Range Not Satisfiable', # RFC7233 (renamed, see below)
47
+ 417 => 'Expectation Failed',
48
+ 418 => 'I\'m A Teapot', #RFC2324
49
+ 421 => 'Too Many Connections From This IP',
50
+ 422 => 'Unprocessable Entity', #WebDAV
51
+ 423 => 'Locked', #WebDAV
52
+ 424 => 'Failed Dependency', #WebDAV
53
+ 425 => 'Unordered Collection', #WebDAV
54
+ 426 => 'Upgrade Required',
55
+ 428 => 'Precondition Required', #RFC6585
56
+ 429 => 'Too Many Requests', #RFC6585
57
+ 431 => 'Request Header Fields Too Large', #RFC6585
58
+ 449 => 'Retry With', #Microsoft
59
+ 450 => 'Blocked By Windows Parental Controls', #Microsoft
60
+
61
+ 500 => 'Internal Server Error',
62
+ 501 => 'Not Implemented',
63
+ 502 => 'Bad Gateway',
64
+ 503 => 'Service Unavailable',
65
+ 504 => 'Gateway Timeout',
66
+ 505 => 'HTTP Version Not Supported',
67
+ 506 => 'Variant Also Negotiates',
68
+ 507 => 'Insufficient Storage', #WebDAV
69
+ 508 => 'Loop Detected', # RFC5842
70
+ 509 => 'Bandwidth Limit Exceeded', #Apache
71
+ 510 => 'Not Extended',
72
+ 511 => 'Network Authentication Required', # RFC6585
73
+ }
74
+
75
+ end
@@ -0,0 +1,18 @@
1
+ module RestMan
2
+
3
+ STATUSES_COMPATIBILITY = {
4
+ # The RFCs all specify "Not Found", but "Resource Not Found" was used in
5
+ # earlier RestMan releases.
6
+ 404 => ['ResourceNotFound'],
7
+
8
+ # HTTP 413 was renamed to "Payload Too Large" in RFC7231.
9
+ 413 => ['RequestEntityTooLarge'],
10
+
11
+ # HTTP 414 was renamed to "URI Too Long" in RFC7231.
12
+ 414 => ['RequestURITooLong'],
13
+
14
+ # HTTP 416 was renamed to "Range Not Satisfiable" in RFC7233.
15
+ 416 => ['RequestedRangeNotSatisfiable'],
16
+ }
17
+
18
+ end
data/lib/restman/utils.rb CHANGED
@@ -4,55 +4,21 @@ module RestMan
4
4
  # Various utility methods
5
5
  module Utils
6
6
 
7
- # Return encoding from an HTTP header hash.
8
- #
9
- # We use the RFC 7231 specification and do not impose a default encoding on
10
- # text. This differs from the older RFC 2616 behavior, which specifies
11
- # using ISO-8859-1 for text/* content types without a charset.
12
- #
13
- # Strings will use the default encoding when this method returns nil. This
14
- # default is likely to be UTF-8 for Ruby >= 2.0
15
- #
16
- # @param headers [Hash<Symbol,String>]
17
- #
18
- # @return [String, nil] Return the string encoding or nil if no header is
19
- # found.
20
- #
21
- # @example
22
- # >> get_encoding_from_headers({:content_type => 'text/plain; charset=UTF-8'})
23
- # => "UTF-8"
24
- #
7
+ # :include: _doc/lib/restman/utils/get_encoding_from_headers.rdoc
25
8
  def self.get_encoding_from_headers(headers)
26
9
  type_header = headers[:content_type]
27
10
  return nil unless type_header
28
11
 
29
- # TODO: remove this hack once we drop support for Ruby 2.0
30
- if RUBY_VERSION.start_with?('2.0')
31
- _content_type, params = deprecated_cgi_parse_header(type_header)
32
-
33
- if params.include?('charset')
34
- return params.fetch('charset').gsub(/(\A["']*)|(["']*\z)/, '')
35
- end
36
-
12
+ begin
13
+ _content_type, params = cgi_parse_header(type_header)
14
+ rescue HTTP::Accept::ParseError
15
+ return nil
37
16
  else
38
-
39
- begin
40
- _content_type, params = cgi_parse_header(type_header)
41
- rescue HTTP::Accept::ParseError
42
- return nil
43
- else
44
- params['charset']
45
- end
17
+ params['charset']
46
18
  end
47
19
  end
48
20
 
49
- # Parse a Content-Type like header.
50
- #
51
- # Return the main content-type and a hash of params.
52
- #
53
- # @param [String] line
54
- # @return [Array(String, Hash)]
55
- #
21
+ # :include: _doc/lib/restman/utils/cgi_parse_header.rdoc
56
22
  def self.cgi_parse_header(line)
57
23
  types = HTTP::Accept::MediaTypes.parse(line)
58
24
 
@@ -63,165 +29,12 @@ module RestMan
63
29
  [types.first.mime_type, types.first.parameters]
64
30
  end
65
31
 
66
- # Parse semi-colon separated, potentially quoted header string iteratively.
67
- #
68
- # @private
69
- #
70
- # @deprecated This method is deprecated and only exists to support Ruby
71
- # 2.0, which is not supported by HTTP::Accept.
72
- #
73
- # @todo remove this method when dropping support for Ruby 2.0
74
- #
75
- def self._cgi_parseparam(s)
76
- return enum_for(__method__, s) unless block_given?
77
-
78
- while s[0] == ';'
79
- s = s[1..-1]
80
- ends = s.index(';')
81
- while ends && ends > 0 \
82
- && (s[0...ends].count('"') -
83
- s[0...ends].scan('\"').count) % 2 != 0
84
- ends = s.index(';', ends + 1)
85
- end
86
- if ends.nil?
87
- ends = s.length
88
- end
89
- f = s[0...ends]
90
- yield f.strip
91
- s = s[ends..-1]
92
- end
93
- nil
94
- end
95
-
96
- # Parse a Content-Type like header.
97
- #
98
- # Return the main content-type and a hash of options.
99
- #
100
- # This method was ported directly from Python's cgi.parse_header(). It
101
- # probably doesn't read or perform particularly well in ruby.
102
- # https://github.com/python/cpython/blob/3.4/Lib/cgi.py#L301-L331
103
- #
104
- # @param [String] line
105
- # @return [Array(String, Hash)]
106
- #
107
- # @deprecated This method is deprecated and only exists to support Ruby
108
- # 2.0, which is not supported by HTTP::Accept.
109
- #
110
- # @todo remove this method when dropping support for Ruby 2.0
111
- #
112
- def self.deprecated_cgi_parse_header(line)
113
- parts = _cgi_parseparam(';' + line)
114
- key = parts.next
115
- pdict = {}
116
-
117
- begin
118
- while (p = parts.next)
119
- i = p.index('=')
120
- if i
121
- name = p[0...i].strip.downcase
122
- value = p[i+1..-1].strip
123
- if value.length >= 2 && value[0] == '"' && value[-1] == '"'
124
- value = value[1...-1]
125
- value = value.gsub('\\\\', '\\').gsub('\\"', '"')
126
- end
127
- pdict[name] = value
128
- end
129
- end
130
- rescue StopIteration
131
- end
132
-
133
- [key, pdict]
134
- end
135
-
136
- # Serialize a ruby object into HTTP query string parameters.
137
- #
138
- # There is no standard for doing this, so we choose our own slightly
139
- # idiosyncratic format. The output closely matches the format understood by
140
- # Rails, Rack, and PHP.
141
- #
142
- # If you don't want handling of complex objects and only want to handle
143
- # simple flat hashes, you may want to use `URI.encode_www_form` instead,
144
- # which implements HTML5-compliant URL encoded form data.
145
- #
146
- # @param [Hash,ParamsArray] object The object to serialize
147
- #
148
- # @return [String] A string appropriate for use as an HTTP query string
149
- #
150
- # @see {flatten_params}
151
- #
152
- # @see URI.encode_www_form
153
- #
154
- # @see See also Object#to_query in ActiveSupport
155
- # @see http://php.net/manual/en/function.http-build-query.php
156
- # http_build_query in PHP
157
- # @see See also Rack::Utils.build_nested_query in Rack
158
- #
159
- # Notable differences from the ActiveSupport implementation:
160
- #
161
- # - Empty hash and empty array are treated the same as nil instead of being
162
- # omitted entirely from the output. Rather than disappearing, they will
163
- # appear to be nil instead.
164
- #
165
- # It's most common to pass a Hash as the object to serialize, but you can
166
- # also use a ParamsArray if you want to be able to pass the same key with
167
- # multiple values and not use the rack/rails array convention.
168
- #
169
- # @since 2.0.0
170
- #
171
- # @example Simple hashes
172
- # >> encode_query_string({foo: 123, bar: 456})
173
- # => 'foo=123&bar=456'
174
- #
175
- # @example Simple arrays
176
- # >> encode_query_string({foo: [1,2,3]})
177
- # => 'foo[]=1&foo[]=2&foo[]=3'
178
- #
179
- # @example Nested hashes
180
- # >> encode_query_string({outer: {foo: 123, bar: 456}})
181
- # => 'outer[foo]=123&outer[bar]=456'
182
- #
183
- # @example Deeply nesting
184
- # >> encode_query_string({coords: [{x: 1, y: 0}, {x: 2}, {x: 3}]})
185
- # => 'coords[][x]=1&coords[][y]=0&coords[][x]=2&coords[][x]=3'
186
- #
187
- # @example Null and empty values
188
- # >> encode_query_string({string: '', empty: nil, list: [], hash: {}})
189
- # => 'string=&empty&list&hash'
190
- #
191
- # @example Nested nulls
192
- # >> encode_query_string({foo: {string: '', empty: nil}})
193
- # => 'foo[string]=&foo[empty]'
194
- #
195
- # @example Multiple fields with the same name using ParamsArray
196
- # >> encode_query_string(RestMan::ParamsArray.new([[:foo, 1], [:foo, 2], [:foo, 3]]))
197
- # => 'foo=1&foo=2&foo=3'
198
- #
199
- # @example Nested ParamsArray
200
- # >> encode_query_string({foo: RestMan::ParamsArray.new([[:a, 1], [:a, 2]])})
201
- # => 'foo[a]=1&foo[a]=2'
202
- #
203
- # >> encode_query_string(RestMan::ParamsArray.new([[:foo, {a: 1}], [:foo, {a: 2}]]))
204
- # => 'foo[a]=1&foo[a]=2'
205
- #
32
+ # :include: _doc/lib/restman/utils/encode_query_string.rdoc
206
33
  def self.encode_query_string(object)
207
34
  flatten_params(object, true).map {|k, v| v.nil? ? k : "#{k}=#{v}" }.join('&')
208
35
  end
209
36
 
210
- # Transform deeply nested param containers into a flat array of [key,
211
- # value] pairs.
212
- #
213
- # @example
214
- # >> flatten_params({key1: {key2: 123}})
215
- # => [["key1[key2]", 123]]
216
- #
217
- # @example
218
- # >> flatten_params({key1: {key2: 123, arr: [1,2,3]}})
219
- # => [["key1[key2]", 123], ["key1[arr][]", 1], ["key1[arr][]", 2], ["key1[arr][]", 3]]
220
- #
221
- # @param object [Hash, ParamsArray] The container to flatten
222
- # @param uri_escape [Boolean] Whether to URI escape keys and values
223
- # @param parent_key [String] Should not be passed (used for recursion)
224
- #
37
+ # :include: _doc/lib/restman/utils/flatten_params.rdoc
225
38
  def self.flatten_params(object, uri_escape=false, parent_key=nil)
226
39
  unless object.is_a?(Hash) || object.is_a?(ParamsArray) ||
227
40
  (parent_key && object.is_a?(Array))
@@ -257,16 +70,7 @@ module RestMan
257
70
  }
258
71
  end
259
72
 
260
- # Encode string for safe transport by URI or form encoding. This uses a CGI
261
- # style escape, which transforms ` ` into `+` and various special
262
- # characters into percent encoded forms.
263
- #
264
- # This calls URI.encode_www_form_component for the implementation. The only
265
- # difference between this and CGI.escape is that it does not escape `*`.
266
- # http://stackoverflow.com/questions/25085992/
267
- #
268
- # @see URI.encode_www_form_component
269
- #
73
+ # :include: _doc/lib/restman/utils/escape.rdoc
270
74
  def self.escape(string)
271
75
  URI.encode_www_form_component(string)
272
76
  end
@@ -1,5 +1,5 @@
1
1
  module RestMan
2
- VERSION_INFO = [1, 0, 0].freeze
2
+ VERSION_INFO = [1, 1, 0].freeze
3
3
  VERSION = VERSION_INFO.map(&:to_s).join('.').freeze
4
4
 
5
5
  def self.version
data/lib/restman.rb CHANGED
@@ -2,64 +2,35 @@ require 'net/http'
2
2
  require 'openssl'
3
3
  require 'stringio'
4
4
  require 'uri'
5
+ require 'active_method'
5
6
 
6
7
  require File.dirname(__FILE__) + '/restman/version'
8
+ require File.dirname(__FILE__) + '/restman/statuses'
9
+ require File.dirname(__FILE__) + '/restman/statuses_compatibility'
7
10
  require File.dirname(__FILE__) + '/restman/platform'
8
- require File.dirname(__FILE__) + '/restman/exceptions'
11
+ require File.dirname(__FILE__) + '/restman/exception'
12
+ require File.dirname(__FILE__) + '/restman/exceptions/exception_with_response'
13
+ require File.dirname(__FILE__) + '/restman/exceptions/request_failed'
14
+ require File.dirname(__FILE__) + '/restman/exceptions/exceptions_map'
15
+ require File.dirname(__FILE__) + '/restman/exceptions/timeout'
16
+ require File.dirname(__FILE__) + '/restman/exceptions/server_broke_connection'
9
17
  require File.dirname(__FILE__) + '/restman/utils'
18
+ require File.dirname(__FILE__) + '/restman/request/init'
19
+ require File.dirname(__FILE__) + '/restman/request/transmit'
10
20
  require File.dirname(__FILE__) + '/restman/request'
11
21
  require File.dirname(__FILE__) + '/restman/abstract_response'
12
22
  require File.dirname(__FILE__) + '/restman/response'
13
23
  require File.dirname(__FILE__) + '/restman/raw_response'
14
24
  require File.dirname(__FILE__) + '/restman/resource'
15
25
  require File.dirname(__FILE__) + '/restman/params_array'
26
+ require File.dirname(__FILE__) + '/restman/params_array/process_pair'
16
27
  require File.dirname(__FILE__) + '/restman/payload'
17
- require File.dirname(__FILE__) + '/restman/windows'
18
-
19
- # This module's static methods are the entry point for using the REST client.
20
- #
21
- # # GET
22
- # xml = RestMan.get 'http://example.com/resource'
23
- # jpg = RestMan.get 'http://example.com/resource', :accept => 'image/jpg'
24
- #
25
- # # authentication and SSL
26
- # RestMan.get 'https://user:password@example.com/private/resource'
27
- #
28
- # # POST or PUT with a hash sends parameters as a urlencoded form body
29
- # RestMan.post 'http://example.com/resource', :param1 => 'one'
30
- #
31
- # # nest hash parameters
32
- # RestMan.post 'http://example.com/resource', :nested => { :param1 => 'one' }
33
- #
34
- # # POST and PUT with raw payloads
35
- # RestMan.post 'http://example.com/resource', 'the post body', :content_type => 'text/plain'
36
- # RestMan.post 'http://example.com/resource.xml', xml_doc
37
- # RestMan.put 'http://example.com/resource.pdf', File.read('my.pdf'), :content_type => 'application/pdf'
38
- #
39
- # # DELETE
40
- # RestMan.delete 'http://example.com/resource'
41
- #
42
- # # retrieve the response http code and headers
43
- # res = RestMan.get 'http://example.com/some.jpg'
44
- # res.code # => 200
45
- # res.headers[:content_type] # => 'image/jpg'
46
- #
47
- # # HEAD
48
- # RestMan.head('http://example.com').headers
49
- #
50
- # To use with a proxy, just set RestMan.proxy to the proper http proxy:
51
- #
52
- # RestMan.proxy = "http://proxy.example.com/"
53
- #
54
- # Or inherit the proxy from the environment:
55
- #
56
- # RestMan.proxy = ENV['http_proxy']
57
- #
58
- # For live tests of RestMan, try using http://rest-test.heroku.com, which echoes back information about the rest call:
59
- #
60
- # >> RestMan.put 'http://rest-test.heroku.com/resource', :foo => 'baz'
61
- # => "PUT http://rest-test.heroku.com/resource with a 7 byte payload, content type application/x-www-form-urlencoded {\"foo\"=>\"baz\"}"
62
- #
28
+ require File.dirname(__FILE__) + '/restman/payload/base'
29
+ require File.dirname(__FILE__) + '/restman/payload/multipart'
30
+ require File.dirname(__FILE__) + '/restman/payload/streamed'
31
+ require File.dirname(__FILE__) + '/restman/payload/url_encoded'
32
+
33
+ # :include: _doc/lib/restman.rdoc
63
34
  module RestMan
64
35
 
65
36
  def self.get(url, headers={}, &block)
@@ -90,8 +61,7 @@ module RestMan
90
61
  Request.execute(:method => :options, :url => url, :headers => headers, &block)
91
62
  end
92
63
 
93
- # A global proxy URL to use for all requests. This can be overridden on a
94
- # per-request basis by passing `:proxy` to RestMan::Request.
64
+ # :include: _doc/lib/restman/proxy.rdoc
95
65
  def self.proxy
96
66
  @proxy ||= nil
97
67
  end
@@ -101,24 +71,17 @@ module RestMan
101
71
  @proxy_set = true
102
72
  end
103
73
 
104
- # Return whether RestMan.proxy was set explicitly. We use this to
105
- # differentiate between no value being set and a value explicitly set to nil.
106
- #
107
- # @return [Boolean]
108
- #
74
+ # :include: _doc/lib/restman/proxy_set?.rdoc
109
75
  def self.proxy_set?
110
76
  @proxy_set ||= false
111
77
  end
112
78
 
113
- # Setup the log for RestMan calls.
114
- # Value should be a logger but can can be stdout, stderr, or a filename.
115
- # You can also configure logging by the environment variable RESTCLIENT_LOG.
79
+ # :include: _doc/lib/restman/log=.rdoc
116
80
  def self.log= log
117
81
  @@log = create_log log
118
82
  end
119
83
 
120
- # Create a log that respond to << like a logger
121
- # param can be 'stdout', 'stderr', a string (then we will log to that file) or a logger (then we return it)
84
+ # :include: _doc/lib/restman/create_log.rdoc
122
85
  def self.create_log param
123
86
  if param
124
87
  if param.is_a? String
@@ -164,14 +127,13 @@ module RestMan
164
127
 
165
128
  @@before_execution_procs = []
166
129
 
167
- # Add a Proc to be called before each request in executed.
168
- # The proc parameters will be the http request and the request params.
130
+ # :include: _doc/lib/restman/add_before_execution_proc.rdoc
169
131
  def self.add_before_execution_proc &proc
170
132
  raise ArgumentError.new('block is required') unless proc
171
133
  @@before_execution_procs << proc
172
134
  end
173
135
 
174
- # Reset the procs to be called before each request is executed.
136
+ # :include: _doc/lib/restman/reset_before_execution_procs.rdoc
175
137
  def self.reset_before_execution_procs
176
138
  @@before_execution_procs = []
177
139
  end
data/matrixeval.yml CHANGED
@@ -4,6 +4,8 @@ project_name: rest_man
4
4
  parallel_workers: number_of_processors
5
5
  commands:
6
6
  - jruby
7
+ - rubycritic
8
+ - rdoc
7
9
  # - ps
8
10
  # - top
9
11
  # - an_additional_command
@@ -12,16 +14,25 @@ commands:
12
14
  matrix:
13
15
  ruby:
14
16
  variants:
17
+ - key: 2.6
18
+ container:
19
+ image: ruby:2.6.10
15
20
  - key: 2.7
16
21
  container:
17
22
  image: ruby:2.7.6
18
23
  - key: 3.0
19
- default: true
20
24
  container:
21
25
  image: ruby:3.0.4
22
26
  - key: 3.1
23
27
  container:
24
28
  image: ruby:3.1.0
29
+ - key: 3.2
30
+ default: true
31
+ container:
32
+ image: ruby:3.2.2
33
+ - key: 3.3
34
+ container:
35
+ image: ruby:3.3.0-preview1
25
36
  - key: jruby-9.3
26
37
  container:
27
38
  image: hoppergee/jruby:9.3.7-dev
@@ -29,6 +40,13 @@ matrix:
29
40
  PATH: "/opt/jruby/bin:/app/bin:/bundle/bin:$PATH"
30
41
  JRUBY_OPTS: "--dev -X-C --debug"
31
42
  JAVA_OPTS: "-client -XX:+TieredCompilation -XX:TieredStopAtLevel=1"
43
+ - key: jruby-9.4
44
+ container:
45
+ image: hoppergee/jruby:9.4.2-dev
46
+ env:
47
+ PATH: "/opt/jruby/bin:/app/bin:/bundle/bin:$PATH"
48
+ JRUBY_OPTS: "--dev -X-C --debug"
49
+ JAVA_OPTS: "-client -XX:+TieredCompilation -XX:TieredStopAtLevel=1"
32
50
  # mounts:
33
51
  # - /a/path/need/to/mount:/a/path/mount/to
34
52