Flask is a BSD licensed, Python microframework based on Werkzeug and Jinja2. Being a microframework doesn’t make it any less functional; Flask is a very simple yet highly extensible framework. This gives developers the power to choose the configuration they want, thereby making writing applications or plugins easy. Flask was originally created by Pocoo, a team of open source developers in 2010, and it is now developed and maintained by The Pallets Project who power all the components behind Flask. Flask is supported by an active and helpful developer community including an active IRC channel and a mailing list.
Introduction to Flask
Flask has two major components, Werkzeug and Jinja2. While Werkzeug is responsible for providing routing, debugging, and Web Server Gateway Interface (WSGI), Flask leverages Jinja2 as template engine. Natively, Flask doesn’t support database access, user authentication, or any other high-level utility, but it does provide support for extensions integration to add all such functionalities, making Flask a micro- yet production-ready framework for developing web applications and services. A simple Flask application can fit into a single Python file or it can be modularized to create a production-ready application. The idea behind Flask is to build a good foundation for all applications leaving everything else on extensions.
Flask community is quite big and active with hundreds of open source extensions. The Flask core team continuously reviews extensions and ensures approved extensions are compatible with the future releases. Flask being a microframework provides flexibility to the developers to choose the design decisions appropriate to their project. It maintains a registry of extensions which is regularly updated and continuously maintained.
Starting Flask
Flask, just like all other Python libraries, is installable from the Python Package Index (PPI) and is really easy to setup and start developing with, and it only takes a few minutes to getting started with Flask. To be able to follow this book, you should be familiar with Python, command line (or at least PIP), and MySQL.
Basic Flask Application
The preceding code imports the Flask library, initiates the application by creating an instance of the Flask class, declares the route, and then defines the function to execute when the route is called. This code is enough to start your first Flask application.
The following code launches a very simple built-in server, which is good enough for testing but probably not when you want to go in production, but we will cover that in the later chapters.
Flask Components Covered in This Book
Now that you have been introduced to Flask, we will discuss the components that we’ll cover in Flask REST API development in this book.
This book will serve as a practical guide to REST API development using Flask, and we’ll be using MySQL as the backend database. As already discussed, Flask doesn’t come with native database access support, and to bridge that gap, we’ll use a Flask extension called Flask-SQLAlchemy which adds support for SQLAlchemy in Flask. SQLAlchemy is essentially a Python SQL toolkit and Object Relational Mapper which provides the developers the full power and flexibility of SQL.
SQLAlchemy provides full support for enterprise-level design patterns and is designed for high-performing database access while maintaining efficiency and ease of use. We’ll build a user authentication module, CRUD (Create, Read, Update, and Delete) REST APIs for object creation, retrieval, manipulation, and deletion. We’ll also integrate a documentation utility called Swagger for creating API documentation, write unit and integration tests, learn application debugging, and, finally, check out different methods of deploying and monitoring our REST APIs on cloud platforms for production use.
For unit tests, we’ll use pytest which is a full-featured Python testing tool—pytest is easy to write tests with and yet is scalable to support complex use cases. We’ll also use Postman which is a complete REST API Platform—Postman provides integration tools for every stage of the API lifecycle, making API development easier and more reliable.
API deployment and monitoring are critical parts of REST API development; development paradigm changes drastically when it comes to scaling the APIs for production use cases, and for the sake of this book, we’ll deploy our REST APIs using uWSGI and Nginx on a cloud Ubuntu server. We’ll also deploy our REST APIs on Heroku which is a cloud platform that facilitates Flask app deployment and scaling out of the box.
Last but not least, we’ll discuss debugging common Flask errors and warnings and debugging Nginx requests and check out Flask application monitoring ensuring least amount on the downtime for production use.
Introduction to RESTful Services
Representational State Transfer (REST) is a software architectural style for web services that provides a standard for data communication between different kinds of systems. Web services are open standard web applications that interact with other applications with a motive of exchanging data making it an essential part of client server architecture in modern web and mobile applications. In simple terms, REST is a standard for exchanging data over the Web for the sake of interoperability between computer systems. Web services which conform to the REST architectural style are called RESTful web services which allow requesting systems to access and manipulate the data using a uniform and predefined set of stateless operations.
Since its inception in 2000 by Roy Feilding, RESTful architecture has grown a lot and has been implemented in millions of systems since then. REST has now become one of the most important technologies for web-based applications and is likely to grow even more with its integration in mobile and IoT-based applications as well. Every major development language has frameworks for building REST web services. REST principles are what makes it popular and heavily used. REST is stateless, making it straightforward for any kind of system to use and also making it possible for each request to be served by a different system.
REST enables us to distinguish between the client and the server, letting us implement the client and the server independently. The most important feature of REST is its statelessness, which simply means that neither the client nor the server has to know the state of each other to be able to communicate. In this way, both the client and the server can understand any message received without seeing the previous message. Since we are talking about RESTful web services, let’s take a dive into web services and compare other web service standards.
SOAP (Simple Object Access Protocol) is another web service communication protocol which has been overtaken by REST in the recent years. REST services now dominate the industry representing more than 70% of public APIs according to Stormpath. They operate by exposing consistent interface to access named resources. SOAP, however, exposes components of application logic as services rather than data. SOAP is now a legacy protocol originally created by Microsoft and has a lot of other constraints when compared to REST. SOAP only exchanges data over XML, and REST provides the ability to exchange data over a variety of data formats. RESTful services are comparatively faster and less resource intensive. However, SOAP still has its own use cases in which it’s a preferred protocol over REST.
SOAP is preferred when robust security is essential as it provides support for Web Services Security (WS-Security), which is a specification defining how security measures are implemented in web services to protect them from external attacks. Another advantage of SOAP over REST is its built-in retry logic to compensate for failed requests unlike REST in which the client has to handle failed requests by retrying. SOAP is highly extensible with other technologies and protocols like WS-Security, WS-addressing, WS-coordination, and so on which provides it an edge over other web service protocols.
- 1.
Uniform interface
- 2.
Representations
- 3.
Messages
- 4.
Links between resources
- 5.
Caching
- 6.
Stateless
Uniform Interface
RESTful services should have a uniform interface to access resources, and as the name suggests, APIs’ interface for the system should be uniform across the system. A logical URI system with uniform ways to fetch and manipulate data is what makes REST easy to work with. HTTP/1.1 provides a set of methods to work on noun-based resources; the methods are generally called verbs for this purpose.
Commonly used HTTP verbs useful in RESTful services
Verb | CRUD | Operation | Safe | Idempotent |
---|---|---|---|---|
GET | Read | Fetch a single or multiple resource | Yes | Yes |
POST | Created | Insert a new resource | No | No |
PUT | Update/Create | Insert a new resource or update existing | No | Yes |
DELETE | Delete | Delete a single or multiple resource | No | Yes |
OPTIONS | READ | List allowed operations on a resource | Yes | Yes |
HEAD | READ | Return only response headers and no body | Yes | Yes |
PATCH | Update/Modify | Only update the provided changes to the resource | No | No |
Representations
RESTful services focus on resources and providing access to the resources. A resource can be easily thought of as an object in OOP. The first thing to do while designing RESTful services is identifying different resources and determining the relation between them. A representation is a machine-readable explanation defining the current state of a resource.
Once the resources are identified, representations are the next course of action. REST provides us the ability to use any format for representing the resources in the system. Unlike SOAP which restricts us to use XML to represent the data, we can either use JSON or XML. Usually, JSON is the preferred method for representing the resources to be called by mobile or web clients, but XML can be used to represent more complex resources.
XML Representation of a Book Resource
JSON Representation of a Book resource
Messages
In Figure 1-4, GET is the request method, “/comments” is the path in the server, “postId=1” is a request parameter, “HTTP/1.1” is the protocol version that the client is requesting, “jsonplaceholder.typicode.com” is the server host, and content type is a part of the request headers. All of these combined is what makes a HTTP request that the server understands.
In the preceding figure, “HTTP/2” is the response HTTP version and “200” is the response code. The part below that till “cf-ray” is the response headers, and the array of post comments below “cf-ray” is the response body of the request.
Links Between Resources
A Book with Link to Buy
Caching
Caching is a technique that stores a copy of a given resource and serves it back when requested, saving extra DB calls and processing time. It can be done at different levels like the client, the server, or a middleware proxy server. Caching is an important tool for increasing the API performance and scaling the application; however, if not managed properly, it results in the client being served old results. Caching in REST APIs is controlled using HTTP headers. Cache headers have been an essential part of HTTP header specifications and have been an important part of scaling web services with efficiency. In REST specification, when a safe method is used on a resource URL, usually the reverse proxy caches the results to use the cached data when the same resource is requested the next time.
Stateless
Each request from client to server must contain all of the information necessary to understand the request, and cannot take advantage of any stored context on the server. Session state is therefore kept entirely on the client
—Roy Fielding
Statelessness here means that every HTTP response is a complete entity in itself and enough to serve the purpose of providing information to be executed without any need of another HTTP request. The point of statelessness is to defeat the purpose of accord with the server allowing intended flexibility in the infrastructure. To facilitate the same, REST servers provide enough information in the HTTP response that the client may need. Statelessness is an essential part of being able to scale the infrastructure enabling us to deploy multiple servers to serve millions of concurrent users given the fact that there is no server session state dependency. It also enables the caching feature of REST infrastructure as it lets the caching server to decide whether to cache the request or not, just by looking at the particular request irrespective of any previous requests.
Planning REST API
- 1.
Understanding the use case. It is really important to know why you are building the API and what services will the API provide.
- 2.
Listing down API features to understand what all actions your APIs are going to do. This also includes listing down actions and grouping them together to tackle redundant endpoints.
- 3.
Identify different platforms that’ll use the API and provide support accordingly.
- 4.
Plan long term on supporting growth and scaling the infrastructure.
- 5.
Plan API versioning strategy ensuring continuous support is maintained over different versions of the APIs.
- 6.
Plan API access strategy, that is, authentication, ACL, and throttling.
- 7.
Plan API documentation and testing.
- 8.
Understand how to use hypermedia with your APIs.
So, these are the eight important things to ensure while planning your API and are really crucial for developing a stable, production-focused API system.
API Design
Now let’s look into API design. Here we’ll cover the standards of designing REST APIs keeping in mind the list of things we just talked about.
Long-Term Implementation
Long-term implementation helps you analyze the flaws in design before actual implementation. This helps the developers to choose the right kind of platforms and tools to build upon making sure the same system can be scaled for more users later.
Spec-Driven Development
Spec-driven development enforces API design using definition and not just the code, which ensures that the changes are made to the codebase while the API design is intact. It is good practice to use a tool like API Designer to understand the API design before development which also lets you foresee the flaws. Tools like swagger or RAML let you keep the API design standardized and enable you to port the API to different platforms if needed.
Prototyping
Once the API specs are put in place, prototyping helps you visualize the API before actual development by letting the developers create MOCK API to help them understand every potential aspect of the API.
Authentication and Authorization
Authentication involves the verification process to know who the person is, but it just doesn’t involve giving access to all the resources yet, and that’s where authorization comes in, which involves authorizing an authenticated person to keep a check on resources allowed to access using an Access Control List (ACL).
We have different ways of authenticating and authorizing users like basic authentication, HMAC, and OAuth. OAuth 2.0 is however a preferred method for the same and is a standard protocol used by enterprises as well as small companies for authentication and authorization in their REST APIs.
So, these are the key features of the REST infrastructure, and we’ll discuss more about how REST works and enables better communication in later chapters.
Now, we’ll start with setting up our development environment and understand some key factors of developing applications with Python.
Setting Up Development Environment
Working with PIP
PIP is a PyPi recommended tool for project dependency management. PIP comes preinstalled with Python if you are using Python downloaded from www.python.org .
However, if you don’t have PIP installed in your system, follow the guide here to install PIP.
The previous command will install PIP, setuptools (required for installing source distributions), and wheel.
Choosing the IDE
Once we have the IDE setup, we can move to installing and setting up the virtual environment.
Understanding Python Virtual Environments
Python, just like other modern programming languages, provides a huge amount of third-party libraries and SDKs. Different applications might need various specific versions of third-party modules, and it won’t be possible for one Python installation to meet such requirements of every application. So, in the world of Python, the solution for this problem is virtual environment, which creates a separate self-contained directory tree containing a Python installation of the required version alongside the required packages.
At its core, the main purpose of a virtual environment is to create an isolated environment to contain an installation of Python and required packages for the application. There is no limit to the number of virtual environments you can create, and it’s super easy to create them.
Using Virtual Environments
In Python 2.7 we need a module called virtualenv which is installed using PIP to get started with Python virtual environments.
Note
In Python 3 the venv module comes preshipped as a part of the standard library.
Once we have the virtualenv module installed in our system, next we’ll create a new directory and create a virtual environment in it.
The previous command will use the virtualenv module and create a virtual environment called venv. You can name your virtual environment anything, but for this book, we’ll just use venv for the sake of uniformity.
Once this command stops executing, you’ll see a directory called venv. This directory will now hold your virtual environment.
- 1.
bin: Files to interact with the virtual environment.
- 2.
include: C headers to compile the Python packages.
- 3.
lib: This folder contains a copy of the Python version and all the other third-party modules.
So now you understand the concept of virtual environments, we can dig a little deeper and understand what’s happening inside the virtual environment.
Understanding how virtual environments work can really help you debug the application and understand the execution environment. To start with, let’s check out the Python executable with virtual environment activated and deactivated, in order to understand the basic difference.
So once you activate the virtual environment, the $path environment variable is modified to point at our virtual environment, and thus the Python in our virtual environment is used rather than the system one. However, an important thing to notice here is that it is basically a copy of, or a symlink to, the system’s Python executable.
Setting Up Flask
We have already installed Flask in the earlier module, but let’s start over and setup the Flask microframework.
Installing Flask
The preceding command will install Flask in your virtual environment.
- 1.
Werkzeug ( http://werkzeug.pocoo.org/ ): Werkzeug implements WSGI, the standard Python interface between the application and the server.
- 2.
Jinja ( http://jinja.pocoo.org/ ): Jinja is the templating engine in Flask which renders the pages for the application.
- 3.
MarkupSafe ( https://pypi.org/project/MarkupSafe/ ): Markupsafe comes preshipped with Jinja, which helps escape an untrusted user input to escalate injection attacks.
- 4.
ItsDangerous( https://pythonhosted.org/itsdangerous/ ): ItsDangerous is responsible for securely signing data to ensure data integrity and is used to protect Flask session cookies.
- 5.
Click ( http://click.pocoo.org/ ): Click is a framework to write CLI applications. It provides the “Flask” CLI command.
Conclusion
Once you have Flask installed in your virtual environment, you are ready to go to the next step of the development phase. Before we do that, we’ll discuss about MySQL and Flask-SQLAlchemy which is the ORM that we’ll use in our Flask application. Database is an essential part of a REST application, and in the next chapter, we’ll discuss the MySQL database and Flask-SQLAchemy ORM and also learn how to connect our Flask application with Flask-SQLAlchemy.