silk.http.target.
The target of an HTTP request, the authority in it, and the Host field.
When to use#
A server uses RequestTarget.parse on the target of a received request line, and
validateRequestHost and effectiveAuthority to find the host that the client asked for. A
client uses RequestTarget.fromUri and hostForUri to write the target and the Host
value for a URI.
Details#
There are four target forms. Origin form is a path and query, such as /search?q=silk. Absolute
form is a full URI, used with proxies. Authority form is host:port, used only with CONNECT.
Asterisk form is *, used only with OPTIONS. Parsing keeps the spelling and the percent
escapes of the input. Nothing in this module does DNS or connects.
Errors#
ValueErrorwithInvalidTarget,InvalidAuthority,InvalidPort, orMethodTargetMismatch, and the byte offset.
Gotchas#
A received target with a fragment (#...) fails. RequestTarget.fromUri drops the fragment
of a URI, because a fragment is never sent.
Examples#
Parse request targets#
import silk.http.message { Method, ValueError, ValueReason }
import silk.http.target { HttpAuthority, RequestTarget, effectiveAuthority }
import silk.core.option { Option }
import silk.core.result { Result }
pub fn main() -> i32 {
let get = Method.get()
let target = match RequestTarget.parse(&get, "/search?q=silk", 8192) {
Result<RequestTarget, ValueError>.Success { value } => value
Result<RequestTarget, ValueError>.Failure { error: _ } => {
return 1
}
}
if RequestTarget.isAbsolute(&target) || RequestTarget.format(target) != "/search?q=silk" {
return 1
}
// CONNECT takes host:port.
let connect = Method.connect()
let tunnel = match RequestTarget.parse(&connect, "example.com:443", 8192) {
Result<RequestTarget, ValueError>.Success { value } => value
Result<RequestTarget, ValueError>.Failure { error: _ } => {
return 1
}
}
let port = match effectiveAuthority(tunnel, Option<HttpAuthority>.none()) {
Result<Option<HttpAuthority>, ValueError>.Success {
value: Option<HttpAuthority>.Some { value }
} => HttpAuthority.port(&value)
_ => Option<u16>.none()
}
if Option<u16>.unwrapOr(move port, 0) != 443 {
return 1
}
// Only OPTIONS can use "*".
let mismatch = match RequestTarget.parse(&get, "*", 8192) {
Result<RequestTarget, ValueError>.Success { value: _ } => false
Result<RequestTarget, ValueError>.Failure { error } => match error.reason {
ValueReason.MethodTargetMismatch => true
_ => false
}
}
if !mismatch {
return 1
}
return 0
}Import as RequestTarget with import silk.http.target { RequestTarget }.
Public declarations: 6.
TargetForm#
pub enum TargetFormThe target form that RequestTarget.fromUri writes.
Origin#
OriginThe path and query, such as /search?q=silk. Use it for a direct request.
Absolute#
AbsoluteThe full URI without the fragment. Use it for a request to an HTTP proxy.
HttpAuthority#
pub struct HttpAuthority<'text>A checked host or host:port, without user information. It keeps the spelling of its input.
Implementation Copy for HttpAuthority<'text>#
impl<'text> Copy for HttpAuthority<'text>Implementation HttpAuthority<'text>#
impl<'text> HttpAuthority<'text>Associated function parse#
pub fn parse(text: string<'text>) -> Result<HttpAuthority<'text>, ValueError>Checks text as a host[:port] authority. An IPv6 host keeps its brackets. User information
fails.
Method format#
pub fn format(self: &Self) -> string<'text>Returns the whole authority text.
Method host#
pub fn host(self: &Self) -> string<'text>Returns the host, with brackets for IPv6.
Method portText#
pub fn portText(self: &Self) -> Option<string<'text>>Returns the port digits without the colon, or None if there is no port.
Method port#
pub fn port(self: &Self) -> Option<u16>Returns the port as a number, or None if there is no port.
RequestTarget#
pub union RequestTarget<'text>The target of a request, in one of its four forms.
Details#
Origin form is a path and query, such as /search?q=silk. Absolute form is a full URI, used
with proxies. Authority form is host:port, used only with CONNECT. Asterisk form is *,
used only with OPTIONS. Parsing keeps the spelling and the percent escapes of the input.
Gotchas#
A received target with a fragment (#...) fails. RequestTarget.fromUri drops the fragment
of a URI, because a fragment is never sent.
Origin#
OriginA path and an optional query, such as /a?b=c.
Absolute#
AbsoluteA full URI, such as http://example.com/a.
Authority#
AuthorityA host:port, for CONNECT.
Asterisk#
AsteriskThe * target, for OPTIONS.
Implementation Copy for RequestTarget<'text>#
impl<'text> Copy for RequestTarget<'text>Implementation RequestTarget<'text>#
impl<'text> RequestTarget<'text>Associated function parse#
pub fn parse(
method: &Method,
text: string<'text>,
maxBytes: usize,
) -> Result<RequestTarget<'text>, ValueError>Parses a received target, and selects its form from the method and the text.
Details#
* is asterisk form. With CONNECT, the text is authority form, and needs a port that is not
0. Text that starts with / is origin form. All other text is absolute form.
Errors#
LimitExceedediftextis longer thanmaxBytes.InvalidTargetiftextis empty, has a space, a control byte, or a fragment.MethodTargetMismatchif*is used withoutOPTIONS.
Associated function validateForMethod#
pub fn validateForMethod(
method: &Method,
target: RequestTarget<'text>,
) -> Result<(), ValueError>Returns MethodTargetMismatch if the form of target does not fit method.
Method format#
pub fn format(self: Self) -> string<'text>Returns the target text, spelled as received.
Method isAbsolute#
pub fn isAbsolute(self: &Self) -> boolReturns true for absolute form.
Method isAuthority#
pub fn isAuthority(self: &Self) -> boolReturns true for authority form.
Associated function fromUri#
pub fn fromUri(
uri: &Uri,
form: TargetForm,
output: &mut [u8],
) -> Result<usize, ValueError>Writes the target for uri in the given form to the start of output, and returns the
length.
The fragment is not written. An empty path is written as /.
Errors#
InvalidAuthorityifurihas user information.OutputTooSmallifoutputis too small. Nothing is written.
validateRequestHost#
pub fn validateRequestHost<'value>(
version: Version,
target: &RequestTarget,
headers: &Headers<'value>,
) -> Result<Option<HttpAuthority<'value>>, ValueError>Checks the Host field of a received request, and returns its authority.
Errors#
MissingHostif an HTTP/1.1 request has noHostfield.DuplicateHostif there is more than oneHostfield.InvalidAuthorityif the value is not a valid authority.fieldIndextells which field.
effectiveAuthority#
pub fn effectiveAuthority<'value>(
target: RequestTarget<'value>,
host: Option<HttpAuthority<'value>>,
) -> Result<Option<HttpAuthority<'value>>, ValueError>Returns the authority that the request is for: the authority in an absolute or CONNECT target,
else the Host authority.
hostForUri#
pub fn hostForUri<'value>(uri: &Uri<'value>, output: &mut [u8]) -> Result<usize, ValueError>Writes the Host value for uri, such as example.com:8080, to the start of output, and
returns the length.
Errors#
InvalidAuthorityifurihas user information or no host.OutputTooSmallifoutputis too small. Nothing is written.
Category: HTTP.
Profiles: aarch64-apple-darwin, aarch64-unknown-linux-gnu, aarch64-unknown-linux-gnu-no-libc, x86_64-unknown-linux-gnu, x86_64-unknown-linux-gnu-no-libc, wasm32-unknown-unknown, wasm32-wasip1, wasm32-wasip2.