I'm trying to connect to Airbnb and return my reservations from it.
I was able to successfully login using cURL, but I can't retrieve the reservations.
The reservations URL: http://airbnbapi.org/#get-host-messages
As you can see the HTTP Method is GET, client_id must be passed in the URL and X-Airbnb-OAuth-Token in the headers (after login).
After perform the cURL on login I receive the following header output (by using the function CURLINFO_HEADER_OUT):
POST /v1/authorize HTTP/1.1
Host: api.airbnb.com
Accept: */*
Content-Length: 511
Expect: 100-continue
Content-Type: multipart/form-data; boundary=------------------------aa1ew132ff32wca9
With the 200 HTTP code.
After login, I perform the cURL on reservations and I get:
GET /v2/threads?client_id=MyApiKey&_limit=10 HTTP/1.1
Host: api.airbnb.com
Accept: */*
{"error_code":404,"error_type":"invalid_action","error_message":"Action not found."}
With the following code:
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://api.airbnb.com/v2/threads?client_id=MyApiKey&_limit=10');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($ch, CURLOPT_HTTPHEADER, array('X-Airbnb-OAuth-Token: ' . $MyAccessToken));
curl_setopt($ch, CURLINFO_HEADER_OUT, true);
$response = curl_exec($ch);
$http = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$headerout = curl_getinfo($ch, CURLINFO_HEADER_OUT);
curl_close($ch);
print_r($headerout);
return array($http, $response);
If I use the hurl.it with my values it works without any problem.
Solved.
The problem was that my return should be decoding the $response as JSON and instead I'm retrieving it as plain text and therefore I'm not able to get the access_token parameter.
And since error_reporting is turned off, I didn't see that access_token was empty.
return array($http, json_decode($response));
Related
Ok guys, I will try to make this question as simple as possible (I am struggling to discover the problem for few days now):
I have this function
function readContent($url, $sessionId)
{
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
$cookiesFile = realpath(__DIR__.'/cookies/'.$sessionId.'.txt');
if(file_exists($cookiesFile))
{
curl_setopt($ch, CURLOPT_COOKIEFILE, $cookiesFile);
curl_setopt($ch, CURLOPT_COOKIEJAR, $cookiesFile);
}
//DEBUG------------------------------------------------------------------
$debugFile = fopen(__DIR__.'/debug/'.$sessionId.'.txt', 'w');
curl_setopt($ch, CURLOPT_VERBOSE, true);
curl_setopt($ch, CURLOPT_STDERR, $debugFile);
//-----------------------------------------------------------------------
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_USERAGENT, $_SERVER['HTTP_USER_AGENT']);
try
{
$output = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if($httpCode == 200)
{
file_put_contents(__DIR__.'/contents/'.$sessionId.'.html', $output);
curl_close($ch);
preg_match_all('/<[\s]*meta[\s]*http-equiv="?REFRESH"?' . '[\s]*content="?[0-9]*;[\s]*URL[\s]*=[\s]*([^>"]*)"?' . '[\s]*[\/]?[\s]*>/si', $output, $match);
if (isset($match) && is_array($match) && count($match) == 2 && count($match[1]) == 1)
{
return readContent(str_replace('&', '&', $match[1][0]), $sessionId);
}
}
}
catch(Exception $e)
{
return false;
}
}
And it does 3 requests (logs from STDERR file):
GET /redacted/ HTTP/2
Host: redacted.coom
accept: */*
< HTTP/2 302
< location: https://redacted.com/location1/
* Added cookie redacted="redacted" for domain redacted.com, path /, expire 1634127679
< set-cookie: redacted=redacted; path=/; expires=Wed, 13 Oct 2021 12:21:19 GMT; SameSite=Lax
multiple set-cookie / added cookie follows...
So this first request, is done without any cookie, but it set multiple cookies in the COOKIEFILE/COOKIEJAR. Once CURL follows the location specified on request answer, it sends all cookies set:
* Ignoring the response-body
* Connection #0 to host redacted.com left intact
* Issue another request to this URL: 'https://redacted.com/location1/'
> GET /location1/ HTTP/2
Host: redacted.com
accept: */*
cookie: redacted=redacted;redacted=redacted;redacted=redacted......
< HTTP/2 200
This second request, returns 200 OK with META REFRESH in html body.
As you see in the function, if it detects 200 with META REFRESH regex, the function self calls passing the URL on META REFRESH. And it goes to the 3rd request, but this time, it sends only 1 cookie
> GET /location1/?from_meta_refresh=1 HTTP/2
Host: redacted.com
accept: */*
cookie: redacted=redacted
This is an invalid request for this page, because it require another cookies that were set and are on CURLOPT_COOKIEFILE, but aren't sent.
This only cookie sent, is the last line on the COOKIEFILE. I thought it may be some parameter on cookie like domain/folder/secure but I noted that have another cookie on the file, with the exact same parameters, and not sent on this request:
redacted.com FALSE / FALSE 1634128519 not_sent redacted
redacted.com FALSE / FALSE 1634128519 sent redacted
Please, help!
For some unknown reason, PHP Curl doesn't save the cookies to COOKIEJAR file when you call curl_close(). So I needed to save the cookies before close, using:
curl_setopt($ch, CURLOPT_COOKIELIST, 'FLUSH');
After this, the cookies were available for the next request.
In PHP, I'm trying to retrieve the url for a specific page in DocuSign that constantly refreshes. The POST to retrieve this url is in the form:
POST http://demo.docusign.net/restapi/{apiVersion}/accounts/{accountId}/envelopes/{envelopeId}/views/recipient
This should return a json file in the form:
{
"url": "example.example.com"
}
However, I am extremely new to using PHP and POST methods and don't believe I'm doing this correctly. The API explorer for this method in particular is here. I am using cURL methods to make this request. Here is my code ($recipient,$account_id,$access_token are found accurately within another file):
$url = "http://demo.docusign.net/restapi/v2/accounts/$account_id
/envelopes/$envelope_id/views/recipient";
$body = array("returnUrl" => "http://www.docusign.com/devcenter",
"authenticationMethod" => "None",
"email" => "$recipient",
"userName" => "$recipient");
$body_string = json_encode($body);
$header = array(
'Accept: application/json',
'Content-Type: application/json',
'Content-Length: '.strlen($body_string),
);
$curl = curl_init($url);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_HTTPHEADER, $header);
curl_setopt($curl, CURLOPT_POST, 1);
curl_setopt($curl, CURLOPT_POSTFIELDS, $body_string);
$json_response = curl_exec($curl);
$response = json_decode($json_response, true);
var_dump($response);
I am able to get the correct return on the API explorer, but not when making the request with PHP. I believe this is due to the fact that I am not incorporating the $header or $body correctly, but at this point I am just not sure.
ADDED: This is the raw output for the request when correctly running the method on the API Explorer:
Accept: application/json
Accept-Encoding: gzip,deflate,sdch
Accept-Language: en-US,en;q=0.8,fa;q=0.6,sv;q=0.4
Cache-Control: no-cache
Origin: https://apiexplorer.docusign.com
Referer: https://apiexplorer.docusign.com/
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.103 Safari/537.36
Authorization: Bearer fGehcK7fkRvFguyu/7NGh01UUFs=
Content-Length:
Content-Type: application/json
This is the JSON request being formed in my code:
{
"returnUrl":"http:\/\/www.docusign.com\/devcenter",
"authenticationMethod":"Password",
"email":"example#example.com",
"userName":"example#example.com",
"clientUserId":"4c6228f4-fcfe-47f9-bee1-c9d5e6ab6a41",
"userId":"example#example.com"
}
You are not hitting a valid DocuSign URL in your cURL code. Right now you are sending requests to:
http://demo.docusign.net/apiVersion/v2/accounts/{accountId}/envelopes/{envelopeId}/views/recipient
Instead of "apiVersion" it should be "restApi" like this:
http://demo.docusign.net/restapi/v2/accounts/{accountId}/envelopes/{envelopeId}/views/recipient
We can't send post fields, because we want to send JSON, not pretend to be a form (the merits of an API which accepts POST requests with data in form-format is an interesting debate). Instead, we create the correct JSON data, set that as the body of the POST request, and also set the headers correctly so that the server that receives this request will understand what we sent:
$data = array("name" => "Hagrid", "age" => "36");
$data_string = json_encode($data);
$ch = curl_init('http://api.local/rest/users');
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
curl_setopt($ch, CURLOPT_POSTFIELDS, $data_string);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
'Content-Type: application/json',
'Content-Length: ' . strlen($data_string))
);
$result = curl_exec($ch);
All these settings are pretty well explained on the curl_setopt() page, but basically the idea is to set the request to be a POST request, set the json-encoded data to be the body, and then set the correct headers to describe that post body. The CURLOPT_RETURNTRANSFER is purely so that the response from the remote server gets placed in $result rather than echoed. If you're sending JSON data with PHP, I hope this might help!
I know this question was asked more than 3 years ago, but this may help someone who finds this question because they are having the same problem. I do not see a cURL option that will decode the response in your code. I have found that I need to use the cURL option CURLOPT_ENCODING like this: curl_setopt($ch,CURLOPT_ENCODING,""); According to the PHP manual online, it says, 'CURLOPT_ENCODING - The contents of the "Accept-Encoding: " header. This enables decoding of the response. Supported encodings are "identity", "deflate", and "gzip". If an empty string, "", is set, a header containing all supported encoding types is sent.' You can find this option at https://www.php.net/manual/en/function.curl-setopt.php. I hope this helps save someone from having a headache.
I want to send json data via PUT to a REST service using the following php code:
$data = '{"api_key":"my-api-key","post":{"exception":["2015-04-10T11:09:51+00:00 ERR (3):\\nexception 'Exception' with message 'a simple exception' in \/private\/var\/www\/index.php:1\\nStack trace:\\n#0 {main}"],"access":["::1 - - [10\/Apr\/2015:13:08:17 +0200] \"GET \/index.php HTTP\/1.1\" 200 19039"]}}';
$curl = curl_init($url);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_CUSTOMREQUEST, "PUT");
curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
curl_setopt($curl, CURLOPT_HTTPHEADER, array(
'Content-Type: application/json',
'Content-Length: ' . strlen($data))
);
$response = curl_exec($curl);
As you can see I send valid json (validated by http://jsonlint.com/). On the side of the service I get the following json:
{"api_key":"my-api-key","post":{"exception":["2015-04-10T11:09:51+00:00 ERR (3):\\\\nexception \'Exception\' with message \'a simple exception\' in \\/private\\/var\\/www\\/index.php:1\\\\nStack trace:\\\\n#0 {main}"],"access":["::1 - - [10\\/Apr\\/2015:13:08:17 +0200] \\"GET \\/index.php HTTP\\/1.1\\" 200 19039"]}}
Validating this says I got a parse error. And this seems correct as I can't understand why further escaping is done like \\\\n. What am I doing wrong here?
I doubt that this is a valid use of a PUT and should be a POST but that is just a technicality. If you can, make it a POST. The PUT is likely the root of the issue.
The CURLOPT_PUT uses CURLOPT_INFILE and CURLOPT_INFILESIZE
The URLOPT_CUSTOMREQUEST should work fine but it appears you have some RFC 3986 escaping going on for some unexplainable reason.
You may want to use rawurldecode ( ) on the Service Side.
This will give you (appears correct but I'm not the guy to verify):
{"api_key":"my-api-key","post":{"exception":["2015-04-10T11:09:51+00:00 ERR (3):\\nexception 'Exception' with message 'a simple exception' in \/private\/var\/www\/index.php:1\\nStack trace:\\n#0 {main}"],"access":["::1 - - [10\/Apr\/2015:13:08:17 +0200] \"GET \/index.php HTTP\/1.1\" 200 19039"]}}
Disclaimer: I have never used curl to POST Content-Type: application/json data.
You need to look at your Request Header and maybe Response. It would be interesting to see if you get the proper PUT Response.
curl_setopt($ch, CURLOPT_HEADER, true);
curl_setopt($ch, CURLINFO_HEADER_OUT, true);
Check your Request Header Content-Type
To get the headers:
The response Header will be in the returned transfer.
The Request Header will be in curl_getinfo()
The curl info will also include the HTTP Response Status. Which for a PUT should be 201 or 301 but not important.
$data = curl_exec($ch);
$skip = intval(curl_getinfo($ch, CURLINFO_HEADER_SIZE));
$responseHeader = substr($data,0,$skip);
$data= substr($data,$skip);
$info = var_export(curl_getinfo($ch),true);
echo $responseHeader . $info . $data;
If you still want to send the json without curl escaping it I have some thoughts on that. but there is probably a post on that subject here somewhere.
I am currently trying to use the Nest API but I can't get past the authorization part.
Here is the PHP code I use to call the API :
//access token url used for authorization
$url="https://api.home.nest.com/oauth2/access_token?code=".$_GET['pin']."&client_id=".$api_key."&client_secret=".$secret_key."&grant_type=authorization_code";
$ch = curl_init ($url);
curl_setopt ($ch, CURLOPT_RETURNTRANSFER, true);
//https
curl_setopt($ch, CURLOPT_SSLVERSION,1);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_POST,true);
//to have headers in response
curl_setopt($ch, CURLOPT_HEADER, 1);
$result = curl_exec ($ch);
if($result){
echo "Result : " .$result;
}else{
echo curl_error($ch);
}
And I get the following result for this call :
Result : HTTP/1.1 200 Connection established HTTP/1.1 400 BAD_REQUEST Content-Length: 0 Connection: Close
Is there other options I need to set in order to get it working?
EDIT : The generated url ($url) works fine with HTTPRequester (Firefox addon) so the problem comes most certainly from the curl request itself
Thanks in advance.
HTTP Status codes
400 - Bad request - typically this occurs when a bad parameter is
given to a method
So, try this:
echo $url;
exit;
before:
$ch = curl_init ($url);
and copy paste that url to your browser address bar. See where you're posting wrong parameter.
See, if that helps.
I think dev and inspect are running on same port. so remove the port and host for inspect on node by setting "inspect": false
angular.json
"serve": {
"builder": "#nrwl/node:execute",
"options": {
"buildTarget": "api:build",
"inspect": false
}
},
My goal is to send a POST request to a server and get the proper response.
Note: Angled brackets represent placeholders.
In Terminal, using the following code will provide me the desired response.
curl -u <user>:<pass> -H 'Content-Type: application/xml' -X POST https://<rest of url>
My current PHP looks something like this:
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $uri); //$uri is the same that I use in terminal
curl_setopt($ch, CURLOPT_USERPWD,
sprintf('%s:%s', $user, $pass)); //same as terminal user & pass
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
$headers = array(
'Content-Type: application/xml', //expect an xml response
);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
$curl_result = curl_exec($ch);
Using this PHP, I get a 400 Bad Request error.
The verbose information:
> POST <same url> HTTP/1.1
Authorization: Basic YWRtaW5Ac3Bhcms0NTEuY29tOnNwYXJrc29tZXRoaW5n
Host: <correct host>
Accept: */*
Content-Type: application/xml
Content-Length: -1
Expect: 100-continue
* HTTP 1.0, assume close after body
< HTTP/1.0 400 Bad request
< Cache-Control: no-cache
< Connection: close
< Content-Type: text/html
Why am I getting a 400 Bad Request error when I use PHP, but not when I use command line? How can I fix this issue so that I get my desired response using PHP?
curl_setopt($ch, CURLOPT_POSTFIELDS, array());
After adding this line, I resolved my problem. In a way, this solution makes sense; but I don't understand why CURLOPT_POSTFIELDS is required. In the PHP documentation, this part should be included under CURLOPT_POST, unless this just accidentally works.
I don't know if this can help you, but for me the Expect: 100-continue looks strange. Take a look at this comment:
http://php.net/manual/en/function.curl-setopt.php#82418
So maybe you can fix it like in the example:
<?php
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Expect:'));
?>