A RESTful API in Flask refers to an application programming interface (API) built using the Flask web framework that follows the principles of Representational State Transfer (REST). Flask is a micro web framework for Python, which is lightweight and flexible, making it a popular choice for building web applications and APIs
APACHE-2.0 License
Rest stands for Representational State Transfer.
Let's understand the meaning of each word in the REST acronym.
State means data Representational means formats (such as XML, JSON, YAML, HTML, etc) Transfer means carry data between consumer and provider using the HTTP protocol
To understand what is a REST API, let’s, first of all, understand what is an API. An API stands for an application programming interface. It defines how applications or devices can connect to and communicate with each other.
A REST (Representational State Transfer) API is an architectural style for an API that uses HTTP (Hypertext Transfer Protocol) request methods to access and manipulate data over the Internet. The most popular HTTP request methods (which are explained below) are GET, POST, PUT, DELETE, PATCH, HEAD, TRACE, CONNECT and OPTIONS.
One of the examples of when REST APIs are used is when we need to expose back-end systems and data to front-end developers in a standardized format. That's why REST APIs architecture is vital when it comes to building web services that are consumed by a wide range of clients such as browsers, desktop applications and mobile devices.
The GET request is one of the HTTP methods which in simple words is in charge of grabbing data from a data source. The response from a GET request can contain data such as a list of items, a single item, or even just a status message.
A GET request is a safe and idempotent method, meaning that it can be repeated multiple times without having any side effects because it should only retrieve data, not modify it.
HTTP HEAD method is used to fetch the request headers that would be returned if a corresponding GET request was made. In other words, the HEAD method is the same as the GET method with the only difference being that it doesn't return the response body when the request was made.
The HEAD method can be very useful because it can save you some bandwidth in situations when you only need to retrieve some metadata about the resource without retrieving the actual resource as part of the response body. The metadata returned by a HEAD request can be used to validate the information about the resource such as Content-Length of the resource, Content-Type, Last-Modified date, etc.
This metadata from the headers can be very handy in situations when you for example just want to check whether the resource actually exists before fetching it or maybe when you just want to see when the resource was modified last time (P.S. imagine if a resource is a big file and you just need to check the date but you don't want to download it).
HTTP TRACE request can be used for debugging purposes when you want to determine what is exactly happening with your HTTP requests. When the TRACE request is sent, the web server would normally echo the exact content of an HTTP request back to the client.
However, the TRACE requests should not be enabled in a production environment because in some scenarios they potentially can reveal some sensitive information about the server.
HTTP OPTIONS request method can be used to request the available communication options from the server for the target resource.
When a client sends an OPTIONS request to a server, the server would normally include the list of the allowed HTTP methods for the target resource as part of the "Allow" header in the response.
This enforces API design using definition, and not just the code, which ensures that the changes are made to the codebase while API design is intact.
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 involves the verification process to know who the person is while authorization involves authoring an authenticated user to keep a check on resources allowed to access using Access Control List(ACL)
from flask import Flask
from flask_restful import Api, Resource
app = Flask(__name__)
api = Api(app)
class HelloWorld(Resource):
def get(self):
return {"message": "Hello, World!"}
api.add_resource(HelloWorld, '/hello')
if __name__ == '__main__':
app.run(debug=True)
from flask import Flask, jsonify
app = Flask(__name__)
# Dummy data for books
books = [
{"id": 1, "title": "To Kill a Mockingbird", "author": "Harper Lee", "year": 1960},
{"id": 2, "title": "1984", "author": "George Orwell", "year": 1949},
{"id": 3, "title": "Pride and Prejudice", "author": "Jane Austen", "year": 1813}
]
# Endpoint to retrieve all books
@app.route('/books', methods=['GET'])
def get_books():
return jsonify(books)
if __name__ == '__main__':
app.run(debug=True)
from flask import Flask, jsonify
app = Flask(__name__)
# Dummy user data
users = [
{"id": 1, "name": "Guru", "age": 23},
{"id": 2, "name": "Mounesh", "age": 23},
{"id": 3, "name": "Mgpatils", "age": 23}
]
@app.route('/users', methods=['GET'])
def get_users():
return jsonify(users)
if __name__ == '__main__':
app.run(debug=True)
# using flask_restful
from flask import Flask, jsonify, request
from flask_restful import Resource, Api
# creating the flask app
app = Flask(__name__)
# creating an API object
api = Api(app)
# making a class for a particular resource
# the get, post methods correspond to get and post requests
# they are automatically mapped by flask_restful.
# other methods include put, delete, etc.
class Hello(Resource):
# corresponds to the GET request.
# this function is called whenever there
# is a GET request for this resource
def get(self):
return jsonify({'message': 'hello world'})
# Corresponds to POST request
def post(self):
data = request.get_json() # status code
return jsonify({'data': data}), 201
# another resource to calculate the square of a number
class Square(Resource):
def get(self, num):
return jsonify({'square': num**2})
# adding the defined resources along with their corresponding urls
api.add_resource(Hello, '/')
api.add_resource(Square, '/square/<int:num>')
# driver function
if __name__ == '__main__':
app.run(debug = True)
from flask import Flask, jsonify, request, abort
app = Flask(__name__)
# Dummy data for books
books = [
{"id": 1, "title": "To Kill a Mockingbird", "author": "Harper Lee", "year": 1960},
{"id": 2, "title": "1984", "author": "George Orwell", "year": 1949},
{"id": 3, "title": "Pride and Prejudice", "author": "Jane Austen", "year": 1813}
]
# Endpoint to retrieve all books (GET)
@app.route('/books', methods=['GET'])
def get_books():
return jsonify(books)
# Endpoint to add a new book (POST)
@app.route('/books', methods=['POST'])
def add_book():
if not request.json or 'title' not in request.json:
abort(400) # Bad request
book = {
'id': books[-1]['id'] + 1,
'title': request.json['title'],
'author': request.json.get('author', ""),
'year': request.json.get('year', "")
}
books.append(book)
return jsonify({'message': 'Book added', 'book': book}), 201 # Created
# Endpoint to retrieve a specific book (GET)
@app.route('/books/<int:book_id>', methods=['GET'])
def get_book(book_id):
book = [book for book in books if book['id'] == book_id]
if len(book) == 0:
abort(404) # Not found
return jsonify(book[0])
# Endpoint to update a specific book (PUT)
@app.route('/books/<int:book_id>', methods=['PUT'])
def update_book(book_id):
book = [book for book in books if book['id'] == book_id]
if len(book) == 0:
abort(404) # Not found
if not request.json:
abort(400) # Bad request
book[0]['title'] = request.json.get('title', book[0]['title'])
book[0]['author'] = request.json.get('author', book[0]['author'])
book[0]['year'] = request.json.get('year', book[0]['year'])
return jsonify({'message': 'Book updated', 'book': book[0]})
# Endpoint to delete a specific book (DELETE)
@app.route('/books/<int:book_id>', methods=['DELETE'])
def delete_book(book_id):
book = [book for book in books if book['id'] == book_id]
if len(book) == 0:
abort(404) # Not found
books.remove(book[0])
return jsonify({'message': 'Book deleted'}), 204 # No content
if __name__ == '__main__':
app.run(debug=True)
from flask import Flask, request
from flask_restful import Api, Resource
from marshmallow import Schema, fields, ValidationError
app = Flask(__name__)
api = Api(app)
class UserSchema(Schema):
username = fields.Str(required=True)
email = fields.Email(required=True)
class UserResource(Resource):
def get(self):
# Implement logic to retrieve and return user data
# For demonstration, let's return dummy data
users = [
{"username": "user1", "email": "[email protected]"},
{"username": "user2", "email": "[email protected]"}
]
return users, 200
def post(self):
# Get user data from form parameters or request JSON
json_data = request.get_json()
username = json_data.get('username')
email = json_data.get('email')
try:
# Validate user data
user_data = UserSchema().load({"username": username, "email": email})
except ValidationError as err:
# Handle validation errors
return {"message": "Validation error", "errors": err.messages}, 400
# Process valid data (in this example, just return the data)
return user_data, 201
api.add_resource(UserResource, '/user')
if __name__ == '__main__':
app.run(debug=True)