Skip to content

Commit

Permalink
Merge pull request #181 from lipanski/into-header-name
Browse files Browse the repository at this point in the history
Introduce a local IntoHeaderName trait to avoid exposing hyper::header::HeaderName
  • Loading branch information
lipanski committed Nov 1, 2023
2 parents 9dae3ce + d2f5065 commit 5e57b0d
Show file tree
Hide file tree
Showing 4 changed files with 50 additions and 6 deletions.
3 changes: 3 additions & 0 deletions src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,8 @@ pub enum ErrorKind {
ResponseBodyFailure,
/// File not found
FileNotFound,
/// Invalid header name
InvalidHeaderName,
}

impl ErrorKind {
Expand All @@ -75,6 +77,7 @@ impl ErrorKind {
ErrorKind::RequestBodyFailure => "failed to read the request body",
ErrorKind::ResponseBodyFailure => "failed to write the response body",
ErrorKind::FileNotFound => "file not found",
ErrorKind::InvalidHeaderName => "invalid header name",
}
}
}
2 changes: 1 addition & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -672,7 +672,7 @@
pub use error::{Error, ErrorKind};
#[allow(deprecated)]
pub use matcher::Matcher;
pub use mock::Mock;
pub use mock::{IntoHeaderName, Mock};
pub use request::Request;
pub use server::Server;
pub use server_pool::ServerGuard;
Expand Down
48 changes: 45 additions & 3 deletions src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use crate::server::RemoteMock;
use crate::server::State;
use crate::Request;
use crate::{Error, ErrorKind};
use hyper::header::IntoHeaderName;
use hyper::header::HeaderName;
use hyper::HeaderMap;
use hyper::StatusCode;
use rand::distributions::Alphanumeric;
Expand All @@ -19,6 +19,42 @@ use std::string::ToString;
use std::sync::Arc;
use std::sync::RwLock;

#[allow(missing_docs)]
pub trait IntoHeaderName {
#[track_caller]
fn into_header_name(self) -> HeaderName;
}

impl IntoHeaderName for String {
fn into_header_name(self) -> HeaderName {
HeaderName::try_from(self)
.map_err(|_| Error::new(ErrorKind::InvalidHeaderName))
.unwrap()
}
}

impl IntoHeaderName for &String {
fn into_header_name(self) -> HeaderName {
HeaderName::try_from(self)
.map_err(|_| Error::new(ErrorKind::InvalidHeaderName))
.unwrap()
}
}

impl IntoHeaderName for &str {
fn into_header_name(self) -> HeaderName {
HeaderName::try_from(self)
.map_err(|_| Error::new(ErrorKind::InvalidHeaderName))
.unwrap()
}
}

impl IntoHeaderName for HeaderName {
fn into_header_name(self) -> HeaderName {
self
}
}

#[derive(Clone, Debug)]
pub struct InnerMock {
pub(crate) id: String,
Expand Down Expand Up @@ -202,8 +238,11 @@ impl Mock {
/// .match_header("authorization", "password");
/// ```
///
#[track_caller]
pub fn match_header<T: IntoHeaderName, M: Into<Matcher>>(mut self, field: T, value: M) -> Self {
self.inner.headers.append(field, value.into());
self.inner
.headers
.append(field.into_header_name(), value.into());

self
}
Expand Down Expand Up @@ -284,7 +323,10 @@ impl Mock {
/// ```
///
pub fn with_header<T: IntoHeaderName>(mut self, field: T, value: &str) -> Self {
self.inner.response.headers.append(field, value.to_owned());
self.inner
.response
.headers
.append(field.into_header_name(), value.to_owned());

self
}
Expand Down
3 changes: 1 addition & 2 deletions tests/lib.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
#[macro_use]
extern crate serde_json;

use hyper::header::HeaderName;
use mockito::{Matcher, Server};
use rand::distributions::Alphanumeric;
use rand::Rng;
Expand Down Expand Up @@ -700,7 +699,7 @@ fn test_mock_preserves_header_order() {

// Add a large number of headers so getting the same order accidentally is unlikely.
for i in 0..100 {
let field: HeaderName = format!("x-custom-header-{}", i).try_into().unwrap();
let field = format!("x-custom-header-{}", i);
let value = "test";
mock = mock.with_header(&field, value);
expected_headers.push(format!("{}: {}", field, value));
Expand Down

0 comments on commit 5e57b0d

Please sign in to comment.