protocol-http 0.35.0 → 0.37.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (40) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/lib/protocol/http/accept_encoding.rb +7 -7
  4. data/lib/protocol/http/body/buffered.rb +8 -1
  5. data/lib/protocol/http/body/completable.rb +1 -1
  6. data/lib/protocol/http/body/deflate.rb +8 -5
  7. data/lib/protocol/http/body/digestable.rb +2 -2
  8. data/lib/protocol/http/body/file.rb +1 -1
  9. data/lib/protocol/http/body/head.rb +1 -1
  10. data/lib/protocol/http/body/inflate.rb +32 -22
  11. data/lib/protocol/http/body/readable.rb +10 -0
  12. data/lib/protocol/http/body/reader.rb +8 -0
  13. data/lib/protocol/http/body/rewindable.rb +2 -2
  14. data/lib/protocol/http/body/stream.rb +2 -2
  15. data/lib/protocol/http/body/streamable.rb +3 -3
  16. data/lib/protocol/http/body/wrapper.rb +5 -1
  17. data/lib/protocol/http/body/writable.rb +5 -5
  18. data/lib/protocol/http/content_encoding.rb +9 -9
  19. data/lib/protocol/http/cookie.rb +6 -6
  20. data/lib/protocol/http/header/authorization.rb +1 -1
  21. data/lib/protocol/http/header/cache_control.rb +13 -13
  22. data/lib/protocol/http/header/connection.rb +4 -4
  23. data/lib/protocol/http/header/cookie.rb +2 -2
  24. data/lib/protocol/http/header/date.rb +1 -1
  25. data/lib/protocol/http/header/etag.rb +1 -1
  26. data/lib/protocol/http/header/etags.rb +3 -3
  27. data/lib/protocol/http/header/vary.rb +1 -1
  28. data/lib/protocol/http/headers.rb +39 -39
  29. data/lib/protocol/http/methods.rb +9 -9
  30. data/lib/protocol/http/middleware/builder.rb +1 -1
  31. data/lib/protocol/http/middleware.rb +5 -5
  32. data/lib/protocol/http/reference.rb +20 -20
  33. data/lib/protocol/http/request.rb +4 -4
  34. data/lib/protocol/http/response.rb +3 -3
  35. data/lib/protocol/http/url.rb +5 -5
  36. data/lib/protocol/http/version.rb +1 -1
  37. data/lib/protocol/http.rb +4 -4
  38. data.tar.gz.sig +0 -0
  39. metadata +2 -2
  40. metadata.gz.sig +0 -0
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b60538bc2a8f661748e6a70b92bf46932440e56f69e0cb22348fa14b0c59706f
4
- data.tar.gz: 9a6629a169c0afff229eed8b660fc94c918cc9f0a953e5251b5f5f283e4e28fa
3
+ metadata.gz: 077e5dedb752c1fcbaf9cd4385815019bb17b9bf6d1e47943b39f90dc5d09025
4
+ data.tar.gz: 543a8f7b47ea5216d5753e97f90d02a787b21e38613ba431119f648cf7571694
5
5
  SHA512:
6
- metadata.gz: 707f195fa9b7b2bfe446b6a2132dfe608570ec8fed696c8df558686e80da07c5026fac90941109dc7d743e3806daf8fdfb4d28ce051ba1412242b8fde4f45a99
7
- data.tar.gz: 41a940d1dee93bc30d90fc0ae63fa34103d82379862c502a2ec11ec6f06521491e8eb6586ef43707957ff8ebc7f7016e893ad3b88751e93fdcf14976de8227d2
6
+ metadata.gz: bd1b08154595e4d417e3121bd7e7d0da704de64c54228da39a82c875dc19c1c06924cc8eb43ed710086bf9a2c2c404e79fe7191c360f23fa671c85ac4d995b64
7
+ data.tar.gz: 38700f2f25e04f633afdae9146ce3e135631618dd9dee9acf79953bdfad5487f7f7915cadc3c0d65f77aba646a6b68c80f33457f71c34009ffed257b49e4dd3a
checksums.yaml.gz.sig CHANGED
Binary file
@@ -3,20 +3,20 @@
3
3
  # Released under the MIT License.
4
4
  # Copyright, 2019-2023, by Samuel Williams.
5
5
 
6
- require_relative 'middleware'
6
+ require_relative "middleware"
7
7
 
8
- require_relative 'body/buffered'
9
- require_relative 'body/inflate'
8
+ require_relative "body/buffered"
9
+ require_relative "body/inflate"
10
10
 
11
11
  module Protocol
12
12
  module HTTP
13
13
  # Set a valid accept-encoding header and decode the response.
14
14
  class AcceptEncoding < Middleware
15
- ACCEPT_ENCODING = 'accept-encoding'.freeze
16
- CONTENT_ENCODING = 'content-encoding'.freeze
15
+ ACCEPT_ENCODING = "accept-encoding".freeze
16
+ CONTENT_ENCODING = "content-encoding".freeze
17
17
 
