Build your own API – Due Monday, March 9th
In this assignment you will be tasked to build your own server that will serve as an API. You will be building a fully functional server that could, if deployed to the cloud, serve real live internet traffic and be integrated as a part of a web application.
Summary
You will be building a server that can keep track of tasks. Your server must be able to do the following:
- Create a new task with a title property and a boolean determining whether the task has been completed. A new unique id would be created for each new task
- List all tasks created
- Get a specific task
- Delete a specified task
- Edit the title or completion of a specific task
- (Extra Credit) Bulk add multiple tasks in one request
- (Extra Credit) Bulk delete multiple tasks in one request
Your application will accept JSON and/or URL parameters and will return JSON data. Your server would be ready to be automatically integrated in a web system.
List of endpoints to be created
Here is a specific list of endpoints that you will be required to create, along with the method and the inputs/outputs:
Create a new Task
POST /v1/tasks
Input
{title: "Test Task 2"}
Output
{id: 2} (return a 201 code)
The id returned is a unique id for the todo that was just created
List all tasks created
GET /v1/tasks
Input
None
Output
(return a 200 code) { tasks: [ {id: 1, title: "Test Task 1", is_completed: true}, {id: 2, title: "Test Task 2", is_completed: false} ] }
Notes
This endpoint list all tasks including their id's
Get a specific task
GET /v1/tasks/{id}
Input
id (passed through the URL)
Output
(return a 200 code) {id: 3, title: "Test Task 2", is_completed: false}
On Error
if id not found: (return a 404 code) { error: "There is no task at that id" }
Notes
This endpoint returns a specific task or returns a 404 not found response
Delete a specific task
DELETE /v1/tasks/{id}
Input
id (passed through the URL)
Output
None (return a 204 code)
Notes: This endpoint deletes a specific task. If the task doesn’t exist still send the same response
Edit the title or completion of a specific task
PUT /v1/tasks/{id}
Input
{title: "Test Task 2", is_completed: false}
Output
None (return a 204 code)
On Error
if id not found: (return a 404 code) { error: "There is no task at that id" }
Notes: This endpoint deletes a specific task or returns a 404 not found response
(Extra Credit) Bulk add tasks
POST /v1/tasks
Input
{ tasks: [ {title: "Test Task 1", is_completed: true}, {title: "Test Task 2", is_completed: false}, {title: "Test Task 3", is_completed: true} ] }
Output
(return a 201 code) { tasks: [ {id: 1}, {id: 2}, {id: 3} ] }
Notes: This endpoint bulk adds more than one task. Note that this feature uses the same endpoint as the single task creation endpoint
(Extra Credit) Bulk delete tasks
DELETE /v1/tasks
Input
{ tasks: [ {id: 1}, {id: 2}, {id: 3} ] }
Output
None (return a 204 code)
Notes: This endpoint bulk deletes more than one task.
Tests
To see if you are on the right track, run the below file (using pytest, while your server is running) to test your endpoints. This is not an extensive test.
This test is to ensure that you have all of the routes correct and that your response is properly formed. For example, ensuring that your GET /v1/tasks/{id} endpoint returns a dictionary with an id (a number), a title (a string), and whether the task is completed (boolean).
Note: please run this as the first thing that hits your server on boot up. If it successfully completes once then your assignment is on the right track. Re-running the tests could fail as written.
So in short:
- Start your webserver
- Run your tests once
- If pass you are good!
import requests import json def test_create_task(): r = requests.post('http://localhost:5000/v1/tasks', json={"title": "My First Task"}) assert isinstance(r.json()["id"], int) assert len(r.json()) == 1 def test_list_all_tasks(): r = requests.get('http://localhost:5000/v1/tasks') assert isinstance(r.json()["tasks"], list) assert len(r.json()) == 1 assert isinstance(r.json()["tasks"][0]["id"], int) assert isinstance(r.json()["tasks"][0]["title"], str) assert isinstance(r.json()["tasks"][0]["is_completed"], bool) assert len(r.json()["tasks"][0]) == 3 def test_get_task(): r = requests.get('http://localhost:5000/v1/tasks/1') assert isinstance(r.json(),dict) assert isinstance(r.json()["id"], int) assert isinstance(r.json()["title"], str) assert isinstance(r.json()["is_completed"], bool) assert len(r.json()) == 3 def test_update_task(): r = requests.put('http://localhost:5000/v1/tasks/1', json={"title": "My 1st Task", "is_completed": True}) assert not r.content def test_delete_task(): r = requests.delete('http://localhost:5000/v1/tasks/1') assert not r.content
Submission
Please use the repository you created in week2. You will need to add all of your code to that repository and use the git commands to stage, commit, and push your code to GitHub. Please check that lab’s instructions to make sure you are set up and ready to go.
Please submit the URL of your repository to BCourses. This is important so that we know whose repository is whose in the class.