Split cURL header info into array - php

Consider the following PHP cURL command:
$url = 'http://bit.ly/faV1vd';
$_h = curl_init();
curl_setopt($_h, CURLOPT_HEADER, 1);
curl_setopt($_h, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($_h, CURLOPT_HTTPGET, 1);
curl_setopt($_h, CURLOPT_URL, $url);
curl_setopt($_h, CURLOPT_DNS_USE_GLOBAL_CACHE, false );
curl_setopt($_h, CURLOPT_DNS_CACHE_TIMEOUT, 2 );
$return = curl_exec($_h);
This returns:
HTTP/1.1 301 Moved
Server: nginx
Date: Sun, 29 Apr 2012 12:48:07 GMT
Content-Type: text/html; charset=utf-8
Connection: keep-alive
Set-Cookie: _bit=4f9d3887-00215-020af-2f1cf10a;domain=.bit.ly;expires=Fri Oct 26 12:48:07 2012;path=/; HttpOnly
Cache-control: private; max-age=90
Location: http://www.macroaxis.com/invest/market/VZ--Sat-Feb-26-06-16-35-CST-2011?utm_source=twitterfeed&utm_medium=twitter
MIME-Version: 1.0
Content-Length: 209
I want to split the header info into an array, as follows
[Status] => HTTP/1.1 301 Moved,
[Server] => nginx,
[Date] => Sun, 29 Apr 2012 12:48:07 GMT,
...
[Content-Length] => 209
So:
- the first line (HTTP/1.1 301 Moved) should be the value of [Status]
- all other header info should be split on :
I'm not succeeding in splitting the header info:
explode("\r\n\r\n", $return);
explode("\r\n", $return);
This doesn't split the header into an array (to further split on :, etc. as expected. What am I doing wrong?

The answer by Altaf Hussain is good but does not support a case where the header response contains a ':'. i.e. X-URL: http://something.com. In this case the $myarray will only contain ('X-URL' => 'http')
This can be fixed by adding the limit parameter and setting it to 2. In addition, there should be a space after the colon. So the full solution with the bug fix is:
$myarray=array();
$data=explode("\n",$return);
$myarray['status']=$data[0];
array_shift($data);
foreach($data as $part){
$middle=explode(": ",$part,2);
$myarray[trim($middle[0])] = trim($middle[1]);
}
print_r($myarray);

Use this to split your header into an array
$myarray = array();
$data = explode("\n",$return);
$myarray['status'] = $data[0];
array_shift($data);
foreach($data as $part){
$middle = explode(":",$part);
$myarray[trim($middle[0])] = trim($middle[1]);
}
print_r($myarray);
As well as use curl_setopt($_h, CURLOPT_NOBODY, 1);
if you need to return only header.
More info can be found here
http://altafphp.blogspot.com/2012/04/get-http-headers-of-any-site-using-curl.html

cURL already supports a callback function for parsing the headers.
CURLOPT_HEADERFUNCTION : A callback accepting two parameters. The first is the cURL resource,
the second is a string with the header data to be written. The header
data must be written by this callback. Return the number of bytes
written.
function handle_headers($curl, $header_line)
{
list($name, $value) = explode(": ", $header_line, 2);
//do something with name/value...
return strlen($header_line);
}
curl_setopt($curl, CURLOPT_HEADERFUNCTION, "handle_headers");

You could also just split it into maximum of 2
explode("\r\n\r\n",$result,2);
and remember to setup followlocation and max redirect if you want the actual url to fetch
curl_setopt($curl, CURLOPT_FOLLOWLOCATION, TRUE);
curl_setopt($curl, CURLOPT_MAXREDIRS, 5);

Related

PHP - curl post view request body (parameters)

I get an error response for missing parameter when posting cURL POST method,
I'm adding an array of parameters to CURLOPT_POSTFIELDS the following way:
$service = "AutoInsuranceFormPostService";
$method = "autoInsurancePublisherFormPost";
$userAgent = "Mozilla%2F5.0+%28Linux%3B+Android+4.4.4%3B+Z752C+Build%2FKTU84P%29+AppleWebKit%2F537.36+%28KHTML%2C+like+Gecko%29+Chrome%2F36.0.1985.135+Mobile+Safari%2F537.36";
$payload = $encodedPayLoad;
$parameters = array (
'service' => $service,
'method' => $method,
'UserAgent' => $userAgent,
'payload' => $payload
);
With:
curl_setopt($ch,CURLOPT_POSTFIELDS,$parameters);
Since the response is saying missing parameter "service", I figured I need to debug the request body.
I managed to get the headers with:
curl_getinfo($ch)
I also attempted to use:
curl_setopt($ch, CURLOPT_VERBOSE, true);
But unfortunately in both cases I only got the headers and not the body (the parameters values).
Full curl execution function:
function openurl($url, $postvars) {
$ch=curl_init();
curl_setopt($ch, CURLOPT_VERBOSE, true);
$verbose = fopen('php://temp', 'w+');
curl_setopt($ch, CURLOPT_STDERR, $verbose);
curl_setopt($ch,CURLOPT_URL,$url);
curl_setopt($ch, CURLOPT_POST, TRUE);
curl_setopt($ch,CURLOPT_POSTFIELDS,$postvars);
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/x-www-form-urlencoded'));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch,CURLOPT_TIMEOUT, '3');
$result = curl_exec($ch);
rewind($verbose);
$verboseLog = stream_get_contents($verbose);
echo "Verbose information:\n<pre>", htmlspecialchars($verboseLog), "</pre>\n";
return $result;
}
Verbos information:
Content-Length: 6659
Expect: 100-continue
Content-Type: application/x-www-form-urlencoded; boundary=------------------------45b2d9f6776306b0
< HTTP/1.1 100 Continue
< HTTP/1.1 200 OK
< Date: Thu, 12 Jul 2018 16:32:52 GMT
< Server: Apache
< Cache-Control: public
< ORIGIN: S_CACHE
< Vary: User-Agent,Accept-Encoding
< Set-Cookie: _qs_origin=s-cache; path=/;
< Set-Cookie: _qs_deviceType=; path=/;
< Content-Length: 141
< Content-Type: application/json;charset=ISO-8859-1
<
This output is useless for me since I cannot see how the parameters were sent and those cannot fix their format.
The response I get is:
{"Status":"Fail","StatusCode":"400","ResponseMessage":"\"service\" parameter empty! || \"method\" parameter empty! ","SkipMatchingFlag":"No"}
I have been searching for a solution all day long, I've seen a ton of answers on "How to see the RESPONSE body", and "How to see the request HEADERS".
But none for "How to see the request body", so any help would be much appreciated,
Best regards.

get curl work with Content-Disposition of the response header after sending $_POST request

Ok, to understand the problem, first please visit
http://unblockproxy.nu/
Try to surf any website, let's say (http://www.example.com/samplepage.html) put it in the field then click "unblock" button
After sending the $_POST request, the site should redirect you to something like:
http://unblockproxy.nu/index.php?x=Mfv0KjYRb3J3JO50MgBNbplFn2sTMoqPUIu1Unqn0bqdUoq5VbA9OnO8%3D
Response Headers of the browser is like:
HTTP/1.1 302 Found
Date: Fri, 06 Mar 2015 12:49:30 GMT
Server: Apache/2.2.15
x-powered-by: PHP/5.3.3
Location: http://unblockproxy.nu/index.php?x=Mfv0KjYRb3J3JO50MgBNbplFn2sTMoqPUIu1Unqn0bqdUoq5VbA9OnO8%3D
Cache-Control: max-age=600, private, must-revalidate
Expires: Fri, 06 Mar 2015 12:59:30 GMT
Vary: Accept-Encoding
Connection: close
Content-Type: text/html; charset=UTF-8
Transfer-Encoding: chunked
HTTP/1.1 200 OK
Date: Fri, 06 Mar 2015 12:49:34 GMT
Server: Apache/2.2.15
X-Powered-By: PHP/5.3.3
Content-Disposition: inline; filename="samplepage.html"
Cache-Control: max-age=600, private, must-revalidate
Expires: Fri, 06 Mar 2015 12:59:34 GMT
Vary: Accept-Encoding
Connection: close
Content-Type: text/html; charset=UTF-8
Transfer-Encoding: chunked
That's easy, now you got the contents of the surfed page by using this web proxy.
Now, i want to do the same job by using curl
My problem is, i don't know how to let curl deal with Content-Disposition of the response header
Here is some codes to simulate my problem::
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'http://unblockproxy.nu/index.php');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt($ch, CURLOPT_MAXREDIRS, 5);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, array('x' => 'http://www.example.com/samplepage.html'));
curl_setopt($ch, CURLOPT_COOKIESESSION, 1);
curl_setopt($ch, CURLOPT_COOKIEJAR, 'cookies.txt');
curl_setopt($ch, CURLOPT_COOKIEFILE, 'cookies.txt');
$string = curl_exec($ch);
curl_close($ch);
echo $string;
This will return the contents of http://unblockproxy.nu/ and that is not what i want (http://www.example.com/samplepage.html which surfed by http://unblockproxy.nu/)
If you want to take a look into the script of this site (2 PHP files only), you can go here
Thank you.
Try this. This works for me just fine if I'm understanding your question correctly. I removed a lot of code that did nothing. Turns out, the problems was that you weren't setting the referer in the request headers.
Let me start from the beginning. Upon submitting the form via POST to view a given website with a proxy, a request is sent to http://unblockproxy.nu/index.php. As you mentioned in your question, index.php handles the form submission and generates an HTTP status code of 302 which essentially just redirects you to another page. Assuming that you send a properly formatted request to index.php, you can parse the response headers and get the value of the redirect URL. Follow the code below to get the redirect URL.
/**
* Submit the form via POST
* #param [site_url] The link to the page that you want to view
* eg: http://sitetoget.com/page.html
* #return A string containing the response headers
*/
function GetRedirect($site_url) {
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'http://unblockproxy.nu/index.php');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_HEADER, 1);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, array('x' => $site_url));
$response = curl_exec($ch);
curl_close($ch);
return $response;
}
/**
* Turn a header string into an associative array
* #param [response] The response headers from the form submission
* #return An array containing all of the headers
*/
function GetHeaders($response) {
$headers = [];
$text = substr($response, strpos($response, "\r\n\r\n"));
foreach(explode("\r\n", $text) as $i => $line) {
if($i === 0 || $i == 1) {
$headers['http_code'] = $line;
} else {
list($key, $value) = explode(': ', $line);
if($key != '' && $value != '') {
$headers[$key] = $value;
}
}
}
return $headers;
}
// Get the redirect URL
$redirect = GetRedirect('http://lancenewman.me/');
// Parse the response headers
$headers = GetHeaders($redirect);
// Save the redirect URL
$new_url = $headers['Location'];
Now that you have the URL that index.php redirects to, send a cURL request to it as follows. Strangely enough, almost all of the other request headers that I've tinkered with play no role in determining whether or not this solution works. The reason your code is getting the contents of http://unblockproxy.nu instead of the contents of the given site as viewed by http://unblockproxy.nu is because you're not following the redirections correctly and you're not setting the referer in request headers. The cookies, content-disposition and all of the other headers seem to play no role in solving this.
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $new_url);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt($ch, CURLOPT_REFERER, 'http://unblockproxy.nu');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$string = curl_exec($ch);
curl_close($ch);
echo $string;
It's important to note that some of the images, CSS and JS on some of the pages might not properly load because some use relative URLs instead of absolute ones. Just keep that in mind.
The problem is it requires two round-trips to the server to complete the request. Many sites use the method to reduce the number or requests by "bots". The first request creates a cookie (typically for a "session") which must be present in order for the form to be processed.
Perform the curl_exec() twice and see if you get the results you want. The first time the response will send a cookie which curl will save since you have enabled cookies. The second time you should get the results you want.

