CURL POST with file - not working on Windows - php

I have a php script that sends a file via cURL, to a remote location.
This works great on a Mac.
On Windows w/ MAMP (I am stuck with this at present), no request reaches the remote server.
If I take away the CURLOPT_POSTFIELDS parameter, the request is sent, however without my data (obviously). This tells me that cURL is loaded ok, and is able to send a request.
What I can't work out, is what is causing this to do nothing when CURLOPT_POSTFIELDS is included (as per the code below) - no errors (that I am aware of).
Here is the code that I am running:
function getCurlValue($filename, $contentType, $postname)
{
if (function_exists('curl_file_create')) {
return curl_file_create($filename, $contentType, $postname);
}
// Use the old style if using an older version of PHP
$value = "#{$this->filename};filename=" . $postname;
if ($contentType) {
$value .= ';type=' . $contentType;
}
return $value;
}
$filename = 'c:\path\to\file\test.txt';
$cfile = getCurlValue($filename,'text/plain','test.txt');
$data = array('updateFile' => $cfile);
$ch = curl_init();
$options = array(CURLOPT_URL => 'http://url/to/my/service',
CURLOPT_RETURNTRANSFER => true,
CURLINFO_HEADER_OUT => true, //Request header
CURLOPT_HEADER => true, //Return header
CURLOPT_FAILONERROR => true,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_SSL_VERIFYPEER => false,
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => $data
);
curl_setopt_array($ch, $options);
$result = curl_exec($ch);
$header_info = curl_getinfo($ch,CURLINFO_HEADER_OUT);
$header_size = curl_getinfo($ch, CURLINFO_HEADER_SIZE);
$header = substr($result, 0, $header_size);
$body = substr($result, $header_size);
curl_close($ch);
I have checked for cURL errors, of which there are none thrown.
Any thoughts would be most appreciated.
Thanks,
Nathan

This issue appears to have resolved itself. All is now working, with no changes on my part.
Must have been something at the server end....

Related

How to fix cURL error "SSL connection timeout" only on the first time the script is called?

I'm facing a strange problem using cURL with PHP on a Windows server. I have a very basic code:
private function curlConnection($method, $url, $timeout, $charset, array $data = null)
{
if (strtoupper($method) === 'POST') {
$postFields = ($data ? http_build_query($data, '', '&') : "");
$contentLength = "Content-length: " . strlen($postFields);
$methodOptions = array(
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => $postFields,
);
} else {
$contentLength = null;
$methodOptions = array(
CURLOPT_HTTPGET => true
);
}
$options = array(
CURLOPT_HTTPHEADER => array(
"Content-Type: application/x-www-form-urlencoded; charset=" . $charset,
$contentLength,
'lib-description: php:' . PagSeguroLibrary::getVersion(),
'language-engine-description: php:' . PagSeguroLibrary::getPHPVersion()
),
CURLOPT_URL => $url,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HEADER => true,
CURLOPT_SSL_VERIFYPEER => false,
CURLOPT_CONNECTTIMEOUT => $timeout
);
$options = ($options + $methodOptions);
$curl = curl_init();
curl_setopt_array($curl, $options);
$resp = curl_exec($curl);
$info = curl_getinfo($curl);
$error = curl_errno($curl);
$errorMessage = curl_error($curl);
curl_close($curl);
$this->setStatus((int) $info['http_code']);
$this->setResponse((String) $resp);
if ($error) {
throw new Exception("CURL can't connect: $errorMessage");
} else {
return true;
}
}
The problem is that the first time this script is called, the response is always this: string(22) "SSL connection timeout".
Subsequent calls to the script output the desired result, but, if I wait a couple of minutes before calling the script again, the timeout issue happens again.
So, steps to reproduce the "error":
Call the script -> SSL connection timeout
Call the script again -> works fine
Call the script one more time -> works fine
Call the script n more times -> works fine
Wait 10 minutes
Call the script -> SSL connection timeout
Call the script n more times again -> works fine
If I call any other script the response is immediate, even after a period of inactivity, so this behaviour only happen when cURL is involved.
PHP - 5.2.17
CURL - libcurl/7.16.0 OpenSSL/0.9.8q zlib/1.2.3
The server is running Windows 2012 with IIS 8, latest upgrades, running PHP on FastCGI.
Does anyone have any idea on how I can solve this?
Thanks.
Try using the ca-bundle.crt bundle available here https://raw.githubusercontent.com/bagder/ca-bundle/master/ca-bundle.crt
Upload file
curl_setopt($ch, CURLOPT_CAINFO, "path");
Reference: http://richardwarrender.com/2007/05/the-secret-to-curl-in-php-on-windows
Hope this helps.
Try to check the state of the 'Server' Windows service, if stopped - could be the reason. Have no idea how it is related, but it helped for me with the same issue.

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;
}

