htty 1.4.1 → 1.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +2 -1
- data/.rspec +2 -0
- data/.travis.yml +21 -3
- data/.yardopts +1 -1
- data/Gemfile +2 -2
- data/Guardfile +12 -10
- data/History.markdown +14 -0
- data/{MIT-LICENSE.markdown → License.markdown} +1 -1
- data/README.markdown +50 -65
- data/Rakefile +2 -2
- data/htty.gemspec +2 -2
- data/lib/htty/cli.rb +59 -74
- data/lib/htty/cli/command.rb +21 -20
- data/lib/htty/cli/commands/body_edit.rb +89 -0
- data/lib/htty/cli/commands/query_add.rb +3 -0
- data/lib/htty/cli/commands/query_set.rb +3 -0
- data/lib/htty/cli/commands/userinfo_set.rb +8 -14
- data/lib/htty/cli/display.rb +14 -12
- data/lib/htty/cli/input_device.rb +75 -0
- data/lib/htty/cli/url_escaping.rb +2 -2
- data/lib/htty/headers.rb +81 -0
- data/lib/htty/no_header_error.rb +10 -0
- data/lib/htty/payload.rb +22 -9
- data/lib/htty/request.rb +67 -43
- data/lib/htty/requests_util.rb +22 -8
- data/lib/htty/response.rb +20 -1
- data/lib/htty/uri.rb +16 -0
- data/lib/htty/version.rb +1 -1
- data/spec/integration/htty/cli/commands/query_add_spec.rb +7 -1
- data/spec/integration/htty/cli/commands/query_remove_spec.rb +19 -1
- data/spec/integration/htty/cli/commands/query_set_spec.rb +9 -3
- data/spec/integration/htty/cli/commands/query_unset_spec.rb +8 -2
- data/spec/spec_helper.rb +69 -0
- data/spec/unit/htty/cli/commands/address_spec.rb +1 -1
- data/spec/unit/htty/cli/commands/body_clear_spec.rb +1 -1
- data/spec/unit/htty/cli/commands/body_edit_spec.rb +18 -0
- data/spec/unit/htty/cli/commands/body_request_spec.rb +1 -1
- data/spec/unit/htty/cli/commands/body_response_spec.rb +1 -1
- data/spec/unit/htty/cli/commands/body_set_spec.rb +1 -1
- data/spec/unit/htty/cli/commands/body_unset_spec.rb +1 -1
- data/spec/unit/htty/cli/commands/cd_spec.rb +1 -1
- data/spec/unit/htty/cli/commands/cookie_add_spec.rb +1 -1
- data/spec/unit/htty/cli/commands/cookie_remove_spec.rb +1 -1
- data/spec/unit/htty/cli/commands/cookies_add_spec.rb +1 -1
- data/spec/unit/htty/cli/commands/cookies_clear_spec.rb +1 -1
- data/spec/unit/htty/cli/commands/cookies_remove_all_spec.rb +1 -1
- data/spec/unit/htty/cli/commands/cookies_remove_spec.rb +1 -1
- data/spec/unit/htty/cli/commands/cookies_spec.rb +1 -1
- data/spec/unit/htty/cli/commands/cookies_use_spec.rb +1 -1
- data/spec/unit/htty/cli/commands/delete_spec.rb +1 -1
- data/spec/unit/htty/cli/commands/exit_spec.rb +1 -1
- data/spec/unit/htty/cli/commands/follow_spec.rb +1 -1
- data/spec/unit/htty/cli/commands/form_add_spec.rb +1 -1
- data/spec/unit/htty/cli/commands/form_clear_spec.rb +1 -1
- data/spec/unit/htty/cli/commands/form_remove_all_spec.rb +1 -1
- data/spec/unit/htty/cli/commands/form_remove_spec.rb +1 -1
- data/spec/unit/htty/cli/commands/form_spec.rb +1 -1
- data/spec/unit/htty/cli/commands/fragment_clear_spec.rb +1 -1
- data/spec/unit/htty/cli/commands/fragment_set_spec.rb +1 -1
- data/spec/unit/htty/cli/commands/fragment_unset_spec.rb +1 -1
- data/spec/unit/htty/cli/commands/get_spec.rb +1 -1
- data/spec/unit/htty/cli/commands/header_set_spec.rb +1 -1
- data/spec/unit/htty/cli/commands/header_unset_spec.rb +1 -1
- data/spec/unit/htty/cli/commands/headers_clear_spec.rb +1 -1
- data/spec/unit/htty/cli/commands/headers_request_spec.rb +1 -1
- data/spec/unit/htty/cli/commands/headers_response_spec.rb +1 -1
- data/spec/unit/htty/cli/commands/headers_set_spec.rb +1 -1
- data/spec/unit/htty/cli/commands/headers_unset_all_spec.rb +1 -1
- data/spec/unit/htty/cli/commands/headers_unset_spec.rb +1 -1
- data/spec/unit/htty/cli/commands/help_spec.rb +1 -1
- data/spec/unit/htty/cli/commands/history_spec.rb +1 -1
- data/spec/unit/htty/cli/commands/history_verbose_spec.rb +1 -1
- data/spec/unit/htty/cli/commands/host_set_spec.rb +1 -1
- data/spec/unit/htty/cli/commands/http_delete_spec.rb +1 -1
- data/spec/unit/htty/cli/commands/http_get_spec.rb +1 -1
- data/spec/unit/htty/cli/commands/http_head_spec.rb +1 -1
- data/spec/unit/htty/cli/commands/http_options_spec.rb +1 -1
- data/spec/unit/htty/cli/commands/http_patch_spec.rb +1 -1
- data/spec/unit/htty/cli/commands/http_post_spec.rb +1 -1
- data/spec/unit/htty/cli/commands/http_put_spec.rb +1 -1
- data/spec/unit/htty/cli/commands/http_trace_spec.rb +1 -1
- data/spec/unit/htty/cli/commands/patch_spec.rb +1 -1
- data/spec/unit/htty/cli/commands/path_set_spec.rb +1 -1
- data/spec/unit/htty/cli/commands/port_set_spec.rb +1 -1
- data/spec/unit/htty/cli/commands/post_spec.rb +1 -1
- data/spec/unit/htty/cli/commands/put_spec.rb +1 -1
- data/spec/unit/htty/cli/commands/query_add_spec.rb +1 -1
- data/spec/unit/htty/cli/commands/query_clear_spec.rb +1 -1
- data/spec/unit/htty/cli/commands/query_remove_spec.rb +1 -1
- data/spec/unit/htty/cli/commands/query_set_spec.rb +1 -1
- data/spec/unit/htty/cli/commands/query_unset_all_spec.rb +1 -1
- data/spec/unit/htty/cli/commands/query_unset_spec.rb +1 -1
- data/spec/unit/htty/cli/commands/quit_spec.rb +1 -1
- data/spec/unit/htty/cli/commands/reuse_spec.rb +1 -1
- data/spec/unit/htty/cli/commands/scheme_set_spec.rb +1 -1
- data/spec/unit/htty/cli/commands/shared_examples_for_commands.rb +55 -0
- data/spec/unit/htty/cli/commands/ssl_verification_off_spec.rb +1 -1
- data/spec/unit/htty/cli/commands/ssl_verification_on_spec.rb +1 -1
- data/spec/unit/htty/cli/commands/ssl_verification_spec.rb +1 -1
- data/spec/unit/htty/cli/commands/status_spec.rb +1 -1
- data/spec/unit/htty/cli/commands/undo_spec.rb +1 -1
- data/spec/unit/htty/cli/commands/userinfo_clear_spec.rb +1 -1
- data/spec/unit/htty/cli/commands/userinfo_set_spec.rb +23 -1
- data/spec/unit/htty/cli/commands/userinfo_unset_spec.rb +1 -1
- data/spec/unit/htty/cli/display_spec.rb +84 -0
- data/spec/unit/htty/cli_spec.rb +1 -1
- data/spec/unit/htty/command.rb +47 -0
- data/spec/unit/htty/{ordered_hash_spec.rb → headers_spec.rb} +4 -4
- data/spec/unit/htty/payload_spec.rb +60 -0
- data/spec/unit/htty/preferences_spec.rb +1 -1
- data/spec/unit/htty/request_follow_spec.rb +94 -0
- data/spec/unit/htty/request_spec.rb +5 -187
- data/spec/unit/htty/request_userinfo_spec.rb +208 -0
- data/spec/unit/htty/session_spec.rb +1 -1
- data/spec/unit/htty/shared_examples_for_requests.rb +32 -0
- data/spec/unit/htty/url_escaping.rb +70 -0
- data/spec/unit/htty/version_spec.rb +1 -1
- metadata +43 -30
- data/lib/htty/ordered_hash.rb +0 -68
data/lib/htty/payload.rb
CHANGED
@@ -1,4 +1,6 @@
|
|
1
|
-
require File.expand_path("#{File.dirname __FILE__}/
|
1
|
+
require File.expand_path("#{File.dirname __FILE__}/headers")
|
2
|
+
require File.expand_path("#{File.dirname __FILE__}/no_header_error")
|
3
|
+
require File.expand_path("#{File.dirname __FILE__}/cookies_util")
|
2
4
|
|
3
5
|
module HTTY; end
|
4
6
|
|
@@ -20,6 +22,24 @@ class HTTY::Payload
|
|
20
22
|
@headers.to_a
|
21
23
|
end
|
22
24
|
|
25
|
+
def headers_with_key(key)
|
26
|
+
headers.select do |header_key, header_value|
|
27
|
+
key.downcase == header_key.downcase
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def header(key, otherwise=:__no_default_value_given)
|
32
|
+
all_headers_with_key = headers_with_key(key)
|
33
|
+
return all_headers_with_key.last.last unless all_headers_with_key.empty?
|
34
|
+
raise otherwise if otherwise.is_a? Exception
|
35
|
+
return otherwise unless otherwise == :__no_default_value_given
|
36
|
+
raise HTTY::NoHeaderError.new(key)
|
37
|
+
end
|
38
|
+
|
39
|
+
def cookies_from(cookies_header_key)
|
40
|
+
HTTY::CookiesUtil.cookies_from_string header(cookies_header_key, nil)
|
41
|
+
end
|
42
|
+
|
23
43
|
protected
|
24
44
|
|
25
45
|
# Initializes a new HTTY::Payload with attribute values specified in the
|
@@ -31,17 +51,10 @@ protected
|
|
31
51
|
# * <tt>:headers</tt>
|
32
52
|
def initialize(attributes={})
|
33
53
|
@body = attributes[:body]
|
34
|
-
@headers = HTTY::
|
54
|
+
@headers = HTTY::Headers.new
|
35
55
|
Array(attributes[:headers]).each do |name, value|
|
36
56
|
@headers[name] = value
|
37
57
|
end
|
38
58
|
end
|
39
59
|
|
40
|
-
# @private
|
41
|
-
def initialize_copy(source)
|
42
|
-
super
|
43
|
-
@body = @body.dup if @body
|
44
|
-
@headers = @headers.dup
|
45
|
-
end
|
46
|
-
|
47
60
|
end
|
data/lib/htty/request.rb
CHANGED
@@ -6,6 +6,7 @@ require File.expand_path("#{File.dirname __FILE__}/cookies_util")
|
|
6
6
|
require File.expand_path("#{File.dirname __FILE__}/no_location_header_error")
|
7
7
|
require File.expand_path("#{File.dirname __FILE__}/no_response_error")
|
8
8
|
require File.expand_path("#{File.dirname __FILE__}/no_set_cookie_header_error")
|
9
|
+
require File.expand_path("#{File.dirname __FILE__}/uri")
|
9
10
|
require File.expand_path("#{File.dirname __FILE__}/payload")
|
10
11
|
require File.expand_path("#{File.dirname __FILE__}/requests_util")
|
11
12
|
require File.expand_path("#{File.dirname __FILE__}/response")
|
@@ -141,13 +142,6 @@ public
|
|
141
142
|
establish_content_length
|
142
143
|
end
|
143
144
|
|
144
|
-
# @private
|
145
|
-
def initialize_copy(source)
|
146
|
-
super
|
147
|
-
@response = @response.dup if @response
|
148
|
-
@uri = @uri.dup
|
149
|
-
end
|
150
|
-
|
151
145
|
# Returns +true+ if _other_request_ is equivalent to the request.
|
152
146
|
def ==(other_request)
|
153
147
|
return false unless super(other_request)
|
@@ -229,9 +223,14 @@ public
|
|
229
223
|
self
|
230
224
|
end
|
231
225
|
|
226
|
+
# Returns true if has some cookies.
|
227
|
+
def cookies?
|
228
|
+
not cookies.empty?
|
229
|
+
end
|
230
|
+
|
232
231
|
# Returns an array of the cookies belonging to the request.
|
233
232
|
def cookies
|
234
|
-
|
233
|
+
cookies_from(COOKIES_HEADER_NAME)
|
235
234
|
end
|
236
235
|
|
237
236
|
# Removes all #cookies.
|
@@ -267,14 +266,7 @@ public
|
|
267
266
|
# HTTY::NoLocationHeaderError.
|
268
267
|
def follow(response)
|
269
268
|
raise HTTY::NoResponseError unless response
|
270
|
-
|
271
|
-
location_header = response.headers.detect do |name, value|
|
272
|
-
name == HTTY::Response::LOCATION_HEADER_NAME
|
273
|
-
end
|
274
|
-
unless location_header && location_header.last
|
275
|
-
raise HTTY::NoLocationHeaderError
|
276
|
-
end
|
277
|
-
address location_header.last
|
269
|
+
response.follow_relative_to(self)
|
278
270
|
end
|
279
271
|
|
280
272
|
# Establishes a new #uri with the specified _fragment_.
|
@@ -302,13 +294,29 @@ public
|
|
302
294
|
def header_set(name, value)
|
303
295
|
return dup_without_response.header_set(name, value) if response
|
304
296
|
|
305
|
-
name = name.to_s
|
297
|
+
name = name && name.to_s
|
298
|
+
value = value && value.to_s
|
299
|
+
|
300
|
+
# to avoid recursion when rebuild_uri
|
301
|
+
return self if @headers[name] == value
|
302
|
+
|
306
303
|
if value.nil?
|
307
304
|
@headers.delete name
|
305
|
+
if name.downcase == AUTHORIZATION_HEADER_NAME.downcase
|
306
|
+
return rebuild_uri :userinfo => nil
|
307
|
+
end
|
308
308
|
return self
|
309
309
|
end
|
310
310
|
|
311
|
-
@headers[name] = value
|
311
|
+
@headers[name] = value
|
312
|
+
if name.downcase == AUTHORIZATION_HEADER_NAME.downcase
|
313
|
+
HTTY::Headers.credentials_from(value) do |username, password|
|
314
|
+
return rebuild_uri :userinfo => [
|
315
|
+
HTTY::URI.escape_component(username),
|
316
|
+
HTTY::URI.escape_component(password)
|
317
|
+
].compact.join(':')
|
318
|
+
end
|
319
|
+
end
|
312
320
|
self
|
313
321
|
end
|
314
322
|
|
@@ -317,6 +325,14 @@ public
|
|
317
325
|
header_set name, nil
|
318
326
|
end
|
319
327
|
|
328
|
+
# Removes all #headers.
|
329
|
+
def headers_unset_all
|
330
|
+
return dup_without_response.headers_unset_all if response
|
331
|
+
|
332
|
+
@headers.clear
|
333
|
+
rebuild_uri :userinfo => nil
|
334
|
+
end
|
335
|
+
|
320
336
|
# Returns an array of the headers belonging to the payload. If
|
321
337
|
# _include_content_length_ is +false+, then a 'Content Length' header will be
|
322
338
|
# omitted. If _include_content_length_ is not specified, then it will be
|
@@ -333,14 +349,6 @@ public
|
|
333
349
|
super()
|
334
350
|
end
|
335
351
|
|
336
|
-
# Removes all #headers.
|
337
|
-
def headers_unset_all
|
338
|
-
return dup_without_response.headers_unset_all if response
|
339
|
-
|
340
|
-
@headers.clear
|
341
|
-
self
|
342
|
-
end
|
343
|
-
|
344
352
|
# Establishes a new #uri with the specified _host_.
|
345
353
|
def host_set(host)
|
346
354
|
rebuild_uri :host => host
|
@@ -383,8 +391,34 @@ public
|
|
383
391
|
def query_add(name, value=nil)
|
384
392
|
entries = current_query_entries
|
385
393
|
entries << name + (value.nil? ? '' : "=#{value}")
|
386
|
-
|
387
|
-
|
394
|
+
query_set_all(entries)
|
395
|
+
end
|
396
|
+
|
397
|
+
# Establishes a new #uri with the specified _value_ for the query-string
|
398
|
+
# parameter specified by _name_. The _value_ is optional.
|
399
|
+
#
|
400
|
+
# If there is more than one query-string parameter named _name_, they are
|
401
|
+
# replaced by a single one with the specified _value_.
|
402
|
+
def query_set(name, value=nil)
|
403
|
+
entries = current_query_entries
|
404
|
+
add_or_replace_field(entries, name, value)
|
405
|
+
query_set_all(entries)
|
406
|
+
end
|
407
|
+
|
408
|
+
# Establishes a new #uri with the query-string parameter specified by by
|
409
|
+
# _query_string_ parameter
|
410
|
+
def query_set_all(query_string)
|
411
|
+
# _query_string_ as an array of parameters is only for internal usage
|
412
|
+
query_string =
|
413
|
+
case query_string
|
414
|
+
when Array
|
415
|
+
query_string.empty? ? nil : query_string.join('&')
|
416
|
+
when String
|
417
|
+
query_string
|
418
|
+
else
|
419
|
+
nil
|
420
|
+
end
|
421
|
+
rebuild_uri :query => query_string
|
388
422
|
end
|
389
423
|
|
390
424
|
# Establishes a new #uri, removing the last query-string parameter specified
|
@@ -401,19 +435,7 @@ public
|
|
401
435
|
break
|
402
436
|
end
|
403
437
|
end
|
404
|
-
|
405
|
-
end
|
406
|
-
|
407
|
-
# Establishes a new #uri with the specified _value_ for the query-string
|
408
|
-
# parameter specified by _name_. The _value_ is optional.
|
409
|
-
#
|
410
|
-
# If there is more than one query-string parameter named _name_, they are
|
411
|
-
# replaced by a single one with the specified _value_.
|
412
|
-
def query_set(name, value=nil)
|
413
|
-
entries = current_query_entries
|
414
|
-
add_or_replace_field(entries, name, value)
|
415
|
-
new_query = entries.empty? ? nil : entries.join('&')
|
416
|
-
rebuild_uri :query => new_query
|
438
|
+
query_set_all(entries)
|
417
439
|
end
|
418
440
|
|
419
441
|
# Establishes a new #uri without the query-string parameter specified by
|
@@ -427,7 +449,7 @@ public
|
|
427
449
|
entries.delete_if do |entry|
|
428
450
|
entry =~ field_matcher(name)
|
429
451
|
end
|
430
|
-
|
452
|
+
query_set_all(entries)
|
431
453
|
end
|
432
454
|
|
433
455
|
# Establishes a new #uri without a query string.
|
@@ -484,8 +506,10 @@ protected
|
|
484
506
|
components = URI::HTTP::COMPONENT.inject({}) do |result, c|
|
485
507
|
result.merge c => uri.send(c)
|
486
508
|
end
|
509
|
+
components = components.merge(changed_components)
|
510
|
+
components[:query] = nil if components[:query] && components[:query].empty?
|
487
511
|
self.class.send(:set_up_cookies_and_authentication, self) do
|
488
|
-
@uri = self.class.build_uri(components
|
512
|
+
@uri = self.class.build_uri(components)
|
489
513
|
end
|
490
514
|
end
|
491
515
|
|
data/lib/htty/requests_util.rb
CHANGED
@@ -13,28 +13,28 @@ module HTTY::RequestsUtil
|
|
13
13
|
# Makes an HTTP DELETE request with the specified _request_.
|
14
14
|
def self.delete(request)
|
15
15
|
request(request) do |host|
|
16
|
-
host.delete request.send(:path_query_and_fragment), request
|
16
|
+
host.delete request.send(:path_query_and_fragment), headers_from(request)
|
17
17
|
end
|
18
18
|
end
|
19
19
|
|
20
20
|
# Makes an HTTP GET request with the specified _request_.
|
21
21
|
def self.get(request)
|
22
22
|
request(request) do |host|
|
23
|
-
host.request_get request.send(:path_query_and_fragment), request
|
23
|
+
host.request_get request.send(:path_query_and_fragment), headers_from(request)
|
24
24
|
end
|
25
25
|
end
|
26
26
|
|
27
27
|
# Makes an HTTP HEAD request with the specified _request_.
|
28
28
|
def self.head(request)
|
29
29
|
request(request) do |host|
|
30
|
-
host.head request.send(:path_query_and_fragment), request
|
30
|
+
host.head request.send(:path_query_and_fragment), headers_from(request)
|
31
31
|
end
|
32
32
|
end
|
33
33
|
|
34
34
|
# Makes an HTTP OPTIONS request with the specified _request_.
|
35
35
|
def self.options(request)
|
36
36
|
request(request) do |host|
|
37
|
-
host.options request.send(:path_query_and_fragment), request
|
37
|
+
host.options request.send(:path_query_and_fragment), headers_from(request)
|
38
38
|
end
|
39
39
|
end
|
40
40
|
|
@@ -43,7 +43,7 @@ module HTTY::RequestsUtil
|
|
43
43
|
request(request) do |host|
|
44
44
|
host.patch request.send(:path_query_and_fragment),
|
45
45
|
request.body,
|
46
|
-
request
|
46
|
+
headers_from(request)
|
47
47
|
end
|
48
48
|
end
|
49
49
|
|
@@ -52,7 +52,7 @@ module HTTY::RequestsUtil
|
|
52
52
|
request(request) do |host|
|
53
53
|
host.post request.send(:path_query_and_fragment),
|
54
54
|
request.body,
|
55
|
-
request
|
55
|
+
headers_from(request)
|
56
56
|
end
|
57
57
|
end
|
58
58
|
|
@@ -61,14 +61,14 @@ module HTTY::RequestsUtil
|
|
61
61
|
request(request) do |host|
|
62
62
|
host.put request.send(:path_query_and_fragment),
|
63
63
|
request.body,
|
64
|
-
request
|
64
|
+
headers_from(request)
|
65
65
|
end
|
66
66
|
end
|
67
67
|
|
68
68
|
# Makes an HTTP TRACE request with the specified _request_.
|
69
69
|
def self.trace(request)
|
70
70
|
request(request) do |host|
|
71
|
-
host.trace request.send(:path_query_and_fragment), request
|
71
|
+
host.trace request.send(:path_query_and_fragment), headers_from(request)
|
72
72
|
end
|
73
73
|
end
|
74
74
|
|
@@ -106,4 +106,18 @@ private
|
|
106
106
|
request
|
107
107
|
end
|
108
108
|
|
109
|
+
def self.headers_from(request)
|
110
|
+
return request.headers unless HEADERS_MUST_BE_AN_HASH
|
111
|
+
return {} if request.headers.empty?
|
112
|
+
request.headers.flatten.each_slice(2).reduce({}) do |hash, pair|
|
113
|
+
hash[pair.first] = pair.last
|
114
|
+
hash
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
# starting from 2.0.0 net/http requires headers to be hashes
|
119
|
+
require 'rubygems' # Not necessary under Ruby v2
|
120
|
+
HEADERS_MUST_BE_AN_HASH =
|
121
|
+
Gem::Version.new(RUBY_VERSION) >= Gem::Version.new('2.0.0')
|
122
|
+
|
109
123
|
end
|
data/lib/htty/response.rb
CHANGED
@@ -23,11 +23,30 @@ class HTTY::Response < HTTY::Payload
|
|
23
23
|
def initialize(attributes={})
|
24
24
|
super attributes
|
25
25
|
@status = attributes[:status]
|
26
|
+
@already_followed = false
|
26
27
|
end
|
27
28
|
|
28
29
|
# Returns an array of the cookies belonging to the response.
|
29
30
|
def cookies
|
30
|
-
|
31
|
+
cookies_from(COOKIES_HEADER_NAME)
|
31
32
|
end
|
32
33
|
|
34
|
+
def follow_relative_to(request)
|
35
|
+
return request if @already_followed
|
36
|
+
location_uri = URI.parse(location_header = location)
|
37
|
+
if location_uri.absolute?
|
38
|
+
request.address location_header
|
39
|
+
else
|
40
|
+
request.
|
41
|
+
path_set(location_uri.path).
|
42
|
+
query_set_all(location_uri.query).
|
43
|
+
fragment_set(location_uri.fragment)
|
44
|
+
end
|
45
|
+
ensure
|
46
|
+
@already_followed = true
|
47
|
+
end
|
48
|
+
|
49
|
+
def location
|
50
|
+
header(LOCATION_HEADER_NAME, HTTY::NoLocationHeaderError.new)
|
51
|
+
end
|
33
52
|
end
|
data/lib/htty/uri.rb
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'uri'
|
2
|
+
|
3
|
+
module HTTY; end
|
4
|
+
|
5
|
+
class HTTY::URI
|
6
|
+
# There's a lot of confusion about this, the default implementation
|
7
|
+
# of URI.escape is marked as "obsolete", CGI.escape does another work,
|
8
|
+
# a safe solution seems to use https://github.com/sporkmonger/addressable
|
9
|
+
# without adding a new dependecy I found that encode all not unreserved
|
10
|
+
# characters (unfortunately that doesn't mean all reserved characters) it's
|
11
|
+
# a pretty safe solution, see http://tools.ietf.org/html/rfc3986#section-2.3
|
12
|
+
# URI.escape(a, /[^-_.~a-zA-Z0-9]/)
|
13
|
+
def self.escape_component(component)
|
14
|
+
URI.escape(component, /[^-_.~a-zA-Z0-9]/) unless component.nil?
|
15
|
+
end
|
16
|
+
end
|
data/lib/htty/version.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
require '
|
1
|
+
require 'spec_helper'
|
2
2
|
require File.expand_path("#{File.dirname __FILE__}/../../../../../lib/htty/session")
|
3
3
|
require File.expand_path("#{File.dirname __FILE__}/../../../../../lib/htty/cli/commands/query_add")
|
4
4
|
|
@@ -15,6 +15,12 @@ describe HTTY::CLI::Commands::QueryAdd do
|
|
15
15
|
klass.new :session => session, :arguments => arguments
|
16
16
|
end
|
17
17
|
|
18
|
+
describe 'without an argument' do
|
19
|
+
it 'should raise an error' do
|
20
|
+
expect{instance.perform}.to raise_error(ArgumentError)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
18
24
|
describe 'with key argument only' do
|
19
25
|
describe 'without key already present' do
|
20
26
|
it 'should add key' do
|
@@ -1,4 +1,4 @@
|
|
1
|
-
require '
|
1
|
+
require 'spec_helper'
|
2
2
|
require File.expand_path("#{File.dirname __FILE__}/../../../../../lib/htty/session")
|
3
3
|
require File.expand_path("#{File.dirname __FILE__}/../../../../../lib/htty/cli/commands/query_remove")
|
4
4
|
|
@@ -15,6 +15,24 @@ describe HTTY::CLI::Commands::QueryRemove do
|
|
15
15
|
klass.new :session => session, :arguments => arguments
|
16
16
|
end
|
17
17
|
|
18
|
+
describe 'with existing query string with only one key and value' do
|
19
|
+
before :each do
|
20
|
+
session.requests.last.uri.query = 'test=true'
|
21
|
+
end
|
22
|
+
|
23
|
+
describe 'with only key in query string' do
|
24
|
+
it 'should empty the query string' do
|
25
|
+
instance('test').perform
|
26
|
+
session.requests.last.uri.query.should be_nil
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'should not leave a trailing question mark' do
|
30
|
+
instance('test').perform
|
31
|
+
session.requests.last.uri.to_s.should_not end_with('?')
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
18
36
|
describe 'with existing query string with duplicate keys set' do
|
19
37
|
before :each do
|
20
38
|
session.requests.last.uri.query = 'test=true&test=false'
|