Raghav Agrawal — January 20, 2022
Advanced Machine Learning Python

This article was published as a part of the Data Science Blogathon.

Hello, I hope you are fine. I want to welcome you to a beautiful article on creating a REST API using Flask. In one of our previous articles, we have learned the basics of Flask and how to set it. We have made one complete end-end machine learning project with Flask. You can access the previous article from here. But people have many doubts about REST API, how can we create it for a different use case, or perform some task like validation, converting code, etc. In this tutorial, we will practically learn to create Flask API and make working our REST APIs more powerful. Before starting this, I assume that you are familiar with basic Python and Flask.

 

Table of Contents

  1. Brief Introduction to REST API
  2. Create your first REST API using Flask
  3. Different HTTP Request with REST API
  4. Using Decorators in REST API
  5. How to Secure Flask API
  6. How to Enable tracking on Flask API
  7. Writing Unit test for REST API
  8. End Notes

What is REST API (Application Programming Interface)

REST API stands for Restful API that allows integrating applications or interaction with RESTful web services. It is now growing as the most common method for connecting components in a microservice architecture. APIs will enable you to get or send data to a website and perform some action to get your task done over a web service. Each website uses different types of API, like stock market trading websites integrating with Sensex or Nifty to get a current price and ups-down. Ticket booking apps use a desired single portal API to keep updated data at a familiar interface.

Create your first REST API

let’s get over to code editor. You can use any Python IDE that you are comfortable with. We are creating the Hello world API, which says that if you hit a get request on it, you will get a JSON response because it’s universal that API always gives a JSON type response. I hope you have the Flask installed; otherwise, use the PIP command and install it using the below code. Create a new python file and type the below code.

pip install flask
pip install flask-restful
from flask import Flask

from flask_restful import Resource, Api

app = Flask(__name__)

api = Api(app)

class Helloworld(Resource):

	def __init__(self):

		pass

	def get(self):

		return {

			"Hello": "World"

		}

api.add_resource(Helloworld, '/')

if __name__ == '__main__':

	app.run(debug=True)

What is Flask-Restful?

Flask restful defines the resource class, which contains methods for each HTTP method. Method name should be the same as its corresponding HTTP method and written in lowercase. You can observe this in the above code. However, these methods do not have a route decorator, so they are based on resource routes. Whatever class we define, we define the route to it using add resource method and on which route we have to call it.

Explanation ~ In the above code, we first load required parent classes, then initialize our app and API. After that, we create a course, and we are making a GET request that states if anyone hits on this class, then he will get Hello world as the response in JSON format. To switch on a particular URL, we use the add resource method and route it to the default slash. To run this file, you can use the POSTMAN tool, an API maintenance tool, to create, test, and manage APIs. You can also make use request module to try this API using the below code. First, run the above file, which will give you the localhost URL, and in another command prompt, run the below code file.

import requests
url = "http://127.0.0.1:5000/"
response = requests.get(url=url)
print(response.text)
Output | API with Python and Flask

Understanding HTTP Request through Flask RESTApi

Now we are familiar with REST API. Under this heading, we will explore different HTTP methods using REST API, where we will define one list which will store all the data obtained from the server in the form of a dictionary(JSON object). This is important because we have different APIs in projects to get data post data but the data somewhere else.

Here we are creating an API where we will create 3 HTTP methods named GET, POST, and DELETE where we will create a customize URL and say that when you request POST method, then it will take Name as input and on hitting GET method, will give that Name back and In delete, we will delete that Name if it is present and again accessing that it will give us NULL. Create a file and write the below code.

from flask import Flask
from flask_restful import Resource, Api
app = Flask(__name__)
api = Api(app)
data = []
class People(Resource):
	def get(self):
		for x in data:
			if x['Data'] == name:
				return x
		return {'Data': None}
	def post(self, name):
		temp = {'Data': name}
		data.append(temp)
		return temp
	def delete(self):
		for ind, x in enumerate(data):
			if x['Data'] == name:
				temp = data.pop(ind)
				return {'Note': 'Deleted'}
