14
14
15
15
import { InstanceConnectionInfo } from './instance-connection-info' ;
16
16
import { CloudSQLConnectorError } from './errors' ;
17
+ import { resolveTxtRecord } from './dns-lookup' ;
17
18
18
- export function parseInstanceConnectionName (
19
- instanceConnectionName : string | undefined
20
- ) : InstanceConnectionInfo {
21
- if ( ! instanceConnectionName ) {
19
+ export async function resolveInstanceName (
20
+ name : string | undefined
21
+ ) : Promise < InstanceConnectionInfo > {
22
+ if ( ! name ) {
22
23
throw new CloudSQLConnectorError ( {
23
24
message :
24
25
'Missing instance connection name, expected: "PROJECT:REGION:INSTANCE"' ,
25
26
code : 'ENOCONNECTIONNAME' ,
26
27
} ) ;
28
+ } else if ( isInstanceConnectionName ( name ) ) {
29
+ return parseInstanceConnectionName ( name ) ;
30
+ } else if ( isValidDomainName ( name ) ) {
31
+ return await resolveDomainName ( name ) ;
32
+ } else {
33
+ throw new CloudSQLConnectorError ( {
34
+ message :
35
+ 'Malformed Instance connection name, expected an instance connection name in the form "PROJECT:REGION:INSTANCE" or a valid domain name' ,
36
+ code : 'EBADCONNECTIONNAME' ,
37
+ } ) ;
27
38
}
39
+ }
28
40
29
- const connectionNameRegex =
30
- / (?< projectId > [ ^ : ] + ( : [ ^ : ] + ) ? ) : (?< regionId > [ ^ : ] + ) : (?< instanceId > [ ^ : ] + ) / ;
31
- const matches = String ( instanceConnectionName ) . match ( connectionNameRegex ) ;
32
- if ( ! matches ) {
41
+ const connectionNameRegex =
42
+ / ^ (?< projectId > [ ^ : ] + ( : [ ^ : ] + ) ? ) : (?< regionId > [ ^ : ] + ) : (?< instanceId > [ ^ : ] + ) $ / ;
43
+
44
+ // The domain name pattern in accordance with RFC 1035, RFC 1123 and RFC 2181.
45
+ // From Go Connector:
46
+ const domainNameRegex =
47
+ / ^ (?: [ _ a - z 0 - 9 ] (?: [ _ a - z 0 - 9 - ] { 0 , 61 } [ a - z 0 - 9 ] ) ? \. ) + (?: [ a - z ] (?: [ a - z 0 - 9 - ] { 0 , 61 } [ a - z 0 - 9 ] ) ? ) ? $ / ;
48
+
49
+ export function isValidDomainName ( name : string ) : boolean {
50
+ const matches = String ( name ) . match ( domainNameRegex ) ;
51
+ return Boolean ( matches ) ;
52
+ }
53
+
54
+ export function isInstanceConnectionName ( name : string ) : boolean {
55
+ const matches = String ( name ) . match ( connectionNameRegex ) ;
56
+ return Boolean ( matches ) ;
57
+ }
58
+
59
+ export async function resolveDomainName (
60
+ name : string
61
+ ) : Promise < InstanceConnectionInfo > {
62
+ const icn = await resolveTxtRecord ( name ) ;
63
+ if ( ! isInstanceConnectionName ( icn ) ) {
33
64
throw new CloudSQLConnectorError ( {
34
65
message :
35
- 'Malformed instance connection name provided: expected format ' +
36
- `of "PROJECT:REGION:INSTANCE", got ${ instanceConnectionName } ` ,
37
- code : 'EBADCONNECTIONNAME' ,
66
+ 'Malformed instance connection name returned for domain ' +
67
+ name +
68
+ ' : ' +
69
+ icn ,
70
+ code : 'EBADDOMAINCONNECTIONNAME' ,
71
+ } ) ;
72
+ }
73
+
74
+ const info = parseInstanceConnectionName ( icn ) ;
75
+ info . domainName = name ;
76
+ return info ;
77
+ }
78
+
79
+ export function parseInstanceConnectionName (
80
+ instanceConnectionName : string | undefined
81
+ ) : InstanceConnectionInfo {
82
+ if ( ! instanceConnectionName ) {
83
+ throw new CloudSQLConnectorError ( {
84
+ message :
85
+ 'Missing instance connection name, expected: "PROJECT:REGION:INSTANCE"' ,
86
+ code : 'ENOCONNECTIONNAME' ,
38
87
} ) ;
39
88
}
40
89
41
- const unmatchedItems = matches [ 0 ] !== matches . input ;
42
- if ( unmatchedItems || ! matches . groups ) {
90
+ const matches = String ( instanceConnectionName ) . match ( connectionNameRegex ) ;
91
+ if ( ! matches || ! matches . groups ) {
43
92
throw new CloudSQLConnectorError ( {
44
93
message :
45
94
'Malformed instance connection name provided: expected format ' +
@@ -52,5 +101,6 @@ export function parseInstanceConnectionName(
52
101
projectId : matches . groups . projectId ,
53
102
regionId : matches . groups . regionId ,
54
103
instanceId : matches . groups . instanceId ,
104
+ domainName : undefined ,
55
105
} ;
56
106
}
0 commit comments