1 |
|
2 |
|
3 |
|
4 | import {
|
5 | BaseRequestPolicy,
|
6 | RequestPolicy,
|
7 | RequestPolicyFactory,
|
8 | RequestPolicyOptionsLike,
|
9 | } from "./requestPolicy";
|
10 | import { HttpOperationResponse } from "../httpOperationResponse";
|
11 | import { ProxySettings } from "../serviceClient";
|
12 | import { WebResourceLike } from "../webResource";
|
13 | import { Constants } from "../util/constants";
|
14 | import { URLBuilder } from "../url";
|
15 |
|
16 |
|
17 |
|
18 |
|
19 | export const noProxyList: string[] = loadNoProxy();
|
20 | const byPassedList: Map<string, boolean> = new Map();
|
21 |
|
22 |
|
23 |
|
24 |
|
25 | export function getEnvironmentValue(name: string): string | undefined {
|
26 | if (process.env[name]) {
|
27 | return process.env[name];
|
28 | } else if (process.env[name.toLowerCase()]) {
|
29 | return process.env[name.toLowerCase()];
|
30 | }
|
31 | return undefined;
|
32 | }
|
33 |
|
34 | function loadEnvironmentProxyValue(): string | undefined {
|
35 | if (!process) {
|
36 | return undefined;
|
37 | }
|
38 |
|
39 | const httpsProxy = getEnvironmentValue(Constants.HTTPS_PROXY);
|
40 | const allProxy = getEnvironmentValue(Constants.ALL_PROXY);
|
41 | const httpProxy = getEnvironmentValue(Constants.HTTP_PROXY);
|
42 |
|
43 | return httpsProxy || allProxy || httpProxy;
|
44 | }
|
45 |
|
46 |
|
47 |
|
48 |
|
49 | function isBypassed(uri: string): boolean | undefined {
|
50 | if (noProxyList.length === 0) {
|
51 | return false;
|
52 | }
|
53 | const host = URLBuilder.parse(uri).getHost()!;
|
54 | if (byPassedList.has(host)) {
|
55 | return byPassedList.get(host);
|
56 | }
|
57 | let isBypassedFlag = false;
|
58 | for (const pattern of noProxyList) {
|
59 | if (pattern[0] === ".") {
|
60 |
|
61 |
|
62 | if (host.endsWith(pattern)) {
|
63 | isBypassedFlag = true;
|
64 | } else {
|
65 | if (host.length === pattern.length - 1 && host === pattern.slice(1)) {
|
66 | isBypassedFlag = true;
|
67 | }
|
68 | }
|
69 | } else {
|
70 | if (host === pattern) {
|
71 | isBypassedFlag = true;
|
72 | }
|
73 | }
|
74 | }
|
75 | byPassedList.set(host, isBypassedFlag);
|
76 | return isBypassedFlag;
|
77 | }
|
78 |
|
79 |
|
80 |
|
81 |
|
82 | export function loadNoProxy(): string[] {
|
83 | const noProxy = getEnvironmentValue(Constants.NO_PROXY);
|
84 | if (noProxy) {
|
85 | return noProxy
|
86 | .split(",")
|
87 | .map((item) => item.trim())
|
88 | .filter((item) => item.length);
|
89 | }
|
90 |
|
91 | return [];
|
92 | }
|
93 |
|
94 |
|
95 |
|
96 |
|
97 | function extractAuthFromUrl(
|
98 | url: string
|
99 | ): { username?: string; password?: string; urlWithoutAuth: string } {
|
100 | const atIndex = url.indexOf("@");
|
101 | if (atIndex === -1) {
|
102 | return { urlWithoutAuth: url };
|
103 | }
|
104 |
|
105 | const schemeIndex = url.indexOf("://");
|
106 | const authStart = schemeIndex !== -1 ? schemeIndex + 3 : 0;
|
107 | const auth = url.substring(authStart, atIndex);
|
108 | const colonIndex = auth.indexOf(":");
|
109 | const hasPassword = colonIndex !== -1;
|
110 | const username = hasPassword ? auth.substring(0, colonIndex) : auth;
|
111 | const password = hasPassword ? auth.substring(colonIndex + 1) : undefined;
|
112 | const urlWithoutAuth = url.substring(0, authStart) + url.substring(atIndex + 1);
|
113 | return {
|
114 | username,
|
115 | password,
|
116 | urlWithoutAuth,
|
117 | };
|
118 | }
|
119 |
|
120 | export function getDefaultProxySettings(proxyUrl?: string): ProxySettings | undefined {
|
121 | if (!proxyUrl) {
|
122 | proxyUrl = loadEnvironmentProxyValue();
|
123 | if (!proxyUrl) {
|
124 | return undefined;
|
125 | }
|
126 | }
|
127 |
|
128 | const { username, password, urlWithoutAuth } = extractAuthFromUrl(proxyUrl);
|
129 | const parsedUrl = URLBuilder.parse(urlWithoutAuth);
|
130 | const schema = parsedUrl.getScheme() ? parsedUrl.getScheme() + "://" : "";
|
131 | return {
|
132 | host: schema + parsedUrl.getHost(),
|
133 | port: Number.parseInt(parsedUrl.getPort() || "80"),
|
134 | username,
|
135 | password,
|
136 | };
|
137 | }
|
138 |
|
139 | export function proxyPolicy(proxySettings?: ProxySettings): RequestPolicyFactory {
|
140 | if (!proxySettings) {
|
141 | proxySettings = getDefaultProxySettings();
|
142 | }
|
143 | return {
|
144 | create: (nextPolicy: RequestPolicy, options: RequestPolicyOptionsLike) => {
|
145 | return new ProxyPolicy(nextPolicy, options, proxySettings!);
|
146 | },
|
147 | };
|
148 | }
|
149 |
|
150 | export class ProxyPolicy extends BaseRequestPolicy {
|
151 | proxySettings: ProxySettings;
|
152 |
|
153 | constructor(
|
154 | nextPolicy: RequestPolicy,
|
155 | options: RequestPolicyOptionsLike,
|
156 | proxySettings: ProxySettings
|
157 | ) {
|
158 | super(nextPolicy, options);
|
159 | this.proxySettings = proxySettings;
|
160 | }
|
161 |
|
162 | public sendRequest(request: WebResourceLike): Promise<HttpOperationResponse> {
|
163 | if (!request.proxySettings && !isBypassed(request.url)) {
|
164 | request.proxySettings = this.proxySettings;
|
165 | }
|
166 | return this._nextPolicy.sendRequest(request);
|
167 | }
|
168 | }
|