I am trying to cURL a base64_encoded xml string to a c# WebAPI that i dont have control over. I can cURL the string successfully but it is not being accepted by the API.
Logging the output shows that cURL is stripping + characters from the base64 string which i believe to be the problem.
The code i have is:
$username = "username";
$password = "$23hrlkbl";
$xml = "<Envelope><Header><User>".$username."</User><Password>".$password."</Password></Header></Envelope>";
$passThru = "https://api.domain.com/SignIn.aspx?passthruUrl=/Management/Api/DataEnrichment/GetAddresses/?buildingNumber=1%26streetName=Nightingale%20Road%26postcode=L12%200QN
$post_packet_data = 'XMLdataPacket='.urlencode(base64_encode($xml));
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $passThru);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $post_packet_data);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
curl_setopt($ch, CURLOPT_HEADER, 1);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
$response = curl_exec ($ch);
curl_close($ch);
print_r($response);
Posting the following string (non urlencoded $post_packet_data) via an html form to the $passThru address works successfully
XMLdataPacket=PEVudmVsb3BlPjxIZWFkZXI+PFVzZXI+dXNlcm5hbWU8L1VzZXI+PFBhc3N3b3JkPiQyM2hybGtibDwvUGFzc3dvcmQ+PC9IZWFkZXI+PC9FbnZlbG9wZT4=
However when posting the same string via cURL the following is sent and not accepted
XMLdataPacket=PEVudmVsb3BlPjxIZWFkZXI PFVzZXI dXNlcm5hbWU8L1VzZXI PFBhc3N3b3JkPiQyM2hybGtibDwvUGFzc3dvcmQ PC9IZWFkZXI PC9FbnZlbG9wZT4=
UPDATE
After speaking to the developers of the API they have confirmed the requests are now coming in in the correct format but believe the calls are not being processed due to incorrect headers being sent. They have sent me the headers of a working call which they got using fiddler:
POST https://api.domain.com/SignIn.aspx?passthruUrl=/Management/Api/DataEnrichment/GetAddresses/?buildingNumber=1%26streetName=Nightingale%20Road%26postcode=L12%200QN HTTP/1.1
Host: test.domain.com
Connection: keep-alive
Content-Length: 164
Cache-Control: max-age=0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Origin: null
User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/33.0.1750.146 Safari/537.36
Content-Type: application/x-www-form-urlencoded
Accept-Encoding: gzip,deflate,sdch
Accept-Language: en-GB,en-US;q=0.8,en;q=0.6
Cookie: ASP.NET_SessionId=uzwfjq3zojao3l5fw141l453
XMLdataPacket=PEVudmVsb3BlPjxIZWFkZXI%2BPFVzZXI+dXNlcm5hbWU8L1VzZXI%2BPFBhc3N3b3JkPiQyM2hybGtibDwvUGFzc3dvcmQ%2BPC9IZWFkZXI%2BPC9FbnZlbG9wZT4%3D
How would i amend the headers of the cURL call to replicate the above. Currently again using fiddler the cURL call headers appear as the following:
GET http://test.domain.com/test_call.php HTTP/1.1
Host: test.domain.com
User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64; rv:27.0) Gecko/20100101 Firefox/27.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-gb,en;q=0.5
Accept-Encoding: gzip, deflate
Cookie: CAKEPHP=g22d7kf7qs8b1v02uui2mnop30
Authorization: Basic bmV0aG91c2VwcmljZXMxOnRlbXAxODkx
Connection: keep-alive
Cache-Control: max-age=0
The data is receieved at the api end as POST but the curl headers are coming through as GET according to the above
Try using rawurlencode() instead of urlencode() - it encodes the space character using '%20' instead of using the '+' character.
Related
I am trying to send a GET request to a python server with an Authorization Token in the header.
I do receive the Request on the server side but without the authorization token
Here is the php code that is generating the request :
<?php
$url = "http://localhost:7432/f.php";
$curl = curl_init($url);
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
$headers = array(
"Authorization: sdfascvthsgdgdssgvsgscf",
);
curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
//for debug only!
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
$resp = curl_exec($curl);
curl_close($curl);
var_dump($resp);
?>
When I generate the request from Reqbin, I do Receive the request with the Authorization token in the header , but when I try to generate the request from the php file then it does not send the Authorization token to the server
Here is the request received on server side when I use the Reqbin website to make the request:
127.0.0.1 - - [03/Sep/2021 13:27:10] "GET /f.php HTTP/1.1" 200 -
Host: localhost:7432
Connection: keep-alive
sec-ch-ua: " Not A;Brand";v="99", "Chromium";v="92", "Opera";v="78"
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159
Safari/537.36 OPR/78.0.4093.184
sec-ch-ua-mobile: ?0
Authorization: sdfascvthsgdgdssgvsgscf
Accept: */*
Sec-Fetch-Site: none
Sec-Fetch-Mode: cors
Sec-Fetch-Dest: empty
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9
Cookie: _ga=GA1.1.1359401486.1622671713
And This is the received Request when I use the php code mentioned above :
127.0.0.1 - - [03/Sep/2021 13:27:20] "GET /f.php HTTP/1.1" 200 -
Host: localhost:7432Connection: keep-alive Cache-Control: max-age=0
sec-ch-ua: " Not A;Brand";v="99", "Chromium";v="92", "Opera";v="78"
sec-ch-ua-mobile: ?0 Upgrade-Insecure-Requests: 1 User-Agent:
Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML,
like Gecko) Chrome/92.0.4515.159 Safari/537.36 OPR/78.0.4093.184
Accept:
text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Sec-Fetch-Site: none Sec-Fetch-Mode: navigate Sec-Fetch-User: ?1
Sec-Fetch-Dest: document Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9 Cookie:
_ga=GA1.1.1359401486.1622671713
What am I doing wrong at the php side ?
Okay, i have some website which i should parse...
Firstly, i open debugger in Firefox hitting F12, and look at Network tab, then enter needed website, and reading first root GET request, like
Doman => website.com
File => /
I get there all the request headers and write them into php array manually, then in code i call
curl_setopt($curl, CURLOPT_HTTPHEADER, $headerArray);
and also other options, then call
curl_exec();
while inspecting the Network tab in Firefox, i see that request headers are maybe such as default, and no specific headers written manually into array were sent. Similar problem with CURLOPT_COOKIEFILE and CURLOPT_COOKIEJAR, cookies are just written to cookie file on server, but in fact, there are another cookies in next request instead of previously saved in cookies file.
Actual request headers in browser's inspector:
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Encoding: gzip, deflate
Accept-Language: ru-RU,ru;q=0.8,en-US;q=0.5,en;q=0.3
Cache-Control: max-age=0
Connection: keep-alive
Cookie: _ga=GA1.1.1951751996.1563984714; _gid=GA1.1.1564173251.1563984714; _userGUID=0:jyhg490v:AIQdD2Qpm9rmbla1U93mK2a45CFRe49c; jv_enter_ts_2VumZAPpbr=1563984717382; jv_visits_count_2VumZAPpbr=1; .....
Host: localhost
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:68.0) Gecko/20100101 Firefox/68.0
PHP Code:
<?php
$headers = ['Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
'Accept-Language: ru-RU,ru;q=0.8,en-US;q=0.5,en;q=0.3',
'Cache-Control: max-age=0',
'Connection: keep-alive',
'Cookie: visid_incap_1987259....,
'Host: website.com',
'TE: Trailers',
'Upgrade-Insecure-Requests: 1',
'User-Agent: Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)'];
$curl = curl_init("https://www.website.com/");
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);
curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
curl_setopt($curl, CURLOPT_COOKIEFILE, dirname(__FILE__)."/cookies.txt");
curl_setopt($curl, CURLOPT_COOKIEJAR, dirname(__FILE__)."/cookies.txt");
echo curl_exec($curl);
?>
You will not be able to see the headers send CURL in the Browser Dev Tools. All requests are executed on the server side. Your headers are sent successfully. You can check it out like this:
curl_setopt($curl, CURLINFO_HEADER_OUT, true);
$sentHeaders = curl_getinfo($curl, CURLINFO_HEADER_OUT);
print_r($sentHeaders);
Is there any command in php curl to print response query string parameters
Below is my php code
<?php
session_start();
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL,"http://192.168.1.220/cgi-bin/handle_login.tcl");
curl_setopt($ch, CURLOPT_POST, TRUE);
curl_setopt($ch, CURLOPT_POSTFIELDS,
"user=admin&pw=admin&submit=Login&sid=' '");
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: x-www-form-urlencoded'));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
$response = curl_exec($ch);
echo "$response";
curl_close ($ch);
?>
below is header response
Request URL:http://localhost:8080/cgi-bin/frameset.tcl?
sid=3514275041172666092
Request Method:GET
Status Code:404 Not Found
Remote Address:[::1]:8080
Referrer Policy:no-referrer-when-downgrade
Response Headers
Accept-Ranges:bytes
Connection:Keep-Alive
Content-Language:en
Content-Type:text/html; charset=utf-8
Date:Mon, 29 May 2017 06:54:33 GMT
Keep-Alive:timeout=5, max=99
Server:Apache/2.4.18 (Win32) OpenSSL/1.0.2e PHP/7.0.4
Transfer-Encoding:chunked
Vary:accept-language,accept-charset
Request Headers
Accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,
*/*;q=0.8
Accept-Encoding:gzip, deflate, sdch, br
Accept-Language:en-US,en;q=0.8
Connection:keep-alive
Cookie:PHPSESSID=hj7kbp4hp0pjq16m1tk7j3goo3; _ga=GA1.1.981975196.1489736033; XDEBUG_TRACE=XDEBUG_ECLIPSE
DNT:1
Host:localhost:8080
Referer:http://localhost:8080/nias/automate.php
Upgrade-Insecure-Requests:1
User-Agent:Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36
Query String Parameters
sid=3514275041172666092 //need to print these value
Since output was in string format and the output remains constant eachtime..needed to find the position of the required character in the string and extract the required value..
Below is the code
$response= curl_exec($ch);//executes the curl
echo strpos("$response","variable_to_find")."<br/>";//know the position
$sid = substr($response,position,length);
I'm trying to set up a proxy server to make a post request. Problem is when I make the request I am not seeing the payload.
One thing I notice is that curl seems to be adding an extra "boundary" to the content-type in the request.
Am I missing something?
The Code:
$contentType = $_SERVER["HTTP_CONTENT_TYPE"];
$post = http_build_query($_POST);
$ch = curl_init();
$header = array("Content-Type:" . $contentType,
"Accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8",
"Accept-Encoding:gzip, deflate, br",
"Accept-Language:en-US,en;q=0.8",
"Connection:keep-alive",
"User-Agent:Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36",
"Cache-Control:max-age=0",
"Upgrade-Insecure-Requests:1",
"Origin:<url here>");
echo "<b>POST</b><br>" . var_dump($_POST) . "<br><br>";
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POST, count($_POST));
curl_setopt($ch, CURLOPT_POSTFIELDS, $_POST);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
curl_setopt($ch, CURLINFO_HEADER_OUT, true);
curl_setopt($ch, CURLOPT_COOKIEFILE, "cookiejar.txt");
curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
curl_setopt($ch, CURLOPT_HEADER, 1);
$result = curl_exec($ch);
$headerSent = curl_getinfo($ch, CURLINFO_HEADER_OUT );
echo "<b>Request Header</b><br>$headerSent<br><br>";
$header_size = curl_getinfo($ch, CURLINFO_HEADER_SIZE);
$header = substr($result, 0, $header_size);
$body = substr($result, $header_size);
echo "<b>Response Header</b><br>$header<br><br>";
echo "<b>Response Body</b><br>$body";
Response
$_POST = array(5) { ["formFields_Complaint_Type"]=> string(9) "1-GM2-226"
["formFields_Descriptor_1"]=> string(10) "1-GM3-3085"
["formFields_Descriptor_2"]=> string(9) "1-GM4-903"
["formFields_Date/Time_of_Occurrence"]=> string(0) "" ["_target1"]=> string(1) " " }
Request Header:
POST <relative address> HTTP/1.1 Host: <url>
Cookie:
JSESSIONID=mDMJZQdLV4bhvJQ6vPyQvxqHVTynGS3byBnYsTpjDvY1xBnB93R8!-759339305!-1867032216 Accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Encoding:gzip, deflate, br
Accept-Language:en-US,en;q=0.8
Connection:keep-alive
User-Agent:Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36
Cache-Control:max-age=0 Upgrade-Insecure-Requests:1
Origin: <url>
Content-Length: 633
Expect: 100-continue
Content-Type:multipart/form-data; boundary=----
WebKitFormBoundarybdBepqnmjSF86t50; boundary=------------------------
f8e2ad22b9bb626c
best guess: your (biggest, code-breaking, but not only) problem is that the target server supports only application/x-www-form-urlencoded-encoded POST requests, but your curl code converts both application/x-www-form-urlencoded-encoded requests, and multipart/form-data requests to multipart/form-data, regardless of what the client used. (this is because PHP transparently translates both of them to an equal native PHP array called $_POST)
this will use multipart/form-data encoding:
curl_setopt($ch, CURLOPT_POSTFIELDS, $_POST);
this will use application/x-www-form-urlencoded encoding:
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($_POST));
you must decide which encoding to use, based on $_SERVER["HTTP_CONTENT_TYPE"];
and if its neither of those (for example, if its application/json), you must add special code to handle each, and you should probably error out whenever $_SERVER["HTTP_CONTENT_TYPE"]; is not 1 of the types you have made a special case for (like raw $_POST for multipart, and http_build_query($_POST) x-www-form-urlencoded)
also you're not forwarding arbitrary http headers, you should probably add some code for that
and if you really need to support Upgrade-Insecure-Requests:1 header, you need to implement specific code to handle that at the proxy side (go read the http specs on the subject - https://www.w3.org/TR/upgrade-insecure-requests/ )
and you say to the target that you accept Accept-Encoding:gzip, deflate, br , but provide no code to decode any of them, so it will look like garbage binary data to the client if the target server decide to use any of them (curl can decode them for you though, using CURLOPT_ENCODING, if libcurl was compiled with gzip and deflate and br support. i've never seen a libcurl with br support, and i bet your curl doesn't have it. probably have gzip/deflate support compiled-in though)
I have this cURL code in php.
curl_setopt($ch, CURLOPT_URL, trim("http://stackoverflow.com/questions/tagged/java"));
curl_setopt($ch, CURLOPT_PORT, 80); //ignore explicit setting of port 80
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_ENCODING, "");
curl_setopt($ch, CURLOPT_HTTPHEADER, $v);
curl_setopt($ch, CURLOPT_VERBOSE, true);
The contents of HTTPHEADER are ;
Proxy-Connection: Close
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1017.2 Safari/535.19
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Encoding: gzip,deflate,sdch
Accept-Language: en-US,en;q=0.8
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3
Cookie: __qca=blabla
Connection: Close
Each of them individual items in the array $v.
When I upload the file on my host and run the code, what I get is :
400 Bad request
Your browser sent an invalid request.
But when I run it on my system using command line PHP, what I get is this and the full page.
< HTTP/1.1 200 OK
< Vary: Accept-Encoding
< Cache-Control: private
< Content-Type: text/html; charset=utf-8
< Content-Encoding: gzip
< Date: Sat, 03 Mar 2012 21:50:17 GMT
< Connection: close
< Set-Cookie: buncha cokkies; path=/; HttpOnly
< Content-Length: 22151
<
* Closing connection #0
.
It's not only on stackoverflow, this happens, it happens also on 4shared, but works on google and others.
Thanks for any help.
Your empty CURLOPT_ENCODING argument is causing the issue. If you don't want gzip/deflate, simply omit the header.
I also see you're defining encoding both in your curl_setopt() and in the HTTP_HEADER array.
You should use native curl_setopt() commands when possible. CURLOPT_USERAGENT is one you can move out of your HTTP_HEADER array.
But as Andrew Marshall mentioned, screen-scraping isn't something you should be doing; especially since they have an API.
EDIT
Here's the sample script I'm using:
<?php
$v = Array(
'Proxy-Connection: Close',
'User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1017.2 Safari/535.19',
'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
'Accept-Language: en-US,en;q=0.8',
'Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3',
'Cookie: __qca=blabla',
'Connection: Close'
);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, trim("http://stackoverflow.com/questions/tagged/java"));
//curl_setopt($ch, CURLOPT_PORT, 80); //ignore explicit setting of port 80
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
//curl_setopt($ch, CURLOPT_ENCODING, "");
curl_setopt($ch, CURLOPT_HTTPHEADER, $v);
curl_setopt($ch, CURLOPT_VERBOSE, true);
echo curl_exec($ch);
?>
Now I'm running this via command-line, but the net effect is the same. I removed the Accept-Encoding in the $v array simply so I could get un-compressed output.
The one thing we haven't established is your PHP and libcurl versions. For me, this is PHP 5.3.2 with libcurl 7.12.1. This can be important. You can find your libcurl version either by php -i | grep -i curl on the command line, or phpinfo() via a web-based script on your server.
It seems some header is breaking the expected request pattern on some sites. The easiest way to fix this would be to remove the headers one by one and test.
I think it should be the encoding one.
It seems the "Host" header is missing:
Host: stackoverflow.com