@@ -40,71 +40,76 @@ public function connect($uri)
40
40
return $ connector ->connect ($ uri );
41
41
}
42
42
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
- {
94
43
$ promise = $ this ->resolver ->resolve ($ host );
44
+ $ resolved = null ;
95
45
96
46
return new Promise \Promise (
97
- function ($ resolve , $ reject ) use ($ promise ) {
47
+ function ($ resolve , $ reject ) use (& $ promise, & $ resolved , $ uri , $ connector , $ host , $ parts ) {
98
48
// 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 );
100
97
},
101
- function ($ _ , $ reject ) use ($ promise ) {
98
+ function ($ _ , $ reject ) use (& $ promise, & $ resolved , $ uri ) {
102
99
// 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
+ }
104
104
105
- // (try to) cancel pending DNS lookup
105
+ // (try to) cancel pending DNS lookup / connection attempt
106
106
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
+
107
111
$ promise ->cancel ();
112
+ $ promise = null ;
108
113
}
109
114
}
110
115
);
0 commit comments