1
1
import * as url from 'url' ;
2
2
import * as domain from 'domain' ;
3
3
import * as domainContext from 'domain-context' ;
4
+ import * as isAbsoluteUrl from 'is-absolute-url' ;
4
5
import { baseUrl } from './main' ;
5
6
const isomorphicFetch = require ( 'isomorphic-fetch' ) ;
6
7
const isNode = typeof process === 'object' && process . versions && ! ! process . versions . node ;
8
+ const nodeHttps = isNode && require ( 'https' ) ;
7
9
8
10
function issueRequest ( baseUrl : string , req : string | Request , init ?: RequestInit ) : Promise < any > {
11
+ const reqUrl = ( req instanceof Request ) ? req . url : req ;
12
+ const isRelativeUrl = reqUrl && ! isAbsoluteUrl ( reqUrl ) ;
13
+
9
14
// Resolve relative URLs
10
15
if ( baseUrl ) {
11
16
if ( req instanceof Request ) {
@@ -25,9 +30,42 @@ function issueRequest(baseUrl: string, req: string | Request, init?: RequestInit
25
30
` ) ;
26
31
}
27
32
33
+ init = applyHttpsAgentPolicy ( init , isRelativeUrl ) ;
28
34
return isomorphicFetch ( req , init ) ;
29
35
}
30
36
37
+ function applyHttpsAgentPolicy ( init : RequestInit , isRelativeUrl : boolean ) : RequestInit {
38
+ // HTTPS is awkward in Node because it uses a built-in list of CAs, rather than recognizing
39
+ // the OS's system-level CA list. There are dozens of issues filed against Node about this,
40
+ // but still (as of v8.0.0) no resolution besides manually duplicating your CA config.
41
+ //
42
+ // The biggest problem for typical isomorphic-SPA development this causes is that if you're
43
+ // using a self-signed localhost cert in development, Node won't be able to make API calls
44
+ // to it (e.g., https://github.com/aspnet/JavaScriptServices/issues/1089). Developers could
45
+ // fix this by either manually configuring the cert in Node (which is extremely inconvenient,
46
+ // especially if multiple devs on a team have different self-signed localhost certs), or by
47
+ // disabling cert verification on their API requests.
48
+ //
49
+ // Fortunately, 'domain-task/fetch' knows when you're making a relative-URL request to your
50
+ // own web server (as opposed to an arbitrary request to anywhere else). In this specific case,
51
+ // there's no real point in cert verification, since the request never even leaves the machine
52
+ // so a MitM attack isn't meaningful. So by default, when your code is running in Node and
53
+ // is making a relative-URL request, *and* if you haven't explicitly configured any option
54
+ // for 'agent' (which would let you set up other HTTPS-handling policies), then we automatically
55
+ // disable cert verification for that request.
56
+ if ( isNode && isRelativeUrl ) {
57
+ const hasAgentConfig = init && ( 'agent' in init ) ;
58
+ if ( ! hasAgentConfig ) {
59
+ const agentForRequest = new ( nodeHttps . Agent ) ( { rejectUnauthorized : false } ) ;
60
+
61
+ init = init || { } ;
62
+ ( init as any ) . agent = agentForRequest ;
63
+ }
64
+ }
65
+
66
+ return init ;
67
+ }
68
+
31
69
export function fetch ( url : string | Request , init ?: RequestInit ) : Promise < any > {
32
70
// As of domain-task 2.0.0, we no longer auto-add the 'fetch' promise to the current domain task list.
33
71
// This is because it's misleading to do so, and can result in race-condition bugs, e.g.,
0 commit comments