api.add_resource(People, '/Name/')
if __name__ == '__main__':
	app.run(debug=True)

Open the POSTMAN API tool and hit on each HTTP method request. First, when we use post request using Name, it gives us a name. In getting the request, we get the Name back. It is deleted on deleting, and when you try to get it back again, it will give you NULL. Observe the results below.

Understanding HTTP
Response of HTTP | API with Python and Flask
API with Python and Flask

 

How to use Decorators in Flask REST API

We use decorators with APIs to monitor IP addresses, cookies, etc. So under this heading, we will learn how to leverage the flask API with decorators. A decorator is a function that takes another function as an argument and returns another function. You can also understand it as a function that provides some additional functionalities to the existing function without changing or modifying the current function.

Here we create a new file, and I will show you by creating two decorators. So in the first one, we are making the external time function which returns the code execution time. We import the wrap decorator applied to the wrapper function from the functools module(standard module for higher-order python functions). It updates the wrapped function by copying all its arguments.

from flask import Flask
from flask_restful import Resource, Api
import datetime
from flask import request
from functools import wraps
app = Flask(__name__)
api = Api(app)
def time(function=None):
@wraps(function)
def wrapper(*args, **kwargs):
s = datetime.datetime.now()
_ = function(*args, **kwargs)
e = datetime.datetime.now()
print(“Execution Time : {} “.format(e-s))
return _
return wrapper
class HelloWorld(Resource):
@monitor
def get(self):
return {‘hello’: ‘world’}
api.add_resource(HelloWorld, ‘/’)
if __name__ == ‘__main__’:
app.run(debug=True)

Decorators in Flask Tools

We create the second decorator for monitoring cookies and IP addresses, so make the below function. Instead of adding a time decorator to the hello world function, add a monitor decorator and run the code.

def monitor(function=None):
    @wraps(function)
    def wrapper(*args, **kwargs):
        _ = function(*args, **kwargs)
        print("Ip Address  : {} ".format(request.remote_user))
        print("Cookies : {} ".format(request.cookies))
        print(request.user_agent)
        return _
    return wrapper

How to make Flask API more secure with basic Authentication

When we design the API, we should also take care of security because many people will access it. What if you want only authorized people to access the API because it may contain some confidential data between some parties so that we can do that? Using Flask basic authentication. You need to install this flask module using the pip command.

pip install flask-httpauth

We are building an API and defining the User data dictionary, which contains username and password. When you work in real-time use-cases, you accept the username and password through a configuration file or from a database. First, we create a primary function to match username and password and a GET method that says that anyone who hits on this API so without login we cannot access the data.

from flask import Flask
from flask_restful import Resource, Api
from flask_httpauth import HTTPBasicAuth
app = Flask(__name__)
api = Api(app, prefix="/api/v1")
auth = HTTPBasicAuth()
USER_DATA = {
	"admin": "SuperSecretPwd"
}
#route to verify the password
@auth.verify_password
def verify(username, password):
	if not(username and password):
		return False
	return USER_DATA.get(username) == password
class PrivateResource(Resource):
	@auth.login_required
	def get(self):
		return {"How's the Josh": "High"}
api.add_resource(PrivateResource, '/private')
if __name__ == '__main__':
	app.run(debug=True)

When we run the above file using POSTMAN, we try to get the data without login to give you unauthorized access.

Basic Authentication

Now go to authorization and click on Basic Authorization. Enter the username and password you have used and then hit GET request to get the desired result.

API with Python and Flask

This is how you can secure your Flask API. To know more about Flask Basic Authorization, you can visit this blog.

How to Enable Tracking on Flask API

We have learned how we can secure our API from unauthorized login, but what if we also want to know the location(latitude and longitude points), IP address, server name like details of a person who is accessing our API so we can configure the basic flask Tracking application with our REST API. First, install the flask tracking package using PIP Command.

