tilia-http 4.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +19 -0
- data/.rspec +1 -0
- data/.rubocop.yml +35 -0
- data/.simplecov +4 -0
- data/.travis.yml +3 -0
- data/CHANGELOG.sabre.md +235 -0
- data/CONTRIBUTING.md +25 -0
- data/Gemfile +18 -0
- data/Gemfile.lock +69 -0
- data/LICENSE +27 -0
- data/LICENSE.sabre +27 -0
- data/README.md +68 -0
- data/Rakefile +17 -0
- data/examples/asyncclient.rb +45 -0
- data/examples/basicauth.rb +39 -0
- data/examples/client.rb +20 -0
- data/examples/reverseproxy.rb +39 -0
- data/examples/stringify.rb +37 -0
- data/lib/tilia/http/auth/abstract_auth.rb +51 -0
- data/lib/tilia/http/auth/aws.rb +191 -0
- data/lib/tilia/http/auth/basic.rb +43 -0
- data/lib/tilia/http/auth/bearer.rb +37 -0
- data/lib/tilia/http/auth/digest.rb +187 -0
- data/lib/tilia/http/auth.rb +12 -0
- data/lib/tilia/http/client.rb +452 -0
- data/lib/tilia/http/client_exception.rb +15 -0
- data/lib/tilia/http/client_http_exception.rb +37 -0
- data/lib/tilia/http/http_exception.rb +21 -0
- data/lib/tilia/http/message.rb +241 -0
- data/lib/tilia/http/message_decorator_trait.rb +183 -0
- data/lib/tilia/http/message_interface.rb +154 -0
- data/lib/tilia/http/request.rb +235 -0
- data/lib/tilia/http/request_decorator.rb +160 -0
- data/lib/tilia/http/request_interface.rb +126 -0
- data/lib/tilia/http/response.rb +164 -0
- data/lib/tilia/http/response_decorator.rb +58 -0
- data/lib/tilia/http/response_interface.rb +36 -0
- data/lib/tilia/http/sapi.rb +165 -0
- data/lib/tilia/http/url_util.rb +70 -0
- data/lib/tilia/http/util.rb +51 -0
- data/lib/tilia/http/version.rb +9 -0
- data/lib/tilia/http.rb +416 -0
- data/test/http/auth/aws_test.rb +189 -0
- data/test/http/auth/basic_test.rb +60 -0
- data/test/http/auth/bearer_test.rb +47 -0
- data/test/http/auth/digest_test.rb +141 -0
- data/test/http/client_mock.rb +101 -0
- data/test/http/client_test.rb +331 -0
- data/test/http/message_decorator_test.rb +67 -0
- data/test/http/message_test.rb +163 -0
- data/test/http/request_decorator_test.rb +87 -0
- data/test/http/request_test.rb +132 -0
- data/test/http/response_decorator_test.rb +28 -0
- data/test/http/response_test.rb +38 -0
- data/test/http/sapi_mock.rb +12 -0
- data/test/http/sapi_test.rb +133 -0
- data/test/http/url_util_test.rb +155 -0
- data/test/http/util_test.rb +186 -0
- data/test/http_test.rb +102 -0
- data/test/test_helper.rb +6 -0
- data/tilia-http.gemspec +18 -0
- metadata +192 -0
@@ -0,0 +1,235 @@
|
|
1
|
+
require 'cgi'
|
2
|
+
module Tilia
|
3
|
+
module Http
|
4
|
+
# The Request class represents a single HTTP request.
|
5
|
+
#
|
6
|
+
# You can either simply construct the object from scratch, or if you need
|
7
|
+
# access to the current HTTP request, use Sapi::getRequest.
|
8
|
+
class Request
|
9
|
+
include Tilia::Http::Message
|
10
|
+
include Tilia::Http::RequestInterface
|
11
|
+
|
12
|
+
protected
|
13
|
+
|
14
|
+
# HTTP Method
|
15
|
+
#
|
16
|
+
# @return [String]
|
17
|
+
attr_accessor :method
|
18
|
+
|
19
|
+
# Request Url
|
20
|
+
#
|
21
|
+
# @return [String]
|
22
|
+
attr_accessor :url
|
23
|
+
|
24
|
+
public
|
25
|
+
|
26
|
+
# Creates the request object
|
27
|
+
#
|
28
|
+
# @param [String] method
|
29
|
+
# @param [String] url
|
30
|
+
# @param array headers
|
31
|
+
# @param resource body
|
32
|
+
def initialize(method = nil, url = nil, headers = nil, body = nil)
|
33
|
+
initialize_message
|
34
|
+
@base_url = '/' # RUBY
|
35
|
+
@post_data = {}
|
36
|
+
@raw_server_data = {}
|
37
|
+
|
38
|
+
fail ArgumentError, 'The first argument for this constructor should be a string or null, not an array. Did you upgrade from sabre/http 1.0 to 2.0?' if method.is_a?(Array)
|
39
|
+
|
40
|
+
self.method = method if method
|
41
|
+
self.url = url if url
|
42
|
+
update_headers(headers) if headers
|
43
|
+
self.body = body if body
|
44
|
+
end
|
45
|
+
|
46
|
+
# Returns the current HTTP method
|
47
|
+
#
|
48
|
+
# @return [String]
|
49
|
+
attr_reader :method
|
50
|
+
|
51
|
+
# Sets the HTTP method
|
52
|
+
#
|
53
|
+
# @param [String] method
|
54
|
+
# @return [void]
|
55
|
+
attr_writer :method
|
56
|
+
|
57
|
+
# Returns the request url.
|
58
|
+
#
|
59
|
+
# @return [String]
|
60
|
+
attr_reader :url
|
61
|
+
|
62
|
+
# Sets the request url.
|
63
|
+
#
|
64
|
+
# @param [String] url
|
65
|
+
# @return [void]
|
66
|
+
attr_writer :url
|
67
|
+
|
68
|
+
# Returns the list of query parameters.
|
69
|
+
#
|
70
|
+
# This is equivalent to PHP's $_GET superglobal.
|
71
|
+
#
|
72
|
+
# @return array
|
73
|
+
def query_parameters
|
74
|
+
url = self.url
|
75
|
+
|
76
|
+
if !(index = url.index('?'))
|
77
|
+
{}
|
78
|
+
else
|
79
|
+
query_params = CGI.parse(url[index + 1..-1])
|
80
|
+
query_params.keys.each do |key|
|
81
|
+
query_params[key] = query_params[key][0] if query_params[key].size == 1
|
82
|
+
query_params[key] = nil if query_params[key].size == 0
|
83
|
+
end
|
84
|
+
query_params
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
# Sets the absolute url.
|
89
|
+
#
|
90
|
+
# @param [String] url
|
91
|
+
# @return [void]
|
92
|
+
attr_writer :absolute_url
|
93
|
+
|
94
|
+
# Returns the absolute url.
|
95
|
+
#
|
96
|
+
# @return [String]
|
97
|
+
attr_reader :absolute_url
|
98
|
+
|
99
|
+
protected
|
100
|
+
|
101
|
+
# Base url
|
102
|
+
#
|
103
|
+
# @return [String]
|
104
|
+
attr_accessor :base_url
|
105
|
+
|
106
|
+
public
|
107
|
+
|
108
|
+
# Sets a base url.
|
109
|
+
#
|
110
|
+
# This url is used for relative path calculations.
|
111
|
+
#
|
112
|
+
# @param [String] url
|
113
|
+
# @return [void]
|
114
|
+
attr_writer :base_url
|
115
|
+
|
116
|
+
# Returns the current base url.
|
117
|
+
#
|
118
|
+
# @return [String]
|
119
|
+
attr_reader :base_url
|
120
|
+
|
121
|
+
# Returns the relative path.
|
122
|
+
#
|
123
|
+
# This is being calculated using the base url. This path will not start
|
124
|
+
# with a slash, so it will always return something like
|
125
|
+
# 'example/path.html'.
|
126
|
+
#
|
127
|
+
# If the full path is equal to the base url, this method will return an
|
128
|
+
# empty string.
|
129
|
+
#
|
130
|
+
# This method will also urldecode the path, and if the url was incoded as
|
131
|
+
# ISO-8859-1, it will convert it to UTF-8.
|
132
|
+
#
|
133
|
+
# If the path is outside of the base url, a LogicException will be thrown.
|
134
|
+
#
|
135
|
+
# @return [String]
|
136
|
+
def path
|
137
|
+
# Removing duplicated slashes.
|
138
|
+
uri = url.gsub('//', '/')
|
139
|
+
|
140
|
+
uri = Tilia::Uri.normalize(uri)
|
141
|
+
base_uri = Tilia::Uri.normalize(base_url)
|
142
|
+
|
143
|
+
if uri.index(base_uri) == 0
|
144
|
+
# We're not interested in the query part (everything after the ?).
|
145
|
+
uri = uri.split('?').first
|
146
|
+
return Tilia::Http::UrlUtil.decode_path(uri[base_uri.size..-1]).gsub(%r{^/+|/+$}, '')
|
147
|
+
elsif uri + '/' == base_uri
|
148
|
+
# A special case, if the baseUri was accessed without a trailing
|
149
|
+
# slash, we'll accept it as well.
|
150
|
+
return ''
|
151
|
+
end
|
152
|
+
|
153
|
+
fail "Requested uri (#{url}) is out of base uri (#{base_url})"
|
154
|
+
end
|
155
|
+
|
156
|
+
protected
|
157
|
+
|
158
|
+
# Equivalent of PHP's $_POST.
|
159
|
+
#
|
160
|
+
# @return array
|
161
|
+
attr_accessor :post_data
|
162
|
+
|
163
|
+
public
|
164
|
+
|
165
|
+
# Sets the post data.
|
166
|
+
#
|
167
|
+
# This is equivalent to PHP's $_POST superglobal.
|
168
|
+
#
|
169
|
+
# This would not have been needed, if POST data was accessible as
|
170
|
+
# php://input, but unfortunately we need to special case it.
|
171
|
+
#
|
172
|
+
# @param array post_data
|
173
|
+
# @return [void]
|
174
|
+
attr_writer :post_data
|
175
|
+
|
176
|
+
# Returns the POST data.
|
177
|
+
#
|
178
|
+
# This is equivalent to PHP's $_POST superglobal.
|
179
|
+
#
|
180
|
+
# @return array
|
181
|
+
attr_reader :post_data
|
182
|
+
|
183
|
+
protected
|
184
|
+
|
185
|
+
# An array containing the raw _SERVER array.
|
186
|
+
#
|
187
|
+
# @return array
|
188
|
+
attr_accessor :raw_server_data
|
189
|
+
|
190
|
+
public
|
191
|
+
|
192
|
+
# Returns an item from the _SERVER array.
|
193
|
+
#
|
194
|
+
# If the value does not exist in the array, null is returned.
|
195
|
+
#
|
196
|
+
# @param [String] value_name
|
197
|
+
# @return [String, nil]
|
198
|
+
def raw_server_value(value_name)
|
199
|
+
@raw_server_data[value_name]
|
200
|
+
end
|
201
|
+
|
202
|
+
# Sets the _SERVER array.
|
203
|
+
#
|
204
|
+
# @param array data
|
205
|
+
# @return [void]
|
206
|
+
def raw_server_data=(data)
|
207
|
+
@raw_server_data = data.dup
|
208
|
+
end
|
209
|
+
|
210
|
+
# Serializes the request object as a string.
|
211
|
+
#
|
212
|
+
# This is useful for debugging purposes.
|
213
|
+
#
|
214
|
+
# @return [String]
|
215
|
+
def to_s
|
216
|
+
out = "#{method} #{url} HTTP/#{http_version}\r\n"
|
217
|
+
|
218
|
+
headers.each do |key, value|
|
219
|
+
value.each do |v|
|
220
|
+
if key == 'Authorization'
|
221
|
+
v = v.split(' ').first
|
222
|
+
v << ' REDACTED'
|
223
|
+
end
|
224
|
+
out << "#{key}: #{v}\r\n"
|
225
|
+
end
|
226
|
+
end
|
227
|
+
|
228
|
+
out << "\r\n"
|
229
|
+
out << body_as_string
|
230
|
+
|
231
|
+
out
|
232
|
+
end
|
233
|
+
end
|
234
|
+
end
|
235
|
+
end
|
@@ -0,0 +1,160 @@
|
|
1
|
+
module Tilia
|
2
|
+
module Http
|
3
|
+
# Request Decorator
|
4
|
+
#
|
5
|
+
# This helper class allows you to easily create decorators for the Request
|
6
|
+
# object.
|
7
|
+
class RequestDecorator
|
8
|
+
include Tilia::Http::RequestInterface
|
9
|
+
include Tilia::Http::MessageDecoratorTrait
|
10
|
+
|
11
|
+
# Constructor.
|
12
|
+
#
|
13
|
+
# @param RequestInterface inner
|
14
|
+
def initialize(inner)
|
15
|
+
@inner = inner
|
16
|
+
end
|
17
|
+
|
18
|
+
# Returns the current HTTP method
|
19
|
+
#
|
20
|
+
# @return [String]
|
21
|
+
def method
|
22
|
+
@inner.method
|
23
|
+
end
|
24
|
+
|
25
|
+
# Sets the HTTP method
|
26
|
+
#
|
27
|
+
# @param [String] method
|
28
|
+
# @return [void]
|
29
|
+
def method=(method)
|
30
|
+
@inner.method = method
|
31
|
+
end
|
32
|
+
|
33
|
+
# Returns the request url.
|
34
|
+
#
|
35
|
+
# @return [String]
|
36
|
+
def url
|
37
|
+
@inner.url
|
38
|
+
end
|
39
|
+
|
40
|
+
# Sets the request url.
|
41
|
+
#
|
42
|
+
# @param [String] url
|
43
|
+
# @return [void]
|
44
|
+
def url=(url)
|
45
|
+
@inner.url = url
|
46
|
+
end
|
47
|
+
|
48
|
+
# Returns the absolute url.
|
49
|
+
#
|
50
|
+
# @return [String]
|
51
|
+
def absolute_url
|
52
|
+
@inner.absolute_url
|
53
|
+
end
|
54
|
+
|
55
|
+
# Sets the absolute url.
|
56
|
+
#
|
57
|
+
# @param [String] url
|
58
|
+
# @return [void]
|
59
|
+
def absolute_url=(url)
|
60
|
+
@inner.absolute_url = url
|
61
|
+
end
|
62
|
+
|
63
|
+
# Returns the current base url.
|
64
|
+
#
|
65
|
+
# @return [String]
|
66
|
+
def base_url
|
67
|
+
@inner.base_url
|
68
|
+
end
|
69
|
+
|
70
|
+
# Sets a base url.
|
71
|
+
#
|
72
|
+
# This url is used for relative path calculations.
|
73
|
+
#
|
74
|
+
# The base url should default to /
|
75
|
+
#
|
76
|
+
# @param [String] url
|
77
|
+
# @return [void]
|
78
|
+
def base_url=(url)
|
79
|
+
@inner.base_url = url
|
80
|
+
end
|
81
|
+
|
82
|
+
# Returns the relative path.
|
83
|
+
#
|
84
|
+
# This is being calculated using the base url. This path will not start
|
85
|
+
# with a slash, so it will always return something like
|
86
|
+
# 'example/path.html'.
|
87
|
+
#
|
88
|
+
# If the full path is equal to the base url, this method will return an
|
89
|
+
# empty string.
|
90
|
+
#
|
91
|
+
# This method will also urldecode the path, and if the url was incoded as
|
92
|
+
# ISO-8859-1, it will convert it to UTF-8.
|
93
|
+
#
|
94
|
+
# If the path is outside of the base url, a LogicException will be thrown.
|
95
|
+
#
|
96
|
+
# @return [String]
|
97
|
+
def path
|
98
|
+
@inner.path
|
99
|
+
end
|
100
|
+
|
101
|
+
# Returns the list of query parameters.
|
102
|
+
#
|
103
|
+
# This is equivalent to PHP's $_GET superglobal.
|
104
|
+
#
|
105
|
+
# @return array
|
106
|
+
def query_parameters
|
107
|
+
@inner.query_parameters
|
108
|
+
end
|
109
|
+
|
110
|
+
# Returns the POST data.
|
111
|
+
#
|
112
|
+
# This is equivalent to PHP's $_POST superglobal.
|
113
|
+
#
|
114
|
+
# @return array
|
115
|
+
def post_data
|
116
|
+
@inner.post_data
|
117
|
+
end
|
118
|
+
|
119
|
+
# Sets the post data.
|
120
|
+
#
|
121
|
+
# This is equivalent to PHP's $_POST superglobal.
|
122
|
+
#
|
123
|
+
# This would not have been needed, if POST data was accessible as
|
124
|
+
# php://input, but unfortunately we need to special case it.
|
125
|
+
#
|
126
|
+
# @param array post_data
|
127
|
+
# @return [void]
|
128
|
+
def post_data=(post_data)
|
129
|
+
@inner.post_data = post_data
|
130
|
+
end
|
131
|
+
|
132
|
+
# Returns an item from the _SERVER array.
|
133
|
+
#
|
134
|
+
# If the value does not exist in the array, null is returned.
|
135
|
+
#
|
136
|
+
# @param [String] value_name
|
137
|
+
# @return [String, nil]
|
138
|
+
def raw_server_value(value_name)
|
139
|
+
@inner.raw_server_value(value_name)
|
140
|
+
end
|
141
|
+
|
142
|
+
# Sets the _SERVER array.
|
143
|
+
#
|
144
|
+
# @param array data
|
145
|
+
# @return [void]
|
146
|
+
def raw_server_data=(data)
|
147
|
+
@inner.raw_server_data = data
|
148
|
+
end
|
149
|
+
|
150
|
+
# Serializes the request object as a string.
|
151
|
+
#
|
152
|
+
# This is useful for debugging purposes.
|
153
|
+
#
|
154
|
+
# @return [String]
|
155
|
+
def to_s
|
156
|
+
@inner.to_s
|
157
|
+
end
|
158
|
+
end
|
159
|
+
end
|
160
|
+
end
|
@@ -0,0 +1,126 @@
|
|
1
|
+
module Tilia
|
2
|
+
module Http
|
3
|
+
# The RequestInterface represents a HTTP request.
|
4
|
+
module RequestInterface
|
5
|
+
include Tilia::Http::MessageInterface
|
6
|
+
|
7
|
+
# Returns the current HTTP method
|
8
|
+
#
|
9
|
+
# @return [String]
|
10
|
+
def method
|
11
|
+
end
|
12
|
+
|
13
|
+
# Sets the HTTP method
|
14
|
+
#
|
15
|
+
# @param [String] method
|
16
|
+
# @return [void]
|
17
|
+
def method=(_method)
|
18
|
+
end
|
19
|
+
|
20
|
+
# Returns the request url.
|
21
|
+
#
|
22
|
+
# @return [String]
|
23
|
+
def url
|
24
|
+
end
|
25
|
+
|
26
|
+
# Sets the request url.
|
27
|
+
#
|
28
|
+
# @param [String] url
|
29
|
+
# @return [void]
|
30
|
+
def url=(_url)
|
31
|
+
end
|
32
|
+
|
33
|
+
# Returns the absolute url.
|
34
|
+
#
|
35
|
+
# @return [String]
|
36
|
+
def absolute_url
|
37
|
+
end
|
38
|
+
|
39
|
+
# Sets the absolute url.
|
40
|
+
#
|
41
|
+
# @param [String] url
|
42
|
+
# @return [void]
|
43
|
+
def absolute_url=(_url)
|
44
|
+
end
|
45
|
+
|
46
|
+
# Returns the current base url.
|
47
|
+
#
|
48
|
+
# @return [String]
|
49
|
+
def base_url
|
50
|
+
end
|
51
|
+
|
52
|
+
# Sets a base url.
|
53
|
+
#
|
54
|
+
# This url is used for relative path calculations.
|
55
|
+
#
|
56
|
+
# The base url should default to /
|
57
|
+
#
|
58
|
+
# @param [String] url
|
59
|
+
# @return [void]
|
60
|
+
def base_url=(_url)
|
61
|
+
end
|
62
|
+
|
63
|
+
# Returns the relative path.
|
64
|
+
#
|
65
|
+
# This is being calculated using the base url. This path will not start
|
66
|
+
# with a slash, so it will always return something like
|
67
|
+
# 'example/path.html'.
|
68
|
+
#
|
69
|
+
# If the full path is equal to the base url, this method will return an
|
70
|
+
# empty string.
|
71
|
+
#
|
72
|
+
# This method will also urldecode the path, and if the url was incoded as
|
73
|
+
# ISO-8859-1, it will convert it to UTF-8.
|
74
|
+
#
|
75
|
+
# If the path is outside of the base url, a LogicException will be thrown.
|
76
|
+
#
|
77
|
+
# @return [String]
|
78
|
+
def path
|
79
|
+
end
|
80
|
+
|
81
|
+
# Returns the list of query parameters.
|
82
|
+
#
|
83
|
+
# This is equivalent to PHP's $_GET superglobal.
|
84
|
+
#
|
85
|
+
# @return array
|
86
|
+
def query_parameters
|
87
|
+
end
|
88
|
+
|
89
|
+
# Returns the POST data.
|
90
|
+
#
|
91
|
+
# This is equivalent to PHP's $_POST superglobal.
|
92
|
+
#
|
93
|
+
# @return array
|
94
|
+
def post_data
|
95
|
+
end
|
96
|
+
|
97
|
+
# Sets the post data.
|
98
|
+
#
|
99
|
+
# This is equivalent to PHP's $_POST superglobal.
|
100
|
+
#
|
101
|
+
# This would not have been needed, if POST data was accessible as
|
102
|
+
# php://input, but unfortunately we need to special case it.
|
103
|
+
#
|
104
|
+
# @param array post_data
|
105
|
+
# @return [void]
|
106
|
+
def post_data=(_post_data)
|
107
|
+
end
|
108
|
+
|
109
|
+
# Returns an item from the _SERVER array.
|
110
|
+
#
|
111
|
+
# If the value does not exist in the array, null is returned.
|
112
|
+
#
|
113
|
+
# @param [String] value_name
|
114
|
+
# @return [String, nil]
|
115
|
+
def raw_server_value(_value_name)
|
116
|
+
end
|
117
|
+
|
118
|
+
# Sets the _SERVER array.
|
119
|
+
#
|
120
|
+
# @param array data
|
121
|
+
# @return [void]
|
122
|
+
def raw_server_data=(_data)
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
@@ -0,0 +1,164 @@
|
|
1
|
+
module Tilia
|
2
|
+
module Http
|
3
|
+
# This class represents a single HTTP response.
|
4
|
+
class Response
|
5
|
+
include Tilia::Http::Message
|
6
|
+
include Tilia::Http::ResponseInterface
|
7
|
+
|
8
|
+
# This is the list of currently registered HTTP status codes.
|
9
|
+
#
|
10
|
+
# @return array
|
11
|
+
def self.status_codes
|
12
|
+
{
|
13
|
+
100 => 'Continue',
|
14
|
+
101 => 'Switching Protocols',
|
15
|
+
102 => 'Processing',
|
16
|
+
200 => 'OK',
|
17
|
+
201 => 'Created',
|
18
|
+
202 => 'Accepted',
|
19
|
+
203 => 'Non-Authorative Information',
|
20
|
+
204 => 'No Content',
|
21
|
+
205 => 'Reset Content',
|
22
|
+
206 => 'Partial Content',
|
23
|
+
207 => 'Multi-Status', # RFC 4918
|
24
|
+
208 => 'Already Reported', # RFC 5842
|
25
|
+
226 => 'IM Used', # RFC 3229
|
26
|
+
300 => 'Multiple Choices',
|
27
|
+
301 => 'Moved Permanently',
|
28
|
+
302 => 'Found',
|
29
|
+
303 => 'See Other',
|
30
|
+
304 => 'Not Modified',
|
31
|
+
305 => 'Use Proxy',
|
32
|
+
307 => 'Temporary Redirect',
|
33
|
+
308 => 'Permanent Redirect',
|
34
|
+
400 => 'Bad Request',
|
35
|
+
401 => 'Unauthorized',
|
36
|
+
402 => 'Payment Required',
|
37
|
+
403 => 'Forbidden',
|
38
|
+
404 => 'Not Found',
|
39
|
+
405 => 'Method Not Allowed',
|
40
|
+
406 => 'Not Acceptable',
|
41
|
+
407 => 'Proxy Authentication Required',
|
42
|
+
408 => 'Request Timeout',
|
43
|
+
409 => 'Conflict',
|
44
|
+
410 => 'Gone',
|
45
|
+
411 => 'Length Required',
|
46
|
+
412 => 'Precondition failed',
|
47
|
+
413 => 'Request Entity Too Large',
|
48
|
+
414 => 'Request-URI Too Long',
|
49
|
+
415 => 'Unsupported Media Type',
|
50
|
+
416 => 'Requested Range Not Satisfiable',
|
51
|
+
417 => 'Expectation Failed',
|
52
|
+
418 => 'I\'m a teapot', # RFC 2324
|
53
|
+
421 => 'Misdirected Request', # RFC7540 (HTTP/2)
|
54
|
+
422 => 'Unprocessable Entity', # RFC 4918
|
55
|
+
423 => 'Locked', # RFC 4918
|
56
|
+
424 => 'Failed Dependency', # RFC 4918
|
57
|
+
426 => 'Upgrade Required',
|
58
|
+
428 => 'Precondition Required', # RFC 6585
|
59
|
+
429 => 'Too Many Requests', # RFC 6585
|
60
|
+
431 => 'Request Header Fields Too Large', # RFC 6585
|
61
|
+
451 => 'Unavailable For Legal Reasons', # draft-tbray-http-legally-restricted-status
|
62
|
+
500 => 'Internal Server Error',
|
63
|
+
501 => 'Not Implemented',
|
64
|
+
502 => 'Bad Gateway',
|
65
|
+
503 => 'Service Unavailable',
|
66
|
+
504 => 'Gateway Timeout',
|
67
|
+
505 => 'HTTP Version not supported',
|
68
|
+
506 => 'Variant Also Negotiates',
|
69
|
+
507 => 'Insufficient Storage', # RFC 4918
|
70
|
+
508 => 'Loop Detected', # RFC 5842
|
71
|
+
509 => 'Bandwidth Limit Exceeded', # non-standard
|
72
|
+
510 => 'Not extended',
|
73
|
+
511 => 'Network Authentication Required' # RFC 6585
|
74
|
+
}
|
75
|
+
end
|
76
|
+
|
77
|
+
protected
|
78
|
+
|
79
|
+
# HTTP status code
|
80
|
+
#
|
81
|
+
# @return int
|
82
|
+
attr_accessor :status
|
83
|
+
|
84
|
+
# HTTP status text
|
85
|
+
#
|
86
|
+
# @return [String]
|
87
|
+
attr_accessor :status_text
|
88
|
+
|
89
|
+
public
|
90
|
+
|
91
|
+
# Creates the response object
|
92
|
+
#
|
93
|
+
# @param [String, Fixnum] status
|
94
|
+
# @param array headers
|
95
|
+
# @param resource body
|
96
|
+
# @return [void]
|
97
|
+
def initialize(status = nil, headers = nil, body = nil)
|
98
|
+
initialize_message # RUBY
|
99
|
+
|
100
|
+
self.status = status if status
|
101
|
+
update_headers(headers) if headers
|
102
|
+
self.body = body if body
|
103
|
+
end
|
104
|
+
|
105
|
+
# Returns the current HTTP status code.
|
106
|
+
#
|
107
|
+
# @return int
|
108
|
+
attr_reader :status
|
109
|
+
|
110
|
+
# Returns the human-readable status string.
|
111
|
+
#
|
112
|
+
# In the case of a 200, this may for example be 'OK'.
|
113
|
+
#
|
114
|
+
# @return [String]
|
115
|
+
attr_reader :status_text
|
116
|
+
|
117
|
+
# Sets the HTTP status code.
|
118
|
+
#
|
119
|
+
# This can be either the full HTTP status code with human readable string,
|
120
|
+
# for example: "403 I can't let you do that, Dave".
|
121
|
+
#
|
122
|
+
# Or just the code, in which case the appropriate default message will be
|
123
|
+
# added.
|
124
|
+
#
|
125
|
+
# @param [String, Fixnum] status
|
126
|
+
# @throws \InvalidArgumentExeption
|
127
|
+
# @return [void]
|
128
|
+
def status=(status)
|
129
|
+
if status.is_a?(Fixnum) || status =~ /^\d+$/
|
130
|
+
status_code = status
|
131
|
+
status_text = self.class.status_codes.key?(status.to_i) ? self.class.status_codes[status.to_i] : 'Unkown'
|
132
|
+
else
|
133
|
+
(
|
134
|
+
status_code,
|
135
|
+
status_text
|
136
|
+
) = status.split(' ', 2)
|
137
|
+
end
|
138
|
+
|
139
|
+
fail ArgumentError, 'The HTTP status code must be exactly 3 digits' if status_code.to_i < 100 || status_code.to_i > 999
|
140
|
+
|
141
|
+
@status = status_code.to_i
|
142
|
+
@status_text = status_text
|
143
|
+
end
|
144
|
+
|
145
|
+
# Serializes the response object as a string.
|
146
|
+
#
|
147
|
+
# This is useful for debugging purposes.
|
148
|
+
#
|
149
|
+
# @return [String]
|
150
|
+
def to_s
|
151
|
+
str = "HTTP/#{http_version} #{status} #{status_text}\r\n"
|
152
|
+
headers.each do |key, value|
|
153
|
+
value.each do |v|
|
154
|
+
str << "#{key}: #{v}\r\n"
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
str << "\r\n"
|
159
|
+
str << body_as_string
|
160
|
+
str
|
161
|
+
end
|
162
|
+
end
|
163
|
+
end
|
164
|
+
end
|