PHP Web Services Basic Documentation Release 1.0-draft
Kamal Mustafa
March 14, 2016
Contents
1 Introduction 3 1.1 SOAP vs XMLRPC vs HTTP/REST...... 3 1.2 HTTP/REST...... 4 1.3 Security - Use SSL...... 4
2 Data Format / Serialization 5 2.1 Encoding/Decoding...... 5 2.2 Defining Status Code...... 6
3 Authentication 9 3.1 Example...... 9
4 Testing and Debugging 11
5 Full Example 13
6 Indices and tables 15
i ii PHP Web Services Basic Documentation, Release 1.0-draft
Contents:
Contents 1 PHP Web Services Basic Documentation, Release 1.0-draft
2 Contents CHAPTER 1
Introduction
Web services are client and server applications that communicate over the World Wide Web’s (WWW) HyperText Transfer Protocol (HTTP). As described by the World Wide Web Consortium (W3C), web services provide a stan- dard means of interoperating between software applications running on a variety of platforms and frameworks. Web services are characterized by their great interoperability and extensibility, as well as their machine-processable de- scriptions, thanks to the use of XML. Web services can be combined in a loosely coupled way to achieve complex operations. Programs providing simple services can interact with each other to deliver sophisticated added-value services.
1.1 SOAP vs XMLRPC vs HTTP/REST
SOAP and XMLRPC are ways to expose certain operations of the application over the network. For example, if the application has a function called getUser($username), the function can be accessed using XML such as:
On the server side, to expose the above function, we also need to write another XML in a format called WSDL (Web Services Description Language). The file will be more verbose and details than above and most of the time, not written by hand but instead being generated with a special program that scan our application source code. REST on the other hand is a way to expose data (called Resource) over the web using HTTP. For example, we may have a resource called User, exposed through HTTP as: http://www.example.org/User
Having above resource, we can use standard HTTP method to do operations such as: GET http://www.example.org/User/kamal POST http://www.example.org/User DELETE http://www.example.org/User/kamal
3 PHP Web Services Basic Documentation, Release 1.0-draft
Again, this is the major difference between SOAP and REST:- • SOAP exposed a set of operations. • REST exposed a set of resources (data).
1.2 HTTP/REST
The key principles of REST involve separating your API into logical resources. These resources are manipulated using HTTP requests where the method (GET, POST, PUT, PATCH, DELETE) has specific meaning. But what can be a resource ? Well, these should be nouns (not verbs!) that make sense from the perspective of the API consumer. Although your internal models may map neatly to resources, it isn’t necessarily a one-to-one mapping. The key here is to not leak irrelevant implementation details out to your API! Once you have your resources defined, you need to identify what actions apply to them and how those would map to your API. RESTful principles provide strategies to handle CRUD actions using HTTP methods mapped as follows: • GET /tickets - Retrieves a list of tickets • GET /tickets/12 - Retrieves a specific ticket • POST /tickets - Creates a new ticket • PUT /tickets/12 - Updates ticket #12 • PATCH /tickets/12 - Partially updates ticket #12 • DELETE /tickets/12 - Deletes ticket #12 The great thing about REST is that you’re leveraging existing HTTP methods to implement significant functionality on just a single /tickets endpoint.
1.3 Security - Use SSL
Always use SSL. No exceptions. Today, your web APIs can get accessed from anywhere there is internet (like libraries, coffee shops, airports among others). Not all of these are secure. Many don’t encrypt communications at all, allowing for easy eavesdropping or impersonation if authentication credentials are hijacked. Another advantage of always using SSL is that guaranteed encrypted communications simplifies authentication efforts - you can get away with simple access tokens instead of having to sign each API request.
4 Chapter 1. Introduction CHAPTER 2
Data Format / Serialization
2.1 Encoding/Decoding
To enable seemless integration between our web services and the applications that consume it, we need to have standard data format. The most common one is to use JSON. In PHP, there are 2 main function used to read and write JSON format:
$user = array( 'id' => 1, 'username' => 'Kamal', 'profiles' => array( 'credits' => 100, 'address' => 'JB', ), ); echo json_encode($user);
Above code will produce JSON string that look like: {"id":1,"username":"Kamal","profiles":{"credits":100,"address":"JB"}}
Conversely, when reading data submitted using our web service endpoint, we can use json_decode function. Let say user submit to us the above JSON string, can read it as:
When user send the request, they will get back the same data: curl -v -d'{"id":1,"username":"Kamal","profiles":{"credits":100,"address":"JB"}}' -H 'Content-Type: application/json' http://localhost:4000/user.php * About to connect() to localhost port 4000 (#0) * Trying ::1... Connection refused * Trying 127.0.0.1... connected * Connected to localhost (127.0.0.1) port 4000 (#0) > POST /user.php HTTP/1.1 > User-Agent: curl/7.21.4 (universal-apple-darwin11.0) libcurl/7.21.4 OpenSSL/0.9.8z zlib/1.2.5 > Host: localhost:4000 > Accept: */*
5 PHP Web Services Basic Documentation, Release 1.0-draft
> Content-Type: application/json > Content-Length: 69 > < HTTP/1.1 200 OK < Host: localhost:4000 < Connection: close < X-Powered-By: PHP/5.4.43 < Content-type: text/html < Array ( [id] => 1 [username] => Kamal [profiles] => Array ( [credits] => 100 [address] => JB )
) * Closing connection #0
2.2 Defining Status Code
It’s very important when building web services, all requests get a standardized status or error code. HTTP already pro- vides rich status code to indicate various state of the request. Our REST API can use this status codes to communicate with our users. Below are among the most common use status code:-
2.2.1 200 OK
This response code indicates that the request was successful.
2.2.2 201 Created
This indicates the request was successful and a resource was created. It is used to confirm success of a PUT or POST request.
2.2.3 400 Bad Request
The request was malformed. This happens especially with POST and PUT requests, when the data does not pass validation, or is in the wrong format.
2.2.4 404 Not Found
This response indicates that the required resource could not be found. This is generally returned to all requests which point to a URL with no corresponding resource.
6 Chapter 2. Data Format / Serialization PHP Web Services Basic Documentation, Release 1.0-draft
2.2.5 401 Unauthorized
This error indicates that you need to perform authentication before accessing the resource.
2.2.6 405 Method Not Allowed
The HTTP method used is not supported for this resource.
2.2.7 409 Conflict
This indicates a conflict. For instance, you are using a PUT request to create the same resource twice.
2.2.8 500 Internal Server Error
When all else fails; generally, a 500 response is used when processing fails due to unanticipated circumstances on the server side, which causes the server to error out.
2.2. Defining Status Code 7 PHP Web Services Basic Documentation, Release 1.0-draft
8 Chapter 2. Data Format / Serialization CHAPTER 3
Authentication
A RESTful API should be stateless. This means that request authentication should not depend on cookies or sessions. Instead, each request should come with some sort authentication credentials. By always using SSL, the authentication credentials can be simplified to a randomly generated access token that is delivered in the user name field of HTTP Basic Auth. The great thing about this is that it’s completely browser explorable - the browser will just popup a prompt asking for credentials if it receives a 401 Unauthorized status code from the server.
3.1 Example
Below is an example of using HTTP Basic authentication in PHP: 'abc123', 'user2' => 'abcxyz' ); if (!isset($_SERVER['PHP_AUTH_USER'])) { header('WWW-Authenticate: Basic realm="My API"'); header('HTTP/1.1 401 Unauthorized'); exit; } else { $username = $_SERVER['PHP_AUTH_USER']; $password = $_SERVER['PHP_AUTH_PW'];
if (!array_key_exists($username, $api_credentials)) { header('HTTP/1.1 403 Forbidden'); exit; } if ($password != $api_credentials[$username]) { header('HTTP/1.1 403 Forbidden'); exit; } }
The $api_credentials above simply store the user’s credentials details such as username and password in a PHP array, hardcoded in the source code but in practice you’ll store the information in database such as MySQL.
9 PHP Web Services Basic Documentation, Release 1.0-draft
10 Chapter 3. Authentication CHAPTER 4
Testing and Debugging
One advantage of using HTTP based API is there are lot of existing tools that can be used to test and debug the API endpoint. One of such tools is the curl command line application. Below are a few examples of using curl to make an API request. Making GET request: curl -v -H 'Content-Type: application/json' http://localhost:4000/User/
And you’ll see the following output:
* About to connect() to localhost port 4000 (#0) * Trying ::1... Connection refused * Trying 127.0.0.1... connected * Connected to localhost (127.0.0.1) port 4000 (#0) * Server auth using Basic with user 'user1' > GET /User/kamal HTTP/1.1 > Authorization: Basic dXNlcjE6YWJjMTIz > User-Agent: curl/7.21.4 (universal-apple-darwin11.0) libcurl/7.21.4 OpenSSL/0.9.8z zlib/1.2.5 > Host: localhost:4000 > Accept: */* > Content-Type: application/json > < HTTP/1.1 200 OK < Host: localhost:4000 < Connection: close < X-Powered-By: PHP/5.4.43 < Content-type: text/html < * Closing connection #0 {"url":"\/User\/kamal"}
By default, curl will make a GET request but we can explicitly specify the request method: curl -X POST -v -H 'Content-Type: application/json' http://localhost:4000/User/ curl -X PUT -v -H 'Content-Type: application/json' http://localhost:4000/User/ curl -X DELETE -v -H 'Content-Type: application/json' http://localhost:4000/User/
Other than curl, we can also use a GUI based HTTP client such as Postman.
11 PHP Web Services Basic Documentation, Release 1.0-draft
12 Chapter 4. Testing and Debugging CHAPTER 5
Full Example
Below are the full example to demonstrate the basic structure of PHP web services. Assume you have the following file in ./includes/User.php: $_SERVER['REQUEST_URI'], ); print_r($params); echo json_encode($response); }
public function do_POST($params) { $data = file_get_contents('php://input'); $data_json = json_decode($data, true); print_r($params); echo json_encode($data_json); } }
And this is index.php:
$api_credentials = array( 'user1' => 'abc123', 'user2' => 'abcxyz' );
$resources = array( 'User', ); include 'includes/User.php';
/*********************** Authentication ************************/ if (!isset($_SERVER['PHP_AUTH_USER'])) { header('WWW-Authenticate: Basic realm="My API"'); header('HTTP/1.1 401 Unauthorized');
13 PHP Web Services Basic Documentation, Release 1.0-draft
exit; } else { $username = $_SERVER['PHP_AUTH_USER']; $password = $_SERVER['PHP_AUTH_PW'];
if (!array_key_exists($username, $api_credentials)) { header('HTTP/1.1 403 Forbidden'); exit; } if ($password != $api_credentials[$username]) { header('HTTP/1.1 403 Forbidden'); exit; } }
/****************** Finding Resources ******************/ $paths = explode('/', $_SERVER['REQUEST_URI']); array_shift($paths); $resource = array_shift($paths); if (!in_array($resource, $resources)) { header('HTTP/1.1 404 Not Found'); exit; }
/**************** Operations ****************/ $method = $_SERVER['REQUEST_METHOD']; $resource_instance = new $resource; $resource_method = 'do_' . $method; if (method_exists($resource_instance, $resource_method)) { call_user_func(array($resource_instance, $resource_method), $paths); } else { header('HTTP/1.1 405 Method Not Allowed'); header('Allow: GET, POST'); }
14 Chapter 5. Full Example CHAPTER 6
Indices and tables
• genindex • modindex • search
15