18
18
  DEFAULT_WRAPPERS = {
19
- 'gzip' => Body::Inflate.method(:for),
19
+ "gzip" => Body::Inflate.method(:for),
20
20
 
21
21
  # There is no point including this:
22
22
  # 'identity' => ->(body){body},
@@ -25,7 +25,7 @@ module Protocol
25
25
  def initialize(app, wrappers = DEFAULT_WRAPPERS)
26
26
  super(app)
27
27
 
28
- @accept_encoding = wrappers.keys.join(', ')
28
+ @accept_encoding = wrappers.keys.join(", ")
29
29
  @wrappers = wrappers
30
30
  end
31
31
 
@@ -4,7 +4,7 @@
4
4
  # Copyright, 2019-2024, by Samuel Williams.
5
5
  # Copyright, 2020, by Bryan Powell.
6
6
 
7
- require_relative 'readable'
7
+ require_relative "readable"
8
8
 
9
9
  module Protocol
10
10
  module HTTP
@@ -59,6 +59,8 @@ module Protocol
59
59
  # Ensure that future reads return nil, but allow for rewinding.
60
60
  def close(error = nil)
61
61
  @index = @chunks.length
62
+
63
+ return nil
62
64
  end
63
65
 
64
66
  def clear
@@ -90,6 +92,11 @@ module Protocol
90
92
  end
91
93
  end
92
94
 
95
+ def discard
96
+ # It's safe to call close here because there is no underlying stream to close:
97
+ self.close
98
+ end
99
+
93
100
  def write(chunk)
94
101
  @chunks << chunk
95
102
  end
@@ -3,7 +3,7 @@
3
3
  # Released under the MIT License.
4
4
  # Copyright, 2019-2024, by Samuel Williams.
5
5
 
6
- require_relative 'wrapper'
6
+ require_relative "wrapper"
7
7
 
8
8
  module Protocol
9
9
  module HTTP
@@ -3,9 +3,9 @@
3
3
  # Released under the MIT License.
4
4
  # Copyright, 2019-2024, by Samuel Williams.
5
5
 
6
- require_relative 'wrapper'
6
+ require_relative "wrapper"
7
7
 
8
- require 'zlib'
8
+ require "zlib"
9
9
 
10
10
  module Protocol
11
11
  module HTTP
@@ -17,8 +17,8 @@ module Protocol
17
17
  GZIP = Zlib::MAX_WBITS | 16
18
18
 
19
19
  ENCODINGS = {
20
- 'deflate' => DEFLATE,
21
- 'gzip' => GZIP,
20
+ "deflate" => DEFLATE,
21
+ "gzip" => GZIP,
22
22
  }
23
23
 
24
24
  def initialize(body, stream)
@@ -31,7 +31,10 @@ module Protocol
31
31
  end
32
32
 
33
33
  def close(error = nil)
34
- @stream.close unless @stream.closed?
34
+ if stream = @stream
35
+ @stream = nil
36
+ stream.close unless stream.closed?
37
+ end
35
38
 
36
39
  super
37
40
  end
@@ -3,9 +3,9 @@
3
3
  # Released under the MIT License.
4
4
  # Copyright, 2020-2024, by Samuel Williams.
5
5
 
6
- require_relative 'wrapper'
6
+ require_relative "wrapper"
7
7
 
8
- require 'digest/sha2'
8
+ require "digest/sha2"
9
9
 
10
10
  module Protocol
11
11
  module HTTP
@@ -3,7 +3,7 @@
3
3
  # Released under the MIT License.
4
4
  # Copyright, 2019-2024, by Samuel Williams.
5
5
 
6
- require_relative 'readable'
6
+ require_relative "readable"
7
7
 
8
8
  module Protocol
9
9
  module HTTP
@@ -3,7 +3,7 @@
3
3
  # Released under the MIT License.
4
4
  # Copyright, 2020-2023, by Samuel Williams.
5
5
 
6
- require_relative 'readable'
6
+ require_relative "readable"
7
7
 
8
8
  module Protocol
9
9
  module HTTP
@@ -3,9 +3,9 @@
3
3
  # Released under the MIT License.
4
4
  # Copyright, 2019-2024, by Samuel Williams.
5
5
 
6
- require 'zlib'
6
+ require "zlib"
7
7
 
8
- require_relative 'deflate'
8
+ require_relative "deflate"
9
9
 
10
10
  module Protocol
11
11
  module HTTP
@@ -16,30 +16,40 @@ module Protocol
16
16
  end
17
17
 
18
18
  def read
19
- return if @stream.finished?
19
+ if stream = @stream
20
+ # Read from the underlying stream and inflate it:
21
+ while chunk = super
22
+ @input_length += chunk.bytesize
23
+
24
+ # It's possible this triggers the stream to finish.
25
+ chunk = stream.inflate(chunk)
26
+
27
+ break unless chunk&.empty?
28
+ end
20
29
 
21
- # The stream might have been closed while waiting for the chunk to come in.
22
- while chunk = super
23
- @input_length += chunk.bytesize
30
+ if chunk
31
+ @output_length += chunk.bytesize
32
+ elsif !stream.closed?
33
+ chunk = stream.finish
34
+ @output_length += chunk.bytesize
35
+ end
24
36
 
25
- # It's possible this triggers the stream to finish.
26
- chunk = @stream.inflate(chunk)
37
+ # If the stream is finished, we need to close it and potentially return nil:
38
+ if stream.finished?
39
+ @stream = nil
40
+ stream.close
41
+
42
+ while super
43
+ # There is data left in the stream, so we need to keep reading until it's all consumed.
44
+ end
45
+
46
+ if chunk.empty?
47
+ return nil
48
+ end
49
+ end
27
50
 
28
- break unless chunk&.empty?
51
+ return chunk
29
52
  end
30
-
31
- if chunk
32
- @output_length += chunk.bytesize
33
- elsif !@stream.closed?
34
- chunk = @stream.finish
35
- @output_length += chunk.bytesize
36
- end
37
-
38
- if chunk.empty? and @stream.finished?
39
- return nil
40
- end
41
-
42
- return chunk
43
53
  end
44
54
  end
45
55
  end
@@ -133,6 +133,16 @@ module Protocol
133
133
  Buffered.read(self)
134
134
  end
135
135
 
136
+ # Discard the body as efficiently as possible.
137
+ #
138
+ # The default implementation simply reads all chunks until the body is empty.
139
+ #
140
+ # Useful for discarding the body when it is not needed, but preserving the underlying connection.
141
+ def discard
142
+ while chunk = self.read
143
+ end
144
+ end
145
+
136
146
  def as_json(...)
137
147
  {
138
148
  class: self.class.name,
@@ -40,6 +40,14 @@ module Protocol
40
40
  end
41
41
  end
42
42
 
43
+ # Discard the body as efficiently as possible.
44
+ def discard
45
+ if body = @body
46
+ @body = nil
47
+ body.discard
48
+ end
49
+ end
50
+
43
51
  # Buffer the entire request/response body.
44
52
  # @returns [Reader] itself.
45
53
  def buffered!
@@ -3,8 +3,8 @@
3
3
  # Released under the MIT License.
4
4
  # Copyright, 2019-2024, by Samuel Williams.
5
5
 
6
- require_relative 'wrapper'
7
- require_relative 'buffered'
6
+ require_relative "wrapper"
7
+ require_relative "buffered"
8
8
 
9
9
  module Protocol
10
10
  module HTTP
@@ -4,7 +4,7 @@
4
4
  # Copyright, 2019-2024, by Samuel Williams.
5
5
  # Copyright, 2023, by Genki Takiuchi.
6
6
 
7
- require_relative 'buffered'
7
+ require_relative "buffered"
8
8
 
9
9
  module Protocol
10
10
  module HTTP
@@ -43,7 +43,7 @@ module Protocol
43
43
  # @param buffer [String] the buffer which will receive the data
44
44
  # @return a buffer containing the data
45
45
  def read(length = nil, buffer = nil)
46
- return '' if length == 0
46
+ return "" if length == 0
47
47
 
48
48
  buffer ||= String.new.force_encoding(Encoding::BINARY)
49
49
 
@@ -3,10 +3,10 @@
3
3
  # Released under the MIT License.
4
4
  # Copyright, 2019-2024, by Samuel Williams.
5
5
 
6
- require_relative 'readable'
7
- require_relative 'writable'
6
+ require_relative "readable"
7
+ require_relative "writable"
8
8
 
9
- require_relative 'stream'
9
+ require_relative "stream"
10
10
 
11
11
  module Protocol
12
12
  module HTTP
@@ -3,7 +3,7 @@
3
3
  # Released under the MIT License.
4
4
  # Copyright, 2019-2024, by Samuel Williams.
5
5
 
6
- require_relative 'readable'
6
+ require_relative "readable"
7
7
 
8
8
  module Protocol
9
9
  module HTTP
@@ -59,6 +59,10 @@ module Protocol
59
59
  @body.read
60
60
  end
61
61
 
62
+ def discard
63
+ @body.discard
64
+ end
65
+
62
66
  def as_json(...)
63
67
  {
64
68
  class: self.class.name,
@@ -3,7 +3,7 @@
3
3
  # Released under the MIT License.
4
4
  # Copyright, 2024, by Samuel Williams.
5
5
 
6
- require_relative 'readable'
6
+ require_relative "readable"
7
7
 
8
8
  module Protocol
9
9
  module HTTP
@@ -137,15 +137,15 @@ module Protocol
137
137
  def status
138
138
  if @queue.empty?
139
139
  if @queue.closed?
140
- 'closed'
140
+ "closed"
141
141
  else
142
- 'waiting'
142
+ "waiting"
143
143
  end
144
144
  else
145
145
  if @queue.closed?
146
- 'closing'
146
+ "closing"
147
147
  else
148
- 'ready'
148
+ "ready"
149
149
  end
150
150
  end
151
151
  end
@@ -3,17 +3,17 @@
3
3
  # Released under the MIT License.
4
4
  # Copyright, 2019-2023, by Samuel Williams.
5
5
 
6
- require_relative 'middleware'
6
+ require_relative "middleware"
7
7
 
8
- require_relative 'body/buffered'
9
- require_relative 'body/deflate'
8
+ require_relative "body/buffered"
9
+ require_relative "body/deflate"
10
10
 
11
11
  module Protocol
12
12
  module HTTP
13
13
  # Encode a response according the the request's acceptable encodings.
14
14
  class ContentEncoding < Middleware
15
15
  DEFAULT_WRAPPERS = {
16
- 'gzip' => Body::Deflate.method(:for)
16
+ "gzip" => Body::Deflate.method(:for)
17
17
  }
18
18
 
19
19
  DEFAULT_CONTENT_TYPES = %r{^(text/.*?)|(.*?/json)|(.*?/javascript)$}
@@ -29,24 +29,24 @@ module Protocol
29
29
  response = super
30
30
 
31
31
  # Early exit if the response has already specified a content-encoding.
32
- return response if response.headers['content-encoding']
32
+ return response if response.headers["content-encoding"]
33
33
 
34
34
  # This is a very tricky issue, so we avoid it entirely.
35
35
  # https://lists.w3.org/Archives/Public/ietf-http-wg/2014JanMar/1179.html
36
36
  return response if response.partial?
37
37
 
38
38
  # Ensure that caches are aware we are varying the response based on the accept-encoding request header:
39
- response.headers.add('vary', 'accept-encoding')
39
+ response.headers.add("vary", "accept-encoding")
40
40
 
41
41
  # TODO use http-accept and sort by priority
42
- if !response.body.empty? and accept_encoding = request.headers['accept-encoding']
42
+ if !response.body.empty? and accept_encoding = request.headers["accept-encoding"]
43
43
 
44
- if content_type = response.headers['content-type'] and @content_types =~ content_type
44
+ if content_type = response.headers["content-type"] and @content_types =~ content_type
45
45
  body = response.body
46
46
 
47
47
  accept_encoding.each do |name|
48
48
  if wrapper = @wrappers[name]
49
- response.headers['content-encoding'] = name
49
+ response.headers["content-encoding"] = name
50
50
 
51
51
  body = wrapper.call(body)
52
52
 
@@ -4,7 +4,7 @@
4
4
  # Copyright, 2019-2023, by Samuel Williams.
5
5
  # Copyright, 2022, by Herrick Fang.
6
6
 
7
- require_relative 'url'
7
+ require_relative "url"
8
8
 
9
9
  module Protocol
10
10
  module HTTP
@@ -31,15 +31,15 @@ module Protocol
31
31
  def to_s
32
32
  buffer = String.new.b
33
33
 
34
- buffer << encoded_name << '=' << encoded_value
34
+ buffer << encoded_name << "=" << encoded_value
35
35
 
36
36
  if @directives
37
37
  @directives.collect do |key, value|
38
- buffer << ';'
38
+ buffer << ";"
39
39
 
40
40
  case value
41
41
  when String
42
- buffer << key << '=' << value
42
+ buffer << key << "=" << value
43
43
  when TrueClass
44
44
  buffer << key
45
45
  end
@@ -52,7 +52,7 @@ module Protocol
52
52
  def self.parse(string)
53
53
  head, *directives = string.split(/\s*;\s*/)
54
54
 
55
- key, value = head.split('=', 2)
55
+ key, value = head.split("=", 2)
56
56
  directives = self.parse_directives(directives)
57
57
 
58
58
  self.new(
@@ -64,7 +64,7 @@ module Protocol
64
64
 
65
65
  def self.parse_directives(strings)
66
66
  strings.collect do |string|
67
- key, value = string.split('=', 2)
67
+ key, value = string.split("=", 2)
68
68
  [key, value || true]
69
69
  end.to_h
70
70
  end
@@ -20,7 +20,7 @@ module Protocol
20
20
  end
21
21
 
22
22
  def self.basic(username, password)
23
- strict_base64_encoded = ["#{username}:#{password}"].pack('m0')
23
+ strict_base64_encoded = ["#{username}:#{password}"].pack("m0")
24
24
 
25
25
  self.new(
26
26
  "Basic #{strict_base64_encoded}"
@@ -4,25 +4,25 @@
4
4
  # Copyright, 2020-2023, by Samuel Williams.
5
5
  # Copyright, 2023, by Thomas Morgan.
6
6
 
7
- require_relative 'split'
7
+ require_relative "split"
8
8
 
9
9
  module Protocol
10
10
  module HTTP
11
11
  module Header
12
12
  class CacheControl < Split
13
- PRIVATE = 'private'
14
- PUBLIC = 'public'
15
- NO_CACHE = 'no-cache'
16
- NO_STORE = 'no-store'
17
- MAX_AGE = 'max-age'
18
- S_MAXAGE = 's-maxage'
13
+ PRIVATE = "private"
14
+ PUBLIC = "public"
15
+ NO_CACHE = "no-cache"
16
+ NO_STORE = "no-store"
17
+ MAX_AGE = "max-age"
18
+ S_MAXAGE = "s-maxage"
19
19
 
20
- STATIC = 'static'
21
- DYNAMIC = 'dynamic'
22
- STREAMING = 'streaming'
20
+ STATIC = "static"
21
+ DYNAMIC = "dynamic"
22
+ STREAMING = "streaming"
23
23
 
24
- MUST_REVALIDATE = 'must-revalidate'
25
- PROXY_REVALIDATE = 'proxy-revalidate'
24
+ MUST_REVALIDATE = "must-revalidate"
25
+ PROXY_REVALIDATE = "proxy-revalidate"
26
26
 
27
27
  def initialize(value = nil)
28
28
  super(value&.downcase)
@@ -89,7 +89,7 @@ module Protocol
89
89
 
90
90
  def find_integer_value(value_name)
91
91
  if value = self.find{|value| value.start_with?(value_name)}
92
- _, age = value.split('=', 2)
92
+ _, age = value.split("=", 2)
93
93
 
94
94
  if age =~ /\A[0-9]+\z/
95
95
  return Integer(age)
@@ -4,15 +4,15 @@
4
4
  # Copyright, 2019-2024, by Samuel Williams.
5
5
  # Copyright, 2024, by Thomas Morgan.
6
6
 
7
- require_relative 'split'
7
+ require_relative "split"
8
8
 
9
9
  module Protocol
10
10
  module HTTP
11
11
  module Header
12
12
  class Connection < Split
13
- KEEP_ALIVE = 'keep-alive'
14
- CLOSE = 'close'
15
- UPGRADE = 'upgrade'
13
+ KEEP_ALIVE = "keep-alive"
14
+ CLOSE = "close"
15
+ UPGRADE = "upgrade"
16
16
 
17
17
  def initialize(value = nil)
18
18
  super(value&.downcase)
@@ -3,8 +3,8 @@
3
3
  # Released under the MIT License.
4
4
  # Copyright, 2019-2023, by Samuel Williams.
5
5
 
6
- require_relative 'multiple'
7
- require_relative '../cookie'
6
+ require_relative "multiple"
7
+ require_relative "../cookie"
8
8
 
9
9
  module Protocol
10
10
  module HTTP
@@ -3,7 +3,7 @@
3
3
  # Released under the MIT License.
4
4
  # Copyright, 2023-2024, by Samuel Williams.
5
5
 
6
- require 'time'
6
+ require "time"
7
7
 
8
8
  module Protocol
9
9
  module HTTP
@@ -12,7 +12,7 @@ module Protocol
12
12
  end
13
13
 
14
14
  def weak?
15
- self.start_with?('W/')
15
+ self.start_with?("W/")
16
16
  end
17
17
  end
18
18
  end
@@ -4,14 +4,14 @@
4
4
  # Copyright, 2020-2023, by Samuel Williams.
5
5
  # Copyright, 2023, by Thomas Morgan.
6
6
 
7
- require_relative 'split'
7
+ require_relative "split"
8
8
 
9
9
  module Protocol
10
10
  module HTTP
11
11
  module Header
12
12
  class ETags < Split
13
13
  def wildcard?
14
- self.include?('*')
14
+ self.include?("*")
15
15
  end
16
16
 
17
17
  # This implementation is not strictly correct according to the RFC-specified format.
@@ -36,7 +36,7 @@ module Protocol
36
36
  end
37
37
 
38
38
  def weak_tag?(tag)
39
- tag&.start_with? 'W/'
39
+ tag&.start_with? "W/"
40
40
  end
41
41
  end
42
42
  end
@@ -3,7 +3,7 @@
3
3
  # Released under the MIT License.
4
4
  # Copyright, 2020-2023, by Samuel Williams.
5
5
 
6
- require_relative 'split'
6
+ require_relative "split"
7
7
 
8
8
  module Protocol
9
9
  module HTTP
@@ -3,16 +3,16 @@
3
3
  # Released under the MIT License.
4
4
  # Copyright, 2018-2024, by Samuel Williams.
5
5
 
6
- require_relative 'header/split'
7
- require_relative 'header/multiple'
8
- require_relative 'header/cookie'
9
- require_relative 'header/connection'
10
- require_relative 'header/cache_control'
11
- require_relative 'header/etag'
12
- require_relative 'header/etags'
13
- require_relative 'header/vary'
14
- require_relative 'header/authorization'
15
- require_relative 'header/date'
6
+ require_relative "header/split"
7
+ require_relative "header/multiple"
8
+ require_relative "header/cookie"
9
+ require_relative "header/connection"
10
+ require_relative "header/cache_control"
11
+ require_relative "header/etag"
12
+ require_relative "header/etags"
13
+ require_relative "header/vary"
14
+ require_relative "header/authorization"
15
+ require_relative "header/date"
16
16
 
17
17
  module Protocol
18
18
  module HTTP
@@ -21,7 +21,7 @@ module Protocol
21
21
  Split = Header::Split
22
22
  Multiple = Header::Multiple
23
23
 
24
- TRAILER = 'trailer'
24
+ TRAILER = "trailer"
25
25
 
26
26
  # Construct an instance from a headers Array or Hash. No-op if already an instance of `Headers`. If the underlying array is frozen, it will be duped.
27
27
  # @return [Headers] an instance of headers.
@@ -203,49 +203,49 @@ module Protocol
203
203
 
204
204
  POLICY = {
205
205
  # Headers which may only be specified once.
206
- 'content-type' => false,
207
- 'content-disposition' => false,
208
- 'content-length' => false,
209
- 'user-agent' => false,
210
- 'referer' => false,
211
- 'host' => false,
212
- 'from' => false,
213
- 'location' => false,
214
- 'max-forwards' => false,
206
+ "content-type" => false,
207
+ "content-disposition" => false,
208
+ "content-length" => false,
209
+ "user-agent" => false,
210
+ "referer" => false,
211
+ "host" => false,
212
+ "from" => false,
213
+ "location" => false,
214
+ "max-forwards" => false,
215
215
 
216
216
  # Custom headers:
217
- 'connection' => Header::Connection,
218
- 'cache-control' => Header::CacheControl,
219
- 'vary' => Header::Vary,
217
+ "connection" => Header::Connection,
218
+ "cache-control" => Header::CacheControl,
219
+ "vary" => Header::Vary,
220
220
 
221
221
  # Headers specifically for proxies:
222
- 'via' => Split,
223
- 'x-forwarded-for' => Split,
222
+ "via" => Split,
223
+ "x-forwarded-for" => Split,
224
224
 
225
225
  # Authorization headers:
226
- 'authorization' => Header::Authorization,
227
- 'proxy-authorization' => Header::Authorization,
226
+ "authorization" => Header::Authorization,
227
+ "proxy-authorization" => Header::Authorization,
228
228
 
229
229
  # Cache validations:
230
- 'etag' => Header::ETag,
231
- 'if-match' => Header::ETags,
232
- 'if-none-match' => Header::ETags,
230
+ "etag" => Header::ETag,
231
+ "if-match" => Header::ETags,
232
+ "if-none-match" => Header::ETags,
233
233
 
234
234
  # Headers which may be specified multiple times, but which can't be concatenated:
235
- 'www-authenticate' => Multiple,
236
- 'proxy-authenticate' => Multiple,
235
+ "www-authenticate" => Multiple,
236
+ "proxy-authenticate" => Multiple,
237
237
 
238
238
  # Custom headers:
239
- 'set-cookie' => Header::SetCookie,
240
- 'cookie' => Header::Cookie,
239
+ "set-cookie" => Header::SetCookie,
240
+ "cookie" => Header::Cookie,
241
241
 
242
242
  # Date headers:
243
243
  # These headers include a comma as part of the formatting so they can't be concatenated.
244
- 'date' => Header::Date,
245
- 'expires' => Header::Date,
246
- 'last-modified' => Header::Date,
247
- 'if-modified-since' => Header::Date,
248
- 'if-unmodified-since' => Header::Date,
244
+ "date" => Header::Date,
245
+ "expires" => Header::Date,
246
+ "last-modified" => Header::Date,
247
+ "if-modified-since" => Header::Date,
248
+ "if-unmodified-since" => Header::Date,
249
249
  }.tap{|hash| hash.default = Split}
250
250
 
251
251
  # Delete all headers with the given key, and return the merged value.
@@ -24,31 +24,31 @@ module Protocol
24
24
  # See <https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods> for more details.
25
25
  class Methods
26
26
  # The GET method requests a representation of the specified resource. Requests using GET should only retrieve data.
27
- GET = 'GET'
27
+ GET = "GET"
28
28
 
29
29
  # The HEAD method asks for a response identical to a GET request, but without the response body.
30
- HEAD = 'HEAD'
30
+ HEAD = "HEAD"
31
31
 
32
32
  # The POST method submits an entity to the specified resource, often causing a change in state or side effects on the server.
33
- POST = 'POST'
33
+ POST = "POST"
34
34
 
35
35
  # The PUT method replaces all current representations of the target resource with the request payload.
36
- PUT = 'PUT'
36
+ PUT = "PUT"
37
37
 
38
38
  # The DELETE method deletes the specified resource.
39
- DELETE = 'DELETE'
39
+ DELETE = "DELETE"
40
40
 
41
41
  # The CONNECT method establishes a tunnel to the server identified by the target resource.
42
- CONNECT = 'CONNECT'
42
+ CONNECT = "CONNECT"
43
43
 
44
44
  # The OPTIONS method describes the communication options for the target resource.
45
- OPTIONS = 'OPTIONS'
45
+ OPTIONS = "OPTIONS"
46
46
 
47
47
  # The TRACE method performs a message loop-back test along the path to the target resource.
48
- TRACE = 'TRACE'
48
+ TRACE = "TRACE"
49
49
 
50
50
  # The PATCH method applies partial modifications to a resource.
51
- PATCH = 'PATCH'
51
+ PATCH = "PATCH"
52
52
 
53
53
  def self.valid?(name)
54
54
  const_defined?(name)
@@ -3,7 +3,7 @@
3
3
  # Released under the MIT License.
4
4
  # Copyright, 2019-2024, by Samuel Williams.
5
5
 
6
- require_relative '../middleware'
6
+ require_relative "../middleware"
7
7
 
8
8
  module Protocol
9
9
  module HTTP
@@ -3,10 +3,10 @@
3
3
  # Released under the MIT License.
4
4
  # Copyright, 2019-2023, by Samuel Williams.
5
5
 
6
- require_relative 'methods'
7
- require_relative 'headers'
8
- require_relative 'request'
9
- require_relative 'response'
6
+ require_relative "methods"
7
+ require_relative "headers"
8
+ require_relative "request"
9
+ require_relative "response"
10
10
 
11
11
  module Protocol
12
12
  module HTTP
@@ -66,7 +66,7 @@ module Protocol
66
66
  end
67
67
 
68
68
  def self.call(request)
69
- Response[200, Headers['content-type' => 'text/plain'], ["Hello World!"]]
69
+ Response[200, Headers["content-type" => "text/plain"], ["Hello World!"]]
70
70
  end
71
71
  end
72
72
  end
@@ -3,7 +3,7 @@
3
3
  # Released under the MIT License.
4
4
  # Copyright, 2018-2023, by Samuel Williams.
5
5
 
6
- require_relative 'url'
6
+ require_relative "url"
7
7
 
8
8
  module Protocol
9
9
  module HTTP
@@ -12,14 +12,14 @@ module Protocol
12
12
  include Comparable
13
13
 
14
14
  # Generate a reference from a path and user parameters. The path may contain a `#fragment` or `?query=parameters`.
15
- def self.parse(path = '/', parameters = nil)
16
- base, fragment = path.split('#', 2)
17
- path, query = base.split('?', 2)
15
+ def self.parse(path = "/", parameters = nil)
16
+ base, fragment = path.split("#", 2)
17
+ path, query = base.split("?", 2)
18
18
 
19
19
  self.new(path, query, fragment, parameters)
20
20
  end
21
21
 
22
- def initialize(path = '/', query = nil, fragment = nil, parameters = nil)
22
+ def initialize(path = "/", query = nil, fragment = nil, parameters = nil)
23
23
  @path = path
24
24
  @query = query
25
25
  @fragment = fragment
@@ -79,15 +79,15 @@ module Protocol
79
79
 
80
80
  def append(buffer)
81
81
  if query?
82
- buffer << URL.escape_path(@path) << '?' << @query
83
- buffer << '&' << URL.encode(@parameters) if parameters?
82
+ buffer << URL.escape_path(@path) << "?" << @query
83
+ buffer << "&" << URL.encode(@parameters) if parameters?
84
84
  else
85
85
  buffer << URL.escape_path(@path)
86
- buffer << '?' << URL.encode(@parameters) if parameters?
86
+ buffer << "?" << URL.encode(@parameters) if parameters?
87
87
  end
88
88
 
89
89
  if fragment?
90
- buffer << '#' << URL.escape(@fragment)
90
+ buffer << "#" << URL.escape(@fragment)
91
91
  end
92
92
 
93
93
  return buffer
@@ -150,31 +150,31 @@ module Protocol
150
150
  if path.empty?
151
151
  [path]
152
152
  else
153
- path.split('/', -1)
153
+ path.split("/", -1)
154
154
  end
155
155
  end
156
156
 
157
157
  def expand_absolute_path(path, parts)
158
158
  parts.each do |part|
159
- if part == '..'
159
+ if part == ".."
160
160
  path.pop
161
- elsif part == '.'
161
+ elsif part == "."
162
162
  # Do nothing.
163
163
  else
164
164
  path << part
165
165
  end
166
166
  end
167
167
 
168
- if path.first != ''
169
- path.unshift('')
168
+ if path.first != ""
169
+ path.unshift("")
170
170
  end
171
171
  end
172
172
 
173
173
  def expand_relative_path(path, parts)
174
174
  parts.each do |part|
175
- if part == '..' and path.any?
175
+ if part == ".." and path.any?
176
176
  path.pop
177
- elsif part == '.'
177
+ elsif part == "."
178
178
  # Do nothing.
179
179
  else
180
180
  path << part
@@ -184,7 +184,7 @@ module Protocol
184
184
 
185
185
  # @param pop [Boolean] whether to remove the last path component of the base path, to conform to URI merging behaviour, as defined by RFC2396.
186
186
  def expand_path(base, relative, pop = true)
187
- if relative.start_with? '/'
187
+ if relative.start_with? "/"
188
188
  return relative
189
189
  end
190
190
 
@@ -194,18 +194,18 @@ module Protocol
194
194
  # 6) a) All but the last segment of the base URI's path component is
195
195
  # copied to the buffer. In other words, any characters after the
196
196
  # last (right-most) slash character, if any, are excluded.
197
- path.pop if pop or path.last == ''
197
+ path.pop if pop or path.last == ""
198
198
 
199
199
  parts = split(relative)
200
200
 
201
201
  # Absolute path:
202
- if path.first == ''
202
+ if path.first == ""
203
203
  expand_absolute_path(path, parts)
204
204
  else
205
205
  expand_relative_path(path, parts)
206
206
  end
207
207
 
208
- return path.join('/')
208
+ return path.join("/")
209
209
  end
210
210
  end
211
211
  end
@@ -3,11 +3,11 @@
3
3
  # Released under the MIT License.
4
4
  # Copyright, 2019-2024, by Samuel Williams.
5
5
 
6
- require_relative 'body/buffered'
7
- require_relative 'body/reader'
6
+ require_relative "body/buffered"
7
+ require_relative "body/reader"
8
8
 
9
- require_relative 'headers'
10
- require_relative 'methods'
9
+ require_relative "headers"
10
+ require_relative "methods"
11
11
 
12
12
  module Protocol
13
13
  module HTTP
@@ -3,8 +3,8 @@
3
3
  # Released under the MIT License.
4
4
  # Copyright, 2019-2024, by Samuel Williams.
5
5
 
6
- require_relative 'body/buffered'
7
- require_relative 'body/reader'
6
+ require_relative "body/buffered"
7
+ require_relative "body/reader"
8
8
 
9
9
  module Protocol
10
10
  module HTTP
@@ -141,7 +141,7 @@ module Protocol
141
141
  #
142
142
  # @parameter exception [Exception] The exception to generate the response for.
143
143
  def self.for_exception(exception)
144
- Response[500, Headers['content-type' => 'text/plain'], ["#{exception.class}: #{exception.message}"]]
144
+ Response[500, Headers["content-type" => "text/plain"], ["#{exception.class}: #{exception.message}"]]
145
145
  end
146
146
 
147
147
  def as_json(...)
@@ -10,7 +10,7 @@ module Protocol
10
10
  # Escapes a string using percent encoding.
11
11
  def self.escape(string, encoding = string.encoding)
12
12
  string.b.gsub(/([^a-zA-Z0-9_.\-]+)/) do |m|
13
- '%' + m.unpack('H2' * m.bytesize).join('%').upcase
13
+ "%" + m.unpack("H2" * m.bytesize).join("%").upcase
14
14
  end.force_encoding(encoding)
15
15
  end
16
16
 
@@ -28,7 +28,7 @@ module Protocol
28
28
  def self.escape_path(path)
29
29
  encoding = path.encoding
30
30
  path.b.gsub(NON_PCHAR) do |m|
31
- '%' + m.unpack('H2' * m.bytesize).join('%').upcase
31
+ "%" + m.unpack("H2" * m.bytesize).join("%").upcase
32
32
  end.force_encoding(encoding)
33
33
  end
34
34
 
@@ -42,7 +42,7 @@ module Protocol
42
42
  when Hash
43
43
  return value.map {|k, v|
44
44
  self.encode(v, prefix ? "#{prefix}[#{escape(k.to_s)}]" : escape(k.to_s))
45
- }.reject(&:empty?).join('&')
45
+ }.reject(&:empty?).join("&")
46
46
  when nil
47
47
  return prefix
48
48
  else
@@ -57,10 +57,10 @@ module Protocol
57
57
  # @parameter key [String] The unescaped key.
58
58
  # @parameter value [String] The unescaped key.
59
59
  def self.scan(string)
60
- string.split('&') do |assignment|
60
+ string.split("&") do |assignment|
61
61
  next if assignment.empty?
62
62
 
63
- key, value = assignment.split('=', 2)
63
+ key, value = assignment.split("=", 2)
64
64
 
65
65
  yield unescape(key), value.nil? ? value : unescape(value)
66
66
  end
@@ -5,6 +5,6 @@
5
5
 
6
6
  module Protocol
7
7
  module HTTP
8
- VERSION = "0.35.0"
8
+ VERSION = "0.37.0"
9
9
  end
10
10
  end
data/lib/protocol/http.rb CHANGED
@@ -5,10 +5,10 @@
5
5
 
6
6
  require_relative "http/version"
7
7
 
8
- require_relative 'http/headers'
9
- require_relative 'http/request'
10
- require_relative 'http/response'
11
- require_relative 'http/middleware'
8
+ require_relative "http/headers"
9
+ require_relative "http/request"
10
+ require_relative "http/response"
11
+ require_relative "http/middleware"
12
12
 
13
13
  # @namespace
14
14
  module Protocol
data.tar.gz.sig CHANGED
Binary file
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: protocol-http
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.35.0
4
+ version: 0.37.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Samuel Williams
@@ -47,7 +47,7 @@ cert_chain:
47
47
  Q2K9NVun/S785AP05vKkXZEFYxqG6EW012U4oLcFl5MySFajYXRYbuUpH6AY+HP8
48
48
  voD0MPg1DssDLKwXyt1eKD/+Fq0bFWhwVM/1XiAXL7lyYUyOq24KHgQ2Csg=
49
49
  -----END CERTIFICATE-----
50
- date: 2024-09-16 00:00:00.000000000 Z
50
+ date: 2024-09-18 00:00:00.000000000 Z
51
51
  dependencies: []
52
52
  description:
53
53
  email:
metadata.gz.sig CHANGED
Binary file