protocol-http 0.26.5 → 0.26.7

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: ec1274383518ed67d583ca4bd675984a61c34b2bc4b19600a064fd80e595548a
4
- data.tar.gz: cdf454fb4d8c1513dab3f9e1dd48a2b8bf466af01cbb97fcee256fd79d7ec91c
3
+ metadata.gz: 5821a26af6f718626313da18d47d4aba2e33f0f4ce3809551c91e1a57e10bfbd
4
+ data.tar.gz: a432928361e31ca78408e444dd05622dd6853e56f40b3581a19fe97d8dac8dcc
5
5
  SHA512:
6
- metadata.gz: af8dc10e55a1079c3862fe05316d8e1716a0ff4af45e705927e310f707c49fb2c10a13954af9ddee21cca9814037faddeed035691bbc35136bbe058facf354ac
7
- data.tar.gz: fdf5fcbb3d7a184aa77e55b3016820fcd34863b401301901232f188cc350c357e76590448ee67a74c032c931f064b9a833291c2b95c48a7da69f767e6887df69
6
+ metadata.gz: 025540a24e4e72ea76257cee2c3bd4039854d6bd5f0f446553ffb5843aa2a41f278860d3f047b3c0861d8b15b120cbd03e1f54c2714583aabe7556451e6df728
7
+ data.tar.gz: e5b69ddfe8c874b00f6e36d03f48b71bb985f2c529df5aed4b4417ba1f10c258c768456897fdad1b63a9f257f4271472a3e56f7649664935e56ebb4a1136faf1
checksums.yaml.gz.sig CHANGED
Binary file
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  # Released under the MIT License.
4
- # Copyright, 2019-2023, by Samuel Williams.
4
+ # Copyright, 2019-2024, by Samuel Williams.
5
5
  # Copyright, 2020, by Bryan Powell.
6
6
 
7
7
  require_relative 'readable'
@@ -12,7 +12,11 @@ module Protocol
12
12
  # A body which buffers all it's contents.
13
13
  class Buffered < Readable
14
14
  # Wraps an array into a buffered body.
15
- # @return [Readable, nil] the wrapped body or nil if nil was given.
15
+ #
16
+ # For compatibility, also accepts anything that behaves like an `Array(String)`.
17
+ #
18
+ # @parameter body [String | Array(String) | Readable | nil] the body to wrap.
19
+ # @returns [Readable | nil] the wrapped body or nil if nil was given.
16
20
  def self.wrap(body)
17
21
  if body.is_a?(Readable)
18
22
  return body
@@ -7,17 +7,11 @@
7
7
  module Protocol
8
8
  module HTTP
9
9
  module Body
10
- # A generic base class for wrapping body instances. Typically you'd override `#read`.
11
- # The implementation assumes a sequential unbuffered stream of data.
12
- # def each -> yield(String | nil)
13
- # def read -> String | nil
14
- # def join -> String
15
-
16
- # def finish -> buffer the stream and close it.
17
- # def close(error = nil) -> close the stream immediately.
18
- # end
10
+ # An interface for reading data from a body.
11
+ #
12
+ # Typically, you'd override `#read` to return chunks of data.
19
13
  class Readable
20
- # The consumer can call stop to signal that the stream output has terminated.
14
+ # Close the stream immediately.
21
15
  def close(error = nil)
22
16
  end
23
17
 
@@ -40,6 +34,7 @@ module Protocol
40
34
  end
41
35
 
42
36
  # Read the next available chunk.
37
+ # @returns [String | Nil] The chunk of data, or `nil` if the stream has finished.
43
38
  def read
44
39
  nil
45
40
  end
@@ -60,12 +55,16 @@ module Protocol
60
55
  end
61
56
 
62
57
  # Read all remaining chunks into a buffered body and close the underlying input.
58
+ # @returns [Buffered] The buffered body.
63
59
  def finish
64
60
  # Internally, this invokes `self.each` which then invokes `self.close`.
65
61
  Buffered.for(self)
66
62
  end
67
63
 
68
64
  # Enumerate all chunks until finished, then invoke `#close`.
65
+ #
66
+ # @yields {|chunk| ...} The block to call with each chunk of data.
67
+ # @parameter chunk [String | Nil] The chunk of data, or `nil` if the stream has finished.
69
68
  def each
70
69
  return to_enum(:each) unless block_given?
71
70
 
@@ -79,6 +78,8 @@ module Protocol
79
78
  end
80
79
 
81
80
  # Read all remaining chunks into a single binary string using `#each`.
81
+ #
82
+ # @returns [String | Nil] The binary string containing all chunks of data, or `nil` if the stream has finished (or did not contain any data).
82
83
  def join
