CURL is failed in sending the parameters to the Server - php

I am going to send a Log in request to the server by using CURL in my PHP code. This request is POST and I wrote following code,
if (strpos($header, 'POST') !== false){
curl_setopt_array($curl, array(
CURLOPT_RETURNTRANSFER => 1,
CURLOPT_HEADER => 1,
CURLOPT_URL => $url,
CURLOPT_USERAGENT => 'proxy',
CURLOPT_POST => 1,
CURLOPT_POSTFIELDS => $postParameters,
CURLOPT_COOKIE => $postCoockies
));
$respond = curl_exec($curl);
curl_close($curl); }
and if I want to say what my variables are here:
$url is the exact String after POST and before HTTP/1.1.
when I want to send the GET request also, I am using this part as my urs which would be contained all parameters in my query String.
$postParameters is the exact String that exist in POST body.
(That's a String, not an associative array)
$postCoockies in the exact String after Cookie: in my request header.
(again, that's not an associative array)
My problem is:
When I send this request, server sends me back a response to only the URL I am passing. Which is to load the login page again! it seems that the server is not receiving my parameters!
Also, when I used GET request for login (I have access to the source code of website), and sent the whole URL and parameters inside the $url, the same thing happened.
Am I wrong somewhere in sending my request?
Should I consider something else here?

Related

How to retrieve cURL response on error in PHP

I am using PHP 7.4/8.0 and cURL to call an API and download a large PDF file based on a user request. Because the file is large, I don't want to use CURLOPT_RETURNTRANSFER and first save the file to a PHP string or a temp file, only to then send the file contents to the user's browser. Instead, I want to pass the file contents directly to the user's browser, like a proxy server might do. I am calling it with code:
<?php
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_URL => 'https://www.example.com/api',
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => '{"item": "1"}',
CURLOPT_FAILONERROR => true,
));
curl_exec($curl);
curl_close($curl);
?>
The issue is when the API returns an error, it sends a HTTP 500 code, and in the response body, it includes the error details such as:
{
"error": "111",
"message": "This is the error message"
}
When an error happens, I want to catch that error in my code and handle it. Passing CURLOPT_FAILONERROR allows me to catch the error, but I can't figure out how to get the response body that the API sent back.
Is there a way to get the response body in a scenario like this? Again, I don't want to use CURLOPT_RETURNTRANSFER as I want to pass the output directly through to the user's browser when there is no error. I only want to get the response body when there is an error.
Thanks for your help.

Send a complex data using curl in PHP

I have searched a lot, and found many related questions and forums related to this, but this one is a challenging one.
I'm trying to POST a complex array via curl. It has to be form-data while the first value in the array is of type JSON.
The two other values of array are two images which are uploaded and ready to send.
I tried to run it in Postman, and works perfectly fine. I used the generated PHP code from Postman, but it is not working. Seems like postman is handling some of its tricks without revealing them to us.
Any way, I'm posting a Postman image to illustrate what I mean:
As you can see, I'm sending the data in form-data tab, my first value (param1) is a JSON with content-type application/json, the second and third values are images uploaded in Postman.
This works just fine in Postman.
The problem is, if I set Content-Type:multipart/form-data in header, the destination server throws an error saying the content-type must be JSON.
If I set the Content-Type:application/json in header, the destination server says content must be of type Multipart.
Somehow, I need to set both content-types. The main one as form-data and the one for param1 as JSON.
I paste the Postman code as well, may that be a good start for you fellas to help out with the code.
Postman Code:
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_URL => 'http://xxxxx.com/xxxx/xxx/xxxx',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => '',
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 0,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_POSTFIELDS => array('param1' => '{
"AgentId":"1414",
"ContractId":36529,
"Files":[
{
"FileName":"car_card_front_image.png",
"FileTypeId":2
},
{
"FileName":"car_card_back_image.png",
"FileTypeId":2
}
]
}','param2'=> new CURLFILE('/C:/images/icons/car_card_back_image.png'),'param3'=> new CURLFILE('/C:/images/icons/car_card_front_image.png')),
CURLOPT_HTTPHEADER => array(
'authenticationToken: xxxx-xxx-xx-xxxxxxxx'
),
));
$response = curl_exec($curl);
curl_close($curl);
echo $response;
The PHP generated code by postman, is not working. One of the reasons can be that there's no content-type mentioned in it.
I tried modifying the code, adding content-types in header and in parameter, nothing seems to work.
If Postman can do it, we should be able it too, right?
Go ahead, make as much changes as you would or suggest anything that comes to your mind, I will test them all.
Cheeeeers...
May i suggest the ixudrra/curl library ?
It would make your life easier ....
$response = Curl::to('http://example.org')
->withData( array( 'Foo' => 'Bar' ) )
->withFile( 'image_1', '/path/to/dir/image1.png', 'image/png', 'imageName1.png' )
->withFile( 'image_2', '/path/to/dir/image2.png', 'image/png', 'imageName2.png' )
->post();

GET request with headers using cURL PHP

