1
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2025-01-03 04:48:52 -05:00

fix(unstable): Deno.serve() can parse hostnames (#15579)

This commit is contained in:
Bartek Iwańczuk 2022-08-24 16:38:51 +02:00 committed by GitHub
parent 5268fa0e0f
commit a4cc09447e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 49 additions and 15 deletions

View file

@ -34,16 +34,27 @@ function onListen<T>(
}; };
} }
Deno.test(async function httpServerInvalidHostname() { Deno.test(async function httpServerCanResolveHostnames() {
await assertRejects( const ac = new AbortController();
() => const listeningPromise = deferred();
Deno.serve({
const server = Deno.serve({
handler: (_req) => new Response("ok"), handler: (_req) => new Response("ok"),
hostname: "localhost", hostname: "localhost",
}), port: 4501,
TypeError, signal: ac.signal,
"hostname could not be parsed as an IP address", onListen: onListen(listeningPromise),
); onError: createOnErrorCb(ac),
});
await listeningPromise;
const resp = await fetch("http://localhost:4501/", {
headers: { "connection": "close" },
});
const text = await resp.text();
assertEquals(text, "ok");
ac.abort();
await server;
}); });
Deno.test({ permissions: { net: true } }, async function httpServerBasic() { Deno.test({ permissions: { net: true } }, async function httpServerBasic() {

View file

@ -4,6 +4,7 @@
// https://github.com/rust-lang/rust-clippy/issues/6446 // https://github.com/rust-lang/rust-clippy/issues/6446
#![allow(clippy::await_holding_lock)] #![allow(clippy::await_holding_lock)]
use deno_core::error::generic_error;
use deno_core::error::type_error; use deno_core::error::type_error;
use deno_core::error::AnyError; use deno_core::error::AnyError;
use deno_core::op; use deno_core::op;
@ -47,6 +48,7 @@ use std::io::Write;
use std::marker::PhantomPinned; use std::marker::PhantomPinned;
use std::mem::replace; use std::mem::replace;
use std::net::SocketAddr; use std::net::SocketAddr;
use std::net::ToSocketAddrs;
use std::pin::Pin; use std::pin::Pin;
use std::rc::Rc; use std::rc::Rc;
use std::sync::Arc; use std::sync::Arc;
@ -1232,6 +1234,28 @@ fn run_server(
Ok(()) Ok(())
} }
fn make_addr_port_pair(hostname: &str, port: u16) -> (&str, u16) {
// Default to localhost if given just the port. Example: ":80"
if hostname.is_empty() {
return ("0.0.0.0", port);
}
// If this looks like an ipv6 IP address. Example: "[2001:db8::1]"
// Then we remove the brackets.
let addr = hostname.trim_start_matches('[').trim_end_matches(']');
(addr, port)
}
/// Resolve network address *synchronously*.
pub fn resolve_addr_sync(
hostname: &str,
port: u16,
) -> Result<impl Iterator<Item = SocketAddr>, AnyError> {
let addr_port_pair = make_addr_port_pair(hostname, port);
let result = addr_port_pair.to_socket_addrs()?;
Ok(result)
}
#[op] #[op]
fn op_flash_serve<P>( fn op_flash_serve<P>(
state: &mut OpState, state: &mut OpState,
@ -1244,11 +1268,10 @@ where
state state
.borrow_mut::<P>() .borrow_mut::<P>()
.check_net(&(&opts.hostname, Some(opts.port)))?; .check_net(&(&opts.hostname, Some(opts.port)))?;
let parsed_hostname = opts
.hostname let addr = resolve_addr_sync(&opts.hostname, opts.port)?
.parse() .next()
.map_err(|_| type_error("hostname could not be parsed as an IP address"))?; .ok_or_else(|| generic_error("No resolved address found"))?;
let addr = SocketAddr::new(parsed_hostname, opts.port);
let (tx, rx) = mpsc::channel(100); let (tx, rx) = mpsc::channel(100);
let (close_tx, close_rx) = mpsc::channel(1); let (close_tx, close_rx) = mpsc::channel(1);
let (listening_tx, listening_rx) = mpsc::channel(1); let (listening_tx, listening_rx) = mpsc::channel(1);