Skip to content

Commit

Permalink
Add reqwest::Response to HTTP related errors
Browse files Browse the repository at this point in the history
  • Loading branch information
jpopesculian committed Oct 4, 2023
1 parent 084ce78 commit 0dbf2df
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 24 deletions.
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "reqwest-eventsource"
version = "0.4.0"
version = "0.5.0"
authors = ["Julian Popescu <[email protected]>"]
edition = "2018"
resolver = "2"
Expand Down
5 changes: 3 additions & 2 deletions src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use eventsource_stream::EventStreamError;
use nom::error::Error as NomError;
use reqwest::header::HeaderValue;
use reqwest::Error as ReqwestError;
use reqwest::Response;
use reqwest::StatusCode;
use std::string::FromUtf8Error;

Expand Down Expand Up @@ -36,10 +37,10 @@ pub enum Error {
Transport(ReqwestError),
/// The `Content-Type` returned by the server is invalid
#[error("Invalid header value: {0:?}")]
InvalidContentType(HeaderValue),
InvalidContentType(HeaderValue, Response),
/// The status code returned by the server is invalid
#[error("Invalid status code: {0}")]
InvalidStatusCode(StatusCode),
InvalidStatusCode(StatusCode, Response),
/// The `Last-Event-ID` cannot be formed into a Header to be submitted to the server
#[error("Invalid `Last-Event-ID`: {0}")]
InvalidLastEventId(String),
Expand Down
55 changes: 34 additions & 21 deletions src/event_source.rs
Original file line number Diff line number Diff line change
Expand Up @@ -115,29 +115,38 @@ impl EventSource {
}
}

fn check_response(response: &Response) -> Result<(), Error> {
fn check_response(response: Response) -> Result<Response, Error> {
match response.status() {
StatusCode::OK => {}
status => {
return Err(Error::InvalidStatusCode(status));
return Err(Error::InvalidStatusCode(status, response));
}
}
let content_type = response
.headers()
.get(&reqwest::header::CONTENT_TYPE)
.ok_or_else(|| Error::InvalidContentType(HeaderValue::from_static("")))?;
let mime_type: mime::Mime = content_type
let content_type =
if let Some(content_type) = response.headers().get(&reqwest::header::CONTENT_TYPE) {
content_type
} else {
return Err(Error::InvalidContentType(
HeaderValue::from_static(""),
response,
));
};
if content_type
.to_str()
.map_err(|_| Error::InvalidContentType(content_type.clone()))?
.parse()
.map_err(|_| Error::InvalidContentType(content_type.clone()))?;
if !matches!(
(mime_type.type_(), mime_type.subtype()),
(mime::TEXT, mime::EVENT_STREAM)
) {
return Err(Error::InvalidContentType(content_type.clone()));
.map_err(|_| ())
.and_then(|s| s.parse::<mime::Mime>().map_err(|_| ()))
.map(|mime_type| {
matches!(
(mime_type.type_(), mime_type.subtype()),
(mime::TEXT, mime::EVENT_STREAM)
)
})
.unwrap_or(false)
{
Ok(response)
} else {
Err(Error::InvalidContentType(content_type.clone(), response))
}
Ok(())
}

impl<'a> EventSourceProjection<'a> {
Expand Down Expand Up @@ -226,12 +235,16 @@ impl Stream for EventSource {
match response_future.poll(cx) {
Poll::Ready(Ok(res)) => {
this.clear_fetch();
if let Err(err) = check_response(&res) {
*this.is_closed = true;
return Poll::Ready(Some(Err(err)));
match check_response(res) {
Ok(res) => {
this.handle_response(res);
return Poll::Ready(Some(Ok(Event::Open)));
}
Err(err) => {
*this.is_closed = true;
return Poll::Ready(Some(Err(err)));
}
}
this.handle_response(res);
return Poll::Ready(Some(Ok(Event::Open)));
}
Poll::Ready(Err(err)) => {
let err = Error::Transport(err);
Expand Down

0 comments on commit 0dbf2df

Please sign in to comment.