Skip to content

Commit

Permalink
fix: don't panic on invalid uri (#712)
Browse files Browse the repository at this point in the history
* fix: don't panic on invalid uri

* fix macos & ios
  • Loading branch information
amrbashir committed Sep 30, 2022
1 parent 7458952 commit 818ce99
Show file tree
Hide file tree
Showing 7 changed files with 75 additions and 47 deletions.
5 changes: 5 additions & 0 deletions .changes/invalid-uri.md
@@ -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.
File renamed without changes.
8 changes: 7 additions & 1 deletion src/webview/android/binding.rs
Expand Up @@ -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";
Expand Down
6 changes: 2 additions & 4 deletions src/webview/mod.rs
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
16 changes: 11 additions & 5 deletions src/webview/webkitgtk/web_context.rs
Expand Up @@ -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) => {
Expand Down
8 changes: 6 additions & 2 deletions src/webview/webview2/mod.rs
Expand Up @@ -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) => {
Expand Down
79 changes: 44 additions & 35 deletions src/webview/wkwebview/mod.rs
Expand Up @@ -158,46 +158,55 @@ impl InnerWebView {
http_request = http_request.header(header_field.to_str(), header_value.to_str());
}

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
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())];
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)];
}
}

// 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(),
};

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 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];
}
// Finish
let () = msg_send![task, didFinish];
} else {
Expand Down

0 comments on commit 818ce99

Please sign in to comment.