How to get json string and header element using cURL - php

I've been trying to get json and some header elements using this code:
And I was able to print the details that I need but it seems that I can't actually "get" them.
$url = 'http://192.168.254.211:8080/sampleOnCurl/auth/login';
$initCurl = curl_init($url);
curl_setopt_array($initCurl,
array(
CURLOPT_URL => $url,
CURLOPT_POST => true,
// CURLOPT_NOBODY => true,
CURLOPT_RETURNTRANSFER => true,
// CURLOPT_FOLLOWLOCATION => true,
CURLOPT_POSTFIELDS => $loginData,
CURLOPT_HEADER => true,
CURLOPT_HTTPHEADER => array(
'Content-Type: application/json',
'jrr: 7ffed684cbe1fc085b7b47dc4e508e99a5effee9',
'slave: 01bdfcc20777907712e97f7bd2faeb978584f317',
'spoil: ' .$timeStamp
)
)
);
$result = curl_exec($initCurl);
print_r($result);
//prints jrr, slave, spoil
$result = json_decode($result);
// $header = curl_getinfo($initCurl);
curl_close($initCurl);
and this is what I get
HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
jrr: 2e278657295bdfae2bc49b0bc6ad38363e9b149b
slave: d77985811796708b89471b4d29a904b224d41dde
spoil: 20130916222842701
Content-Type: application/json;charset=UTF-8
Transfer-Encoding: chunked
Date: Mon, 16 Sep 2013 14:28:42 GMT
{"true":null}
I want to get {"true":null} and convert it to array to check if index is true
and get jrr, slave and spoil values .. without using the get method ..
The string that is printed doesn't seem to be in json as well. My guess is that the problem is in my curl options. What could I be missing out?
Here's what I need to do:
get the json {"true":null}
get the Response Header: jrr, slave, spoil
avoid using Get method
thanks

How about something like this:
list($headers, $body) = explode("\r\n\r\n", $result, 2);
function parseSimpleHeaders($headers) {
$lines = explode("\r\n", $headers);
$parsed = array();
foreach($lines as $line) {
$colon = strpos($line, ':');
if($colon !== false) {
$name = trim(substr($line, 0, $colon));
$value = trim(substr($line, $colon + 1));
$parsed[$name] = $value;
}
}
return $parsed;
}
$headers = parseSimpleHeaders($headers);
$json = json_decode($body);
echo $headers['jrr'], "\n"; // 2e278657295bdfae2bc49b0bc6ad38363e9b149b
echo $headers['slave'], "\n"; // d77985811796708b89471b4d29a904b224d41dde
echo $headers['spoil'], "\n"; // 20130916222842701
var_dump($json); // object(stdClass)#1 (1) { ["true"] => NULL }
N.B. There's a http_parse_headers() function in pecl_http but I've included my own simplified version parseSimpleHeaders() in case it's not installed.

You are getting response content and header in variable $result so you can't parse it directly.
To get it working explode $result using two new lines.
$result = explode("\n\n", $result);
and now you can access headers string by $result[0] and response content by $result[1] (and parse it using json_decode($result[1], true).

Related

Extracting Content-Type of external website and save the value on JSON file as "Null"

I'm trying to extract the encode of external website and save it on a JSON File (UTF-8).
It was working well until I tried "www.secra.de" it save the value from this page as Null.
As I can see is that obtain more than values on the "Content-Type" and I think it could be the redirection but I'm not sure.
What is the best way to solve it?
$domain = "http://www.secra.de";
$info = get_headers($domain, 1)["Content-Type"];
$infostr = explode('=', $info);
$encoding = end($infostr);
if (!empty($info)){
$data_array[$key]['encode'] = $encoding;
} else {
$data_array[$key]['encode'] = "It don't have Encode";
}
$json = json_encode($data_array);
file_put_contents('data/data.json', $json);
};
The problem is that http://www.secra.de redirects to https://www.secra.de, and the get_headers functions returns you the Content-Type for both the original and the redirected request:
[Content-Type] => Array
(
[0] => text/html; charset=iso-8859-1
[1] => text/html; charset=utf-8
)
So the problem is that you're treating $info as a string when it is an array. Fix that:
$info = get_headers($domain, 1)["Content-Type"];
if (is_array($info)) {
$info = end($info);
}
$infostr = explode('=', $info);
$encoding = end($infostr);

