Using some code from NHTSA's API, my own and ideas from this site, wrapping it into a function, it is working just fine but would not run on my live server.
On the live server, it was giving an error which I finally solved to the code using an array shortcut not supported by my live server's PHP version:
Parse error: syntax error, unexpected '[', expecting ')' in /home/pchome/public_html/verify/functions/sitefunctions.php on line 9
which is this line:
$postdata = http_build_query(["data" => $VINS, "format" => "JSON"]);
Changed to this it works and also changed similar code in several other places in the same manner:
$postdata = http_build_query(array("data" => $VINS, "format" => "JSON"));
Occasionally (but not always) I may want to pass multiple VINs to it as a semicolon-separated list. This format is not changeable so what is needed to give this functionality? (Sample VINs: 3GNDA13D76S000000;5XYKT3A12CG000000
// Uses NHTSA API to decode VIN(s)
function decodeVINS($VINS) {
if ($VINS) :
$return = "";
$postdata = http_build_query(array("data" => $VINS, "format" => "JSON"));
$stream_options = array(
'http' => array(
'header' => "Content-Type: application/x-www-form-urlencoded\r\n".
"Content-Length: ".strlen($postdata)."\r\n",
'method' => "POST",
'content' => $postdata
)
);
$context = stream_context_create($stream_options);
$apiURL = "https://vpic.nhtsa.dot.gov/api/vehicles/DecodeVINValuesBatch/";
$fp = #fopen($apiURL, 'rb', FALSE, $context);
$results = array_column(json_decode(#stream_get_contents($fp),TRUE), '0');
$results = $results[0];
$output = "<blockquote>\n";
$output .= "<div><strong>VIN: {$results['VIN']}</strong></div>\n";
$output .= "<div><strong>ErrorCode: {$results['ErrorCode']}</strong></div>\n";
if ($results['AdditionalErrorText']) :
$output .= "<div><strong>AdditionalErrorText: {$results['AdditionalErrorText']}</strong></div>\n";
endif;
foreach ($results as $key => $val) :
if ($val && $key != "VIN" && $key != "ErrorCode" && $key != "AdditionalErrorText") :
$output .= "<div>$key: $val</div>";
endif;
endforeach;
$output .= "</blockquote>\n\n";
else :
$output = "Enter VINs above separated by line breaks";
endif;
return $output;
}
. . . and it is outputting something like this:
VIN: JB7FJ43S5KJ000911
ErrorCode: 0 - VIN decoded clean. Check Digit (9th position) is correct
BodyClass: Sport Utility Vehicle (SUV)/Multi Purpose Vehicle (MPV)
DisplacementCC: 3000
DisplacementCI: 183.0712322841
DisplacementL: 3
DriveType: 4WD/4-Wheel Drive/4x4
EngineConfiguration: V-Shaped
EngineCylinders: 6
FuelTypePrimary: Gasoline
GVWR: Class 1C: 4,001 - 5,000 lb (1,814 - 2,268 kg)
Make: DODGE
Manufacturer: MITSUBISHI MOTORS CORPORATION (MMC)
ManufacturerId: 1052
Model: Raider
ModelYear: 1989
PlantCity: Nagoya
PlantCompanyName: Nagoya #3
PlantCountry: Japan
VehicleType: TRUCK
Working with JSON instead of CSV, in my opinion, is going to be much easier/direct/stable.
I have added a parameter ($fields) to the custom function call which will dictate how to isolate and sort your data.
I have also modified the first parameter ($VINs), to be passed as an array instead of a semicolon delimited string. This I hope simplifies your processing -- if it doesn't you are welcome to fallback to your original string format and remove my implode(";",$VINs) call.
Code: (Demo)
function searchByVINs ($VINs,$fields) {
// test multi-VIN batching via textarea at bottom of https://vpic.nhtsa.dot.gov/api/
$stream_options_content = http_build_query(["data" => implode(";", $VINS), "format" => "JSON"]);
$stream_options = [
'http' => [
'header' => "Content-Type: application/x-www-form-urlencoded\r\n".
"Content-Length: ".strlen($postdata)."\r\n",
'method' => "POST",
'content' => $postdata
]
];
$context = stream_context_create($stream_options);
$apiURL = "https://vpic.nhtsa.dot.gov/api/vehicles/DecodeVINValuesBatch/";
if (!$fp = #fopen($apiURL, "rb", FALSE, $context)) {
return ["success" => false, "response" => "Unable to open stream"];
}
if (!$response = stream_get_contents($fp),true)) {
return ["success" => false, "response" => "Unable to receive streamed data"];
}
if(($data = #json_decode($response,true)) === null && json_last_error()!==JSON_ERROR_NONE){
return ["success" => false, "response" => "Unable to parse streamed data"];
}
if (!isset($data["Message"]) || $data["Message"] != "Results returned successfully") {
return ["success" => false, "response" => "Received unsuccessful dataset"];
}
$return = [];
$keys = array_flip($fields);
foreach ($data["Results"] as $dataset) {
$isolated = array_intersect_key($dataset,$keys); // only retain the elements with keys that match $fields values
$sorted = array_replace($keys,$isolated); // order the dataset by order of elements in $fields
$return[] = $sorted;
}
return ["success" => true, "response" => $return];
}
$VINs = ["3GNDA13D76S000000", "5XYKT3A12CG000000"];
$fields = ["VIN", "ModelYear", "Make", "FuelTypePrimary", "DriveType", "BodyClass"];
$response = searchByVINs($VINs,$fields);
if (!$response["success"]) {
echo "Oops, the api call failed. {$response["response"]}";
} else {
foreach ($response["response"] as $item){
echo "<div>";
foreach ($item as $key => $value) {
echo "<div>$key: $value</div>";
}
echo "</div>";
}
}
Output (from mocked demo)
<div>
<div>VIN: 3GNDA13D76S000000</div>
<div>ModelYear: 2006</div>
<div>Make: CHEVROLET</div>
<div>FuelTypePrimary: Gasoline</div>
<div>DriveType: </div>
<div>BodyClass: Wagon</div>
</div>
<div>
<div>VIN: 5XYKT3A12CG000000</div>
<div>ModelYear: 2012</div>
<div>Make: KIA</div>
<div>FuelTypePrimary: Gasoline</div>
<div>DriveType: 4x2</div>
<div>BodyClass: Wagon</div>
</div>
All working now so here is the final version! As needed, shows only rows with values and can handle multiple VINs in one submission. The function is called from a simple form that has a textarea for entering the VINs, along with a Submit button.
// Uses NHTSA API to decode VIN(s)
function decodeVINS($VINS) {
// sample VINs 3GNDA13D76S000000;5XYKT3A12CG000000
if ($VINS) :
$postdata = http_build_query(array("data" => $VINS, "format" => "JSON"));
$stream_options = array(
'http' => array(
'header' => "Content-Type: application/x-www-form-urlencoded\r\n".
"Content-Length: ".strlen($postdata)."\r\n",
'method' => "POST",
'content' => $postdata
)
);
$context = stream_context_create($stream_options);
$apiURL = "https://vpic.nhtsa.dot.gov/api/vehicles/DecodeVINValuesBatch/";
$fp = #fopen($apiURL, 'rb', FALSE, $context);
$returnValue = json_decode(#stream_get_contents($fp),TRUE);
if(!isset($returnValue['Results'])):
echo "Invalid return data or no return data. Exiting";
return FALSE;
endif;
$results = $returnValue['Results'];
if(!is_array($results)):
$results = array($results);
endif;
$output = '';
foreach($results as $result):
$output .= "<blockquote>\n";
$output .= "<div><strong>VIN: {$result['VIN']}</strong></div>\n";
$output .= "<div><strong>ErrorCode: {$result['ErrorCode']}</strong></div>\n";
if ($result['AdditionalErrorText']) :
$output .= "<div><strong>AdditionalErrorText: {$result['AdditionalErrorText']}</strong></div>\n";
endif;
foreach ($result as $key => $val) :
if ($val && $key != "VIN" && $key != "ErrorCode" && $key != "AdditionalErrorText") :
$output .= "<div>$key: $val</div>";
endif;
endforeach;
$output .= "</blockquote>\n\n";
endforeach;
else :
$output = "Enter VINs above separated by line breaks";
endif;
return $output;
}
Related
I am trying to get sentiment scores of random product descriptions from a CSV file, I'm facing a problem with what I think is the API response time, not sure if I'm traversing through the CSV using the API incorrectly / un-efficiently but it is taking a long time to get results for all the 300+ entries in the CSV and whenever I want to push new changes to my codebase I need to wait for the API to re-evaluate the entries every time, here is my code I made for loading in the CSV file and for getting the sentiment scores
<?php
set_time_limit(500); // extended timeout due to slow / overwhelmed API response
function extract_file($csv) { // CSV to array function
$file = fopen($csv, 'r');
while (!feof($file)) {
$lines[] = fgetcsv($file, 1000, ',');
}
fclose($file);
return $lines;
}
$the_file = 'dataset.csv';
$csv_data = extract_file($the_file);
$response_array = []; // array container to hold returned sentiment values from among prduct descriptions
for($x = 1; $x < count($csv_data) - 1; $x++) { // loop through all descriptions
echo $x; // show iteration
$api_text = $csv_data[$x][1];
$api_text = str_replace('&', ' and ', $api_text); // removing escape sequence characters, '&' breaks the api :)
$api_text = str_replace(" ", "%20", $api_text); // serializing string
$text = 'text=';
$text .=$api_text; // serializing string further for the API
//echo 'current text1: ', $api_text;
$curl = curl_init(); // API request init
curl_setopt_array($curl, [
CURLOPT_URL => "https://text-sentiment.p.rapidapi.com/analyze",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => $text,
CURLOPT_HTTPHEADER => [
"X-RapidAPI-Host: text-sentiment.p.rapidapi.com",
"X-RapidAPI-Key: <snip>",
"content-type: application/x-www-form-urlencoded"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}
$json = json_decode($response, true); // convert response to JSON format
if(isset($json["pos"]) == false) { // catching response error 100, makes array faulty otherwise
continue;
}
else {
array_push($response_array, array($x, "+" => $json["pos"], "-" => $json["neg"])); // appends array with sentiment values at current index
}
}
echo "<br>";
echo "<br> results: ";
echo "<p>";
for ($y = 0; $y < count($response_array); $y++){ // prints out all the sentiment values
echo "<br>";
echo print_r($response_array[$y]);
echo "<br>";
}
echo "</p>";
echo "<br>the most negative description: ";
$max_neg = array_keys($response_array, max(array_column($response_array, '-')));
//$max_neg = max(array_column($response_array, '-'));
echo print_r($csv_data[$max_neg[0]]);
echo "<br>the most positive description: ";
$max_pos = array_keys($response_array, max(array_column($response_array, '+')));
echo print_r($csv_data[$max_pos[0]]);
?>
What this code snippet aims to do is find the most negative and most positive sentiment among the description column in the csv and print them out according to their index, I'm only interested in finding descriptions with the highest amount of positive and negative sentiment word number not the percentage of the overall sentiment
The file can be found in this git repo
Thanks for any suggestions
This can be achieved by creating a cache file.
This solution creates a file cache.json that contains the results from the API, using the product name as the key for each entry.
On subsequent calls, it will use the cache value if it exists.
set_time_limit(500);
function file_put_json($file, $data)
{
$json = json_encode($data, JSON_PRETTY_PRINT);
file_put_contents($file, $json);
}
function file_get_json($file, $as_array=false)
{
return json_decode(file_get_contents($file), $as_array);
}
function file_get_csv($file, $header_row=true)
{
$handle = fopen($file, 'r');
if ($header_row === true)
$header = fgetcsv($handle);
$array = [];
while ($row = fgetcsv($handle)) {
if ($header_row === true) {
$array[] = array_combine($header, array_map('trim', $row));
} else {
$array[] = array_map('trim', $row);
}
}
fclose($handle);
return $array;
}
function call_sentiment_api($input)
{
$text = 'text=' . $input;
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://text-sentiment.p.rapidapi.com/analyze",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => $text,
CURLOPT_HTTPHEADER => [
"X-RapidAPI-Host: text-sentiment.p.rapidapi.com",
"X-RapidAPI-Key: <snip>",
"content-type: application/x-www-form-urlencoded"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
throw new Exception("cURL Error #:" . $err);
}
return $response;
}
$csv_data = file_get_csv('dataset.csv');
if (file_exists('cache.json')) {
$cache_data = file_get_json('cache.json', true);
} else {
$cache_data = [];
}
$cache_names = array_keys($cache_data);
$output = [];
foreach ($csv_data as $csv) {
$product_name = $csv['name'];
echo $product_name . '...';
if (in_array($product_name, $cache_names)) {
echo 'CACHED...' . PHP_EOL;
continue;
}
$description = urlencode(str_replace('&', ' and ', $csv['description']));
$response = call_sentiment_api($description);
echo 'API...' . PHP_EOL;
$json = json_decode($response, true);
$cache_data[$product_name] = $json;
}
file_put_json('cache.json', $cache_data);
echo 'SAVE CACHE!' . PHP_EOL . PHP_EOL;
$highest_pos = 0;
$highest_neg = 0;
$pos = [];
$neg = [];
foreach ($cache_data as $name => $cache) {
if (!isset($cache['pos']) || !isset($cache['neg'])) {
continue;
}
if ($cache['pos'] > $highest_pos) {
$pos = [$name => $cache];
$highest_pos = $cache['pos'];
}
if ($cache['pos'] === $highest_pos) {
$pos[$name] = $cache;
}
if ($cache['neg'] > $highest_neg) {
$neg = [$name => $cache];
$highest_neg = $cache['neg'];
}
if ($cache['neg'] === $highest_neg) {
$neg[$name] = $cache;
}
}
echo "Most Positive Sentiment: " . $highest_pos . PHP_EOL;
foreach ($pos as $name => $pos_) {
echo "\t" . $name . PHP_EOL;
}
echo PHP_EOL;
echo "Most Negative Sentiment: " . $highest_neg . PHP_EOL;
foreach ($neg as $name => $neg_) {
echo "\t" . $name . PHP_EOL;
}
Results in:
Most Positive Sentiment: 4
X-Grip Lifting Straps - GymBeam
Beta Carotene - GymBeam
Chelated Magnesium - GymBeam
Creatine Crea7in - GymBeam
L-carnitine 1000 mg - GymBeam - 20 tabs
Resistance Band Set - GymBeam
Most Negative Sentiment: 2
Calorie free Ketchup sauce 320 ml - GymBeam
ReHydrate Hypotonic Drink 1000 ml - GymBeam
Vitamin E 60 caps - GymBeam
Vitamin B-Complex 120 tab - GymBeam
Zero Syrup Hazelnut Choco 350 ml - GymBeam
Bio Psyllium - GymBeam
Zero calorie Vanilla Syrup - GymBeam
You need to know where the time is going.
Start with identifying where the time goes in the curl request.
My guess is the API response time.
If that's the case I have a solution. Meanwhile I will get the "multi-tasking" code code I use to do simultaneous curl requests.
curl has the timing you need. It looks like this:
'total_time' => 0.029867,
'namelookup_time' => 0.000864,
'connect_time' => 0.001659,
'pretransfer_time' => 0.00988,
'size_upload' => 0.0,
'size_download' => 8300.0,
'speed_download' => 277898.0,
'speed_upload' => 0.0,
Just add a couple of lines of code
$response = curl_exec($curl);
$info = var_export(curl_getinfo($curl),true);
file_put_contents('timing.txt',$info,FILE_APPEND);
Running simultaneous curl sockets.
Put your curl in curl.php
$text = $_GET['text'];
curl_setopt_array($curl, [
CURLOPT_URL => "https://text-sentiment.p.rapidapi.com/analyze",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => $text,
CURLOPT_HTTPHEADER => [
"X-RapidAPI-Host: text-sentiment.p.rapidapi.com",
"X-RapidAPI-Key: <snip>",
"content-type: application/x-www-form-urlencoded"
],
]);
This code goes in your CSV loop to create all the URL query fields to pass to curl.php (e.g. http://127.0.0.1/curl.php?text=$text)
$query = urlencode($text);
$urls[] = array('host' => "127.0.0.1",'path' => "/curl.php?text=$query
Then process all the URLs.
foreach($urls as $path){
$host = $path['host'];
$path = $path['path'];
$http = "GET $path HTTP/1.0\r\nHost: $host\r\n\r\n";
$stream = stream_socket_client("$host:80", $errno,$errstr, 120,STREAM_CLIENT_ASYNC_CONNECT|STREAM_CLIENT_CONNECT);
if ($stream) {
$sockets[] = $stream; // supports multiple sockets
fwrite($stream, $http);
}
else {
$err .= "$id Failed<br>\n";
}
}
Then Monitor the sockets and retrieve the response from each socket.
Then close the socket until you have them all.
while (count($sockets)) {
$read = $sockets;
stream_select($read, $write = NULL, $except = NULL, $timeout);
if (count($read)) {
foreach ($read as $r) {
$id = array_search($r, $sockets);
$data = fread($r, $buffer_size);
if (strlen($data) == 0) {
// echo "$id Closed: " . date('h:i:s') . "\n\n\n";
$closed[$id] = microtime(true);
fclose($r);
unset($sockets[$id]);
}
else {
$results[$id] .= $data;
}
}
}
else {
// echo 'Timeout: ' . date('h:i:s') . "\n\n\n";
break;
}
}
Then all your results are in $results[].
I am using php file_get_contents and dom documment for login to 3rd party site (gmail). But when i run my code, it's displaying cookie problem text page: Turn cookies on or off, that's mean i am not enable cookie. But already i turn it on using this code $http_response_header, check below code then you will understand.
I don't want to use curl. Curl support cookies but file_get_contents not supporting cookies. I want to remote login using only php, so i don't used curl. I don't understand exactly where is my mistake and why displaying cookie problem after adding cookie function on code. After unsuccessful, i submitting this post on here for getting solution from genius.
Here Is My gmail.php Code:
<?php
class LoginGmail
{
public $request_cookies = '';
public $response_cookies = '';
public $content = '';
public function set_cookies_json($cookies)
{
$cookies_json = json_decode($cookies, true);
$cookies_array = array();
foreach ($cookies_json as $key => $value)
{
$cookies_array[] = $key .'='.$value;
}
$this->request_cookies = 'Cookie: ' . join('; ', $cookies_array) . "\r\n";
}
public function set_cookies_string($cookies)
{
$this->request_cookies = 'Cookie: ' . $cookies . "\r\n";
}
private function get_cookies($http_response_header)
{
$cookies_array = array();
foreach($http_response_header as $s)
{
if (preg_match('|^Set-Cookie:\s*([^=]+)=([^;]+);(.+)$|', $s, $parts))
{
$cookies_array[] = $parts[1] . '=' . $parts[2];
}
}
$this->response_cookies = 'Cookie: ' . join('; ', $cookies_array) . "\r\n";
}
public function get($url)
{
$opts = array(
'http' => array(
'method' => 'GET',
'header' => "Accept-language: en\r\n" .
"User-Agent: com.google.android.apps.maps/984200142 (Linux; U; Android 5.0; en_US; GT-I9500; Build/LRX21M; Cronet/66.0.3359.100)\r\n" .
$this->request_cookies
)
);
$context = stream_context_create($opts);
$this->content = file_get_contents($url, false, $context);
$this->get_cookies($http_response_header);
return $this->content;
}
public function post($url, $inputs)
{
$post_content = array();
foreach ($inputs as $key => $value)
{
$post_content[] = $key .'='.$value;
}
$opts = array(
'http' => array(
'method' => 'POST',
'header' => "Content-type: application/x-www-form-urlencoded\r\n" .
"User-Agent: com.google.android.apps.maps/984200142 (Linux; U; Android 5.0; en_US; GT-I9500; Build/LRX21M; Cronet/66.0.3359.100)\r\n" .
$this->request_cookies,
'content' => join('&', $post_content),
)
);
$context = stream_context_create($opts);
$this->content = file_get_contents($url, false, $context);
$this->get_cookies($http_response_header);
return $this->content;
}
public function postPass($url, $inputs)
{
$post_content = array();
foreach ($inputs as $key => $value)
{
$post_content[] = $key .'='.$value;
}
$opts = array(
'http' => array(
'method' => 'POST',
'header' => "Content-type: application/x-www-form-urlencoded\r\n" .
"User-Agent: com.google.android.apps.maps/984200142 (Linux; U; Android 5.0; en_US; GT-I9500; Build/LRX21M; Cronet/66.0.3359.100)\r\n" .
$this->request_cookies,
'content' => join('&', $post_content),
)
);
$context = stream_context_create($opts);
$this->content = file_get_contents($url, false, $context);
$this->get_cookies($http_response_header);
return $this->content;
}
}
?>
And Here Is My login.php Code:
<?php
require_once('gmail.php');
$connect = new LoginGmail();
$url = 'https://store.google.com/account';
$first = $connect->get($url);
$domd = #DOMDocument::loadHTML($first);
$xp = new DOMXPath($domd);
foreach($domd->getElementsByTagName("form")->item(0)->getElementsByTagName("input") as $get)
{
$inputs[$get->getAttribute("name")]=$get->getAttribute("value");
}
$inputs["Email"]="HERE_IS_GMAIL_ID";
$url = $xp->query("//form")->item(0)->getAttribute("action");
$second = $connect->post($url, $inputs);
$domd = #DOMDocument::loadHTML($second);
$xp = new DOMXPath($domd);
foreach($domd->getElementsByTagName("form")->item(0)->getElementsByTagName("input") as $get)
{
$inputs[$get->getAttribute("name")]=$get->getAttribute("value");
}
$inputs["Passwd"]="HERE_IS_GMAIL_PASSWORD";
$url = $xp->query("//form")->item(0)->getAttribute("action");
echo $connect->postPass($url, $inputs);
?>
NB: I hide my personal Email & Password on code. Sorry for not good english. Thanks
I believe that the way you are performing requests on google is not the correct form. Your code is not wrong, the way you try to authenticate yourself. Check out this documentation, maybe it will help.
I am using OpenTok API for the audio/video chat and now trying to record the audio/video chat conference with the same.
I have downloaded the API from this link
But the result always comes empty (check the result by var_dump($res); ) and response comes empty array.
Following is my function:
protected function request($method, $url, $opts = null) {
$url = $this->endpoint . $url;
if(($method == 'PUT' || $method == 'POST') && $opts) {
$bodyFormat = $opts->contentType();
$dataString = $opts->dataString();
}
$authString = "X-TB-PARTNER-AUTH: $this->apiKey:$this->apiSecret";
if (function_exists("file_get_contents")) {
$http = array(
'method' => $method
);
$headers = array($authString);
if($method == "POST" || $method == "PUT") {
$headers[1] = "Content-type: " . $bodyFormat;
$headers[2] = "Content-Length: " . strlen($dataString);
$http["content"] = $dataString;
}
$http["header"] = $headers;
$context_source = array ('http' =>$http);
$context = stream_context_create($context_source);
$res = file_get_contents( $url ,true, $context);
var_dump($res);
$statusarr = explode(" ", $http_response_header[0]);
$status = $statusarr[1];
$headers = array();
foreach($http_response_header as $header) {
if(strpos($header, "HTTP/") !== 0) {
$split = strpos($header, ":");
$key = strtolower(substr($header, 0, $split));
$val = trim(substr($header, $split + 1));
$headers[$key] = $val;
}
}
$response = (object)array(
"status" => $status
);
if(strtolower($headers["content-type"]) == "application/json") {
$response->body = json_decode($res);
} else {
$response->body = $res;
}
} else{
throw new OpenTokArchivingRequestException("Your PHP installion doesn't support file_get_contents. Please enable it so that you can make API calls.");
}
return $response;
}
When I print $context_source then I get the following array:
Array
(
[http] => Array
(
[method] => POST
[content] => {"action":"start","sessionId":"1_MX40NTM2MDgxMn4xMjcuMC4wLjF-MTQ0MzcxMDQ0NzU2NH4wWkZ3bkN1NDJaYlNFMFZFZmYwcGZ1a2F-UH4","name":"filename"}
[header] => Array
(
[0] => X-TB-PARTNER-AUTH: 45360812:cbbd8b29be4c75d5aab1945a71bf0cb3443e3939
[1] => Content-type: application/json
[2] => Content-Length: 136
)
)
)
Everything seems good. Can anyone tell me what I am doing wrong.
I use the file_get_contents() from server M to get the response from server X. The result was success but it take too long.
$url = "http://10.20.30.40";
$opts = array('http' =>
array(
'method' => 'GET',
'header' => 'Connection: close\r\n'
)
);
$context = stream_context_create($opts);
$result = file_get_contents($url, false, $context);
$result = json_decode($result);
$response = parse_http_response_header($http_response_header);
print_r($result);
print_r($response);
/////// below is just function to parse the response ///////
function parse_http_response_header(array $headers)
{
$responses = array();
$buffer = NULL;
foreach ($headers as $header)
{
if ('HTTP/' === substr($header, 0, 5))
{
// add buffer on top of all responses
if ($buffer) array_unshift($responses, $buffer);
$buffer = array();
list($version, $code, $phrase) = explode(' ', $header, 3) + array('', FALSE, '');
$buffer['status'] = array(
'line' => $header,
'version' => $version,
'code' => (int) $code,
'phrase' => $phrase
);
$fields = &$buffer['fields'];
$fields = array();
continue;
}
list($name, $value) = explode(': ', $header, 2) + array('', '');
// header-names are case insensitive
$name = strtoupper($name);
// values of multiple fields with the same name are normalized into
// a comma separated list (HTTP/1.0+1.1)
if (isset($fields[$name]))
{
$value = $fields[$name].','.$value;
}
$fields[$name] = $value;
}
unset($fields); // remove reference
array_unshift($responses, $buffer);
return $responses;
}
Is there any suggestion or function option to get the response (the content and the response code) faster?
(NOTE: I am not allowed to install cURL, so please gimme other option)
I'm trying to develop a full PHP web browser that can handle cookies. I've created the following class:
<?php
class Browser
{
private $cookies = '';
private $response_cookies = '';
private $content = '';
/**
* Cookie manager
* #Description : To set or get cookies as Array or String
*/
public function set_cookies_json($cookies)
{
$cookies_json = json_decode($cookies, true);
$cookies_array = array();
foreach ($cookies_json as $key => $value)
{
$cookies_array[] = $key .'='.$value;
}
$this->cookies = 'Cookie: ' . $cookies_array.join('; ') . "\r\n";
}
public function set_cookies_string($cookies)
{
$this->cookies = 'Cookie: ' . $cookies . "\r\n";
}
private function get_cookies()
{
global $http_response_header;
$cookies_array = array();
foreach($http_response_header as $s)
{
if (preg_match('|^Set-Cookie:\s*([^=]+)=([^;]+);(.+)$|', $s, $parts))
{
$cookies_array[] = $parts[1] . '=' . $parts[2];
}
}
$this->cookies = 'Cookie: ' . $cookies_array.join('; ') . "\r\n";
}
/**
* GET and POST request
* Send a GET or a POST request to a remote URL
*/
public function get($url)
{
$opts = array(
'http' => array(
'method' => 'GET',
'header' => "Accept-language: en\r\n" .
$this->cookies
)
);
$context = stream_context_create($opts);
$this->content = file_get_contents($url, false, $context);
$this->get_cookies();
return $this->content;
}
public function post($url, $post_data)
{
$post_content = array();
foreach ($post_data as $key => $value)
{
$post_content[] = $key .'='.$value;
}
$opts = array(
'http' => array(
'method' => 'GET',
'header' => "Content-type: application/x-www-form-urlencoded\r\n" .
$this->cookies,
'content' => $post_content.join('&'),
)
);
$context = stream_context_create($opts);
$this->content = file_get_contents($url, false, $context);
$this->get_cookies();
return $this->content;
}
}
Basically, it can send a GET request and 'should' retrieve the cookies.
I've made a very simple test script:
<?php
require('browser.class.php');
$browser = new Browser();
$browser->get('http://google.com');
print_r($browser->response_cookies);
But it fails on line 32 as $http_response_header looks to be null. Isn't it supposed to contain the header of my response ? I've read that page but it looks to work well for this guy : get cookie with file_get_contents in PHP
I know I could use cUrl to handle this but I'd really like to use a rough PHP code.
Did I make something wrong ?
Thanks for your precious help.
Edit:
Solution is:
<?php
class Browser
{
public $request_cookies = '';
public $response_cookies = '';
public $content = '';
/**
* Cookie manager
* #Description : To set or get cookies as Array or String
*/
public function set_cookies_json($cookies)
{
$cookies_json = json_decode($cookies, true);
$cookies_array = array();
foreach ($cookies_json as $key => $value)
{
$cookies_array[] = $key .'='.$value;
}
$this->request_cookies = 'Cookie: ' . join('; ', $cookies_array) . "\r\n";
}
public function set_cookies_string($cookies)
{
$this->request_cookies = 'Cookie: ' . $cookies . "\r\n";
}
private function get_cookies($http_response_header)
{
$cookies_array = array();
foreach($http_response_header as $s)
{
if (preg_match('|^Set-Cookie:\s*([^=]+)=([^;]+);(.+)$|', $s, $parts))
{
$cookies_array[] = $parts[1] . '=' . $parts[2];
}
}
$this->response_cookies = 'Cookie: ' . join('; ', $cookies_array) . "\r\n";
}
/**
* GET and POST request
* Send a GET or a POST request to a remote URL
*/
public function get($url)
{
$opts = array(
'http' => array(
'method' => 'GET',
'header' => "Accept-language: en\r\n" .
$this->request_cookies
)
);
$context = stream_context_create($opts);
$this->content = file_get_contents($url, false, $context);
$this->get_cookies($http_response_header);
return $this->content;
}
public function post($url, $post_data)
{
$post_content = array();
foreach ($post_data as $key => $value)
{
$post_content[] = $key .'='.$value;
}
$opts = array(
'http' => array(
'method' => 'GET',
'header' => "Content-type: application/x-www-form-urlencoded\r\n" .
$this->request_cookies,
'content' => join('&', $post_content),
)
);
$context = stream_context_create($opts);
$this->content = file_get_contents($url, false, $context);
$this->get_cookies($http_response_header);
return $this->content;
}
}
According to php.net:
$http_response_header will be created in the local scope.
Because of this $http_response_header is available only in the scope of get().
You can pass it like $this->get_cookies($http_response_header); or create a property to store it.