@@ -40,71 +40,76 @@ public function connect($uri)
4040 return $ connector ->connect ($ uri );
4141 }
4242
43- return $ this
44- ->resolveHostname ($ host )
45- ->then (function ($ ip ) use ($ connector , $ host , $ parts ) {
46- $ uri = '' ;
47-
48- // prepend original scheme if known
49- if (isset ($ parts ['scheme ' ])) {
50- $ uri .= $ parts ['scheme ' ] . ':// ' ;
51- }
52-
53- if (strpos ($ ip , ': ' ) !== false ) {
54- // enclose IPv6 addresses in square brackets before appending port
55- $ uri .= '[ ' . $ ip . '] ' ;
56- } else {
57- $ uri .= $ ip ;
58- }
59-
60- // append original port if known
61- if (isset ($ parts ['port ' ])) {
62- $ uri .= ': ' . $ parts ['port ' ];
63- }
64-
65- // append orignal path if known
66- if (isset ($ parts ['path ' ])) {
67- $ uri .= $ parts ['path ' ];
68- }
69-
70- // append original query if known
71- if (isset ($ parts ['query ' ])) {
72- $ uri .= '? ' . $ parts ['query ' ];
73- }
74-
75- // append original hostname as query if resolved via DNS and if
76- // destination URI does not contain "hostname" query param already
77- $ args = array ();
78- parse_str (isset ($ parts ['query ' ]) ? $ parts ['query ' ] : '' , $ args );
79- if ($ host !== $ ip && !isset ($ args ['hostname ' ])) {
80- $ uri .= (isset ($ parts ['query ' ]) ? '& ' : '? ' ) . 'hostname= ' . rawurlencode ($ host );
81- }
82-
83- // append original fragment if known
84- if (isset ($ parts ['fragment ' ])) {
85- $ uri .= '# ' . $ parts ['fragment ' ];
86- }
87-
88- return $ connector ->connect ($ uri );
89- });
90- }
91-
92- private function resolveHostname ($ host )
93- {
9443 $ promise = $ this ->resolver ->resolve ($ host );
44+ $ resolved = null ;
9545
9646 return new Promise \Promise (
97- function ($ resolve , $ reject ) use ($ promise ) {
47+ function ($ resolve , $ reject ) use (& $ promise, & $ resolved , $ uri , $ connector , $ host , $ parts ) {
9848 // resolve/reject with result of DNS lookup
99- $ promise ->then ($ resolve , $ reject );
49+ $ promise ->then (function ($ ip ) use (&$ promise , &$ resolved , $ connector , $ host , $ parts ) {
50+ $ resolved = $ ip ;
51+ $ uri = '' ;
52+
53+ // prepend original scheme if known
54+ if (isset ($ parts ['scheme ' ])) {
55+ $ uri .= $ parts ['scheme ' ] . ':// ' ;
56+ }
57+
58+ if (strpos ($ ip , ': ' ) !== false ) {
59+ // enclose IPv6 addresses in square brackets before appending port
60+ $ uri .= '[ ' . $ ip . '] ' ;
61+ } else {
62+ $ uri .= $ ip ;
63+ }
64+
65+ // append original port if known
66+ if (isset ($ parts ['port ' ])) {
67+ $ uri .= ': ' . $ parts ['port ' ];
68+ }
69+
70+ // append orignal path if known
71+ if (isset ($ parts ['path ' ])) {
72+ $ uri .= $ parts ['path ' ];
73+ }
74+
75+ // append original query if known
76+ if (isset ($ parts ['query ' ])) {
77+ $ uri .= '? ' . $ parts ['query ' ];
78+ }
79+
80+ // append original hostname as query if resolved via DNS and if
81+ // destination URI does not contain "hostname" query param already
82+ $ args = array ();
83+ parse_str (isset ($ parts ['query ' ]) ? $ parts ['query ' ] : '' , $ args );
84+ if ($ host !== $ ip && !isset ($ args ['hostname ' ])) {
85+ $ uri .= (isset ($ parts ['query ' ]) ? '& ' : '? ' ) . 'hostname= ' . rawurlencode ($ host );
86+ }
87+
88+ // append original fragment if known
89+ if (isset ($ parts ['fragment ' ])) {
90+ $ uri .= '# ' . $ parts ['fragment ' ];
91+ }
92+
93+ return $ promise = $ connector ->connect ($ uri );
94+ }, function ($ e ) use ($ uri , $ reject ) {
95+ $ reject (new RuntimeException ('Connection to ' . $ uri .' failed during DNS lookup: ' . $ e ->getMessage (), 0 , $ e ));
96+ })->then ($ resolve , $ reject );
10097 },
101- function ($ _ , $ reject ) use ($ promise ) {
98+ function ($ _ , $ reject ) use (& $ promise, & $ resolved , $ uri ) {
10299 // cancellation should reject connection attempt
103- $ reject (new RuntimeException ('Connection attempt cancelled during DNS lookup ' ));
100+ // reject DNS resolution with custom reason, otherwise rely on connection cancellation below
101+ if ($ resolved === null ) {
102+ $ reject (new RuntimeException ('Connection to ' . $ uri . ' cancelled during DNS lookup ' ));
103+ }
104104
105- // (try to) cancel pending DNS lookup
105+ // (try to) cancel pending DNS lookup / connection attempt
106106 if ($ promise instanceof CancellablePromiseInterface) {
107+ // overwrite callback arguments for PHP7+ only, so they do not show
108+ // up in the Exception trace and do not cause a possible cyclic reference.
109+ $ _ = $ reject = null ;
110+
107111 $ promise ->cancel ();
112+ $ promise = null ;
108113 }
109114 }
110115 );
0 commit comments