PHP: call to a REST api - php

I am trying to call a vChargeBack API for getting information on vCenter server. I am having issues with this.
I have to pass request as XML data in request body. And also I have to pass version as URL parameter. The code I have written is
$xmlfile=simplexml_load_file('login.xml');
$ch = curl_init();
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS,$xmlfile);//Passing XML file as POST field
curl_setopt($ch, CURLOPT_TIMEOUT, 10);
curl_setopt($ch, CURLOPT_URL,"https://xx.xx.xx.xx/vCenter-CB/api/login");//Setting URL
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch , CURLOPT_SSL_VERIFYPEER , false );//Since I am requesting https
curl_setopt($ch , CURLOPT_SSL_VERIFYHOST , false );//Since I am requesting https
curl_setopt($ch, CURLOPT_HTTPHEADER, array ('Accept: ' . $this->acceptType ));
$response=curl_exec($ch);//Getting response
$responseInfo=curl_getinfo($ch);//Getting response headers
When I execute, I have 400 Bad Request response. What I noticed is I am not sending version as URL parameter.
It should be
Name : version
value : 1.5.0
I am not knowing how to send this version as URL parameter. Should I send that as POSTFIELD then how should i send xml file as a request body.
Please help me...
Regards,
Srinath

The Chargeback interface is not RESTful. It's an XML portal with resources at given endpoints defined by the documentation. To log in, fill in the API_NAMESPACE as the XML namespace provided for your installation, API_VERSION as the API version number, TYPE (which can be "local" or "ldap"). NAME and PASSWORD should be obvious.
<Request xmlns="$API_NAMESPACE/$API_VERSION">
<Users>
<User>
<Type>$TYPE</Type>
<Name>$NAME</Name>
<Password>$PASSWORD</Password>
</User>
</Users>
</Request>
Generate a POST request to https://hostname/vCenter-CB/api/login?version=$API_VERSION with the raw POST-data set to the XML above. Remember to keep the session cookie you are sent after this request returns, as it represents your session to the server.
Also, if you're using LDAP logins, you may have to include an LdapUsers child element below the Users (as a sibling of the User element) to provide LDAP credentials. This is documented in the API Programming Guide from VMware.

Related

401 Unauthorized when authenticating using referer

I am trying to use an API which says to use it in a custom application to set a custom referer. Here's the official text:
The API requires (if enabled) a token for read operations to be send
to allow request, otherwise "Missing 'key' parameter" message will be
returned.
The security module will use the referrer heading ("referer" in Java,
HTTP_REFERER in PHP) of the request to identify and filter the
authorized domains.
I can currently log in to the web interface by using a special URL provided which seems to set the session and then redirects to the main URL. If I try navigating to the main URL directly without first using the special URL, I get a 401 error, as expected (afterwards, I can just use the main URL)
The key given below the text above is something like: http://example.com/api/?key=secretkeyhere
While I can use the API using the GUI tool in my web browser as described above, I can't figure out how to connect to it programatically. I have tried using both curl in Linux as well as curl in PHP. Both have failed.
curl from terminal:
curl --header http://example.com/api/?key=secretkeyhere http://example.com/api/search?query=terms*
curl in PHP:
<?php
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'http://example.com/api/search?query=terms');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_REFERER, 'http://example.com/api/?key=secretkeyhere');
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_AUTOREFERER, true);
$html = curl_exec($ch);
curl_close($ch);
echo "$html";
?>
I continue to get:
Unauthorized This server could not verify that you are authorized to
access the document requested. Either you supplied the wrong
credentials (e.g., bad password), or your browser doesn't understand
how to supply the credentials required.
Am I doing something wrong here? Is the API not set up correctly? I've read the man page for cURL and it seems like this is exactly what I should be doing.

How can I call a SAS Stored Process from CURL within PHP?