How to perform a PUT operation using CURL in PHP?

I would like to perform a PUT operation on a webservice using CURL. Let's assume that:
webservice url: http://stageapi.myprepaid.co.za/api/ConsumerRegisterRequest/cac52674-1711-e311-b4a8-00155d4905d3
municipality= NMBM
sgc= 12345
I've written the code below, but it outputs this error message: "ExceptionMessage":"Object reference not set to an instance of an object.". Any help would be so much appreciated. Thanks!
<?php
function sendJSONRequest($url, $data)
{
$data_string = json_encode($data);
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "PUT");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $data_string);
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
'Content-Type: application/json',
'Accept: application/json',
'X-MP-Version: 10072013')
);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
ob_start();
$result = curl_exec($ch);
$info = curl_getinfo($ch);
if ($result === false || $info['http_code'] == 400) {
return $result;
} else {
return $result;
}
ob_end_clean();
curl_close($ch);
}
$mun = $_GET['municipality'];
$sgc = $_GET['sgc'];
$req = $_GET['req']; //cac52674-1711-e311-b4a8-00155d4905d3
//myPrepaid PUT URL
echo $mpurl = "http://stageapi.myprepaid.co.za/api/ConsumerRegisterRequest/$req";
// Set Variables
$data = array("Municipality" => "$mun", "SGC" => "$sgc");
//Get Response
echo $response = sendJSONRequest($mpurl, $data);
?>
I copied your code, but changed it so it pointed at a very basic HTTP server on my localhost. Your code is working correctly, and making the following request:
PUT /api/ConsumerRegisterRequest/cac52674-1711-e311-b4a8-00155d4905d3 HTTP/1.1
Host: localhost:9420
Content-Type: application/json
Accept: application/json
X-MP-Version: 10072013
Content-Length: 37
{"Municipality":"NMBM","SGC":"12345"}
The error message you're receiving is coming from the stageapi.myprepaid.co.za server. This is the full response when I point it back to them:
HTTP/1.1 500 Internal Server Error
Cache-Control: no-cache
Pragma: no-cache
Content-Type: application/json; charset=utf-8
Expires: -1
Server: Microsoft-IIS/8.0
X-AspNet-Version: 4.0.30319
X-Powered-By: ASP.NET
Date: Fri, 30 Aug 2013 04:30:41 GMT
Connection: close
Content-Length: 867
{"Message":"An error has occurred.","ExceptionMessage":"Object reference not set to an instance of an object.","ExceptionType":"System.NullReferenceException","StackTrace":" at MyPrepaidApi.Controllers.ConsumerRegisterRequestController.Put(CrmRegisterRequest value) in c:\\Workspace\\MyPrepaid\\Prepaid Vending System\\PrepaidCloud\\WebApi\\Controllers\\ConsumerRegisterRequestController.cs:line 190\r\n at lambda_method(Closure , Object , Object[] )\r\n at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ActionExecutor.<>c__DisplayClass13.<GetExecutor>b__c(Object instance, Object[] methodParameters)\r\n at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ActionExecutor.Execute(Object instance, Object[] arguments)\r\n at System.Threading.Tasks.TaskHelpers.RunSynchronously[TResult](Func`1 func, CancellationToken cancellationToken)"}
You may want to check out the API to make sure you're passing them the correct information. If you are, the problem could be on their end.
And while I realize this isn't part of your question and this is in development, please remember to sanitize any data from $_GET. :)
Try with:
curl_setopt($ch, CURLOPT_PUT, true);

regex to extract this string or use json decode

In PHP what would the regex be to extract "taken" from below, considering that it is dynamic and is always after status:
HTTP/1.0 200 OK
Date: Sat, 09 Feb 2013 23:07:09 GMT
Accept-Ranges: bytes
Server: Noelios-Restlet-Engine/1.1.7
Content-Type: application/json;charset=UTF-8
Content-Length: 147
X-Cache: MISS from geonisis-2.eurodns.com
X-Cache-Lookup: MISS from geonisis-2.eurodns.com:80
Via: 1.0 geonisis-2.eurodns.com (squid/3.1.10)
Connection: keep-alive
{"service":"availability","domain":"","timestamp":1360451229,"content":{"domainList":[{"status":"taken","name":""}]}}
The following shows that I should be using json decoded. How would one achieve this?
The above in generated using:
$process = curl_init($host);
curl_setopt($process, CURLOPT_HTTPHEADER, array('Content-Type: application/xml', $additionalHeaders));
curl_setopt($process, CURLOPT_HEADER, 1);
curl_setopt($process, CURLOPT_USERPWD, $username . ":" . $password);
curl_setopt($process, CURLOPT_TIMEOUT, 30);
curl_setopt($process, CURLOPT_POST, 1);
curl_setopt($process, CURLOPT_POSTFIELDS, $payloadName);
curl_setopt($process, CURLOPT_RETURNTRANSFER, TRUE);
$return = curl_exec($process);
Remove the header from the response by changing:
curl_setopt($process, CURLOPT_HEADER, false);
And then decode the JSON string with:
$data = json_decode($curlResponse, true);
If you discard headers from the response, you can use:
$json = '{"service":"availability","domain":"","timestamp":1360451229,
"content":{"domainList":[{"status":"taken","name":""}]}}';
$data = json_decode($json, TRUE);
echo $data['content']['domainList'][0]['status'];
Why care about the header? That's a JSON string, just decode it and you'll have an object that you can access easily
in php:
$jsonobj = json_decode('{"service":"availability","domain":"","timestamp":1360451229, "content":{"domainList":[{"status":"taken","name":""}]}}');
in javascript:
var jsonobj = JSON.parse('{"service":"availability","domain":"","timestamp":1360451229,"content":{"domainList":[{"status":"taken","name":""}]}}');
$string = '
HTTP/1.0 200 OK
Date: Sat, 09 Feb 2013 23:07:09 GMT
Accept-Ranges: bytes
Server: Noelios-Restlet-Engine/1.1.7
Content-Type: application/json;charset=UTF-8
Content-Length: 147
X-Cache: MISS from geonisis-2.eurodns.com
X-Cache-Lookup: MISS from geonisis-2.eurodns.com:80
Via: 1.0 geonisis-2.eurodns.com (squid/3.1.10)
Connection: keep-alive
{"service":"availability","domain":"","timestamp":1360451229,"content":{"domainList":[{"status":"taken","name":""}]}}';
$parts = explode("\n", $string);
$json = end($parts);
$data = json_decode($json);
$status = $data->content->domainList[0]->status; die;
echo $status;
Edit (based on the question update):
Remove the CURLOPT_HEADER line from your cURL request. This would simplify the response and make it easier to parse.
If you need to work with headers, you have two options;
// first: regex
preg_match('~"status":"(.*?)"~i', $return, $match);
// print_r($match);
echo $match[1]; // taken
// second: json encode
$response = explode("\r\n\r\n", $return, 3);
// print_r($response);
$json_object = json_decode($response[2]);
$json_array = json_decode($response[2], true); // toArray
// echo $json_object->content->domainList[0]->status;
echo $json_array['content']['domainList'][0]['status'];

