mirror of
https://github.com/servo/servo.git
synced 2025-08-09 23:45:35 +01:00
Replace NetworkError::Internal with structured enum variants
Signed-off-by: Uthman Yahaya Baba <uthmanyahayababa@gmail.com>
This commit is contained in:
parent
0eec22303b
commit
fe4e90d7dc
10 changed files with 55 additions and 106 deletions
|
@ -227,9 +227,7 @@ pub async fn main_fetch(
|
|||
"about" | "blob" | "data" | "filesystem"
|
||||
)
|
||||
{
|
||||
response = Some(Response::network_error(NetworkError::Internal(
|
||||
"Non-local scheme".into(),
|
||||
)));
|
||||
response = Some(Response::network_error(NetworkError::UnsupportedScheme));
|
||||
}
|
||||
|
||||
// Step 2.2.
|
||||
|
@ -285,19 +283,13 @@ pub async fn main_fetch(
|
|||
|
||||
if check_result == csp::CheckResult::Blocked {
|
||||
warn!("Request blocked by CSP");
|
||||
response = Some(Response::network_error(NetworkError::Internal(
|
||||
"Blocked by Content-Security-Policy".into(),
|
||||
)))
|
||||
response = Some(Response::network_error(NetworkError::SecurityBlock))
|
||||
}
|
||||
if should_request_be_blocked_due_to_a_bad_port(&request.current_url()) {
|
||||
response = Some(Response::network_error(NetworkError::Internal(
|
||||
"Request attempted on bad port".into(),
|
||||
)));
|
||||
response = Some(Response::network_error(NetworkError::InvalidPort));
|
||||
}
|
||||
if should_request_be_blocked_as_mixed_content(request) {
|
||||
response = Some(Response::network_error(NetworkError::Internal(
|
||||
"Blocked as mixed content".into(),
|
||||
)));
|
||||
response = Some(Response::network_error(NetworkError::MixedContent));
|
||||
}
|
||||
|
||||
// Step 8: If request’s referrer policy is the empty string, then set request’s referrer policy
|
||||
|
@ -371,13 +363,11 @@ pub async fn main_fetch(
|
|||
// Substep 2. Return the result of running scheme fetch given fetchParams.
|
||||
scheme_fetch(fetch_params, cache, target, done_chan, context).await
|
||||
} else if request.mode == RequestMode::SameOrigin {
|
||||
Response::network_error(NetworkError::Internal("Cross-origin response".into()))
|
||||
Response::network_error(NetworkError::CorsViolation)
|
||||
} else if request.mode == RequestMode::NoCors {
|
||||
// Substep 1. If request’s redirect mode is not "follow", then return a network error.
|
||||
if request.redirect_mode != RedirectMode::Follow {
|
||||
Response::network_error(NetworkError::Internal(
|
||||
"NoCors requests must follow redirects".into(),
|
||||
))
|
||||
Response::network_error(NetworkError::CorsViolation)
|
||||
} else {
|
||||
// Substep 2. Set request’s response tainting to "opaque".
|
||||
request.response_tainting = ResponseTainting::Opaque;
|
||||
|
@ -386,7 +376,7 @@ pub async fn main_fetch(
|
|||
scheme_fetch(fetch_params, cache, target, done_chan, context).await
|
||||
}
|
||||
} else if !matches!(current_scheme, "http" | "https") {
|
||||
Response::network_error(NetworkError::Internal("Non-http scheme".into()))
|
||||
Response::network_error(NetworkError::UnsupportedScheme)
|
||||
} else if request.use_cors_preflight ||
|
||||
(request.unsafe_request &&
|
||||
(!is_cors_safelisted_method(&request.method) ||
|
||||
|
@ -521,17 +511,14 @@ pub async fn main_fetch(
|
|||
|
||||
let internal_response = if should_replace_with_nosniff_error {
|
||||
// Defer rebinding result
|
||||
blocked_error_response =
|
||||
Response::network_error(NetworkError::Internal("Blocked by nosniff".into()));
|
||||
blocked_error_response = Response::network_error(NetworkError::SecurityBlock);
|
||||
&blocked_error_response
|
||||
} else if should_replace_with_mime_type_error {
|
||||
// Defer rebinding result
|
||||
blocked_error_response =
|
||||
Response::network_error(NetworkError::Internal("Blocked by mime type".into()));
|
||||
blocked_error_response = Response::network_error(NetworkError::SecurityBlock);
|
||||
&blocked_error_response
|
||||
} else if should_replace_with_mixed_content {
|
||||
blocked_error_response =
|
||||
Response::network_error(NetworkError::Internal("Blocked as mixed content".into()));
|
||||
blocked_error_response = Response::network_error(NetworkError::MixedContent);
|
||||
&blocked_error_response
|
||||
} else {
|
||||
internal_response
|
||||
|
@ -549,9 +536,7 @@ pub async fn main_fetch(
|
|||
!request.headers.contains_key(RANGE)
|
||||
{
|
||||
// Defer rebinding result
|
||||
blocked_error_response = Response::network_error(NetworkError::Internal(
|
||||
PARTIAL_RESPONSE_TO_NON_RANGE_REQUEST_ERROR.into(),
|
||||
));
|
||||
blocked_error_response = Response::network_error(NetworkError::CacheError);
|
||||
&blocked_error_response
|
||||
} else {
|
||||
internal_response
|
||||
|
@ -594,9 +579,7 @@ pub async fn main_fetch(
|
|||
if response.termination_reason.is_none() &&
|
||||
!is_response_integrity_valid(integrity_metadata, &response)
|
||||
{
|
||||
Response::network_error(NetworkError::Internal(
|
||||
"Subresource integrity validation failed".into(),
|
||||
))
|
||||
Response::network_error(NetworkError::SecurityBlock)
|
||||
} else {
|
||||
response
|
||||
}
|
||||
|
@ -821,7 +804,7 @@ async fn scheme_fetch(
|
|||
|
||||
_ => match context.protocols.get(scheme) {
|
||||
Some(handler) => handler.load(request, done_chan, context).await,
|
||||
None => Response::network_error(NetworkError::Internal("Unexpected scheme".into())),
|
||||
None => Response::network_error(NetworkError::UnsupportedScheme),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
|
@ -787,7 +787,7 @@ pub async fn http_fetch(
|
|||
(res.url_list.len() > 1 && request.redirect_mode != RedirectMode::Follow) ||
|
||||
res.is_network_error()
|
||||
{
|
||||
return Response::network_error(NetworkError::Internal("Request failed".into()));
|
||||
return Response::network_error(NetworkError::ConnectionFailure);
|
||||
}
|
||||
|
||||
// Subsubstep 4
|
||||
|
@ -843,7 +843,7 @@ pub async fn http_fetch(
|
|||
|
||||
// Substep 4
|
||||
if cors_flag && cors_check(&fetch_params.request, &fetch_result).is_err() {
|
||||
return Response::network_error(NetworkError::Internal("CORS check failed".into()));
|
||||
return Response::network_error(NetworkError::CorsViolation);
|
||||
}
|
||||
|
||||
fetch_result.return_internal = false;
|
||||
|
@ -894,9 +894,7 @@ pub async fn http_fetch(
|
|||
|
||||
// Substep 5.
|
||||
response = match request.redirect_mode {
|
||||
RedirectMode::Error => {
|
||||
Response::network_error(NetworkError::Internal("Redirect mode error".into()))
|
||||
},
|
||||
RedirectMode::Error => Response::network_error(NetworkError::RedirectError),
|
||||
RedirectMode::Manual => response.to_filtered(ResponseType::OpaqueRedirect),
|
||||
RedirectMode::Follow => {
|
||||
// set back to default
|
||||
|
@ -982,9 +980,7 @@ pub async fn http_redirect_fetch(
|
|||
},
|
||||
// Step 4
|
||||
Some(Ok(ref url)) if !matches!(url.scheme(), "http" | "https") => {
|
||||
return Response::network_error(NetworkError::Internal(
|
||||
"Location URL not an HTTP(S) scheme".into(),
|
||||
));
|
||||
return Response::network_error(NetworkError::UnsupportedScheme);
|
||||
},
|
||||
Some(Ok(url)) => url,
|
||||
};
|
||||
|
@ -1022,7 +1018,7 @@ pub async fn http_redirect_fetch(
|
|||
|
||||
// Step 7: If request’s redirect count is 20, then return a network error.
|
||||
if request.redirect_count >= 20 {
|
||||
return Response::network_error(NetworkError::Internal("Too many redirects".into()));
|
||||
return Response::network_error(NetworkError::RedirectError);
|
||||
}
|
||||
|
||||
// Step 8: Increase request’s redirect count by 1.
|
||||
|
@ -1040,9 +1036,7 @@ pub async fn http_redirect_fetch(
|
|||
let has_credentials = has_credentials(&location_url);
|
||||
|
||||
if request.mode == RequestMode::CorsMode && !same_origin && has_credentials {
|
||||
return Response::network_error(NetworkError::Internal(
|
||||
"Cross-origin credentials check failed".into(),
|
||||
));
|
||||
return Response::network_error(NetworkError::CorsViolation);
|
||||
}
|
||||
|
||||
// Step 9
|
||||
|
@ -1052,7 +1046,7 @@ pub async fn http_redirect_fetch(
|
|||
|
||||
// Step 10
|
||||
if cors_flag && has_credentials {
|
||||
return Response::network_error(NetworkError::Internal("Credentials check failed".into()));
|
||||
return Response::network_error(NetworkError::CorsViolation);
|
||||
}
|
||||
|
||||
// Step 11: If internalResponse’s status is not 303, request’s body is non-null, and request’s
|
||||
|
@ -1060,7 +1054,7 @@ pub async fn http_redirect_fetch(
|
|||
if response.actual_response().status != StatusCode::SEE_OTHER &&
|
||||
request.body.as_ref().is_some_and(|b| b.source_is_null())
|
||||
{
|
||||
return Response::network_error(NetworkError::Internal("Request body is not done".into()));
|
||||
return Response::network_error(NetworkError::ConnectionFailure);
|
||||
}
|
||||
|
||||
// Step 12
|
||||
|
@ -1549,9 +1543,7 @@ async fn http_network_or_cache_fetch(
|
|||
// The cache will not be updated,
|
||||
// set its state to ready to construct.
|
||||
update_http_cache_state(context, http_request);
|
||||
return Response::network_error(NetworkError::Internal(
|
||||
"Couldn't find response in cache".into(),
|
||||
));
|
||||
return Response::network_error(NetworkError::CacheError);
|
||||
}
|
||||
|
||||
// Step 10.2 Let forwardResponse be the result of running HTTP-network fetch given httpFetchParams,
|
||||
|
@ -1609,9 +1601,7 @@ async fn http_network_or_cache_fetch(
|
|||
cross_origin_resource_policy_check(http_request, &response) ==
|
||||
CrossOriginResourcePolicy::Blocked
|
||||
{
|
||||
return Response::network_error(NetworkError::Internal(
|
||||
"Cross-origin resource policy check failed".into(),
|
||||
));
|
||||
return Response::network_error(NetworkError::CorsViolation);
|
||||
}
|
||||
|
||||
// TODO(#33616): Step 11. Set response’s URL list to a clone of httpRequest’s URL list.
|
||||
|
@ -1682,9 +1672,7 @@ async fn http_network_or_cache_fetch(
|
|||
// Step 15.1 If request’s window is "no-window", then return a network error.
|
||||
|
||||
if request_has_no_window {
|
||||
return Response::network_error(NetworkError::Internal(
|
||||
"Can't find Window object".into(),
|
||||
));
|
||||
return Response::network_error(NetworkError::ResourceError);
|
||||
}
|
||||
|
||||
// (Step 15.2 does not exist, requires testing on Proxy-Authenticate headers)
|
||||
|
@ -1913,9 +1901,7 @@ async fn http_network_fetch(
|
|||
//
|
||||
match fetch_terminated_receiver.recv().await {
|
||||
Some(true) => {
|
||||
return Response::network_error(NetworkError::Internal(
|
||||
"Request body streaming failed.".into(),
|
||||
));
|
||||
return Response::network_error(NetworkError::ConnectionFailure);
|
||||
},
|
||||
Some(false) => {},
|
||||
_ => warn!("Failed to receive confirmation request was streamed without error."),
|
||||
|
@ -1984,7 +1970,7 @@ async fn http_network_fetch(
|
|||
let meta_headers = meta.headers;
|
||||
let cancellation_listener = context.cancellation_listener.clone();
|
||||
if cancellation_listener.cancelled() {
|
||||
return Response::network_error(NetworkError::Internal("Fetch aborted".into()));
|
||||
return Response::network_error(NetworkError::ConnectionFailure);
|
||||
}
|
||||
|
||||
*res_body.lock().unwrap() = ResponseBody::Receiving(vec![]);
|
||||
|
@ -2183,9 +2169,7 @@ async fn cors_preflight_fetch(
|
|||
Some(methods) => methods.iter().collect(),
|
||||
// Substep 3
|
||||
None => {
|
||||
return Response::network_error(NetworkError::Internal(
|
||||
"CORS ACAM check failed".into(),
|
||||
));
|
||||
return Response::network_error(NetworkError::CorsViolation);
|
||||
},
|
||||
}
|
||||
} else {
|
||||
|
@ -2201,9 +2185,7 @@ async fn cors_preflight_fetch(
|
|||
Some(names) => names.iter().collect(),
|
||||
// Substep 3
|
||||
None => {
|
||||
return Response::network_error(NetworkError::Internal(
|
||||
"CORS ACAH check failed".into(),
|
||||
));
|
||||
return Response::network_error(NetworkError::CorsViolation);
|
||||
},
|
||||
}
|
||||
} else {
|
||||
|
@ -2228,9 +2210,7 @@ async fn cors_preflight_fetch(
|
|||
(request.credentials_mode == CredentialsMode::Include ||
|
||||
methods.iter().all(|m| m.as_ref() != "*"))
|
||||
{
|
||||
return Response::network_error(NetworkError::Internal(
|
||||
"CORS method check failed".into(),
|
||||
));
|
||||
return Response::network_error(NetworkError::CorsViolation);
|
||||
}
|
||||
|
||||
debug!(
|
||||
|
@ -2243,9 +2223,7 @@ async fn cors_preflight_fetch(
|
|||
is_cors_non_wildcard_request_header_name(name) &&
|
||||
header_names.iter().all(|hn| hn != name)
|
||||
}) {
|
||||
return Response::network_error(NetworkError::Internal(
|
||||
"CORS authorization check failed".into(),
|
||||
));
|
||||
return Response::network_error(NetworkError::CorsViolation);
|
||||
}
|
||||
|
||||
// Substep 7
|
||||
|
@ -2258,9 +2236,7 @@ async fn cors_preflight_fetch(
|
|||
(request.credentials_mode == CredentialsMode::Include ||
|
||||
!header_names_contains_star)
|
||||
{
|
||||
return Response::network_error(NetworkError::Internal(
|
||||
"CORS headers check failed".into(),
|
||||
));
|
||||
return Response::network_error(NetworkError::CorsViolation);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2290,7 +2266,7 @@ async fn cors_preflight_fetch(
|
|||
}
|
||||
|
||||
// Step 8
|
||||
Response::network_error(NetworkError::Internal("CORS check failed".into()))
|
||||
Response::network_error(NetworkError::CorsViolation)
|
||||
}
|
||||
|
||||
/// [CORS check](https://fetch.spec.whatwg.org#concept-cors-check)
|
||||
|
|
|
@ -19,18 +19,14 @@ pub fn fetch(request: &mut Request, url: ServoUrl, path_buf: PathBuf) -> Respons
|
|||
if !pref!(network_local_directory_listing_enabled) {
|
||||
// If you want to be able to browse local directories, configure Servo prefs so that
|
||||
// "network.local_directory_listing.enabled" is set to true.
|
||||
return Response::network_error(NetworkError::Internal(
|
||||
"Local directory listing feature has not been enabled in preferences".into(),
|
||||
));
|
||||
return Response::network_error(NetworkError::LocalDirectoryError);
|
||||
}
|
||||
|
||||
if !request.origin.is_opaque() {
|
||||
// Checking for an opaque origin as a shorthand for user activation
|
||||
// as opposed to a request originating from a script.
|
||||
// TODO(32534): carefully consider security of this approach.
|
||||
return Response::network_error(NetworkError::Internal(
|
||||
"Cannot request local directory listing from non-local origin.".into(),
|
||||
));
|
||||
return Response::network_error(NetworkError::LocalDirectoryError);
|
||||
}
|
||||
|
||||
let directory_contents = match std::fs::read_dir(path_buf.clone()) {
|
||||
|
|
|
@ -33,9 +33,7 @@ impl ProtocolHandler for BlobProtocolHander {
|
|||
|
||||
// Step 2.
|
||||
if request.method != Method::GET {
|
||||
return Box::pin(ready(Response::network_error(NetworkError::Internal(
|
||||
"Unexpected method for blob".into(),
|
||||
))));
|
||||
return Box::pin(ready(Response::network_error(NetworkError::InvalidMethod)));
|
||||
}
|
||||
|
||||
let range_header = request.headers.typed_get::<Range>();
|
||||
|
|
|
@ -47,9 +47,7 @@ impl ProtocolHandler for DataProtocolHander {
|
|||
},
|
||||
Err(_) => None,
|
||||
}
|
||||
.unwrap_or_else(|| {
|
||||
Response::network_error(NetworkError::Internal("Decoding data URL failed".into()))
|
||||
});
|
||||
.unwrap_or_else(|| Response::network_error(NetworkError::ResourceError));
|
||||
|
||||
Box::pin(std::future::ready(response))
|
||||
}
|
||||
|
|
|
@ -34,9 +34,7 @@ impl ProtocolHandler for FileProtocolHander {
|
|||
let url = request.current_url();
|
||||
|
||||
if request.method != Method::GET {
|
||||
return Box::pin(ready(Response::network_error(NetworkError::Internal(
|
||||
"Unexpected method for file".into(),
|
||||
))));
|
||||
return Box::pin(ready(Response::network_error(NetworkError::InvalidMethod)));
|
||||
}
|
||||
let response = if let Ok(file_path) = url.to_file_path() {
|
||||
if file_path.is_dir() {
|
||||
|
@ -66,9 +64,7 @@ impl ProtocolHandler for FileProtocolHander {
|
|||
};
|
||||
let mut reader = BufReader::with_capacity(FILE_CHUNK_SIZE, file);
|
||||
if reader.seek(SeekFrom::Start(range.start as u64)).is_err() {
|
||||
return Box::pin(ready(Response::network_error(NetworkError::Internal(
|
||||
"Unexpected method for file".into(),
|
||||
))));
|
||||
return Box::pin(ready(Response::network_error(NetworkError::InvalidMethod)));
|
||||
}
|
||||
|
||||
// Set response status to 206 if Range header is present.
|
||||
|
@ -98,12 +94,10 @@ impl ProtocolHandler for FileProtocolHander {
|
|||
|
||||
response
|
||||
} else {
|
||||
Response::network_error(NetworkError::Internal("Opening file failed".into()))
|
||||
Response::network_error(NetworkError::ResourceError)
|
||||
}
|
||||
} else {
|
||||
Response::network_error(NetworkError::Internal(
|
||||
"Constructing file path failed".into(),
|
||||
))
|
||||
Response::network_error(NetworkError::ResourceError)
|
||||
};
|
||||
|
||||
Box::pin(ready(response))
|
||||
|
|
|
@ -59,12 +59,7 @@ fn assert_parse(
|
|||
},
|
||||
None => {
|
||||
assert!(response.is_network_error());
|
||||
assert_eq!(
|
||||
response.metadata().err(),
|
||||
Some(NetworkError::Internal(
|
||||
"Decoding data URL failed".to_owned()
|
||||
))
|
||||
);
|
||||
assert_eq!(response.metadata().err(), Some(NetworkError::ResourceError));
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
|
@ -86,10 +86,7 @@ fn test_fetch_on_bad_port_is_network_error() {
|
|||
let fetch_response = fetch(request, None);
|
||||
assert!(fetch_response.is_network_error());
|
||||
let fetch_error = fetch_response.get_network_error().unwrap();
|
||||
assert_eq!(
|
||||
fetch_error,
|
||||
&NetworkError::Internal("Request attempted on bad port".into())
|
||||
)
|
||||
assert_eq!(fetch_error, &NetworkError::InvalidPort)
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
|
@ -1141,7 +1141,7 @@ fn test_load_errors_when_there_a_redirect_loop() {
|
|||
|
||||
assert_eq!(
|
||||
response.get_network_error(),
|
||||
Some(&NetworkError::Internal("Too many redirects".to_owned()))
|
||||
Some(&NetworkError::RedirectError)
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -933,6 +933,18 @@ pub enum NetworkError {
|
|||
SslValidation(String, Vec<u8>),
|
||||
/// Crash error, to be converted to Resource::Crash in the HTML parser.
|
||||
Crash(String),
|
||||
UnsupportedScheme,
|
||||
CorsViolation,
|
||||
ConnectionFailure,
|
||||
Timeout,
|
||||
RedirectError,
|
||||
InvalidMethod,
|
||||
ResourceError,
|
||||
SecurityBlock,
|
||||
MixedContent,
|
||||
CacheError,
|
||||
InvalidPort,
|
||||
LocalDirectoryError,
|
||||
}
|
||||
|
||||
impl NetworkError {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue