зеркало из https://github.com/Azure/ms-rest-js.git
Add proxy support using tunnel package
This commit is contained in:
Родитель
0632d022c1
Коммит
5f2b44c718
|
@ -1,7 +1,7 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
|
||||
import axios, { AxiosError, AxiosRequestConfig, AxiosResponse } from "axios";
|
||||
import axios, { AxiosError, AxiosRequestConfig, AxiosResponse, AxiosProxyConfig, AxiosInstance } from "axios";
|
||||
import { Transform, Readable } from "stream";
|
||||
import FormData from "form-data";
|
||||
import * as tough from "tough-cookie";
|
||||
|
@ -10,15 +10,14 @@ import { HttpHeaders } from "./httpHeaders";
|
|||
import { HttpOperationResponse } from "./httpOperationResponse";
|
||||
import { RestError } from "./restError";
|
||||
import { WebResource, HttpRequestBody } from "./webResource";
|
||||
|
||||
const axiosClient = axios.create();
|
||||
// Workaround for https://github.com/axios/axios/issues/1158
|
||||
axiosClient.interceptors.request.use(config => ({ ...config, method: config.method && config.method.toUpperCase() as any }));
|
||||
import { ProxySettings } from "./serviceClient";
|
||||
import * as tunnel from "tunnel";
|
||||
|
||||
/**
|
||||
* A HttpClient implementation that uses axios to send HTTP requests.
|
||||
*/
|
||||
export class AxiosHttpClient implements HttpClient {
|
||||
// public static readonly axiosClient = axios.create();
|
||||
private readonly cookieJar = new tough.CookieJar();
|
||||
|
||||
public async sendRequest(httpRequest: WebResource): Promise<HttpOperationResponse> {
|
||||
|
@ -96,8 +95,8 @@ export class AxiosHttpClient implements HttpClient {
|
|||
// Workaround for https://github.com/axios/axios/issues/755
|
||||
// tslint:disable-next-line:no-null-keyword
|
||||
typeof httpRequestBody === "undefined" ? null :
|
||||
typeof httpRequestBody === "function" ? httpRequestBody() :
|
||||
httpRequestBody;
|
||||
typeof httpRequestBody === "function" ? httpRequestBody() :
|
||||
httpRequestBody;
|
||||
|
||||
const onUploadProgress = httpRequest.onUploadProgress;
|
||||
if (onUploadProgress && axiosBody) {
|
||||
|
@ -130,8 +129,24 @@ export class AxiosHttpClient implements HttpClient {
|
|||
maxContentLength: 1024 * 1024 * 1024 * 10,
|
||||
responseType: httpRequest.streamResponseBody ? "stream" : "text",
|
||||
cancelToken,
|
||||
timeout: httpRequest.timeout
|
||||
timeout: httpRequest.timeout,
|
||||
};
|
||||
|
||||
let axiosClient: AxiosInstance;
|
||||
if (httpRequest.proxySettings) {
|
||||
const agent = tunnel.httpsOverHttp({
|
||||
proxy: {
|
||||
host: httpRequest.proxySettings.host,
|
||||
port: httpRequest.proxySettings.port,
|
||||
headers: {}
|
||||
}
|
||||
});
|
||||
|
||||
axiosClient = axios.create({ httpAgent: agent, proxy: false });
|
||||
} else {
|
||||
axiosClient = axios.create();
|
||||
}
|
||||
|
||||
res = await axiosClient(config);
|
||||
} catch (err) {
|
||||
if (err instanceof axios.Cancel) {
|
||||
|
@ -198,6 +213,25 @@ export class AxiosHttpClient implements HttpClient {
|
|||
}
|
||||
}
|
||||
|
||||
export function convertToAxiosProxyConfig(proxySettings: ProxySettings | undefined): AxiosProxyConfig | undefined {
|
||||
if (!proxySettings) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const axiosAuthConfig = (proxySettings.username && proxySettings.password) ? {
|
||||
username: proxySettings.username,
|
||||
password: proxySettings.password
|
||||
} : undefined;
|
||||
|
||||
const axiosProxyConfig: AxiosProxyConfig = {
|
||||
host: proxySettings.host,
|
||||
port: proxySettings.port,
|
||||
auth: axiosAuthConfig
|
||||
};
|
||||
|
||||
return axiosProxyConfig;
|
||||
}
|
||||
|
||||
function isReadableStream(body: any): body is Readable {
|
||||
return typeof body.pipe === "function";
|
||||
}
|
||||
|
|
|
@ -0,0 +1,68 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
|
||||
import { BaseRequestPolicy, RequestPolicy, RequestPolicyFactory, RequestPolicyOptions } from "./requestPolicy";
|
||||
import { HttpOperationResponse } from "../httpOperationResponse";
|
||||
import { ProxySettings } from "../serviceClient";
|
||||
import { WebResource } from "../webResource";
|
||||
import { Constants } from "../util/constants";
|
||||
import { URLBuilder } from "../url";
|
||||
|
||||
function loadEnvironmentProxyValue(): string | undefined {
|
||||
if (!process) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
let proxyUrl = undefined;
|
||||
if (process.env[Constants.HTTPS_PROXY]) {
|
||||
proxyUrl = process.env[Constants.HTTPS_PROXY];
|
||||
} else if (process.env[Constants.HTTPS_PROXY.toLowerCase()]) {
|
||||
proxyUrl = process.env[Constants.HTTPS_PROXY.toLowerCase()];
|
||||
} else if (process.env[Constants.HTTP_PROXY]) {
|
||||
proxyUrl = process.env[Constants.HTTP_PROXY];
|
||||
} else if (process.env[Constants.HTTP_PROXY.toLowerCase()]) {
|
||||
proxyUrl = process.env[Constants.HTTP_PROXY.toLowerCase()];
|
||||
}
|
||||
|
||||
return proxyUrl;
|
||||
}
|
||||
|
||||
export function getDefaultProxySettings(proxyUrl?: string): ProxySettings | undefined {
|
||||
if (!proxyUrl) {
|
||||
proxyUrl = loadEnvironmentProxyValue();
|
||||
if (!proxyUrl) {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
const parsedUrl = URLBuilder.parse(proxyUrl);
|
||||
return {
|
||||
host: parsedUrl.getScheme() + "//" + parsedUrl.getHost(),
|
||||
port: Number.parseInt(parsedUrl.getPort() || "80")
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
export function proxyPolicy(proxySettings?: ProxySettings): RequestPolicyFactory {
|
||||
return {
|
||||
create: (nextPolicy: RequestPolicy, options: RequestPolicyOptions) => {
|
||||
return new ProxyPolicy(nextPolicy, options, proxySettings!);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export class ProxyPolicy extends BaseRequestPolicy {
|
||||
proxySettings: ProxySettings;
|
||||
|
||||
constructor(nextPolicy: RequestPolicy, options: RequestPolicyOptions, proxySettings: ProxySettings) {
|
||||
super(nextPolicy, options);
|
||||
this.proxySettings = proxySettings;
|
||||
}
|
||||
|
||||
public sendRequest(request: WebResource): Promise<HttpOperationResponse> {
|
||||
if (!request.proxySettings) {
|
||||
request.proxySettings = this.proxySettings;
|
||||
}
|
||||
return this._nextPolicy.sendRequest(request);
|
||||
}
|
||||
}
|
|
@ -26,6 +26,17 @@ import { stringifyXML } from "./util/xml";
|
|||
import { RequestOptionsBase, RequestPrepareOptions, WebResource } from "./webResource";
|
||||
import { OperationResponse } from "./operationResponse";
|
||||
import { ServiceCallback } from "./util/utils";
|
||||
import { proxyPolicy, getDefaultProxySettings } from "./policies/proxyPolicy";
|
||||
|
||||
/**
|
||||
* HTTP proxy settings (Node.js only)
|
||||
*/
|
||||
export interface ProxySettings {
|
||||
host: string;
|
||||
port: number;
|
||||
username?: string;
|
||||
password?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Options to be provided while creating the client.
|
||||
|
@ -74,6 +85,10 @@ export interface ServiceClientOptions {
|
|||
* The string to be set to the telemetry header while sending the request.
|
||||
*/
|
||||
userAgent?: string;
|
||||
/**
|
||||
* Proxy settings which will be used for every HTTP request (Node.js only).
|
||||
*/
|
||||
proxySettings?: ProxySettings;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -369,6 +384,10 @@ function createDefaultRequestPolicyFactories(credentials: ServiceClientCredentia
|
|||
|
||||
factories.push(deserializationPolicy(options.deserializationContentTypes));
|
||||
|
||||
if (options.proxySettings || (options.proxySettings = getDefaultProxySettings())) {
|
||||
factories.push(proxyPolicy(options.proxySettings));
|
||||
}
|
||||
|
||||
return factories;
|
||||
}
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@ import { Mapper, Serializer } from "./serializer";
|
|||
import { generateUuid } from "./util/utils";
|
||||
import { HttpOperationResponse } from "./httpOperationResponse";
|
||||
import { OperationResponse } from "./operationResponse";
|
||||
import { ProxySettings } from "./serviceClient";
|
||||
|
||||
export type HttpMethods = "GET" | "PUT" | "POST" | "DELETE" | "PATCH" | "HEAD" | "OPTIONS" | "TRACE";
|
||||
export type HttpRequestBody = Blob | string | ArrayBuffer | ArrayBufferView | (() => NodeJS.ReadableStream);
|
||||
|
@ -64,6 +65,7 @@ export class WebResource {
|
|||
operationSpec?: OperationSpec;
|
||||
withCredentials: boolean;
|
||||
timeout: number;
|
||||
proxySettings?: ProxySettings;
|
||||
|
||||
abortSignal?: AbortSignalLike;
|
||||
|
||||
|
@ -84,7 +86,8 @@ export class WebResource {
|
|||
abortSignal?: AbortSignalLike,
|
||||
timeout?: number,
|
||||
onUploadProgress?: (progress: TransferProgressEvent) => void,
|
||||
onDownloadProgress?: (progress: TransferProgressEvent) => void) {
|
||||
onDownloadProgress?: (progress: TransferProgressEvent) => void,
|
||||
proxySettings?: ProxySettings) {
|
||||
|
||||
this.streamResponseBody = streamResponseBody;
|
||||
this.url = url || "";
|
||||
|
@ -98,6 +101,7 @@ export class WebResource {
|
|||
this.timeout = timeout || 0;
|
||||
this.onUploadProgress = onUploadProgress;
|
||||
this.onDownloadProgress = onDownloadProgress;
|
||||
this.proxySettings = proxySettings;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
"email": "azsdkteam@microsoft.com",
|
||||
"url": "https://github.com/Azure/ms-rest-js"
|
||||
},
|
||||
"version": "1.0.0",
|
||||
"version": "1.1.0",
|
||||
"description": "Isomorphic client Runtime for Typescript/node.js/browser javascript client libraries generated using AutoRest",
|
||||
"tags": [
|
||||
"isomorphic",
|
||||
|
@ -52,6 +52,7 @@
|
|||
"form-data": "^2.3.2",
|
||||
"tough-cookie": "^2.4.3",
|
||||
"tslib": "^1.9.2",
|
||||
"tunnel": "0.0.6",
|
||||
"uuid": "^3.2.1",
|
||||
"xml2js": "^0.4.19"
|
||||
},
|
||||
|
@ -63,6 +64,7 @@
|
|||
"@types/node": "^10.11.4",
|
||||
"@types/should": "^8.3.0",
|
||||
"@types/tough-cookie": "^2.3.3",
|
||||
"@types/tunnel": "0.0.0",
|
||||
"@types/uuid": "^3.4.4",
|
||||
"@types/webpack": "^4.4.13",
|
||||
"@types/webpack-dev-middleware": "^2.0.2",
|
||||
|
|
Загрузка…
Ссылка в новой задаче