I am trying to communicate with anREST API using cURL and PHP. But, I am getting an issue from the API and I need to be able to see my HTTP request in plain text where I can analyses it and correct it.
I tried the following to write my request to a file
$file = fopen('request.txt', 'w');
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_VERBOSE, true);
curl_setopt($ch, CURLOPT_STDERR, $file);
But this does not show me the JSON data.
Here is what I get in the request.txt file
* Hostname servername was found in DNS cache
* Trying INTERNAL IP...
* Connected to servername (INTERNAL IP) port 8018 (#0)
> PUT /icws/1163386002/messaging/subscriptions/queues/blahblah HTTP/1.1
Host: servername:8018
Accept: */*
ININ-ICWS-CSRF-Token: WAhtYWxoYXlla1dBY2GHSDMNDFtjMDcwZmIyYy1mguc4LTQ3YjEtODgzMy1iOTBkM2ZhYWHfoyNmYTlYCjEwLjAuNC4xNjA=
ININ-ICWS-Session-ID: 1163386002
Cookie: icws_1163386002=232sggsdfgdabe-404c-8d8c-12345dfgdfg
Content-Length: 156
Content-Type: application/x-www-form-urlencoded
* upload completely sent off: 156 out of 156 bytes
< HTTP/1.1 500 Internal Server Error
< Cache-Control: no-cache, no-store, must-revalidate
< Pragma: no-cache
< Expires: 0
< Access-Control-Allow-Origin: *
< Access-Control-Allow-Credentials: true
< Content-Type: application/vnd.inin.icws+JSON; charset=utf-8
< Date: Tue, 12 May 2015 17:52:52 GMT
< Server: HttpPluginHost
< Content-Length: 90
<
* Connection #0 to host servername left intact
I would like to see the JSON string in plain text.
Here is how I am doing my cURL call using PHP
private function _processRequest($method, $uri, $data = false, $header = NULL, &$httpRespond = array(), &$httpCode = NULL)
{
$ch = curl_init();
$url = $this->_baseURL . $uri;
if(
($method == 'POST' || $method == 'PUT')
&& $data
){
$jsonString = json_encode( $data );
curl_setopt( $ch, CURLOPT_POSTFIELDS, $jsonString );
}
if($method == 'POST'){
curl_setopt($ch, CURLOPT_POST, true);
} elseif( $method == 'PUT'){
//curl_setopt($ch, CURLOPT_PUT, true);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'PUT');
} else {
if ($data){
$url = sprintf("%s?%s", $url, http_build_query($data));
}
}
//disable the use of cached connection
curl_setopt($ch, CURLOPT_FRESH_CONNECT, true);
//return the respond from the API
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
//return the HEADER respond from the API
curl_setopt($ch, CURLOPT_HEADER, true);
//add custom headers
if(!empty($header)){
curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
}
//enable SSL
if( $this->_protocol == 'https' ){
curl_setopt($ch, CURLOPT_CAINFO, $this->_cainfo);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, true);
}
//set the URL
curl_setopt($ch, CURLOPT_URL, $url);
$file = fopen('request.txt', 'w');
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_VERBOSE, true);
curl_setopt($ch, CURLOPT_STDERR, $file);
$respond = curl_exec($ch);
//throw cURL exception
if($respond === false){
$errorNo = curl_errno($ch);
$errorMessage = curl_error($ch);
throw new ApiException($errorMessage, $errorNo);
}
list($header, $body) = explode("\r\n\r\n", $respond, 2);
$httpRespond = $this->_http_parse_headers($header);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$result = json_decode($body, true);
return $result;
}
How do I see the entire HTTP request in a plain text?
You can use Fiddler (http://www.telerik.com/fiddler) to see your complete request/response in plain text and to test your REST API as well.
Also, you can use Wireshark (https://www.wireshark.org/) applying a HTTP filter.
My recommendation is Fiddler, I use it a lot to test and debug my REST API.
Hope this helps
Related
I'm trying to build a custom accounting report using the PayPal NVP API that will get all transactions for a specific date range.
My code:
$headers = array(
'USER' => $production_user,
'PWD' => $production_pass,
'SIGNATURE' => $production_sig
);
$nvp = array(
'METHOD' => 'TransactionSearch',
'TRANSACTIONCLASS' => 'RECEIVED',
'STARTDATE' => '2016-12-01T00:00:00Z',
'ENDDATE' => '2016-12-31T00:00:00Z'
);
$request_url = "https://api-3t.paypal.com/nvp?".http_build_query($nvp);
$curl = curl_init($request_url);
curl_setopt($curl, CURLOPT_FAILONERROR, true);
curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($curl, CURLOPT_HEADER, $headers);
curl_setopt($curl, CURLOPT_POST, 1);
$result = curl_exec($curl);
$result = explode("&", $result);
foreach($result as $f=>$v){
$t = explode("=", $v);
echo $t[0]." => ".urldecode($t[1]);
echo "<br>";
}
Here is what gets printed:
HTTP/1.1 200 OK Date: Fri, 10 Feb 2017 19:51:20 GMT Server: Apache X-PAYPAL-OPERATION-NAME: X-PAYPAL-API-RC: 10001 Connection: close Cache-Control: max-age => 0, no-cache, no-store, must-revalidate Pragma: no-cache HTTP_X_PP_AZ_LOCATOR: slcb.slc Paypal-Debug-Id: 484a759b46e4a Set-Cookie: X-PP-SILOVER
CORRELATIONID => some_random_characters
ACK => Failure
L_ERRORCODE0 => 10001
L_SHORTMESSAGE0 => Internal Error
L_LONGMESSAGE0 => Timeout processing request
Any assistance with this issue would be greatly appreciated!
You are using a post request and have not post data.
I do not know what PayPal wants to see but I'm guessing it's not what you are sending.
Some things to try:
If you need to pass the USER, PWD, and SIGNATURE in the Request Header do it like this:
$request = array();
$request[] = "USER: $production_user";
$request[] = "PWD: $production_pass";
$request[] = "SIGNATURE: $production_sig";
curl_setopt($ch, CURLOPT_HTTPHEADER, $request);
If the $nvp parameters need to be post data, try this:
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $nvp);
The $nvp can be passed as a query string in the post data also.
$query = http_build_query($nvp);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $query);
The difference is the Content-Type.
The first method:
Content-Type: application/x-www-form-urlencoded
The second method:
Content-Type: multipart/form-data
To help in trouble shooting it would be good to see both the request and response header.
Use these options to get the headers:
curl_setopt($ch, CURLOPT_VERBOSE, true);
curl_setopt($ch, CURLINFO_HEADER_OUT, true);
The Request Header will be in the 'curl_getinfo()'
curl_setopt($ch, CURLOPT_HEADER, true);
$result = curl_exec($ch);
$info = curl_getinfo($ch);
var_export($info);
The above gives lots of other details of the request. If you only want to see the header:
$request = curl_getinfo($ch, CURLINFO_HEADER_OUT);
To get the response header:
$result = curl_exec($ch);
$skip = intval(curl_getinfo($ch, CURLINFO_HEADER_SIZE));
$response = substr($result ,0,$skip);
$result = substr($result ,$skip);
I am trying to communicate with an API using cURL Calls.
I am trying to see the exact request that I am sending to the API "including the header, the body and the fields that are being posted." How can I get a copy of the request?
I tried to use curl_getinfo but that does not tell me the exact request. Then, I have added a code to print the request to a file called request.txt
here is my code which is working fine but it is not showing the fields that are being posted
function CallAPI($method, $url, $data = false, $header = array())
{
$curl = curl_init();
if(!empty($header)){
curl_setopt($curl, CURLOPT_HTTPHEADER, $header);
}
$f = fopen('request.txt', 'w');
//disable the use of cached connection
curl_setopt($curl, CURLOPT_FRESH_CONNECT, TRUE);
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($curl, CURLOPT_VERBOSE, TRUE);
curl_setopt($curl, CURLOPT_FILE, $f);
curl_setopt($curl, CURLOPT_INFILESIZE, $f);
curl_setopt($curl, CURLOPT_STDERR, $f);
switch ($method)
{
case "POST":
curl_setopt($curl, CURLOPT_POST, 1);
if ($data){
curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
}
break;
case "PUT":
curl_setopt($curl, CURLOPT_PUT, 1);
break;
default:
if ($data){
$url = sprintf("%s?%s", $url, http_build_query($data));
}
}
$result = curl_exec($curl);
$info = curl_getinfo($curl);
//print data
echo '<pre>';
print_r($info);
echo '</pre>';
curl_close($curl);
fclose($f);
return $result;
}
I am able to see something like this
* Hostname SERVERNAME was found in DNS cache
* Trying INTERNAL IP...
* Connected to SERVERNAME (INTERNAL IP) port INTERNAL PORT (#0)
> POST /icws/connection HTTP/1.1
Host: SERVERNAME:INTERNAL PORT
Accept: */*
Accept-Language: en-US
Content-Length: 517
Expect: 100-continue
Content-Type: multipart/form-data; boundary=------------------------cb7489673677d758
* Done waiting for 100-continue
< HTTP/1.1 400 Bad Request
< Cache-Control: no-cache, no-store, must-revalidate
< Pragma: no-cache
< Expires: 0
< Access-Control-Allow-Origin: *
< Access-Control-Allow-Credentials: true
< Content-Type: application/vnd.inin.icws+JSON; charset=utf-8
< Date: Mon, 04 May 2015 20:31:56 GMT
< Server: HttpPluginHost
< Content-Length: 79
* HTTP error before end of send, stop sending
<
How can I also include the field that are being sent with the request?
Running Out Of Sanity
I have looked high and low and lost a bit of my life and a lot of my sanity trying to return a cURL POST request. Everything works fine except I cannot remove the headers. Oh yes I have tried
curl_setopt($ch, CURLOPT_HEADER, false);
What worse is that when I try
$headerLength = curl_getinfo($ch, CURLINFO_HEADER_SIZE);
I get a return of 25 which is completely wrong. Please help I am at my wits end with this one.
So I call this method
$service = new RestfulService($Url1);
$response = $service->request('', 'POST', $tokenXml, null,
array(CURLOPT_SSL_VERIFYPEER => false,
CURLOPT_ENCODING =>'UTF-8'));
Which in turn calls (using SilverStripe framework)
public function curlRequest($url, $method, $data = null, $headers = null, $curlOptions = array()) {
$ch = curl_init();
$timeout = 5;
$sapphireInfo = new SapphireInfo();
$useragent = 'SilverStripe/' . $sapphireInfo->Version();
$curlOptions = $curlOptions + (array)$this->config()->default_curl_options;
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_USERAGENT, $useragent);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $timeout);
if(!ini_get('open_basedir')) curl_setopt($ch, CURLOPT_FOLLOWLOCATION,1);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $method);
//include headers in the response
curl_setopt($ch, CURLOPT_HEADER, true);
// Add headers
if($this->customHeaders) {
$headers = array_merge((array)$this->customHeaders, (array)$headers);
}
if($headers) curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
// Add authentication
if($this->authUsername) curl_setopt($ch, CURLOPT_USERPWD, $this->getBasicAuthString());
// Add fields to POST and PUT requests
if($method == 'POST') {
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
} elseif($method == 'PUT') {
$put = fopen("php://temp", 'r+');
fwrite($put, $data);
fseek($put, 0);
curl_setopt($ch, CURLOPT_PUT, 1);
curl_setopt($ch, CURLOPT_INFILE, $put);
curl_setopt($ch, CURLOPT_INFILESIZE, strlen($data));
}
// Apply proxy settings
if(is_array($this->proxy)) {
curl_setopt_array($ch, $this->proxy);
}
// Set any custom options passed to the request() function
curl_setopt_array($ch, $curlOptions);
// Run request
$rawResponse = curl_exec($ch);
if (curl_error($ch)) var_dump(curl_error($ch));
$response = $this->extractResponse($ch, $rawResponse);
curl_close($ch);
return $response;
}
When I dump the response, the remove header command only removes the first few characters. Like so...
object(RestfulService_Response)[1065]
protected 'simpleXML' => null
protected 'cachedResponse' => boolean false
protected 'statusCode' => int 100
protected 'statusDescription' => string 'Continue' (length=8)
protected 'headers' =>
array (size=0)
empty
protected 'body' => string 'ontrol: no-cache
Pragma: no-cache
Content-Length: 3593
Content-Type: application/soap+xml; charset=utf-8
Expires: Fri, 20 Sep 2013 01:14:14 GMT
Server: Microsoft-IIS/7.5
P3P: CP="DSP CUR OTPi IND OTRi ONL FIN"
X-XSS-Protection: 0
PPServer: PPV: 30 H: CO1IDOLGN62 V: 0
Date: Fri, 20 Sep 2013 01:15:13 GMT
Connection: close
�<?xml version="1.0" encoding="utf-8" ?><S:Envelope xmlns:S="http://www.w3.org/2003/05/soap-envel
Has it got anything to do with the strange character before the
Update: I have checked this code on my colleagues computer, he doesn't have any problems. I am running WAMP my colleague is on a MAC, could there be any set up issues? I have downloaded the most recent curl.dll and added it to my php library, still no cigar.
Any ideas???
In my case the encoding was incorrect I needed to add the following option
curl_setopt($ch, CURLOPT_SSLVERSION, 3)
Works fine now
I am using PHP 5.3.6 and it seems I am unable to make a PUT request using CURL for PUTting just a string.
function put_data($url, $data)
{
$useragent="SimpleAgent-1.0";
$fh = fopen('php://memory', 'rw');
fwrite($fh, $data);
rewind($fh);$ch = curl_init();
curl_setopt($ch, CURLOPT_USERAGENT, $useragent);
curl_setopt($ch, CURLOPT_INFILE, $fh);
curl_setopt($ch, CURLOPT_INFILESIZE, strlen($data));
curl_setopt($ch, CURLOPT_TIMEOUT, 10);
curl_setopt($ch, CURLOPT_PUT, 1);
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$result = curl_exec($ch);
curl_close($ch);
fclose($fh);
return $result;
}
Here, $data is the string that I want to PUT.
Doesn't work and returns the following error:
500 Internal Server Error The server has either erred or is incapable
of performing the requested operation.
expected string or buffer
I used your code so defined a url and filled the data with a string and all worked as expected. Being I was rejected by the website as there was no receiving end that could deal with a put. To get info easily just add the line
curl_setopt($ch, CURLOPT_VERBOSE, true);
and you will get something like:
* About to connect() to yyyy.xxxx.com port 80 (#0)
* Trying 62.221.196.28...
* connected
* Connected to yyyy.xxxx.com (zz.221.196.28) port 80 (#0)
> PUT / HTTP/1.1
User-Agent: SimpleAgent-1.0
Host: yyyy.xxxx.com
Accept: */*
Content-Length: 14
Expect: 100-continue
< HTTP/1.1 100 Continue
* We are completely uploaded and fine
< HTTP/1.1 405 Method Not Allowed
< Date: Thu, 09 Feb 2012 19:46:28 GMT
< Server: Apache
< Allow: GET,HEAD,POST,OPTIONS
< Vary: Accept-Encoding
< Content-Length: 231
< Content-Type: text/html; charset=iso-8859-1
<
* Connection #0 to host yyy.xxxx.com left intact
* Closing connection #0
As you can see from the logging the request went out, however when you want to put the data, the apache setting doesn't allow you to put data to that url. So depending upon the server you will have to take care of a receiving url that accepts the PUT.
I am only able to pass the array as a data with the versions I am using. So this is what I am doing now:
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "PUT");
curl_setopt($ch, CURLINFO_HEADER_OUT, TRUE);
curl_setopt($ch, CURLOPT_COOKIE, $curl_cookie);
$arr = array();
if (isset($data)) {
$arr['my_data'] = $data;
}
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($arr));
curl_exec($ch);
I have logged into a website by posting data with curl. I now want to display the page that a user would normally see after logging in but I can't because the url always changes.
http://some.example.com/niceday/foobar.php?TID=abcd
where abcd is some seemingly random number.
I've been trying to get the response headers but it keeps giving me the request headers I just sent.
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'http://example.com/niceday/dirlogin.php'); //login URL
curl_setopt ($ch, CURLOPT_POST, 1);
$postData = 'userName=scott&password=abc123& etc...';
curl_setopt($ch, CURLOPT_POSTFIELDS, $postData);
curl_setopt($ch, CURLOPT_COOKIEJAR, 'cookie.txt');
curl_setopt( $ch, CURLOPT_FOLLOWLOCATION, true );
curl_setopt( $ch, CURLOPT_ENCODING, "" );
curl_setopt( $ch, CURLOPT_AUTOREFERER, true );
curl_setopt ($ch, CURLOPT_HEADER, true);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_NOBODY, true);
$store = curl_exec($ch);
$info = curl_getinfo($ch);
print_r($info);//wrong headers are printed out
The headers for the curl_exec($ch) are shown but how do I get the response headers?
I'm not sure if it's relevant but the form where the login credentials are entered uses javascript
YOu can get the response header line this : $headers = curl_getinfo($ch); But i can't see how it will help you with your problem and then you can use http_parse_header() or explode("\n", $headers);
update :
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'http://www.mozilla.org/');
curl_setopt ($ch, CURLOPT_HEADER, true);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_NOBODY, true); // HTTP request is 'HEAD'
$headers=curl_exec($ch);
This will return only the headers.
Try this:
<?php
function my_get_headers($url ) {
$url_info=parse_url($url);
if (isset($url_info['scheme']) && $url_info['scheme'] == 'https') {
$port = 443;
#$fp=fsockopen('ssl://'.$url_info['host'], $port, $errno, $errstr, 10);
} else {
$port = isset($url_info['port']) ? $url_info['port'] : 80;
#$fp=fsockopen($url_info['host'], $port, $errno, $errstr, 10);
}
if($fp) {
stream_set_timeout($fp, 10);
$head = "HEAD ".#$url_info['path']."?".#$url_info['query'];
$head .= " HTTP/1.0\r\nHost: ".#$url_info['host']."\r\n\r\n";
fputs($fp, $head);
while(!feof($fp)) {
if($header=trim(fgets($fp, 1024))) {
$sc_pos = strpos( $header, ':' );
if( $sc_pos === false ) {
$headers['status'] = $header;
} else {
$label = substr( $header, 0, $sc_pos );
$value = substr( $header, $sc_pos+1 );
$headers[strtolower($label)] = trim($value);
}
}
}
return $headers;
}
else {
return false;
}
}
print_r( my_get_headers("http://www.mozilla.org"));
?>
OUTPUTS:
Array
(
[status] => HTTP/1.1 200 OK
[server] => Apache
[x-backend-server] => pm-web01
[content-type] => text/html; charset=UTF-8
[date] => Mon, 15 Aug 2011 14:26:16 GMT
[keep-alive] => timeout=20, max=999
[expires] => Mon, 15 Aug 2011 00:36:16 GMT
[connection] => close
[x-powered-by] => PHP/5.2.9
[x-cache-info] => not cacheable; response has already expired
)
Function my_get_headers was stolen from http://www.php.net/manual/en/function.get-headers.php#64073
Documentation for get_gheaders says: "Fetches all the headers sent by the server in response to a HTTP request". Should actually be: "Fetches all the headers sent by the server in response to the HTTP request that caused the current script to execute".