mirror of
https://github.com/denoland/deno.git
synced 2024-11-21 15:04:11 -05:00
fix(runtime): use host header for inspector websocket URL (#20171)
If a `host` header is specified, use that for the generated websocket URLs. Fixes #20087
This commit is contained in:
parent
f1a2d928cb
commit
1fd219fe8a
2 changed files with 56 additions and 19 deletions
|
@ -9,6 +9,8 @@ use deno_runtime::deno_fetch::reqwest;
|
|||
use fastwebsockets::FragmentCollector;
|
||||
use fastwebsockets::Frame;
|
||||
use fastwebsockets::WebSocket;
|
||||
use http::header::HOST;
|
||||
use hyper::header::HeaderValue;
|
||||
use hyper::upgrade::Upgraded;
|
||||
use hyper::Body;
|
||||
use hyper::Request;
|
||||
|
@ -704,14 +706,34 @@ async fn inspector_json() {
|
|||
let mut url = ws_url.clone();
|
||||
let _ = url.set_scheme("http");
|
||||
url.set_path("/json");
|
||||
let resp = reqwest::get(url).await.unwrap();
|
||||
assert_eq!(resp.status(), reqwest::StatusCode::OK);
|
||||
let endpoint_list: Vec<deno_core::serde_json::Value> =
|
||||
serde_json::from_str(&resp.text().await.unwrap()).unwrap();
|
||||
let matching_endpoint = endpoint_list
|
||||
.iter()
|
||||
.find(|e| e["webSocketDebuggerUrl"] == ws_url.as_str());
|
||||
assert!(matching_endpoint.is_some());
|
||||
let client = reqwest::Client::new();
|
||||
|
||||
// Ensure that the webSocketDebuggerUrl matches the host header
|
||||
for (host, expected) in [
|
||||
(None, ws_url.as_str()),
|
||||
(Some("some.random.host"), "ws://some.random.host/"),
|
||||
(Some("some.random.host:1234"), "ws://some.random.host:1234/"),
|
||||
(Some("[::1]:1234"), "ws://[::1]:1234/"),
|
||||
] {
|
||||
let mut req = reqwest::Request::new(reqwest::Method::GET, url.clone());
|
||||
if let Some(host) = host {
|
||||
req
|
||||
.headers_mut()
|
||||
.insert(HOST, HeaderValue::from_static(host));
|
||||
}
|
||||
let resp = client.execute(req).await.unwrap();
|
||||
assert_eq!(resp.status(), reqwest::StatusCode::OK);
|
||||
let endpoint_list: Vec<deno_core::serde_json::Value> =
|
||||
serde_json::from_str(&resp.text().await.unwrap()).unwrap();
|
||||
let matching_endpoint = endpoint_list.iter().find(|e| {
|
||||
e["webSocketDebuggerUrl"]
|
||||
.as_str()
|
||||
.unwrap()
|
||||
.contains(expected)
|
||||
});
|
||||
assert!(matching_endpoint.is_some());
|
||||
}
|
||||
|
||||
child.kill().unwrap();
|
||||
}
|
||||
|
||||
|
|
|
@ -16,6 +16,7 @@ use deno_core::serde_json;
|
|||
use deno_core::serde_json::json;
|
||||
use deno_core::serde_json::Value;
|
||||
use deno_core::task::spawn;
|
||||
use deno_core::url::Url;
|
||||
use deno_core::InspectorMsg;
|
||||
use deno_core::InspectorSessionProxy;
|
||||
use deno_core::JsRuntime;
|
||||
|
@ -189,11 +190,12 @@ fn handle_ws_request(
|
|||
|
||||
fn handle_json_request(
|
||||
inspector_map: Rc<RefCell<HashMap<Uuid, InspectorInfo>>>,
|
||||
host: Option<String>,
|
||||
) -> http::Result<http::Response<hyper::Body>> {
|
||||
let data = inspector_map
|
||||
.borrow()
|
||||
.values()
|
||||
.map(|info| info.get_json_metadata())
|
||||
.map(move |info| info.get_json_metadata(&host))
|
||||
.collect::<Vec<_>>();
|
||||
http::Response::builder()
|
||||
.status(http::StatusCode::OK)
|
||||
|
@ -224,7 +226,7 @@ async fn server(
|
|||
.map(|info| {
|
||||
eprintln!(
|
||||
"Debugger listening on {}",
|
||||
info.get_websocket_debugger_url()
|
||||
info.get_websocket_debugger_url(&info.host.to_string())
|
||||
);
|
||||
eprintln!("Visit chrome://inspect to connect to the debugger.");
|
||||
if info.wait_for_session {
|
||||
|
@ -258,6 +260,17 @@ async fn server(
|
|||
future::ok::<_, Infallible>(hyper::service::service_fn(
|
||||
move |req: http::Request<hyper::Body>| {
|
||||
future::ready({
|
||||
// If the host header can make a valid URL, use it
|
||||
let host = req
|
||||
.headers()
|
||||
.get("host")
|
||||
.and_then(|host| host.to_str().ok())
|
||||
.and_then(|host| Url::parse(&format!("http://{host}")).ok())
|
||||
.and_then(|url| match (url.host(), url.port()) {
|
||||
(Some(host), Some(port)) => Some(format!("{host}:{port}")),
|
||||
(Some(host), None) => Some(format!("{host}")),
|
||||
_ => None,
|
||||
});
|
||||
match (req.method(), req.uri().path()) {
|
||||
(&http::Method::GET, path) if path.starts_with("/ws/") => {
|
||||
handle_ws_request(req, Rc::clone(&inspector_map))
|
||||
|
@ -266,10 +279,10 @@ async fn server(
|
|||
handle_json_version_request(json_version_response.clone())
|
||||
}
|
||||
(&http::Method::GET, "/json") => {
|
||||
handle_json_request(Rc::clone(&inspector_map))
|
||||
handle_json_request(Rc::clone(&inspector_map), host)
|
||||
}
|
||||
(&http::Method::GET, "/json/list") => {
|
||||
handle_json_request(Rc::clone(&inspector_map))
|
||||
handle_json_request(Rc::clone(&inspector_map), host)
|
||||
}
|
||||
_ => http::Response::builder()
|
||||
.status(http::StatusCode::NOT_FOUND)
|
||||
|
@ -381,27 +394,29 @@ impl InspectorInfo {
|
|||
}
|
||||
}
|
||||
|
||||
fn get_json_metadata(&self) -> Value {
|
||||
fn get_json_metadata(&self, host: &Option<String>) -> Value {
|
||||
let host_listen = format!("{}", self.host);
|
||||
let host = host.as_ref().unwrap_or(&host_listen);
|
||||
json!({
|
||||
"description": "deno",
|
||||
"devtoolsFrontendUrl": self.get_frontend_url(),
|
||||
"devtoolsFrontendUrl": self.get_frontend_url(host),
|
||||
"faviconUrl": "https://deno.land/favicon.ico",
|
||||
"id": self.uuid.to_string(),
|
||||
"title": self.get_title(),
|
||||
"type": "node",
|
||||
"url": self.url.to_string(),
|
||||
"webSocketDebuggerUrl": self.get_websocket_debugger_url(),
|
||||
"webSocketDebuggerUrl": self.get_websocket_debugger_url(host),
|
||||
})
|
||||
}
|
||||
|
||||
pub fn get_websocket_debugger_url(&self) -> String {
|
||||
format!("ws://{}/ws/{}", &self.host, &self.uuid)
|
||||
pub fn get_websocket_debugger_url(&self, host: &str) -> String {
|
||||
format!("ws://{}/ws/{}", host, &self.uuid)
|
||||
}
|
||||
|
||||
fn get_frontend_url(&self) -> String {
|
||||
fn get_frontend_url(&self, host: &str) -> String {
|
||||
format!(
|
||||
"devtools://devtools/bundled/js_app.html?ws={}/ws/{}&experiments=true&v8only=true",
|
||||
&self.host, &self.uuid
|
||||
host, &self.uuid
|
||||
)
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue