Related
Can anyone show me how to do a PHP cURL with an HTTP POST?
I want to send data like this:
username=user1, password=passuser1, gender=1
To www.example.com
I expect the cURL to return a response like result=OK. Are there any examples?
<?php
//
// A very simple PHP example that sends a HTTP POST to a remote site
//
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL,"http://www.example.com/tester.phtml");
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS,
"postvar1=value1&postvar2=value2&postvar3=value3");
// In real life you should use something like:
// curl_setopt($ch, CURLOPT_POSTFIELDS,
// http_build_query(array('postvar1' => 'value1')));
// Receive server response ...
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$server_output = curl_exec($ch);
curl_close($ch);
// Further processing ...
if ($server_output == "OK") { ... } else { ... }
?>
Procedural
// set post fields
$post = [
'username' => 'user1',
'password' => 'passuser1',
'gender' => 1,
];
$ch = curl_init('http://www.example.com');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $post);
// execute!
$response = curl_exec($ch);
// close the connection, release resources used
curl_close($ch);
// do anything you want with your response
var_dump($response);
Object oriented
<?php
// mutatis mutandis
namespace MyApp\Http;
class CurlPost
{
private $url;
private $options;
/**
* #param string $url Request URL
* #param array $options cURL options
*/
public function __construct($url, array $options = [])
{
$this->url = $url;
$this->options = $options;
}
/**
* Get the response
* #return string
* #throws \RuntimeException On cURL error
*/
public function __invoke(array $post)
{
$ch = \curl_init($this->url);
foreach ($this->options as $key => $val) {
\curl_setopt($ch, $key, $val);
}
\curl_setopt($ch, \CURLOPT_RETURNTRANSFER, true);
\curl_setopt($ch, \CURLOPT_POSTFIELDS, $post);
$response = \curl_exec($ch);
$error = \curl_error($ch);
$errno = \curl_errno($ch);
if (\is_resource($ch)) {
\curl_close($ch);
}
if (0 !== $errno) {
throw new \RuntimeException($error, $errno);
}
return $response;
}
}
Usage
// create curl object
$curl = new \MyApp\Http\CurlPost('http://www.example.com');
try {
// execute the request
echo $curl([
'username' => 'user1',
'password' => 'passuser1',
'gender' => 1,
]);
} catch (\RuntimeException $ex) {
// catch errors
die(sprintf('Http error %s with code %d', $ex->getMessage(), $ex->getCode()));
}
Side note here: it would be best to create some kind of interface called AdapterInterface for example with getResponse() method and let the class above implement it. Then you can always swap this implementation with another adapter of your like, without any side effects to your application.
Using HTTPS / encrypting traffic
Usually there's a problem with cURL in PHP under the Windows operating system. While trying to connect to a https protected endpoint, you will get an error telling you that certificate verify failed.
What most people do here is to tell the cURL library to simply ignore certificate errors and continue (curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);). As this will make your code work, you introduce huge security hole and enable malicious users to perform various attacks on your app like Man In The Middle attack or such.
Never, ever do that. Instead, you simply need to modify your php.ini and tell PHP where your CA Certificate file is to let it verify certificates correctly:
; modify the absolute path to the cacert.pem file
curl.cainfo=c:\php\cacert.pem
The latest cacert.pem can be downloaded from the Internet or extracted from your favorite browser. When changing any php.ini related settings remember to restart your webserver.
A live example of using php curl_exec to do an HTTP post:
Put this in a file called foobar.php:
<?php
$ch = curl_init();
$skipper = "luxury assault recreational vehicle";
$fields = array( 'penguins'=>$skipper, 'bestpony'=>'rainbowdash');
$postvars = '';
foreach($fields as $key=>$value) {
$postvars .= $key . "=" . $value . "&";
}
$url = "http://www.google.com";
curl_setopt($ch,CURLOPT_URL,$url);
curl_setopt($ch,CURLOPT_POST, 1); //0 for a get request
curl_setopt($ch,CURLOPT_POSTFIELDS,$postvars);
curl_setopt($ch,CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch,CURLOPT_CONNECTTIMEOUT ,3);
curl_setopt($ch,CURLOPT_TIMEOUT, 20);
$response = curl_exec($ch);
print "curl response is:" . $response;
curl_close ($ch);
?>
Then run it with the command php foobar.php, it dumps this kind of output to screen:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Title</title>
<meta http-equiv="Pragma" content="no-cache">
<meta http-equiv="Expires" content="0">
<body>
A mountain of content...
</body>
</html>
So you did a PHP POST to www.google.com and sent it some data.
Had the server been programmed to read in the post variables, it could decide to do something different based upon that.
It's can be easily reached with:
<?php
$post = [
'username' => 'user1',
'password' => 'passuser1',
'gender' => 1,
];
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'http://www.domain.com');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($post));
$response = curl_exec($ch);
var_export($response);
1.Step by step
Initialize the cURL session:
$url = "www.domain.com";
$ch = curl_init($url);
If your request has headers like bearer token or defining JSON contents you have to set HTTPHEADER options to cURL:
$token = "generated token code";
curl_setopt(
$ch,
CURLOPT_HTTPHEADER,
array(
'Content-Type: application/json', // for define content type that is json
'bearer: '.$token, // send token in header request
'Content-length: 100' // content length for example 100 characters (can add by strlen($fields))
)
);
If you want to include the header in the output set CURLOPT_HEADER to true:
curl_setopt($ch, CURLOPT_HEADER, false);
Set RETURNTRANSFER option to true to return the transfer as a string instead of outputting it directly:
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
To check the existence of a common name in the SSL peer certificate can be set to 0(to not check the names), 1(not supported in cURL 7.28.1), 2(default value and for production mode):
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
For posting fields as an array by cURL:
$fields = array(
"username" => "user1",
"password" => "passuser1",
"gender" => 1
);
curl_setopt($ch, CURLOPT_POSTFIELDS, $fields);
Execute cURL and return the string. depending on your resource this returns output like result=OK:
$result = curl_exec($ch);
Close cURL resource, and free up system resources:
curl_close($ch);
2.Use as a class
The whole call_cURL class that can be extended:
class class_name_for_call_cURL {
protected function getUrl() {
return "www.domain.com";
}
public function call_cURL() {
$token = "generated token code";
$fields = array(
"username" => "user1",
"password" => "passuser1",
"gender" => 1
);
$url = $this->getUrl();
$output = $this->_execute($fields, $url, $token);
// if you want to get json data
// $output = json_decode($output);
if ($output == "OK") {
return true;
} else {
return false;
}
}
private function _execute($postData, $url, $token) {
// for sending data as json type
$fields = json_encode($postData);
$ch = curl_init($url);
curl_setopt(
$ch,
CURLOPT_HTTPHEADER,
array(
'Content-Type: application/json', // if the content type is json
'bearer: '.$token // if you need token in header
)
);
curl_setopt($ch, CURLOPT_HEADER, false);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
curl_setopt($ch, CURLOPT_POSTFIELDS, $fields);
$result = curl_exec($ch);
curl_close($ch);
return $result;
}
}
Using the class and call cURL:
$class = new class_name_for_call_cURL();
var_dump($class->call_cURL()); // output is true/false
3.One function
A function for using anywhere that needed:
function get_cURL() {
$url = "www.domain.com";
$token = "generated token code";
$postData = array(
"username" => "user1",
"password" => "passuser1",
"gender" => 1
);
// for sending data as json type
$fields = json_encode($postData);
$ch = curl_init($url);
curl_setopt(
$ch,
CURLOPT_HTTPHEADER,
array(
'Content-Type: application/json', // if the content type is json
'bearer: '.$token // if you need token in header
)
);
curl_setopt($ch, CURLOPT_HEADER, false);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
curl_setopt($ch, CURLOPT_POSTFIELDS, $fields);
$result = curl_exec($ch);
curl_close($ch);
return $result;
}
This function is usable just by:
var_dump(get_cURL());
Curl Post + Error Handling + Set Headers [thanks to #mantas-d]:
function curlPost($url, $data=NULL, $headers = NULL) {
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
if(!empty($data)){
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
}
if (!empty($headers)) {
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
}
$response = curl_exec($ch);
if (curl_error($ch)) {
trigger_error('Curl Error:' . curl_error($ch));
}
curl_close($ch);
return $response;
}
curlPost('google.com', [
'username' => 'admin',
'password' => '12345',
]);
curlPost('google.com', [
'username' => 'admin',
'password' => '12345',
]);
function curlPost($url, $data) {
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
$response = curl_exec($ch);
$error = curl_error($ch);
curl_close($ch);
if ($error !== '') {
throw new \Exception($error);
}
return $response;
}
I'm surprised nobody suggested file_get_contents:
$url = "http://www.example.com";
$parameters = array('username' => 'user1', 'password' => 'passuser1', 'gender' => '1');
$options = array('http' => array(
'header' => 'Content-Type: application/x-www-form-urlencoded\r\n',
'method' => 'POST',
'content' => http_build_query($parameters)
));
$context = stream_context_create($options);
$result = file_get_contents($url, false, $context);
it's simple, it works; I use it in an environment where I control the code at both ends.
even better, use json_decode (and set up your code to return JSON)
$result = json_decode(file_get_contents($url, false, $context), TRUE);
this approach invokes curl behind the scenes, but you don't jump through as many hoops.
Answer refined from this original answer elsewhere on Stack Overflow:
PHP sending variables to file_get_contents()
If the form is using redirects, authentication, cookies, SSL (https), or anything else other than a totally open script expecting POST variables, you are going to start gnashing your teeth really quick. Take a look at Snoopy, which does exactly what you have in mind while removing the need to set up a lot of the overhead.
A simpler answer IF you are passing information to your own website is to use a SESSION variable. Begin php page with:
session_start();
If at some point there is information you want to generate in PHP and pass to the next page in the session, instead of using a POST variable, assign it to a SESSION variable. Example:
$_SESSION['message']='www.'.$_GET['school'].'.edu was not found. Please try again.'
Then on the next page you simply reference this SESSION variable. NOTE: after you use it, be sure you destroy it, so it doesn't persist after it is used:
if (isset($_SESSION['message'])) {echo $_SESSION['message']; unset($_SESSION['message']);}
Here are some boilerplate code for PHP + curl
http://www.webbotsspidersscreenscrapers.com/DSP_download.php
include in these library will simplify development
<?php
# Initialization
include("LIB_http.php");
include("LIB_parse.php");
$product_array=array();
$product_count=0;
# Download the target (store) web page
$target = "http://www.tellmewhenitchanges.com/buyair";
$web_page = http_get($target, "");
...
?>
Examples of sending form and raw data:
$curlHandler = curl_init();
curl_setopt_array($curlHandler, [
CURLOPT_URL => 'https://postman-echo.com/post',
CURLOPT_RETURNTRANSFER => true,
/**
* Specify POST method
*/
CURLOPT_POST => true,
/**
* Specify array of form fields
*/
CURLOPT_POSTFIELDS => [
'foo' => 'bar',
'baz' => 'biz',
],
]);
$response = curl_exec($curlHandler);
curl_close($curlHandler);
echo($response);
If you try to login on site with cookies.
This code:
if ($server_output == "OK") { ... } else { ... }
It May not works if you try to login, because many sites return status 200, but the post is not successful.
The easy way to check if the login post is successful is to check if it setting cookies again. If in output have a Set-Cookies string, this means the posts are not successful and it starts a new session.
Also, the post can be successful, but the status can redirect instead of 200.
To be sure the post is successful try this:
Follow location after the post, so it will go to the page where the post does redirect to:
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
And than check if new cookies existing in the request:
if (!preg_match('/^Set-Cookie:\s*([^;]*)/mi', $server_output))
{echo 'post successful'; }
else { echo 'not successful'; }
Easiest is to send data as application/json. This will take an array as input and properly encodes it into a json string:
$data = array(
'field1' => 'field1value',
'field2' => 'field2value',
)
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
'Content-Type:application/json',
));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$resultStr = curl_exec($ch);
return json_decode($resultStr, true);
Here is the WSDL ...
I am using the SOAP Client in PHP with documentation HERE ...
Soap Call
$wsdl = 'https://api.krollcorp.com/EBusinessTest/Kroll.Dealer.EBusiness.svc/Docs?singleWsdl';
try {
$client = new SoapClient($wsdl, array('soap_version' => SOAP_1_2, 'trace' => 1));
// $result = $client->SubmitPurchaseOrder();
$result = $client->__soapCall("SubmitPurchaseOrder", array());
} catch (SoapFault $e) {
printf("\nERROR: %s\n", $e->getMessage());
}
$requestHeaders = $client->__getLastRequestHeaders();
$request = $client->__getLastRequest();
$responseHeaders = $client->__getLastResponseHeaders();
printf("\nRequest Headers -----\n");
print_r($requestHeaders);
printf("\nRequest -----\n");
print_r($request);
printf("\nResponse Headers -----\n");
print_r($responseHeaders);
printf("\nEND\n");
Output
ERROR: The SOAP action specified on the message, '', does not match the HTTP SOAP Action, 'http://tempuri.org/IEBusinessService/SubmitPurchaseOrder'.
Request Headers -----
POST /EBusinessTest/Kroll.Dealer.EBusiness.svc HTTP/1.1
Host: api.krollcorp.com
Connection: Keep-Alive
User-Agent: PHP-SOAP/5.6.19
Content-Type: application/soap+xml; charset=utf-8; action="http://tempuri.org/IEBusinessService/SubmitPurchaseOrder"
Content-Length: 200
Request -----
<?xml version="1.0" encoding="UTF-8"?>
<env:Envelope xmlns:env="http://www.w3.org/2003/05/soap-envelope" xmlns:ns1="http://tempuri.org/"><env:Body><ns1:SubmitPurchaseOrder/></env:Body></env:Envelope>
Response Headers -----
HTTP/1.1 500 Internal Server Error
Content-Length: 637
Content-Type: application/soap+xml; charset=utf-8
Server: Microsoft-IIS/7.5
X-Powered-By: ASP.NET
Date: Wed, 06 Sep 2017 12:42:57 GMT
END
Attempts
I am a beginner at using SOAP APIs.
I believe this is failing because SOAP 1.2 uses WsHttpBinding instead of BasicHttpBinding.
I am not sure how to set WS Addressing with the SOAP Client in PHP ...
Below code is working for me.You can enable Ws-A Addressing and call soap method-
$client = new SoapClient("http://www.xyz.Services?Wsdl", array('soap_version' => SOAP_1_2,'trace' => 1,'exceptions'=> false
));
$wsa_namespace = 'http://www.w3.org/2005/08/addressing';
$ACTION_ISSUE = 'http://www.xyx/getPassword';// Url With method name
$NS_ADDR = 'http://www.w3.org/2005/08/addressing';
$action = new SoapHeader($NS_ADDR, 'Action', $ACTION_ISSUE, true);
$to = new SoapHeader($NS_ADDR, 'To', 'http://www.xyx.svc/Basic', false);
$headerbody = array('Action' => $action,'To' => $to);
$client->__setSoapHeaders($headerbody);
//$fcs = $client->__getFunctions();
//pre($client->__getLastRequest());
//pre($fcs);
$parameters=array('UserId'=>'12345678','MemberId'=>'123456','Password' => '123456','PassKey' => 'abcdef1234');
;
$result = $client->__soapCall('getPassword', array($parameters));//getPassword method name
print_r(htmlspecialchars($client->__getLastRequest()));// view your request in xml code
print_r($client->__getLastRequest());die; //Get Last Request
print_r($result);die; //print response
Dude, I totally feel your pain. I was able to get this to work but I don't think this is the right way, but it is pointing in the right direction. A caveat though, you have to know what namespace soap_client is going to assign to the addressing. Best way is just to capture the request XML and look for what namespace is attache to the addressing, and then pass it in. Below is my code with a default of 'ns2' for namespace, but you can't count on it for your example. Good Luck!
private function generateWSAddressingHeader($action,$to,$replyto,$message_id=false,$ns='ns2')
{
$message_id = ($message_id) ? $message_id : $this->_uniqueId(true);
$soap_header = <<<SOAP
<{$ns}:Action env:mustUnderstand="0">{$action}</{$ns}:Action>
<{$ns}:MessageID>urn:uuid:{$message_id}</{$ns}:MessageID>
<{$ns}:ReplyTo>
<{$ns}:Address>{$replyto}</{$ns}:Address>
</{$ns}:ReplyTo>
<{$ns}:To env:mustUnderstand="0">$to</{$ns}:To>
SOAP;
return new \SoapHeader('http://www.w3.org/2005/08/addressing','Addressing',new \SoapVar($soap_header, XSD_ANYXML),true);
}
My solution is
Send request using SoapUi
Copy request http log from SoapUi screen ( Bottom of SoapUi program)
Past that code into the PHP project as fallows
$soap_request = '{copy that part from SoapUi http log}';
$WSDL = "**wsdl adres**";
$ch = curl_init();
curl_setopt($ch, CURLOPT_HEADER, false);
curl_setopt($ch, CURLOPT_URL, $WSDL);
curl_setopt($ch, CURLOPT_FAILONERROR, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, Array(
'Content-Type: application/soap+xml; charset=utf-8',
'SOAPAction: "run"',
'Accept: text/xml',
'Cache-Control: no-cache',
'Pragma: no-cache',
'Content-length: '. strlen($soap_request),
'User-Agent: PHP-SOAP/7.0.10',
));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 30);
curl_setopt($ch, CURLOPT_TIMEOUT, 30);
curl_setopt($ch, CURLOPT_POSTFIELDS, $soap_request);
$response = curl_exec($ch);
if (empty($response)) {
throw new SoapFault('CURL error: '.curl_error($ch), curl_errno($ch));
}
curl_close($ch);
Can anyone show me how to do a PHP cURL with an HTTP POST?
I want to send data like this:
username=user1, password=passuser1, gender=1
To www.example.com
I expect the cURL to return a response like result=OK. Are there any examples?
<?php
//
// A very simple PHP example that sends a HTTP POST to a remote site
//
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL,"http://www.example.com/tester.phtml");
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS,
"postvar1=value1&postvar2=value2&postvar3=value3");
// In real life you should use something like:
// curl_setopt($ch, CURLOPT_POSTFIELDS,
// http_build_query(array('postvar1' => 'value1')));
// Receive server response ...
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$server_output = curl_exec($ch);
curl_close($ch);
// Further processing ...
if ($server_output == "OK") { ... } else { ... }
?>
Procedural
// set post fields
$post = [
'username' => 'user1',
'password' => 'passuser1',
'gender' => 1,
];
$ch = curl_init('http://www.example.com');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $post);
// execute!
$response = curl_exec($ch);
// close the connection, release resources used
curl_close($ch);
// do anything you want with your response
var_dump($response);
Object oriented
<?php
// mutatis mutandis
namespace MyApp\Http;
class CurlPost
{
private $url;
private $options;
/**
* #param string $url Request URL
* #param array $options cURL options
*/
public function __construct($url, array $options = [])
{
$this->url = $url;
$this->options = $options;
}
/**
* Get the response
* #return string
* #throws \RuntimeException On cURL error
*/
public function __invoke(array $post)
{
$ch = \curl_init($this->url);
foreach ($this->options as $key => $val) {
\curl_setopt($ch, $key, $val);
}
\curl_setopt($ch, \CURLOPT_RETURNTRANSFER, true);
\curl_setopt($ch, \CURLOPT_POSTFIELDS, $post);
$response = \curl_exec($ch);
$error = \curl_error($ch);
$errno = \curl_errno($ch);
if (\is_resource($ch)) {
\curl_close($ch);
}
if (0 !== $errno) {
throw new \RuntimeException($error, $errno);
}
return $response;
}
}
Usage
// create curl object
$curl = new \MyApp\Http\CurlPost('http://www.example.com');
try {
// execute the request
echo $curl([
'username' => 'user1',
'password' => 'passuser1',
'gender' => 1,
]);
} catch (\RuntimeException $ex) {
// catch errors
die(sprintf('Http error %s with code %d', $ex->getMessage(), $ex->getCode()));
}
Side note here: it would be best to create some kind of interface called AdapterInterface for example with getResponse() method and let the class above implement it. Then you can always swap this implementation with another adapter of your like, without any side effects to your application.
Using HTTPS / encrypting traffic
Usually there's a problem with cURL in PHP under the Windows operating system. While trying to connect to a https protected endpoint, you will get an error telling you that certificate verify failed.
What most people do here is to tell the cURL library to simply ignore certificate errors and continue (curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);). As this will make your code work, you introduce huge security hole and enable malicious users to perform various attacks on your app like Man In The Middle attack or such.
Never, ever do that. Instead, you simply need to modify your php.ini and tell PHP where your CA Certificate file is to let it verify certificates correctly:
; modify the absolute path to the cacert.pem file
curl.cainfo=c:\php\cacert.pem
The latest cacert.pem can be downloaded from the Internet or extracted from your favorite browser. When changing any php.ini related settings remember to restart your webserver.
A live example of using php curl_exec to do an HTTP post:
Put this in a file called foobar.php:
<?php
$ch = curl_init();
$skipper = "luxury assault recreational vehicle";
$fields = array( 'penguins'=>$skipper, 'bestpony'=>'rainbowdash');
$postvars = '';
foreach($fields as $key=>$value) {
$postvars .= $key . "=" . $value . "&";
}
$url = "http://www.google.com";
curl_setopt($ch,CURLOPT_URL,$url);
curl_setopt($ch,CURLOPT_POST, 1); //0 for a get request
curl_setopt($ch,CURLOPT_POSTFIELDS,$postvars);
curl_setopt($ch,CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch,CURLOPT_CONNECTTIMEOUT ,3);
curl_setopt($ch,CURLOPT_TIMEOUT, 20);
$response = curl_exec($ch);
print "curl response is:" . $response;
curl_close ($ch);
?>
Then run it with the command php foobar.php, it dumps this kind of output to screen:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Title</title>
<meta http-equiv="Pragma" content="no-cache">
<meta http-equiv="Expires" content="0">
<body>
A mountain of content...
</body>
</html>
So you did a PHP POST to www.google.com and sent it some data.
Had the server been programmed to read in the post variables, it could decide to do something different based upon that.
It's can be easily reached with:
<?php
$post = [
'username' => 'user1',
'password' => 'passuser1',
'gender' => 1,
];
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'http://www.domain.com');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($post));
$response = curl_exec($ch);
var_export($response);
1.Step by step
Initialize the cURL session:
$url = "www.domain.com";
$ch = curl_init($url);
If your request has headers like bearer token or defining JSON contents you have to set HTTPHEADER options to cURL:
$token = "generated token code";
curl_setopt(
$ch,
CURLOPT_HTTPHEADER,
array(
'Content-Type: application/json', // for define content type that is json
'bearer: '.$token, // send token in header request
'Content-length: 100' // content length for example 100 characters (can add by strlen($fields))
)
);
If you want to include the header in the output set CURLOPT_HEADER to true:
curl_setopt($ch, CURLOPT_HEADER, false);
Set RETURNTRANSFER option to true to return the transfer as a string instead of outputting it directly:
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
To check the existence of a common name in the SSL peer certificate can be set to 0(to not check the names), 1(not supported in cURL 7.28.1), 2(default value and for production mode):
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
For posting fields as an array by cURL:
$fields = array(
"username" => "user1",
"password" => "passuser1",
"gender" => 1
);
curl_setopt($ch, CURLOPT_POSTFIELDS, $fields);
Execute cURL and return the string. depending on your resource this returns output like result=OK:
$result = curl_exec($ch);
Close cURL resource, and free up system resources:
curl_close($ch);
2.Use as a class
The whole call_cURL class that can be extended:
class class_name_for_call_cURL {
protected function getUrl() {
return "www.domain.com";
}
public function call_cURL() {
$token = "generated token code";
$fields = array(
"username" => "user1",
"password" => "passuser1",
"gender" => 1
);
$url = $this->getUrl();
$output = $this->_execute($fields, $url, $token);
// if you want to get json data
// $output = json_decode($output);
if ($output == "OK") {
return true;
} else {
return false;
}
}
private function _execute($postData, $url, $token) {
// for sending data as json type
$fields = json_encode($postData);
$ch = curl_init($url);
curl_setopt(
$ch,
CURLOPT_HTTPHEADER,
array(
'Content-Type: application/json', // if the content type is json
'bearer: '.$token // if you need token in header
)
);
curl_setopt($ch, CURLOPT_HEADER, false);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
curl_setopt($ch, CURLOPT_POSTFIELDS, $fields);
$result = curl_exec($ch);
curl_close($ch);
return $result;
}
}
Using the class and call cURL:
$class = new class_name_for_call_cURL();
var_dump($class->call_cURL()); // output is true/false
3.One function
A function for using anywhere that needed:
function get_cURL() {
$url = "www.domain.com";
$token = "generated token code";
$postData = array(
"username" => "user1",
"password" => "passuser1",
"gender" => 1
);
// for sending data as json type
$fields = json_encode($postData);
$ch = curl_init($url);
curl_setopt(
$ch,
CURLOPT_HTTPHEADER,
array(
'Content-Type: application/json', // if the content type is json
'bearer: '.$token // if you need token in header
)
);
curl_setopt($ch, CURLOPT_HEADER, false);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
curl_setopt($ch, CURLOPT_POSTFIELDS, $fields);
$result = curl_exec($ch);
curl_close($ch);
return $result;
}
This function is usable just by:
var_dump(get_cURL());
Curl Post + Error Handling + Set Headers [thanks to #mantas-d]:
function curlPost($url, $data=NULL, $headers = NULL) {
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
if(!empty($data)){
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
}
if (!empty($headers)) {
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
}
$response = curl_exec($ch);
if (curl_error($ch)) {
trigger_error('Curl Error:' . curl_error($ch));
}
curl_close($ch);
return $response;
}
curlPost('google.com', [
'username' => 'admin',
'password' => '12345',
]);
curlPost('google.com', [
'username' => 'admin',
'password' => '12345',
]);
function curlPost($url, $data) {
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
$response = curl_exec($ch);
$error = curl_error($ch);
curl_close($ch);
if ($error !== '') {
throw new \Exception($error);
}
return $response;
}
I'm surprised nobody suggested file_get_contents:
$url = "http://www.example.com";
$parameters = array('username' => 'user1', 'password' => 'passuser1', 'gender' => '1');
$options = array('http' => array(
'header' => 'Content-Type: application/x-www-form-urlencoded\r\n',
'method' => 'POST',
'content' => http_build_query($parameters)
));
$context = stream_context_create($options);
$result = file_get_contents($url, false, $context);
it's simple, it works; I use it in an environment where I control the code at both ends.
even better, use json_decode (and set up your code to return JSON)
$result = json_decode(file_get_contents($url, false, $context), TRUE);
this approach invokes curl behind the scenes, but you don't jump through as many hoops.
Answer refined from this original answer elsewhere on Stack Overflow:
PHP sending variables to file_get_contents()
If the form is using redirects, authentication, cookies, SSL (https), or anything else other than a totally open script expecting POST variables, you are going to start gnashing your teeth really quick. Take a look at Snoopy, which does exactly what you have in mind while removing the need to set up a lot of the overhead.
A simpler answer IF you are passing information to your own website is to use a SESSION variable. Begin php page with:
session_start();
If at some point there is information you want to generate in PHP and pass to the next page in the session, instead of using a POST variable, assign it to a SESSION variable. Example:
$_SESSION['message']='www.'.$_GET['school'].'.edu was not found. Please try again.'
Then on the next page you simply reference this SESSION variable. NOTE: after you use it, be sure you destroy it, so it doesn't persist after it is used:
if (isset($_SESSION['message'])) {echo $_SESSION['message']; unset($_SESSION['message']);}
Here are some boilerplate code for PHP + curl
http://www.webbotsspidersscreenscrapers.com/DSP_download.php
include in these library will simplify development
<?php
# Initialization
include("LIB_http.php");
include("LIB_parse.php");
$product_array=array();
$product_count=0;
# Download the target (store) web page
$target = "http://www.tellmewhenitchanges.com/buyair";
$web_page = http_get($target, "");
...
?>
Examples of sending form and raw data:
$curlHandler = curl_init();
curl_setopt_array($curlHandler, [
CURLOPT_URL => 'https://postman-echo.com/post',
CURLOPT_RETURNTRANSFER => true,
/**
* Specify POST method
*/
CURLOPT_POST => true,
/**
* Specify array of form fields
*/
CURLOPT_POSTFIELDS => [
'foo' => 'bar',
'baz' => 'biz',
],
]);
$response = curl_exec($curlHandler);
curl_close($curlHandler);
echo($response);
If you try to login on site with cookies.
This code:
if ($server_output == "OK") { ... } else { ... }
It May not works if you try to login, because many sites return status 200, but the post is not successful.
The easy way to check if the login post is successful is to check if it setting cookies again. If in output have a Set-Cookies string, this means the posts are not successful and it starts a new session.
Also, the post can be successful, but the status can redirect instead of 200.
To be sure the post is successful try this:
Follow location after the post, so it will go to the page where the post does redirect to:
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
And than check if new cookies existing in the request:
if (!preg_match('/^Set-Cookie:\s*([^;]*)/mi', $server_output))
{echo 'post successful'; }
else { echo 'not successful'; }
Easiest is to send data as application/json. This will take an array as input and properly encodes it into a json string:
$data = array(
'field1' => 'field1value',
'field2' => 'field2value',
)
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
'Content-Type:application/json',
));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$resultStr = curl_exec($ch);
return json_decode($resultStr, true);
Trying to send filestream with other data to an API , but it return the error:
The video provided was null
Here is my code:
function create_video($files) {
$api = "http://api.brightcove.com/services/post";
$local_file_list = $files['file']['tmp_name'];
foreach ($local_file_list as $local_file) {
try {
$fp = fopen($local_file, 'r');
$ch = curl_init();
if (FALSE === $ch) {
throw new Exception('failed to initialize');
}
//"video":{"name":"test","shortDescription":"test","startDate":1432282741000,"endDate":null}
$request = 'json={"params":{"encode_to":"MP4","create_multiple_renditions":"True","token":"' . WRITE_TOKEN . '"},"method":"create_video"}';
curl_setopt($ch, CURLOPT_URL, $api);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $request);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_INFILE, $fp);
curl_setopt($ch, CURLOPT_INFILESIZE, filesize($local_file));
$content = curl_exec($ch);
if (FALSE === $content) {
throw new Exception(curl_error($ch), curl_errno($ch));
}
die(var_dump(json_decode($content)));
return json_decode($content);
} catch (Exception $e) {
trigger_error(sprintf('Curl failed with error #%d: %s', $e->getCode(), $e->getMessage()), E_USER_ERROR);
}
}
}
Few things need to note:
CURL does not return error , so it may not caused by CURL
The filesize($local_file) has return the correct file size
fopen($local_file, 'r'); return the stream type content, so the file is exist
How to fix that? Thanks
API reference:
https://docs.brightcove.com/en/video-cloud/media/references/reference.html#Video_Write
Update:
Thanks for helping , but it now return another error:
POST methods require valid JSON-RPC in the POST body, with "method" and "params" properties
I have some idea of that as when I look at the request payload, it is slightly different from the correct one:
Current my version:
------WebKitFormBoundary8VABz8KuNRE8Hepd
Content-Disposition: form-data; name="file[0]"; filename="big_buck_bunny.mp4"
Content-Type: video/mp4
------WebKitFormBoundary8VABz8KuNRE8Hepd--
The correct version
------WebKitFormBoundaryCAB6WEANBJxoB3Op
Content-Disposition: form-data; name="JSONRPC"
{"params":{"video":{"name":"test","shortDescription":"test","startDate":1432282741000,"endDate":null},"encode_to":"MP4","create_multiple_renditions":"True","token":"VyocgALDnxU8HPvmnSnckgmXjoPlYWomc2La5Tn-evuAfsnSPJJoow.."},"method":"create_video"}
------WebKitFormBoundaryCAB6WEANBJxoB3Op
Content-Disposition: form-data; name="filePath"; filename="big_buck_bunny.mp4"
Content-Type: video/mp4
------WebKitFormBoundaryCAB6WEANBJxoB3Op
Content-Disposition: form-data; name="JSONView"
{"params":{"video":{"name":"test","shortDescription":"test","startDate":1432282741000,"endDate":null},"encode_to":"MP4","create_multiple_renditions":"True","token":"VyocgALDnxU8HPvmnSnckgmXjoPlYWomc2La5Tn-evuAfsnSPJJoow.."},"method":"create_video"}
------WebKitFormBoundaryCAB6WEANBJxoB3Op--
You can wrap the file to upload into CURLFile (PHP >= 5.5):
$cfile = new CURLFile($local_file, 'video/mp4', basename($local_file));
Then, add to CURLOPT_POSTFIELDS, making it part of the whole request:
$ch = curl_init();
curl_setopt($ch, CURLOPT_POSTFIELDS, [
'file' => $cfile,
'JSONRPC' => '{"params":{"encode_to":"MP4","create_multiple_renditions":"True","token":"' . WRITE_TOKEN . '"},"method":"create_video"}';
]);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$content = curl_exec($ch);
Before PHP 5.5 you can use the # to indicate a file:
curl_setopt($ch, CURLOPT_POSTFIELDS, [
'file' => "#$local_file",
'JSONRPC' => '{"params":{"encode_to":"MP4","create_multiple_renditions":"True","token":"' . WRITE_TOKEN . '"},"method":"create_video"}';
]);
I've got a simple PHP script that sends an HTTP POST request via cURL, and expects a json string in response (would have loved to use an existing library like pecl_http/HTTPRequest for this, but can't). The call consistently fails with a 415 error - Unsupported Media Type. I think I'm not configuring cURL correctly, but after much searching, I can't find out what I'm doing wrong. Here's some code:
class URLRequest
{
public $url;
public $headers;
public $params;
public $body;
public $expectedFormat;
public $method;
public function URLRequest($aUrl, array $aHeaders, array $aParams, $aFormat = "json", $isPost = false, $aBody = "+")
{
$this->url = $aUrl;
$this->headers = $aHeaders;
$this->params = $aParams;
$this->expectedFormat = $aFormat;
$this->method = ($isPost ? "POST" : "GET");
$this->body = $aBody;
}
public function exec()
{
$queryStr = "?";
foreach($this->params as $key=>$val)
$queryStr .= $key . "=" . $val . "&";
//trim the last '&'
$queryStr = rtrim($queryStr, "&");
$url = $this->url . $queryStr;
$request = curl_init();
curl_setopt($request, CURLOPT_URL, $url);
curl_setopt($request, CURLOPT_HEADER, 1);
curl_setopt($request, CURLOPT_HTTPHEADER, $this->headers);
curl_setopt($request, CURLOPT_RETURNTRANSFER, 1);
//curl_setopt($request, CURLOPT_SSL_VERIFYPEER, false);
if($this->method == "POST")
{
curl_setopt($request, CURLOPT_POST, 1);
curl_setopt($request, CURLOPT_POSTFIELDS, $this->body);
//this prevents an additions code 100 from getting returned
//found it in some forum - seems kind of hacky
curl_setopt($request, CURLOPT_HTTPHEADER, array("Expect:"));
}
$response = curl_exec($request);
curl_close($request);
preg_match("%(?<=HTTP/[0-9]\.[0-9] )[0-9]+%", $response, $code);
$resp = "";
if($this->expectedFormat == "json")
{
//parse response
}
elseif($this->expectedFormat == "xml")
{
//parse response
}
return $resp;
}
}
$url = "http://mydomain.com/myrestcall";
$query = array( "arg_1" => "test001",
"arg_2" => "test002",
"arg_3" => "test003");
$headers = array( "Accept-Encoding" => "gzip",
"Content-Type" => "application/json",
"Accept" => "application/json",
"custom_header_1" => "test011",
"custom_header_2" => "test012",
"custom_header_3" => "test013");
$body = array( "body_arg_1" => "test021",
"body_arg_2" => array("test022", "test023"),
"body_arg_3" => "test024");
$request = new URLRequest($url, $headers, $query, "json", true, $body);
$response = $request->exec();
...and the response:
HTTP/1.1 415 Unsupported Media Type
Server: Apache-Coyote/1.1
X-Powered-By: Servlet 2.5; JBoss-5.0/JBossWeb-2.1
Content-Type: text/html;charset=utf-8
Content-Length: 1047
Date: Mon, 18 Jun 2012 16:30:44 GMT
<html><head><title>JBoss Web/2.1.3.GA - Error report</title></head><body><h1>HTTP Status 415 - </h1><p><b>type</b> Status report</p><p><b>message</b> <u></u></p><p><b>description</b> <u>The server refused this request because the request entity is in a format not supported by the requested resource for the requested method ().</u></p><h3>JBoss Web/2.1.3.GA</h3></body></html>
Any insights or ideas?
Thanks in advance!
Problem solved! Here's the issue:
Sending an associative-array of headers DOES NOT WORK with cURL. There are several forums scattered around that show examples using an associative array for headers. DON'T DO IT!
The correct way (which is also scattered around the internets, but that I'm too dense to have noticed) is to construct your header key/value pairs as strings, and pass a standard array of these strings when setting the CURLOPT_HTTPHEADER option.
So in summary,
WRONG:
$headers = array( "Accept-Encoding" => "gzip",
"Content-Type" => "application/json",
"custom_header_1" => "test011",
"custom_header_2" => "test012",
"custom_header_3" => "test013");
RIGHT:
$headers = array( "Accept-Encoding: gzip",
"Content-Type: application/json",
"custom_header_1: test011",
"custom_header_2: test012",
"custom_header_3: test013");
I hope this comes in handy to some other noble doofus down the road before they waste as much time debugging as I did.
If I had to guess, I would assume that the same rule applies to the POST body key/value pairs as well, which is why #drew010 's comment about using http_build_query() or json_encode() to stringify your message body is a great idea as well.
Thanks to everyone for your very useful comments, and for you time and consideration. In the end, a side by side comparison of the http traffic (captured via Wireshark) revealed the issue.
Thanks!
I think the problem is that you are passing an array as the CURLOPT_POSTFIELDS option. By passing an array, this forces the POST request to use multipart/form-data when the server is probably expecting application/x-www-form-urlencoded.
Try changing
curl_setopt($request, CURLOPT_POSTFIELDS, $this->body);
to
curl_setopt($request, CURLOPT_POSTFIELDS, http_build_query($this->body));
See http_build_query for more information and also this answer: My cURL request confuses some servers?
I had the same problem and I fixed changing the header.
My code:
$authorization = 'authorization: Bearer '.trim($apiKey);
$header = [
'Content-Type: application/json',
$authorization
];
curl_setopt($session, CURLOPT_HTTPHEADER, $header);
I don't know why the array function doesn't work :
curl_setopt($session, CURLOPT_HTTPHEADER, array('Content-Type:
application/json',
$authorization));
This worked for me
$data ="data";
$headers = [
"Content-Type: application/json",
"X-Content-Type-Options:nosniff",
"Accept:application/json",
"Cache-Control:no-cache"
];
$auth = $USER . ":" . $PASSWORD;
$curl = curl_init();
curl_setopt($curl,CURLOPT_URL, $url);
curl_setopt($curl,CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl,CURLOPT_ENCODING, "");
curl_setopt($curl,CURLOPT_MAXREDIRS, 10);
curl_setopt($curl,CURLOPT_TIMEOUT, 0);
curl_setopt($curl,CURLOPT_FOLLOWLOCATION, true);
curl_setopt($curl,CURLOPT_HTTP_VERSION,CURL_HTTP_VERSION_1_1);
curl_setopt($curl,CURLOPT_CUSTOMREQUEST, "POST");
curl_setopt($curl,CURLOPT_POSTFIELDS, json_encode($data));
curl_setopt($curl, CURLOPT_USERPWD, $auth);
curl_setopt($curl,CURLOPT_HTTPHEADER, $headers);
$result = curl_exec($curl);