@juspay/neurolink 12.49.2 → 12.49.3
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.
|
@@ -4,14 +4,19 @@
|
|
|
4
4
|
* Supports comprehensive NO_PROXY pattern matching including wildcards, domains, ports, and CIDR
|
|
5
5
|
*/
|
|
6
6
|
/**
|
|
7
|
-
*
|
|
7
|
+
* NO_PROXY bypass check. The value is a comma- or space-separated list; each
|
|
8
|
+
* entry is matched case-insensitively.
|
|
8
9
|
*
|
|
9
|
-
* Supported
|
|
10
|
+
* Supported entries:
|
|
10
11
|
* - "*" - bypass all requests
|
|
11
|
-
* - "example.com" -
|
|
12
|
-
* - "
|
|
13
|
-
*
|
|
14
|
-
* - "
|
|
12
|
+
* - "example.com", ".example.com", "*.example.com" - the host and any subdomain
|
|
13
|
+
* - "example.com:8443" - the same, on that port only; a URL without a port is
|
|
14
|
+
* on the scheme's default (80 for http, 443 for https)
|
|
15
|
+
* - "example.com." - the same as "example.com": one trailing dot is ignored on
|
|
16
|
+
* an entry and on the URL's host name, so "https://api.example.com./" matches
|
|
17
|
+
* - "192.168.1.10", "::1", "[::1]:8080" - an IP literal, exactly
|
|
18
|
+
* - "192.168.1.0/24" - an IPv4 CIDR range, for IPv4 literal targets (IPv6 CIDR
|
|
19
|
+
* ranges are not supported)
|
|
15
20
|
*
|
|
16
21
|
* @param targetUrl - The URL to check for proxy bypass
|
|
17
22
|
* @param noProxyEnv - Optional NO_PROXY environment variable value (if not provided, reads from process.env)
|
|
@@ -27,15 +27,124 @@ function isIpInCIDR(ip, cidr) {
|
|
|
27
27
|
return false;
|
|
28
28
|
}
|
|
29
29
|
}
|
|
30
|
+
const IPV4_LITERAL = /^\d{1,3}(\.\d{1,3}){3}$/;
|
|
30
31
|
/**
|
|
31
|
-
*
|
|
32
|
+
* The form a URL gives an IPv6 literal (`[::1]`, lower-case, compressed), so
|
|
33
|
+
* `[0:0:0:0:0:0:0:1]` and `[::1]` compare equal. `null` when it is not one.
|
|
34
|
+
*/
|
|
35
|
+
function canonicalIpv6Host(address) {
|
|
36
|
+
try {
|
|
37
|
+
return new URL(`http://[${address}]`).hostname;
|
|
38
|
+
}
|
|
39
|
+
catch {
|
|
40
|
+
return null;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
/** A fully qualified name's trailing dot, which a URL keeps and curl ignores. */
|
|
44
|
+
function withoutTrailingDot(name) {
|
|
45
|
+
return name.endsWith(".") ? name.slice(0, -1) : name;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* curl's rules for one list entry: an optional leading `.` or `*.` is ignored;
|
|
49
|
+
* the entry names that host and every subdomain of it, an IP literal only
|
|
50
|
+
* itself; and a `:port` restricts it to that port. IPv6 is written bare (`::1`)
|
|
51
|
+
* or bracketed (`[::1]:8080`), and only the bracketed form can carry a port.
|
|
52
|
+
* One trailing dot is ignored on the entry's domain and on the URL's host name,
|
|
53
|
+
* so `example.com.` and `example.com` name the same host; an entry made only of
|
|
54
|
+
* dots names none.
|
|
55
|
+
*/
|
|
56
|
+
function matchesNoProxyEntry(entry, hostname, port) {
|
|
57
|
+
let host = entry;
|
|
58
|
+
let entryPort;
|
|
59
|
+
if (entry.startsWith("[")) {
|
|
60
|
+
const close = entry.indexOf("]");
|
|
61
|
+
if (close === -1) {
|
|
62
|
+
return false;
|
|
63
|
+
}
|
|
64
|
+
host = entry.slice(0, close + 1);
|
|
65
|
+
const rest = entry.slice(close + 1);
|
|
66
|
+
if (rest !== "") {
|
|
67
|
+
if (!/^:\d+$/.test(rest)) {
|
|
68
|
+
return false;
|
|
69
|
+
}
|
|
70
|
+
entryPort = rest.slice(1);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
else {
|
|
74
|
+
const colons = entry.split(":").length - 1;
|
|
75
|
+
if (colons === 1) {
|
|
76
|
+
const separator = entry.indexOf(":");
|
|
77
|
+
host = entry.slice(0, separator);
|
|
78
|
+
entryPort = entry.slice(separator + 1);
|
|
79
|
+
if (!/^\d+$/.test(entryPort)) {
|
|
80
|
+
return false;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
else if (colons > 1) {
|
|
84
|
+
host = `[${entry}]`;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
if (entryPort !== undefined && entryPort !== port) {
|
|
88
|
+
return false;
|
|
89
|
+
}
|
|
90
|
+
if (host.startsWith("[")) {
|
|
91
|
+
return canonicalIpv6Host(host.slice(1, -1)) === hostname;
|
|
92
|
+
}
|
|
93
|
+
host = host.replace(/^(\*\.|\.)/, "");
|
|
94
|
+
if (/^\.*$/.test(host) || /[\s*/]/.test(host)) {
|
|
95
|
+
return false;
|
|
96
|
+
}
|
|
97
|
+
if (IPV4_LITERAL.test(host)) {
|
|
98
|
+
return hostname === host;
|
|
99
|
+
}
|
|
100
|
+
const domain = withoutTrailingDot(host);
|
|
101
|
+
// curl does not take "127.0.0.1." for an address, so it names nothing.
|
|
102
|
+
if (IPV4_LITERAL.test(domain)) {
|
|
103
|
+
return false;
|
|
104
|
+
}
|
|
105
|
+
const name = withoutTrailingDot(hostname);
|
|
106
|
+
return name === domain || name.endsWith(`.${domain}`);
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* The rules this function applied before it followed curl, unchanged and still
|
|
110
|
+
* consulted, so that a configuration that bypassed the proxy through them keeps
|
|
111
|
+
* doing so. That includes where they are looser than curl (`.example.com` also
|
|
112
|
+
* matches `notexample.com`) and an IPv4 CIDR range such as `192.168.1.0/24`,
|
|
113
|
+
* which curl-style entries do not express.
|
|
114
|
+
*/
|
|
115
|
+
function matchesLegacyNoProxyEntry(lowerPattern, hostname, port) {
|
|
116
|
+
// Domain suffix match (.example.com)
|
|
117
|
+
if (lowerPattern.startsWith(".")) {
|
|
118
|
+
const suffix = lowerPattern.slice(1);
|
|
119
|
+
return hostname.endsWith(suffix) || hostname === suffix;
|
|
120
|
+
}
|
|
121
|
+
// Port-specific match (hostname:port)
|
|
122
|
+
if (lowerPattern.includes(":")) {
|
|
123
|
+
const [patternHost, patternPort] = lowerPattern.split(":");
|
|
124
|
+
return hostname === patternHost && port === patternPort;
|
|
125
|
+
}
|
|
126
|
+
// CIDR notation (192.168.1.0/24) - only for IP addresses
|
|
127
|
+
if (lowerPattern.includes("/")) {
|
|
128
|
+
// Only apply CIDR when target is an IP literal
|
|
129
|
+
return IPV4_LITERAL.test(hostname) && isIpInCIDR(hostname, lowerPattern);
|
|
130
|
+
}
|
|
131
|
+
// Exact hostname match
|
|
132
|
+
return hostname === lowerPattern;
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* NO_PROXY bypass check. The value is a comma- or space-separated list; each
|
|
136
|
+
* entry is matched case-insensitively.
|
|
32
137
|
*
|
|
33
|
-
* Supported
|
|
138
|
+
* Supported entries:
|
|
34
139
|
* - "*" - bypass all requests
|
|
35
|
-
* - "example.com" -
|
|
36
|
-
* - "
|
|
37
|
-
*
|
|
38
|
-
* - "
|
|
140
|
+
* - "example.com", ".example.com", "*.example.com" - the host and any subdomain
|
|
141
|
+
* - "example.com:8443" - the same, on that port only; a URL without a port is
|
|
142
|
+
* on the scheme's default (80 for http, 443 for https)
|
|
143
|
+
* - "example.com." - the same as "example.com": one trailing dot is ignored on
|
|
144
|
+
* an entry and on the URL's host name, so "https://api.example.com./" matches
|
|
145
|
+
* - "192.168.1.10", "::1", "[::1]:8080" - an IP literal, exactly
|
|
146
|
+
* - "192.168.1.0/24" - an IPv4 CIDR range, for IPv4 literal targets (IPv6 CIDR
|
|
147
|
+
* ranges are not supported)
|
|
39
148
|
*
|
|
40
149
|
* @param targetUrl - The URL to check for proxy bypass
|
|
41
150
|
* @param noProxyEnv - Optional NO_PROXY environment variable value (if not provided, reads from process.env)
|
|
@@ -51,7 +160,7 @@ export function shouldBypassProxy(targetUrl, noProxyEnv) {
|
|
|
51
160
|
const hostname = url.hostname.toLowerCase();
|
|
52
161
|
const port = url.port || (url.protocol === "https:" ? "443" : "80");
|
|
53
162
|
const patterns = noProxy
|
|
54
|
-
.split(
|
|
163
|
+
.split(/[,\s]+/)
|
|
55
164
|
.map((p) => p.trim())
|
|
56
165
|
.filter(Boolean);
|
|
57
166
|
for (const pattern of patterns) {
|
|
@@ -60,30 +169,8 @@ export function shouldBypassProxy(targetUrl, noProxyEnv) {
|
|
|
60
169
|
if (lowerPattern === "*") {
|
|
61
170
|
return true;
|
|
62
171
|
}
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
const suffix = lowerPattern.slice(1);
|
|
66
|
-
if (hostname.endsWith(suffix) || hostname === suffix) {
|
|
67
|
-
return true;
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
// Port-specific match (hostname:port)
|
|
71
|
-
else if (lowerPattern.includes(":")) {
|
|
72
|
-
const [patternHost, patternPort] = lowerPattern.split(":");
|
|
73
|
-
if (hostname === patternHost && port === patternPort) {
|
|
74
|
-
return true;
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
// CIDR notation (192.168.1.0/24) - only for IP addresses
|
|
78
|
-
else if (lowerPattern.includes("/")) {
|
|
79
|
-
// Only apply CIDR when target is an IP literal
|
|
80
|
-
if (/^\d{1,3}(\.\d{1,3}){3}$/.test(hostname) &&
|
|
81
|
-
isIpInCIDR(hostname, lowerPattern)) {
|
|
82
|
-
return true;
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
// Exact hostname match
|
|
86
|
-
else if (hostname === lowerPattern) {
|
|
172
|
+
if (matchesNoProxyEntry(lowerPattern, hostname, port) ||
|
|
173
|
+
matchesLegacyNoProxyEntry(lowerPattern, hostname, port)) {
|
|
87
174
|
return true;
|
|
88
175
|
}
|
|
89
176
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@juspay/neurolink",
|
|
3
|
-
"version": "12.49.
|
|
3
|
+
"version": "12.49.3",
|
|
4
4
|
"packageManager": "pnpm@10.15.1",
|
|
5
5
|
"description": "The pipe layer of an AI nervous system: one interface connecting provider neurons to your application, across three inference types — generate, stream and decide. `decide` returns typed, calibrated judgements from a non-generative model (~400ms, ~$0.00002/call) for routing, tool selection and context budgeting. MCP-native (4 transports), voice TTS/STT/realtime, RAG, agents, memory, compaction, 9 observability exporters. OpenAI · Anthropic · Gemini · Bedrock · Azure · Ollama · TypeSafe Jev and more.",
|
|
6
6
|
"author": {
|