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,58 @@
|
|
1
|
+
module Tilia
|
2
|
+
module Http
|
3
|
+
# Response Decorator
|
4
|
+
#
|
5
|
+
# This helper class allows you to easily create decorators for the Response
|
6
|
+
# object.
|
7
|
+
class ResponseDecorator
|
8
|
+
include Tilia::Http::ResponseInterface
|
9
|
+
include Tilia::Http::MessageDecoratorTrait
|
10
|
+
|
11
|
+
# Constructor.
|
12
|
+
#
|
13
|
+
# @param ResponseInterface inner
|
14
|
+
def initialize(inner)
|
15
|
+
@inner = inner
|
16
|
+
end
|
17
|
+
|
18
|
+
# Returns the current HTTP status code.
|
19
|
+
#
|
20
|
+
# @return int
|
21
|
+
def status
|
22
|
+
@inner.status
|
23
|
+
end
|
24
|
+
|
25
|
+
# Returns the human-readable status string.
|
26
|
+
#
|
27
|
+
# In the case of a 200, this may for example be 'OK'.
|
28
|
+
#
|
29
|
+
# @return [String]
|
30
|
+
def status_text
|
31
|
+
@inner.status_text
|
32
|
+
end
|
33
|
+
|
34
|
+
# Sets the HTTP status code.
|
35
|
+
#
|
36
|
+
# This can be either the full HTTP status code with human readable string,
|
37
|
+
# for example: "403 I can't let you do that, Dave".
|
38
|
+
#
|
39
|
+
# Or just the code, in which case the appropriate default message will be
|
40
|
+
# added.
|
41
|
+
#
|
42
|
+
# @param [String, Fixnum] status
|
43
|
+
# @return [void]
|
44
|
+
def status=(status)
|
45
|
+
@inner.status = status
|
46
|
+
end
|
47
|
+
|
48
|
+
# Serializes the request object as a string.
|
49
|
+
#
|
50
|
+
# This is useful for debugging purposes.
|
51
|
+
#
|
52
|
+
# @return [String]
|
53
|
+
def to_s
|
54
|
+
@inner.to_s
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module Tilia
|
2
|
+
module Http
|
3
|
+
# This interface represents a HTTP response.
|
4
|
+
module ResponseInterface
|
5
|
+
include Tilia::Http::MessageInterface
|
6
|
+
|
7
|
+
# Returns the current HTTP status code.
|
8
|
+
#
|
9
|
+
# @return int
|
10
|
+
def status
|
11
|
+
end
|
12
|
+
|
13
|
+
# Returns the human-readable status string.
|
14
|
+
#
|
15
|
+
# In the case of a 200, this may for example be 'OK'.
|
16
|
+
#
|
17
|
+
# @return [String]
|
18
|
+
def status_text
|
19
|
+
end
|
20
|
+
|
21
|
+
# Sets the HTTP status code.
|
22
|
+
#
|
23
|
+
# This can be either the full HTTP status code with human readable string,
|
24
|
+
# for example: "403 I can't let you do that, Dave".
|
25
|
+
#
|
26
|
+
# Or just the code, in which case the appropriate default message will be
|
27
|
+
# added.
|
28
|
+
#
|
29
|
+
# @param [String, Fixnum] status
|
30
|
+
# @throws \InvalidArgumentExeption
|
31
|
+
# @return [void]
|
32
|
+
def status=(_status)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,165 @@
|
|
1
|
+
require 'stringio'
|
2
|
+
require 'base64'
|
3
|
+
module Tilia
|
4
|
+
module Http
|
5
|
+
# PHP SAPI
|
6
|
+
#
|
7
|
+
# This object is responsible for:
|
8
|
+
# 1. Constructing a Request object based on the current HTTP request sent to
|
9
|
+
# the PHP process.
|
10
|
+
# 2. Sending the Response object back to the client.
|
11
|
+
#
|
12
|
+
# It could be said that this class provides a mapping between the Request and
|
13
|
+
# Response objects, and php's:
|
14
|
+
#
|
15
|
+
# * $_SERVER
|
16
|
+
# * $_POST
|
17
|
+
# * $_FILES
|
18
|
+
# * php://input
|
19
|
+
# * echo
|
20
|
+
# * header
|
21
|
+
# * php://output
|
22
|
+
#
|
23
|
+
# You can choose to either call all these methods statically, but you can also
|
24
|
+
# instantiate this as an object to allow for polymorhpism.
|
25
|
+
class Sapi
|
26
|
+
# This static method will create a new Request object, based on the
|
27
|
+
# current PHP request.
|
28
|
+
#
|
29
|
+
# @return Request
|
30
|
+
def self.request
|
31
|
+
fail NotImplementedError, 'This object method now is an instance method'
|
32
|
+
end
|
33
|
+
|
34
|
+
# Sends the HTTP response back to a HTTP client.
|
35
|
+
#
|
36
|
+
# This calls php's header function and streams the body to php://output.
|
37
|
+
#
|
38
|
+
# @param ResponseInterface response
|
39
|
+
# @return [void]
|
40
|
+
def self.send_response(response)
|
41
|
+
# RUBY: Rack does not support HTTP Version (?)
|
42
|
+
# header("HTTP/#{response.http_version} #{response.status} #{response.status_text}")
|
43
|
+
|
44
|
+
status = response.status
|
45
|
+
headers = {}
|
46
|
+
response.headers.each do |key, value|
|
47
|
+
headers[key] = value.join("\n")
|
48
|
+
end
|
49
|
+
|
50
|
+
body = response.body_as_stream
|
51
|
+
content_length = response.header('Content-Length')
|
52
|
+
if content_length
|
53
|
+
output = StringIO.new
|
54
|
+
output.write body.read(content_length.to_i)
|
55
|
+
output.rewind
|
56
|
+
body = output
|
57
|
+
end
|
58
|
+
|
59
|
+
[status, headers, body]
|
60
|
+
end
|
61
|
+
|
62
|
+
# This static method will create a new Request object, based on a PHP
|
63
|
+
# $_SERVER array.
|
64
|
+
#
|
65
|
+
# @param array server_array
|
66
|
+
# @return Request
|
67
|
+
def self.create_from_server_array(server_array)
|
68
|
+
headers = {}
|
69
|
+
method = nil
|
70
|
+
url = nil
|
71
|
+
http_version = '1.1'
|
72
|
+
|
73
|
+
protocol = 'http'
|
74
|
+
host_name = 'localhost'
|
75
|
+
|
76
|
+
server_array.each do |key, value|
|
77
|
+
case key
|
78
|
+
when 'SERVER_PROTOCOL'
|
79
|
+
http_version = '1.0' if value == 'HTTP/1.0'
|
80
|
+
when 'REQUEST_METHOD'
|
81
|
+
method = value
|
82
|
+
when 'REQUEST_URI'
|
83
|
+
url = value
|
84
|
+
|
85
|
+
# These sometimes should up without a HTTP_ prefix
|
86
|
+
when 'CONTENT_TYPE'
|
87
|
+
headers['Content-Type'] = value
|
88
|
+
when 'CONTENT_LENGTH'
|
89
|
+
headers['Content-Length'] = value
|
90
|
+
|
91
|
+
# mod_php on apache will put credentials in these variables.
|
92
|
+
# (fast)cgi does not usually do this, however.
|
93
|
+
when 'PHP_AUTH_USER'
|
94
|
+
if server_array.key? 'PHP_AUTH_PW'
|
95
|
+
headers['Authorization'] = "Basic #{Base64.strict_encode64 "#{value}:#{server_array['PHP_AUTH_PW']}"}"
|
96
|
+
end
|
97
|
+
when 'PHP_AUTH_DIGEST'
|
98
|
+
headers['Authorization'] = "Digest #{value}"
|
99
|
+
|
100
|
+
# Apache may prefix the HTTP_AUTHORIZATION header with
|
101
|
+
# REDIRECT_, if mod_rewrite was used.
|
102
|
+
when 'REDIRECT_HTTP_AUTHORIZATION'
|
103
|
+
headers['Authorization'] = value
|
104
|
+
|
105
|
+
when 'HTTP_HOST'
|
106
|
+
host_name = value
|
107
|
+
headers['Host'] = value
|
108
|
+
|
109
|
+
when 'HTTPS'
|
110
|
+
protocol = 'https' if value && value != 'off'
|
111
|
+
|
112
|
+
# RUBY
|
113
|
+
when 'rack.url_scheme'
|
114
|
+
protocol = value
|
115
|
+
|
116
|
+
else
|
117
|
+
if key.index('HTTP_') == 0
|
118
|
+
# It's a HTTP header
|
119
|
+
|
120
|
+
# Normalizing it to be prettier
|
121
|
+
header = key[5..-1].downcase
|
122
|
+
|
123
|
+
# Transforming dashes into spaces, and uppercasing
|
124
|
+
# every first letter.
|
125
|
+
# Turning spaces into dashes.
|
126
|
+
header = header.split(/_/).map(&:capitalize).join('-')
|
127
|
+
|
128
|
+
headers[header] = value
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
r = Tilia::Http::Request.new(method, url, headers)
|
134
|
+
r.http_version = http_version
|
135
|
+
r.raw_server_data = server_array
|
136
|
+
r.absolute_url = "#{protocol}://#{host_name}#{url}"
|
137
|
+
r
|
138
|
+
end
|
139
|
+
|
140
|
+
# TODO: document
|
141
|
+
def initialize(env)
|
142
|
+
@env = env
|
143
|
+
@rack_request = Rack::Request.new(env)
|
144
|
+
end
|
145
|
+
|
146
|
+
# TODO: document
|
147
|
+
def request
|
148
|
+
r = create_from_server_array(@env)
|
149
|
+
r.body = StringIO.new
|
150
|
+
r.post_data = @rack_request.POST
|
151
|
+
r
|
152
|
+
end
|
153
|
+
|
154
|
+
# TODO: document
|
155
|
+
def send_response(response)
|
156
|
+
self.class.send_response(response)
|
157
|
+
end
|
158
|
+
|
159
|
+
# TODO: document
|
160
|
+
def create_from_server_array(server_array)
|
161
|
+
self.class.create_from_server_array(server_array)
|
162
|
+
end
|
163
|
+
end
|
164
|
+
end
|
165
|
+
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
module Tilia
|
2
|
+
module Http
|
3
|
+
# URL utility class
|
4
|
+
#
|
5
|
+
# Note: this class is deprecated. All its functionality moved to functions.php
|
6
|
+
# or sabre\uri.
|
7
|
+
#
|
8
|
+
# @deprectated
|
9
|
+
module UrlUtil
|
10
|
+
# Encodes the path of a url.
|
11
|
+
#
|
12
|
+
# slashes (/) are treated as path-separators.
|
13
|
+
#
|
14
|
+
# @deprecated use \Sabre\HTTP\encode_path
|
15
|
+
# @param [String] path
|
16
|
+
# @return [String]
|
17
|
+
def self.encode_path(path)
|
18
|
+
Tilia::Http.encode_path(path)
|
19
|
+
end
|
20
|
+
|
21
|
+
# Encodes a 1 segment of a path
|
22
|
+
#
|
23
|
+
# Slashes are considered part of the name, and are encoded as %2f
|
24
|
+
#
|
25
|
+
# @deprecated use \Sabre\HTTP\encode_path_segment
|
26
|
+
# @param [String] path_segment
|
27
|
+
# @return [String]
|
28
|
+
def self.encode_path_segment(path_segment)
|
29
|
+
Tilia::Http.encode_path_segment(path_segment)
|
30
|
+
end
|
31
|
+
|
32
|
+
# Decodes a url-encoded path
|
33
|
+
#
|
34
|
+
# @deprecated use \Sabre\HTTP\decodePath
|
35
|
+
# @param [String] path
|
36
|
+
# @return [String]
|
37
|
+
def self.decode_path(path)
|
38
|
+
Tilia::Http.decode_path(path)
|
39
|
+
end
|
40
|
+
|
41
|
+
# Decodes a url-encoded path segment
|
42
|
+
#
|
43
|
+
# @deprecated use \Sabre\HTTP\decode_path_segment
|
44
|
+
# @param [String] path
|
45
|
+
# @return [String]
|
46
|
+
def self.decode_path_segment(path)
|
47
|
+
Tilia::Http.decode_path_segment(path)
|
48
|
+
end
|
49
|
+
|
50
|
+
# Returns the 'dirname' and 'basename' for a path.
|
51
|
+
#
|
52
|
+
# @deprecated Use Sabre\Uri\split.
|
53
|
+
# @param [String] path
|
54
|
+
# @return array
|
55
|
+
def self.split_path(path)
|
56
|
+
Tilia::Uri.split(path)
|
57
|
+
end
|
58
|
+
|
59
|
+
# Resolves relative urls, like a browser would.
|
60
|
+
#
|
61
|
+
# @deprecated Use Sabre\Uri\resolve.
|
62
|
+
# @param [String] base_path
|
63
|
+
# @param [String] new_path
|
64
|
+
# @return [String]
|
65
|
+
def self.resolve(base_path, new_path)
|
66
|
+
Tilia::Uri.resolve(base_path, new_path)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
module Tilia
|
2
|
+
module Http
|
3
|
+
# HTTP utility methods
|
4
|
+
#
|
5
|
+
# @deprecated All these functions moved to the Tilia::Http namespace
|
6
|
+
module Util
|
7
|
+
# Content negotiation
|
8
|
+
#
|
9
|
+
# @deprecated Use Tilia::Http::negotiate_content_type
|
10
|
+
# @param [String, nil] accept_header_value
|
11
|
+
# @param array available_options
|
12
|
+
# @return [String, nil]
|
13
|
+
def self.negotiate_content_type(accept_header_value, available_options)
|
14
|
+
Http.negotiate_content_type(accept_header_value, available_options)
|
15
|
+
end
|
16
|
+
|
17
|
+
# Deprecated! Use negotiateContentType.
|
18
|
+
#
|
19
|
+
# @deprecated Use Tilia::Http::negotiate_content_type
|
20
|
+
# @param [String, nil] accept_header
|
21
|
+
# @param array available_options
|
22
|
+
# @return [String, nil]
|
23
|
+
def self.negotiate(accept_header_value, available_options)
|
24
|
+
Http.negotiate_content_type(accept_header_value, available_options)
|
25
|
+
end
|
26
|
+
|
27
|
+
# Parses a RFC2616-compatible date string
|
28
|
+
#
|
29
|
+
# This method returns false if the date is invalid
|
30
|
+
#
|
31
|
+
# @deprecated Use Tilia::Http::parse_date
|
32
|
+
# @param [String] date_header
|
33
|
+
# @return bool|DateTime
|
34
|
+
def self.parse_http_date(date_header)
|
35
|
+
Http.parse_date(date_header)
|
36
|
+
end
|
37
|
+
|
38
|
+
# Transforms a DateTime object to HTTP's most common date format.
|
39
|
+
#
|
40
|
+
# We're serializing it as the RFC 1123 date, which, for HTTP must be
|
41
|
+
# specified as GMT.
|
42
|
+
#
|
43
|
+
# @deprecated Use Tilia::Http::to_date
|
44
|
+
# @param \DateTime date_time
|
45
|
+
# @return [String]
|
46
|
+
def self.to_http_date(date_time)
|
47
|
+
Http.to_date(date_time)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|