This commit is contained in:
Glenn Harper 2023-04-19 12:02:57 -04:00 коммит произвёл GitHub
Родитель e6faf6b7fc
Коммит d071d11d1e
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
5 изменённых файлов: 79 добавлений и 121 удалений

Просмотреть файл

@ -3,11 +3,6 @@ Microsoft Azure Cognitive Services Speech SDK Javascript
Copyright (c) Microsoft Corporation
All rights reserved.
Component.
ocsp (https://github.com/indutny/ocsp)
Open Source License/Copyright Notice.
Copyright Fedor Indutny, 2015.
Component.
uuid (https://github.com/uuidjs/uuid)
Open Source License/Copyright Notice.
@ -22,4 +17,4 @@ The above copyright notice and this permission notice shall be included in all c
THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
----------------------------------------------- END OF LICENSE ------------------------------------------
----------------------------------------------- END OF LICENSE ------------------------------------------

Просмотреть файл

@ -16,14 +16,6 @@ Notwithstanding any other terms, you may reverse engineer this software to the
extent required to debug changes to any libraries licensed under the GNU Lesser
General Public License.
Component.
ocsp (https://github.com/indutny/ocsp)
Open Source License/Copyright Notice.
This software is licensed under the MIT License.
Copyright Fedor Indutny, 2015.
Component.
uuid (https://github.com/uuidjs/uuid)

Просмотреть файл

@ -73,7 +73,6 @@
"gulp-typescript": "^5.0.1",
"jest": "^27.0.0",
"jest-junit": "^12.0.0",
"ocsp": "^1.2.0",
"rimraf": "^3.0.2",
"semver": "^6.3.0",
"source-map-loader": "^3.0.1",

Просмотреть файл

@ -1,102 +0,0 @@
/* eslint-disable import/order */
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
import * as http from "http";
import * as tls from "tls";
import { ProxyInfo } from "./ProxyInfo";
import Agent from "agent-base";
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
import HttpsProxyAgent from "https-proxy-agent";
import * as net from "net";
export class CertCheckAgent {
// Test hook to enable forcing expiration / refresh to happen.
public static testTimeOffset: number = 0;
// Test hook to disable stapling for cache testing.
public static forceDisableOCSPStapling: boolean = false;
private privProxyInfo: ProxyInfo;
public constructor(proxyInfo?: ProxyInfo) {
if (!!proxyInfo) {
this.privProxyInfo = proxyInfo;
}
}
// eslint-disable-next-line @typescript-eslint/no-unused-vars
public GetAgent(): http.Agent {
// eslint-disable-next-line @typescript-eslint/unbound-method
const agent: any = new Agent.Agent(this.CreateConnection);
if (this.privProxyInfo !== undefined &&
this.privProxyInfo.HostName !== undefined &&
this.privProxyInfo.Port > 0) {
const proxyName: string = "privProxyInfo";
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
agent[proxyName] = this.privProxyInfo;
}
return agent as http.Agent;
}
private static GetProxyAgent(proxyInfo: ProxyInfo): HttpsProxyAgent {
const httpProxyOptions: HttpsProxyAgent.HttpsProxyAgentOptions = {
host: proxyInfo.HostName,
port: proxyInfo.Port,
};
if (!!proxyInfo.UserName) {
httpProxyOptions.headers = {
"Proxy-Authentication": "Basic " + new Buffer(`${proxyInfo.UserName}:${(proxyInfo.Password === undefined) ? "" : proxyInfo.Password}`).toString("base64"),
};
} else {
httpProxyOptions.headers = {};
}
httpProxyOptions.headers.requestOCSP = "true";
const httpProxyAgent: HttpsProxyAgent = new HttpsProxyAgent(httpProxyOptions);
return httpProxyAgent;
}
private CreateConnection(request: Agent.ClientRequest, options: Agent.RequestOptions): Promise<net.Socket> {
let socketPromise: Promise<net.Socket>;
options = {
...options,
...{
requestOCSP: !CertCheckAgent.forceDisableOCSPStapling,
servername: options.host
}
};
if (!!this.privProxyInfo) {
const httpProxyAgent: HttpsProxyAgent = CertCheckAgent.GetProxyAgent(this.privProxyInfo);
const baseAgent: Agent.Agent = httpProxyAgent as unknown as Agent.Agent;
socketPromise = new Promise<net.Socket>((resolve: (value: net.Socket) => void, reject: (error: string | Error) => void): void => {
baseAgent.callback(request, options, (error: Error, socket: net.Socket): void => {
if (!!error) {
reject(error);
} else {
resolve(socket);
}
});
});
} else {
if (!!options.secureEndpoint) {
socketPromise = Promise.resolve(tls.connect(options));
} else {
socketPromise = Promise.resolve(net.connect(options));
}
}
return socketPromise;
}
}

Просмотреть файл

@ -2,6 +2,14 @@
// Licensed under the MIT license.
// Node.JS specific web socket / browser support.
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
import * as http from "http";
import * as net from "net";
import * as tls from "tls";
import Agent from "agent-base";
import HttpsProxyAgent from "https-proxy-agent";
import ws from "ws";
import { HeaderNames } from "../common.speech/HeaderNames";
import {
@ -27,8 +35,6 @@ import {
} from "../common/Exports";
import { ProxyInfo } from "./ProxyInfo";
import { CertCheckAgent } from "./CertChecks";
interface ISendItem {
Message: ConnectionMessage;
RawWebsocketMessage: RawWebsocketMessage;
@ -115,9 +121,8 @@ export class WebsocketMessageAdapter {
const options: ws.ClientOptions = { headers: this.privHeaders, perMessageDeflate: this.privEnableCompression };
// The ocsp library will handle validation for us and fail the connection if needed.
this.privCertificateValidatedDeferral.resolve();
const checkAgent: CertCheckAgent = new CertCheckAgent(this.proxyInfo);
options.agent = checkAgent.GetAgent();
options.agent = this.getAgent();
// Workaround for https://github.com/microsoft/cognitive-services-speech-sdk-js/issues/465
// Which is root caused by https://github.com/TooTallNate/node-agent-base/issues/61
const uri = new URL(this.privUri);
@ -322,6 +327,75 @@ export class WebsocketMessageAdapter {
Events.instance.onEvent(event);
}
// eslint-disable-next-line @typescript-eslint/no-unused-vars
private getAgent(): http.Agent {
// eslint-disable-next-line @typescript-eslint/unbound-method
const agent: { proxyInfo: ProxyInfo } = new Agent.Agent(this.createConnection) as unknown as { proxyInfo: ProxyInfo } ;
if (this.proxyInfo !== undefined &&
this.proxyInfo.HostName !== undefined &&
this.proxyInfo.Port > 0) {
agent.proxyInfo = this.proxyInfo;
}
return agent as unknown as http.Agent;
}
private static GetProxyAgent(proxyInfo: ProxyInfo): HttpsProxyAgent {
const httpProxyOptions: HttpsProxyAgent.HttpsProxyAgentOptions = {
host: proxyInfo.HostName,
port: proxyInfo.Port,
};
if (!!proxyInfo.UserName) {
httpProxyOptions.headers = {
"Proxy-Authentication": "Basic " + new Buffer(`${proxyInfo.UserName}:${(proxyInfo.Password === undefined) ? "" : proxyInfo.Password}`).toString("base64"),
};
} else {
httpProxyOptions.headers = {};
}
httpProxyOptions.headers.requestOCSP = "true";
const httpProxyAgent: HttpsProxyAgent = new HttpsProxyAgent(httpProxyOptions);
return httpProxyAgent;
}
private createConnection(request: Agent.ClientRequest, options: Agent.RequestOptions): Promise<net.Socket> {
let socketPromise: Promise<net.Socket>;
options = {
...options,
...{
requestOCSP: true,
servername: options.host
}
};
if (!!this.proxyInfo) {
const httpProxyAgent: HttpsProxyAgent = WebsocketMessageAdapter.GetProxyAgent(this.proxyInfo);
const baseAgent: Agent.Agent = httpProxyAgent as unknown as Agent.Agent;
socketPromise = new Promise<net.Socket>((resolve: (value: net.Socket) => void, reject: (error: string | Error) => void): void => {
baseAgent.callback(request, options, (error: Error, socket: net.Socket): void => {
if (!!error) {
reject(error);
} else {
resolve(socket);
}
});
});
} else {
if (!!options.secureEndpoint) {
socketPromise = Promise.resolve(tls.connect(options));
} else {
socketPromise = Promise.resolve(net.connect(options));
}
}
return socketPromise;
}
private get isWebsocketOpen(): boolean {
return this.privWebsocketClient && this.privWebsocketClient.readyState === this.privWebsocketClient.OPEN;
}