@serenity-js/rest 3.33.1 → 3.34.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (59) hide show
  1. package/CHANGELOG.md +27 -0
  2. package/lib/io/AxiosRequestConfigDefaults.d.ts +1 -0
  3. package/lib/io/AxiosRequestConfigDefaults.d.ts.map +1 -1
  4. package/lib/io/EnvironmentVariables.d.ts +9 -0
  5. package/lib/io/EnvironmentVariables.d.ts.map +1 -0
  6. package/lib/io/EnvironmentVariables.js +39 -0
  7. package/lib/io/EnvironmentVariables.js.map +1 -0
  8. package/lib/io/ProxyAgent.d.ts +1 -3
  9. package/lib/io/ProxyAgent.d.ts.map +1 -1
  10. package/lib/io/ProxyAgent.js +1 -2
  11. package/lib/io/ProxyAgent.js.map +1 -1
  12. package/lib/io/ProxyBypass.d.ts +6 -0
  13. package/lib/io/ProxyBypass.d.ts.map +1 -0
  14. package/lib/io/ProxyBypass.js +70 -0
  15. package/lib/io/ProxyBypass.js.map +1 -0
  16. package/lib/io/createAxios.d.ts.map +1 -1
  17. package/lib/io/createAxios.js +2 -2
  18. package/lib/io/createAxios.js.map +1 -1
  19. package/lib/io/proxy.d.ts +14 -0
  20. package/lib/io/proxy.d.ts.map +1 -0
  21. package/lib/io/proxy.js +104 -0
  22. package/lib/io/proxy.js.map +1 -0
  23. package/lib/screenplay/abilities/CallAnApi.d.ts +59 -15
  24. package/lib/screenplay/abilities/CallAnApi.d.ts.map +1 -1
  25. package/lib/screenplay/abilities/CallAnApi.js +74 -28
  26. package/lib/screenplay/abilities/CallAnApi.js.map +1 -1
  27. package/package.json +6 -7
  28. package/src/io/AxiosRequestConfigDefaults.ts +1 -0
  29. package/src/io/EnvironmentVariables.ts +39 -0
  30. package/src/io/ProxyAgent.ts +2 -5
  31. package/src/io/ProxyBypass.ts +83 -0
  32. package/src/io/createAxios.ts +1 -1
  33. package/src/io/proxy.ts +91 -0
  34. package/src/screenplay/abilities/CallAnApi.ts +74 -30
  35. package/lib/io/axiosProxyOverridesFor.d.ts +0 -11
  36. package/lib/io/axiosProxyOverridesFor.d.ts.map +0 -1
  37. package/lib/io/axiosProxyOverridesFor.js +0 -34
  38. package/lib/io/axiosProxyOverridesFor.js.map +0 -1
  39. package/lib/screenplay/abilities/proxy/ProxyAgent.d.ts +0 -54
  40. package/lib/screenplay/abilities/proxy/ProxyAgent.d.ts.map +0 -1
  41. package/lib/screenplay/abilities/proxy/ProxyAgent.js +0 -121
  42. package/lib/screenplay/abilities/proxy/ProxyAgent.js.map +0 -1
  43. package/lib/screenplay/abilities/proxy/axiosProxyOverridesFor.d.ts +0 -11
  44. package/lib/screenplay/abilities/proxy/axiosProxyOverridesFor.d.ts.map +0 -1
  45. package/lib/screenplay/abilities/proxy/axiosProxyOverridesFor.js +0 -34
  46. package/lib/screenplay/abilities/proxy/axiosProxyOverridesFor.js.map +0 -1
  47. package/lib/screenplay/abilities/proxy/createUrl.d.ts +0 -9
  48. package/lib/screenplay/abilities/proxy/createUrl.d.ts.map +0 -1
  49. package/lib/screenplay/abilities/proxy/createUrl.js +0 -29
  50. package/lib/screenplay/abilities/proxy/createUrl.js.map +0 -1
  51. package/lib/screenplay/abilities/proxy/index.d.ts +0 -2
  52. package/lib/screenplay/abilities/proxy/index.d.ts.map +0 -1
  53. package/lib/screenplay/abilities/proxy/index.js +0 -18
  54. package/lib/screenplay/abilities/proxy/index.js.map +0 -1
  55. package/src/io/axiosProxyOverridesFor.ts +0 -39
  56. package/src/screenplay/abilities/proxy/ProxyAgent.ts +0 -129
  57. package/src/screenplay/abilities/proxy/axiosProxyOverridesFor.ts +0 -39
  58. package/src/screenplay/abilities/proxy/createUrl.ts +0 -39
  59. package/src/screenplay/abilities/proxy/index.ts +0 -1
