em-http-request 0.2.15 → 0.3.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.
Potentially problematic release.
This version of em-http-request might be problematic. Click here for more details.
- data/.gitignore +2 -1
- data/.rspec +0 -0
- data/Changelog.md +13 -0
- data/Gemfile +2 -14
- data/README.md +7 -0
- data/Rakefile +6 -35
- data/em-http-request.gemspec +25 -94
- data/ext/buffer/extconf.rb +53 -53
- data/ext/http11_client/ext_help.h +14 -14
- data/ext/http11_client/extconf.rb +6 -6
- data/ext/http11_client/http11_client.c +328 -328
- data/ext/http11_client/http11_parser.h +48 -48
- data/lib/em-http.rb +15 -16
- data/lib/em-http/client.rb +15 -222
- data/lib/em-http/http_encoding.rb +135 -0
- data/lib/em-http/http_header.rb +71 -0
- data/lib/em-http/http_options.rb +4 -3
- data/lib/em-http/request.rb +0 -3
- data/lib/em-http/version.rb +5 -0
- data/spec/encoding_spec.rb +7 -1
- data/spec/mock_spec.rb +1 -1
- data/spec/multi_spec.rb +68 -68
- data/spec/request_spec.rb +125 -75
- data/spec/stallion.rb +1 -0
- metadata +100 -25
- data/LICENSE +0 -58
- data/VERSION +0 -1
- data/autotest/discover.rb +0 -1
@@ -1,48 +1,48 @@
|
|
1
|
-
/**
|
2
|
-
* Copyright (c) 2005 Zed A. Shaw
|
3
|
-
* You can redistribute it and/or modify it under the same terms as Ruby.
|
4
|
-
*/
|
5
|
-
|
6
|
-
#ifndef http11_parser_h
|
7
|
-
#define http11_parser_h
|
8
|
-
|
9
|
-
#include <sys/types.h>
|
10
|
-
|
11
|
-
#if defined(_WIN32)
|
12
|
-
#include <stddef.h>
|
13
|
-
#endif
|
14
|
-
|
15
|
-
typedef void (*element_cb)(void *data, const char *at, size_t length);
|
16
|
-
typedef void (*field_cb)(void *data, const char *field, size_t flen, const char *value, size_t vlen);
|
17
|
-
|
18
|
-
typedef struct httpclient_parser {
|
19
|
-
int cs;
|
20
|
-
size_t body_start;
|
21
|
-
int content_len;
|
22
|
-
size_t nread;
|
23
|
-
size_t mark;
|
24
|
-
size_t field_start;
|
25
|
-
size_t field_len;
|
26
|
-
|
27
|
-
void *data;
|
28
|
-
|
29
|
-
field_cb http_field;
|
30
|
-
element_cb reason_phrase;
|
31
|
-
element_cb status_code;
|
32
|
-
element_cb chunk_size;
|
33
|
-
element_cb http_version;
|
34
|
-
element_cb header_done;
|
35
|
-
element_cb last_chunk;
|
36
|
-
|
37
|
-
|
38
|
-
} httpclient_parser;
|
39
|
-
|
40
|
-
int httpclient_parser_init(httpclient_parser *parser);
|
41
|
-
int httpclient_parser_finish(httpclient_parser *parser);
|
42
|
-
size_t httpclient_parser_execute(httpclient_parser *parser, const char *data, size_t len, size_t off);
|
43
|
-
int httpclient_parser_has_error(httpclient_parser *parser);
|
44
|
-
int httpclient_parser_is_finished(httpclient_parser *parser);
|
45
|
-
|
46
|
-
#define httpclient_parser_nread(parser) (parser)->nread
|
47
|
-
|
48
|
-
#endif
|
1
|
+
/**
|
2
|
+
* Copyright (c) 2005 Zed A. Shaw
|
3
|
+
* You can redistribute it and/or modify it under the same terms as Ruby.
|
4
|
+
*/
|
5
|
+
|
6
|
+
#ifndef http11_parser_h
|
7
|
+
#define http11_parser_h
|
8
|
+
|
9
|
+
#include <sys/types.h>
|
10
|
+
|
11
|
+
#if defined(_WIN32)
|
12
|
+
#include <stddef.h>
|
13
|
+
#endif
|
14
|
+
|
15
|
+
typedef void (*element_cb)(void *data, const char *at, size_t length);
|
16
|
+
typedef void (*field_cb)(void *data, const char *field, size_t flen, const char *value, size_t vlen);
|
17
|
+
|
18
|
+
typedef struct httpclient_parser {
|
19
|
+
int cs;
|
20
|
+
size_t body_start;
|
21
|
+
int content_len;
|
22
|
+
size_t nread;
|
23
|
+
size_t mark;
|
24
|
+
size_t field_start;
|
25
|
+
size_t field_len;
|
26
|
+
|
27
|
+
void *data;
|
28
|
+
|
29
|
+
field_cb http_field;
|
30
|
+
element_cb reason_phrase;
|
31
|
+
element_cb status_code;
|
32
|
+
element_cb chunk_size;
|
33
|
+
element_cb http_version;
|
34
|
+
element_cb header_done;
|
35
|
+
element_cb last_chunk;
|
36
|
+
|
37
|
+
|
38
|
+
} httpclient_parser;
|
39
|
+
|
40
|
+
int httpclient_parser_init(httpclient_parser *parser);
|
41
|
+
int httpclient_parser_finish(httpclient_parser *parser);
|
42
|
+
size_t httpclient_parser_execute(httpclient_parser *parser, const char *data, size_t len, size_t off);
|
43
|
+
int httpclient_parser_has_error(httpclient_parser *parser);
|
44
|
+
int httpclient_parser_is_finished(httpclient_parser *parser);
|
45
|
+
|
46
|
+
#define httpclient_parser_nread(parser) (parser)->nread
|
47
|
+
|
48
|
+
#endif
|
data/lib/em-http.rb
CHANGED
@@ -1,20 +1,19 @@
|
|
1
|
-
#--
|
2
|
-
# Copyright (C)2008 Ilya Grigorik
|
3
|
-
# You can redistribute this under the terms of the Ruby license
|
4
|
-
# See file LICENSE for details
|
5
|
-
#++
|
6
|
-
|
7
1
|
require 'eventmachine'
|
8
|
-
require '
|
2
|
+
require 'escape_utils'
|
3
|
+
require 'addressable/uri'
|
9
4
|
|
10
|
-
require
|
11
|
-
require
|
5
|
+
require 'base64'
|
6
|
+
require 'socket'
|
12
7
|
|
13
|
-
require
|
8
|
+
require 'http11_client'
|
9
|
+
require 'em_buffer'
|
14
10
|
|
15
|
-
require
|
16
|
-
require
|
17
|
-
require
|
18
|
-
require
|
19
|
-
require
|
20
|
-
require
|
11
|
+
require 'em-http/core_ext/bytesize'
|
12
|
+
require 'em-http/http_header'
|
13
|
+
require 'em-http/http_encoding'
|
14
|
+
require 'em-http/http_options'
|
15
|
+
require 'em-http/client'
|
16
|
+
require 'em-http/multi'
|
17
|
+
require 'em-http/request'
|
18
|
+
require 'em-http/decoders'
|
19
|
+
require 'em-http/mock'
|
data/lib/em-http/client.rb
CHANGED
@@ -9,223 +9,14 @@
|
|
9
9
|
|
10
10
|
module EventMachine
|
11
11
|
|
12
|
-
# A simple hash is returned for each request made by HttpClient with the
|
13
|
-
# headers that were given by the server for that request.
|
14
|
-
class HttpResponseHeader < Hash
|
15
|
-
# The reason returned in the http response ("OK","File not found",etc.)
|
16
|
-
attr_accessor :http_reason
|
17
|
-
|
18
|
-
# The HTTP version returned.
|
19
|
-
attr_accessor :http_version
|
20
|
-
|
21
|
-
# The status code (as a string!)
|
22
|
-
attr_accessor :http_status
|
23
|
-
|
24
|
-
# E-Tag
|
25
|
-
def etag
|
26
|
-
self[HttpClient::ETAG]
|
27
|
-
end
|
28
|
-
|
29
|
-
def last_modified
|
30
|
-
self[HttpClient::LAST_MODIFIED]
|
31
|
-
end
|
32
|
-
|
33
|
-
# HTTP response status as an integer
|
34
|
-
def status
|
35
|
-
Integer(http_status) rescue 0
|
36
|
-
end
|
37
|
-
|
38
|
-
# Length of content as an integer, or nil if chunked/unspecified
|
39
|
-
def content_length
|
40
|
-
@content_length ||= ((s = self[HttpClient::CONTENT_LENGTH]) &&
|
41
|
-
(s =~ /^(\d+)$/)) ? $1.to_i : nil
|
42
|
-
end
|
43
|
-
|
44
|
-
# Cookie header from the server
|
45
|
-
def cookie
|
46
|
-
self[HttpClient::SET_COOKIE]
|
47
|
-
end
|
48
|
-
|
49
|
-
# Is the transfer encoding chunked?
|
50
|
-
def chunked_encoding?
|
51
|
-
/chunked/i === self[HttpClient::TRANSFER_ENCODING]
|
52
|
-
end
|
53
|
-
|
54
|
-
def keep_alive?
|
55
|
-
/keep-alive/i === self[HttpClient::KEEP_ALIVE]
|
56
|
-
end
|
57
|
-
|
58
|
-
def compressed?
|
59
|
-
/gzip|compressed|deflate/i === self[HttpClient::CONTENT_ENCODING]
|
60
|
-
end
|
61
|
-
|
62
|
-
def location
|
63
|
-
self[HttpClient::LOCATION]
|
64
|
-
end
|
65
|
-
end
|
66
|
-
|
67
|
-
class HttpChunkHeader < Hash
|
68
|
-
# When parsing chunked encodings this is set
|
69
|
-
attr_accessor :http_chunk_size
|
70
|
-
|
71
|
-
def initialize
|
72
|
-
super
|
73
|
-
@http_chunk_size = '0'
|
74
|
-
end
|
75
|
-
|
76
|
-
# Size of the chunk as an integer
|
77
|
-
def chunk_size
|
78
|
-
@http_chunk_size.to_i(base=16)
|
79
|
-
end
|
80
|
-
end
|
81
|
-
|
82
|
-
# Methods for building HTTP requests
|
83
|
-
module HttpEncoding
|
84
|
-
HTTP_REQUEST_HEADER="%s %s HTTP/1.1\r\n"
|
85
|
-
FIELD_ENCODING = "%s: %s\r\n"
|
86
|
-
|
87
|
-
# Escapes a URI.
|
88
|
-
def escape(s)
|
89
|
-
s.to_s.gsub(/([^a-zA-Z0-9_.-]+)/n) {
|
90
|
-
'%'+$1.unpack('H2'*bytesize($1)).join('%').upcase
|
91
|
-
}
|
92
|
-
end
|
93
|
-
|
94
|
-
# Unescapes a URI escaped string.
|
95
|
-
def unescape(s)
|
96
|
-
s.tr('+', ' ').gsub(/((?:%[0-9a-fA-F]{2})+)/n){
|
97
|
-
[$1.delete('%')].pack('H*')
|
98
|
-
}
|
99
|
-
end
|
100
|
-
|
101
|
-
if ''.respond_to?(:bytesize)
|
102
|
-
def bytesize(string)
|
103
|
-
string.bytesize
|
104
|
-
end
|
105
|
-
else
|
106
|
-
def bytesize(string)
|
107
|
-
string.size
|
108
|
-
end
|
109
|
-
end
|
110
|
-
|
111
|
-
# Map all header keys to a downcased string version
|
112
|
-
def munge_header_keys(head)
|
113
|
-
head.inject({}) { |h, (k, v)| h[k.to_s.downcase] = v; h }
|
114
|
-
end
|
115
|
-
|
116
|
-
# HTTP is kind of retarded that you have to specify a Host header, but if
|
117
|
-
# you include port 80 then further redirects will tack on the :80 which is
|
118
|
-
# annoying.
|
119
|
-
def encode_host
|
120
|
-
if @uri.port == 80 || @uri.port == 443
|
121
|
-
return @uri.host
|
122
|
-
else
|
123
|
-
@uri.host + ":#{@uri.port}"
|
124
|
-
end
|
125
|
-
end
|
126
|
-
|
127
|
-
def encode_request(method, uri, query, proxy)
|
128
|
-
query = encode_query(uri, query)
|
129
|
-
|
130
|
-
# Non CONNECT proxies require that you provide the full request
|
131
|
-
# uri in request header, as opposed to a relative path.
|
132
|
-
query = uri.join(query) if proxy && proxy[:type] != :socks && !proxy[:use_connect]
|
133
|
-
|
134
|
-
HTTP_REQUEST_HEADER % [method.to_s.upcase, query]
|
135
|
-
end
|
136
|
-
|
137
|
-
def encode_query(uri, query)
|
138
|
-
encoded_query = if query.kind_of?(Hash)
|
139
|
-
query.map { |k, v| encode_param(k, v) }.join('&')
|
140
|
-
else
|
141
|
-
query.to_s
|
142
|
-
end
|
143
|
-
|
144
|
-
if !uri.query.to_s.empty?
|
145
|
-
encoded_query = [encoded_query, uri.query].reject {|part| part.empty?}.join("&")
|
146
|
-
end
|
147
|
-
encoded_query.to_s.empty? ? uri.path : "#{uri.path}?#{encoded_query}"
|
148
|
-
end
|
149
|
-
|
150
|
-
# URL encodes query parameters:
|
151
|
-
# single k=v, or a URL encoded array, if v is an array of values
|
152
|
-
def encode_param(k, v)
|
153
|
-
if v.is_a?(Array)
|
154
|
-
v.map { |e| escape(k) + "[]=" + escape(e) }.join("&")
|
155
|
-
else
|
156
|
-
escape(k) + "=" + escape(v)
|
157
|
-
end
|
158
|
-
end
|
159
|
-
|
160
|
-
def form_encode_body(obj)
|
161
|
-
pairs = []
|
162
|
-
recursive = Proc.new do |h, prefix|
|
163
|
-
h.each do |k,v|
|
164
|
-
key = prefix == '' ? escape(k) : "#{prefix}[#{escape(k)}]"
|
165
|
-
|
166
|
-
if v.is_a? Array
|
167
|
-
nh = Hash.new
|
168
|
-
v.size.times { |t| nh[t] = v[t] }
|
169
|
-
recursive.call(nh, key)
|
170
|
-
|
171
|
-
elsif v.is_a? Hash
|
172
|
-
recursive.call(v, key)
|
173
|
-
else
|
174
|
-
pairs << "#{key}=#{escape(v)}"
|
175
|
-
end
|
176
|
-
end
|
177
|
-
end
|
178
|
-
|
179
|
-
recursive.call(obj, '')
|
180
|
-
return pairs.join('&')
|
181
|
-
end
|
182
|
-
|
183
|
-
# Encode a field in an HTTP header
|
184
|
-
def encode_field(k, v)
|
185
|
-
FIELD_ENCODING % [k, v]
|
186
|
-
end
|
187
|
-
|
188
|
-
# Encode basic auth in an HTTP header
|
189
|
-
# In: Array ([user, pass]) - for basic auth
|
190
|
-
# String - custom auth string (OAuth, etc)
|
191
|
-
def encode_auth(k,v)
|
192
|
-
if v.is_a? Array
|
193
|
-
FIELD_ENCODING % [k, ["Basic", Base64.encode64(v.join(":")).chomp].join(" ")]
|
194
|
-
else
|
195
|
-
encode_field(k,v)
|
196
|
-
end
|
197
|
-
end
|
198
|
-
|
199
|
-
def encode_headers(head)
|
200
|
-
head.inject('') do |result, (key, value)|
|
201
|
-
# Munge keys from foo-bar-baz to Foo-Bar-Baz
|
202
|
-
key = key.split('-').map { |k| k.to_s.capitalize }.join('-')
|
203
|
-
result << case key
|
204
|
-
when 'Authorization', 'Proxy-authorization'
|
205
|
-
encode_auth(key, value)
|
206
|
-
else
|
207
|
-
encode_field(key, value)
|
208
|
-
end
|
209
|
-
end
|
210
|
-
end
|
211
|
-
|
212
|
-
def encode_cookie(cookie)
|
213
|
-
if cookie.is_a? Hash
|
214
|
-
cookie.inject('') { |result, (k, v)| result << encode_param(k, v) + ";" }
|
215
|
-
else
|
216
|
-
cookie
|
217
|
-
end
|
218
|
-
end
|
219
|
-
end
|
220
|
-
|
221
12
|
class HttpClient < Connection
|
222
13
|
include EventMachine::Deferrable
|
223
|
-
include HttpEncoding
|
14
|
+
include EventMachine::HttpEncoding
|
224
15
|
|
225
16
|
TRANSFER_ENCODING="TRANSFER_ENCODING"
|
226
17
|
CONTENT_ENCODING="CONTENT_ENCODING"
|
227
18
|
CONTENT_LENGTH="CONTENT_LENGTH"
|
228
|
-
CONTENT_TYPE="CONTENT_TYPE"
|
19
|
+
CONTENT_TYPE="CONTENT_TYPE"
|
229
20
|
LAST_MODIFIED="LAST_MODIFIED"
|
230
21
|
KEEP_ALIVE="CONNECTION"
|
231
22
|
SET_COOKIE="SET_COOKIE"
|
@@ -236,7 +27,7 @@ module EventMachine
|
|
236
27
|
CRLF="\r\n"
|
237
28
|
|
238
29
|
attr_accessor :method, :options, :uri
|
239
|
-
attr_reader :response, :response_header, :error, :redirects, :last_effective_url
|
30
|
+
attr_reader :response, :response_header, :error, :redirects, :last_effective_url, :content_charset
|
240
31
|
|
241
32
|
def post_init
|
242
33
|
@parser = HttpClientParser.new
|
@@ -425,7 +216,12 @@ module EventMachine
|
|
425
216
|
|
426
217
|
# Set content-type header if missing and body is a Ruby hash
|
427
218
|
if not head['content-type'] and options[:body].is_a? Hash
|
428
|
-
head['content-type'] =
|
219
|
+
head['content-type'] = 'application/x-www-form-urlencoded'
|
220
|
+
end
|
221
|
+
|
222
|
+
# Set connection close unless keepalive
|
223
|
+
unless options[:keepalive]
|
224
|
+
head['connection'] = 'close'
|
429
225
|
end
|
430
226
|
end
|
431
227
|
|
@@ -474,7 +270,7 @@ module EventMachine
|
|
474
270
|
end
|
475
271
|
|
476
272
|
def on_decoded_body_data(data)
|
477
|
-
data.force_encoding @content_charset
|
273
|
+
data.force_encoding @content_charset if @content_charset
|
478
274
|
if @stream
|
479
275
|
@stream.call(data)
|
480
276
|
else
|
@@ -652,7 +448,7 @@ module EventMachine
|
|
652
448
|
end
|
653
449
|
|
654
450
|
if ''.respond_to?(:force_encoding) && /;\s*charset=\s*(.+?)\s*(;|$)/.match(response_header[CONTENT_TYPE])
|
655
|
-
@content_charset = Encoding.find
|
451
|
+
@content_charset = Encoding.find($1.gsub(/^\"|\"$/, '')) rescue Encoding.default_external
|
656
452
|
end
|
657
453
|
|
658
454
|
true
|
@@ -852,13 +648,10 @@ module EventMachine
|
|
852
648
|
on_request_complete
|
853
649
|
|
854
650
|
else
|
855
|
-
|
856
|
-
|
857
|
-
|
858
|
-
|
859
|
-
@state = :invalid
|
860
|
-
on_error "garbage at end of body"
|
861
|
-
end
|
651
|
+
|
652
|
+
@data.clear
|
653
|
+
@state = :finished
|
654
|
+
on_request_complete
|
862
655
|
end
|
863
656
|
|
864
657
|
false
|
@@ -0,0 +1,135 @@
|
|
1
|
+
module EventMachine
|
2
|
+
module HttpEncoding
|
3
|
+
HTTP_REQUEST_HEADER="%s %s HTTP/1.1\r\n"
|
4
|
+
FIELD_ENCODING = "%s: %s\r\n"
|
5
|
+
|
6
|
+
# Escapes a URI.
|
7
|
+
def escape(s)
|
8
|
+
EscapeUtils.escape_url(s.to_s)
|
9
|
+
end
|
10
|
+
|
11
|
+
# Unescapes a URI escaped string.
|
12
|
+
def unescape(s)
|
13
|
+
EscapeUtils.unescape_url(s.to_s)
|
14
|
+
end
|
15
|
+
|
16
|
+
if ''.respond_to?(:bytesize)
|
17
|
+
def bytesize(string)
|
18
|
+
string.bytesize
|
19
|
+
end
|
20
|
+
else
|
21
|
+
def bytesize(string)
|
22
|
+
string.size
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
# Map all header keys to a downcased string version
|
27
|
+
def munge_header_keys(head)
|
28
|
+
head.inject({}) { |h, (k, v)| h[k.to_s.downcase] = v; h }
|
29
|
+
end
|
30
|
+
|
31
|
+
# HTTP is kind of retarded that you have to specify a Host header, but if
|
32
|
+
# you include port 80 then further redirects will tack on the :80 which is
|
33
|
+
# annoying.
|
34
|
+
def encode_host
|
35
|
+
if @uri.port == 80 || @uri.port == 443
|
36
|
+
return @uri.host
|
37
|
+
else
|
38
|
+
@uri.host + ":#{@uri.port}"
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def encode_request(method, uri, query, proxy)
|
43
|
+
query = encode_query(uri, query)
|
44
|
+
|
45
|
+
# Non CONNECT proxies require that you provide the full request
|
46
|
+
# uri in request header, as opposed to a relative path.
|
47
|
+
query = uri.join(query) if proxy && proxy[:type] != :socks && !proxy[:use_connect]
|
48
|
+
|
49
|
+
HTTP_REQUEST_HEADER % [method.to_s.upcase, query]
|
50
|
+
end
|
51
|
+
|
52
|
+
def encode_query(uri, query)
|
53
|
+
encoded_query = if query.kind_of?(Hash)
|
54
|
+
query.map { |k, v| encode_param(k, v) }.join('&')
|
55
|
+
else
|
56
|
+
query.to_s
|
57
|
+
end
|
58
|
+
|
59
|
+
if !uri.query.to_s.empty?
|
60
|
+
encoded_query = [encoded_query, uri.query].reject {|part| part.empty?}.join("&")
|
61
|
+
end
|
62
|
+
encoded_query.to_s.empty? ? uri.path : "#{uri.path}?#{encoded_query}"
|
63
|
+
end
|
64
|
+
|
65
|
+
# URL encodes query parameters:
|
66
|
+
# single k=v, or a URL encoded array, if v is an array of values
|
67
|
+
def encode_param(k, v)
|
68
|
+
if v.is_a?(Array)
|
69
|
+
v.map { |e| escape(k) + "[]=" + escape(e) }.join("&")
|
70
|
+
else
|
71
|
+
escape(k) + "=" + escape(v)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def form_encode_body(obj)
|
76
|
+
pairs = []
|
77
|
+
recursive = Proc.new do |h, prefix|
|
78
|
+
h.each do |k,v|
|
79
|
+
key = prefix == '' ? escape(k) : "#{prefix}[#{escape(k)}]"
|
80
|
+
|
81
|
+
if v.is_a? Array
|
82
|
+
nh = Hash.new
|
83
|
+
v.size.times { |t| nh[t] = v[t] }
|
84
|
+
recursive.call(nh, key)
|
85
|
+
|
86
|
+
elsif v.is_a? Hash
|
87
|
+
recursive.call(v, key)
|
88
|
+
else
|
89
|
+
pairs << "#{key}=#{escape(v)}"
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
recursive.call(obj, '')
|
95
|
+
return pairs.join('&')
|
96
|
+
end
|
97
|
+
|
98
|
+
# Encode a field in an HTTP header
|
99
|
+
def encode_field(k, v)
|
100
|
+
FIELD_ENCODING % [k, v]
|
101
|
+
end
|
102
|
+
|
103
|
+
# Encode basic auth in an HTTP header
|
104
|
+
# In: Array ([user, pass]) - for basic auth
|
105
|
+
# String - custom auth string (OAuth, etc)
|
106
|
+
def encode_auth(k,v)
|
107
|
+
if v.is_a? Array
|
108
|
+
FIELD_ENCODING % [k, ["Basic", Base64.encode64(v.join(":")).chomp].join(" ")]
|
109
|
+
else
|
110
|
+
encode_field(k,v)
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
def encode_headers(head)
|
115
|
+
head.inject('') do |result, (key, value)|
|
116
|
+
# Munge keys from foo-bar-baz to Foo-Bar-Baz
|
117
|
+
key = key.split('-').map { |k| k.to_s.capitalize }.join('-')
|
118
|
+
result << case key
|
119
|
+
when 'Authorization', 'Proxy-Authorization'
|
120
|
+
encode_auth(key, value)
|
121
|
+
else
|
122
|
+
encode_field(key, value)
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
def encode_cookie(cookie)
|
128
|
+
if cookie.is_a? Hash
|
129
|
+
cookie.inject('') { |result, (k, v)| result << encode_param(k, v) + ";" }
|
130
|
+
else
|
131
|
+
cookie
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|