83
84
  buffer = String.new.force_encoding(Encoding::BINARY)
84
85
 
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  # Released under the MIT License.
4
- # Copyright, 2018-2023, by Samuel Williams.
4
+ # Copyright, 2018-2024, by Samuel Williams.
5
5
 
6
6
  module Protocol
7
7
  module HTTP
@@ -65,12 +65,12 @@ module Protocol
65
65
  return to_enum(:each) unless block_given?
66
66
 
67
67
  constants.each do |name|
68
- yield name, const_get(name)
68
+ yield name.downcase, const_get(name)
69
69
  end
70
70
  end
71
71
 
72
72
  self.each do |name, value|
73
- define_method(name.downcase) do |location, headers = nil, body = nil|
73
+ define_method(name) do |location, headers = nil, body = nil|
74
74
  self.call(
75
75
  Request[value, location.to_s, Headers[headers], body]
76
76
  )
@@ -11,6 +11,17 @@ require_relative 'methods'
11
11
 
12
12
  module Protocol
13
13
  module HTTP
14
+ # Represents an HTTP request which can be used both server and client-side.
15
+ #
16
+ # ~~~ ruby
17
+ # require 'protocol/http'
18
+ #
19
+ # # Long form:
20
+ # Protocol::HTTP::Request.new("http", "example.com", "GET", "/index.html", "HTTP/1.1", Protocol::HTTP::Headers[["accept", "text/html"]])
21
+ #
22
+ # # Short form:
23
+ # Protocol::HTTP::Request["GET", "/index.html", {"accept" => "text/html"}]
24
+ # ~~~
14
25
  class Request
15
26
  prepend Body::Reader
16
27
 
@@ -25,28 +36,28 @@ module Protocol
25
36
  @protocol = protocol
26
37
  end
27
38
 
28
- # The request scheme, usually one of "http" or "https".
39
+ # @attribute [String] the request scheme, usually `"http"` or `"https"`.
29
40
  attr_accessor :scheme
30
-
31
- # The request authority, usually a hostname and port number.
41
+
42
+ # @attribute [String] the request authority, usually a hostname and port number, e.g. `"example.com:80"`.
32
43
  attr_accessor :authority
33
-
34
- # The request method, usually one of "GET", "HEAD", "POST", "PUT", "DELETE", "CONNECT" or "OPTIONS".
44
+
45
+ # @attribute [String] the request method, usually one of `"GET"`, `"HEAD"`, `"POST"`, `"PUT"`, `"DELETE"`, `"CONNECT"` or `"OPTIONS"`, etc.
35
46
  attr_accessor :method
36
-
37
- # The request path, usually a path and query string.
47
+
48
+ # @attribute [String] the request path, usually a path and query string, e.g. `"/index.html"`, `"/search?q=hello"`, however it can be any [valid request target](https://www.rfc-editor.org/rfc/rfc9110#target.resource).
38
49
  attr_accessor :path
39
-
40
- # The request version, usually "http/1.0", "http/1.1", "h2", or "h3".
50
+
51
+ # @attribute [String] the request version, usually `"http/1.0"`, `"http/1.1"`, `"h2"`, or `"h3"`.
41
52
  attr_accessor :version
42
-
43
- # The request headers, contains metadata associated with the request such as the user agent, accept (content type), accept-language, etc.
53
+
54
+ # @attribute [Headers] the request headers, usually containing metadata associated with the request such as the `"user-agent"`, `"accept"` (content type), `"accept-language"`, etc.
44
55
  attr_accessor :headers
45
-
46
- # The request body, an instance of Protocol::HTTP::Body::Readable or similar.
56
+
57
+ # @attribute [Body::Readable] the request body. It should only be read once (it may not be idempotent).
47
58
  attr_accessor :body
48
59
 
49
- # The request protocol, usually empty, but occasionally "websocket" or "webtransport", can be either single value `String` or multi-value `Array` of `String` instances. In HTTP/1, it is used to request a connection upgrade, and in HTTP/2 it is used to indicate a specfic protocol for the stream.
60
+ # @attribute [String | Array(String) | Nil] the request protocol, usually empty, but occasionally `"websocket"` or `"webtransport"`. In HTTP/1, it is used to request a connection upgrade, and in HTTP/2 it is used to indicate a specfic protocol for the stream.
50
61
  attr_accessor :protocol
51
62
 
52
63
  # Send the request to the given connection.
@@ -54,14 +65,22 @@ module Protocol
54
65
  connection.call(self)
55
66
  end
56
67
 
68
+ # Whether this is a HEAD request: no body is expected in the response.
57
69
  def head?