Box-api V2 upload file curl php returns false

I´m trying to upload a file from PHP via Box-API v2 and I only get a boolean false response.
I think this is caused by CURL, not Box-API but I was fighting the last five hours, and I can´t find the solution. Any idea??
The implicated code is that:
note: the file exists and is accessible from code and the token is ok (other calls to API work fine)
const CONTENT_ENDPOINT = 'https://api.box.com/2.0/';
$file = "unexeceles.xlsx";
private $defaultOptions = array(
CURLOPT_SSL_VERIFYPEER => false,
CURLOPT_VERBOSE => true,
CURLOPT_HEADER => true,
CURLINFO_HEADER_OUT => false,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
);
public function putFile($file) {
$options = $this->defaultOptions;
$options[CURLOPT_HTTPHEADER] = array ("Authorization: Bearer ".$this->token);
$options[CURLOPT_POST] = true;
$postfields = array();
$postfields["filename"] = '#'.$file;
$postfields["parent_id"] = 0;
$options[CURLOPT_POSTFIELDS] = $postfields;
$handle = curl_init(BoxConfig::CONTENT_ENDPOINT."files/content");
curl_setopt_array($handle, $options);
$response = curl_exec($handle);
curl_close($handle);
if (is_string($response)) {
$response = $this->parse($response);
}
return $response;
}
Finally I've found the solution.
The problem was the relative path to the file, the file exists and it´s accessible form code, but CURL seems to need the entire path to the file.
Very helpful the function curl_errno($handle)
if(curl_errno($handle)) {
echo 'Curl error: ' . curl_error($handle);
}

PHP stalls on loop of curl function with bad url

