Skip to content

Commit

Permalink
Merge pull request #286 from m00nwtchr/into_http
Browse files Browse the repository at this point in the history
`http` compatibility
  • Loading branch information
StuartHarris authored Jan 22, 2025
2 parents 256f869 + cf9c617 commit a0af102
Show file tree
Hide file tree
Showing 15 changed files with 166 additions and 86 deletions.
18 changes: 18 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions crux_http/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ default = ["encoding"]
# requires web-sys for TextDecoder on wasm
encoding = ["encoding_rs", "web-sys"]
typegen = ["crux_core/typegen"]
http-compat = ["dep:http"]

[dependencies]
anyhow.workspace = true
Expand All @@ -25,6 +26,7 @@ encoding_rs = { version = "0.8.35", optional = true }
futures-util = "0.3"
http-types = { package = "http-types-red-badger-temporary-fork", version = "2.12.0", default-features = false }
pin-project-lite = "0.2.16"
http = { version = "1.1", optional = true }
serde = { workspace = true, features = ["derive"] }
serde_bytes = "0.11"
serde_json = "1.0.137"
Expand Down
2 changes: 1 addition & 1 deletion crux_http/src/client.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
use std::fmt;
use std::sync::Arc;

use crate::http::{Method, Url};
use crate::middleware::{Middleware, Next};
use crate::protocol::{EffectSender, HttpResult, ProtocolRequestBuilder};
use crate::{Config, Request, RequestBuilder, ResponseAsync, Result};
use http_types::{Method, Url};

/// An HTTP client, capable of sending `Request`s
///
Expand Down
6 changes: 4 additions & 2 deletions crux_http/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@
use std::{collections::HashMap, fmt::Debug};

use http_types::headers::{HeaderName, HeaderValues, ToHeaderValues};
use http_types::{
headers::{HeaderName, HeaderValues, ToHeaderValues},
Url,
};

use crate::http::Url;
use crate::Result;