How to get/set Header in Rest Server API?

i have a chriskacerguis Rest Server ,that listen for a client request as usually an API Server do.
base on client request i want to send/response some data to client in header only.
my questions are:
how do i access Client header first? then
how do i set Header in Rest Server?
This is how i send a request to REST SERVER:
function request_curl($url = NULL) {
$utc = time();
$post = "id=1&CustomerId=1&amount=2450&operatorName=Jondoe&operator=12";
$header_data = array(
"Content-Type: application/json",
"Accept: application/json",
"X-API-KEY:3ecbcb4e62a00d2bc58080218a4376f24a8079e1",
"X-UTC:" . $utc,
);
$ch = curl_init();
$curlOpts = array(
CURLOPT_URL => 'http://domain.com/customapi/api/clientRequest',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => $header_data,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => $post,
CURLOPT_HEADER => 1,
);
curl_setopt_array($ch, $curlOpts);
$answer = curl_exec($ch);
// If there was an error, show it
if (curl_error($ch)) {
die(curl_error($ch));
}
curl_close($ch);
echo '<pre>';
print_r($answer);
echo '</pre>';
}
Below is my REST SERVER function that listen request and will response a header:
public function clientRequest_post() {
// Getting Post Data
$entityBody = file_get_contents('php://input', 'r');
$this->response($entityBody,200);
//getting header data ,no idea
}
May be try php function getallheaders() which will fetch all the header data for you. If you want to convert it into array, use foreach.
So this will get you the header data and will convert it into array
$headers=array();
foreach (getallheaders() as $name => $value) {
$headers[$name] = $value;
}
Now if you want to get body and convert it into array as well
$entityBody = file_get_contents('php://input', 'r');
parse_str($entityBody , $post_data);
The final function will look something like this...
public function clientRequest_post() {
$headers=array();
foreach (getallheaders() as $name => $value) {
$headers[$name] = $value;
}
$entityBody = file_get_contents('php://input', 'r');
parse_str($entityBody , $post_data);
$this->response($entityBody, 200);
}
Btw, I assume $this->response($entityBody,200); will generate the response for you. Best of luck with it

Detect content type in a request made with cURL

I am trying to send cURL request to a remote API server with this code:
$ch = curl_init();
$options = array(CURLOPT_URL => 'http://minecms.info/update/index.php',
CURLOPT_POST => true,
CURLOPT_RETURNTRANSFER => 1,
CURLOPT_POSTFIELDS => $data,
CURLOPT_HTTPHEADER => array('Content-type: application/json'),
CURLOPT_SSL_VERIFYPEER => false
);
curl_setopt_array($ch, $options);
$response = curl_exec($ch);
But I don't want users accessing the updates page on their browsers so I set a content type header on the request. The problem is that I don't know how to detect this content type on the remote server. Basically what I want is to check whether the client request has a content type: application/json set if yes it executes the rest of the code if not it just does exit;.
Thank you to anyone who would help in advance.
You can try using getallheaders() and check whether the Content-Type is in place.
Give a look at the man http://www.php.net/manual/it/function.getallheaders.php for insights
---- EDIT INSIGHTS ----
And what about this one? (Which I'm currently using)
public function getAllHeaders()
{
if(function_exists('getallheaders'))
{
return getallheaders();
}
$headers = array();
foreach ($this->parameters as $key => $value)
{
if (substr($key, 0, 5) == 'HTTP_')
{
$headers[str_replace(" ", "-", ucwords(strtolower(str_replace("_", " ", substr($key, 5)))))] = $value;
}
if ($key == "CONTENT_TYPE")
{
$headers["Content-Type"] = $value;
}
}
return $headers;
}

Php Curl and Json

My question is I want to get acess my fb friends using curl and decode into json then i want to show only those friends whose name starting with letter a such as aman,adam etc pls help me..Following is my code.
<?php
// create a new cURL resource
$json_url="https://graph.facebook.com/100001513782830/friends?access_token=AAACEdEose0cBAPdK62FSjs4RvA21efqc8ZBKyzAesT5r4VSpu0XScAYDtKrCxk4PmcRBVzE2SLiGvs2d5FeXvZAD72ZCShwge3vk4DQqRAb8vLlm1W3";
$ch = curl_init( $json_url );
// Configuring curl options
/* $options = array(
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => array('Content-type: application/json')
);
// Setting curl options
curl_setopt_array( $ch );
*/// Getting results
$result = curl_exec($ch); // Getting jSON result string
$obj = json_decode($result, true);
foreach($obj[data] as $p)
{
echo '
Name: '.$p[name][first].'
Age: '.$p[age].'
';
}
You will offcourse try not to hardcode "a" but for this purpose :
foreach($obj[data] as $p){
if(strtolower(substr(trim($p[name][first]),0,1)) == 'a'){
echo 'Name: '.$p[name][first].'Age: '.$p[age];
}
}
Btw, it is not a good idea to post security tokens (in URL) to public places.
Since the name is string, you can simply iterate over that array and filter by name:
$letter = 'A';
foreach($obj['data'] as $p) {
if ($p['name'][0] == $letter) {
// do something with $p
}
}
But there is a little problem with UTF-8 -- this solution (and that one with substr too) will not work on multibyte characters. So you need to use mb_substr instead of plain substr function:
foreach($obj['data'] as $p) {
if(mb_strtolower(mb_substr($p['name'], 0, 1))) == 'Á'){
echo "Name: ", $p['name'], "\n",
"Age: ", $p['age'], "\n";
}
}