I want to build a web application that calls a SAS stored process and prints the results. I want the authentication to be handled behind the scenes.
The web application is built in PHP and I'll be using CURL to make the request.
Is this possible? What CURL options are necessary?
The proper way to do this (with security in mind) would be to use their ticket API- you can do CURL requests with PHP with a handshake first to eventually get the results of an STP endpoint.
Step1a) POST request .../SASLogon/v1/tickets with a form encoded payload of username and password.
Step1b) Look at response header "Location" (split by "/"[-1]) to get your auth token.
Step2a) Make a POST request to the same first url with the auth token appended at the end- and pass in the body (form encoded) the service url (service=xxx) (which ideally is the .../SASStoredProcess/do) endpoint.
Step2b) parse the response body for your ticket token.
Step3a) Run a request to the service (the .../do?token=[TicketToken]) with a POST payload (form encoded) of _program = STP endpoint
Step3b) Results will be the result of your request.
This probably requires some specific SAS installation config things setup- but is the general ticket handshake (generally- typing from memory, not with example in front of me). SAS is very specific depending on the version and what the install you have is.
You can achieve this with CURL, but in my personal opinion I like using higher level request libraries.
The other answers given are both valid- but auth-behind the scenes I assume you want a proper level of security- passing the username and password in each request is a security risk. Using the ticket system and handshake would be a "better" form solution in my mind.
First ensure your stored process web server is configured correctly by following the instructions located here.
Create a .php file containing the below code.
<?php
$parameters = array('_program' => '/Products/SAS Intelligence Platform/Samples/Sample: Hello World', // PATH TO STORED PROCESS
'_username' => 'mysasusername',
'_password' => '{SAS002}EFC0A34D034F489E2E0E03E840D324D6D30964A3', // ENCODED PASSWORD FROM PROC PWENCODE
'myParam1' => 'abc',
'myParam2' => 123
);
//
// CREATE A NEW CURL INSTANCE AND CONFIGURE IT
//
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "http://sas.myserver.com/SASStoredProcess/do?");
curl_setopt($ch, CURLOPT_PORT, 7980); // PORT USED TO MAKE STORED PROCESS REQUESTS
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); // DISABLE SSL CERTIFICATE CHECKING - OPTIONAL DEPENDING ON SERVER CERTIFICATE
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0); // DISABLE SSL CERTIFICATE CHECKING - OPTIONAL DEPENDING ON SERVER CERTIFICATE
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); // STORED PROCESS LOGIN INVOLVES MULTIPLE PAGE REQUESTS
curl_setopt($ch, CURLOPT_COOKIEFILE, ""); // STORED PROCESS LOGIN REQUIRES COOKIES
curl_setopt($ch, CURLOPT_COOKIEJAR, ""); // STORED PROCESS LOGIN REQUIRES COOKIES
curl_setopt($ch, CURLOPT_HEADER, true); // DONT SUPPRESS HTTP HEADER INFO
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE); // SUPPRESS DIRECTLY PRINTING RESULTS WHEN CURL_EXEC IS RUN.
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT ,90); // TIMEOUT LIMIT WHILE TRYING TO CONNECT
curl_setopt($ch, CURLOPT_TIMEOUT, 90); // TIMEOUT WHILE WAITING FOR RESPONSE
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($parameters)); // SET THIS OPTION LAST. MUST USE HTTP_BUILD_QUERY CALL ELSE YOU WILL BE PRESENTED WITH LOGIN PAGE
//
// EXECUTE IS AND SAVE THE RESULTS THEN CLOSE THE CURL OBJECT
//
$response = curl_exec($ch) ;
//
// PARSE OUT THE HTTP HEADER VS THE BODY
//
$header_size = curl_getinfo($ch, CURLINFO_HEADER_SIZE);
$header = substr($response, 0, $header_size);
$body = substr($response, $header_size);
print $body;
curl_close($ch);
?>
Configure the following:
_username
_password
_program (for this example I've used a sample that comes with SAS)
CURLOPT_URL
CURLOPT_PORT
depending on your site architecture you may require additional CURL options but the above should suffice for most cases
Once you have configured it, enter the URL of the .php file into your browser's address bar. You should see the output:
Hello World!
The PHP code listed used the minimum # of options required to work. It assumes that at some point you may also want to parse the header data to determine the CONTENT-TYPE of the result.
Also, when implementing the above code, be sure that any user credentials are stored securely. It is never a good idea to hardcode user credentials into source code (even if the SAS password has been run through PWENCODE).
For a generic (non-php, command-line) answer, here is a one-liner.
curl -v -L -c cookiefile -b cookiefile \
-d "_program=$STP&_username=$USERNAME&_password=$PASSWORD" \
https://yourdomain.com/SASStoredProcess/do
As discussed here, things to note include:
1) A cookiefile is used so that the session token can be written (-c) and subsequently read (-b) by the SASLogon redirect.
2) The _username and _password parameters are used to authenticate (see docs)
3) -v for verbose logging, -L to tell curl to follow the redirect (SASLogon) location