/// Configuration for `crux_http::Http`s and their underlying HTTP client.
Expand Down
8 changes: 4 additions & 4 deletions crux_http/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ pub enum HttpError {
#[error("HTTP error {code}: {message}")]
#[serde(skip)]
Http {
code: crate::http::StatusCode,
code: http_types::StatusCode,
message: String,
body: Option<Vec<u8>>,
},
Expand All @@ -21,8 +21,8 @@ pub enum HttpError {
Timeout,
}

impl From<crate::http::Error> for HttpError {
fn from(e: crate::http::Error) -> Self {
impl From<http_types::Error> for HttpError {
fn from(e: http_types::Error) -> Self {
HttpError::Http {
code: e.status(),
message: e.to_string(),
Expand Down Expand Up @@ -50,7 +50,7 @@ mod tests {
#[test]
fn test_error_display() {
let error = HttpError::Http {
code: crate::http::StatusCode::BadRequest,
code: http_types::StatusCode::BadRequest,
message: "Bad Request".to_string(),
body: None,
};
Expand Down
6 changes: 3 additions & 3 deletions crux_http/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
// #![warn(missing_docs)]

use crux_core::capability::CapabilityContext;
use http::Method;
use http_types::Method;
use url::Url;

mod config;
Expand All @@ -21,7 +21,7 @@ pub mod middleware;
pub mod protocol;
pub mod testing;

pub use http_types::{self as http};
pub use http_types;

pub use self::{
config::Config,
Expand Down Expand Up @@ -307,7 +307,7 @@ where
///
/// When finished, the response will be wrapped in an event and dispatched to
/// the app's `update function.
pub fn request(&self, method: http::Method, url: Url) -> RequestBuilder<Ev> {
pub fn request(&self, method: http_types::Method, url: Url) -> RequestBuilder<Ev> {
RequestBuilder::new(method, url, self.clone())
}
}
6 changes: 3 additions & 3 deletions crux_http/src/middleware/redirect.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@
//! # }
//! ```
use crate::http::{self, headers, StatusCode, Url};
use crate::middleware::{Middleware, Next, Request};
use crate::{Client, ResponseAsync, Result};
use http_types::{headers, StatusCode, Url};

// List of acceptable 300-series redirect codes.
const REDIRECT_CODES: &[StatusCode] = &[
Expand Down Expand Up @@ -107,14 +107,14 @@ impl Middleware for Redirect {
let res: ResponseAsync = client.send(r).await?;
if REDIRECT_CODES.contains(&res.status()) {
if let Some(location) = res.header(headers::LOCATION) {
let http_req: &mut http::Request = req.as_mut();
let http_req: &mut http_types::Request = req.as_mut();
*http_req.url_mut() = match Url::parse(location.last().as_str()) {
Ok(valid_url) => {
base_url = valid_url;
base_url.clone()
}
Err(e) => match e {
http::url::ParseError::RelativeUrlWithoutBase => {
http_types::url::ParseError::RelativeUrlWithoutBase => {
base_url.join(location.last().as_str())?
}
e => return Err(e.into()),
Expand Down
2 changes: 1 addition & 1 deletion crux_http/src/protocol.rs
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,7 @@ impl ProtocolRequestBuilder for crate::Request {

impl From<HttpResponse> for crate::ResponseAsync {
fn from(effect_response: HttpResponse) -> Self {
let mut res = crate::http::Response::new(effect_response.status);
let mut res = http_types::Response::new(effect_response.status);
res.set_body(effect_response.body);
for header in effect_response.headers {
res.append_header(header.name.as_str(), header.value);
Expand Down
65 changes: 42 additions & 23 deletions crux_http/src/request.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
use crate::http::{
self,
use crate::middleware::Middleware;
use http_types::{
headers::{self, HeaderName, HeaderValues, ToHeaderValues},
Body, Method, Mime, Url,
};
use crate::middleware::Middleware;

use serde::Serialize;

Expand All @@ -15,7 +14,7 @@ use std::sync::Arc;
#[derive(Clone)]
pub struct Request {
/// Holds the state of the request.
req: http::Request,
req: http_types::Request,
/// Holds an optional per-request middleware stack.
middleware: Option<Vec<Arc<dyn Middleware>>>,
}
Expand All @@ -31,14 +30,14 @@ impl Request {
///
/// ```
/// fn main() -> crux_http::Result<()> {
/// use crux_http::http::{Url, Method};
/// use crux_http::http_types::{Url, Method};
///
/// let url = Url::parse("https://httpbin.org/get")?;
/// let req = crux_http::Request::new(Method::Get, url);
/// # Ok(()) }
/// ```
pub fn new(method: Method, url: Url) -> Self {
let req = http::Request::new(method, url);
let req = http_types::Request::new(method, url);
Self {
req,
middleware: None,
Expand Down Expand Up @@ -199,7 +198,7 @@ impl Request {
/// # struct Capabilities { http: crux_http::Http<Event> }
/// # fn update(caps: &Capabilities) -> crux_http::Result<()> {
/// let req = caps.http.get("https://httpbin.org/get").build();
/// assert_eq!(req.method(), crux_http::http::Method::Get);
/// assert_eq!(req.method(), crux_http::http_types::Method::Get);
/// # Ok(()) }
/// ```
pub fn method(&self) -> Method {
Expand All @@ -214,7 +213,7 @@ impl Request {
/// # enum Event {}
/// # struct Capabilities { http: crux_http::Http<Event> }
/// # fn update(caps: &Capabilities) -> crux_http::Result<()> {
/// use crux_http::http::Url;
/// use crux_http::http_types::Url;
/// let req = caps.http.get("https://httpbin.org/get").build();
/// assert_eq!(req.url(), &Url::parse("https://httpbin.org/get")?);
/// # Ok(()) }
Expand Down Expand Up @@ -362,44 +361,64 @@ impl Request {
}
}

impl AsRef<http::Headers> for Request {
fn as_ref(&self) -> &http::Headers {
impl AsRef<http_types::Headers> for Request {
fn as_ref(&self) -> &http_types::Headers {
self.req.as_ref()
}
}

impl AsMut<http::Headers> for Request {
fn as_mut(&mut self) -> &mut http::Headers {
impl AsMut<http_types::Headers> for Request {
fn as_mut(&mut self) -> &mut http_types::Headers {
self.req.as_mut()
}
}

impl AsRef<http::Request> for Request {
fn as_ref(&self) -> &http::Request {
impl AsRef<http_types::Request> for Request {
fn as_ref(&self) -> &http_types::Request {
&self.req
}
}

impl AsMut<http::Request> for Request {
fn as_mut(&mut self) -> &mut http::Request {
impl AsMut<http_types::Request> for Request {
fn as_mut(&mut self) -> &mut http_types::Request {
&mut self.req
}
}

impl From<http::Request> for Request {
/// Converts an `http::Request` to a `crux_http::Request`.
fn from(req: http::Request) -> Self {
impl From<http_types::Request> for Request {
/// Converts an `http_types::Request` to a `crux_http::Request`.
fn from(req: http_types::Request) -> Self {
Self {
req,
middleware: None,
}
}
}

#[cfg(feature = "http-compat")]
impl<B: Into<Body>> TryFrom<http::Request<B>> for Request {
type Error = anyhow::Error;

fn try_from(req: http::Request<B>) -> Result<Self, Self::Error> {
use std::str::FromStr;
let mut o = Request::new(
Method::from_str(req.method().as_str()).map_err(|e| anyhow::anyhow!(e))?,
req.uri().to_string().parse()?,
);

for (k, v) in req.headers().iter() {
o.append_header(k.as_str(), v.to_str()?);
}

o.set_body(req.into_body());
Ok(o)
}
}

#[allow(clippy::from_over_into)]
impl Into<http::Request> for Request {
/// Converts a `crux_http::Request` to an `http::Request`.
fn into(self) -> http::Request {
impl Into<http_types::Request> for Request {
/// Converts a `crux_http::Request` to an `http_types::Request`.
fn into(self) -> http_types::Request {
self.req
}
}
Expand All @@ -414,7 +433,7 @@ impl IntoIterator for Request {
type Item = (HeaderName, HeaderValues);
type IntoIter = headers::IntoIter;

/// Returns a iterator of references over the remaining items.
/// Returns an iterator of references over the remaining items.
#[inline]
fn into_iter(self) -> Self::IntoIter {
self.req.into_iter()
Expand Down
20 changes: 9 additions & 11 deletions crux_http/src/request_builder.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,14 @@
use crate::expect::ResponseExpectation;
use crate::expect::{ExpectBytes, ExpectJson, ExpectString};
use crate::middleware::Middleware;
use crate::{
expect::ResponseExpectation,
http::{
headers::{HeaderName, ToHeaderValues},
Body, Method, Mime, Url,
},
};
use crate::{Client, HttpError, Request, Response, ResponseAsync, Result};

use futures_util::future::BoxFuture;
use http_types::convert::DeserializeOwned;
use http_types::{
convert::DeserializeOwned,
headers::{HeaderName, ToHeaderValues},
Body, Method, Mime, Url,
};
use serde::Serialize;

use std::{fmt, marker::PhantomData};
Expand All @@ -23,7 +21,7 @@ use std::{fmt, marker::PhantomData};
/// # Examples
///
/// ```no_run
/// use crux_http::http::{mime::HTML};
/// use crux_http::http_types::{mime::HTML};
/// # enum Event { ReceiveResponse(crux_http::Result<crux_http::Response<Vec<u8>>>) }
/// # struct Capabilities { http: crux_http::Http<Event> }
/// # fn update(caps: &Capabilities) {
Expand Down Expand Up @@ -107,7 +105,7 @@ where
/// # Examples
///
/// ```no_run
/// # use crux_http::http::mime;
/// # use crux_http::http_types::mime;
/// # enum Event { ReceiveResponse(crux_http::Result<crux_http::Response<Vec<u8>>>) }
/// # struct Capabilities { http: crux_http::Http<Event> }
/// # fn update(caps: &Capabilities) {
Expand Down Expand Up @@ -137,7 +135,7 @@ where
/// # struct Capabilities { http: crux_http::Http<Event> }
/// # fn update(caps: &Capabilities) {
/// use serde_json::json;
/// use crux_http::http::mime;
/// use crux_http::http_types::mime;
/// caps.http
/// .post("https://httpbin.org/post")
/// .body(json!({"any": "Into<Body>"}))
Expand Down
2 changes: 1 addition & 1 deletion crux_http/src/response/decode.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::http::Error;
use http_types::Error;

use std::fmt;
use std::io;
Expand Down
4 changes: 2 additions & 2 deletions crux_http/src/response/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@ mod response_async;

pub use self::{response::Response, response_async::ResponseAsync};

pub(crate) fn new_headers() -> crate::http::Headers {
pub(crate) fn new_headers() -> http_types::Headers {
// http-types doesn't seem to let you construct a Headers, very annoying.
// So here's a horrible hack to do it.
crate::http::Request::new(crate::http::Method::Get, "https://thisisveryannoying.com")
http_types::Request::new(http_types::Method::Get, "https://thisisveryannoying.com")
.as_ref()
.clone()
}
Loading

0 comments on commit a0af102

Please sign in to comment.