@@ -296,13 +296,14 @@ public static function _encodeArray($value, $allowParseObjects)
296
296
/**
297
297
* Parse\Client::_request, internal method for communicating with Parse.
298
298
*
299
- * @param string $method HTTP Method for this request.
300
- * @param string $relativeUrl REST API Path.
301
- * @param null $sessionToken Session Token.
302
- * @param null $data Data to provide with the request.
303
- * @param bool $useMasterKey Whether to use the Master Key.
304
- * @param bool $appRequest App request to create or modify a application
305
- * @param string $contentType The content type for this request, default is application/json
299
+ * @param string $method HTTP Method for this request.
300
+ * @param string $relativeUrl REST API Path.
301
+ * @param null $sessionToken Session Token.
302
+ * @param null $data Data to provide with the request.
303
+ * @param bool $useMasterKey Whether to use the Master Key.
304
+ * @param bool $appRequest App request to create or modify a application
305
+ * @param string $contentType The content type for this request, default is application/json
306
+ * @param bool $returnHeaders Allow to return response headers
306
307
*
307
308
* @throws \Exception
308
309
*
@@ -315,7 +316,8 @@ public static function _request(
315
316
$ data = null ,
316
317
$ useMasterKey = false ,
317
318
$ appRequest = false ,
318
- $ contentType = 'application/json '
319
+ $ contentType = 'application/json ' ,
320
+ $ returnHeaders = false
319
321
) {
320
322
if ($ data === '[] ' ) {
321
323
$ data = '{} ' ;
@@ -329,34 +331,46 @@ public static function _request(
329
331
}
330
332
331
333
$ url = self ::$ serverURL .'/ ' .self ::$ mountPath .ltrim ($ relativeUrl , '/ ' );
334
+
332
335
if ($ method === 'GET ' && !empty ($ data )) {
333
336
$ url .= '? ' .http_build_query ($ data );
334
337
}
338
+
335
339
$ rest = curl_init ();
336
340
curl_setopt ($ rest , CURLOPT_URL , $ url );
337
341
curl_setopt ($ rest , CURLOPT_RETURNTRANSFER , 1 );
342
+
338
343
if ($ method === 'POST ' ) {
339
344
$ headers [] = 'Content-Type: ' .$ contentType ;
340
345
curl_setopt ($ rest , CURLOPT_POST , 1 );
341
346
curl_setopt ($ rest , CURLOPT_POSTFIELDS , $ data );
342
347
}
348
+
343
349
if ($ method === 'PUT ' ) {
344
350
$ headers [] = 'Content-Type: ' .$ contentType ;
345
351
curl_setopt ($ rest , CURLOPT_CUSTOMREQUEST , $ method );
346
352
curl_setopt ($ rest , CURLOPT_POSTFIELDS , $ data );
347
353
}
354
+
348
355
if ($ method === 'DELETE ' ) {
349
356
curl_setopt ($ rest , CURLOPT_CUSTOMREQUEST , $ method );
350
357
}
358
+
351
359
curl_setopt ($ rest , CURLOPT_HTTPHEADER , $ headers );
352
360
353
361
if (!is_null (self ::$ connectionTimeout )) {
354
362
curl_setopt ($ rest , CURLOPT_CONNECTTIMEOUT , self ::$ connectionTimeout );
355
363
}
364
+
356
365
if (!is_null (self ::$ timeout )) {
357
366
curl_setopt ($ rest , CURLOPT_TIMEOUT , self ::$ timeout );
358
367
}
359
368
369
+ if ($ returnHeaders ) {
370
+ curl_setopt ($ rest , CURLOPT_HEADER , 1 );
371
+ curl_setopt ($ rest , CURLOPT_FOLLOWLOCATION , true );
372
+ }
373
+
360
374
$ response = curl_exec ($ rest );
361
375
$ status = curl_getinfo ($ rest , CURLINFO_HTTP_CODE );
362
376
$ contentType = curl_getinfo ($ rest , CURLINFO_CONTENT_TYPE );
@@ -367,6 +381,16 @@ public static function _request(
367
381
return false ;
368
382
}
369
383
}
384
+
385
+ $ headerData = [];
386
+
387
+ if ($ returnHeaders ) {
388
+ $ headerSize = curl_getinfo ($ rest , CURLINFO_HEADER_SIZE );
389
+ $ headerContent = substr ($ response , 0 , $ headerSize );
390
+ $ headerData = self ::parseCurlHeaders ($ headerContent );
391
+ $ response = substr ($ response , $ headerSize );
392
+ }
393
+
370
394
curl_close ($ rest );
371
395
if (strpos ($ contentType , 'text/html ' ) !== false ) {
372
396
throw new ParseException ('Bad Request ' , -1 );
@@ -383,9 +407,57 @@ public static function _request(
383
407
);
384
408
}
385
409
410
+ if ($ returnHeaders ) {
411
+ $ decoded ['_headers ' ] = $ headerData ;
412
+ }
413
+
386
414
return $ decoded ;
387
415
}
388
416
417
+ /**
418
+ * ParseClient::parseCurlHeaders, will parse headers data and returns it as array.
419
+ * @param $headerContent
420
+ *
421
+ * @return array
422
+ */
423
+ private static function parseCurlHeaders ($ headerContent )
424
+ {
425
+ $ headers = [];
426
+ $ headersContentSet = explode ("\r\n\r\n" , $ headerContent );
427
+ $ withRedirect = count ($ headersContentSet ) > 2 ;
428
+
429
+ if ($ withRedirect ) {
430
+ $ headers ['_previous ' ] = [];
431
+ }
432
+
433
+ foreach ($ headersContentSet as $ headerIndex => $ headersData ) {
434
+ if (empty ($ headersData )) {
435
+ continue ;
436
+ }
437
+
438
+ if ($ withRedirect && $ headerIndex === 0 ) {
439
+ $ storage = &$ headers ['_previous ' ];
440
+ } else {
441
+ $ storage = &$ headers ;
442
+ }
443
+
444
+ $ exploded = explode ("\r\n" , $ headersData );
445
+
446
+ foreach ($ exploded as $ i => $ line ) {
447
+ if (empty ($ line )) {
448
+ continue ;
449
+ } elseif ($ i === 0 ) {
450
+ $ storage ['http_status ' ] = $ line ;
451
+ } else {
452
+ list ($ headerName , $ headerValue ) = explode (': ' , $ line );
453
+ $ storage [$ headerName ] = $ headerValue ;
454
+ }
455
+ }
456
+ }
457
+
458
+ return $ headers ;
459
+ }
460
+
389
461
/**
390
462
* ParseClient::setStorage, will update the storage object used for
391
463
* persistence.
0 commit comments