58
70
  @method == Methods::HEAD
59
71
  end
60
72
 
73
+ # Whether this is a CONNECT request: typically used to establish a tunnel.
61
74
  def connect?
62
75
  @method == Methods::CONNECT
63
76
  end
64
77
 
78
+ # A short-cut method which exposes the main request variables that you'd typically care about.
79
+ #
80
+ # @parameter method [String] The HTTP method, e.g. `"GET"`, `"POST"`, etc.
81
+ # @parameter path [String] The path, e.g. `"/index.html"`, `"/search?q=hello"`, etc.
82
+ # @parameter headers [Hash] The headers, e.g. `{"accept" => "text/html"}`, etc.
83
+ # @parameter body [String | Array(String) | Body::Readable] The body, e.g. `"Hello, World!"`, etc. See {Body::Buffered.wrap} for more information about .
65
84
  def self.[](method, path, headers = nil, body = nil)
66
85
  body = Body::Buffered.wrap(body)
67
86
  headers = ::Protocol::HTTP::Headers[headers]
@@ -69,6 +88,7 @@ module Protocol
69
88
  self.new(nil, nil, method, path, nil, headers, body)
70
89
  end
71
90
 
91
+ # Whether the request can be replayed without side-effects.
72
92
  def idempotent?
73
93
  @method != Methods::POST && (@body.nil? || @body.empty?)
74
94
  end
@@ -8,9 +8,27 @@ require_relative 'body/reader'
8
8
 
9
9
  module Protocol
10
10
  module HTTP
11
+ # Represents an HTTP response which can be used both server and client-side.
12
+ #
13
+ # ~~~ ruby
14
+ # require 'protocol/http'
15
+ #
16
+ # # Long form:
17
+ # Protocol::HTTP::Response.new("http/1.1", 200, Protocol::HTTP::Headers[["content-type", "text/html"]], Protocol::HTTP::Body::Buffered.wrap("Hello, World!"))
18
+ #
19
+ # # Short form:
20
+ # Protocol::HTTP::Response[200, {"content-type" => "text/html"}, ["Hello, World!"]]
21
+ # ~~~
11
22
  class Response
12
23
  prepend Body::Reader
13
24
 
25
+ # Create a new response.
26
+ #
27
+ # @parameter version [String | Nil] The HTTP version, e.g. `"HTTP/1.1"`. If `nil`, the version may be provided by the server sending the response.
28
+ # @parameter status [Integer] The HTTP status code, e.g. `200`, `404`, etc.
29
+ # @parameter headers [Hash] The headers, e.g. `{"content-type" => "text/html"}`, etc.
30
+ # @parameter body [Body::Readable] The body, e.g. `"Hello, World!"`, etc.
31
+ # @parameter protocol [String | Array(String)] The protocol, e.g. `"websocket"`, etc.
14
32
  def initialize(version = nil, status = 200, headers = Headers.new, body = nil, protocol = nil)
15
33
  @version = version
16
34
  @status = status
@@ -19,12 +37,22 @@ module Protocol
19
37
  @protocol = protocol
20
38
  end
21
39
 
40
+ # @attribute [String | Nil] The HTTP version, usually one of `"HTTP/1.1"`, `"HTTP/2"`, etc.
22
41
  attr_accessor :version
42
+
43
+ # @attribute [Integer] The HTTP status code, e.g. `200`, `404`, etc.
23
44
  attr_accessor :status
45
+
46
+ # @attribute [Hash] The headers, e.g. `{"content-type" => "text/html"}`, etc.
24
47
  attr_accessor :headers
48
+
49
+ # @attribute [Body::Readable] The body, e.g. `"Hello, World!"`, etc.
25
50
  attr_accessor :body
51
+
52
+ # @attribute [String | Array(String) | Nil] The protocol, e.g. `"websocket"`, etc.
26
53
  attr_accessor :protocol
27
54
 
55
+ # Whether the response is considered a hijack: the connection has been taken over by the application and the server should not send any more data.
28
56
  def hijack?
29
57
  false
30
58
  end
@@ -93,6 +121,15 @@ module Protocol
93
121
  # @deprecated Use {#internal_server_error?} instead.
94
122
  alias server_failure? internal_server_error?
95
123
 
