aws-crt
Version:
NodeJS/browser bindings to the aws-c-* libraries
303 lines (257 loc) • 9.86 kB
text/typescript
/*
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0.
*/
import { HttpClientConnectionManager, HttpClientConnection, HttpHeader, HttpHeaders, HttpRequest } from "@awscrt/http";
import { ClientBootstrap, SocketOptions, SocketType, SocketDomain, ClientTlsContext, TlsConnectionOptions, InputStream } from "@awscrt/io";
import { PassThrough } from "stream";
jest.setTimeout(10000);
jest.retryTimes(3);
test('HTTP Headers', () => {
const long_token = "AQoDYXdzEPT//////////wEXAMPLEtc764bNrC9SAPBSM22wDOk4x4HIZ8j4FZTwdQWLWsKWHGBuFqwAeMicRXmxfpSPfIeoIYRqTflfKD8YUuwthAx7mSEI/qkPpKPi/kMcGdQrmGdeehM4IC1NtBmUpp2wUE8phUZampKsburEDy0KPkyQDYwT7WZ0wq5VSXDvp75YU9HFvlRd8Tx6q6fE8YQcHNVXAkiY9q6d+xo0rKwT38xVqr7ZD0u0iPPkUL64lIZbqBAz+scqKmlzm8FDrypNC9Yjc8fPOLn9FX9KSYvKTr4rvx3iSIlTJabIQwj2ICCR/oLxBA==";
const header_array: HttpHeader[] = [
['Host', 'www.amazon.com'],
['Content-Length', '42'],
["x-amz-security-token", long_token],
];
let headers = new HttpHeaders(header_array);
let request = new HttpRequest("", "", new HttpHeaders(header_array));
<unknown>request;
const iterator = headers[Symbol.iterator].call(headers);
<unknown>iterator;
const next = iterator.next.call(iterator);
<unknown>next;
let found_headers = 0;
for (const header of headers) {
expect(['Host', 'Content-Length', 'x-amz-security-token']).toContain(header[0]);
expect(['www.amazon.com', '42', long_token]).toContain(header[1]);
found_headers++;
}
expect(found_headers).toBe(3);
// Upgrade header does not exist
expect(headers.get('Upgrade')).toBeFalsy();
// Make sure case doesn't matter
expect(headers.get('HOST')).toBe('www.amazon.com');
expect(headers.get('x-amz-security-token')).toBe(long_token);
// Remove Content-Length, and make sure host is all that's left
headers.remove('content-length');
headers.remove('x-amz-security-token');
found_headers = 0;
for (const header of headers) {
expect(header[0]).toBe('Host');
expect(header[1]).toBe('www.amazon.com');
found_headers++;
}
expect(found_headers).toBe(1);
headers.clear();
for (const header of headers) {
// this should never be called
expect(header).toBeNull();
}
});
test('HTTP Request without body', () => {
let request = new HttpRequest("GET", "/index.html");
expect(request.method).toBe("GET");
expect(request.path).toBe('/index.html');
expect(request.headers.length).toBe(0);
request.method = "POST";
request.path = "/test.html"
expect(request.method).toBe("POST");
expect(request.path).toBe('/test.html');
request.headers.add("Host", "www.amazon.com");
expect(request.headers.length).toBe(1);
});
test('HTTP Request with body', () => {
let stream = new PassThrough();
stream.write("test");
stream.end();
let body_stream = new InputStream(stream);
let request = new HttpRequest("POST", "/index.html", undefined, body_stream);
expect(request.method).toBe("POST");
expect(request.path).toBe('/index.html');
expect(request.headers.length).toBe(0);
// Body property for request is not readable
});
async function test_connection(host: string, port: number, tls_opts?: TlsConnectionOptions, bootstrap?: ClientBootstrap) {
let setup_error_code: Number = -1;
let shutdown_error_code: Number = -1;
let connection_error: Error | undefined;
const promise = new Promise((resolve, reject) => {
let connection = new HttpClientConnection(
bootstrap,
host,
port,
new SocketOptions(SocketType.STREAM, SocketDomain.IPV4, 3000),
tls_opts
);
connection.on('connect', () => {
setup_error_code = 0;
connection.close();
});
connection.on('close', () => {
if (!connection_error) {
shutdown_error_code = 0;
resolve(true);
}
});
connection.on('error', (error) => {
connection_error = error;
reject(error);
});
});
await expect(promise).resolves.toBeTruthy();
expect(setup_error_code).toEqual(0);
expect(shutdown_error_code).toEqual(0);
expect(connection_error).toBeUndefined();
}
test('HTTP Connection Create/Destroy', async () => {
await test_connection("s3.amazonaws.com", 80, undefined, new ClientBootstrap());
});
test('HTTP Connection Create/Destroy Undef Bootstrap', async () => {
await test_connection("s3.amazonaws.com", 80, undefined, undefined);
});
test('HTTPS Connection Create/Destroy', async () => {
const host = "s3.amazonaws.com";
await test_connection(host, 443, new TlsConnectionOptions(new ClientTlsContext(), host), new ClientBootstrap());
});
test('HTTPS Connection Create/Destroy Undef Bootstrap', async () => {
const host = "s3.amazonaws.com";
await test_connection(host, 443, new TlsConnectionOptions(new ClientTlsContext(), host), undefined);
});
async function test_stream(method: string, host: string, port: number, activate: boolean, tls_opts?: TlsConnectionOptions) {
const promise = new Promise((resolve, reject) => {
let connection = new HttpClientConnection(
new ClientBootstrap(),
host,
port,
new SocketOptions(SocketType.STREAM, SocketDomain.IPV4, 3000),
tls_opts);
connection.on('connect', () => {
let request = new HttpRequest(
method,
'/',
new HttpHeaders([
['host', host],
['user-agent', 'AWS CRT for NodeJS']
])
);
let stream = connection.request(request);
stream.on('response', (status_code, headers) => {
expect(status_code == 301 || status_code == 200).toBe(true);
expect(headers).toBeDefined();
});
stream.on('data', (body_data) => {
expect(body_data.byteLength).toBeGreaterThan(0);
});
stream.on('end', () => {
connection.close();
});
stream.on('error', (error) => {
connection.close();
console.log(error);
expect(error).toBeUndefined();
});
if (activate) {
stream.activate();
} else {
resolve(true);
}
});
connection.on('close', () => {
resolve(true);
});
connection.on('error', (error) => {
reject(error);
});
});
await expect(promise).resolves.toBeTruthy();
}
test('HTTP Stream GET', async () => {
await test_stream('GET', 'amazon.com', 80, true, undefined);
});
test('HTTPS Stream GET', async () => {
const host = 'amazon.com';
await test_stream('GET', host, 443, true, new TlsConnectionOptions(new ClientTlsContext(), host));
});
test('HTTP Stream UnActivated', async () => {
await test_stream('GET', 'amazon.com', 80, false, undefined);
});
test('HTTP Connection Manager create/destroy', () => {
const bootstrap = new ClientBootstrap();
let connection_manager = new HttpClientConnectionManager(
bootstrap,
"s3.amazon.com",
80,
4,
16 * 1024,
new SocketOptions(SocketType.STREAM, SocketDomain.IPV4, 3000),
undefined
);
expect(connection_manager).toBeDefined();
connection_manager.close();
});
test('HTTP Connection Manager acquire/release', async () => {
const bootstrap = new ClientBootstrap();
let connection_manager = new HttpClientConnectionManager(
bootstrap,
"s3.amazon.com",
80,
4,
16 * 1024,
new SocketOptions(SocketType.STREAM, SocketDomain.IPV4, 3000),
undefined
);
expect(connection_manager).toBeDefined();
const connection = await connection_manager.acquire();
expect(connection).toBeDefined();
connection_manager.release(connection);
connection_manager.close();
});
test('HTTP Connection Manager acquire/stream/release', async () => {
const bootstrap = new ClientBootstrap();
let connection_manager = new HttpClientConnectionManager(
bootstrap,
"amazon.com",
80,
4,
16 * 1024,
new SocketOptions(SocketType.STREAM, SocketDomain.IPV4, 3000),
undefined
);
expect(connection_manager).toBeDefined();
const connection = await connection_manager.acquire();
expect(connection).toBeDefined();
let request = new HttpRequest(
'GET',
'/',
new HttpHeaders([
['host', 'amazon.com'],
['user-agent', 'AWS CRT for NodeJS']
])
);
let connection_error: Error | undefined;
const promise = new Promise((resolve, reject) => {
let stream = connection.request(request);
stream.on('response', (status_code, headers) => {
expect(status_code == 301 || status_code == 200).toBe(true);
expect(headers).toBeDefined();
});
stream.on('data', (body_data) => {
expect(body_data.byteLength).toBeGreaterThan(0);
});
stream.on('end', () => {
connection_manager.release(connection);
connection_manager.close();
if (!connection_error) {
resolve(true);
}
});
stream.on('error', (error) => {
connection_error = error;
reject(error);
});
stream.activate();
})
await expect(promise).resolves.toBeTruthy();
expect(connection_error).toBeUndefined();
});