@@ -82,44 +82,14 @@ export function shouldBypassProxy(host: string): boolean {
8282}
8383
8484/**
85- * Get proxy configuration. Sources (in order): env (HTTP_PROXY/HTTPS_PROXY), then global config
86- * from `csdx config:set:proxy --host <host> --port <port> --protocol <protocol>`.
85+ * Get proxy configuration. Priority order (per spec):
86+ * 1. Global CLI config from `csdx config:set:proxy --host <host> --port <port> --protocol <protocol>`
87+ * 2. Environment variables (HTTPS_PROXY or HTTP_PROXY)
8788 * For per-request use, prefer getProxyConfigForHost(host) so NO_PROXY overrides both sources.
8889 * @returns ProxyConfig object or undefined if no proxy is configured
8990 */
9091export function getProxyConfig ( ) : ProxyConfig | undefined {
91- // Priority 1: Environment variables (HTTPS_PROXY or HTTP_PROXY)
92- const proxyUrl = process . env . HTTPS_PROXY || process . env . HTTP_PROXY ;
93-
94- if ( proxyUrl ) {
95- try {
96- const url = new URL ( proxyUrl ) ;
97- const defaultPort = url . protocol === 'https:' ? 443 : 80 ;
98- const port = url . port ? Number . parseInt ( url . port , 10 ) : defaultPort ;
99-
100- if ( ! Number . isNaN ( port ) && port >= 1 && port <= 65535 ) {
101- const protocol = url . protocol . replace ( ':' , '' ) as 'http' | 'https' ;
102- const proxyConfig : ProxyConfig = {
103- protocol : protocol ,
104- host : url . hostname ,
105- port : port ,
106- } ;
107-
108- if ( url . username || url . password ) {
109- proxyConfig . auth = {
110- username : url . username ,
111- password : url . password ,
112- } ;
113- }
114-
115- return proxyConfig ;
116- }
117- } catch {
118- // Invalid URL, continue to check global config
119- }
120- }
121-
122- // Priority 2: Global config (csdx config:set:proxy)
92+ // Priority 1: Global config (csdx config:set:proxy)
12393 const globalProxyConfig = configStore . get ( 'proxy' ) ;
12494 if ( globalProxyConfig ) {
12595 if ( typeof globalProxyConfig === 'object' ) {
@@ -151,11 +121,42 @@ export function getProxyConfig(): ProxyConfig | undefined {
151121 return proxyConfig ;
152122 }
153123 } catch {
154- // Invalid URL, return undefined
124+ // Invalid URL, continue to check environment
155125 }
156126 }
157127 }
158128
129+ // Priority 2: Environment variables (HTTPS_PROXY or HTTP_PROXY)
130+ const proxyUrl = process . env . HTTPS_PROXY || process . env . HTTP_PROXY ;
131+
132+ if ( proxyUrl ) {
133+ try {
134+ const url = new URL ( proxyUrl ) ;
135+ const defaultPort = url . protocol === 'https:' ? 443 : 80 ;
136+ const port = url . port ? Number . parseInt ( url . port , 10 ) : defaultPort ;
137+
138+ if ( ! Number . isNaN ( port ) && port >= 1 && port <= 65535 ) {
139+ const protocol = url . protocol . replace ( ':' , '' ) as 'http' | 'https' ;
140+ const proxyConfig : ProxyConfig = {
141+ protocol : protocol ,
142+ host : url . hostname ,
143+ port : port ,
144+ } ;
145+
146+ if ( url . username || url . password ) {
147+ proxyConfig . auth = {
148+ username : url . username ,
149+ password : url . password ,
150+ } ;
151+ }
152+
153+ return proxyConfig ;
154+ }
155+ } catch {
156+ // Invalid URL, return undefined
157+ }
158+ }
159+
159160 return undefined ;
160161}
161162
@@ -172,27 +173,38 @@ export function getProxyConfigForHost(host: string): ProxyConfig | undefined {
172173 return getProxyConfig ( ) ;
173174}
174175
176+ function regionCmaHostname ( ) : string {
177+ const cma = configStore . get ( 'region' ) ?. cma ;
178+ if ( ! cma || typeof cma !== 'string' ) {
179+ return '' ;
180+ }
181+ if ( cma . startsWith ( 'http' ) ) {
182+ try {
183+ const u = new URL ( cma ) ;
184+ return u . hostname || cma ;
185+ } catch {
186+ return cma ;
187+ }
188+ }
189+ return cma ;
190+ }
191+
175192/**
176- * Resolve request host for proxy/NO_PROXY checks: config.host or default CMA from region.
177- * Use when the caller may omit host so NO_PROXY still applies (e.g. from region.cma).
178- * @param config - Object with optional host (e.g. API client config)
179- * @returns Host string (hostname or empty)
193+ * Hostname for NO_PROXY / proxy. Prefer `region.cma` when set so callers that pass a
194+ * default SDK host (e.g. bulk-entries -> api.contentstack.io) still match rules like
195+ * `.csnonprod.com` against the real API host (e.g. dev11-api.csnonprod.com).
180196 */
181197export function resolveRequestHost ( config : { host ?: string } ) : string {
182- if ( config . host ) return config . host ;
183- const cma = configStore . get ( 'region' ) ?. cma ;
184- if ( cma && typeof cma === 'string' ) {
185- if ( cma . startsWith ( 'http' ) ) {
186- try {
187- const u = new URL ( cma ) ;
188- return u . hostname || cma ;
189- } catch {
190- return cma ;
191- }
192- }
193- return cma ;
198+ const fromRegion = regionCmaHostname ( ) ;
199+ if ( fromRegion ) {
200+ return normalizeHost ( fromRegion ) || fromRegion ;
201+ }
202+
203+ const raw = config . host ?. trim ( ) || '' ;
204+ if ( ! raw ) {
205+ return '' ;
194206 }
195- return '' ;
207+ return normalizeHost ( raw ) || raw ;
196208}
197209
198210/**
0 commit comments