I m trying to make a GET request with headers using cURL PHP. I am getting an empty response form the server. I would like to know if I have made this request correctly using cURL PHP.
// curl GET request with headers
$url = $sendMailURL;
$requestHeaders = array(
$hConLength_.':'.$conLengthValue,
$hConType_.':'.$conTypeValue,
$hHost_.':'.$conHostValue,
$hDate_.':'.$conAmzDateValue);
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_HTTPHEADER, $requestHeaders);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$output = curl_exec($ch);
if(curl_error($ch)){
echo 'curl error: '.curl_error($ch);
}else{
print_r($output);
}
print_r($requestHeaders):
Array ( [0] => Content-Length:207
[1] => Content-Type:application/x-www-form-urlencoded
[2] => Host:email.eu-west-1.amazonaws.com
[3] => X-amz-date:20180115T224433Z )
I'm positive that you have found your answer, but in case there are others who will probably want to figure out how to check the headers or want to go down the rabbit hole trying to figure out how SignatureV4 works.
You need to set curl_option CURLINFO_HEADER_OUT
I used following to set all the options in one go, but I don't see why you can't set them one by one.
$conf = [
\CURLOPT_CUSTOMREQUEST => $method, // method
\CURLOPT_URL => $url, // url
\CURLOPT_HTTPHEADER => $requestHeaders, // headers
\CURLOPT_RETURNTRANSFER => true,
\CURLOPT_HEADER => true,
\CURLOPT_CONNECTTIMEOUT => $timeout, // set to anything that fits
\CURLOPT_PROTOCOLS => CURLPROTO_HTTPS, // whatever is your protocol
\CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, // normally 1.1
\CURLINFO_HEADER_OUT => 1, // this will cause request headers to show up
];
curl_setopt_array($this->curl, $conf);
After running your request and before closing curl you can check for your headers and response headers all together.
$result = curl_exec($this->curl);
$info = curl_getinfo($this->curl, CURLINFO_HEADER_OUT); // run after exec before close
var_dump($info);
curl_close($this->curl);
you don't have to specify CURLINFO_HEADER_OUT when calling curl_getinfo but it will show a lot more info which makes it a little harder to find what you are looking for.
Since you mentioned in comments that you are trying to make SignatureV4 for AWS and I had the same issue, a few notes:
Although http headers are not case sensitive, when calculating hash they should be in lowercase and also specified in authorization token in lower case too. to make it easier, I just included headers in both request and hash as lowercase
You don't need to hash all the headers, since you will need to mention which headers are included in hash, in the authorization token.
Someone at AWS thought it is cool to sort querystring items alphabetically before calculating hash, so if you are sending querystring, make sure tokens are sorted before hashing it e.g.
Engine=standard&LanguageCode=en-US // will work
LanguageCode=en-US&Engine=standard // will not work
The only two headers that need to be in hash are x-amz-date and host. (at least that was the case for Polly) and they need to look like this
host:service.region.amazonaws.com
x-amz-date:20210920T180242Z
authorization:AWS4-HMAC-SHA256 Credential=xxxxxxxxxxxxxxxxxxxx/20210920/region/service/aws4_request, SignedHeaders=host;x-amz-date, Signature=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

How does Laravel know Request::wantsJson is a request for JSON?

I noticed that Laravel has a neat method Request::wantsJson - I assume when I make the request I can pass information to request a JSON response, but how do I do this, and what criteria does Laravel use to detect whether a request asks for JSON ?
It uses the Accept header sent by the client to determine if it wants a JSON response.
Let's look at the code :
public function wantsJson() {
$acceptable = $this->getAcceptableContentTypes();
return isset($acceptable[0]) && $acceptable[0] == 'application/json';
}
So if the client sends a request with the first acceptable content type to application/json then the method will return true.
As for how to request JSON, you should set the Accept header accordingly, it depends on what library you use to query your route, here are some examples with libraries I know :
Guzzle (PHP):
GuzzleHttp\get("http://laravel/route", ["headers" => ["Accept" => "application/json"]]);
cURL (PHP) :
$curl = curl_init();
curl_setopt_array($curl, [CURLOPT_URL => "http://laravel/route", CURLOPT_HTTPHEADER => ["Accept" => "application/json"], CURLOPT_RETURNTRANSFER => true]);
curl_exec($curl);
Requests (Python) :
requests.get("http://laravel/route", headers={"Accept":"application/json"})

How to send URL variables programmatically with response from my PHP endpoint

I have a basic API endpoint set up on my site, which a 3rd party site will use to verify certain info that is entered into a form by the user.
Here's the flow:
1. User is on 3rd party site.
2. User enters info into a form
3. Info is sent to my site's endpoint.
4. My site checks the information and returns a JSON object.
As you can see from #4, my API is currently set up to return a JSON object. After the info is checked, something like this happens:
header('content-type: application/json; charset=utf-8');
echo json_encode($response);
exit;
However, the 3rd party site is only set up to receive URL variables. Is there a way to pass back url variables programmatically? I realize I could theoretically send a new request, but it's not clear to me where that request should go (the internal workings of the 3rd party site aren't well documented), so I'd much prefer to send it as a response.
I hope this makes sense. Please comment if it doesn't. Thanks in advance!
You don't get to send GET/POST parameters in the response, but in the response body you can send whatever you want in whatever format you want - and they can use curl or file_get_content and parse it on their side (3rd party's website).
For example (on the 3rd party's website):
//setting a call to your server
$opts = array('http' =>
array(
'method' => 'POST',
'header' => "Content-Type: text/xml\r\n".
"Authorization: Basic ".base64_encode("$https_user:$https_password")."\r\n",
'content' => $body,
'timeout' => 60
)
);
$context = stream_context_create($opts);
$url = 'https://'.$https_server;
// Here they call your server
$result = file_get_contents($url, false, $context, -1, 40000);
// Here you'll parse the $result

Categories