Fix support for HTTP extension methods.

This commit is contained in:
lobsterwise 2024-08-16 22:47:26 -04:00 committed by Sergio Benitez
parent 51d4ed4394
commit 4c71ed6ee3
4 changed files with 38 additions and 5 deletions

View File

@ -2,6 +2,7 @@ use std::{io, fmt};
use std::ops::RangeFrom; use std::ops::RangeFrom;
use std::sync::{Arc, atomic::Ordering}; use std::sync::{Arc, atomic::Ordering};
use std::borrow::Cow; use std::borrow::Cow;
use std::str::FromStr;
use std::future::Future; use std::future::Future;
use std::net::IpAddr; use std::net::IpAddr;
@ -1086,7 +1087,7 @@ impl<'r> Request<'r> {
// Keep track of parsing errors; emit a `BadRequest` if any exist. // Keep track of parsing errors; emit a `BadRequest` if any exist.
let mut errors = vec![]; let mut errors = vec![];
// Ensure that the method is known. TODO: Allow made-up methods? // Ensure that the method is known.
let method = match hyper.method { let method = match hyper.method {
hyper::Method::GET => Method::Get, hyper::Method::GET => Method::Get,
hyper::Method::PUT => Method::Put, hyper::Method::PUT => Method::Put,
@ -1097,10 +1098,10 @@ impl<'r> Request<'r> {
hyper::Method::TRACE => Method::Trace, hyper::Method::TRACE => Method::Trace,
hyper::Method::CONNECT => Method::Connect, hyper::Method::CONNECT => Method::Connect,
hyper::Method::PATCH => Method::Patch, hyper::Method::PATCH => Method::Patch,
_ => { ref ext => Method::from_str(ext.as_str()).unwrap_or_else(|_| {
errors.push(RequestError::BadMethod(hyper.method.clone())); errors.push(RequestError::BadMethod(hyper.method.clone()));
Method::Get Method::Get
} }),
}; };
// TODO: Keep around not just the path/query, but the rest, if there? // TODO: Keep around not just the path/query, but the rest, if there?

View File

@ -26,7 +26,9 @@ impl Client {
.connect_timeout(Duration::from_secs(5)) .connect_timeout(Duration::from_secs(5))
} }
pub fn request(&self, server: &Server, method: Method, url: &str) -> Result<RequestBuilder> { pub fn request<M>(&self, server: &Server, method: M, url: &str) -> Result<RequestBuilder>
where M: AsRef<str>
{
let uri = match Uri::parse_any(url).map_err(|e| e.into_owned())? { let uri = match Uri::parse_any(url).map_err(|e| e.into_owned())? {
Uri::Origin(uri) => { Uri::Origin(uri) => {
let proto = if server.tls { "https" } else { "http" }; let proto = if server.tls { "https" } else { "http" };
@ -45,7 +47,7 @@ impl Client {
uri => return Err(Error::InvalidUri(uri.into_owned())), uri => return Err(Error::InvalidUri(uri.into_owned())),
}; };
let method = reqwest::Method::from_str(method.as_str()).unwrap(); let method = reqwest::Method::from_str(method.as_ref()).unwrap();
Ok(self.client.request(method, uri.to_string())) Ok(self.client.request(method, uri.to_string()))
} }

View File

@ -0,0 +1,29 @@
//! Test that HTTP method extensions unlike POST or GET work.
use crate::prelude::*;
use rocket::http::Method;
#[route(PROPFIND, uri = "/")]
fn route() -> &'static str {
"Hello, World!"
}
pub fn test_http_extensions() -> Result<()> {
let server = spawn! {
Rocket::default().mount("/", routes![route])
}?;
let client = Client::default();
let response = client.request(&server, Method::PropFind, "/")?.send()?;
assert_eq!(response.status(), 200);
assert_eq!(response.text()?, "Hello, World!");
// Make sure that verbs outside of extensions are marked as errors
let res = client.request(&server, "BAKEMEACOOKIE", "/")?.send()?;
assert_eq!(res.status(), 400);
Ok(())
}
register!(test_http_extensions);

View File

@ -1,5 +1,6 @@
pub mod ignite_failure; pub mod ignite_failure;
pub mod bind; pub mod bind;
pub mod http_extensions;
pub mod infinite_stream; pub mod infinite_stream;
pub mod tls_resolver; pub mod tls_resolver;
pub mod mtls; pub mod mtls;