Rename transport binding to WIP over HTTP
This commit is contained in:
@@ -0,0 +1,142 @@
|
||||
use wip_http::http::{Method, Request, StatusCode};
|
||||
use wip_http::{Endpoint, RequestMetadataError, Route, validate_http_request};
|
||||
|
||||
#[test]
|
||||
fn endpoint_preserves_http_and_https_when_resolving_canonical_routes() {
|
||||
for scheme in ["http", "https"] {
|
||||
let endpoint = Endpoint::parse(&format!("{scheme}://example.test/root/prefix")).unwrap();
|
||||
assert_eq!(
|
||||
endpoint.to_string(),
|
||||
format!("{scheme}://example.test/root/prefix/")
|
||||
);
|
||||
|
||||
let expected = [
|
||||
(Route::Observe, "v1/observe"),
|
||||
(Route::FetchInterface, "v1/fetch_interface"),
|
||||
(Route::CallOperation, "v1/call_operation"),
|
||||
(Route::Batch, "v1/batch"),
|
||||
];
|
||||
for (route, suffix) in expected {
|
||||
let url = format!("{scheme}://example.test/root/prefix/{suffix}");
|
||||
assert_eq!(endpoint.route(route).as_str(), url);
|
||||
assert_eq!(
|
||||
endpoint.recognize(&wip_http::url::Url::parse(&url).unwrap()),
|
||||
Some(route)
|
||||
);
|
||||
}
|
||||
assert_eq!(
|
||||
endpoint.recognize(
|
||||
&wip_http::url::Url::parse(&format!(
|
||||
"{scheme}://example.test/root/prefix/v1/observe?path=/items"
|
||||
))
|
||||
.unwrap()
|
||||
),
|
||||
None
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn routes_never_mix_worldspace_paths_into_endpoint_prefixes() {
|
||||
let endpoint = Endpoint::parse("https://example.test/wip/%E4%B8%96%E7%95%8C/").unwrap();
|
||||
let route = endpoint.route(Route::Observe);
|
||||
assert_eq!(route.path(), "/wip/%E4%B8%96%E7%95%8C/v1/observe");
|
||||
assert!(!route.as_str().contains("items"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn inbound_http_metadata_enforces_post_route_and_json() {
|
||||
let endpoint = Endpoint::parse("https://example.test/wip").unwrap();
|
||||
let valid = Request::builder()
|
||||
.method(Method::POST)
|
||||
.uri("/wip/v1/observe")
|
||||
.header("content-type", "application/json; charset=utf-8")
|
||||
.body(Vec::<u8>::new())
|
||||
.unwrap();
|
||||
assert!(validate_http_request(&endpoint, Route::Observe, &valid).is_ok());
|
||||
|
||||
let wrong_method = Request::builder()
|
||||
.method(Method::GET)
|
||||
.uri("/wip/v1/observe")
|
||||
.header("content-type", "application/json")
|
||||
.body(Vec::<u8>::new())
|
||||
.unwrap();
|
||||
assert!(validate_http_request(&endpoint, Route::Observe, &wrong_method).is_err());
|
||||
|
||||
let wrong_route = Request::builder()
|
||||
.method(Method::POST)
|
||||
.uri("/wip/v1/fetch_interface")
|
||||
.header("content-type", "application/json")
|
||||
.body(Vec::<u8>::new())
|
||||
.unwrap();
|
||||
assert!(validate_http_request(&endpoint, Route::Observe, &wrong_route).is_err());
|
||||
|
||||
for accept in [
|
||||
"text/plain, */*;q=1, application/json;q=0",
|
||||
"application/json; charset=utf-16",
|
||||
"application/json; profile=future",
|
||||
] {
|
||||
let incompatible_accept = Request::builder()
|
||||
.method(Method::POST)
|
||||
.uri("/wip/v1/observe")
|
||||
.header("content-type", "application/json")
|
||||
.header("accept", accept)
|
||||
.body(Vec::<u8>::new())
|
||||
.unwrap();
|
||||
let error =
|
||||
validate_http_request(&endpoint, Route::Observe, &incompatible_accept).unwrap_err();
|
||||
assert!(matches!(&error, RequestMetadataError::NotAcceptable));
|
||||
assert_eq!(error.status(), StatusCode::NOT_ACCEPTABLE);
|
||||
}
|
||||
|
||||
for accept in [
|
||||
"application/json; charset=UTF-8",
|
||||
"application/json; q=1; profile=accept-extension",
|
||||
] {
|
||||
let compatible_accept = Request::builder()
|
||||
.method(Method::POST)
|
||||
.uri("/wip/v1/observe")
|
||||
.header("content-type", "application/json")
|
||||
.header("accept", accept)
|
||||
.body(Vec::<u8>::new())
|
||||
.unwrap();
|
||||
assert!(validate_http_request(&endpoint, Route::Observe, &compatible_accept).is_ok());
|
||||
}
|
||||
|
||||
let unsupported_media_type = Request::builder()
|
||||
.method(Method::POST)
|
||||
.uri("/wip/v1/observe")
|
||||
.header("content-type", "text/plain")
|
||||
.header("accept", "application/json")
|
||||
.body(Vec::<u8>::new())
|
||||
.unwrap();
|
||||
let error =
|
||||
validate_http_request(&endpoint, Route::Observe, &unsupported_media_type).unwrap_err();
|
||||
assert!(matches!(&error, RequestMetadataError::UnsupportedMediaType));
|
||||
assert_eq!(error.status(), StatusCode::UNSUPPORTED_MEDIA_TYPE);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn invalid_endpoint_components_and_non_routes_are_rejected() {
|
||||
assert!(Endpoint::parse("/relative").is_err());
|
||||
assert!(Endpoint::parse("file:///wip").is_err());
|
||||
assert!(Endpoint::parse("https://example.test/wip?q=1").is_err());
|
||||
assert!(Endpoint::parse("https://example.test/wip#fragment").is_err());
|
||||
|
||||
let deployment_endpoint = Endpoint::parse("http://user:secret@example.test/wip").unwrap();
|
||||
assert_eq!(deployment_endpoint.as_url().scheme(), "http");
|
||||
assert_eq!(deployment_endpoint.as_url().username(), "user");
|
||||
|
||||
let endpoint = Endpoint::parse("http://example.test/wip").unwrap();
|
||||
for outside in [
|
||||
"http://example.test/wip/v1/unknown",
|
||||
"http://example.test/wip/v1/observe/extra",
|
||||
"https://example.test/wip/v1/observe",
|
||||
"http://other.test/wip/v1/observe",
|
||||
] {
|
||||
assert_eq!(
|
||||
endpoint.recognize(&wip_http::url::Url::parse(outside).unwrap()),
|
||||
None
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user