From 08995af26859124fc4d54180075aef1ab26a9034 Mon Sep 17 00:00:00 2001 From: FantasticFiasco Date: Fri, 27 Sep 2024 18:41:55 +0200 Subject: [PATCH] wip --- packages/axis-core/sample/index.ts | 6 +-- packages/axis-core/src/DeviceRequest.ts | 20 ++------ packages/axis-core/src/Response.ts | 19 ------- packages/axis-core/src/client.ts | 50 +++++++++++++++++-- packages/axis-core/src/errors/RequestError.ts | 27 ---------- .../axis-core/src/errors/UnauthorizedError.ts | 4 -- packages/axis-core/src/errors/UnknownError.ts | 17 ------- packages/axis-core/src/errors/index.ts | 3 -- packages/axis-core/src/index.ts | 2 - .../test/auth/client-provider.spec.ts | 27 ---------- packages/axis-core/test/client.spec.ts | 23 +++------ 11 files changed, 61 insertions(+), 137 deletions(-) delete mode 100644 packages/axis-core/src/Response.ts delete mode 100644 packages/axis-core/src/errors/RequestError.ts delete mode 100644 packages/axis-core/src/errors/UnauthorizedError.ts delete mode 100644 packages/axis-core/src/errors/UnknownError.ts delete mode 100644 packages/axis-core/src/errors/index.ts delete mode 100644 packages/axis-core/test/auth/client-provider.spec.ts diff --git a/packages/axis-core/sample/index.ts b/packages/axis-core/sample/index.ts index dea071d2f..171213bf7 100644 --- a/packages/axis-core/sample/index.ts +++ b/packages/axis-core/sample/index.ts @@ -1,10 +1,10 @@ -import { Connection, get, Protocol, Response } from '../src'; +import { Connection, get, Protocol } from '../src'; (async () => { const connection = new Connection(Protocol.Http, '', 80, 'root', ''); const res: Response = await get(connection, '/axis-cgi/param.cgi?action=list&group=Brand.ProdShortName'); - console.log('Status code:', res.statusCode); + console.log('Status:', res.status); console.log('Headers:', res.headers); - console.log('Body:', res.body); + console.log('Body:', await res.text()); })(); diff --git a/packages/axis-core/src/DeviceRequest.ts b/packages/axis-core/src/DeviceRequest.ts index 4de30b492..854fe5b6f 100644 --- a/packages/axis-core/src/DeviceRequest.ts +++ b/packages/axis-core/src/DeviceRequest.ts @@ -1,7 +1,5 @@ -import * as got from 'got'; import { get } from './client'; import { Connection } from './Connection'; -import { RequestError, UnauthorizedError } from './errors'; /** * Abstract class describing a HTTP request. @@ -22,20 +20,8 @@ export abstract class DeviceRequest { * Sends a HTTP GET request to a device. * @param relativePath The relative path. */ - protected async get(relativePath: string): Promise { - try { - const res = await get(this.connection, relativePath); - return res.body; - } catch (error) { - if (error instanceof got.HTTPError && error.response.statusCode === 401) { - throw new UnauthorizedError(); - } - if (error instanceof got.RequestError) { - throw new RequestError(error, error.message, error.code); - } - - // Fallback - throw error; - } + protected async get(relativePath: string): Promise { + const res = await get(this.connection, relativePath); + return res; } } diff --git a/packages/axis-core/src/Response.ts b/packages/axis-core/src/Response.ts deleted file mode 100644 index 9c928da9f..000000000 --- a/packages/axis-core/src/Response.ts +++ /dev/null @@ -1,19 +0,0 @@ -/** - * Interface describing a response from a camera. - */ -export interface Response { - /** - * The HTTP status code. - */ - statusCode: number; - - /** - * The response headers. - */ - headers: NodeJS.Dict; - - /** - * The response body. - */ - body: Buffer; -} diff --git a/packages/axis-core/src/client.ts b/packages/axis-core/src/client.ts index 1e04ec4a2..956882d74 100644 --- a/packages/axis-core/src/client.ts +++ b/packages/axis-core/src/client.ts @@ -1,6 +1,7 @@ -import { clientProvider } from './auth/client-provider'; import { Connection } from './Connection'; -import { Response } from './Response'; +import { parse } from './auth/challenge'; +import * as basic from './auth/basic'; +import * as digest from './auth/digest'; /** * Send a HTTP GET request to the device. @@ -8,8 +9,51 @@ import { Response } from './Response'; * @param relativePath The relative path. */ export const get = (connection: Connection, relativePath: string): Promise => { + return send("GET", connection, relativePath); +}; + +const send = async (method: string, connection: Connection, relativePath: string): Promise => { const url = connection.url + format(relativePath); - return clientProvider('GET', url, connection.username, connection.password, connection?.options?.agent).get(url); + const options: RequestInit = { + method + } + + let res = await fetch(url, options); + if (res.status !== 401) { + return res; + } + + const wwwAuthenticate = res.headers.get('www-authenticate'); + if (!wwwAuthenticate) { + return res; + } + + const challenge = parse(wwwAuthenticate); + switch (challenge.type) { + case basic.BASIC: + options.headers = { + authorization: basic.createHeader(connection.username, connection.password, challenge) + }; + break; + + case digest.DIGEST: + options.headers = { + authorization: digest.createHeader( + method, + url, + connection.username, + connection.password, + challenge, + challenge.qop === 'auth' ? digest.createCnonce() : undefined) + }; + break; + + default: + return res; + } + + res = await fetch(url, options); + return res; }; const format = (relativePath: string): string => { diff --git a/packages/axis-core/src/errors/RequestError.ts b/packages/axis-core/src/errors/RequestError.ts deleted file mode 100644 index 8f67a3d9b..000000000 --- a/packages/axis-core/src/errors/RequestError.ts +++ /dev/null @@ -1,27 +0,0 @@ -/** - * Error thrown when a request fail. - */ -export class RequestError extends Error { - /** - * Initializes a new instance of the class. - * @param error The error. - * @param message The error message. - * @param code The error code, like `ECONNREFUSED`. - */ - constructor( - /** - * Gets the error. - */ - readonly error: unknown, - /** - * Gets the error message. - */ - message?: string, - /** - * Gets the error code, like `ECONNREFUSED`. - */ - readonly code?: string - ) { - super(message); - } -} diff --git a/packages/axis-core/src/errors/UnauthorizedError.ts b/packages/axis-core/src/errors/UnauthorizedError.ts deleted file mode 100644 index c76b98230..000000000 --- a/packages/axis-core/src/errors/UnauthorizedError.ts +++ /dev/null @@ -1,4 +0,0 @@ -/** - * Error thrown when user is unauthorized to perform a certain operation. - */ -export class UnauthorizedError extends Error {} diff --git a/packages/axis-core/src/errors/UnknownError.ts b/packages/axis-core/src/errors/UnknownError.ts deleted file mode 100644 index 0b7f57f58..000000000 --- a/packages/axis-core/src/errors/UnknownError.ts +++ /dev/null @@ -1,17 +0,0 @@ -/** - * Error thrown when cause is unknown. - */ -export class UnknownError extends Error { - /** - * Initializes a new instance of the class. - * @param message The error message. - */ - constructor( - /** - * The error message. - */ - message: string - ) { - super(message); - } -} diff --git a/packages/axis-core/src/errors/index.ts b/packages/axis-core/src/errors/index.ts deleted file mode 100644 index 6e1ff205c..000000000 --- a/packages/axis-core/src/errors/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -export * from './RequestError'; -export * from './UnauthorizedError'; -export * from './UnknownError'; diff --git a/packages/axis-core/src/index.ts b/packages/axis-core/src/index.ts index 80869a6fc..07888fce6 100644 --- a/packages/axis-core/src/index.ts +++ b/packages/axis-core/src/index.ts @@ -2,6 +2,4 @@ export * from './client'; export * from './Connection'; export * from './DeviceRequest'; export * from './DeviceResponse'; -export * from './errors'; export * from './Protocol'; -export * from './Response'; diff --git a/packages/axis-core/test/auth/client-provider.spec.ts b/packages/axis-core/test/auth/client-provider.spec.ts deleted file mode 100644 index dc348bf6e..000000000 --- a/packages/axis-core/test/auth/client-provider.spec.ts +++ /dev/null @@ -1,27 +0,0 @@ -import * as http from 'http'; -import * as https from 'https'; -import { clientProvider } from '../../src/auth/client-provider'; - -describe('#clientProvider should', () => { - test('respect http agent', () => { - // Arrange - const agent = new http.Agent({ keepAlive: true }); - - // Act - const got = clientProvider('GET', 'https://github.com/FantasticFiasco/axis-js', '', '', agent); - - // Assert - expect((got.defaults.options.agent as { http: http.Agent }).http).toBe(agent); - }); - - test('respect https agent', () => { - // Arrange - const agent = new https.Agent({ keepAlive: true }); - - // Act - const got = clientProvider('GET', 'https://github.com/FantasticFiasco/axis-js', '', '', agent); - - // Assert - expect((got.defaults.options.agent as { https: https.Agent }).https).toBe(agent); - }); -}); diff --git a/packages/axis-core/test/client.spec.ts b/packages/axis-core/test/client.spec.ts index 780d6bdc5..8dada2b58 100644 --- a/packages/axis-core/test/client.spec.ts +++ b/packages/axis-core/test/client.spec.ts @@ -1,4 +1,3 @@ -import { HTTPError } from 'got'; import { URL } from 'url'; import { Connection, get, Protocol } from '../src'; import { WebServer } from './web-server'; @@ -23,8 +22,8 @@ describe('#get should', () => { const got = await get(connection, relativePath); // Assert - expect(got.statusCode).toBe(200); - expect(got.body.toString()).toBe('Success'); + expect(got.status).toBe(200); + await expect(got.text()).resolves.toBe('Success'); }); test('succeed given basic authentication', async () => { @@ -35,8 +34,8 @@ describe('#get should', () => { const got = await get(connection, relativePath); // Assert - expect(got.statusCode).toBe(200); - expect(got.body.toString()).toBe('Success'); + expect(got.status).toBe(200); + await expect(got.text()).resolves.toBe('Success'); }); test('succeed given digest authentication', async () => { @@ -47,8 +46,8 @@ describe('#get should', () => { const got = await get(connection, relativePath); // Assert - expect(got.statusCode).toBe(200); - expect(got.body.toString()).toBe('Success'); + expect(got.status).toBe(200); + await expect(got.text()).resolves.toBe('Success'); }); test('throw error given invalid credentials', async () => { @@ -66,14 +65,8 @@ describe('#get should', () => { const { connection, relativePath } = parseUrl(url, username, password); // Act - try { - await get(connection, relativePath); - throw new Error('This exception should not be thrown'); - } catch (error) { - // Assert - expect(error).toBeInstanceOf(HTTPError); - expect((error as HTTPError).response.statusCode).toBe(401); - } + const res = await get(connection, relativePath); + expect(res.status).toBe(401); } }); });