class Protocol::HTTP::Request

~~~
Protocol::HTTP::Request[“GET”, “/index.html”, {“accept” => “text/html”}]
# Short form:
Protocol::HTTP::Request.new(“http”, “example.com”, “GET”, “/index.html”, “HTTP/1.1”, Protocol::HTTP::Headers[[“accept”, “text/html”]])
# Long form:
require ‘protocol/http’
~~~ ruby
Represents an HTTP request which can be used both server and client-side.

def self.[](method, path, _headers = nil, _body = nil, scheme: nil, authority: nil, headers: _headers, body: _body, protocol: nil, interim_response: nil)

@parameter body [String | Array(String) | Body::Readable] The body, e.g. `"Hello, World!"`, etc. See {Body::Buffered.wrap} for more information about .
@parameter headers [Hash] The headers, e.g. `{"accept" => "text/html"}`, etc.
@parameter path [String] The path, e.g. `"/index.html"`, `"/search?q=hello"`, etc.
@parameter method [String] The HTTP method, e.g. `"GET"`, `"POST"`, etc.

A short-cut method which exposes the main request variables that you'd typically care about.
def self.[](method, path, _headers = nil, _body = nil, scheme: nil, authority: nil, headers: _headers, body: _body, protocol: nil, interim_response: nil)
	body = Body::Buffered.wrap(body)
	headers = Headers[headers]
	
	self.new(scheme, authority, method, path, nil, headers, body, protocol, interim_response)
end

def as_json(...)

@returns [Hash] The request as a hash.

Convert the request to a hash, suitable for serialization.
def as_json(...)
	{
		scheme: @scheme,
		authority: @authority,
		method: @method,
		path: @path,
		version: @version,
		headers: @headers&.as_json,
		body: @body&.as_json,
		protocol: @protocol
	}
end

def call(connection)

Send the request to the given connection.
def call(connection)
	connection.call(self)
end

def connect?

Whether this is a CONNECT request: typically used to establish a tunnel.
def connect?
	@method == Methods::CONNECT
end

def head?

Whether this is a HEAD request: no body is expected in the response.
def head?
	@method == Methods::HEAD
end

def idempotent?

Whether the request can be replayed without side-effects.
def idempotent?
	@method != Methods::POST && (@body.nil? || @body.empty?)
end

def initialize(scheme = nil, authority = nil, method = nil, path = nil, version = nil, headers = Headers.new, body = nil, protocol = nil, interim_response = nil)

@parameter interim_response [Proc] A callback which is called when an interim response is received.
@parameter protocol [String | Array(String) | Nil] The request protocol, usually empty, but occasionally `"websocket"` or `"webtransport"`.
@parameter body [Body::Readable] The request body.
@parameter headers [Headers] The request headers, usually containing metadata associated with the request such as the `"user-agent"`, `"accept"` (content type), `"accept-language"`, etc.
@parameter version [String | Nil] The request version, usually `"http/1.0"`, `"http/1.1"`, `"h2"`, or `"h3"`.
@parameter path [String | Nil] The request path, usually a path and query string, e.g. `"/index.html"`, `"/search?q=hello"`, etc.
@parameter method [String | Nil] The request method, usually one of `"GET"`, `"HEAD"`, `"POST"`, `"PUT"`, `"DELETE"`, `"CONNECT"` or `"OPTIONS"`, etc.
@parameter authority [String | Nil] The request authority, usually a hostname and port number, e.g. `"example.com:80"`.
@parameter scheme [String | Nil] The request scheme, usually `"http"` or `"https"`.

Initialize the request.
def initialize(scheme = nil, authority = nil, method = nil, path = nil, version = nil, headers = Headers.new, body = nil, protocol = nil, interim_response = nil)
	@scheme = scheme
	@authority = authority
	@method = method
	@path = path
	@version = version
	@headers = headers
	@body = body
	@protocol = protocol
	@interim_response = interim_response
end

def on_interim_response(&block)

@parameter headers [Hash] The headers, e.g. `{"link" => "; rel=stylesheet"}`, etc.
@parameter status [Integer] The HTTP status code, e.g. `100`, `101`, etc.
@yields {|status, headers| ...} The callback to be called when an interim response is received.

Register a callback to be called when an interim response is received.
def on_interim_response(&block)
	if interim_response = @interim_response
		@interim_response = ->(status, headers) do
			block.call(status, headers)
			interim_response.call(status, headers)
		end
	else
		@interim_response = block
	end
end

def peer

@returns [Peer | Nil] The peer (address) associated with the request.

A request that is generated by a server, may choose to include the peer (address) associated with the request. It should be implemented by a sub-class.
def peer
	nil
end

def send_interim_response(status, headers)

Send an interim response back to the origin of this request, if possible.
def send_interim_response(status, headers)
	@interim_response&.call(status, headers)
end

def to_json(...)

@returns [String] The request as JSON.

Convert the request to JSON.
def to_json(...)
	as_json.to_json(...)
end

def to_s

@returns [String] The request as a string.

Summarize the request as a string.
def to_s
	"#{@scheme}://#{@authority}: #{@method} #{@path} #{@version}"
end