-
Notifications
You must be signed in to change notification settings - Fork 0
API implementation
📑 Chapter summary
In this section you must implement a RESTful API. The minimum requirements are summarized in the Minimum Requirements section of the Project Work Assignment. If you do not meet the minimum requirements this section WILL NOT be evaluated. Please, remember that the API should be use a Resource Oriented Architecture- Implement a RESTful API
- Write tests for the API
✔️ Chapter evaluation (max 21 points)
You can get a maximum of 21 points after completing this section. More detailed evaluation is provided in the evaluation sheet in Lovelace.📑 Content that must be included in the section
A list of all resourcess. Each resource should include its URL, a short description and supported methods. You should mark also which is the name of the class implementing the resource (if you have implemented such resource) Consider that you do not need to implement every resource you initially planned. The minimum requirements are summarized in the Minimum requirements section from the Project work assignment.✏️ List your resources here. You can use the table below for listing resources. You can also list unimplemented resources if you think they are worth mentioning
| Resource name | Resource url | Resource description | Supported Methods | Implemented |
|---|---|---|---|---|
| API Root (Blueprint) | /api | API entry point (prefix for all REST resources) | - | Yes |
| Health Check | /health | Basic service health check | GET | Yes |
| Shipments Collection | /api/shipments | List all shipments / Create a new shipment | GET, POST | Yes |
| Shipment Item | /api/shipments/ | Retrieve / Update / Delete a specific shipment | GET, PUT, DELETE | Yes |
| Readings Collection | /api/shipments//readings | List/Create readings for a shipment | GET, POST | Yes |
| Reading Item | /api/shipments//readings | Retrieve / Update a specific reading | GET, PUT | Yes |
💻 TODO: SOFTWARE TO DELIVER IN THIS SECTION
The code repository must contain:- The source code for the RESTful API
- The external libraries that you have used
- We recommend to include a set of scripts to setup and run your server
- A database file or the necessary files and scripts to automatically populate your database.
- A README.md file containing:
- Dependencies (external libraries)
- How to setup the framework.
- How to populate and setup the database.
- How to setup (e.g. modifying any configuration files) and run your RESTful API.
- The URL to access your API (usually nameofapplication/api/version/)=> the path to your application. We mean the entry point, the main endpoint of your API.
NOTE: Your code MUST be clearly documented. For each public method/function you must provide: a short description of the method, input parameters, output parameters, exceptions (when the application can fail and how to handle such fail). In addition should be clear which is the code you have implemented yourself and which is the code that you have borrowed from other sources or generated with the help of AI. Always provide a link to the original source. This includes links to the course material.
✏️ You do not need to write anything in this section, just complete the implementation.
💻 TODO: SOFTWARE TO DELIVER IN THIS SECTION
The code repository must contain:- The code to test your RESTful API (Functional test)
- The code of the test MUST be commented indicating what you are going to test in each test case.
- The test must include values that force error messages
- The external libraries that you have used
- We recommend to include a set of scripts to execute your tests.
- A database file or the necessary files and scripts to automatically populate your database.
- A README.md file containing:
- Dependencies (external libraries)
- Instructions on how to run the different tests for your application.
Remember that you MUST implement a functional testing suite. A detailed description of the input / output in the a REST client plugin.
In this section it is your responsibility that your API handles requests correctly. All of the supported methods for each resource should work. You also need to show that invalid requests are properly handled, and that the response codes are correct in each situation.
✏️ Most important part of this section is completing the implementation. Write down here a short reflection on which are the main errors you have solved thanks to the functional tests.
We implemented a functional ing script using pytest and Flask’s test client to verify that all of our methods of Shipments and Readings resources work correctly.
The tests simulate real HTTP requests to the API endpoints and validate the following cases:
- Correct HTTP status codes
- Correct JSON response structure
- Presence of the
Locationheader for201 Created - Proper handling of invalid requests
Both successful and failing scenarios were tested.
-
Error handler signature problem
During testing, a
TypeErrorwas detected in the custom 404 error handler.
Flask automatically passes the error object to error handlers, but the function did not accept any parameters. After modifying the handler to accept the error argument, the issue was resolved. -
Application factory test configuration
Initially, the application factory did not allow a separate configuration for testing.
This made it difficult to run tests without Docker and PostgreSQL.
We updatedcreate_app()to accept a test configuration so that tests can run using an in-memory SQLite database. -
Validation of error responses
Functional tests verified that the API correctly handles invalid requests:
-
415 Unsupported Media Typeis returned when JSON is missing. -
400 Bad Requestis returned when schema validation fails. -
404 Not Foundis returned for non-existing resources. -
403 Forbiddenis returned when deleting a shipment without a valid API key.
-
-
Delete operation verification
Our tests confirmed that after deleting a shipment, subsequent GET requests return
404 Not Found, ensuring that the resource was properly removed from the database.
The functional tests help us check whether:
- All supported HTTP methods work as expected.
- Error handling behaves consistently.
- The API respects REST principles in terms of response codes and behavior.
📑 Content that must be included in the section
Explain briefly how your API meets REST principles. Focus specially in presenting the 4 principles: Addressability, Uniform interface, Statelessness and Connectedness. Provide examples (e.g. how does each HTTP method work in your API).The ChillSense API follows REST architectural principles as described below.
Each resource is uniquely identified by a URI. The API exposes the following resource URIs:
/api/shipments/api/shipments/<shipment>/api/shipments/<shipment>/readings/api/shipments/<shipment>/readings/<reading>
Shipments and readings are treated as separate resources. Readings are nested under shipments to reflect the logical relationship between them. Each individual resource can be directly accessed using its URI.
The API uses HTTP methods consistently and according to REST principles.
-
GET /api/shipmentsRetrieve all shipments -
POST /api/shipmentsCreate a new shipment
-
GET /api/shipments/<shipment>Retrieve a specific shipment -
PUT /api/shipments/<shipment>Update a shipment -
DELETE /api/shipments/<shipment>Delete a shipment
-
GET /api/shipments/<shipment>/readingsRetrieve readings of a shipment -
POST /api/shipments/<shipment>/readingsCreate a reading for a shipment
-
GET /api/shipments/<shipment>/readings/<reading>Retrieve a reading -
PUT /api/shipments/<shipment>/readings/<reading>Update a reading
Each HTTP method has a clear and consistent responsibility across resources.
The API is stateless:
- Each request contains all the information needed to process it.
- The server does not store session data between requests.
- Resource identification is handled through URL parameters.
- Authentication (for DELETE operations) is handled using a request header (
Shipmenthub-Api-Key) without maintaining server-side sessions.
When new resources are created using POST, the API returns:
201 Created- A
Locationheader pointing to the URI of the newly created resource.
The API returns appropriate HTTP status codes:
-
200 OK→ Successful retrieval or update -
201 Created→ Successful creation -
204 No Content→ Successful deletion -
400 Bad Request→ Invalid input (e.g., schema validation errors) -
403 Forbidden→ Missing or invalid API key -
404 Not Found→ Resource does not exist -
415 Unsupported Media Type→ Missing or invalid JSON body
All resources are represented using JSON.
- Request bodies must be valid JSON.
- Responses return JSON objects or arrays.
- Input data is validated using JSON schema validation before being stored.
📑 Details on extra features
This section lists the additional features that will be graded as part of the API but are not required. In addition to implementing the feature you are also asked to write a short description for each. Please, note that you need to **document here** those aspects if you want to be graded. Is not enough to include them in the code.📑 Fill this section if you used URL converters
Write a short rationale of how URL converters are used, including your thoughts on the possible trade-offs. Go through all URL parameters in your API and describe whether they use a converter, what property is used for converting, or why it's not using a converter.✏️ Write your text here
- 2 converters have been defined:
-
ShipmentConverter: convertsshipment_idon the URL into aShipment object. -
ReadingConverter: convertsreading_idon URL intoReading object.
-
- URLs using converters:
- /shipments/shipment:shipment: converts
shipment_idto aShipment object. - /shipments/shipment:shipment/readings: converts
shipment_idto aShipment object. - /shipments/shipment:shipment/readings/reading:reading: both shipment and reading use converters. It converts
shipment_idandreading_idtoobjects.
- /shipments/shipment:shipment: converts
- Benefits: helps to make code shorter, reduces duplication of methods. Reduces manual error handling.
- Trade-off: can make the code harder to read for new developers
📑 Fill this section if you used JSON schema validation
Write a short description of your JSON schemas, including key decision making for choosing how to validate each field.✏️ Write your text here
- The APIs use JSON Schema to validate input data for the resources: Shipment and Reading. Each model has a static
json_schema()function that returns the schema for validation. - The required fields are clearly specified:
- Shipment: name, origin, and destination are mandatory.
- Reading: temp and shipment_id are mandatory.
- And the data types of each field are clearly defined as string, number etc.
- Reasons for choosing validation: ensures data is valid before adding to the database, facilitates debugging with detailed error codes for both developers and clients.
- Comment: Pydantic maybe a good alternative to consider.
📑 Fill this section if you implemented server side caching
Explain your caching decisions here. Include an explanation for every GET method in your API, explaining what is cached (or why it is not cached), and how long is it cached (and why). If you are using manual cache clearing, also explain when it happens.✏️ Write your text here
- The system uses Flask-Caching with FileSystemCache to store server-side cache. The cache is configured in
src/__init__.py:- CACHE_TYPE = "FileSystemCache"
- CACHE_DIR = instance/cache
- This helps increase performance for GET endpoints, reducing database query load.
-
GET /api/shipmentsuses cache. Because the shipment list is frequently queried and doesn't require constant updates from the sensors, caching helps reduce the load on the database. - Manual Cache Clearing: when data changes occur (POST, PUT, DELETE), the cache will be manually cleared using the _clear_cache() function.
📑 Fill this section if you implemented authentication
Explain your authentication scheme here. Describe the authentication requirements for each resource in your API, and your reasoning for the decisions. In addition, provide a plan for how API keys will be distributed, even if the distribution is not currently implemented.✏️ Write your text here
- Each API Key can be associated with a specific shipment or as an admin key (full privileges). We are currently focusing on endpoints requiring changes to database data:
- Deleting a shipment: Only allowed with the admin API Key.
- API Key is sent via header (Shipmenthub-Api-Key: <API_KEY>) for authentication.
- Reasons for choosing API Keys: simple, easy to deploy for small systems, and easy to manage access rights.
- API Key Distribution Plan:
- API Keys will be generated and stored in the database upon system initialization
- Users will receive API Keys via email, SMS, or the management UI (not implemented yet).
📝 If you have use AI during this deliverable, explain what tool/s you have used and how.
We used AI as a proofreading tool to correct typos.
And to fix something in cache. Because our project structure differs from exercise 2, so it needs something else like cache.init_app(app); and does not need page in cache key, since our project currently get all shipments from db instead of pagination.
| Task | Student | Estimated time |
|---|---|---|
| .... | Sajjad Ghaminejad and Hieu Nguyen | 2 hours |
| Improved code quality and refactored duplicate logic (pylint fixes, docstrings, removed unused imports, reduced warnings) | Sajjad Ghaminejad | 2 hours |
| Implemented Readings API (GET, POST, PUT) with validation and DB integration | Sajjad Ghaeminejad | 5 hours |
| Implemented Shipment API (GET, POST, PUT, DELETE) with full CRUD and error handling | Sajjad Ghaeminejad | 7 hours |
| Dockerized API application and configured PostgreSQL integration and DB initialization | Sajjad Ghaeminejad | 2.5 hours |
| Implemented functional tests for Shipments and Readings APIs with full error-case coverage | Sajjad Ghaeminejad | 10 hours |
| Review code, improve code, support tasks plan to keep on track | Hieu Nguyen | 10.5 hours |
| Updated db_init, and do extras task in this phase, improve code | Hieu Nguyen | 11 hours |