diff --git a/cli/dts/lib.deno.unstable.d.ts b/cli/dts/lib.deno.unstable.d.ts index 0833c330185f66..f90cdb0d2334a1 100644 --- a/cli/dts/lib.deno.unstable.d.ts +++ b/cli/dts/lib.deno.unstable.d.ts @@ -978,6 +978,10 @@ declare namespace Deno { hostname?: string; /** Server certificate file. */ certFile?: string; + /** Application-Layer Protocol Negotiation (ALPN) protocols to announce to + * the client. If not specified, no ALPN extension will be included in the + * TLS handshake. */ + alpnProtocols?: string[]; } /** **UNSTABLE**: new API, yet to be vetted. @@ -1001,6 +1005,16 @@ declare namespace Deno { options?: StartTlsOptions, ): Promise; + export interface ListenTlsOptions { + /** **UNSTABLE**: new API, yet to be vetted. + * + * Application-Layer Protocol Negotiation (ALPN) protocols to announce to + * the client. If not specified, no ALPN extension will be included in the + * TLS handshake. + */ + alpnProtocols?: string[]; + } + /** **UNSTABLE**: The `signo` argument may change to require the Deno.Signal * enum. * diff --git a/runtime/js/40_tls.js b/runtime/js/40_tls.js index da43afaac283f3..1e6384e735f64b 100644 --- a/runtime/js/40_tls.js +++ b/runtime/js/40_tls.js @@ -51,6 +51,7 @@ keyFile, hostname = "0.0.0.0", transport = "tcp", + alpnProtocols, }) { const res = opListenTls({ port, @@ -58,18 +59,20 @@ keyFile, hostname, transport, + alpnProtocols, }); return new TLSListener(res.rid, res.localAddr); } async function startTls( conn, - { hostname = "127.0.0.1", certFile } = {}, + { hostname = "127.0.0.1", certFile, alpnProtocols } = {}, ) { const res = await opStartTls({ rid: conn.rid, hostname, certFile, + alpnProtocols, }); return new Conn(res.rid, res.remoteAddr, res.localAddr); } diff --git a/runtime/ops/tls.rs b/runtime/ops/tls.rs index d9c5f1854ab191..616a52d80b805e 100644 --- a/runtime/ops/tls.rs +++ b/runtime/ops/tls.rs @@ -92,6 +92,7 @@ struct StartTlsArgs { rid: ResourceId, cert_file: Option, hostname: String, + alpn_protocols: Option>, } async fn op_start_tls( @@ -132,6 +133,10 @@ async fn op_start_tls( config .root_store .add_server_trust_anchors(&webpki_roots::TLS_SERVER_ROOTS); + if let Some(alpn_protocols) = args.alpn_protocols { + config.alpn_protocols = + alpn_protocols.into_iter().map(|s| s.into_bytes()).collect(); + } if let Some(path) = args.cert_file { let key_file = File::open(path)?; let reader = &mut BufReader::new(key_file); @@ -300,6 +305,7 @@ pub struct ListenTlsArgs { port: u16, cert_file: String, key_file: String, + alpn_protocols: Option>, } fn op_listen_tls( @@ -318,6 +324,11 @@ fn op_listen_tls( permissions.read.check(Path::new(&key_file))?; } let mut config = ServerConfig::new(NoClientAuth::new()); + if let Some(alpn_protocols) = args.alpn_protocols { + super::check_unstable(state, "Deno.listenTls#alpn_protocols"); + config.alpn_protocols = + alpn_protocols.into_iter().map(|s| s.into_bytes()).collect(); + } config .set_single_cert(load_certs(&cert_file)?, load_keys(&key_file)?.remove(0)) .expect("invalid key or certificate");