protocol-http 0.35.0 → 0.37.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.
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