1

I am trying to execute CURL via cron job, hosting is GoDaddy's shared linux hosting. When I execute the script from browser URL then it works, it is not working via cron job.

Following error:

curl: (35) error:14077410:SSL routines:SSL23_GET_SERVER_HELLO:sslv3 alert handshake failure

Please notice: GET request is working fine, it is only issue with POST request, I tried different solutions, but question is that why it is working for GET and not only POST. When I execute script via browser URL it works but it is only issue via cron job.

Following is my code for CURL

$postData = array(
    "email" => "login",
    "password" => "password",
);

$headers = array(
   "Content-Type: application/json"
);

$ch=curl_init();
curl_setopt($ch,CURLOPT_URL,'https://reqres.in/api/login');
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($postData));
curl_setopt($ch,CURLOPT_CONNECTTIMEOUT,2);
curl_setopt($ch,CURLOPT_RETURNTRANSFER,1);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_VERBOSE, 1);
curl_setopt ($ch, CURLOPT_HTTPPROXYTUNNEL, TRUE);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, TRUE);
curl_setopt ($ch, CURLOPT_SSL_VERIFYPEER, FALSE);

$result = curl_exec ($ch);

if (empty($result)){
    $return = "<hr><br>\n";
    $return .= 'Errors: ' . curl_errno($ch) . ' ' . curl_error($ch) . '<br><br>';
    $return .= "<hr><br>\n";
}
else{
    $return = $result;
}
print $result;
curl_close ($ch);

Please suggest.

Developer
  • 324
  • 3
  • 13
  • Did you really just posted your personal password? – Mike Doe Feb 12 '19 at 11:30
  • @emix it is not real request, it is fake data for ajax api testing - https://reqres.in/ – Developer Feb 12 '19 at 11:32
  • Possible duplicate of [Php curl set ssl version](https://stackoverflow.com/questions/35131590/php-curl-set-ssl-version). It doesn't matter… – Mike Doe Feb 12 '19 at 11:33
  • @emix tested above, version is upgraded and main things is, GET is working only POST is not working – Developer Feb 12 '19 at 11:35
  • Using POST to that url and with those credentials works fine when correctly supplying options for dealing with SSL... – Professor Abronsius Feb 12 '19 at 11:37
  • Well I can successfuly execute your code, without any problems. You can try it at [phpFiddle](http://phpfiddle.org/), so I guess this is server related. – Mike Doe Feb 12 '19 at 11:46
  • How are you calling the script through the cron job? Is cron calling PHP to execute the script or is it calling the URL and being executed through the webserver? – Matt Garrod Feb 12 '19 at 11:46
  • please dont use a `browser` as a witness (test) of anything : nowadays they do what they think you want, and try every other way thinkable before failing. – YvesLeBorg Feb 12 '19 at 11:47

1 Answers1

1

When dealing with curl requests to SSL enabled endpoints you'll have much greater success if the curl request includes options specifically geared towards ssl connections. The simple function below uses cacert.pem and other ssl specific options

function curl( $url=NULL, $options=NULL ){
    $cacert='c:/wwwroot/cacert.pem';
    $vbh = fopen('php://temp', 'w+');

    $res=array(
        'response'  =>  NULL,
        'info'      =>  array( 'http_code' => 400 ),
        'headers'   =>  NULL,
        'errors'    =>  NULL
    );
    if( is_null( $url ) ) return (object)$res;

    session_write_close();

    /* Initialise curl request object */
    $curl=curl_init();
    if( parse_url( $url,PHP_URL_SCHEME )=='https' ){
        curl_setopt( $curl, CURLOPT_SSL_VERIFYPEER, true );
        curl_setopt( $curl, CURLOPT_SSL_VERIFYHOST, 2 );
        curl_setopt( $curl, CURLOPT_CAINFO, $cacert );
    }

    /* Define standard options */
    curl_setopt( $curl, CURLOPT_URL,trim( $url ) );
    curl_setopt( $curl, CURLOPT_AUTOREFERER, true );
    curl_setopt( $curl, CURLOPT_FOLLOWLOCATION, true );
    curl_setopt( $curl, CURLOPT_FAILONERROR, true );
    curl_setopt( $curl, CURLOPT_HEADER, false );
    curl_setopt( $curl, CURLINFO_HEADER_OUT, false );
    curl_setopt( $curl, CURLOPT_RETURNTRANSFER, true );
    curl_setopt( $curl, CURLOPT_BINARYTRANSFER, true );
    curl_setopt( $curl, CURLOPT_CONNECTTIMEOUT, 20 );
    curl_setopt( $curl, CURLOPT_TIMEOUT, 60 );
    curl_setopt( $curl, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36' );
    curl_setopt( $curl, CURLOPT_MAXREDIRS, 10 );
    curl_setopt( $curl, CURLOPT_ENCODING, '' );

    curl_setopt( $curl, CURLOPT_VERBOSE, true );
    curl_setopt( $curl, CURLOPT_NOPROGRESS, true );
    curl_setopt( $curl, CURLOPT_STDERR, $vbh );

    /* Assign runtime parameters as options */
    if( isset( $options ) && is_array( $options ) ){
        foreach( $options as $param => $value ) curl_setopt( $curl, $param, $value );
    }

    /* Execute the request and store responses */
    $res=(object)array(
        'response'  =>  curl_exec( $curl ),
        'info'      =>  (object)curl_getinfo( $curl ),
        'errors'    =>  curl_error( $curl )
    );
    rewind( $vbh );
    $res->verbose=stream_get_contents( $vbh );
    fclose( $vbh );
    curl_close( $curl );
    return $res;
}

/* configure the request */
$data = array(
    'email'     => 'peter@klaven',
    'password'  => 'cityslicka'
);

/* the target endpoint */
$url='https://reqres.in/api/login';

$config=array(
    CURLOPT_POST        =>  true,
    CURLOPT_POSTFIELDS  =>  json_encode( $data ),
    CURLOPT_HTTPHEADER  =>  array('Content-Type: application/json')
);
/* make the request */
$results=curl( $url, $config );
if( $results->info->http_code==200 ){
    printf('<pre>%s</pre>',print_r( $results, true ));
}

Some info from the response object - notably verbose details ~ the full response includes the token ~ {"token":"QpwL5tke4Pnpja7X"} which suggests success!

* TCP_NODELAY set
* Connected to reqres.in (104.27.134.11) port 443 (#0)
* ALPN, offering http/1.1
* successfully set certificate verify locations:
  CAfile: c:/wwwroot/cacert.pem
  CApath: none
* SSL connection using TLSv1.2 / ECDHE-ECDSA-CHACHA20-POLY1305
* ALPN, server accepted to use http/1.1
* Server certificate:
*  subject: OU=Domain Control Validated; OU=PositiveSSL Multi-Domain; CN=sni96286.cloudflaressl.com
*  start date: Jan 23 00:00:00 2019 GMT
*  expire date: Aug  1 23:59:59 2019 GMT
*  subjectAltName: host "reqres.in" matched cert's "reqres.in"
*  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.
Professor Abronsius
  • 33,063
  • 5
  • 32
  • 46