5
5
namespace Redmine \Client ;
6
6
7
7
use Redmine \Exception \ClientException ;
8
+ use Redmine \Http \HttpClient ;
9
+ use Redmine \Http \HttpFactory ;
10
+ use Redmine \Http \Request ;
11
+ use Redmine \Http \Response ;
8
12
9
13
/**
10
14
* Native cURL client.
11
15
*/
12
- final class NativeCurlClient implements Client
16
+ final class NativeCurlClient implements Client, HttpClient
13
17
{
14
18
use ClientApiTrait;
15
19
@@ -55,6 +59,27 @@ public function __construct(
55
59
}
56
60
}
57
61
62
+ /**
63
+ * Create and send a HTTP request and return the response
64
+ *
65
+ * @throws ClientException If anything goes wrong on creating or sending the request
66
+ */
67
+ public function request (Request $ request ): Response
68
+ {
69
+ $ this ->runRequest (
70
+ $ request ->getMethod (),
71
+ $ request ->getPath (),
72
+ $ request ->getContent (),
73
+ $ request ->getContentType ()
74
+ );
75
+
76
+ return HttpFactory::makeResponse (
77
+ $ this ->lastResponseStatusCode ,
78
+ $ this ->lastResponseContentType ,
79
+ $ this ->lastResponseBody
80
+ );
81
+ }
82
+
58
83
/**
59
84
* Sets to an existing username so api calls can be
60
85
* impersonated to this user.
@@ -77,31 +102,31 @@ public function stopImpersonateUser(): void
77
102
*/
78
103
public function requestGet (string $ path ): bool
79
104
{
80
- return $ this ->request ( ' get ' , $ path );
105
+ return $ this ->runRequest ( ' GET ' , $ path );
81
106
}
82
107
83
108
/**
84
109
* Create and send a POST request.
85
110
*/
86
111
public function requestPost (string $ path , string $ body ): bool
87
112
{
88
- return $ this ->request ( ' post ' , $ path , $ body );
113
+ return $ this ->runRequest ( ' POST ' , $ path , $ body );
89
114
}
90
115
91
116
/**
92
117
* Create and send a PUT request.
93
118
*/
94
119
public function requestPut (string $ path , string $ body ): bool
95
120
{
96
- return $ this ->request ( ' put ' , $ path , $ body );
121
+ return $ this ->runRequest ( ' PUT ' , $ path , $ body );
97
122
}
98
123
99
124
/**
100
125
* Create and send a DELETE request.
101
126
*/
102
127
public function requestDelete (string $ path ): bool
103
128
{
104
- return $ this ->request ( ' delete ' , $ path );
129
+ return $ this ->runRequest ( ' DELETE ' , $ path );
105
130
}
106
131
107
132
/**
@@ -211,13 +236,13 @@ private function unsetHttpHeader(string $name): void
211
236
/**
212
237
* @throws ClientException If anything goes wrong on curl request
213
238
*/
214
- private function request (string $ method , string $ path , string $ body = '' ): bool
239
+ private function runRequest (string $ method , string $ path , string $ body = '' , string $ contentType = '' ): bool
215
240
{
216
241
$ this ->lastResponseStatusCode = 0 ;
217
242
$ this ->lastResponseContentType = '' ;
218
243
$ this ->lastResponseBody = '' ;
219
244
220
- $ curl = $ this ->createCurl ($ method , $ path , $ body );
245
+ $ curl = $ this ->createCurl ($ method , $ path , $ body, $ contentType );
221
246
222
247
$ response = curl_exec ($ curl );
223
248
@@ -249,7 +274,7 @@ private function request(string $method, string $path, string $body = ''): bool
249
274
*
250
275
* @return \CurlHandle a cURL handle on success, <b>FALSE</b> on errors
251
276
*/
252
- private function createCurl (string $ method , string $ path , string $ body = '' )
277
+ private function createCurl (string $ method , string $ path , string $ body = '' , string $ contentType = '' )
253
278
{
254
279
// General cURL options
255
280
$ curlOptions = [
@@ -264,13 +289,13 @@ private function createCurl(string $method, string $path, string $body = '')
264
289
$ curlOptions [CURLOPT_URL ] = $ this ->url . $ path ;
265
290
266
291
// Set the HTTP request headers
267
- $ curlOptions [CURLOPT_HTTPHEADER ] = $ this ->createHttpHeader ($ path );
292
+ $ curlOptions [CURLOPT_HTTPHEADER ] = $ this ->createHttpHeader ($ path, $ contentType );
268
293
269
294
unset($ curlOptions [CURLOPT_CUSTOMREQUEST ]);
270
295
unset($ curlOptions [CURLOPT_POST ]);
271
296
unset($ curlOptions [CURLOPT_POSTFIELDS ]);
272
297
switch ($ method ) {
273
- case 'post ' :
298
+ case 'POST ' :
274
299
$ curlOptions [CURLOPT_POST ] = 1 ;
275
300
if ($ this ->isUploadCall ($ path ) && $ this ->isValidFilePath ($ body )) {
276
301
@trigger_error ('Uploading an attachment by filepath is deprecated, use file_get_contents() to upload the file content instead. ' , E_USER_DEPRECATED );
@@ -286,13 +311,13 @@ private function createCurl(string $method, string $path, string $body = '')
286
311
$ curlOptions [CURLOPT_POSTFIELDS ] = $ body ;
287
312
}
288
313
break ;
289
- case 'put ' :
314
+ case 'PUT ' :
290
315
$ curlOptions [CURLOPT_CUSTOMREQUEST ] = 'PUT ' ;
291
316
if ($ body !== '' ) {
292
317
$ curlOptions [CURLOPT_POSTFIELDS ] = $ body ;
293
318
}
294
319
break ;
295
- case 'delete ' :
320
+ case 'DELETE ' :
296
321
$ curlOptions [CURLOPT_CUSTOMREQUEST ] = 'DELETE ' ;
297
322
break ;
298
323
default : // GET
@@ -314,7 +339,7 @@ private function createCurl(string $method, string $path, string $body = '')
314
339
return $ curl ;
315
340
}
316
341
317
- private function createHttpHeader (string $ path ): array
342
+ private function createHttpHeader (string $ path, string $ contentType = '' ): array
318
343
{
319
344
// Additional request headers
320
345
$ httpHeaders = [
@@ -352,14 +377,18 @@ private function createHttpHeader(string $path): array
352
377
// Now set or reset mandatory headers
353
378
354
379
// Content type headers
355
- $ tmp = parse_url ($ this ->url . $ path );
356
-
357
- if ($ this ->isUploadCall ($ path )) {
358
- $ httpHeaders [] = 'Content-Type: application/octet-stream ' ;
359
- } elseif ('json ' === substr ($ tmp ['path ' ], -4 )) {
360
- $ httpHeaders [] = 'Content-Type: application/json ' ;
361
- } elseif ('xml ' === substr ($ tmp ['path ' ], -3 )) {
362
- $ httpHeaders [] = 'Content-Type: text/xml ' ;
380
+ if ($ contentType !== '' ) {
381
+ $ httpHeaders [] = 'Content-Type: ' . $ contentType ;
382
+ } else {
383
+ $ tmp = parse_url ($ this ->url . $ path );
384
+
385
+ if ($ this ->isUploadCall ($ path )) {
386
+ $ httpHeaders [] = 'Content-Type: application/octet-stream ' ;
387
+ } elseif ('json ' === substr ($ tmp ['path ' ], -4 )) {
388
+ $ httpHeaders [] = 'Content-Type: application/json ' ;
389
+ } elseif ('xml ' === substr ($ tmp ['path ' ], -3 )) {
390
+ $ httpHeaders [] = 'Content-Type: text/xml ' ;
391
+ }
363
392
}
364
393
365
394
return $ httpHeaders ;
0 commit comments