Getting content body from http post using php CURL - php

I am trying to debug an http post the I am trying to send from list application. I have been able to send the correct post from php CURL which corectly interfaces with my drupal 7 website and uploads an image.
In order to get this to work in my lisp application I really need to see the content body of my http post I have been able to see the headers using a call like this:
curl_setopt($curl, CURLOPT_STDERR, $fp);
curl_setopt($curl, CURLOPT_VERBOSE, 1);
and the headers look the same in my lisp application but I have been unable to examine the body of the post. I have searched online and other people have asked this question but no one posted a response.
The content type of my http post is:
application/x-www-form-urlencoded
I have also tried many http proxy debuging tools but they only ever the http GET to get my php page but never capture the get sent from server once the php code is executed.
EDIT: I have added a code snipet showing where I actually upload the image file.
// file
$file = array(
'filesize' => filesize($filename),
'filename' => basename($filename),
'file' => base64_encode(file_get_contents($filename)),
'uid' => $logged_user->user->uid,
);
$file = http_build_query($file);
// REST Server URL for file upload
$request_url = $services_url . '/file';
// cURL
$curl = curl_init($request_url);
curl_setopt($curl, CURLOPT_HTTPHEADER, array('Content-type: application/x-www-form-urlencoded'));
curl_setopt($curl, CURLOPT_STDERR, $fp);
curl_setopt($curl, CURLOPT_VERBOSE, 1);
curl_setopt($curl, CURLOPT_POST, 1); // Do a regular HTTP POST
curl_setopt($curl, CURLOPT_POSTFIELDS, $file); // Set POST data
curl_setopt($curl, CURLOPT_HEADER, FALSE); // Ask to not return Header
curl_setopt($curl, CURLOPT_COOKIE, "$cookie_session"); // use the previously saved session
curl_setopt($curl, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($curl, CURLOPT_FAILONERROR, TRUE);
curl_setopt_array($curl, array(CURLINFO_HEADER_OUT => true) );
$response = curl_exec($curl);

CURLOPT_VERBOSE should actually show the details. If you're looking for the response body content, you can also use CURLOPT_RETURNTRANSFER, curl_exec() will then return the response body.
If you need to inspect the request body, CURLOPT_VERBOSE should give that to you but I'm not totally sure.
In any case, a good network sniffer should give you all the details transparently.
Example:
$curlOptions = array(
CURLOPT_RETURNTRANSFER => TRUE,
CURLOPT_FOLLOWLOCATION => TRUE,
CURLOPT_VERBOSE => TRUE,
CURLOPT_STDERR => $verbose = fopen('php://temp', 'rw+'),
CURLOPT_FILETIME => TRUE,
);
$url = "http://stackoverflow.com/questions/tagged/java";
$handle = curl_init($url);
curl_setopt_array($handle, $curlOptions);
$content = curl_exec($handle);
echo "Verbose information:\n", !rewind($verbose), stream_get_contents($verbose), "\n";
curl_close($handle);
echo $content;
Output:
Verbose information:
* About to connect() to stackoverflow.com port 80 (#0)
* Trying 64.34.119.12...
* connected
* Connected to stackoverflow.com (64.34.119.12) port 80 (#0)
> GET /questions/tagged/java HTTP/1.1
Host: stackoverflow.com
Accept: */*
< HTTP/1.1 200 OK
< Cache-Control: private
< Content-Type: text/html; charset=utf-8
< Date: Wed, 14 Mar 2012 19:27:53 GMT
< Content-Length: 59110
<
* Connection #0 to host stackoverflow.com left intact
<!DOCTYPE html>
<html>
<head>
<title>Newest 'java' Questions - Stack Overflow</title>
<link rel="shortcut icon" href="http://cdn.sstatic.net/stackoverflow/img/favicon.ico">
<link rel="apple-touch-icon" href="http://cdn.sstatic.net/stackoverflow/img/apple-touch-icon.png">
<link rel="search" type="application/opensearchdescription+xml" title="Stack Overflow" href="/opensearch.xml">
...

Just send it to a random local port and listen on it.
# terminal 1
nc -l localhost 12345
# terminal 2
php -e
<?php
$curl = curl_init('http://localhost:12345');
// etc

If you're talking about viewing the response, if you add curl_setopt( $curl, CURLOPT_RETURNTRANSFER, true );, then the document returned by the request should be returned from your call to curl_exec.
If you're talking about viewing the postdata you are sending, well, you should be able to view that anyway since you're setting that in your PHP.
EDIT: Posting a file, eh? What is the content of $file? I'm guessing probably a call to file_get_contents()?
Try something like this:
$postdata = array( 'upload' => '#/path/to/upload/file.ext' );
curl_setopt( $curl, CURLOPT_POSTFIELDS, $postdata );
You can't just send the file, you still need a postdata array that assigns a key to that file (so you can access in PHP as $_FILES['upload']). Also, the # tells cURL to load the contents of the specified file and send that instead of the string.

You were close:
The PHP manual instructs that you must call the constant CURLINFO_HEADER_OUT in both curl_setopt and curl_getinfo.
$ch = curl_init($url);
... other curl options ...
curl_setopt($ch,CURLINFO_HEADER_OUT,true);
curl_exec(ch);
//Call curl_getinfo(*args) after curl_exec(*args) otherwise the output will be NULL.
$header_info = curl_getinfo($ch,CURLINFO_HEADER_OUT); //Where $header_info contains the HTTP Request information
Synopsis
Set curl_setopt
Set curl_getinfo
Call curl_getinfo after curl_exec

I think you're better off doing this with a proxy than in the PHP. I don't think it's possible to pull the raw POST data from the PHP CURL library.
A proxy should show you the request and response contents

To get the header the CURLINFO_HEADER_OUT flag needs to be set before curl_exec is called.
Then use curl_getinfo with the same flag to get the header after curl_exec.
If you want to see the post data, grab the value you set at CURLOPT_POSTFIELDS
For example:
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "http://example.com/webservice");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($payload));
curl_setopt($ch, CURLINFO_HEADER_OUT, true);
curl_exec($ch);
$header = curl_getinfo($ch, CURLINFO_HEADER_OUT);
curl_close($ch);
echo "Request-Header:\r\n" . $header . "\r\n";
echo "Request-Body(URL Encoded):\r\n" . http_build_query($payload) . "\r\n";
echo "Request-Body(Json Encoded):\r\n" . json_encode($payload) . "\r\n";

Related

Curl PHP GET request - 504

I'm trying to do a curl php get request to display some json data on page.
The issue that I'm having here is that I keep getting hit with a 504 gateway timeout.
So I was hopping to get a second pair of eyes on my code to make sure I'm not doing anything silly or missing something.
// get request
$ch = curl_init('http://*****');
$token = '****';
// Return Data
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLINFO_HEADER_OUT, true);
//User Agent
curl_setopt($ch, CURLOPT_USERAGENT, 'Fiddler');
//Set your auth headers
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
'Host: ****:8090',
'Content-Type: application/json',
'Authorization: Bearer '.$token
));
$data = curl_exec($ch);
$info = curl_getinfo($ch);
// print details of request on page
echo 'info:' . $info ;
// close curl resource to free up system resources
curl_close($ch);
Issue was that the host's firewalls were blocking requests to certain ports and I had to get them to unblock the ports in order for it to work.
You have an error in headers, Host must contain only the hostname Host: *****:8090.
It must be like this one : Host: google.com.
The port must be specified using curl_setopt (), like this:
curl_setopt($ch, CURLOPT_PORT, 8090);

file_get_contents fails via php, works via browser

What I'm trying to achieve:
Get request to an API Endpoint, retrieving an XML and subsequently parse the results.
I am sending a file_get_contents request to achieve this.
Issues:
`file_get_Contents` fails, error:
Warning: file_get_contents(https://api.twitter.com/1.1/statuses/mentions_timeline.json):
failed to open stream:
A connection attempt failed because the connected party did not properly
respond after a period of time, or established connection failed because
connected host has failed to respond.
Update 17/08
To consolidate my current understanding:
1. PHP FAILS:
1.a it fails via php (timeout)
1.b it fails via command line (curl -G http://api.eve-central.com/api/quicklook?typeid=34)
1.c file_get_contents
1.d file_get_contents w/ create_stream_context
2. What WORKS:
2.a Pasting the url in a chrome tab
2.b via postman
What has been attempted:
- Check Headers in Postman ,and try to replicate them via php
Postman Headers sent back by eve-central:
Access-Control-Allow-Origin → *
Connection → Keep-Alive
Content-Encoding → gzip
Content-Type → text/xml; charset=UTF-8
Date → Wed, 17 Aug 2016 10:40:24 GMT
Proxy-Connection → Keep-Alive
Server → nginx
Transfer-Encoding → chunked
Vary → Accept-Encoding
Via → HTTP/1.1 proxy10014
Corresponding Code:
$headers = array(
'method' => 'GET',
'header' => 'Connection: Keep-Alive',
'header' => 'Content-Encoding: gzip',
'header' => 'Content-Type: text/xml',
'header' => 'Proxy-Connection: Keep-Alive',
'header' => 'Server: nginx',
'header' => 'Transfer-Encoding: chunked',
'header' => 'Vary: Accept-Encoding',
'header' => 'Via: HTTP/1.1 proxy10014');
curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true );
curl_setopt($curl, CURLOPT_PORT , 8080); // Attempt at changing port in the event it was blocked.
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);
curl_setopt($curl, CURLOPT_POST, false );
curl_setopt($curl, CURLOPT_URL, $url );
$resp = curl_exec($curl);
if(curl_error($curl))
{
echo 'error:' . curl_error($curl);
}
Use Wireshark to capture the GET request to see if changing the port helped
Run cUrl via command line
I'm out of ideas and option.
So the questions are:
If it works in a browser, and in Postman, why does it not work via PHP ?
How can I modify my code so that it mimics what Postman does? ?
Previous Attempts
What I have tried:
Various cURL options from other threads, such as
function curl_get_contents($url) {
$ch = curl_init();
if (!$ch)
{
die("Couldn't initialize a cURL handle");
} else
echo "Curl Handle initialized ";
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.1.4322)');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
curl_setopt($ch, CURLOPT_TIMEOUT, 5);
$data = curl_exec($ch);
// Check if any error occurred
if (!curl_errno($ch))
{
$info = curl_getinfo($ch);
echo 'Took ', $info['total_time'], ' seconds to send a request to ', $info['url'], "";
displayData($info);
} else
echo "Failed Curl, reason: ".curl_error($ch)." ";
curl_close($ch);
return $data;
}
result: nothing, no data returned.
- Checked php.ini options:
- allow_fopen is On
- allow_url_include = on
- relevant ssl extensions are enabled
- Raised the timeout window
- both via php.ini
- also via explicit declaration within the php file.
- Tried with a different url
- same error, so it doesn't really depends on my particular endpoint
- for example, both twitter/wikipedia/google return the specific error
- tried with:
- file_get_contents on a local xml file (https://msdn.microsoft.com/en-us/library/ms762271(v=vs.85).aspx) --> works
- file_get_contents on a remote xml file (http://www.xmlfiles.com/examples/note.xml) --> fails same error
- Overall, the following is true, so far:
- Curl fails, timeout
- file_get_Contents fails, timeout
- Open XML file url in a browser works
- Make a GET request via Postman, works
Obviously, in all cases where the file_get_contents fails via php, I can easily access the file via any browser.
Tried to work around the issue.
Attempt 1:
Use nitrous.io, create a LAMP stack, perform the deed via the platform
results: file_get_contents works, however, due to the large number of xml files to be retrieved, the operation times-out.
Tentative solution:
- Download XML files from source
- Zip them
- Download xml_file
- Locally parse said xml files
Later on, write a small php scripts that, when invoked, performs the bits above, sends the data to the local directory, which then unpacks it and performs additional work on it.
Another attempt would be to use Google Sheets, with a user function that pulls the data into the sheet, and just dump the excel file / values into mysql.
For my purposes, while an awfully ignorant solution, it does the trick.
Code used for avoiding timeout issue on shared host:
function downloadUrlToFile2($url, $outFileName)
{
//file_put_contents($xmlFileName, fopen($link, 'r'));
//copy($link, $xmlFileName); // download xml file
;
echo "Passing $url into $outFileName ";
// $outFileName = touch();
$fp = fopen($outFileName, "w");
if(is_file($url))
{
copy($url, $outFileName); // download xml file
} else
{
$ch = curl_init();
$options = array(
CURLOPT_TIMEOUT => 28800, // set this to 8 hours so we dont timeout on big files
CURLOPT_URL => $url
);
curl_setopt($ch, CURLOPT_FILE, $fp);
curl_setopt_array($ch, $options);
$contents = curl_exec($ch);
fwrite($fp, $contents);
curl_close($ch);
}
}
I have also added this on top of the ini script:
ignore_user_abort(true);
set_time_limit(0);
ini_set('memory_limit', '2048M');
I see some issue with HTTPS url request, for fix issue you have to add below lines in your CURL request
function curl_get_contents($url) {
$ch = curl_init();
$header[0] = "Accept: text/xml,application/xml,application/xhtml+xml,";
$header[0] .= "text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5";
$header[] = "Cache-Control: max-age=0";
$header[] = "Connection: keep-alive";
$header[] = "Keep-Alive: 300";
$header[] = "Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7";
$header[] = "Accept-Language: en-us,en;q=0.5";
$header[] = "Pragma: ";
curl_setopt( $ch, CURLOPT_HTTPHEADER, $header );
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_URL, $url);
// I have added below two lines
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
$data = curl_exec($ch);
curl_close($ch);
return $data;
}

Slack PHP API - Avoid Timeout error

I am trying to use Slack Custom command and not pretty sure how to use delayed messages since the Yoda Speak External API takes more than 3 seconds to respond.
I have done the following:
Sent the slack command /Yoda in my case and received the reponse_url.
Used the following to post the following to the response URL.
$data_string = '{"response_type": "in_channel", "text":"Checking,please wait..."}' ;
$chs = curl_init();
curl_setopt($chs, CURLOPT_URL, $response_url);
curl_setopt($chs, CURLOPT_POST, true);
curl_setopt($chs, CURLOPT_POSTFIELDS, $data_string);
curl_setopt($chs, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($chs, CURLOPT_SSL_VERIFYHOST, FALSE);
curl_setopt($chs, CURLOPT_RETURNTRANSFER, true);
curl_setopt($chs, CURLOPT_POST, 1);
curl_setopt($chs, CURLOPT_HTTPHEADER, array('Content-Type:application/json'));
$results = curl_exec($chs);
Now, when I call the Yoda API, it gives the following error "Timeout was reached". I read about delayed responses but not sure how should I proceed from here.
$chsres = curl_init();
curl_setopt($chsres, CURLOPT_URL, "https://yoda.p.mashape.com/yoda?sentence=welcome+to+stack");
curl_setopt($chsres, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($chsres, CURLOPT_SSL_VERIFYHOST, FALSE);
curl_setopt($chsres, CURLOPT_VERBOSE, true);
curl_setopt($chsres, CURLOPT_TIMEOUT, 45);
curl_setopt($chsres, CURLOPT_RETURNTRANSFER, true);
curl_setopt($chsres, CURLOPT_HTTPHEADER, array('Content-Type:application/json', "X-Mashape-Key:> deMeGoBfMvmshQSemozTqJEY9z0jp1eIhuAjsnx9cQAQsHUifD"));
$resultchsres = curl_exec($chsres);
echo $resultchsres;
Can someone please let me know how to get rid of the timeout error using delayed responses?
UPDATED CODE:
$response_url = $_POST['response_url'];
$text = $_POST['text'];
$term = str_replace(' ', '+', $text);
//https://paypal.slack.com/services/B0VQMHX8W#service_setup
//initial respond with 200OK for timeout
ignore_user_abort(true);
set_time_limit(0);
ob_start();
echo('{"response_type": "in_channel", "text": "Checking, please wait..."}');
header($_SERVER["SERVER_PROTOCOL"] . " 200 OK");
header("Content-Type: application/json");
header('Content-Length: '.ob_get_length());
ob_end_flush();
ob_flush();
flush();
$chsres = curl_init();
curl_setopt_array($chsres, array(
CURLOPT_URL => "https://yoda.p.mashape.com/yoda?sentence=$term",
CURLOPT_SSL_VERIFYPEER => FALSE,
CURLOPT_SSL_VERIFYHOST => FALSE,
CURLOPT_VERBOSE => true,
CURLOPT_RETURNTRANSFER => FALSE,
CURLOPT_HTTPHEADER => array('Content-Type:application/json', "X-Mashape-Key: deMeGoBfMvmshQSemozTqJEY9z0jp1eIhuAjsnx9cQAQsHUifD"),
CURLOPT_RETURNTRANSFER => true
));
$yodaresponse = curl_exec($chsres);
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_URL => $response_url,
CURLOPT_POST => 1,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POSTFIELDS => $yodaresponse
));
$resp = curl_exec($curl);
var_dump($resp);
curl_close($curl);
I still get the same error "Darn – that slash command didn't work (error message: Timeout was reached). Manage the command at slash-command"
You're doing all the right things, just need to change the order.
Respond to the original request with a 200 OK response immediately. See this answer for details, but essentially:
ignore_user_abort(true);
ob_start();
echo('{"response_type": "in_channel", "text": "Checking, please wait..."}');
header($_SERVER["SERVER_PROTOCOL"] . " 200 OK");
header("Content-Type: application/json");
header('Content-Length: '.ob_get_length());
ob_end_flush();
ob_flush();
flush();
Then make the Yoda API request using curl, as you're doing
Once you have the Yoda results, send them to Slack at $response_url using curl, as you're doing.
If you're using FPM then this is what you want - http://php.net/manual/en/function.fastcgi-finish-request.php
Your code would then look like this...
<?php
$response_url = $_POST["response_url"];
$term = rawurlencode($_POST["text"]);
error_log("POST: " . print_r($_POST, 1));
$response = ["response_type"=>"in_channel", "text"=>"Checking, please wait..."];
echo json_encode($response);
header("Content-Type: application/json");
fastcgi_finish_request();
$ch = curl_init();
...
Another approach that will work is to use a curl request with a short timeout to spawn a second PHP script. Since my provider has put some restrictions on my PHP environment (e.g. no process spawning) this has been the only approach that has worked for me.
The first script will terminate shortly after and send an HTTP OK back to Slack. The second script will continue running, handle the time consuming processing (e.g. calling external APIs) and finally send the result as delayed response to the response_url.
1st script
This is the curl request in your first script:
<?php>
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "second.php?redirect_url=$redirect_url");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_TIMEOUT_MS, 400); //just some very short timeout
curl_setopt($ch, CURLOPT_NOSIGNAL, 1);
curl_exec($ch);
curl_close($ch);
/* send short response back to user, e.g. "Processing your request..." */
?>
The length of the timeouts is arbitrary, however in my tests a very short timeout (e.g. 10ms) did not work.
You will also need to implement a way to transfer input data between the two scripts as illustrated with passing the request_url as URL parameter.
Finally for slash commands Slack requires you to send a short response back to the user.
2nd script
This is how your 2nd script looks like:
<?php
ignore_user_abort(true); //very important!
usleep (500000); //to ensure 2nd script responds after 1st
/* call external API */
/* send response back to Slack using response_url */
?>
The statement ignore_user_abort(true); is mandatory to ensure your 2nd script keeps running after the curl timeout.
The usleep with 0.5 secs is to ensure that the 2nd script responds after the first, but not mandatory for this solution to work.
The example is based on one answer of the "Continue PHP execution after sending HTTP response" question.
From what I can see in the documentation, you're doing things mostly correctly. Just by echoing anything out, you're already passing a 200 OK message, so no need to do it explicitly. You should check to make sure this isn't a server problem though; is the URL being posted to valid? Not getting mangled by a rewrite rule along the way?
I've made some changes to your code below, including some debugging that will go to your error log (i.e. Apache's error log, by default.) Give it a try, and at the very least you'll have some more debugging details.
<?php
$response_url = $_POST["response_url"];
$term = rawurlencode($_POST["text"]);
error_log("POST: " . print_r($_POST, 1));
ob_end_clean();
ob_start();
$response = ["response_type"=>"in_channel", "text"=>"Checking, please wait..."];
echo json_encode($response);
header("Content-Type: application/json");
header("Content-Length: " . ob_get_size());
ob_end_flush();
flush();
$ch = curl_init();
curl_setopt_array($ch, [
CURLOPT_URL => "https://yoda.p.mashape.com/yoda?sentence=$term",
CURLOPT_HTTPHEADER => ["X-Mashape-Key: deMeGoBfMvmshQSemozTqJEY9z0jp1eIhuAjsnx9cQAQsHUifD"],
CURLOPT_RETURNTRANSFER => true
]);
$yodaresponse = curl_exec($ch);
curl_close($ch);
error_log("Yoda response: $yodaresponse");
$yodajson = json_encode([
"response_type"=>"in_channel",
"text"=>$yodaresponse
]);
$ch = curl_init();
curl_setopt_array($ch, [
CURLOPT_URL => $response_url,
CURLOPT_POST => 1,
CURLOPT_HTTPHEADER => ["Content-Type: application/json"],
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POSTFIELDS => $yodajson
]);
$resp = curl_exec($ch);
curl_close($ch);
error_log("API response: $resp");
Posting an answer as I don't have enough reputation to post comments...
I've had the same problem, and then I realized that Slack treats requests and responses differently. Specifically, HTTP request and response differ in their first line.
HTTP request example:
GET /hello.htm HTTP/1.1
User-Agent: Mozilla/4.0 (compatible; MSIE5.01; Windows NT)
Host: www.tutorialspoint.com
Accept-Language: en-us
Accept-Encoding: gzip, deflate
Connection: Keep-Alive
HTTP response example:
HTTP/1.1 200 OK
Date: Mon, 27 Jul 2009 12:28:53 GMT
Server: Apache/2.2.14 (Win32)
Last-Modified: Wed, 22 Jul 2009 19:15:56 GMT
Content-Length: 11
Content-Type: text/xml
Connection: Closed
hello there
If you can access raw bytes to be sent in PHP (never used PHP, so not familiar), just make it look like a response, rather than a request. Otherwise, send a response immediately, then do the work that you need, and send a request with the new message. This can be done in number of ways, one of which was outlined by #miken32, I opted out for invoking a background process in python.

PHP HTTP POST Request

I need to send an XML string via HTTP POST to another server using the settings below...
POST /xmlreceive.asmx/CaseApplicationZipped HTTP/1.1
Host: www.dummyurl.co.uk
Content-Type: application/x-www-form-urlencoded
Content-Length: length
XMLApplication=XMLstring&byArray=base64string
I'm guessing I need to set this up via cURL or maybe fsockopen.
I've tried the following but not having any luck at getting it to work.
$url = "http://www.dummyurl.co.uk/XMLReceive.asmx/CaseApplicationZipped";
$headers = array(
"Content-Type: application/x-www-form-urlencoded"//,
);
$post = http_build_query(array('XMLApplication' => $XML, 'byArray' => $base64));
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $post);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
curl_close($ch);
echo "response: ".$response;
The remote server gives the following response...
"Object reference not set to an instance of an object."
Not enough rep yet to comment, so I'll post this as an answer.
PHP's cURL automatically send the Host (from $url) and the Content-Length headers, so you don't need to specify those manually.
A handy function exists for building the $post string: http_build_query. It'll handle properly encoding your POST body. It would look something like
$post = http_build_query(array('XMLApplication' => $XML, 'byArray' => $base64));
If you want to log out the headers you received, check the curl_getopt function.
As for the error you received, it seems like you're passing the remote site things it doesn't expect. I can't speak for what you're passing or what the site's expecting, but Input string was not in a correct format seems to imply that your $XML is not formatted correctly, or is being passed as an incorrect parameter.

PHP cURL Content-Length and Content-Type wrong

I'm trying to login to a site via PHP cURL and I'm only getting "Bad Request" responses.
I played around with hosts file and set it to my server to check which Request Headers my browser sends and compare it to the request headers sent by cURL.
Everything is equal, except of:
Browser:
Content-Type: application/x-www-form-urlencoded
Content-Length: 51
PHP cURL:
Content-Length: 51, 359
Content-Type: application/x-www-form-urlencoded; boundary=----------------------------5a377b7e6ba7
I already set that values with this command, but it still sends the wrong headers:
curl_setopt($this->hCurl, CURLOPT_HTTPHEADER, array(
'Expect:',
'Content-Type: application/x-www-form-urlencoded',
'Content-Length: 51'
));
You shouldn't have to set the content-length yourself. If you use cURL to send an HTTP POST, it will calculate the content length for you.
If you set the CURLOPT_POSTFIELDS value as an array, it will automatically submit the request as multipart/form-data and use a boundary. If you pass a string, it will use application/x-www-form-urlencoded so make sure you pass a urlencoded string to CURLOPT_POSTFIELDS and not an array since you want form-urlencoded.
You need to be doing this:
$data = 'name=' . urlencode($value) . '&name2=' . urlencode($value2);
curl_setopt($this->hCurl, CURLOPT_POSTFIELDS, $data);
// NOT
$dataArray = array('name' => 'value', 'name2' => 'value2');
curl_setopt($this->hCurl, CURLOPT_POSTFIELDS, $dataArray);
In either case, you do not need to set the content length, but you have to use the first method to get application/x-www-form-urlencoded encoding on the form.
If that doesn't help, post all the code relevant to setting up the curl request, (all the options, and data you are passing to it) and that should help solve the problem.
EDIT:
Added is an example I came up with that works (I get failed login).
<?php
$URL_HOME = 'http://ilocalis.com/';
$LOGIN_URL = 'https://ilocalis.com/login.php';
$ch = curl_init($URL_HOME);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
$home = curl_exec($ch);
//echo $home;
$post = array('username' => 'drew', 'password' => 'testing 123');
$query = http_build_query($post);
curl_setopt($ch, CURLOPT_URL, $LOGIN_URL);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $query);
$login = curl_exec($ch);
echo $login;

Categories