pip install flask-track-usage
from flask import Flask, g
app = Flask(__name__)
app.config['TRACK_USAGE_USE_FREEGEOIP'] = False
app.config['TRACK_USAGE_INCLUDE_OR_EXCLUDE_VIEWS'] = 'include'
from flask_track_usage import TrackUsage
from flask_track_usage.storage.printer import PrintWriter
from flask_track_usage.storage.output import OutputWriter
t = TrackUsage(app, [
		PrintWriter(),
		OutputWriter(transform=lambda s: "OUTPUT: " + str(s))
	])
@t.include
@app.route('/')
def index():
	g.track_var["optional"] = "Write_Something"
	return "Hello"
#Run the application
if __name__ == "__main__":
	app.run(debug=True)

Explanation ~ We will create a tracking application by importing Track Usage, Input writer, and output writer from the package installed. We pass our flask app to the Track package and use Output writer, and we use the lambda function, a single line function, to write the output in string format. After this, we create a basic routing on slash and include our track application as a decorator. G stands for global that says data is global within the context. Hence we have created a basic API which on browser return, hello but on the backend, you will get all the person’s information. On the command prompt, you can observe the following output.

Tracking on Flask

You can use JSON Formatter to see the output in a well-formatted way.

Output | API with Python and Flask

 

How to write a Unit Test code for your REST API

Now you have created an excellent REST API for your case. Still, your manager will ask you to write a Unit-test code for REST API because it is essential to identify the common bugs from your API and help secure production. So I hope that you have a simple API created with you. If not, make a new file named run and develop the below simple API.

from flask import Flask
from flask_restful import Resource, Api
import json
app = Flask(__name__)
api = Api(app)
class Helloworld(Resource):
	def __init__(self):
		pass
	def get(self):
		return json.dumps({"Message": "Fine"})
api.add_resource(Helloworld, '/')
if __name__ == '__main__':
	app.run(debug=True)

Now create another file name test where we will be writing the code for unit testing our API. So most commonly, you are always supposed to perform the below three basic unit tests.

  • Check that the response code is 200
  • Check the content written from API is application JSON Formatted
  • Check that all the keys we are accessing are present in API data processing.
from run import app
import unittest
class FlaskTest(unittest.TestCase):
	#Check for response 200
	def test_inde(self):
		tester = app.test_client(self) #tester object
		response = tester.get("/")
		statuscode = response.status_code
		self.assertEqual(statuscode, 200)
	#check if the content return is application JSON
	def test_index_content(self):
		tester = app.test_client(self)
		response = tester.get("/")
		self.assertEqual(response.content_type, "application/json")
	#check the Data returned
	def test_index_data(self):
		tester = app.test_client(self)
		response = tester.get("/")
		self.assertTrue(b'Message' in response.data)
if __name__ == '__main__':
	unittest.main()

So to elaborate basically if you have done web scraping, then a 200 response code means your request to a particular URL is successfully made, which returns a response. The second is a type of data that the admin is provided that should be scrapped appropriately when someone requests it, and the third is all the data that is present that should go without any modification.

End Notes

Hurry! We have learned to create Flask REST API from scratch and its maintenance easily and securely. REST APIs are of a different kind and are used for other purposes. You can also use routing with APIs like creating a function in a separate file and using it as a decorator with a main Application use case. So this was all for this article. I hope it was easy to catch up with each heading and if you have any queries, feel free to post them in the comment section below or connect with me.

Image Source – Medium

Connect with me on Linkedin

Check out my other articles here and on crazy techie

Thanks for giving your time!

The media shown in this article is not owned by Analytics Vidhya and are used at the Author’s discretion.

About the Author

Raghav Agrawal

I am a final year undergraduate who loves to learn and write about technology. I am a passionate learner, and a data science enthusiast. I am learning and working in data science field from past 2 years, and aspire to grow as Big data architect.

Our Top Authors

Download Analytics Vidhya App for the Latest blog/Article

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