I have a database of a few thousand URL's that I am checking for links on pages (end up looking for specific links) and so I am throwing the below function through a loop and every once and awhile one of the URL's is bad and then the entire program just stalls and stops running and starts building up memory used. I thought adding the CURLOPT_TIMEOUT would fix this but it didn't. Any ideas?
$options = array(
CURLOPT_RETURNTRANSFER => true, // return web page
CURLOPT_HEADER => false, // don't return headers
CURLOPT_FOLLOWLOCATION => true, // follow redirects
CURLOPT_ENCODING => "", // handle all encodings
CURLOPT_USERAGENT => "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.13) Gecko/20080311 Firefox/2.0.0.13'", // who am i
CURLOPT_AUTOREFERER => true, // set referer on redirect
CURLOPT_TIMEOUT => 2, // timeout on response
CURLOPT_MAXREDIRS => 10, // stop after 10 redirects
CURLOPT_POST => 0, // i am sending post data
CURLOPT_POSTFIELDS => $curl_data, // this are my post vars
CURLOPT_SSL_VERIFYHOST => 0, // don't verify ssl
CURLOPT_SSL_VERIFYPEER => false, //
CURLOPT_VERBOSE => 1 //
);
$ch = curl_init($url);
curl_setopt_array($ch,$options);
$content = curl_exec($ch);
$err = curl_errno($ch);
$errmsg = curl_error($ch) ;
$header = curl_getinfo($ch);
curl_close($ch);
// $header['errno'] = $err;
// $header['errmsg'] = $errmsg;
$header['content'] = $content;
#Extract the raw URl from the current one
$scheme = parse_url($url, PHP_URL_SCHEME); //Ex: http
$host = parse_url($url, PHP_URL_HOST); //Ex: www.google.com
$raw_url = $scheme . '://' . $host; //Ex: http://www.google.com
#Replace the relative link by an absolute one
$relative = array();
$absolute = array();
#String to search
$relative[0] = '/src="\//';
$relative[1] = '/href="\//';
#String to remplace by
$absolute[0] = 'src="' . $raw_url . '/';
$absolute[1] = 'href="' . $raw_url . '/';
$source = preg_replace($relative, $absolute, $content); //Ex: src="/image/google.png" to src="http://www.google.com/image/google.png"
return $source;
curl_exec will return false if it cannot find the URL.
The HTTP status code will be zero.
Check the results of curl_exec and check the HTTP status
code too.
$content = curl_exec($ch);
$httpStatus = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ( $content === false) {
if ($httpStatus == 0) {
$content = "link was not found";
}
}
....
The way you have it currently, the line of code
header['content'] = $content;
will get the value of false. This is not what you
want.
I am using curl_exec and my code does not stall if
it cannot find the url. The code keeps running.
You may end up with nothing in your browser though
and a message in the Firebug Console like "500 Internal Server Error".
Maybe that's what you mean by stall.
So basically you don't know and just guess that the curl request is stalling.
For this answer I can only guess as well then. You might need to set one of the following curl option as well: CURLOPT_CONNECTTIMEOUT
If the connect already stalls, the other timeout setting might not be taken into account. I'm not entirely sure, but please see Why would CURL time out in 1000ms when I have set up timeout upto 3000ms?.

PHP client side Digest authentication with qop=auth-int

Does anyone know any PHP library for connecting remote servers that use Digest authentication method with qop=auth-int?
Or, if not, now should I build the A2 for the result? It says in RFC 2617 that I need to use an entity body, but what is this? I am just sending a GET request, it does not have any body at all.
Thanks in advance.
I was looking for the answer to your question too, for requests other than GET.
Perheps you could use something like:
$entityBody = file_get_contents('php://input');
I have not tested if it works, but looking at the answer to this question it would make sence to me that it should.
Note that this stream can only be read once [1] so if you need it again elsewhere you should reuse the $entityBody variable.
From my answer of a similar question:
I implemented the client-side Digest Authentication in PHP with cURL recently. Here's the full code:
<?php
error_reporting(E_ALL);
ini_set( 'display_errors','1');
$url = "https://api.example.com/ws.asmx/do";
$username = "username";
$password = "pwd";
$post_data = array(
'fieldname1' => 'value1',
'fieldname2' => 'value2'
);
$options = array(
CURLOPT_URL => $url,
CURLOPT_HEADER => true,
CURLOPT_VERBOSE => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_SSL_VERIFYPEER => false, // for https
CURLOPT_USERPWD => $username . ":" . $password,
CURLOPT_HTTPAUTH => CURLAUTH_DIGEST,
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => http_build_query($post_data)
);
$ch = curl_init();
curl_setopt_array( $ch, $options );
try {
$raw_response = curl_exec( $ch );
// validate CURL status
if(curl_errno($ch))
throw new Exception(curl_error($ch), 500);
// validate HTTP status code (user/password credential issues)
$status_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($status_code != 200)
throw new Exception("Response with Status Code [" . $status_code . "].", 500);
} catch(Exception $ex) {
if ($ch != null) curl_close($ch);
throw new Exception($ex);
}
if ($ch != null) curl_close($ch);
echo "raw response: " . $raw_response;
?>
If you're doing a GET request, you shouldn't need auth-int. If your service requires it, you can assume an empty entity-body (thus you can just do md5("") for this part of the A2 hash).

Categories