I've been looking around at similar topics on REST APIs but I am still having some confusion in my project, mostly with the PHP side of things.
USPS provides a REST API with functions that can be called via URL like this: https://epfws.usps.gov/ws/resources/epf/login
To make any call successfully, I have been told that a JSON object must be created and passed as a "POST parameter" with the expected values.
This is the JSON object that needs to be passed in this case:
obj=
{
"login":"loginExample",
"pword":"passwordExample"
}
I have also been given a PHP class that is supposed to manage these calls. This is the login function:
public function login ()
{
// Set up the parameters for a login attempt
$jsonData = array(
'login' => $this->loginUser,
'pword' => $this->loginPass,
);
// Make a login request
$jsonResponse = $this->pullResource
('/epf/login', 'POST', $jsonData);
return $jsonResponse;
}
So I have a few questions regarding this:
The document they sent says
"To make the request calls, a JSON object will need to be created and passed as a POST form parameter obj={jsonObject} for security reasons using content-type “application/x-www-form-urlencoded”."
I know that the login function contains the correct input values that USPS' REST API is wanting, but I'm not sure how to pass them as "obj", or how to apply the "content-type".
I have a "constant" defined at the top of my PHP script that looks like this:
const EPF_BASE_URL = 'https://epfws.usps.gov/ws/resources';
And I noticed in the actual functions that this part of the link is left out and they simply reference '/epf/login' as you can see above. Since "$this" contains lots of different values I'm wondering how it supposedly finds EPF_BASE_URL as needed. Is it similar to how 'using' directives work in C#?
What is the easiest way to call this function and display the result? This is my biggest question. Would I use a separate PHP class with an HTML form? I understand the concept of what it should do but I'm completely lost setting up a development environment for it.
I've been trying all of this with MAMP but would love to know if I'm on the right track or not.
That really depends on their API. Hopefully you get a string back that can be decoded to a JSON object (http://au.php.net/manual/en/function.json-decode.php). Some API might give a simple string that says 'SUCCESS' or 'FAIL'. You've got the code, so take a look at what $this->pullResponse() gives you.
If you've been given a PHP class that is supposed to support the API (hopefully from USPS), then it should already take care of putting the data in the form content, and ensuring is it submitted with the appropriate content-type.
A PHP const is more like a C# static string. It is very likely that the library will use the constant to create the end URL (i.e. EPF_BASE_URL . $resource). If you needed to run against a sand box environment, you could change that constant without having to change all the other code.
That's a very big question, because it depends on how you are programming your application. Procedural, MVC, existing frameworks, etc.
At the very least, you would set the loginUser and loginPass on the instantiated object, and call the login method`. You could then inspect the results, assuming the result is a JSON object, or use your favourite debugging method to see the contents.
I'm having a guess as the USPS API class name.
$uspsApi = new UspsApi();
$uspsApi->loginUser = 'username';
$uspsApi->loginPass = 'password';
$result = $uspsApi->login();
echo print_r($result, true);
Related
I'm trying out Azure Functions using PHP.
Getting the request information is not working for me.
I've not been able to find any documentation at all with the information of how to use Azure Functions with PHP code.
According to the only couple of examples, it seems that in order to retrieve the input information you need to first get the content of the req variable (or whatever name you assign in the function configuration).
That has the path of the file containing the request information (in theory).
$input_path = getenv('req');
So far, if I check the content of it, I get something like this:
D:\local\Temp\Functions\Binding\e2b6e195-02f7-481b-a279-eef6f82bc7b4\req
If I check if the file exists it says true, but the file size is 0.
Do anyone knows what to do here? Anyone with an example? Does anyone know where the documentation is?
Thanks
Ok, unfortunately there's pretty limited documentation out there for php as you have discovered.
At present, looking at the code might be the best doc. Here is the InitializeHttpRequestEnvironmentVariables function that adds request metadata to the environment for the script languages (node, powershell, php, python).
Important environment variables are:
REQ_ORIGINAL_URL
REQ_METHOD
REQ_QUERY
REQ_QUERY_<queryname>
REQ_HEADERS_<headername>
REQ_PARAMS_<paramname>
I'm assuming you've made a GET request, in which case there is no content (req is an empty file), but you will see that these other environment variables contain request data. If you were to make a POST request with a body then req would have data.
here is a full example parsing a GET request in PHP with an Azure Function :)
https://www.lieben.nu/liebensraum/2017/08/parsing-a-get-request-in-php-with-an-azure-function/
snippet from source:
<?php
//retrieve original GET string
$getReqString = getenv('REQ_QUERY');
//remove the ? for the parse_str function
$getReqString = substr($getReqString,1,strlen($getReqString));
//convert the GET string to an array
$parsedRequest = array();
parse_str($getReqString,$parsedRequest);
//show contents of the new array
print_r($parsedRequest);
//show the value of a GET variable
echo $parsedRequest["code"];
?>
I'm using HTTPful to send some requests in PHP and get data in JSON, but the library is converting the result into objects, where I want the result to be an array. In other words, its doing a json_decode($data) rather than json_decode($data, true).
There is, somewhere, an option to use the latter, but I can't figure out where. The option was added in v0.2.2:
- FEATURE Add support for parsing JSON responses as associative arrays instead of objects
But I've been reading documentation and even the source, and I don't see the option anywhere... The only way I can think of is making my own MimeHandlerAdapter which does a json_decode($data, true) but it seems like a pretty backwards way of doing it if there is an option somewhere...
It may be a little late to answer this, but I did a little research while using Httpful and found the answer. Httpful uses a default set of handlers for each mime type. If one is registered before you send the request, it will use the one you registered. Conveniently, there is an Httpful\Handlers\JsonHandler class. The constructor takes an array of arguments. The only one it uses is $decode_as_array. Therefore, you can make it return an array like this:
// Create the handler
$json_handler = new Httpful\Handlers\JsonHandler(array('decode_as_array' => true));
// Register it with Httpful
Httpful\Httpful::register('application/json', $json_handler);
// Send the request
$response = Request::get('some-url')->send();
UPDATE
I realized that it sometimes parses the response into a funky array if you don't tell the request to expect JSON. The docs say it's supposed to work automagically, but I was having some issues with it. Therefore, if you get weird output, try explicitly telling the request to expect JSON like so:
$response = Request::get('some/awesome/url')
->expects('application/json')
->send();
I never used this library. But in a research I found that you can find this option at src/Httpful/Handlers/JsonHandler.php on line 11.
There you will see:
private $decode_as_array = false;
And this flag is used at the same file on line 27:
$parsed = json_decode($body, $this->decode_as_array);
You have to set decode_as_array to true value, to do this:
\Httpful\Httpful::register(\Httpful\Mime::JSON, new \Httpful\Handlers\JsonHandler(array('decode_as_array' => true)));
before Request::get calling
The actual questions
How to "map" access restrictions so it can be used from php and javasript?
What kind of method should I use to share access restrictions / rules between php and javascript?
Explanation
I have created a RESTful backend using php which will use context-aware access control to limit data access and modification. For example, person can modify address information that belongs to him and can view (but not modify) address information of all other persons who are in the same groups. And of course, group admin can modify address details of all the persons in that group.
Now, php side is quite "simple" as that is all just a bunch of checks. Javascript side is also quite "simple" as that as well is just a bunch of checks. The real issue here is how to make those checks come from the same place?
Javascript uses checks to show/hide edit/save buttons.
PHP uses checks to make the actual changes.
and yes,
I know this would be much more simpler situation if I ran javascript (NodeJS or the like) on server, but the backend has already been made and changing ways at this point would cause major setbacks.
Maybe someone has already deviced a method to model access checks in "passive" way, then just use some sort of "compiler" to run the actual checks?
Edit:
Im case it helps to mention, the front-end (js) part is built with AngularJS...
Edit2
This is some pseudo-code to clarify what I think I am searching for, but am not at all certain that this is possible in large scale. On the plus side, all access restrictions would be in single place and easy to amend if needed. On the darkside, I would have to write AccessCheck and canAct functions in both languages, or come up with a way to JIT compile some pseudo code to javascript and php :)
AccessRestrictions = {
Address: {
View: [
OWNER, MEMBER_OF_OWNER_PRIMARY_GROUP
],
Edit: [
OWNER, ADMIN_OF_OWNER_PRIMARY_GROUP
]
}
}
AccessCheck = {
OWNER: function(Owner) {
return Session.Person.Id == Owner.Id;
},
MEMBER_OF_OWNER_PRIMARY_GROUP: function(Owner) {
return Session.Person.inGroup(Owner.PrimaryGroup)
}
}
canAct('Owner', 'Address', 'View') {
var result;
AccessRestrictions.Address.View.map(function(role) {
return AccessCheck[role](Owner);
});
}
First things first.
You can't "run JavaScript on the server" because Javascript is always run on the client, at the same way PHP is always run on the server and never on the client.
Next, here's my idea.
Define a small library of functions you need to perform the checks. This can be as simple as a single function that returns a boolean or whatever format for your permissions. Make sure that the returned value is meaningful for both PHP and Javascript (this means, return JSON strings more often than not)
In your main PHP scripts, include the library when you need to check permissions and use the function(s) you defined to determine if the user is allowed.
Your front-end is the one that requires the most updates: when you need to determine user's permission, fire an AJAX request to your server (you may need to write a new script similar to #2 to handle AJAX requests if your current script isn't flexible enough) which will simply reuse your permissions library. Since the return values are in a format that's easily readable to JavaScript, when you get the response you'll be able to check what to show to the user
There are some solutions to this problem. I assume you store session variables, like the name of the authorized user in the PHP's session. Let's assume all you need to share is the $authenticated_user variable. I assume i'ts just a string, but it can also be an array with permissions etc.
If the $authenticated_user is known before loading the AngularJS app you may prepare a small PHP file whish mimics a JS file like this:
config.js.php:
<?php
session_start();
$authenticated_user = $_SESSION['authenticated_user'];
echo "var authenticated_user = '$authenticated_user';";
?>
If you include it in the header of your application it will tell you who is logged in on the server side. The client side will just see this JS code:
var authenticated_user = 'johndoe';
You may also load this file with ajax, or even better JSONP if you wrap it in a function:
<?php
session_start();
$authenticated_user = $_SESSION['authenticated_user'];
echo <<<EOD;
function set_authenticated_user() {
window.authenticated_user = '$authenticated_user';
}
EOD;
?>
I'm writing my first web service, and I have a problem related to JSON data passing. I have my web service divided in two files: controller.php, which contains the service handler, and service.php, which contains the classes and methods to be served on request.
This is the acquisition fragment from controller.php:
public function atender() {
// pre-procesamos la petición
if (!empty($_POST)) {
if (!empty($_POST["class"]) && !empty($_POST["action"]) && !empty($_POST["function"])) {
$clase = ucwords($_POST["class"]);
$metodo = "{$_POST["action"]}{$this->obtenerMetodo($_POST["function"])}";
$id = (!empty($_POST["datos"]) ? stripslashes($_POST["datos"]) : null);
I can attend requests on both GET and POST mode (I use GET for methods not requiring authentication, like getCategories, getCategoryById, getProducts and getProductById. These are methods to get the dish categories and dishes in a sushi restaurant.)
For any of the GET requests, everything works like expected. My problem comes when I handle POST requests. I need to get all URL parameters in JSON, as this is to serve an iOS app, and JSON is the way we handle data to/from.
This is the processing fragment from service.php:
public function putUser($datos) {
if (!empty($datos)) {
$usuario = json_decode($datos);
$this->log .= implode("/", $usuario) . "\r\n";
In this case, $datos is the JSON-encoded data from the request. It's received as $id in controller.php (the code above). As it's my first web service, it's very probable I'm doing something really bad here, but I'm a bit blinded.
I've tried different variations of the service handling code. Using json_decode($datos, true) doesn't work either. I get
'Unexpected token <' as a response and, in raw form (using the advanced REST client from Google Chrome) it says: ''Warning: implode() [<a href='function.implode'>function.implode</a>]: Invalid arguments passed in /home/refine/public_html/sushigo/palma/service.php on line 344'.
I know SOAP is, usually, a better alternative to writing custom code like this but, for now, I need to stick with this code and implement a better alternative for my next project. Could you tell me what am I doing wrong?
The error message says, basically, that it is NOT a valid JSON - and such error messages are usually right.
Your error is somewhere in the sending / receiving code. Probably you send the JSON in one form and try to access it in some other way. Since I have no way of looking at the requests sent from the phone, I would guess that:
you send the data as application/json and try to receive it as an url encoded form. If you don't understand the difference, here's your problem.
you use stripslashes on the JSON data, which is wrong. UNLESS you have magic_quotes turned on, which would also be wrong (that is: both magic_quotes and stripslashes have to go).
I am being forced to work with a database company that only support ASP.NET, despite my employers being well aware that I only code in PHP and the project doesn't have the time to learn the new syntax.
Documentation is scant, and meaning in thin on the ground. Can someone help translate what is happening in this script, so that I can think about doing it in PHP
<%
QES.ContentServer cs = new QES.ContentServer();
string state = "";
state = Request.Url.AbsoluteUri.ToString();
Response.Write(cs.GetXhtml(state));
%>
QES.ContentServer cs = new QES.ContentServer();
the code instantiates the class method ContentServer()
string state = "";
Explicit the type var state as string
state = Request.Url.AbsoluteUri.ToString();
here you get the REQUEST URI (as in php) the path and convert it to one line string and put in the before mentioned string statte var
Response.Write(cs.GetXhtml(state));
and here return the message without refresh the page (ajax).
The Request object wraps a bunch of information regarding the request from the client i.e. Browser capabilities, form or querystring parameters, cookies etc. In this case it is being used to retrieve the absolute URI using Request.Url.AbsoluteUri.ToString(). This will be the full request path including domain, path, querystring values.
The Response object wraps the response stream sent from the server back to the client. In this case it is being used to write the return of the cs.GetXhtml(state) call to the client as part of the body of the response.
QES.ContentServer appears to be a third party class and is not part of the standard .NET framework so you would have to get access to the specific API documention to find out what is for and what the GetXhtml method does exactly.
So, in a nutshell, this script is taking the full URI of the request from the client and returning the output from the GetXhtml back in the response.
It would look like this in PHP:
<?php
$cs = new QES_ContentServer(); //Not a real php class, but doesn't look like a native ASP.NET class either, still, it's a class instantiation, little Google shows it's a class for Qwam E-Content Server.
$state = ""; //Superfluous in PHP, don't need to define variables before use except in certain logic related circumstances, of course, the ASP.NET could have been done in one line like "string state = Request.Url.AbsoluteUri.ToString();"
$state = $_SERVER['REQUEST_URI']; //REQUEST_URI actually isn't the best, but it's pretty close. Request.Url.AbsoluteUri is the absolute uri used to call the page. REQUEST_URI would return something like /index.php while Request.Url.AbsoluteUri would give http://www.domain.com/index.php
//$state = $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI']; or something similar might be better in this case given the above
echo $cs->GetXhtml($state); //GetXhtml would be a method of QES.ContentServer, Response.Write is like echo or print.
?>