Translate CLI request into PHP cURL API request with authorisation string

I've been going round in circles trying to get this bit of code working. The problem I am facing is that there could be any number of places where something is wrong and I'm not experienced enough with cURL and API requests to know if I've just done something simple and silly somewhere. The code below is supposed to fetch a JSON response. What I am currently getting is "false". The API developer keeps giving me a CLI sample and I don't know how to "translate" that into something I can use in PHP.
I have to hide the domain, service name and authentication details in my examples.
The string I was given:
'https://[domain]/agw/latest/services/[service]-api/latest/api/v2/[service]-actual-prizes -vk -H "Proxy-Authorization: Basic [authstr]"'
([authstr] is the username and password, separated by a colon and BASE64 encoded - the API dev has confirmed that my authorisation string is correct)
What I have been trying:
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://[domain]/agw/latest/services/lottery-api/latest/api/v2/sportka-actual-prizes');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($ch, CURLOPT_HEADER, FALSE);
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
"Proxy-Authorization: Basic '.$authstr.'"
,"Content-type: application/json"
));
$response = curl_exec($ch);
curl_close($ch);
var_dump($response);
If I understand this correctly (and I'm not sure that I do), then I'm passing the URL (without flags), saying that I don't want a header in the response (I've tried TRUE as well without any success) and then passing headers with my request that includes the authorisation.
I've tried file_get_contents with a stream_context_create header but that fails too.
Am I missing a header option or flag or something in my cURL code?

cURL request getting wrong request version in Google App Engine

I have a cURL request in my code which works fine when running locally:
$url = "http://ipinfo.io/{$_SERVER['REMOTE_ADDR']}";
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_TIMEOUT, 10);
$response = curl_exec($ch);
$locale = json_decode($response);
and returns a JSON as expected. Our production system is on Google App Engine, however, where I get the website version for a browser rather than the JSON.
I can get this cURL request to work if I change
google_app_engine.enable_curl_lite = "1"
in the php.ini in the root directory of my project to
extension = "curl.so"
but Google's documentation insists the former is to be used on production. Additionally, using the latter breaks things like Monolog's SlackHandler.
Is there a way to get the JSON from this cURL request while still using Google's "cURL Lite"?
From the ipinfo.io documentation:
"We do a little bit of magic on the server to determine if we should send the JSON response or the webpage. We usually get it right, but if you're seeing the webpage instead of the JSON (or want to check the JSON output in a browser) you can force the JSON response by adding /json to the end of the URL"
Adding /json to the end of the URL worked for me in this case, but I wanted a more general solution. Since Google's cURL Lite uses their URL Fetch in the background, ipinfo.io's "magic" is somehow getting confused. I found that by specifying the Accept header then the /json addition wasn't required. In PHP:
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Accept: application/json'));
Thanks to the folks on the #php channel of NashDev Slack for helping me on this one!

Send POST serverside? (instagram api)

Looking at http://instagram.com/developer/authentication/ - The recommended way of communication is serverside.
I understand how I do step1 and step2. But in step3 they want me POST data directly serverside? (I understand how I could do a post request from jQuery) But is it even possible to do directly from PHP/CodeIgniter?
This is basically step3:
In the previous step, you’ll have received a code which you’ll have
to exchange in order to receive an access_token for the user. In order
to make this exchange, you simply have to POST this code, along with
some app identification parameters to our access_token endpoint.
I have all this info: (from response from Instagram)
client_id: your client id
client_secret: your client secret
grant_type: authorization_code is currently the only supported value
redirect_uri: the redirect_uri you used in the authorization request. Note: this has to be the same value as in the authorization request.
code: the exact code you received during the authorization step.
A backend can do a POST just like the browser. Much of the internet is server-to-server communication in this manner.
Here's an example POST request in PHP (using Curl)
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL,"http://www.example.com/site.html");
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, "postvar1=value1&postvar2=value2");
// receive server response ...
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec ($ch);
curl_close ($ch);
An alternative way to set the POST parameters instead of manually creating the param string:
curl_setopt($ch, CURLOPT_POSTFIELDS,
http_build_query(array('postvar1' => 'value1')));

Categories