124
+ # A short-cut method which exposes the main response variables that you'd typically care about. It follows the same order as the `Rack` response tuple, but also includes the protocol.
125
+ #
126
+ # ~~~ ruby
127
+ # Response[200, {"content-type" => "text/html"}, ["Hello, World!"]]
128
+ # ~~~
129
+ #
130
+ # @parameter status [Integer] The HTTP status code, e.g. `200`, `404`, etc.
131
+ # @parameter headers [Hash] The headers, e.g. `{"content-type" => "text/html"}`, etc.
132
+ # @parameter body [String | Array(String) | Body::Readable] The body, e.g. `"Hello, World!"`, etc. See {Body::Buffered.wrap} for more information about .
96
133
  def self.[](status, headers = nil, body = nil, protocol = nil)
97
134
  body = Body::Buffered.wrap(body)
98
135
  headers = ::Protocol::HTTP::Headers[headers]
@@ -100,6 +137,9 @@ module Protocol
100
137
  self.new(nil, status, headers, body, protocol)
101
138
  end
102
139
 
140
+ # Create a response for the given exception.
141
+ #
142
+ # @parameter exception [Exception] The exception to generate the response for.
103
143
  def self.for_exception(exception)
104
144
  Response[500, Headers['content-type' => 'text/plain'], ["#{exception.class}: #{exception.message}"]]
105
145
  end
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  # Released under the MIT License.
4
- # Copyright, 2019-2023, by Samuel Williams.
4
+ # Copyright, 2019-2024, by Samuel Williams.
5
5
  # Copyright, 2022, by Herrick Fang.
6
6
 
7
7
  module Protocol
@@ -65,9 +65,13 @@ module Protocol
65
65
  end
66
66
 
67
67
  def self.split(name)
68
- name.scan(/([^\[]+)|(?:\[(.*?)\])/).flatten!.compact!
68
+ name.scan(/([^\[]+)|(?:\[(.*?)\])/)&.tap do |parts|
69
+ parts.flatten!
70
+ parts.compact!
71
+ end
69
72
  end
70
73
 
74
+ # Assign a value to a nested hash.
71
75
  def self.assign(keys, value, parent)
72
76
  top, *middle = keys
73
77
 
@@ -95,6 +99,10 @@ module Protocol
95
99
  self.scan(string) do |name, value|
96
100
  keys = self.split(name)
97
101
 
102
+ if keys.empty?
103
+ raise ArgumentError, "Invalid key path: #{name.inspect}!"
104
+ end
105
+
98
106
  if keys.size > maximum
99
107
  raise ArgumentError, "Key length exceeded limit!"
100
108
  end
@@ -5,6 +5,6 @@
5
5
 
6
6
  module Protocol
7
7
  module HTTP
8
- VERSION = "0.26.5"
8
+ VERSION = "0.26.7"
9
9
  end
10
10
  end
data/lib/protocol/http.rb CHANGED
@@ -1,6 +1,11 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  # Released under the MIT License.
4
- # Copyright, 2018-2023, by Samuel Williams.
4
+ # Copyright, 2018-2024, by Samuel Williams.
5
5
 
6
6
  require_relative "http/version"
7
+
8
+ require_relative 'http/headers'
9
+ require_relative 'http/request'
10
+ require_relative 'http/response'
11
+ require_relative 'http/middleware'
data/readme.md CHANGED
@@ -30,11 +30,11 @@ We welcome contributions to this project.
30
30
 
31
31
  ### Developer Certificate of Origin
32
32
 
33
- This project uses the [Developer Certificate of Origin](https://developercertificate.org/). All contributors to this project must agree to this document to have their contributions accepted.
33
+ In order to protect users of this project, we require all contributors to comply with the [Developer Certificate of Origin](https://developercertificate.org/). This ensures that all contributions are properly licensed and attributed.
34
34
 
35
- ### Contributor Covenant
35
+ ### Community Guidelines
36
36
 
37
- This project is governed by the [Contributor Covenant](https://www.contributor-covenant.org/). All contributors and participants agree to abide by its terms.
37
+ This project is best served by a collaborative and respectful environment. Treat each other professionally, respect differing viewpoints, and engage constructively. Harassment, discrimination, or harmful behavior is not tolerated. Communicate clearly, listen actively, and support one another. If any issues arise, please inform the project maintainers.
38
38
 
39
39
  ## See Also
40
40
 
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.26.5
4
+ version: 0.26.7
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-05-04 00:00:00.000000000 Z
50
+ date: 2024-07-07 00:00:00.000000000 Z
51
51
  dependencies: []
52
52
  description:
53
53
  email:
@@ -114,7 +114,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
114
114
  - !ruby/object:Gem::Version
115
115
  version: '0'
116
116
  requirements: []
117
- rubygems_version: 3.5.3
117
+ rubygems_version: 3.5.11
118
118
  signing_key:
119
119
  specification_version: 4
120
120
  summary: Provides abstractions to handle HTTP protocols.
metadata.gz.sig CHANGED
Binary file