mirror of
https://github.com/denoland/deno.git
synced 2024-12-25 00:29:09 -05:00
feat(unstable): ALPN config in listenTls (#10065)
This commit adds the ability for users to configure ALPN protocols when calling `Deno.listenTls`.
This commit is contained in:
parent
1c6602b85b
commit
8d55d8b6be
5 changed files with 115 additions and 0 deletions
10
cli/dts/lib.deno.unstable.d.ts
vendored
10
cli/dts/lib.deno.unstable.d.ts
vendored
|
@ -1001,6 +1001,16 @@ declare namespace Deno {
|
|||
options?: StartTlsOptions,
|
||||
): Promise<Conn>;
|
||||
|
||||
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.
|
||||
*
|
||||
|
|
|
@ -5,11 +5,17 @@ use deno_core::serde_json;
|
|||
use deno_core::url;
|
||||
use deno_runtime::deno_fetch::reqwest;
|
||||
use deno_runtime::deno_websocket::tokio_tungstenite;
|
||||
use rustls::Session;
|
||||
use std::fs;
|
||||
use std::io::BufReader;
|
||||
use std::io::Cursor;
|
||||
use std::io::{BufRead, Read, Write};
|
||||
use std::process::Command;
|
||||
use std::sync::Arc;
|
||||
use tempfile::TempDir;
|
||||
use test_util as util;
|
||||
use tokio_rustls::rustls;
|
||||
use tokio_rustls::webpki;
|
||||
|
||||
#[test]
|
||||
fn js_unit_tests_lint() {
|
||||
|
@ -5879,3 +5885,82 @@ console.log("finish");
|
|||
handle.abort();
|
||||
}
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn listen_tls_alpn() {
|
||||
let child = util::deno_cmd()
|
||||
.current_dir(util::root_path())
|
||||
.arg("run")
|
||||
.arg("--unstable")
|
||||
.arg("--quiet")
|
||||
.arg("--allow-net")
|
||||
.arg("--allow-read")
|
||||
.arg("./cli/tests/listen_tls_alpn.ts")
|
||||
.arg("4504")
|
||||
.stdout(std::process::Stdio::piped())
|
||||
.spawn()
|
||||
.unwrap();
|
||||
let mut stdout = child.stdout.unwrap();
|
||||
let mut buffer = [0; 5];
|
||||
let read = stdout.read(&mut buffer).unwrap();
|
||||
assert_eq!(read, 5);
|
||||
let msg = std::str::from_utf8(&buffer).unwrap();
|
||||
assert_eq!(msg, "READY");
|
||||
|
||||
let mut cfg = rustls::ClientConfig::new();
|
||||
let reader =
|
||||
&mut BufReader::new(Cursor::new(include_bytes!("./tls/RootCA.crt")));
|
||||
cfg.root_store.add_pem_file(reader).unwrap();
|
||||
cfg.alpn_protocols.push("foobar".as_bytes().to_vec());
|
||||
|
||||
let tls_connector = tokio_rustls::TlsConnector::from(Arc::new(cfg));
|
||||
let hostname = webpki::DNSNameRef::try_from_ascii_str("localhost").unwrap();
|
||||
let stream = tokio::net::TcpStream::connect("localhost:4504")
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let tls_stream = tls_connector.connect(hostname, stream).await.unwrap();
|
||||
let (_, session) = tls_stream.get_ref();
|
||||
|
||||
let alpn = session.get_alpn_protocol().unwrap();
|
||||
assert_eq!(std::str::from_utf8(alpn).unwrap(), "foobar");
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn listen_tls_alpn_fail() {
|
||||
let child = util::deno_cmd()
|
||||
.current_dir(util::root_path())
|
||||
.arg("run")
|
||||
.arg("--unstable")
|
||||
.arg("--quiet")
|
||||
.arg("--allow-net")
|
||||
.arg("--allow-read")
|
||||
.arg("./cli/tests/listen_tls_alpn.ts")
|
||||
.arg("4505")
|
||||
.stdout(std::process::Stdio::piped())
|
||||
.spawn()
|
||||
.unwrap();
|
||||
let mut stdout = child.stdout.unwrap();
|
||||
let mut buffer = [0; 5];
|
||||
let read = stdout.read(&mut buffer).unwrap();
|
||||
assert_eq!(read, 5);
|
||||
let msg = std::str::from_utf8(&buffer).unwrap();
|
||||
assert_eq!(msg, "READY");
|
||||
|
||||
let mut cfg = rustls::ClientConfig::new();
|
||||
let reader =
|
||||
&mut BufReader::new(Cursor::new(include_bytes!("./tls/RootCA.crt")));
|
||||
cfg.root_store.add_pem_file(reader).unwrap();
|
||||
cfg.alpn_protocols.push("boofar".as_bytes().to_vec());
|
||||
|
||||
let tls_connector = tokio_rustls::TlsConnector::from(Arc::new(cfg));
|
||||
let hostname = webpki::DNSNameRef::try_from_ascii_str("localhost").unwrap();
|
||||
let stream = tokio::net::TcpStream::connect("localhost:4505")
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let tls_stream = tls_connector.connect(hostname, stream).await.unwrap();
|
||||
let (_, session) = tls_stream.get_ref();
|
||||
|
||||
assert!(session.get_alpn_protocol().is_none());
|
||||
}
|
||||
|
|
12
cli/tests/listen_tls_alpn.ts
Normal file
12
cli/tests/listen_tls_alpn.ts
Normal file
|
@ -0,0 +1,12 @@
|
|||
const listener = Deno.listenTls({
|
||||
port: Number(Deno.args[0]),
|
||||
certFile: "./cli/tests/tls/localhost.crt",
|
||||
keyFile: "./cli/tests/tls/localhost.key",
|
||||
alpnProtocols: ["h2", "http/1.1", "foobar"],
|
||||
});
|
||||
|
||||
console.log("READY");
|
||||
|
||||
for await (const conn of listener) {
|
||||
conn.close();
|
||||
}
|
|
@ -51,6 +51,7 @@
|
|||
keyFile,
|
||||
hostname = "0.0.0.0",
|
||||
transport = "tcp",
|
||||
alpnProtocols,
|
||||
}) {
|
||||
const res = opListenTls({
|
||||
port,
|
||||
|
@ -58,6 +59,7 @@
|
|||
keyFile,
|
||||
hostname,
|
||||
transport,
|
||||
alpnProtocols,
|
||||
});
|
||||
return new TLSListener(res.rid, res.localAddr);
|
||||
}
|
||||
|
|
|
@ -300,6 +300,7 @@ pub struct ListenTlsArgs {
|
|||
port: u16,
|
||||
cert_file: String,
|
||||
key_file: String,
|
||||
alpn_protocols: Option<Vec<String>>,
|
||||
}
|
||||
|
||||
fn op_listen_tls(
|
||||
|
@ -318,6 +319,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");
|
||||
|
|
Loading…
Reference in a new issue