async-http 0.59.3 → 0.59.4

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ccef95a0cce84077c1782720ea14a582822ef0431d60fa98303b88437d072636
4
- data.tar.gz: 397a5e8ed0cb1d4ed5ca58190e1c7ab344cabfff040d90df57fe1c49c1ca5360
3
+ metadata.gz: bdec9955ffb3564757b70e1745e2cea19a63961da0431e38eca773c22b2c6008
4
+ data.tar.gz: 2d005a43f0e8b43f25834566cbed86fbccc7cfebd6e27a64fdc69c65d0fec700
5
5
  SHA512:
6
- metadata.gz: 8e0194004b779c0107157cae272fbd9f3c75a050736b2c682d82507a26a88c7dd15e74dc1f3ca1e513ba8f2c1d0697103acf5a5edf172e617c5833cb11094dde
7
- data.tar.gz: 3c19cffb3030cf3b6b88091ef6818cf0339f01f5f52e6e35c704d9228d2b961af47f51d74995a7f83c19f1aa8405979d93cd612f8cd67d70492c71b02207c945
6
+ metadata.gz: 23a2d571edf0bb0fb73277057c84f7469648dba7f0afccf24ac2e3c15f0d1d11658e831fe3ef8a11b4dd4f28469be0c94a330bbd009aeb6a3e661f5323a2cb09
7
+ data.tar.gz: da57464924efd79a5dba6b7c5366ac883d012a1aed10492a11911137cd55b809e24a757ec4481e83a45092f2bd7286aca6852376075e5b07564fdca2ae56ed99
checksums.yaml.gz.sig CHANGED
Binary file
@@ -23,6 +23,7 @@ require_relative 'endpoint'
23
23
  require_relative 'reference'
24
24
 
25
25
  require 'protocol/http/middleware'
26
+ require 'protocol/http/body/rewindable'
26
27
 
27
28
  module Async
28
29
  module HTTP
@@ -30,8 +31,28 @@ module Async
30
31
  end
31
32
 
32
33
  # A client wrapper which transparently handles both relative and absolute redirects to a given maximum number of hops.
34
+ #
35
+ # The best reference for these semantics is defined by the [Fetch specification](https://fetch.spec.whatwg.org/#http-redirect-fetch).
36
+ #
37
+ # | Redirect using GET | Permanent | Temporary |
38
+ # |:-----------------------------------------:|:---------:|:---------:|
39
+ # | Allowed | 301 | 302 |
40
+ # | Preserve original method | 308 | 307 |
41
+ #
42
+ # For the specific details of the redirect handling, see:
43
+ # - <https://datatracker.ietf.org/doc/html/rfc7231#section-6-4-2> 301 Moved Permanently.
44
+ # - <https://datatracker.ietf.org/doc/html/rfc7231#section-6-4-3> 302 Found.
45
+ # - <https://datatracker.ietf.org/doc/html/rfc7538 308 Permanent Redirect.
46
+ # - <https://datatracker.ietf.org/doc/html/rfc7231#section-6-4-7> 307 Temporary Redirect.
47
+ #
33
48
  class RelativeLocation < ::Protocol::HTTP::Middleware
34
- DEFAULT_METHOD = GET
49
+ # Header keys which should be deleted when changing a request from a POST to a GET as defined by <https://fetch.spec.whatwg.org/#request-body-header-name>.
50
+ PROHIBITED_GET_HEADERS = [
51
+ 'content-encoding',
52
+ 'content-language',
53
+ 'content-location',
54
+ 'content-type',
55
+ ]
35
56
 
36
57
  # maximum_hops is the max number of redirects. Set to 0 to allow 1 request with no redirects.
37
58
  def initialize(app, maximum_hops = 3)
@@ -43,20 +64,39 @@ module Async
43
64
  # The maximum number of hops which will limit the number of redirects until an error is thrown.
44
65
  attr :maximum_hops
45
66
 
67
+ def redirect_with_get?(request, response)
68
+ # We only want to switch to GET if the request method is something other than get, e.g. POST.
69
+ if request.method != GET
70
+ # According to the RFC, we should only switch to GET if the response is a 301 or 302:
71
+ return response.status == 301 || response.status == 302
72
+ end
73
+ end
74
+
46
75
  def call(request)
47
- hops = 0
76
+ # We don't want to follow redirects for HEAD requests:
77
+ return super if request.head?
78
+
79
+ if body = request.body
80
+ # We need to cache the body as it might be submitted multiple times if we get a response status of 307 or 308:
81
+ body = ::Protocol::HTTP::Body::Rewindable.new(body)
82
+ request.body = body
83
+ end
48
84
 
49
- # We need to cache the body as it might be submitted multiple times.
50
- request.finish
85
+ hops = 0
51
86
 
52
87
  while hops <= @maximum_hops
53
88
  response = super(request)
54
89
 
55
90
  if response.redirection?
56
91
  hops += 1
92
+
93
+ # Get the redirect location:
94
+ unless location = response.headers['location']
95
+ return response
96
+ end
97
+
57
98
  response.finish
58
99
 
59
- location = response.headers['location']
60
100
  uri = URI.parse(location)
61
101
 
62
102
  if uri.absolute?
@@ -65,8 +105,21 @@ module Async
65
105
  request.path = Reference[request.path] + location
66
106
  end
67
107
 
68
- unless response.preserve_method?
69
- request.method = DEFAULT_METHOD
108
+ if request.method == GET or response.preserve_method?
109
+ # We (might) need to rewind the body so that it can be submitted again:
110
+ body&.rewind
111
+ else
112
+ # We are changing the method to GET:
113
+ request.method = GET
114
+
115
+ # Clear the request body:
116
+ request.finish
117
+ body = nil
118
+
119
+ # Remove any headers which are not allowed in a GET request:
120
+ PROHIBITED_GET_HEADERS.each do |header|
121
+ request.headers.delete(header)
122
+ end
70
123
  end
71
124
  else
72
125
  return response
@@ -22,6 +22,6 @@
22
22
 
23
23
  module Async
24
24
  module HTTP
25
- VERSION = "0.59.3"
25
+ VERSION = "0.59.4"
26
26
  end
27
27
  end
data.tar.gz.sig CHANGED
Binary file
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: async-http
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.59.3
4
+ version: 0.59.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Samuel Williams
@@ -52,7 +52,7 @@ cert_chain:
52
52
  Q2K9NVun/S785AP05vKkXZEFYxqG6EW012U4oLcFl5MySFajYXRYbuUpH6AY+HP8
53
53
  voD0MPg1DssDLKwXyt1eKD/+Fq0bFWhwVM/1XiAXL7lyYUyOq24KHgQ2Csg=
54
54
  -----END CERTIFICATE-----
55
- date: 2022-11-10 00:00:00.000000000 Z
55
+ date: 2022-12-13 00:00:00.000000000 Z
56
56
  dependencies:
57
57
  - !ruby/object:Gem::Dependency
58
58
  name: async
metadata.gz.sig CHANGED
Binary file