diff --git a/CHANGELOG.md b/CHANGELOG.md index 48f74d6a..48943995 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +# Unreleased + +* Add 'QUERY' method support and document 'accept-query' as a new standard header. + # 1.2.0 (December 3, 2024) * Add `StatusCode::TOO_EARLY` constant for 425 status. diff --git a/benches/src/header_name.rs b/benches/src/header_name.rs index 4249f987..d190cad5 100644 --- a/benches/src/header_name.rs +++ b/benches/src/header_name.rs @@ -68,6 +68,7 @@ fn make_all_known_headers() -> Vec> { // standard_response_headers b"Accept-Patch".to_vec(), b"Accept-Ranges".to_vec(), + b"Accept-Query".to_vec(), b"Access-Control-Allow-Credentials".to_vec(), b"Access-Control-Allow-Headers".to_vec(), b"Access-Control-Allow-Methods".to_vec(), @@ -191,6 +192,7 @@ static ALL_KNOWN_HEADERS: &[&str] = &[ // standard_response_headers "accept-patch", "accept-ranges", + "accept-query", "access-control-allow-credentials", "access-control-allow-headers", "access-control-allow-methods", diff --git a/src/method.rs b/src/method.rs index 7b4584ab..da267b7b 100644 --- a/src/method.rs +++ b/src/method.rs @@ -30,7 +30,7 @@ use std::{fmt, str}; /// /// Currently includes 8 variants representing the 8 methods defined in /// [RFC 7230](https://tools.ietf.org/html/rfc7231#section-4.1), plus PATCH, -/// and an Extension variant for all extensions. +/// QUERY, and an Extension variant for all extensions. /// /// # Examples /// @@ -60,6 +60,7 @@ enum Inner { Trace, Connect, Patch, + Query, // If the extension is short enough, store it inline ExtensionInline(InlineExtension), // Otherwise, allocate it @@ -94,6 +95,9 @@ impl Method { /// TRACE pub const TRACE: Method = Method(Trace); + /// QUERY + pub const QUERY: Method = Method(Query); + /// Converts a slice of bytes to an HTTP method. pub fn from_bytes(src: &[u8]) -> Result { match src.len() { @@ -111,6 +115,7 @@ impl Method { 5 => match src { b"PATCH" => Ok(Method(Patch)), b"TRACE" => Ok(Method(Trace)), + b"QUERY" => Ok(Method(Query)), _ => Method::extension_inline(src), }, 6 => match src { @@ -146,7 +151,7 @@ impl Method { /// See [the spec](https://tools.ietf.org/html/rfc7231#section-4.2.1) /// for more words. pub fn is_safe(&self) -> bool { - matches!(self.0, Get | Head | Options | Trace) + matches!(self.0, Get | Head | Options | Trace | Query) } /// Whether a method is considered "idempotent", meaning the request has @@ -174,6 +179,7 @@ impl Method { Trace => "TRACE", Connect => "CONNECT", Patch => "PATCH", + Query => "QUERY", ExtensionInline(ref inline) => inline.as_str(), ExtensionAllocated(ref allocated) => allocated.as_str(), } @@ -452,6 +458,7 @@ mod test { assert!(Method::DELETE.is_idempotent()); assert!(Method::HEAD.is_idempotent()); assert!(Method::TRACE.is_idempotent()); + assert!(Method::QUERY.is_idempotent()); assert!(!Method::POST.is_idempotent()); assert!(!Method::CONNECT.is_idempotent()); diff --git a/src/request.rs b/src/request.rs index 324b676c..07197ce1 100644 --- a/src/request.rs +++ b/src/request.rs @@ -413,6 +413,28 @@ impl Request<()> { { Builder::new().method(Method::TRACE).uri(uri) } + + /// Creates a new `Builder` initialized with a QUERY method and the given URI. + /// + /// This method returns an instance of `Builder` which can be used to + /// create a `Request`. + /// + /// # Example + /// + /// ``` + /// # use http::*; + /// + /// let request = Request::query("https://www.rust-lang.org/") + /// .body(()) + /// .unwrap(); + /// ``` + pub fn query(uri: T) -> Builder + where + T: TryInto, + >::Error: Into, + { + Builder::new().method(Method::QUERY).uri(uri) + } } impl Request { diff --git a/util/src/main.rs b/util/src/main.rs index 915cf0b8..0604f769 100644 --- a/util/src/main.rs +++ b/util/src/main.rs @@ -127,6 +127,19 @@ standard_headers! { "#, "accept-ranges"; + r#" + /// Advertises which query formats the server is able to understand. + /// + /// Accept-Query should appear in the OPTIONS response for any resource that + /// supports the use of the QUERY method. The presence of the + /// Accept-Query header in response to any method is an implicit indication + /// that QUERY is allowed on the resource identified by the URI. The + /// presence of a specific query document format in this header indicates + /// that that specific format is allowed on the resource identified by the + /// URI. + "#, + "accept-query"; + r#" /// Preflight response indicating if the response to the request can be /// exposed to the page.