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 / 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 ’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 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:

kamal

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 can get accessed from anywhere there is (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/' 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