Header only retrieval in php via curl

Actually I have two questions.
(1) Is there any reduction in processing power or bandwidth used on remote server if I retrieve only headers as opposed to full page retrieval using php and curl?
(2) Since I think, and I might be wrong, that answer to first questions is YES, I am trying to get last modified date or If-Modified-Since header of remote file only in order to compare it with time-date of locally stored data, so I can, in case it has been changed, store it locally. However, my script seems unable to fetch that piece of info, I get NULL, when I run this:
class last_change {
public last_change;
function set_last_change() {
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, "http://url/file.xml");
curl_setopt($curl, CURLOPT_HEADER, true);
curl_setopt($curl, CURLOPT_FILETIME, true);
curl_setopt($curl, CURLOPT_NOBODY, true);
// $header = curl_exec($curl);
$this -> last_change = curl_getinfo($header);
curl_close($curl);
}
function get_last_change() {
return $this -> last_change['datetime']; // I have tested with Last-Modified & If-Modified-Since to no avail
}
}
In case $header = curl_exec($curl) is uncomented, header data is displayed, even if I haven't requested it and is as follows:
HTTP/1.1 200 OK
Date: Fri, 04 Sep 2009 12:15:51 GMT
Server: Apache/2.2.8 (Linux/SUSE)
Last-Modified: Thu, 03 Sep 2009 12:46:54 GMT
ETag: "198054-118c-472abc735ab80"
Accept-Ranges: bytes
Content-Length: 4492
Content-Type: text/xml
Based on that, 'Last-Modified' is returned.
So, what am I doing wrong?
You are passing $header to curl_getinfo(). It should be $curl (the curl handle). You can get just the filetime by passing CURLINFO_FILETIME as the second parameter to curl_getinfo(). (Often the filetime is unavailable, in which case it will be reported as -1).
Your class seems to be wasteful, though, throwing away a lot of information that could be useful. Here's another way it might be done:
class URIInfo
{
public $info;
public $header;
private $url;
public function __construct($url)
{
$this->url = $url;
$this->setData();
}
public function setData()
{
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, $this->url);
curl_setopt($curl, CURLOPT_FILETIME, true);
curl_setopt($curl, CURLOPT_NOBODY, true);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_HEADER, true);
$this->header = curl_exec($curl);
$this->info = curl_getinfo($curl);
curl_close($curl);
}
public function getFiletime()
{
return $this->info['filetime'];
}
// Other functions can be added to retrieve other information.
}
$uri_info = new URIInfo('http://www.codinghorror.com/blog/');
$filetime = $uri_info->getFiletime();
if ($filetime != -1) {
echo date('Y-m-d H:i:s', $filetime);
} else {
echo 'filetime not available';
}
Yes, the load will be lighter on the server, since it's only returning only the HTTP header (responding, after all, to a HEAD request). How much lighter will vary greatly.
Why use CURL for this? There is a PHP-function for that:
$headers=get_headers("http://www.amazingjokes.com/img/2014/530c9613d29bd_CountvonCount.jpg");
print_r($headers);
returns the following:
Array
(
[0] => HTTP/1.1 200 OK
[1] => Date: Tue, 11 Mar 2014 22:44:38 GMT
[2] => Server: Apache
[3] => Last-Modified: Tue, 25 Feb 2014 14:08:40 GMT
[4] => ETag: "54e35e8-8873-4f33ba00673f4"
[5] => Accept-Ranges: bytes
[6] => Content-Length: 34931
[7] => Connection: close
[8] => Content-Type: image/jpeg
)
Should be easy to get the content-type after this.
You could also add the format=1 to get_headers:
$headers=get_headers("http://www.amazingjokes.com/img/2014/530c9613d29bd_CountvonCount.jpg",1);
print_r($headers);
This will return the following:
Array
(
[0] => HTTP/1.1 200 OK
[Date] => Tue, 11 Mar 2014 22:44:38 GMT
[Server] => Apache
[Last-Modified] => Tue, 25 Feb 2014 14:08:40 GMT
[ETag] => "54e35e8-8873-4f33ba00673f4"
[Accept-Ranges] => bytes
[Content-Length] => 34931
[Connection] => close
[Content-Type] => image/jpeg
)
More reading here (PHP.NET)
(1) Yes. A HEAD request (as you're issuing in this case) is far lighter on the server because it only returns the HTTP headers, as opposed to the headers and content like a standard GET request.
(2) You need to set the CURLOPT_RETURNTRANSFER option to true before you call curl_exec() to have the content returned, as opposed to printed:
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
That should also make your class work correctly.
You can set the default stream context:
stream_context_set_default(
array(
'http' => array(
'method' => 'HEAD'
)
)
);
Then use:
$headers = get_headers($url,1);
get_headers seems to be more efficient than cURL once get_headers skip steps like trigger authentication routines such as log in prompts or cookies.
Here is my implementation using CURLOPT_HEADER, then parsing the output string into a map:
function http_headers($url){
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_NOBODY, true);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HEADER, true);
$headers = curl_exec($ch);
curl_close($ch);
$data = [];
$headers = explode(PHP_EOL, $headers);
foreach ($headers as $row) {
$parts = explode(':', $row);
if (count($parts) === 2) {
$data[trim($parts[0])] = trim($parts[1]);
}
}
return $data;
};
Sample usage:
$headers = http_headers('https://i.ytimg.com/vi_webp/g-dKXOlsf98/hqdefault.webp');
print_r($headers);
Array
(
['Content-Type'] => 'image/webp'
['ETag'] => '1453807629'
['X-Content-Type-Options'] => 'nosniff'
['Server'] => 'sffe'
['Content-Length'] => 32958
['X-XSS-Protection'] => '1; mode=block'
['Age'] => 11
['Cache-Control'] => 'public, max-age=7200'
)
You need to add
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
to return the header instead of printing it.
Whether returning only the headers is lighter on the server depends on the script that's running, but usually it will be.
I think you also want "filetime" instead of "datetime".

Categories