php curl does not seem to send the intended POST variables - php

I am trying to retrieve a post from a simple POST to api.openweathermap.org.
The URL post should like like: api.openweathermap.org/data/2.5/weather?id=4215110&units=metric&appid=my_api_key
The php code I'm using is:
#!/usr/bin/php
<?php
define('WEATHER_CITY_CODE', 4215110) ; // Peachtree City, GA
define('WEATHER_UNITS', 'imperial') ; // or 'metric' or 'standard'
define('WEATHER_API_KEY', 'my_api_key') ; // Not the real key
$request = "api.openweathermap.org/data/2.5/weather" ;
$requestVariables = Array('id' => WEATHER_CITY_CODE
, 'units' => WEATHER_UNITS
, 'appid' => WEATHER_API_KEY
) ;
printf("Request query parameters should be: %s?%s\n", $request, http_build_query($requestVariables)) ;
$streamVerboseHandle = fopen('php://temp', 'w+') ;
$ch = curl_init($request) ;
curl_setopt($ch, CURLOPT_STDERR, $streamVerboseHandle) ;
curl_setopt($ch, CURLOPT_VERBOSE, true) ;
curl_setopt($ch, CURLOPT_POST, 1) ;
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query( $requestVariables )) ;
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true) ;
$weather_response = curl_exec($ch) ;
//if ($weather_response === FALSE)
{
printf("cUrl error (#%d): %s<br>\n",
curl_errno($ch),
htmlspecialchars(curl_error($ch)))
;
rewind($streamVerboseHandle);
$verboseLog = stream_get_contents($streamVerboseHandle);
echo "cUrl verbose information:\n",
htmlspecialchars($verboseLog), "\n";
}
curl_close($ch) ;
try {
$response_arr = json_decode($weather_response, true, 3, JSON_THROW_ON_ERROR) ;
print_r($response_arr) ;
}
catch (Exception $e) {
$response_file = "weather-response.json" ;
file_put_contents($response_file, $weather_response) ;
$lov->writeLogLine("Exception from send-sms.php: " . $e->getMessage()) ;
$lov->writeLogLine("Response text is: '" . $weather_response . "'"
, false, null, false, false) ;
$lov->writeLogLine("Response saved in " . $response_file) ;
throw new Exception("Failure in send-sms.php") ;
}
?>
When I run this code (even if the WEATHER_API_KEY value is set correctly, I get the following response:
Array
(
[cod] => 401
[message] => Invalid API key. Please see http://openweathermap.org/faq#error401 for more info.
)
Even if the correct API key is used. (Note: I can copy the value in the "Request query paraemters..." line and paste them into a browser to get the correct results without error.
So I added the curl debug code you see above, and it seems to indicate that curl is not sending my parameters. (see the POST /data/2.5/weather HTTP/1.1 below.) I'm not sure why. While I'm not accustomed to using (nor needing) that curl debug information, it seems to me that I should see /data/2.5/weather?id=4... in its place.
I saw this article, but I don't think it applies here...
Can you help?
Process output is:
> ./getweathermap.php
Request query parameters should be: api.openweathermap.org/data/2.5/weather?id=4215110&units=imperial&appid=my_api_key
cUrl error (#0): <br>
cUrl verbose information:
* Trying 192.241.245.161:80...
* TCP_NODELAY set
* Connected to api.openweathermap.org (192.241.245.161) port 80 (#0)
> POST /data/2.5/weather HTTP/1.1
Host: api.openweathermap.org
Accept: */*
Content-Length: 42
Content-Type: application/x-www-form-urlencoded
* upload completely sent off: 42 out of 42 bytes
* Mark bundle as not supporting multiuse
< HTTP/1.1 401 Unauthorized
< Server: openresty
< Date: Sun, 27 Feb 2022 01:45:01 GMT
< Content-Type: application/json; charset=utf-8
< Content-Length: 107
< Connection: keep-alive
< X-Cache-Key: /data/2.5/weather?
< Access-Control-Allow-Origin: *
< Access-Control-Allow-Credentials: true
< Access-Control-Allow-Methods: GET, POST
<
* Connection #0 to host api.openweathermap.org left intact
Array
(
[cod] => 401
[message] => Invalid API key. Please see http://openweathermap.org/faq#error401 for more info.
)

Related

CURLOPT_STDERR is always executed?

Well, I'm having troubles making requests to the Discord API, I'm not understanding how curl is working.
This is my code:
function make_request($mixed, $token, $get_json = true) {
$url = is_string($mixed) ? $mixed : getApiUrl($mixed);
// TODO: Check for valid url!
$log_file = __DIR__.'/../logs/request.txt';
if(!is_readable($log_file)) printError("File '$log_file' is not readable!");
if(!is_writable($log_file)) printError("File '$log_file' is not writable!");
$ch = curl_init();
$f = fopen($log_file, 'w+');
if($f === false) printError("There was an error opening '$log_file'!");
ftruncate($f, 0);
curl_setopt_array($ch, array(
CURLOPT_URL => $url,
CURLOPT_HTTPHEADER => array('Authorization: Bot ' . $token),
CURLOPT_RETURNTRANSFER => 1,
CURLOPT_FOLLOWLOCATION => 1,
CURLOPT_VERBOSE => 1,
CURLOPT_SSL_VERIFYPEER => 0,
CURLOPT_STDERR => $f,
));
$response = curl_exec($ch);
fclose($f);
curl_close($ch);
$contents = file_get_contents($log_file);
if($contents != '')
{
// Censor bot key!
$contents = preg_replace("/^Authorization: Bot.+?$/", "Authorization: Bot xxx", $contents);
printError($contents);
}
if($get_json) {
$pretty = isset($_GET["pretty"]);
if($pretty) {
$json = json_decode($response);
return json_encode($json, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
}
return $response;
}
return json_decode($response, true);
}
And this is my output:
[OuterException] System.Exception: * Hostname in DNS cache was stale, zapped
* Trying 162.159.135.233...
* TCP_NODELAY set
* Connected to discordapp.com (162.159.135.233) port 443 (#0)
* ALPN, offering http/1.1
* Cipher selection: ALL:!EXPORT:!EXPORT40:!EXPORT56:!aNULL:!LOW:!RC4:#STRENGTH
* successfully set certificate verify locations:
* CAfile: /etc/ssl/certs/ca-certificates.crt
CApath: /etc/ssl/certs
* SSL connection using TLSv1.2 / ECDHE-ECDSA-AES128-GCM-SHA256
* ALPN, server accepted to use http/1.1
* Server certificate:
* subject: CN=ssl711320.cloudflaressl.com
* start date: Feb 13 00:00:00 2020 GMT
* expire date: Aug 21 23:59:59 2020 GMT
* subjectAltName: host "discordapp.com" matched cert's "discordapp.com"
* issuer: C=GB; ST=Greater Manchester; L=Salford; O=COMODO CA Limited; CN=COMODO ECC Domain Validation Secure Server CA 2
* SSL certificate verify ok.
> GET /api/guilds/479096180601782274 HTTP/1.1
Host: discordapp.com
Accept: */*
Authorization: Bot ...
< HTTP/1.1 200 OK
< Date: Thu, 20 Feb 2020 17:49:15 GMT
< Content-Type: application/json
< Transfer-Encoding: chunked
< Connection: keep-alive
< Set-Cookie: __cfduid=ddfc25d7448507e06474f24ff3e8352381582220955; expires=Sat, 21-Mar-20 17:49:15 GMT; path=/; domain=.discordapp.com; HttpOnly; SameSite=Lax
< Strict-Transport-Security: max-age=31536000; includeSubDomains
< Via: 1.1 google
< Alt-Svc: clear
< CF-Cache-Status: DYNAMIC
< Set-Cookie: __cfruid=66721d8d16cd42e4884dc62afe94705cbf1e21df-1582220955; path=/; domain=.discordapp.com; HttpOnly; Secure; SameSite=None
< Expect-CT: max-age=604800, report-uri="https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct"
< Server: cloudflare
< CF-RAY: 568250ea9fe2a861-CDG
<
* Curl_http_done: called premature == 0
* Connection #0 to host discordapp.com left intact
en DiscordIdCrawler.Lib.Core.ApiWorker.CheckForErrors(Object response) en E:\PHP\discord-flooder-bot\client\DiscordIdCrawler\DiscordIdCrawler.Lib\Core\ApiWorker.cs:línea 152
en DiscordIdCrawler.Lib.Core.ApiWorker.GetServerName(Int64 serverId) en E:\PHP\discord-flooder-bot\client\DiscordIdCrawler\DiscordIdCrawler.Lib\Core\ApiWorker.cs:línea 312
en DiscordIdCrawler.Lib.Core.DriverWorker.GoToServer(IWebDriver web, Int32 serverNum, Boolean storeOnDB) en E:\PHP\discord-flooder-bot\client\DiscordIdCrawler\DiscordIdCrawler.Lib\Core\DriverWorker.cs:línea 141
My question is that maybe I'm printing an error when curl is just showing a verbosed log, but I'm not sure if the CURLOPT_STDERR is used to print errors or the entire log.
On the docs: https://www.php.net/manual/en/function.curl-setopt.php
An alternative location to output errors to instead of STDERR.
Maybe is because CURLOPT_VERBOSE is enabled.
TRUE to output verbose information. Writes output to STDERR, or the file specified using CURLOPT_STDERR.
On that case, I need to know when an error happens. Any tip here?
You're on the right track. If you want the diagnostic output, you have to arrange to capture it before you make your request. The usual way to do this is by storing it in RAM, checking for curl error, and handling appropriately.
That code looks like:
$ch = curl_init();
curl_setopt_array($ch, [
// ... other options here
CURLOPT_RETURNTRANSFER => 1,
CURLOPT_VERBOSE => 1,
CURLOPT_STDERR => ($log = fopen('php://temp', 'w')),
]);
$response = curl_exec($ch);
if (false === $response) {
$errno = curl_error($ch);
$errmsg = curl_strerror($errno);
$logtext = stream_get_contents($log, -1, 0);
// ... log the info above, take action, etc.
} else {
// ... $response is your HTTP response
}
curl_close($ch);

PHP curl - obtain response headers when error exists?

I am calling a REST service using php curl. If an error occurs (for example because I posted invalid data) the REST server returns error code 400 and provides informative application error details in the response header custom field.
However, when error 400 occurs the header is not provided in the result from curl_exec() at it returns FALSE even though setopt as been provided. Headers are seen if code returned is 2xx.
curl_setopt($curl,CURLOPT_HEADER, 1);
Is there any way to get the response headers on errors >= 400?
In the example below, I'm using https://httpstat.us/400 to simulate a HTTP 400 response code.
<?php
// create curl resource
$ch = curl_init();
// set url that responds with HTTP 400 status
curl_setopt($ch, CURLOPT_URL, "https://httpstat.us/400");
//return the transfer as a string
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
//enable headers
curl_setopt($ch, CURLOPT_HEADER, 1);
//get only headers
curl_setopt($ch, CURLOPT_NOBODY, 1);
// $output contains the output string
$output = curl_exec($ch);
// close curl resource to free up system resources
curl_close($ch);
$headers = [];
$output = rtrim($output);
$data = explode("\n",$output);
$headers['status'] = $data[0];
array_shift($data);
foreach($data as $part){
//some headers will contain ":" character (Location for example), and the part after ":" will be lost, Thanks to #Emanuele
$middle = explode(":",$part,2);
//Supress warning message if $middle[1] does not exist, Thanks to #crayons
if ( !isset($middle[1]) ) { $middle[1] = null; }
$headers[trim($middle[0])] = trim($middle[1]);
}
// Print all headers as array
print_r($headers);
This returns
Array
(
[status] => HTTP/1.1 400 Bad Request
[Cache-Control] => private
[Content-Length] => 15
[Content-Type] => text/plain; charset=utf-8
[Server] => Microsoft-IIS/10.0
[X-AspNetMvc-Version] => 5.1
[Access-Control-Allow-Origin] => *
[X-AspNet-Version] => 4.0.30319
[X-Powered-By] => ASP.NET
[Set-Cookie] => ARRAffinity=93fdbab9d364704de8ef77182b4d13811344b7dd1ec45d3a9682bbd6fa154ead;Path=/;HttpOnly;Domain=httpstat.us
[Date] => Wed, 13 Nov 2019 23:31:51 GMT
)
That array with all response headers matches up with what I get when I use curl from my terminal:
curl -v https://httpstat.us/400
returns
< HTTP/1.1 400 Bad Request
< Cache-Control: private
< Content-Length: 15
< Content-Type: text/plain; charset=utf-8
< Server: Microsoft-IIS/10.0
< X-AspNetMvc-Version: 5.1
< Access-Control-Allow-Origin: *
< X-AspNet-Version: 4.0.30319
< X-Powered-By: ASP.NET
< Set-Cookie: ARRAffinity=93fdbab9d364704de8ef77182b4d13811344b7dd1ec45d3a9682bbd6fa154ead;Path=/;HttpOnly;Domain=httpstat.us
< Date: Wed, 13 Nov 2019 23:33:19 GMT
Here's another option using the CURLOPT_HEADERFUNCTION option with a callback function:
<?php
// this holds the response headers from the curl call
$responseHeaders = array();
// this function processes the response headers from the curl call
function curlResponseHeaderCallback($ch, $headerLine) {
global $responseHeaders;
// trim all the whitespace on this line
$trimmed = trim($headerLine);
// only proceed if the string is not empty
if(!empty($trimmed)) {
// headers follow Key: Value format
$split = explode(':', $trimmed);
// only proceed if the value of the header is not empty
if(!empty($split[1])) {
// $split[0] is the Key of the response header
// $split[1] is the Value of the response header, which can also have whitespace
$responseHeaders[$split[0]] = trim($split[1]);
}
}
// who knows why, but you have to return this.
return strlen($headerLine);
}
// get cURL resource
$ch = curl_init();
// set url
curl_setopt($ch, CURLOPT_URL, "https://httpstat.us/400");
curl_setopt($ch, CURLOPT_HEADERFUNCTION, "curlResponseHeaderCallback");
// send the request
curl_exec($ch);
// close the handle
curl_close($ch);
print_r($responseHeaders);
returns
Array
(
[Cache-Control] => private
[Content-Length] => 15
[Content-Type] => text/plain; charset=utf-8
[Server] => Microsoft-IIS/10.0
[X-AspNetMvc-Version] => 5.1
[Access-Control-Allow-Origin] => *
[X-AspNet-Version] => 4.0.30319
[X-Powered-By] => ASP.NET
[Set-Cookie] => ARRAffinity=93fdbab9d364704de8ef77182b4d13811344b7dd1ec45d3a9682bbd6fa154ead;Path=/;HttpOnly;Domain=httpstat.us
[Date] => Wed, 13 Nov 2019 23
)

Is there any way to urlencode/escape while Curl is Following Location?

I am doing Api integration of SEB open banking while Curl follow location it is not encoding the url as normal browser do.
$url = 'https://api-sandbox.sebgroup.com/mga/sps/oauth/oauth20/authorize?' . 'client_id=XXXXXXXXXXXX&response_type=code&scope=psd2_accounts%20psd2_payments&redirect_uri=https://testcallback.com/test';
curl_setopt_array($curl, array(
CURLOPT_HEADER => true,
CURLOPT_URL => $url,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_VERBOSE => true,
CURLOPT_HTTPHEADER => array(
"accept: text/html",
),
));
$response = curl_exec($curl);
$err = curl_error($curl);
Here is the curl verbose from logs
< HTTP/1.1 302 Found
< content-language: en-US
< date: Thu, 25 Jul 2019 21:15:49 GMT
< location: https://api-sandbox.sebgroup.com/mga/sps/authsvc?PolicyId=urn:ibm:security:authentication:asf:username_login&client_id=XXXXXXXXXXXX&response_type=code&scope=psd2_accounts psd2_payments&redirect_uri=https://testcallback.com/test&state=undefined
< p3p: CP="NON CUR OTPi OUR NOR UNI"
< x-frame-options: SAMEORIGIN
< Strict-Transport-Security: max-age=15552000; includeSubDomains
< Transfer-Encoding: chunked
<
* Ignoring the response-body
* Connection #0 to host api-sandbox.sebgroup.com left intact
* Issue another request to this URL: 'https://api-sandbox.sebgroup.com/mga/sps/authsvc?PolicyId=urn:ibm:security:authentication:asf:username_login&client_id=XXXXXXXXXXXX&response_type=code&scope=psd2_accounts psd2_payments&redirect_uri=https://testcallback.com/test&state=undefined'
* Expire in 30000 ms for 8 (transfer 0x5572d97d6ad0)
* Found bundle for host api-sandbox.sebgroup.com: 0x5572d97744f0 [can pipeline]
* Could pipeline, but not asked to!
* Re-using existing connection! (#0) with host api-sandbox.sebgroup.com
* Connected to api-sandbox.sebgroup.com (129.178.54.70) port 443 (#0)
* Expire in 0 ms for 6 (transfer 0x5572d97d6ad0)
> GET /mga/sps/authsvc?PolicyId=urn:ibm:security:authentication:asf:username_login&client_id=XXXXXXXXXXXX&response_type=code&scope=**psd2_accounts psd2_payments**&redirect_uri=https://testcallback.com/test&state=undefined HTTP/1.1
Host: api-sandbox.sebgroup.com
Cookie: AMWEBJCT!%2Fmga!JSESSIONID=00009xuAYPuCp9GW43jcmC-CafK:f218d509-b31a-4e85-82f3-4026c87d2a41; TS01edf909=0107224bed281ed0132bcd33d1abd742777866cf59ada955adfb4e11b262eec4177bcfece6d5008e34b56a7ab37f409ab22798b97dd781fcdbe67b1d85c3acb10a1c21f2ca; TS01ef558a=0107224bed32bbf99c1c620e086bb40f0577a7d1fcada955adfb4e11b262eec4177bcfece69dd83308b2725dc487ace1c823d15bd6e2e5d0d2968f3683570ed32b96ea5da2; C0WNET=03758b02-5d3a-4321-a19f-1c022988e2f4
accept: text/html
< HTTP/1.1 400 Bad Request
< Cache-Control: no-cache
< Connection: close
< Content-Type: text/html; charset=utf-8
< Pragma: no-cache
< Content-Length: 246
<
* Closing connection 0
This Follow location contains a space betweeb (psd2_accounts psd2_payments). Which is not being converted into %20
/mga/sps/authsvc?PolicyId=urn:ibm:security:authentication:asf:username_login&client_id=XXXXXXXXXXXX&response_type=code&scope=**psd2_accounts psd2_payments**&redirect_uri=https://testcallback.com/test&state=undefined
How can I encode the follow location parameters as well so that the above url automatically become
/mga/sps/authsvc?PolicyId=urn:ibm:security:authentication:asf:username_login&client_id=XXXXXXXXXXXX&response_type=code&scope=**psd2_accounts%20psd2_payments**&redirect_uri=https://testcallback.com/test&state=undefined
URLs are per definition URL encoded already. Otherwise it is not a URL. HTTP redirects should by definition redirect to URLs and they MUST be URL encoded already. Not doing so is a violation of the HTTP spec (Source). The api-sandbox.sebgroup.com website is not returning a real URL in their redirect. Maybe you should consider contacting them and notifying them of this problem since cURL is a pretty common way to access an API.
If they can't get this fixed in a timely manner, I wouldn't recommend just url-encoding the Location header because they might fix it in the future and then you will be double-encoding the URL, which is also obviously wrong. You need to urlencode it only if it is invalid.
Therefore, what I suggest is to remove the CURLOPT_FOLLOWLOCATION option to make sure that it doesn't follow the redirects and add a CURLOPT_HEADERFUNCTION, which will be called by curl for each header received, urlencode the Location header, only if present and invalid, and then execute curl in a loop until there is no Location header. Since spaces in URLs violate the spec, PHP's filter_var() function properly considers it to be invalid.
$url = 'https://example.com';
$ch = curl_init();
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
// this function is called by curl for each header received
curl_setopt($ch, CURLOPT_HEADERFUNCTION,
function($curl, $header) use (&$headers) {
$len = strlen($header);
$header = explode(':', $header, 2);
if (count($header) < 2) {
// ignore invalid headers
return $len;
}
$name = strtolower(trim($header[0]));
if ($name == 'location' && !filter_var(trim($header[1]), FILTER_VALIDATE_URL)) {
$header[1] = urlencode(trim($header[1]));
}
$headers[$name][] = trim($header[1]);
return $len;
}
);
// Maximum number of redirects
$max_iterations = 10;
$iterations = 0;
do {
$url = $headers['location'][0] ?? $url;
$headers = [];
curl_setopt($ch, CURLOPT_URL, $url);
$data = curl_exec($ch);
print_r($headers);
} while (isset($headers['location']) && ++$iterations < $max_iterations);

ipinfo.io via PHP's file_get_contents() and cURL fail

I try to get a GeoLocation data from http://ipinfo.io,
Here is my way :
$resp = file_get_contents('http://ipinfo.io/json');
$data = json_decode($resp);
It return an error :
Warning: file_get_contents(http://ipinfo.io/json): failed to open stream: Permission denied in ....
But then I access the link (http://ipinfo.io/json) manually in the URL box of my browser, it shows a correct json.
I also try it with cURL :
$curlSession = curl_init();
curl_setopt($curlSession, CURLOPT_URL, "ipinfo.io/json");
curl_setopt($curlSession, CURLOPT_BINARYTRANSFER, true);
curl_setopt($curlSession, CURLOPT_RETURNTRANSFER, true);
$resp = curl_exec($curlSession);
if (FALSE === $resp) {
echo curl_errno($curlSession);
}
curl_close($curlSession);
It echo a number of 7, and i look up in the internet, error 7 means Couldn't connect to the server.
Any idea why ?
Thank you
I run http://ipinfo.io, and we don't block access to any IPs (we do rate limit requests from IPs, but that'd result in a HTTP status code, not a blocked connection). This sounds like a config issue with your server to me. Some hosts lock down file_get_contents so it can't open URLs, or might have blocked http://ipinfo.io. Are few ways to track this down:
1) Can you open another URL with file_get_contents? Eg. what happens when you file_get_contents('http://google.com'). If you get a permission denied error there then you should speak to your hosting provider
2) Does command line curl work for ipinfo.io? The -i -v flags should give you more information about what's going on here. Here's what a successful request looks like:
$ curl -iv ipinfo.io
* Rebuilt URL to: ipinfo.io/
* Trying 54.68.119.255...
* Connected to ipinfo.io (54.68.119.255) port 80 (#0)
> GET / HTTP/1.1
> Host: ipinfo.io
> User-Agent: curl/7.49.1
> Accept: */*
>
< HTTP/1.1 200 OK
HTTP/1.1 200 OK
< Access-Control-Allow-Origin: *
Access-Control-Allow-Origin: *
< Content-Type: application/json; charset=utf-8
Content-Type: application/json; charset=utf-8
< Date: Sun, 15 Jan 2017 18:38:44 GMT
Date: Sun, 15 Jan 2017 18:38:44 GMT
< Server: nginx/1.8.1
Server: nginx/1.8.1
< Set-Cookie: first_referrer=; Path=/
Set-Cookie: first_referrer=; Path=/
< X-Content-Type-Options: nosniff
X-Content-Type-Options: nosniff
< Content-Length: 252
Content-Length: 252
< Connection: keep-alive
Connection: keep-alive
<
{
"ip": "24.6.61.239",
"hostname": "c-24-6-61-239.hsd1.ca.comcast.net",
"city": "Mountain View",
"region": "California",
"country": "US",
"loc": "37.3845,-122.0881",
"org": "AS7922 Comcast Cable Communications, LLC",
"postal": "94040"
* Connection #0 to host ipinfo.io left intact
}
Quite often a server will be configured to prevent requests where there is no User-Agent string present in the request headers so you can add a context argument to file_get_contents that supplies a User-Agent and any other headers you need.
$args=array(
'http'=>array(
'method' => "GET",
'header' => implode( "\n", array(
'User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:44.0) Gecko/20100101 Firefox/44.0',
'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
'Host: ipinfo.io'
)
)
)
);
/* create the context */
$context=stream_context_create( $args );
$resp = file_get_contents( 'http://ipinfo.io/json', FILE_TEXT, $context );
$data = json_decode( $resp );
echo '<pre>',print_r( $data,true ),'</pre>';
i see 2 plausible explanations here.
1: you use a shitty DNS server. try GoogleDNS (8.8.8.8) instead.
curl_setopt($curlSession,CURLOPT_DNS_LOCAL_IP4,'8.8.8.8');
if that fixes it, contact your DNS provider and sort it out with them
2: you're IP banned. try to just create a TCP socket to their ip, see if you can do that.
<?php
$sock=socket_create(AF_INET,SOCK_STREAM,SOL_TCP);
var_dump($sock,socket_connect($sock,gethostbyname('ipinfo.io'),80),socket_close($sock));
if you can't do that, you're probably IP banned

php curl not getting same response as fiddler

This is my PHP code :
$source = $_POST['source'];
$destination = $_POST['destination'];
$class = $_POST['class'];
$day = $_POST['day'];
$month = $_POST['month'];
$data = array(
'lccp_src_stncode_dis' => $source,
'lccp_dstn_stncode' => $destination,
'lccp_classopt' => $class,
'lccp_day' => $day,
'lccp_month' => $month
);
# Create a connection
$url = 'data as per raw req ';
$ch = curl_init($url);
echo $ch." <br>";
# Form data string
$postString = http_build_query($data);
echo $postString;
$header = array (
'Host' => 'data as per raw req '
'Connection'=> 'keep-alive',
'Content-Length'=> '180',
'Cache-Control'=> 'max-age=0',
'Accept'=> 'text/html',
'Origin'=> 'data as per raw req ',
'User-Agent' => '',
'Content-Type' => 'application/x-www-form-urlencoded',
'Referer': 'data as per raw req '
'Accept-Encoding'=> '',
'Accept-Language' => 'en-US,en;q=0.8'
);
# Setting options
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $postString);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
//# Get the response
curl_setopt($ch, CURLOPT_POSTFIELDS,
$response = curl_exec($ch);
curl_close($ch);
#print response
echo "
$response
";
receiving form data from:
<html>
<form method="post" action="poster.php">
<table>
<tr><td>source:</td><td><input type="text" name="source"></td></tr>
<tr><td>destination:</td><td><input type="text" name="destination"></td></tr>
<tr><td>day:</td><td><input type="text" name="day"></td></tr>
<tr><td>month:</td><td><input type="text" name="month"></td></tr>
<tr><td>class:</td><td><input type="text" name="class"></td></tr>
<tr><td><input type="submit" name="submit" value="Submit"></td>
<td><input type="reset" name="reset" value="Reset"></td></tr>
</table>
</form>
</html>
this is the raw request
POST http://www.indianrail.gov.in/cgi_bin/inet_srcdest_cgi_date.cgi HTTP/1.1
Host: www.indianrail.gov.in
Connection: keep-alive
Content-Length: 91
Cache-Control: max-age=0
Accept: text/html
Origin: **<---modified since I can't post more than 2 links
User-Agent:
Content-Type: application/x-www-form-urlencoded
Referer: ** <---modified since I can't post more than 2 links
Accept-Encoding:
Accept-Language: en-US,en;q=0.8
lccp_src_stncode_dis=ndls&lccp_dstn_stncode=HYB&lccp_classopt=SL&lccp_day=26&lccp_month=6
Fiddler is giving the appropriate response from the cgi, whereas the php script just shows the html container, I've been stuck for over an hour ! Please help !
EDIT: output from verbose :
* Adding handle: conn: 0x2cab910
* Adding handle: send: 0
* Adding handle: recv: 0
* Curl_addHandleToPipeline: length: 1
* - Conn 3 (0x2cab910) send_pipe: 1, recv_pipe: 0
* About to connect() to www.indianrail.gov.in port 80 (#3)
* Trying 203.176.113.78...
* Connected to www.indianrail.gov.in (203.176.113.78) port 80 (#3)
> POST /cgi_bin/inet_srcdest_cgi_date.cgi HTTP/1.1
Host: www.indianrail.gov.in
Accept: */*
http://www.indianrail.gov.in
http://www.indianrail.gov.in/know_Station_Code.html
Content-Length: 89
Content-Type: application/x-www-form-urlencoded
* upload completely sent off: 89 out of 89 bytes
< HTTP/1.1 200 OK
< Date: Fri, 27 Jun 2014 05:38:17 GMT
* Server Apache/2.2.15 (Red Hat) is not blacklisted
< Server: Apache/2.2.15 (Red Hat)
< Connection: close
< Transfer-Encoding: chunked
< Content-Type: text/html; charset=UTF-8
<
* Closing connection 3
^Off topic: Why did it just let me post links this time, it should have been recognized as links ?
Also, I would compare sessions in fiddler, but fiddler shows the request to my own app on local host, not from my app to the indian railways site.
screenshot :
NEVERMIND, NOT ENOUGH REP
EDIT:
I'll be happy if someone can show me how to make this request with http_request2 as well I've posted the exact raw request that gives me the required output with fiddler in the comments, so no, I'm not missing any authentication and cookie headers and the like
header is not to be entered as an associative array, this is wrong :
$header = array (
'Host' => 'data as per raw req '
'Connection'=> 'keep-alive',
'Content-Length'=> '180',
'Cache-Control'=> 'max-age=0',
'Accept'=> 'text/html',
'Origin'=> 'data as per raw req ',
'User-Agent' => '',
'Content-Type' => 'application/x-www-form-urlencoded',
'Referer': 'data as per raw req '
'Accept-Encoding'=> '',
'Accept-Language' => 'en-US,en;q=0.8'
);
correct method :
$header = array (
'Host:*data as per raw req* '
'Connection:keep-alive',
'Content-Length:180',
'Cache-Control:max-age=0',
'Accept:text/html',
'Origin:*data as per raw req* ',
'User-Agent:',
'Content-Type:application/x-www-form-urlencoded',
'Referer:*data as per raw req* '
'Accept-Encoding:',
'Accept-Language:en-US,en;q=0.8'
);
even the data entered in the associative array I've used is formatted to a url encoded post string, apparently everything pretty much has to be entered as it is in a raw http request. cURL doesn't really do any formatting.

Categories