Python REST API example

Introduction

In order for two networked computers to exchange data, a protocol has to be used. A protocol is an agreed method to identify computers (ex. PC, iPhone), applications (ex. browser, web server) and resources (ex. webpage, image, database table). A protocol also facilitates secure (ex. encryption) and reliable (ex. data loss protection) communication. The world wide web (i.e www) heavily relies on HTTP (i.e. hyper text transfer protocol) protocol. For example, a browser uses HTTP to request a webpage hosted on a web server. The web server returns the requested page back for display. The browser uniquely identifies a webpage resource using a URL (i.e. uniform resource locator). This sounds familiar when we type the address of a website in the browser address bar. The URL fully identifies a resource using a hostname (or IP address), port number and path to the resource. The host name identifies the destination computer. The port number identifies the service (ex. web, ftp) followed by the path to the resource. To demonstrate that, take a look at the following example

  • Protocol: http
  • Host name: www.8bitavenue.com
  • Port number: 80 but since 80 is the default port number for HTTP we can safely remove :80 from the URL
  • Path to resource: /2016/11/python-mutex-example

Note that the path to the resource should not necessarily match the corresponding local file system path on the server. The translation from URL path to system path is taken care of by the web server application. An example showing this translation is provided later in the implementation section.

HTTP commands

We learned that a browser communicates with a web server using HTTP protocol by adopting client server model (as opposed to a peer to peer model). Let us now briefly describe some of the methods that the HTTP protocol provides to facilitate communication.

  • GET method is used to request a resource. It only retrieves data, for example, a browser uses it to download then display a webpage.
  • POST method is used to send data to the destination computer. For example, a browser uses it to submit a web form.
  • PUT method creates a new resource if it does not exist, otherwise it updates that resource.
  • DELETE method is used to delete a resource.

Please note that as we browse the web, GET and POST commands are used the most.

HTTP request vs response

Let us be more specific and put things into perspective. A web browser retrieving a webpage, that is an application level communication. On the HTTP protocol level, a browser sends an HTTP request, the web server returns an HTTP response. With that said, pay attention to the following points:

  • An HTTP method (ex. POST, GET) is part of an HTTP request
  • A status code is part of an HTTP response to indicate what happened with the request
  • Query parameters are part of an HTTP request. They are used as input and can be sent either in request body or added to the URL
  • A request or response contains a headers section to include extra information (meta data). For example, the content type is one of the most important header information when dealing with HTTP response because it specifies the data format being returned
  • Both request and response have a body section containing the data (payload) being sent or received in a given format (JSON in our case)

Python web service

Now that we have a basic idea how the web works, The next step is to utilize HTTP in order to implement data exchange between computers. In other words, we are going to implement a simple Python web service and develop a client to consume it. Instead of retrieving data in HTML format as in the browser case, we are going to send and receive data in JSON format.That is a naive way to think of a web service. A web service basically exposes an API through endpoints.

API vs end point

Lets us quickly clarify what API and end point are. These terms are frequently mentioned when discussing web services. API (application programming interface) is a general term, it can refer to web services, libraries, methods and functions. Without being fancy in the definition, It refers to specifying service name, input parameters, their types and any returned results. APIs allow us glue components together and interconnect systems. End point is one end of the communication channel. It is just another way to refer to the URL of the web service. It is also important to note that web service API typically have more than one end point. Each end point serves a specific purpose. All web service end points share a common base URL. Oh by the way, did we just say JSON? What on eath is JSON format?

JSON Format

Some times, when terms are repeated over and over, we often tend to lose track. For that reason, let us clarify few basic points:

  • Text vs binary: JSON data is typically saved to disk in text format. A binary file is an array of bytes representing some sort of custom data (ex. image pixels). On the other hand, bytes in a text file represent characters in a certain encoding.
  • ASCII vs UTF8: Characters in a JSON text file can be encoded in ASCII (plain text) or UTF8 (if you want to use international character sets). Note that ASCII and UTF8 are just example encoding schemes. You can use whatever encoding suitable for your application.
  • JSON vs XML: that is how we structure the content of the file. In this post, we are going to use JSON format. This is not the place to debate which is better JSON or XML, however JSON seems to win the competition on the web due to simplicity, lightweight and adoption.

JSON (JavaScript Object Notation) is a subset of the JavaScript language syntax where:

  • Data is represented in name value pairs separated by commas
  • Objects are held in curly braces
  • Arrays are held in square brackets

JSON Example

Here is an example

