Repository navigation
Resolve request host from URI authority when headers are absent #1413
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
01a8c2c
5597ed0
1caedc1
b23cf89
48b8b1b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -40,7 +40,7 @@ pub fn copy_custom_headers(from: &Request<EdgeBody>, to: &mut Request<EdgeBody>) | |||||||||||||||||||||||||
| /// Fastly adapter may first consume an authenticated `fastly-client-ip`, but | ||||||||||||||||||||||||||
| /// removes it before routing along with every other listed header. Stripping | ||||||||||||||||||||||||||
| /// them forces [`RequestInfo::from_request`] to fall back to the trustworthy | ||||||||||||||||||||||||||
| /// `Host` header and [`ClientInfo`] TLS detection. | ||||||||||||||||||||||||||
| /// `Host` header or URI authority and [`ClientInfo`] TLS detection. | ||||||||||||||||||||||||||
| pub const SPOOFABLE_FORWARDED_HEADERS: &[&str] = &[ | ||||||||||||||||||||||||||
| "forwarded", | ||||||||||||||||||||||||||
| "x-forwarded-host", | ||||||||||||||||||||||||||
|
|
@@ -123,23 +123,25 @@ pub fn is_navigation_request(req: &Request<EdgeBody>) -> bool { | |||||||||||||||||||||||||
| /// The parser checks forwarded headers (`Forwarded`, `X-Forwarded-Host`, | ||||||||||||||||||||||||||
| /// `X-Forwarded-Proto`) as fallbacks, but on the Fastly edge | ||||||||||||||||||||||||||
| /// [`sanitize_forwarded_headers`] strips those headers before this method is | ||||||||||||||||||||||||||
| /// called, so the `Host` header and Fastly SDK TLS detection are the effective | ||||||||||||||||||||||||||
| /// sources in production. | ||||||||||||||||||||||||||
| /// called. The `Host` header and Fastly SDK TLS detection are the normal sources | ||||||||||||||||||||||||||
| /// in production. URI authority fills in only when no usable `Host` arrives | ||||||||||||||||||||||||||
| /// (absolute-form HTTP/1.1, or HTTP/2 without `Host`). | ||||||||||||||||||||||||||
| #[derive(Debug, Clone)] | ||||||||||||||||||||||||||
| pub struct RequestInfo { | ||||||||||||||||||||||||||
| /// The effective host for URL rewriting (typically the `Host` header after edge sanitization). | ||||||||||||||||||||||||||
| /// The effective host for URL rewriting (`Host` or URI authority after edge sanitization). | ||||||||||||||||||||||||||
| pub host: String, | ||||||||||||||||||||||||||
| /// The effective scheme (typically from Fastly SDK TLS detection after edge sanitization). | ||||||||||||||||||||||||||
| pub scheme: String, | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| impl RequestInfo { | ||||||||||||||||||||||||||
| /// Extract request info from a Fastly request. | ||||||||||||||||||||||||||
| /// Extract host and scheme information from a request. | ||||||||||||||||||||||||||
| /// | ||||||||||||||||||||||||||
| /// Host fallback order (first present wins): | ||||||||||||||||||||||||||
| /// Host fallback order (first nonempty, valid string wins): | ||||||||||||||||||||||||||
| /// 1. `Forwarded` header (`host=...`) | ||||||||||||||||||||||||||
| /// 2. `X-Forwarded-Host` | ||||||||||||||||||||||||||
| /// 3. `Host` header | ||||||||||||||||||||||||||
| /// 4. Request URI authority (host and port only, excluding userinfo) | ||||||||||||||||||||||||||
| /// | ||||||||||||||||||||||||||
| /// Scheme fallback order: | ||||||||||||||||||||||||||
| /// 1. Fastly SDK TLS detection | ||||||||||||||||||||||||||
|
|
@@ -149,8 +151,9 @@ impl RequestInfo { | |||||||||||||||||||||||||
| /// 5. Default `http` | ||||||||||||||||||||||||||
| /// | ||||||||||||||||||||||||||
| /// In production the forwarded headers are stripped by | ||||||||||||||||||||||||||
| /// [`sanitize_forwarded_headers`] at the edge, so `Host` and | ||||||||||||||||||||||||||
| /// [`ClientInfo`] TLS detection are the only sources that fire. | ||||||||||||||||||||||||||
| /// [`sanitize_forwarded_headers`] at the edge, so `Host` and [`ClientInfo`] | ||||||||||||||||||||||||||
| /// TLS detection are the normal sources. URI authority is a fallback for | ||||||||||||||||||||||||||
| /// absolute-form HTTP/1.1 or HTTP/2 requests without a usable `Host`. | ||||||||||||||||||||||||||
| pub fn from_request(req: &Request<EdgeBody>, client_info: &ClientInfo) -> Self { | ||||||||||||||||||||||||||
| let host = extract_request_host(req); | ||||||||||||||||||||||||||
| let scheme = detect_request_scheme( | ||||||||||||||||||||||||||
|
|
@@ -178,6 +181,17 @@ fn extract_request_host(req: &Request<EdgeBody>) -> String { | |||||||||||||||||||||||||
| req.headers() | ||||||||||||||||||||||||||
| .get(header::HOST) | ||||||||||||||||||||||||||
| .and_then(|h| h.to_str().ok()) | ||||||||||||||||||||||||||
| .filter(|host| !host.is_empty()) | ||||||||||||||||||||||||||
| }) | ||||||||||||||||||||||||||
| .or_else(|| { | ||||||||||||||||||||||||||
| // Absolute-form HTTP/1.1 and HTTP/2 may carry the host only in the URI. | ||||||||||||||||||||||||||
| // Drop userinfo so credentials never reach rewritten URLs. | ||||||||||||||||||||||||||
| req.uri().authority().map(|authority| { | ||||||||||||||||||||||||||
| let authority = authority.as_str(); | ||||||||||||||||||||||||||
| authority | ||||||||||||||||||||||||||
| .rsplit_once('@') | ||||||||||||||||||||||||||
| .map_or(authority, |(_, host_and_port)| host_and_port) | ||||||||||||||||||||||||||
| }) | ||||||||||||||||||||||||||
| }) | ||||||||||||||||||||||||||
| .unwrap_or_default() | ||||||||||||||||||||||||||
| .to_owned() | ||||||||||||||||||||||||||
|
|
@@ -572,6 +586,94 @@ mod tests { | |||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| // RequestInfo tests | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| #[test] | ||||||||||||||||||||||||||
| fn request_info_uses_uri_authority_without_host_headers() { | ||||||||||||||||||||||||||
| for (uri, expected_host) in [ | ||||||||||||||||||||||||||
| ( | ||||||||||||||||||||||||||
| "https://publisher.example.com/page", | ||||||||||||||||||||||||||
| "publisher.example.com", | ||||||||||||||||||||||||||
| ), | ||||||||||||||||||||||||||
| ( | ||||||||||||||||||||||||||
| "https://publisher.example.com:8443/page", | ||||||||||||||||||||||||||
| "publisher.example.com:8443", | ||||||||||||||||||||||||||
| ), | ||||||||||||||||||||||||||
| ("https://[2001:db8::1]:8443/page", "[2001:db8::1]:8443"), | ||||||||||||||||||||||||||
| ( | ||||||||||||||||||||||||||
| "https://user:secret@publisher.example.com/page", | ||||||||||||||||||||||||||
| "publisher.example.com", | ||||||||||||||||||||||||||
| ), | ||||||||||||||||||||||||||
| ( | ||||||||||||||||||||||||||
| "https://user:pass@publisher.example.com:8443/page", | ||||||||||||||||||||||||||
| "publisher.example.com:8443", | ||||||||||||||||||||||||||
| ), | ||||||||||||||||||||||||||
| ( | ||||||||||||||||||||||||||
| "https://user:pass@[2001:db8::1]:8443/page", | ||||||||||||||||||||||||||
| "[2001:db8::1]:8443", | ||||||||||||||||||||||||||
| ), | ||||||||||||||||||||||||||
|
Comment on lines
+609
to
+612
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ⛏ nitpick: Pin The http crate accepts an authority like
Suggested change
Verified on this head:
|
||||||||||||||||||||||||||
| ] { | ||||||||||||||||||||||||||
| let req = Request::builder() | ||||||||||||||||||||||||||
| .version(http::Version::HTTP_2) | ||||||||||||||||||||||||||
| .uri(uri) | ||||||||||||||||||||||||||
| .body(EdgeBody::empty()) | ||||||||||||||||||||||||||
| .expect("should build authority-only HTTP/2 request"); | ||||||||||||||||||||||||||
| assert!(req.headers().is_empty(), "should have no host headers"); | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| let info = RequestInfo::from_request(&req, &default_client_info()); | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| assert_eq!( | ||||||||||||||||||||||||||
| info.host, expected_host, | ||||||||||||||||||||||||||
| "should use only the host and port, preserving IPv6 brackets" | ||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| #[test] | ||||||||||||||||||||||||||
| fn request_info_preserves_host_header_precedence_over_uri_authority() { | ||||||||||||||||||||||||||
| for (headers, expected_host) in [ | ||||||||||||||||||||||||||
| (vec![("host", "header.example.com")], "header.example.com"), | ||||||||||||||||||||||||||
| (vec![("host", "")], "authority.example.com"), | ||||||||||||||||||||||||||
| ( | ||||||||||||||||||||||||||
| vec![ | ||||||||||||||||||||||||||
| ("host", "header.example.com"), | ||||||||||||||||||||||||||
| ("x-forwarded-host", "proxy.example.com"), | ||||||||||||||||||||||||||
| ], | ||||||||||||||||||||||||||
| "proxy.example.com", | ||||||||||||||||||||||||||
| ), | ||||||||||||||||||||||||||
| ( | ||||||||||||||||||||||||||
| vec![ | ||||||||||||||||||||||||||
| ("host", "header.example.com"), | ||||||||||||||||||||||||||
| ("x-forwarded-host", "proxy.example.com"), | ||||||||||||||||||||||||||
| ("forwarded", "host=public.example.com"), | ||||||||||||||||||||||||||
| ], | ||||||||||||||||||||||||||
| "public.example.com", | ||||||||||||||||||||||||||
| ), | ||||||||||||||||||||||||||
| ] { | ||||||||||||||||||||||||||
| let mut req = build_request(Method::GET, "https://authority.example.com/page"); | ||||||||||||||||||||||||||
| for (name, value) in headers { | ||||||||||||||||||||||||||
| set_header(&mut req, name, value); | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| let info = RequestInfo::from_request(&req, &default_client_info()); | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| assert_eq!( | ||||||||||||||||||||||||||
| info.host, expected_host, | ||||||||||||||||||||||||||
| "should preserve forwarded and explicit host precedence over URI authority" | ||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| #[test] | ||||||||||||||||||||||||||
| fn request_info_keeps_empty_host_without_headers_or_uri_authority() { | ||||||||||||||||||||||||||
| let req = build_request(Method::GET, "/page"); | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| let info = RequestInfo::from_request(&req, &default_client_info()); | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| assert!( | ||||||||||||||||||||||||||
| info.host.is_empty(), | ||||||||||||||||||||||||||
| "should keep the host empty when no host source is available" | ||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| #[test] | ||||||||||||||||||||||||||
| fn test_request_info_from_host_header() { | ||||||||||||||||||||||||||
| let mut req = build_request(Method::GET, "https://test.example.com/page"); | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -4449,17 +4449,22 @@ pub async fn handle_publisher_request( | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Prebid.js requests are not intercepted here anymore. The HTML processor removes | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // publisher-supplied Prebid scripts; the unified TSJS bundle includes Prebid.js when enabled. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Extract request host and scheme (uses Host header and TLS detection after edge sanitization) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Extract request host and scheme using Host or URI authority and TLS | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // detection after edge sanitization. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| let request_info = RequestInfo::from_request(&req, services.client_info()); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| let request_host = &request_info.host; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| let request_scheme = &request_info.scheme; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| log::debug!( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "Request info: host={}, scheme={} (X-Forwarded-Host: {:?}, Host: {:?}, X-Forwarded-Proto: {:?})", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "Request info: host={}, scheme={} (X-Forwarded-Host: {:?}, Host: {:?}, URI host: {:?}, URI port: {:?}, X-Forwarded-Proto: {:?})", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| request_host, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| request_scheme, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| req.headers().get("x-forwarded-host"), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| req.headers().get(header::HOST), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| req.uri().authority().map(http::uri::Authority::host), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| req.uri() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .authority() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .and_then(http::uri::Authority::port_u16), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| req.headers().get("x-forwarded-proto"), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -19732,6 +19737,81 @@ mod tests { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| #[tokio::test] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| async fn publisher_request_rewrites_html_using_uri_authority() { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| for version in [http::Version::HTTP_11, http::Version::HTTP_2] { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| for (uri, empty_host) in [ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ("https://publisher.example.com:8443/page", false), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ("https://user:pass@publisher.example.com:8443/page", false), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ("https://publisher.example.com:8443/page", true), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ] { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| let mut settings = create_test_settings(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| settings.publisher.origin_url = "https://origin.example.com".to_owned(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| let registry = IntegrationRegistry::new(&settings) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .expect("should create integration registry"); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| let stub = Arc::new(StubHttpClient::new()); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| stub.push_response_with_headers( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 200, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| b"<html><head></head><body><a href=\"https://origin.example.com/article\">Article</a></body></html>".to_vec(), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| vec![("content-type", "text/html; charset=utf-8")], | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| let services = build_services_with_http_client( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Arc::clone(&stub) as Arc<dyn crate::platform::PlatformHttpClient> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| let mut req = HttpRequest::builder() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .version(version) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .uri(uri) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .header("x-forwarded-proto", "https") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .header("sec-fetch-dest", "document") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .body(EdgeBody::empty()) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .expect("should build authority-only publisher request"); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if empty_host { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| req.headers_mut() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .insert(header::HOST, HeaderValue::from_static("")); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| for name in ["forwarded", "x-forwarded-host"] { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| assert!( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| !req.headers().contains_key(name), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "should have no {name} header" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| assert!( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| req.headers() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .get(header::HOST) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .is_none_or(HeaderValue::is_empty), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "should have no nonempty Host header" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| let publisher_response = run_publisher_proxy(&settings, &services, req).await; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| let response = buffer_publisher_response_async( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| publisher_response, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| &Method::GET, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| &settings, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ®istry, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| &AuctionOrchestrator::new(settings.auction.clone()), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| &services, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .await | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .expect("should buffer processed publisher response"); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| let html = response_body_string(response); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| assert!( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| html.contains("href=\"https://publisher.example.com:8443/article\""), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "should rewrite origin links using URI authority: {html}" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| assert!( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| !html.contains("user:pass@"), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "should omit URI userinfo from rewritten HTML: {html}" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| assert!( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| html.contains("id=\"trustedserver-js\""), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "should inject the Trusted Server script: {html}" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+19797
to
+19810
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ⛏ nitpick: Name the failing case in the loop's assertions. The loop covers six cases: two HTTP versions, each with a plain authority, userinfo and an empty
Suggested change
Verified on this head:
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| #[tokio::test] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| async fn publisher_request_sends_configured_host_header_override() { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| let mut settings = create_test_settings(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Uh oh!
There was an error while loading. Please reload this page.