PHP curl_exec returns both HTTP/1.1 100 Continue and HTTP/1.1 200 OK separated by space

I'm calling a service from PHP using cURL, like this:
$response = curl_exec($ch);
and the request/response headers look something like this:
Request:
POST /item/save HTTP/1.1
Host: services.mydomain.com
Accept: */*
Content-Length: 429
Expect: 100-continue
Content-Type: multipart/form-data
Response:
HTTP/1.1 100 Continue
HTTP/1.1 200 OK
Date: Fri, 06 Jul 2012 08:37:01 GMT
Server: Apache
Vary: Accept-Encoding,User-Agent
Content-Length: 256
Content-Type: application/json; charset=utf-8
followed by the body (json encoded data).
The problem is that the common thing is to split headers and body in the response by the first empty line encountered, except in this case, the empty line is after the 100 Continue and therefore everything else gets pushed into the body–and that is not valid json anymore :-)
So my question is this: What's the common way to deal with this?
I have 3 options lined up:
Specify that curl should not expect 100-continue? (How?)
Specify that curl should only send back the headers of the last response? (How?)
Manually check for 100 Continue headers and disregard them and their following empty line? (In that case, are there other similar things that could happen, that I should manually check for?)
Unless I'm missing something obvious, I'm sure people have stumbled upon this and solved it many times!
I will opt for #1.
You can force curl to send empty "Expect" header, by adding:
curl_setopt($ch, CURLOPT_HTTPHEADER,array("Expect:"));
to your code
If you want check it manually, you should define your own header callback and maybe write callback (look for CURLOPT_HEADERFUNCTION and CURLOPT_WRITEFUNCTION in curl_setopt doc), which has simply to ignore all "HTTP/1.1 100 Continue" headers.
Here's another method that uses the approach I described in the comment by parsing the response into header vs. body using CURLINFO_HEADER_SIZE:
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "http://test/curl_test.php");
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLINFO_HEADER_OUT, 1);
curl_setopt($ch, CURLOPT_HEADER, 1);
// sets multipart/form-data content-type
curl_setopt($ch, CURLOPT_POSTFIELDS, array(
'field1' => 'foo',
'field2' => 'bar'
));
$data = curl_exec($ch);
// if you want the headers sent by CURL
$sentHeaders = curl_getinfo($ch, CURLINFO_HEADER_OUT);
$headerSize = curl_getinfo($ch, CURLINFO_HEADER_SIZE);
curl_close($ch);
$header = substr($data, 0, $headerSize);
$body = substr($data, $headerSize);
echo "==Sent Headers==\n$sentHeaders\n==End Sent Headers==\n";
echo "==Response Headers==\n$headers\n==End Response Headers==\n";
echo "==Response Body==\n$body\n==End Body==";
I've tested this, and it results in the following output:
==Sent Headers==
POST /curl_test.php HTTP/1.1
Host: test
Accept: */*
Content-Length: 242
Expect: 100-continue
Content-Type: multipart/form-data; boundary=----------------------------
d86ac263ce1b
==End Sent Headers==
==Response Headers==
HTTP/1.1 100 Continue
HTTP/1.1 200 OK
Date: Fri, 06 Jul 2012 14:21:53 GMT
Server: Apache/2.4.2 (Win32) PHP/5.4.4
X-Powered-By: PHP/5.4.4
Content-Length: 112
Content-Type: text/plain
==End Response Headers==
==Response Body==
**FORM DATA**
array(2) {
["field1"]=>
string(3) "foo"
["field2"]=>
string(3) "bar"
}
**END FORM DATA**
==End Body==
i had the same problem but this solution does note work for me, finaly i have found this methode and all its fine:
we have to prepare data post fields before sending them:
function curl_custom_postfields($curl, array $assoc = array(), array $files = array()) {
/**
* For safe multipart POST request for PHP5.3 ~ PHP 5.4.
* #param resource $ch cURL resource
* #param array $assoc "name => value"
* #param array $files "name => path"
* #return bool
*/
// invalid characters for "name" and "filename"
static $disallow = array("\0", "\"", "\r", "\n");
// build normal parameters
foreach ($assoc as $key => $value) {
$key = str_replace($disallow, "_", $key);
$body[] = implode("\r\n", array(
"Content-Disposition: form-data; name=\"{$key}\"",
"",
filter_var($value),
));
}
// build file parameters
foreach ($files as $key => $value) {
switch (true) {
case false === $value = realpath(filter_var($value)):
case !is_file($value):
case !is_readable($value):
continue; // or return false, throw new InvalidArgumentException
}
$data = file_get_contents($value);
$value = call_user_func("end", explode(DIRECTORY_SEPARATOR, $value));
$key = str_replace($disallow, "_", $key);
$value = str_replace($disallow, "_", $value);
$body[] = implode("\r\n", array(
"Content-Disposition: form-data; name=\"{$key}\"; filename=\"{$value}\"",
"Content-Type: application/octet-stream",
"",
$data,
));
}
// generate safe boundary
do {
$boundary = "---------------------" . md5(mt_rand() . microtime());
} while (preg_grep("/{$boundary}/", $body));
// add boundary for each parameters
array_walk($body, function (&$part) use ($boundary) {
$part = "--{$boundary}\r\n{$part}";
});
// add final boundary
$body[] = "--{$boundary}--";
$body[] = "";
// set options
return #curl_setopt_array($curl, array(
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => implode("\r\n", $body),
CURLOPT_HTTPHEADER => array(
"Expect: 100-continue",
"Content-Type: multipart/form-data; boundary={$boundary}", // change Content-Type
),
));}
you have to prepare two arrays:
1- post field with normal data: (name1 = val1, name2 = val2, ...)
2- post field with file data: (name_file 1, path_file1, name_file2 = path_file2, ..)
and finaly call this function before executing curl like this.
$r = curl_custom_postfields($curl, $post, $postfields_files);
I have come across this with 100s and 302s etc it's annoying but sometimes needed (gdata calls etc) so i would say leave curl returning all headers and extract the body a little differently.
I handle it like this (can't find my actual code but you'll get the idea):
$response = curl_exec($ch);
$headers = array();
$body = array();
foreach(explode("\n\n", $response) as $frag){
if(preg_match('/^HTTP\/[0-9\.]+ [0-9]+/', $frag)){
$headers[] = $frag;
}else{
$body[] = $frag;
}
}
echo implode("\n\n", $headers);
echo implode("\n\n", $body);
I begrudge the longwinded hackish method (would prefer it if curl marked the body content somehow) but it has worked well over the years. let us know how you get on.

Categories