The JSON file above contains information about two cars. Each car object has three fields. It resembles a database table. Car objects are the rows and fields are the columns. Try to copy the JSON text above and paste it to this online JSON viewer to visualize how the file is structured. We agreed that HTTP is going to be used to send and receive data in JSON format so we are ready now to talk about REST.

What is REST?

REST (REpresentational State Transfer) is a set of conventions to structure a web service. A web service that conforms to these conventions is called a RESTful web service. Fine details of REST constraints (i.e. client server, stateless, cacheable, layered, uniform interface, on demand) are not covered in this article. For more information, please see the references at the end of this article. So what is covered here then? I am going to cover basic design tips and implement a simple RESTful web service along with the corresponding client in Python.

Nouns verbs and representations

When designing RESTful API, we should pay attention to nouns, verbs and representations. Nouns refer to resources (ex. database table) exposed through the API. Verbs are HTTP methods (ex. POST, GET) applied to resources. Representation refers to data format (ex. json, xml, html). In our case, we are going to apply the following design tips.

  • Take out verbs out of web service URL and dedicate two base URLs for each resource
  • Use HTTP commands to apply verbs to nouns in order to reduce number of base URLs
  • Use plural nouns as opposed to singular for better intuition and clarity

Taking the same cars example mentioned earlier.

  • GET on /cars retrieves all cars
  • GET on /cars/id retrieves a specific car with id
  • POST on /cars add a new car
  • PUT on /cars/id updates a specific car with id
  • DELETE on /cars/id deletes a specific car with id

As you can see, only two base URLs are used (/cars and /cars/id). HTTP methods are used to reduce the number of base URLs. For example, no need for base URLs like /getCars and addCar. Also, we used plural noun /cars not /car.

Base URL

In base URL, we may include service name and version number. Service name provides a name space in case of hosting more than one service on the server. Version number is handy if we want to update the web service without breaking legacy functionality. Here is an example:

In our implementation, we are not going to use a service name nor version. We are going to keep things simple so that the demonstration is less distracting.

Python REST API server

We are going to use web.py web server Python module. If you do not have it installed, you can do that using the command:

If you do not have pip or easy_install then you need to install it first.

For the sake of clarity, It is not our attention to have a fancy implementation. Typically, a web service is implemented using a production quality python rest api framework such as Django or Flask. Also, a database is used to back the web service for persisting data. In our case, the focus is on exposing an API through a web service and consuming that service. For that reason, web.py is more than enough to do the job. For persistence, we are going to use in memory python list. We are not going to use any database nor save to disk. If you turn off the server then you will loose data but who cares ? it is a demo. Here is our implementation commented well so there is no need for extra explanation.

Python REST API client

Consuming a web service is not hard, we just need to send the appropriare HTTP requests. We can easily do that using a browser or the curl command. In python, we can use built in libraries to invoke HTTP, however there is an easy way. We are going to use (Kenneth Reitz) request library which is a wrapper for Python built in HTTP support.

Request library

The requests library by Kenneth Reitz allows us to invoke HTTP commands like never before. Here is a quick tutorial.

    • If you do not have it installed, you can do so by issuing the command

    • Import the library

    • To do a GET

    • To do a POST

    • Other commands

    • You can pass parameters in the URL

    • The response object encapsulate a lot of useful information

That is more than enough to implement our own client. The code snippet below consumes the web service that we implemented earlier:

Testing a web service

To debug a web service, a web browser may be used but it is not easy to generate all HTTP methods. There are dedicated tools for working with web services that one can try (ex. postman). A simpler and flexible solution is to use the curl command. Here is a list of curl commands to test the web service implemented earlier.

Securing a web service

This is a complex topic and very important, however it is beyond the scope of this article. Users connecting to a private web service must be authenticated before permission is granted. If you want to extend the code in this post to support authentication, you may check the following:

  1. Secure the web service. Check out this article
  2. Use authentication in the requests library. Check out this article

Summary

In this Python REST API tutorial, we discussed how the HTTP protocol is used to exchange data between computers. We also described the format of an HTTP URL. Under the hood, HTTP uses requests to send data and responses to retrieve data. Web services can utilize HTTP by exposing resources via API end points. The main theme of this article was REST, a popular web service design style. We also implemented an example RESTful Python web service and client. We ended the article by suggesting how to test and secure a web service.

References

Check the following articles for more information about REST API design and implementation in Python.

That is all for today. Thanks for visiting. Please leave your comments below.

Tags:, ,

Add a Comment

Your email address will not be published. Required fields are marked *