@@ -7,6 +7,7 @@ const path = require("path");
77const http = require ( "http" ) ;
88const https = require ( "https" ) ;
99const crypto = require ( "crypto" ) ;
10+ const net = require ( 'net' ) ;
1011
1112// config constants
1213
@@ -19,13 +20,36 @@ const LAMBDA_MOUNT_CODE = ["1", "true"].includes(process.env.LAMBDA_MOUNT_CODE);
1920// UTIL FUNCTIONS
2021//----------------
2122
22- const getLocalEndpoint = ( ) => `http://${ getLocalHost ( ) } ` ;
23+ const getLocalEndpoint = async ( ) => `http://${ await getLocalHost ( ) } ` ;
2324
2425const port = process . env . EDGE_PORT || DEFAULT_EDGE_PORT ;
2526
26- const getLocalHost = ( ) => {
27- const host = process . env . LOCALSTACK_HOSTNAME || DEFAULT_HOSTNAME ;
28- return `${ host } :${ port } ` ;
27+ var resolvedHostname = undefined ;
28+
29+ const getLocalHost = async ( ) => {
30+ if ( resolvedHostname ) {
31+ // early exit to not resolve again
32+ return `${ resolvedHostname } :${ port } ` ;
33+ }
34+
35+ var hostname = process . env . LOCALSTACK_HOSTNAME || DEFAULT_HOSTNAME ;
36+ // attempt to connect to the given host/port
37+ const socket = new net . Socket ( ) ;
38+ try {
39+ await socket . connect ( { host : hostname , port } ) ;
40+ } catch ( e ) {
41+ if ( hostname === "localhost" ) {
42+ // fall back to using local IPv4 address - to fix IPv6 issue on MacOS
43+ // see, https://github.com/localstack/serverless-localstack/issues/125
44+ // and https://github.com/localstack/aws-cdk-local/issues/78
45+ hostname = "127.0.0.1" ;
46+ }
47+ } finally {
48+ socket . destroy ( ) ;
49+ }
50+
51+ resolvedHostname = hostname ;
52+ return `${ hostname } :${ port } ` ;
2953} ;
3054
3155const useLocal = ( ) => {
@@ -85,14 +109,14 @@ const importLib = function importLib (libPath) {
85109 }
86110} ;
87111
88- const setSdkOptions = ( options , setHttpOptions ) => {
112+ const setSdkOptions = async ( options , setHttpOptions ) => {
89113 if ( ! useLocal ( options ) ) {
90114 return ;
91115 }
92116 if ( setHttpOptions ) {
93117 options = options . httpOptions = options . httpOptions || { } ;
94118 }
95- options . endpoint = getLocalEndpoint ( ) ;
119+ options . endpoint = await getLocalEndpoint ( ) ;
96120 options . s3ForcePathStyle = true ;
97121 options . accessKeyId = "test" ;
98122 options . secretAccessKey = "test" ;
@@ -101,10 +125,10 @@ const setSdkOptions = (options, setHttpOptions) => {
101125const patchProviderCredentials = ( provider ) => {
102126 const origConstr = provider . SdkProvider . withAwsCliCompatibleDefaults ;
103127 provider . SdkProvider . withAwsCliCompatibleDefaults = async ( options = { } ) => {
104- setSdkOptions ( options , true ) ;
128+ await setSdkOptions ( options , true ) ;
105129 const result = await origConstr ( options ) ;
106130 result . sdkOptions = result . sdkOptions || { } ;
107- setSdkOptions ( result . sdkOptions ) ;
131+ await setSdkOptions ( result . sdkOptions ) ;
108132 return result ;
109133 } ;
110134
@@ -118,18 +142,18 @@ const patchCdkToolkit = (CdkToolkit) => {
118142 const CdkToolkitClass = CdkToolkit . ToolkitInfo || CdkToolkit ;
119143 getMethods ( CdkToolkitClass . prototype ) . forEach ( ( meth ) => {
120144 const original = CdkToolkitClass . prototype [ meth ] ;
121- CdkToolkitClass . prototype [ meth ] = function methFunc ( ...args ) {
122- setSdkOptions ( this . props . sdkProvider . sdkOptions ) ;
145+ CdkToolkitClass . prototype [ meth ] = async function methFunc ( ...args ) {
146+ await setSdkOptions ( this . props . sdkProvider . sdkOptions ) ;
123147 return original . bind ( this ) . apply ( this , args ) ;
124148 } ;
125149 } ) ;
126150} ;
127151
128152const patchCurrentAccount = ( SDK ) => {
129153 const currentAccountOrig = SDK . prototype . currentAccount ;
130- SDK . prototype . currentAccount = function currentAccount ( ) {
154+ SDK . prototype . currentAccount = async function currentAccount ( ) {
131155 const { config} = this ;
132- setSdkOptions ( config ) ;
156+ await setSdkOptions ( config ) ;
133157 return currentAccountOrig . bind ( this ) ( ) ;
134158 } ;
135159
@@ -149,9 +173,9 @@ const patchToolkitInfo = (ToolkitInfo) => {
149173
150174 const setBucketUrl = function setBucketUrl ( object ) {
151175 Object . defineProperty ( object , "bucketUrl" , {
152- get ( ) {
176+ async get ( ) {
153177 const bucket = this . requireOutput ( BUCKET_NAME_OUTPUT ) ;
154- const domain = this . requireOutput ( BUCKET_DOMAIN_NAME_OUTPUT ) || getLocalHost ( ) ;
178+ const domain = this . requireOutput ( BUCKET_DOMAIN_NAME_OUTPUT ) || await getLocalHost ( ) ;
155179 return `https://${ domain . replace ( `${ bucket } .` , "" ) } :${ port } /${ bucket } ` ;
156180 }
157181 } ) ;
0 commit comments