13
13
14
14
use GuzzleHttp \Client ;
15
15
use GuzzleHttp \ClientInterface ;
16
- use GuzzleHttp \Event \CompleteEvent ;
17
- use GuzzleHttp \Event \ErrorEvent ;
18
16
use GuzzleHttp \Exception \RequestException ;
19
- use GuzzleHttp \Message \RequestInterface ;
17
+ use GuzzleHttp \Message \RequestInterface as GuzzleRequest ;
18
+ use GuzzleHttp \Message \ResponseInterface as GuzzleResponse ;
20
19
use GuzzleHttp \Pool ;
21
- use Http \Adapter \Common \Exception \CannotFetchUri ;
22
- use Http \Adapter \Internal \Message \InternalRequest ;
23
- use Http \Adapter \Internal \Message \MessageFactory ;
24
- use Http \Adapter \Normalizer \BodyNormalizer ;
20
+ use Http \Adapter \Common \Exception \HttpAdapterException ;
21
+ use Http \Adapter \Common \Exception \MultiHttpAdapterException ;
22
+ use Http \Common \Message \MessageFactoryGuesser ;
23
+ use Http \Message \MessageFactory ;
24
+ use Http \Message \MessageFactoryAware ;
25
+ use Http \Message \MessageFactoryAwareTemplate ;
26
+ use Psr \Http \Message \RequestInterface ;
27
+ use Psr \Http \Message \ResponseInterface ;
25
28
26
29
/**
27
30
* @author GeLo <[email protected] >
28
31
*/
29
- class Guzzle5HttpAdapter extends Core \CurlHttpAdapter
32
+ class Guzzle5HttpAdapter implements HttpAdapter, MessageFactoryAware
30
33
{
34
+ use MessageFactoryAwareTemplate;
35
+
31
36
/**
32
37
* @var ClientInterface
33
38
*/
@@ -36,138 +41,163 @@ class Guzzle5HttpAdapter extends Core\CurlHttpAdapter
36
41
/**
37
42
*
38
43
* @param ClientInterface|null $client
39
- * @param array $options
40
44
* @param MessageFactory|null $messageFactory
41
45
*/
42
- public function __construct (ClientInterface $ client = null , array $ options = [], MessageFactory $ messageFactory = null )
46
+ public function __construct (ClientInterface $ client = null , MessageFactory $ messageFactory = null )
43
47
{
44
- parent ::__construct ($ options , $ messageFactory );
45
-
46
48
$ this ->client = $ client ?: new Client ();
47
- }
49
+ $ this -> messageFactory = $ messageFactory ?: MessageFactoryGuesser:: guess ();
48
50
49
- /**
50
- * {@inheritdoc}
51
- */
52
- public function getName ()
53
- {
54
- return 'guzzle5 ' ;
55
51
}
56
52
57
53
/**
58
54
* {@inheritdoc}
59
55
*/
60
- protected function sendInternalRequest ( InternalRequest $ internalRequest )
56
+ public function sendRequest ( RequestInterface $ request , array $ options = [] )
61
57
{
58
+ $ guzzleRequest = $ this ->createRequest ($ request , $ options );
59
+
62
60
try {
63
- $ response = $ this ->client ->send ($ this -> createRequest ( $ internalRequest ) );
61
+ $ response = $ this ->client ->send ($ guzzleRequest );
64
62
} catch (RequestException $ e ) {
65
- throw new CannotFetchUri ( $ e -> getRequest ()-> getUrl (), $ this ->getName () , $ e );
63
+ throw $ this ->createException ( $ e , $ request );
66
64
}
67
65
68
- return $ this ->getMessageFactory ()->createResponse (
69
- (integer ) $ response ->getStatusCode (),
70
- null ,
71
- $ response ->getProtocolVersion (),
72
- $ response ->getHeaders (),
73
- BodyNormalizer::normalize (
74
- function () use ($ response ) {
75
- return $ response ->getBody ()->detach ();
76
- },
77
- $ internalRequest ->getMethod ()
78
- )
79
- );
66
+ return $ this ->createResponse ($ response );
80
67
}
81
68
82
69
/**
83
70
* {@inheritdoc}
84
71
*/
85
- protected function sendInternalRequests (array $ internalRequests , callable $ success , callable $ error )
72
+ public function sendRequests (array $ requests , array $ options = [] )
86
73
{
87
- $ requests = [];
88
- foreach ($ internalRequests as $ internalRequest ) {
89
- $ requests [] = $ this ->createRequest ($ internalRequest , $ success , $ error );
74
+ $ requests = array_values ($ requests );
75
+ $ guzzleRequests = [];
76
+
77
+ foreach ($ requests as $ request ) {
78
+ $ guzzleRequests [] = $ this ->createRequest ($ request , $ options );
79
+ }
80
+
81
+ $ results = Pool::batch ($ this ->client , $ guzzleRequests );
82
+
83
+ $ exceptions = [];
84
+ $ responses = [];
85
+
86
+ foreach ($ guzzleRequests as $ key => $ guzzleRequest ) {
87
+ $ result = $ results ->getResult ($ guzzleRequest );
88
+
89
+ if ($ result instanceof GuzzleResponse) {
90
+ $ responses [] = $ this ->createResponse ($ result );
91
+ } elseif ($ result instanceof RequestException) {
92
+ $ exceptions [] = $ this ->createException ($ result , $ requests [$ key ]);
93
+ }
90
94
}
91
95
92
- Pool::batch ($ this ->client , $ requests );
96
+ if (count ($ exceptions ) > 0 ) {
97
+ throw new MultiHttpAdapterException ($ exceptions , $ responses );
98
+ }
99
+
100
+ return $ responses ;
93
101
}
94
102
95
103
/**
96
104
* {@inheritdoc}
97
105
*/
98
- protected function createFile ($ file )
106
+ public function getName ()
107
+ {
108
+ return 'guzzle5 ' ;
109
+ }
110
+
111
+ /**
112
+ * Converts a PSR request into a Guzzle request
113
+ *
114
+ * @param RequestInterface $request
115
+ *
116
+ * @return GuzzleRequest
117
+ */
118
+ private function createRequest (RequestInterface $ request , array $ options = [])
99
119
{
100
- return fopen ($ file , 'r ' );
120
+ $ options = $ this ->buildOptions ($ options );
121
+
122
+ $ options ['version ' ] = $ request ->getProtocolVersion ();
123
+ $ options ['headers ' ] = $ request ->getHeaders ();
124
+ $ options ['body ' ] = (string ) $ request ->getBody ();
125
+
126
+ return $ this ->client ->createRequest (
127
+ $ request ->getMethod (),
128
+ (string ) $ request ->getUri (),
129
+ $ options
130
+ );
101
131
}
102
132
103
133
/**
104
- * Creates a request
134
+ * Converts a Guzzle response into a PSR response
105
135
*
106
- * @param InternalRequest $internalRequest
107
- * @param callable|null $success
108
- * @param callable|null $error
136
+ * @param GuzzleResponse $response
109
137
*
110
- * @return RequestInterface
138
+ * @return ResponseInterface
111
139
*/
112
- private function createRequest ( InternalRequest $ internalRequest , callable $ success = null , callable $ error = null )
140
+ private function createResponse ( GuzzleResponse $ response )
113
141
{
114
- $ request = $ this ->client ->createRequest (
115
- $ internalRequest ->getMethod (),
116
- (string ) $ internalRequest ->getUri (),
117
- [
118
- 'exceptions ' => false ,
119
- 'allow_redirects ' => false ,
120
- 'timeout ' => $ this ->getContextOption ('timeout ' , $ internalRequest ),
121
- 'connect_timeout ' => $ this ->getContextOption ('timeout ' , $ internalRequest ),
122
- 'version ' => $ internalRequest ->getProtocolVersion (),
123
- 'headers ' => $ this ->prepareHeaders ($ internalRequest ),
124
- 'body ' => $ this ->prepareContent ($ internalRequest ),
125
- ]
142
+ $ body = $ response ->getBody ();
143
+
144
+ return $ this ->getMessageFactory ()->createResponse (
145
+ $ response ->getStatusCode (),
146
+ null ,
147
+ $ response ->getProtocolVersion (),
148
+ $ response ->getHeaders (),
149
+ isset ($ body ) ? $ body ->detach () : null
150
+ );
151
+ }
152
+
153
+ /**
154
+ * Converts a Guzzle exception into an HttpAdapter exception
155
+ *
156
+ * @param RequestException $exception
157
+ *
158
+ * @return HttpAdapterException
159
+ */
160
+ private function createException (
161
+ RequestException $ exception ,
162
+ RequestInterface $ originalRequest
163
+ ) {
164
+ $ adapterException = new HttpAdapterException (
165
+ $ exception ->getMessage (),
166
+ 0 ,
167
+ $ exception
126
168
);
127
169
128
- if (isset ($ success )) {
129
- $ messageFactory = $ this ->getMessageFactory ();
130
-
131
- $ request ->getEmitter ()->on (
132
- 'complete ' ,
133
- function (CompleteEvent $ event ) use ($ success , $ internalRequest , $ messageFactory ) {
134
- $ response = $ messageFactory ->createResponse (
135
- (integer ) $ event ->getResponse ()->getStatusCode (),
136
- null ,
137
- $ event ->getResponse ()->getProtocolVersion (),
138
- $ event ->getResponse ()->getHeaders (),
139
- BodyNormalizer::normalize (
140
- function () use ($ event ) {
141
- return $ event ->getResponse ()->getBody ()->detach ();
142
- },
143
- $ internalRequest ->getMethod ()
144
- )
145
- );
146
-
147
- $ response = new Core \Message \ParameterableResponse ($ response );
148
- $ response = $ response ->withParameter ('request ' , $ internalRequest );
149
- call_user_func ($ success , $ response );
150
- }
151
- );
170
+ $ response = null ;
171
+
172
+ if ($ exception ->hasResponse ()) {
173
+ $ response = $ this ->createResponse ($ exception ->getResponse ());
152
174
}
153
175
154
- if (isset ($ error )) {
155
- $ httpAdapterName = $ this ->getName ();
156
-
157
- $ request ->getEmitter ()->on (
158
- 'error ' ,
159
- function (ErrorEvent $ event ) use ($ error , $ internalRequest , $ httpAdapterName ) {
160
- $ exception = new CannotFetchUri (
161
- $ event ->getException ()->getRequest ()->getUrl (),
162
- $ httpAdapterName ,
163
- $ event ->getException ()
164
- );
165
- $ exception ->setRequest ($ internalRequest );
166
- call_user_func ($ error , $ exception );
167
- }
168
- );
176
+ $ adapterException ->setResponse ($ response );
177
+ $ adapterException ->setRequest ($ originalRequest );
178
+
179
+ return $ adapterException ;
180
+ }
181
+
182
+ /**
183
+ * Builds options for Guzzle
184
+ *
185
+ * @param array $options
186
+ *
187
+ * @return array
188
+ */
189
+ private function buildOptions (array $ options )
190
+ {
191
+ $ guzzleOptions = [
192
+ 'exceptions ' => false ,
193
+ 'allow_redirects ' => false ,
194
+ ];
195
+
196
+ if (isset ($ options ['timeout ' ])) {
197
+ $ guzzleOptions ['connect_timeout ' ] = $ options ['timeout ' ];
198
+ $ guzzleOptions ['timeout ' ] = $ options ['timeout ' ];
169
199
}
170
200
171
- return $ request ;
201
+ return $ guzzleOptions ;
172
202
}
173
203
}
0 commit comments