1
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2024-12-22 15:24:46 -05:00

feat(unstable): support in memory certificate data for Deno.createHttpClient (#8739)

This commit is contained in:
yonatan ben avraham 2020-12-20 00:13:48 +02:00 committed by GitHub
parent 4ab1aa8877
commit afbd19ed9b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 57 additions and 4 deletions

View file

@ -1266,6 +1266,10 @@ declare namespace Deno {
* Requires `allow-read` permission. * Requires `allow-read` permission.
*/ */
caFile?: string; caFile?: string;
/** A certificate authority to use when validating TLS certificates. Certificate data must be PEM encoded.
*/
caData?: string;
} }
/** **UNSTABLE**: New API, yet to be vetted. /** **UNSTABLE**: New API, yet to be vetted.

View file

@ -959,7 +959,7 @@ unitTest(function fetchResponseEmptyConstructor(): void {
unitTest( unitTest(
{ perms: { net: true, read: true } }, { perms: { net: true, read: true } },
async function fetchCustomHttpClientSuccess(): Promise< async function fetchCustomHttpClientFileCertificateSuccess(): Promise<
void void
> { > {
const client = Deno.createHttpClient( const client = Deno.createHttpClient(
@ -974,3 +974,42 @@ unitTest(
client.close(); client.close();
}, },
); );
unitTest(
{ perms: { net: true } },
async function fetchCustomHttpClientParamCertificateSuccess(): Promise<
void
> {
const client = Deno.createHttpClient(
{
caData: `-----BEGIN CERTIFICATE-----
MIIDIzCCAgugAwIBAgIJAMKPPW4tsOymMA0GCSqGSIb3DQEBCwUAMCcxCzAJBgNV
BAYTAlVTMRgwFgYDVQQDDA9FeGFtcGxlLVJvb3QtQ0EwIBcNMTkxMDIxMTYyODIy
WhgPMjExODA5MjcxNjI4MjJaMCcxCzAJBgNVBAYTAlVTMRgwFgYDVQQDDA9FeGFt
cGxlLVJvb3QtQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDMH/IO
2qtHfyBKwANNPB4K0q5JVSg8XxZdRpTTlz0CwU0oRO3uHrI52raCCfVeiQutyZop
eFZTDWeXGudGAFA2B5m3orWt0s+touPi8MzjsG2TQ+WSI66QgbXTNDitDDBtTVcV
5G3Ic+3SppQAYiHSekLISnYWgXLl+k5CnEfTowg6cjqjVr0KjL03cTN3H7b+6+0S
ws4rYbW1j4ExR7K6BFNH6572yq5qR20E6GqlY+EcOZpw4CbCk9lS8/CWuXze/vMs
OfDcc6K+B625d27wyEGZHedBomT2vAD7sBjvO8hn/DP1Qb46a8uCHR6NSfnJ7bXO
G1igaIbgY1zXirNdAgMBAAGjUDBOMB0GA1UdDgQWBBTzut+pwwDfqmMYcI9KNWRD
hxcIpTAfBgNVHSMEGDAWgBTzut+pwwDfqmMYcI9KNWRDhxcIpTAMBgNVHRMEBTAD
AQH/MA0GCSqGSIb3DQEBCwUAA4IBAQB9AqSbZ+hEglAgSHxAMCqRFdhVu7MvaQM0
P090mhGlOCt3yB7kdGfsIrUW6nQcTz7PPQFRaJMrFHPvFvPootkBUpTYR4hTkdce
H6RCRu2Jxl4Y9bY/uezd9YhGCYfUtfjA6/TH9FcuZfttmOOlxOt01XfNvVMIR6RM
z/AYhd+DeOXjr35F/VHeVpnk+55L0PYJsm1CdEbOs5Hy1ecR7ACuDkXnbM4fpz9I
kyIWJwk2zJReKcJMgi1aIinDM9ao/dca1G99PHOw8dnr4oyoTiv8ao6PWiSRHHMi
MNf4EgWfK+tZMnuqfpfO9740KzfcVoMNo4QJD4yn5YxroUOO/Azi
-----END CERTIFICATE-----
`,
},
);
const response = await fetch(
"https://localhost:5545/cli/tests/fixture.json",
{ client },
);
const json = await response.json();
assertEquals(json.name, "deno");
client.close();
},
);

View file

@ -260,6 +260,7 @@ where
#[serde(default)] #[serde(default)]
struct CreateHttpClientOptions { struct CreateHttpClientOptions {
ca_file: Option<String>, ca_file: Option<String>,
ca_data: Option<String>,
} }
let args: CreateHttpClientOptions = serde_json::from_value(args)?; let args: CreateHttpClientOptions = serde_json::from_value(args)?;
@ -269,7 +270,9 @@ where
permissions.check_read(&PathBuf::from(ca_file))?; permissions.check_read(&PathBuf::from(ca_file))?;
} }
let client = create_http_client(args.ca_file.as_deref()).unwrap(); let client =
create_http_client(args.ca_file.as_deref(), args.ca_data.as_deref())
.unwrap();
let rid = state.resource_table.add(HttpClientResource::new(client)); let rid = state.resource_table.add(HttpClientResource::new(client));
Ok(json!(rid)) Ok(json!(rid))
@ -277,9 +280,16 @@ where
/// Create new instance of async reqwest::Client. This client supports /// Create new instance of async reqwest::Client. This client supports
/// proxies and doesn't follow redirects. /// proxies and doesn't follow redirects.
fn create_http_client(ca_file: Option<&str>) -> Result<Client, AnyError> { fn create_http_client(
ca_file: Option<&str>,
ca_data: Option<&str>,
) -> Result<Client, AnyError> {
let mut builder = Client::builder().redirect(Policy::none()).use_rustls_tls(); let mut builder = Client::builder().redirect(Policy::none()).use_rustls_tls();
if let Some(ca_file) = ca_file { if let Some(ca_data) = ca_data {
let ca_data_vec = ca_data.as_bytes().to_vec();
let cert = reqwest::Certificate::from_pem(&ca_data_vec)?;
builder = builder.add_root_certificate(cert);
} else if let Some(ca_file) = ca_file {
let mut buf = Vec::new(); let mut buf = Vec::new();
File::open(ca_file)?.read_to_end(&mut buf)?; File::open(ca_file)?.read_to_end(&mut buf)?;
let cert = reqwest::Certificate::from_pem(&buf)?; let cert = reqwest::Certificate::from_pem(&buf)?;