REST stands for Representational State Transfer.
It is an architectural style, set of rules to standardize the web, to maintain uniformity across web applications worldwide. It intends to enhance maintainability, scalability, reliability and portability of web applications.
Main idea behind REST is resources. Everything you want to access in a web application is a resource, whether it is a media or documents you want to download, update, delete. REST defines a way to access, transfer, and modify these resources.
This tutorial covers the following three high-level concepts:
- REST Basic Concepts – This section explains the 6 key rest architectural constraints
- Key elements of RESTFul implementation – This section the 6 different elements of a RESTful implementation
- Create a Python REST web-service – This sections gives a step-by-step instruction on creating a basic REST web-service in python
REST Basic Concepts
The following are few architectural constraints that will make any web service RESTful, as discussed by Roy Fielding, inventor of REST in his research paper.
1. Client Server
This constraint states that client and server implementation should be independent, both should be able to scale, evolve independently of each other. Client should only know URI of resource on server nothing else. Server should return the appropriate response based on received request from the client.
2. Stateless
Client-server interaction should be stateless in nature. Server should not store state data and response should totally depend upon the information present in the request from client. Client can however store keep session state data. This enhances scalability, reliability of interactions.
3. Cache
Cache comes into the picture to solve the issue of stateless nature of REST. This cache is implemented on client end, and cacheable response is cached. If in future client request some data for which it had already sent a request, instead of sending the request to server again, cache can reuse the cached response.
4. Uniform Interface
This states the need of uniform interface between components, every resource in server should have only one logical URI and should expose methods to access this resource, and it should follow standard naming conventions. All resource should be accessed using common approach. This enhances visibility of web interfaces.
5. Layered System
Layered system approach states that web service should follow layered approach, i.e. we should divide our web service in different layers that cannot see beyond their immediate layer, e.g. authentication layer, data access layer, message processor layer. This reduces system complexity and improves scalability.
6. Code on demand
This states that occasionally client can download executable code instead of static data, i.e. JSON/XML. It increases system extensibility.
Key Elements of RESTFul implementation
1. Resource
The basic idea behind REST is resource, everything stored in REST web service data store is a resource. In current context articles stored in TGS data store is a resource. We can access this resource using URI https://www.thegeekstuff.com/category/python/
2. Request Verbs
These defines the way to access the resources, what client wants to do with them is specified with the request verbs, these are basic methods
- GET: This will be used to get articles from data store of TGS web application.
- POST: This will be used to create a new article in TGS web application.
- PUT: This will be used to update any existing article or create a new if it does not exist in TGS data store.
- DELETE: This will be used to delete an article from TGS data store.
3. Request Headers
Extra request sent to server to specify type of response, encoding, and content type and customized parameters. Etc.
4. Request Body
When trying to create a resource, the resource data is sent in body of put request.
5. Response Body
Web server returns data in body of the response. Suppose client sent a GET to query data for python category, web server will return data in response body.
6 Response Codes
These coded returned with the response, and signifies the status of the request sent to the server. These similar to HTTP response code. E.g. 200 OK denotes request succeeded, 404 NOT FOUND denotes resource not found on server.
Create a Python REST web-service
Let’s create a simple REST web service using flask in python, we could consume this web service using Postman tool or Curl command line utility.
If you are new to Python, refer to this: 5 Examples to Jumpstart Object Oriented Programming in Python
Our resource in this service will be articles, it will store all the articles published on TGS, in following format
- Category
- Views
- Title
We will expose REST endpoints to add, modify, delete, and update the articles. CRUD functionality over REST.
Let’s start step by step:
1. Import Flask Module
First, import flask module inside the code and name our web service as shown below.
from flask import Flask from flask_restful import Resource, reqparse , api TGS = Flask(__name__) api = Api(TGS)
2. Create Resource Articles
Next, create resource articles, it will be a simple List of articles , we can also use a database to store out resource.
articles = [ { "category": "python", "views": 100, "title": "Dictionary" }, { "category": "java", "views": 200, "title": "java10" }, { "category": "elastic", "views": 300, "title": "elasticsearch" } ]
3. Create API End Points and REST Methods
Next, we need to create the api endpoints and the required REST methods as show below.
GET method will search requested category in list of articles, and will return the data if found along with response code 200 OK. Otherwise 404 not found
class Article(Resource): def get(self, category):
POST method will insert new article data in list of articles and returns inserted data with response code 201 created. If record already exists it returns error code 400 bad request.
def post(self,category):
PUT method will overwrite the record and return the data along with response code 200 OK. If record does not exist, it creates the data and returns it with response code 201 created.
def put(self,category):
DELETE method deleted the record if exist and returns the data with response code 200 OK. Otherwise 404 not found.
def delete(self,category):
4. Register Resource and Assign URI
Our final step is registering our resource to REST API and assign a URI to it.
api.add_resource(Article, "/category/<string:category>") TGS.run(debug=True,port=8080)
Full REST Sample Program
Create rest.py file:
vi rest.py
Copy/paste the following to the rest.py file:
from flask import Flask from flask_restful import Resource, reqparse ,Api TGS = Flask(__name__) api = Api(TGS) articles = [ { "category": "python", "views": 100, "title": "Dictionary" }, { "category": "java", "views": 200, "title": "java10" }, { "category": "elastic", "views": 300, "title": "elasticsearch" } ] class Article(Resource): def get(self, category): for article in articles: if(category == article["category"]): return article, 200 return "category not found", 404 def post(self, category): parser = reqparse.RequestParser() parser.add_argument("views") parser.add_argument("title") args = parser.parse_args() for article in articles: if(category == article["category"]): return "category {} already exists".format(category), 400 article = { "category": category, "views": args["views"], "title": args["title"] } articles.append(article) return article, 201 def put(self, category): parser = reqparse.RequestParser() parser.add_argument("views") parser.add_argument("title") args = parser.parse_args() for article in articles: if(category == article["category"]): article["views"] = args["views"] article["title"] = args["title"] return article, 200 article = { "category": category, "views": args["views"], "title": args["title"] } articles.append(article) return article, 201 def delete(self, category): global articles articles = [article for article in articles if article["category"] != category] return "{} is deleted.".format(category), 200 api.add_resource(Article, "/category/<string:category>") TGS.run(debug=True,port=8080)
Test the REST Program
Let’s test this using Curl utility, we could use postman utility also it’s a great tool.
Start the python glass REST server
$ python rest.py * Serving Flask app "rest" (lazy loading) * Environment: production WARNING: Do not use the development server in a production environment. Use a production WSGI server instead. * Debug mode: on * Restarting with stat * Debugger is active! * Debugger PIN: 145-292-899 * Running on http://127.0.0.1:8080/ (Press CTRL+C to quit)
1. GET articles from python category of TGS
$ curl -XGET http://127.0.0.1:8080/category/python % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 100 74 100 74 0 0 74000 0 --:--:-- --:--:-- --:--:-- 74000{ "category": "python", "views": 100, "title": "Dictionary" }
2. POST a new category article to TGS
$ curl -XPOST http://127.0.0.1:8080/category/c++ -H "Content-Type: application/json" --data '{ "category": "c++", "views": "199", "title": "tuples" }' % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 100 125 100 69 100 56 1468 1191 --:--:-- --:--:-- --:--:-- 2659{ "category": "c++", "views": "199", "title": "tuples"
3. PUT an article , modify C++ category article
$ curl -XPUT http://127.0.0.1:8080/category/c++ -H "Content-Type: application/json" --data '{ "category": "c++", "views": "201", "title": "tuples" }' % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 100 125 100 69 100 56 69000 56000 --:--:-- --:--:-- --:--:-- 122k{ "category": "c++", "views": "201", "title": "tuples" }
$ curl -XGET http://127.0.0.1:8080/category/c++ % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 100 69 100 69 0 0 4312 0 --:--:-- --:--:-- --:--:-- 4312{ "category": "c++", "views": "201", "title": "tuples" }
As you can see C++ category record is updated.
4. DELETE an article from C++ category
$ curl -XDELETE http://127.0.0.1:8080/category/c++ % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 100 18 100 18 0 0 18000 0 --:--:-- --:--:-- --:--:-- 18000"c++ is deleted." $ curl -XGET http://127.0.0.1:8080/category/c++ % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 100 21 100 21 0 0 21000 0 --:--:-- --:--:-- --:--:-- 21000"category not found"
Recommended exercise: Use MySQL or any database to store articles and implement data access layer to provide CRUD functionality over REST.
Comments on this entry are closed.
Well, you assume that I fully understand what code belongs to server side and which belongs to client side but I don’t.
Sorry, I don’t fully understand what part belongs where.
Simple and to the point explanation of REST. Is a resource. Thank you for another great article.
I would like to request that you make (or recommend me) an article about consuming a REST API with OAuth2 and a Callback URL, in Python. I’m having issue understanding how to implement the concept of the Callback URL in a desktop application.