@@ -11,12 +11,6 @@ const io_1 = require("../../io");
11
11
  * the [actor](https://serenity-js.org/api/core/class/Actor/) to [send](https://serenity-js.org/api/rest/class/Send/)
12
12
  * [HTTP requests](https://serenity-js.org/api/rest/class/HTTPRequest/) to HTTP APIs.
13
13
  *
14
- * `CallAnApi` uses [`proxy-from-env`](https://www.npmjs.com/package/proxy-from-env) and an approach
15
- * described in ["Node.js Axios behind corporate proxies"](https://janmolak.com/node-js-axios-behind-corporate-proxies-8b17a6f31f9d)
16
- * to automatically detect proxy server configuration based
17
- * on your [environment variables](https://www.npmjs.com/package/proxy-from-env#environment-variables).
18
- * You can override this configuration if needed.
19
- *
20
14
  * ## Configuring the ability to call an API
21
15
  *
22
16
  * The easiest way to configure the ability to `CallAnApi` is to provide the `baseURL` of your HTTP API,
@@ -37,6 +31,12 @@ const io_1 = require("../../io");
37
31
  * )
38
32
  * ```
39
33
  *
34
+ * Please note that the following Serenity/JS test runner adapters already provide the ability to `CallAnApi` as part of their default configuration,
35
+ * so you don't need to configure it yourself:
36
+ * - [Playwright Test](https://serenity-js.org/handbook/test-runners/playwright-test/)
37
+ * - [WebdriverIO](https://serenity-js.org/handbook/test-runners/webdriverio/)
38
+ * - [Protractor](https://serenity-js.org/handbook/test-runners/protractor/)
39
+ *
40
40
  * ### Resolving relative URLs
41
41
  *
42
42
  * Serenity/JS resolves request URLs using Node.js [WHATWG URL API](https://nodejs.org/api/url.html#new-urlinput-base).
@@ -95,12 +95,34 @@ const io_1 = require("../../io");
95
95
  * )
96
96
  * ```
97
97
  *
98
- * ### Working with proxy servers
98
+ * ## Working with proxy servers
99
+ *
100
+ * `CallAnApi` uses an approach described in ["Node.js Axios behind corporate proxies"](https://janmolak.com/node-js-axios-behind-corporate-proxies-8b17a6f31f9d)
101
+ * to automatically detect proxy server configuration based on your environment variables.
102
+ *
103
+ * You can override this default proxy detection mechanism by providing your own proxy configuration object.
104
+ *
105
+ * ### Automatic proxy support
99
106
  *
100
- * `CallAnApi` uses [`proxy-from-env`](https://www.npmjs.com/package/proxy-from-env) to automatically
101
- * detect proxy server configuration based on your [environment variables](https://www.npmjs.com/package/proxy-from-env#environment-variables).
107
+ * When the URL you're sending the request to uses the HTTP protocol, Serenity/JS will automatically detect your proxy configuration based on the following environment variables:
108
+ * - `npm_config_http_proxy`
109
+ * - `http_proxy` and `HTTP_PROXY`
110
+ * - `npm_config_proxy`
111
+ * - `all_proxy`
102
112
  *
103
- * This default behaviour can be overridden by providing explicit proxy configuration:
113
+ * Similarly, when the request target URL uses the HTTPS protocol, the following environment variables are used instead:
114
+ * - `npm_config_https_proxy`
115
+ * - `https_proxy` and `HTTPS_PROXY`
116
+ * - `npm_config_proxy`
117
+ * - `all_proxy`
118
+ *
119
+ * Proxy configuration is ignored for both HTTP and HTTPS target URLs matching the proxy bypass rules defined in the following environment variables:
120
+ * - `npm_config_no_proxy`
121
+ * - `no_proxy` and `NO_PROXY`
122
+ *
123
+ * ### Custom proxy configuration
124
+ *
125
+ * To override the automatic proxy detection based on the environment variables, provide a proxy configuration object:
104
126
  *
105
127
  * ```ts
106
128
  * import { actorCalled } from '@serenity-js/core'
@@ -115,10 +137,11 @@ const io_1 = require("../../io");
115
137
  * protocol: 'http',
116
138
  * host: 'proxy.example.org',
117
139
  * port: 9000,
118
- * auth: { // `auth` is optional
140
+ * auth: { // optional
119
141
  * username: 'proxy-username',
120
142
  * password: 'proxy-password',
121
- * }
143
+ * },
144
+ * bypass: 'status.example.org, internal.example.org' // optional
122
145
  * }
123
146
  * // ... other configuration options
124
147
  * })
@@ -129,10 +152,31 @@ const io_1 = require("../../io");
129
152
  * )
130
153
  * ```
131
154
  *
132
- * Please note that Serenity/JS uses [proxy-agents](https://github.com/TooTallNate/proxy-agents)
155
+ * Note that Serenity/JS uses [proxy-agents](https://github.com/TooTallNate/proxy-agents)
133
156
  * and the approach described in ["Node.js Axios behind corporate proxies"](https://janmolak.com/node-js-axios-behind-corporate-proxies-8b17a6f31f9d)
134
157
  * to work around [limited proxy support capabilities](https://github.com/axios/axios/issues?q=is%3Aissue+is%3Aopen+proxy) in Axios itself.
135
158
  *
159
+ * ### Bypassing proxy configuration
160
+ *
161
+ * To bypass the proxy configuration for specific hostnames and IP addresses, you can either:
162
+ * - provide the `bypass` property in the proxy configuration object, or
163
+ * - use the `no_proxy` environment variable.
164
+ *
165
+ * The value of the `bypass` property or the `no_proxy` environment variable should be a comma-separated list of hostnames and IP addresses
166
+ * that should not be routed through the proxy server, for example: `.com, .serenity-js.org, .domain.com`.
167
+ *
168
+ * Note that setting the `bypass` property to `example.org` makes the requests to following URLs bypass the proxy server:
169
+ * - `api.example.org`
170
+ * - `sub.sub.example.org`
171
+ * - `example.org`
172
+ * - `my-example.org`
173
+ *
174
+ * :::info
175
+ * Serenity/JS doesn't currently support `bypass` rules expressed using CIDR notation, like `192.168.17.0/24`.
176
+ * Instead, it uses a simple comma-separated list of hostnames and IP addresses.
177
+ * If you need support for CIDR notation, please [raise an issue](https://github.com/serenity-js/serenity-js/issues).
178
+ * :::
179
+ *
136
180
  * ### Using Axios instance with proxy support
137
181
  *
138
182
  * To have full control over the Axios instance used by the ability to `CallAnApi`, you can create it yourself
@@ -147,7 +191,7 @@ const io_1 = require("../../io");
147
191
  *
148
192
  * import axiosRetry from 'axios-retry'
149
193
  *
150
- * const instance = createAxios({ baseURL 'https://api.example.org/' })
194
+ * const instance = createAxios({ baseURL: 'https://api.example.org/' })
151
195
  * axiosRetry(instance, { retries: 3 })
152
196
  *
153
197
  * await actorCalled('Apisitt')
@@ -174,7 +218,7 @@ const io_1 = require("../../io");
174
218
  * import { axiosCreate } from '@serenity-js/rest'
175
219
  * import axiosRetry from 'axios-retry'
176
220
  *
177
- * const instance = axiosCreate({ baseURL 'https://api.example.org/' })
221
+ * const instance = axiosCreate({ baseURL: 'https://api.example.org/' })
178
222
  * axiosRetry(instance, { retries: 3 })
179
223
  *
180
224
  * await actorCalled('Apisitt')
@@ -471,21 +515,23 @@ function proxyConfigFrom(defaults) {
471
515
  return undefined;
472
516
  }
473
517
  const proxyUrl = defaults.httpAgent.getProxyForUrl(defaults.baseURL);
474
- if (!proxyUrl) {
518
+ try {
519
+ const url = new node_url_1.URL(proxyUrl);
520
+ return {
521
+ protocol: url.protocol?.replace(/:$/, ''),
522
+ host: url.hostname,
523
+ port: url.port ? Number(url.port) : undefined,
524
+ auth: url.username
525
+ ? {
526
+ username: url.username || undefined,
527
+ password: url.password || undefined,
528
+ }
529
+ : undefined,
530
+ };
531
+ }
532
+ catch {
475
533
  return undefined;
476
534
  }
477
- const url = new node_url_1.URL(proxyUrl);
478
- return {
479
- protocol: url.protocol?.replace(/:$/, ''),
480
- host: url.hostname,
481
- port: url.port ? Number(url.port) : undefined,
482
- auth: url.username
483
- ? {
484
- username: url.username || undefined,
485
- password: url.password || undefined,
486
- }
487
- : undefined,
488
- };
489
535
  }
490
536
  function isUndefined(value) {
491
537
  return value === undefined;
@@ -1 +1 @@
1
- {"version":3,"file":"CallAnApi.js","sourceRoot":"","sources":["../../../src/screenplay/abilities/CallAnApi.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"CallAnApi.js","sourceRoot":"","sources":["../../../src/screenplay/abilities/CallAnApi.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@serenity-js/rest",
3
- "version": "3.33.1",
3
+ "version": "3.34.1",
4
4
  "description": "Serenity/JS Screenplay Pattern library for interacting with REST and other HTTP-based services, supporting comprehensive API testing and blended testing scenarios",
5
5
  "author": {
6
6
  "name": "Jan Molak",
@@ -51,18 +51,17 @@
51
51
  "node": "^18.12 || ^20 || ^22"
52
52
  },
53
53
  "dependencies": {
54
- "@serenity-js/core": "3.33.1",
54
+ "@serenity-js/core": "3.34.1",
55
55
  "agent-base": "7.1.4",
56
56
  "axios": "1.11.0",
57
57
  "http-proxy-agent": "7.0.2",
58
58
  "https-proxy-agent": "7.0.6",
59
59
  "lru-cache": "11.1.0",
60
- "proxy-from-env": "1.1.0",
61
- "tiny-types": "1.23.0"
60
+ "tiny-types": "1.24.1"
62
61
  },
63
62
  "devDependencies": {
64
63
  "@integration/testing-tools": "3.0.0",
65
- "@serenity-js/assertions": "3.33.1",
64
+ "@serenity-js/assertions": "3.34.1",
66
65
  "@types/chai": "4.3.20",
67
66
  "@types/mocha": "10.0.10",
68
67
  "axios-mock-adapter": "2.1.0",
@@ -70,7 +69,7 @@
70
69
  "mocha": "11.7.1",
71
70
  "mocha-multi": "1.1.7",
72
71
  "ts-node": "10.9.2",
73
- "typescript": "5.8.3"
72
+ "typescript": "5.9.2"
74
73
  },
75
- "gitHead": "11bbc2bb3f6d4d5fade2b7881b36e5259973901a"
74
+ "gitHead": "8591e154237ca715a067ff5f58351c418416e75a"
76
75
  }
@@ -8,6 +8,7 @@ export type AxiosRequestConfigProxyDefaults = {
8
8
  password: string;
9
9
  };
10
10
  protocol?: string;
11
+ bypass?: string;
11
12
  }
12
13
 
13
14
  export type AxiosRequestConfigDefaults<Data = any> = Omit<CreateAxiosDefaults<Data>, 'proxy'> & {
@@ -0,0 +1,39 @@
1
+ export class EnvironmentVariables {
2
+ constructor(private readonly env: NodeJS.ProcessEnv = process.env) {
3
+ }
4
+
5
+ isSet(name: string): boolean {
6
+ return this.env[name] !== undefined;
7
+ }
8
+
9
+ get(name: string): string | undefined {
10
+ return this.env[name];
11
+ }
12
+
13
+ find(name: string): string | undefined {
14
+ const candidateNames = [
15
+ name,
16
+ name.toLocaleUpperCase(),
17
+ name.toLocaleLowerCase(),
18
+ ];
19
+
20
+ for (const variableName of candidateNames) {
21
+ if (this.isSet(variableName)) {
22
+ return this.get(variableName);
23
+ }
24
+ }
25
+
26
+ return undefined;
27
+ }
28
+
29
+ findFirst(...names: string[]): string | undefined {
30
+ for (const name of names) {
31
+ const found = this.find(name);
32
+ if (found) {
33
+ return found;
34
+ }
35
+ }
36
+
37
+ return undefined;
38
+ }
39
+ }
@@ -6,7 +6,6 @@ import { HttpProxyAgent, type HttpProxyAgentOptions } from 'http-proxy-agent';
6
6
  import * as https from 'https';
7
7
  import { HttpsProxyAgent, type HttpsProxyAgentOptions } from 'https-proxy-agent';
8
8
  import { LRUCache } from 'lru-cache';
9
- import { getProxyForUrl as envGetProxyForUrl } from 'proxy-from-env';
10
9
 
11
10
  const protocols = [
12
11
  ...HttpProxyAgent.protocols,
@@ -34,9 +33,7 @@ export type ProxyAgentOptions =
34
33
  */
35
34
  httpsAgent?: http.Agent;
36
35
  /**
37
- * A callback for dynamic provision of proxy for url.
38
- * Defaults to standard proxy environment variables,
39
- * see https://www.npmjs.com/package/proxy-from-env for details
36
+ * A callback to dynamically determine the proxy to use for the given URL.
40
37
  */
41
38
  getProxyForUrl?: GetProxyForUrlCallback;
42
39
  };
@@ -74,7 +71,7 @@ export class ProxyAgent extends Agent {
74
71
  super(agentOptions);
75
72
  this.httpAgent = agentOptions?.httpAgent || new http.Agent(agentOptions);
76
73
  this.httpsAgent = agentOptions?.httpsAgent || new https.Agent(agentOptions as https.AgentOptions);
77
- this.getProxyForUrl = agentOptions?.getProxyForUrl || envGetProxyForUrl;
74
+ this.getProxyForUrl = agentOptions?.getProxyForUrl;
78
75
  }
79
76
 
80
77
  override async connect(request: http.ClientRequest, options: AgentConnectOpts): Promise<http.Agent> {
@@ -0,0 +1,83 @@
1
+ import type { URL } from 'node:url';
2
+
3
+ import { createUrl } from './createUrl';
4
+
5
+ export abstract class ProxyBypass {
6
+ static create(value: string | undefined): ProxyBypass {
7
+ if (value === undefined || value === '') {
8
+ return new BypassNone();
9
+ }
10
+
11
+ if (value === '*') {
12
+ return new BypassAll();
13
+ }
14
+
15
+ return new BypassMatching(value);
16
+ }
17
+
18
+ abstract matches(url: URL): boolean;
19
+ }
20
+
21
+ class BypassNone extends ProxyBypass {
22
+ matches(url_: URL): boolean {
23
+ return false;
24
+ }
25
+ }
26
+
27
+ class BypassAll extends ProxyBypass {
28
+ matches(url_: URL): boolean {
29
+ return true;
30
+ }
31
+ }
32
+
33
+ class BypassHostnamePattern extends ProxyBypass {
34
+ private static readonly template = /^((?<hostname>[^:]+)(:(?<port>\d+))?)$/;
35
+ private static defaultPorts = {
36
+ 'ftp:': '21',
37
+ 'gopher:': '70',
38
+ 'http:': '80',
39
+ 'https:': '443',
40
+ 'ws:': '80',
41
+ 'wss:': '443',
42
+ };
43
+
44
+ static create(patternConfig: string) {
45
+ const { hostname, port } = this.template.exec(patternConfig)?.groups || {};
46
+
47
+ return new BypassHostnamePattern(hostname, port);
48
+ }
49
+
50
+ private constructor(private readonly hostname: string, private readonly port: string | undefined) {
51
+ super();
52
+ }
53
+
54
+ matches(url: URL): boolean {
55
+ const urlPort = url.port || BypassHostnamePattern.defaultPorts[url.protocol]
56
+
57
+ return url.hostname.endsWith(this.hostname)
58
+ && (this.port ? urlPort === this.port : true);
59
+ }
60
+ }
61
+
62
+ class BypassMatching extends ProxyBypass {
63
+
64
+ private readonly patterns: BypassHostnamePattern[];
65
+
66
+ constructor(value: string) {
67
+ super();
68
+
69
+ this.patterns = value.split(',').map(patternConfig => BypassHostnamePattern.create(patternConfig.trim()));
70
+ }
71
+
72
+ matches(url: URL): boolean {
73
+ const normalisedUrl = createUrl(url);
74
+
75
+ for (const pattern of this.patterns) {
76
+ if (pattern.matches(normalisedUrl)) {
77
+ return true;
78
+ }
79
+ }
80
+ return false;
81
+ }
82
+ }
83
+
@@ -1,8 +1,8 @@
1
1
  import { Duration } from '@serenity-js/core';
2
2
  import axios, { Axios, type AxiosInstance, type AxiosRequestConfig } from 'axios';
3
3
 
4
- import { axiosProxyOverridesFor } from './axiosProxyOverridesFor';
5
4
  import type { AxiosRequestConfigDefaults, AxiosRequestConfigProxyDefaults } from './AxiosRequestConfigDefaults';
5
+ import { axiosProxyOverridesFor } from './proxy';
6
6
 
7
7
  /**
8
8
  * Creates an Axios instance with desired configuration and proxy support.
@@ -0,0 +1,91 @@
1
+ import type * as http from 'node:http';
2
+ import * as process from 'node:process';
3
+
4
+ import { ensure, isDefined } from 'tiny-types';
5
+
6
+ import type { AxiosRequestConfigDefaults, AxiosRequestConfigProxyDefaults } from './AxiosRequestConfigDefaults';
7
+ import { createUrl } from './createUrl';
8
+ import { EnvironmentVariables } from './EnvironmentVariables';
9
+ import { ProxyAgent } from './ProxyAgent';
10
+ import { ProxyBypass } from './ProxyBypass';
11
+
12
+ /**
13
+ * @param options
14
+ */
15
+ export function axiosProxyOverridesFor<Data = any>(options: AxiosRequestConfigDefaults<Data>): {
16
+ proxy: false, httpAgent: http.Agent, httpsAgent: http.Agent
17
+ } {
18
+ const agent = new ProxyAgent({
19
+ httpAgent: options.httpAgent,
20
+ httpsAgent: options.httpsAgent,
21
+
22
+ // if there's a specific proxy override configured, use it
23
+ // if not - detect proxy automatically based on the env variables
24
+ getProxyForUrl: options.proxy
25
+ ? createGetProxyForUrlFromConfig(options.proxy)
26
+ : createGetProxyForUrlFromEnvironmentVariables(new EnvironmentVariables(process.env)),
27
+ });
28
+
29
+ return {
30
+ proxy: false,
31
+ httpAgent: agent,
32
+ httpsAgent: agent,
33
+ };
34
+ }
35
+
36
+ export function createGetProxyForUrlFromConfig(proxyOptions: AxiosRequestConfigProxyDefaults): (url: string) => string | undefined {
37
+ const proxyBypass = ProxyBypass.create(proxyOptions?.bypass);
38
+
39
+ return createGetProxyForUrl(proxyBypass, (url: URL): string => {
40
+ return createUrl({
41
+ username: proxyOptions.auth?.username,
42
+ password: proxyOptions.auth?.password,
43
+ protocol: proxyOptions.protocol,
44
+ hostname: ensure('proxy.host', proxyOptions?.host, isDefined()),
45
+ port: proxyOptions.port ? Number(proxyOptions.port) : undefined,
46
+ }).toString();
47
+ });
48
+ }
49
+
50
+ export function createGetProxyForUrlFromEnvironmentVariables(env: EnvironmentVariables): (url: string) => string | undefined {
51
+ const proxyBypass = ProxyBypass.create(env.findFirst(
52
+ 'npm_config_no_proxy',
53
+ 'no_proxy',
54
+ ));
55
+
56
+ return createGetProxyForUrl(proxyBypass, (url: URL): string => {
57
+ const protocolName = url.protocol.replace(/:$/, '');
58
+ const proxyUrl = env.findFirst(
59
+ `npm_config_${ protocolName }_proxy`,
60
+ `${ protocolName }_proxy`,
61
+ 'npm_config_proxy',
62
+ 'all_proxy'
63
+ );
64
+
65
+ return proxyUrl || undefined;
66
+ });
67
+ }
68
+
69
+ function createGetProxyForUrl(bypass: ProxyBypass, getProxy: (url: URL) => string): (url: string) => string | undefined {
70
+ return function getProxyForUrl(urlValue: string): string | undefined {
71
+ if (! isValidUrl(urlValue)) {
72
+ return undefined;
73
+ }
74
+
75
+ const url = new URL(urlValue);
76
+
77
+ return bypass.matches(url)
78
+ ? undefined
79
+ : getProxy(url);
80
+ };
81
+ }
82
+
83
+ function isValidUrl(url: string): boolean {
84
+ try {
85
+ new URL(url);
86
+ return true;
87
+ } catch {
88
+ return false;
89
+ }
90
+ }
91
+
@@ -26,12 +26,6 @@ import { createAxios } from '../../io';
26
26
  * the [actor](https://serenity-js.org/api/core/class/Actor/) to [send](https://serenity-js.org/api/rest/class/Send/)
27
27
  * [HTTP requests](https://serenity-js.org/api/rest/class/HTTPRequest/) to HTTP APIs.
28
28
  *
29
- * `CallAnApi` uses [`proxy-from-env`](https://www.npmjs.com/package/proxy-from-env) and an approach
30
- * described in ["Node.js Axios behind corporate proxies"](https://janmolak.com/node-js-axios-behind-corporate-proxies-8b17a6f31f9d)
31
- * to automatically detect proxy server configuration based
32
- * on your [environment variables](https://www.npmjs.com/package/proxy-from-env#environment-variables).
33
- * You can override this configuration if needed.
34
- *
35
29
  * ## Configuring the ability to call an API
36
30
  *
37
31
  * The easiest way to configure the ability to `CallAnApi` is to provide the `baseURL` of your HTTP API,
@@ -52,6 +46,12 @@ import { createAxios } from '../../io';
52
46
  * )
53
47
  * ```
54
48
  *
49
+ * Please note that the following Serenity/JS test runner adapters already provide the ability to `CallAnApi` as part of their default configuration,
50
+ * so you don't need to configure it yourself:
51
+ * - [Playwright Test](https://serenity-js.org/handbook/test-runners/playwright-test/)
52
+ * - [WebdriverIO](https://serenity-js.org/handbook/test-runners/webdriverio/)
53
+ * - [Protractor](https://serenity-js.org/handbook/test-runners/protractor/)
54
+ *
55
55
  * ### Resolving relative URLs
56
56
  *
57
57
  * Serenity/JS resolves request URLs using Node.js [WHATWG URL API](https://nodejs.org/api/url.html#new-urlinput-base).
@@ -110,12 +110,34 @@ import { createAxios } from '../../io';
110
110
  * )
111
111
  * ```
112
112
  *
113
- * ### Working with proxy servers
113
+ * ## Working with proxy servers
114
+ *
115
+ * `CallAnApi` uses an approach described in ["Node.js Axios behind corporate proxies"](https://janmolak.com/node-js-axios-behind-corporate-proxies-8b17a6f31f9d)
116
+ * to automatically detect proxy server configuration based on your environment variables.
117
+ *
118
+ * You can override this default proxy detection mechanism by providing your own proxy configuration object.
119
+ *
120
+ * ### Automatic proxy support
114
121
  *
115
- * `CallAnApi` uses [`proxy-from-env`](https://www.npmjs.com/package/proxy-from-env) to automatically
116
- * detect proxy server configuration based on your [environment variables](https://www.npmjs.com/package/proxy-from-env#environment-variables).
122
+ * When the URL you're sending the request to uses the HTTP protocol, Serenity/JS will automatically detect your proxy configuration based on the following environment variables:
123
+ * - `npm_config_http_proxy`
124
+ * - `http_proxy` and `HTTP_PROXY`
125
+ * - `npm_config_proxy`
126
+ * - `all_proxy`
117
127
  *
118
- * This default behaviour can be overridden by providing explicit proxy configuration:
128
+ * Similarly, when the request target URL uses the HTTPS protocol, the following environment variables are used instead:
129
+ * - `npm_config_https_proxy`
130
+ * - `https_proxy` and `HTTPS_PROXY`
131
+ * - `npm_config_proxy`
132
+ * - `all_proxy`
133
+ *
134
+ * Proxy configuration is ignored for both HTTP and HTTPS target URLs matching the proxy bypass rules defined in the following environment variables:
135
+ * - `npm_config_no_proxy`
136
+ * - `no_proxy` and `NO_PROXY`
137
+ *
138
+ * ### Custom proxy configuration
139
+ *
140
+ * To override the automatic proxy detection based on the environment variables, provide a proxy configuration object:
119
141
  *
120
142
  * ```ts
121
143
  * import { actorCalled } from '@serenity-js/core'
@@ -130,10 +152,11 @@ import { createAxios } from '../../io';
130
152
  * protocol: 'http',
131
153
  * host: 'proxy.example.org',
132
154
  * port: 9000,
133
- * auth: { // `auth` is optional
155
+ * auth: { // optional
134
156
  * username: 'proxy-username',
135
157
  * password: 'proxy-password',
136
- * }
158
+ * },
159
+ * bypass: 'status.example.org, internal.example.org' // optional
137
160
  * }
138
161
  * // ... other configuration options
139
162
  * })
@@ -144,10 +167,31 @@ import { createAxios } from '../../io';
144
167
  * )
145
168
  * ```
146
169
  *
147
- * Please note that Serenity/JS uses [proxy-agents](https://github.com/TooTallNate/proxy-agents)
170
+ * Note that Serenity/JS uses [proxy-agents](https://github.com/TooTallNate/proxy-agents)
148
171
  * and the approach described in ["Node.js Axios behind corporate proxies"](https://janmolak.com/node-js-axios-behind-corporate-proxies-8b17a6f31f9d)
149
172
  * to work around [limited proxy support capabilities](https://github.com/axios/axios/issues?q=is%3Aissue+is%3Aopen+proxy) in Axios itself.
150
173
  *
174
+ * ### Bypassing proxy configuration
175
+ *
176
+ * To bypass the proxy configuration for specific hostnames and IP addresses, you can either:
177
+ * - provide the `bypass` property in the proxy configuration object, or
178
+ * - use the `no_proxy` environment variable.
179
+ *
180
+ * The value of the `bypass` property or the `no_proxy` environment variable should be a comma-separated list of hostnames and IP addresses
181
+ * that should not be routed through the proxy server, for example: `.com, .serenity-js.org, .domain.com`.
182
+ *
183
+ * Note that setting the `bypass` property to `example.org` makes the requests to following URLs bypass the proxy server:
184
+ * - `api.example.org`
185
+ * - `sub.sub.example.org`
186
+ * - `example.org`
187
+ * - `my-example.org`
188
+ *
189
+ * :::info
190
+ * Serenity/JS doesn't currently support `bypass` rules expressed using CIDR notation, like `192.168.17.0/24`.
191
+ * Instead, it uses a simple comma-separated list of hostnames and IP addresses.
192
+ * If you need support for CIDR notation, please [raise an issue](https://github.com/serenity-js/serenity-js/issues).
193
+ * :::
194
+ *
151
195
  * ### Using Axios instance with proxy support
152
196
  *
153
197
  * To have full control over the Axios instance used by the ability to `CallAnApi`, you can create it yourself
@@ -162,7 +206,7 @@ import { createAxios } from '../../io';
162
206
  *
163
207
  * import axiosRetry from 'axios-retry'
164
208
  *
165
- * const instance = createAxios({ baseURL 'https://api.example.org/' })
209
+ * const instance = createAxios({ baseURL: 'https://api.example.org/' })
166
210
  * axiosRetry(instance, { retries: 3 })
167
211
  *
168
212
  * await actorCalled('Apisitt')
@@ -189,7 +233,7 @@ import { createAxios } from '../../io';
189
233
  * import { axiosCreate } from '@serenity-js/rest'
190
234
  * import axiosRetry from 'axios-retry'
191
235
  *
192
- * const instance = axiosCreate({ baseURL 'https://api.example.org/' })
236
+ * const instance = axiosCreate({ baseURL: 'https://api.example.org/' })
193
237
  * axiosRetry(instance, { retries: 3 })
194
238
  *
195
239
  * await actorCalled('Apisitt')
@@ -505,23 +549,23 @@ function proxyConfigFrom(defaults: AxiosDefaults): AxiosRequestConfigProxyDefaul
505
549
 
506
550
  const proxyUrl = (defaults.httpAgent as any).getProxyForUrl(defaults.baseURL);
507
551
 
508
- if (! proxyUrl) {
552
+ try {
553
+ const url = new URL(proxyUrl);
554
+ return {
555
+ protocol: url.protocol?.replace(/:$/, ''),
556
+ host: url.hostname,
557
+ port: url.port ? Number(url.port) : undefined,
558
+ auth: url.username
559
+ ? {
560
+ username: url.username || undefined,
561
+ password: url.password || undefined,
562
+ }
563
+ : undefined,
564
+ };
565
+ }
566
+ catch {
509
567
  return undefined;
510
568
  }
511
-
512
- const url = new URL(proxyUrl);
513
-
514
- return {
515
- protocol: url.protocol?.replace(/:$/, ''),
516
- host: url.hostname,
517
- port: url.port ? Number(url.port) : undefined,
518
- auth: url.username
519
- ? {
520
- username: url.username || undefined,
521
- password: url.password || undefined,
522
- }
523
- : undefined,
524
- };
525
569
  }
526
570
 
527
571
  function isUndefined(value: any): value is undefined {
@@ -1,11 +0,0 @@
1
- import type * as http from 'http';
2
- import type { AxiosRequestConfigDefaults } from './AxiosRequestConfigDefaults';
3
- /**
4
- * @param options
5
- */
6
- export declare function axiosProxyOverridesFor<Data = any>(options: AxiosRequestConfigDefaults<Data>): {
7
- proxy: false;
8
- httpAgent: http.Agent;
9
- httpsAgent: http.Agent;
10
- };
11
- //# sourceMappingURL=axiosProxyOverridesFor.d.ts.map