fix: don't panic on invalid uri (#712)

* fix: don't panic on invalid uri

* fix macos & ios
This commit is contained in:
Amr Bashir
2022-09-30 13:22:52 +02:00
committed by GitHub
parent 74589525bd
commit 818ce9989d
7 changed files with 77 additions and 49 deletions

5
.changes/invalid-uri.md Normal file
View File

@@ -0,0 +1,5 @@
---
"wry": "patch"
---
Internally return with error from custom protocol if an invalid uri was requseted such as `wry://` which doesn't contain a host.

View File

@@ -55,7 +55,13 @@ fn handle_request(env: JNIEnv, request: JObject) -> Result<jobject, JniError> {
}
if let Some(handler) = REQUEST_HANDLER.get() {
let response = (handler.0)(request_builder.body(Vec::new()).unwrap());
let final_request = match request_builder.body(Vec::new()) {
Ok(req) => req,
Err(_) => {
return Ok(*JObject::null());
}
};
let response = (handler.0)(final_request);
if let Some(response) = response {
let status_code = response.status().as_u16() as i32;
let reason_phrase = "OK";

View File

@@ -115,8 +115,7 @@ pub struct WebViewAttributes {
/// Register custom file loading protocols with pairs of scheme uri string and a handling
/// closure.
///
/// The closure takes a url string slice, and returns a two item tuple of a vector of
/// bytes which is the content and a mimetype string of the content.
/// The closure takes a [Response] and returns a [Request].
///
/// # Warning
/// Pages loaded from custom protocol will have different Origin on different platforms. And
@@ -308,8 +307,7 @@ impl<'a> WebViewBuilder<'a> {
/// Register custom file loading protocols with pairs of scheme uri string and a handling
/// closure.
///
/// The closure takes a url string slice, and returns a two item tuple of a
/// vector of bytes which is the content and a mimetype string of the content.
/// The closure takes a [Request] and returns a [Response]
///
/// # Warning
/// Pages loaded from custom protocol will have different Origin on different platforms. And

View File

@@ -228,11 +228,17 @@ where
// FIXME: Read the method
// FIXME: Read the headers
// FIXME: Read the body (forms post)
let http_request = Request::builder()
.uri(uri)
.method("GET")
.body(Vec::new())
.unwrap();
let http_request = match Request::builder().uri(uri).method("GET").body(Vec::new()) {
Ok(req) => req,
Err(_) => {
request.finish_error(&mut glib::Error::new(
// TODO: use UriError when we can use 2_66 webkit2gtk feature flag
FileError::Exist,
"Could not get uri.",
));
return;
}
};
match handler(&http_request) {
Ok(http_response) => {

View File

@@ -462,11 +462,15 @@ window.addEventListener('mousemove', (e) => window.chrome.webview.postMessage('_
&format!("https://{}.", custom_protocol.0),
&format!("{}://", custom_protocol.0),
);
let final_request = request
let final_request = match request
.uri(&path)
.method(request_method.as_str())
.body(body_sent)
.unwrap();
{
Ok(req) => req,
Err(_) => return Err(E_FAIL.into()),
};
return match (custom_protocol.1)(&final_request) {
Ok(sent_response) => {

View File

@@ -158,46 +158,55 @@ impl InnerWebView {
http_request = http_request.header(header_field.to_str(), header_value.to_str());
}
// send response
let final_request = http_request.body(sent_form_body).unwrap();
if let Ok(sent_response) = function(&final_request) {
let content = sent_response.body();
// default: application/octet-stream, but should be provided by the client
let wanted_mime = sent_response.headers().get(CONTENT_TYPE);
// default to 200
let wanted_status_code = sent_response.status().as_u16() as i32;
// default to HTTP/1.1
let wanted_version = format!("{:#?}", sent_response.version());
let dictionary: id = msg_send![class!(NSMutableDictionary), alloc];
let headers: id = msg_send![dictionary, initWithCapacity:1];
if let Some(mime) = wanted_mime {
let () = msg_send![headers, setObject:NSString::new(mime.to_str().unwrap()) forKey: NSString::new(CONTENT_TYPE.as_str())];
}
let () = msg_send![headers, setObject:NSString::new(&content.len().to_string()) forKey: NSString::new(CONTENT_LENGTH.as_str())];
// add headers
for (name, value) in sent_response.headers().iter() {
let header_key = name.as_str();
if let Ok(value) = value.to_str() {
let () = msg_send![headers, setObject:NSString::new(value) forKey: NSString::new(&header_key)];
}
}
let urlresponse: id = msg_send![class!(NSHTTPURLResponse), alloc];
let response: id = msg_send![urlresponse, initWithURL:url statusCode: wanted_status_code HTTPVersion:NSString::new(&wanted_version) headerFields:headers];
let () = msg_send![task, didReceiveResponse: response];
// Send data
let bytes = content.as_ptr() as *mut c_void;
let data: id = msg_send![class!(NSData), alloc];
let data: id = msg_send![data, initWithBytesNoCopy:bytes length:content.len() freeWhenDone: if content.len() == 0 { NO } else { YES }];
let () = msg_send![task, didReceiveData: data];
} else {
let respond_with_404 = || {
let urlresponse: id = msg_send![class!(NSHTTPURLResponse), alloc];
let response: id = msg_send![urlresponse, initWithURL:url statusCode:StatusCode::NOT_FOUND HTTPVersion:NSString::new(format!("{:#?}", Version::HTTP_11).as_str()) headerFields:null::<c_void>()];
let () = msg_send![task, didReceiveResponse: response];
}
};
// send response
match http_request.body(sent_form_body) {
Ok(final_request) => {
if let Ok(sent_response) = function(&final_request) {
let content = sent_response.body();
// default: application/octet-stream, but should be provided by the client
let wanted_mime = sent_response.headers().get(CONTENT_TYPE);
// default to 200
let wanted_status_code = sent_response.status().as_u16() as i32;
// default to HTTP/1.1
let wanted_version = format!("{:#?}", sent_response.version());
let dictionary: id = msg_send![class!(NSMutableDictionary), alloc];
let headers: id = msg_send![dictionary, initWithCapacity:1];
if let Some(mime) = wanted_mime {
let () = msg_send![headers, setObject:NSString::new(mime.to_str().unwrap()) forKey: NSString::new(CONTENT_TYPE.as_str())];
}
let () = msg_send![headers, setObject:NSString::new(&content.len().to_string()) forKey: NSString::new(CONTENT_LENGTH.as_str())];
// add headers
for (name, value) in sent_response.headers().iter() {
let header_key = name.as_str();
if let Ok(value) = value.to_str() {
let () = msg_send![headers, setObject:NSString::new(value) forKey: NSString::new(&header_key)];
}
}
let urlresponse: id = msg_send![class!(NSHTTPURLResponse), alloc];
let response: id = msg_send![urlresponse, initWithURL:url statusCode: wanted_status_code HTTPVersion:NSString::new(&wanted_version) headerFields:headers];
let () = msg_send![task, didReceiveResponse: response];
// Send data
let bytes = content.as_ptr() as *mut c_void;
let data: id = msg_send![class!(NSData), alloc];
let data: id = msg_send![data, initWithBytesNoCopy:bytes length:content.len() freeWhenDone: if content.len() == 0 { NO } else { YES }];
let () = msg_send![task, didReceiveData: data];
} else {
respond_with_404()
}
}
Err(_) => respond_with_404(),
};
// Finish
let () = msg_send![task, didFinish];
} else {