Lab 7 - Flask
Create a basic RESTful web application backend using Flask. Consume the API endpoints using cURL and httpie.
Flask
Navigate to a new folder and initialize a new Python virtual environment.
mkdir cmput404lab7
cd cmput404lab7
virtualenv venv --python=python3
source venv/bin/activate
Install Flask.
pip install Flask
Create a new Python file named hello.py and edit its contents so it looks like this:
#!/usr/bin/env python3
from flask import Flask
app = Flask(__name__)
@app.route("/")
def hello():
return "Hello, world!"
if __name__ == "__main__":
app.run(debug=True)
Make the file executable and run the application. Navigate to the page in your browser.
chmod +x hello.py
./hello.py
# or
python3 hello.py
# In a new terminal
curl localhost:5000 # the port may be different on your machine
Modify the hello.py file to serve a RESTful api for managing a TODO list. First, install flask_restful.
pip install flask_restful
Update hello.py so it looks like the following.
#!/usr/bin/env python3
from flask import Flask
from flask_restful import Resource, Api
app = Flask(__name__)
api = Api(app)
class HelloWorld(Resource):
def get(self):
return {'hello': 'world'}
api.add_resource(HelloWorld, "/")
if __name__ == "__main__":
app.run(debug=True)
Run the server and see what it returns in your browser, or using cURL.
curl localhost:5000
Change the contents of hello.py to the following:
#!/usr/bin/env python3
from flask import Flask
from flask_restful import reqparse, abort, Api, Resource
app = Flask(__name__)
api = Api(app)
parser = reqparse.RequestParser()
parser.add_argument("task")
TODOs = {
1: {"task": "build an API"},
2: {"task": "?????"},
3: {"task": "profit"},
}
def abort_if_todo_not_found(todo_id):
if todo_id not in TODOs:
abort(404, message="TODO {} does not exist".format(todo_id))
def add_todo(todo_id):
args = parser.parse_args()
todo = {"task": args["task"]}
TODOs[todo_id] = todo
return todo
class Todo(Resource):
"""
Shows a single TODO item and lets you delete a TODO item.
"""
def get(self, todo_id):
abort_if_todo_not_found(todo_id)
return TODOs[todo_id]
def delete(self, todo_id):
abort_if_todo_not_found(todo_id)
del TODOs[todo_id]
return "", 204
def put(self, todo_id):
return add_todo(todo_id), 201
class TodoList(Resource):
"""
Shows a list of all TODOs and lets you POST to add new tasks.
"""
def get(self):
return TODOs
def post(self):
todo_id = max(TODOs.keys()) + 1
return add_todo(todo_id), 201
api.add_resource(Todo, "/todos/<int:todo_id>")
api.add_resource(TodoList, "/todos")
if __name__ == "__main__":
app.run(debug=True)
What does the browser show you when you navigate to /todos and /todos/1?
Try running the following cURL commands.
curl localhost:5000/todos
curl localhost:5000/todos/3
curl -v -X DELETE localhost:5000/todos/2
curl -v -X POST localhost:5000/todos -d "task=make sure to do lab 7 questions"
curl -v -X PUT localhost:5000/todos/3 -d "task=profit more"
Httpie
In addition to using cURL, httpie is specifically designed for interacting with RESTful JSON APIs. It has colour output and automatically pretty prints JSON for you.
pip install httpie
http localhost:5000/todos
http :5000/todos
http HEAD :5000/todos
http POST :5000/todos task="Try httpie!"
Question 0: What is the URL of your python flask_restfull code on github???
Question 1: How are Flask and Django different? What does Django provide for you that Flask does not?
Question 2: What does REST stand for? When I say something is RESTful, what does that mean?
Question 3: What does CRUD stand for? For each letter in CRUD, give the associated HTTP method.
Question 4: What do HTTP 1XX Status Codes mean? HTTP 2xx? HTTP 3xx? HTTP 4xx? HTTP 5xx?
Question 5: What is an XSS attack? Provide one way a site can be vulneratble to an XSS attack.
Question 6: What does CORS stand for? What situation in web application development will you need to implement CORS protection?
- Hint: What does the CO part of CORS mean?
Optional: Deploy your Flask application to Heroku.
- How does your
Procfilechange when compared to a Django application?