Develop web servers in Python in 2 versions: a first simple synchronous (sync) web server using only the socket module and second an asynchronous (async) web server using the aiohttp framework.
-
Synchronous (Sync) Web Server:
- Create a simple synchronous web server using the
socketmodule. - The sync server should listen on
localhostat port 8001. - Implement a single route /hello that responds with a plain text message "Hello, World!".
- Demonstrate handling HTTP requests synchronously.
- Create a simple synchronous web server using the
-
Asynchronous (Async) Web Server:
- Create an asynchronous web server using the
aiohttpframework. - The async server should listen on
localhostat port 8002. - Implement two routes:
- Route 1: /hello - Respond with a plain text message "Hello, World!".
- Route 2: /echo - Accept POST requests. Respond with the JSON representation of the received POST data.
- Use asynchronous programming features provided by
aiohttp. - Demonstrate the use of asynchronous functions,
asyncio, and theaiohttplibrary to handle requests concurrently.
- Create an asynchronous web server using the
-
External API:
- Create a
packagein core directory for both servers to call any external Weather server with open API (I propose to use this one). - Add endpoint /weather for both servers and use a single common code without duplication.
- Parse all incoming data with
Pydanticmodels and handle it in console somewhere.
- Create a
-
Middleware:
- Implement a middleware that adds a custom header to every response.
-
Error Handling:
- Implement error handling for common HTTP errors (e.g., 404 Not Found, 500 Internal Server Error).
-
Dockerization (Optional):
- Create a Dockerfile for each server to containerize both the sync and async applications.
-
Tests:
- Write unit tests using
pytestfor the main functionality of both the sync and async servers.
- Write unit tests using
-
Stress-test
- Add in each server several endpoints to simulate I/O & CPU bound tasks and something else to simulate error on server-side e.g. /io_task, /cpu_task, /error_task, etc.
- Install
locustpackage in your local env and write a script to stress-test two servers. - It would be cool to plot a graph on the data obtained from locust and put it in the documentation.
- All Python code MUST be typed (the
typingmodule to your rescue). - Implement the project according to the
PEP8standard should be described in thetoolsection of the pyproject.toml for linters with some modifications:- String length should be 120 characters.
- Count of lines after import should be 2.
- The rest is by specification.
Pytestconfigs also should be in in thetoolsection of the pyproject.toml.- Commit style, click. Commits should contain small logical portions of the code being modified. A clear commit name is required, descriptions within commits are welcome. The commit header should be up to 50 characters and the description up to 72 characters, read more.
- Branch style, click. It is suggested to use GitFlow. Don't forget to delete merged or close branches based on PR status. Development should be done in separate branches, it is not allowed to commit or merge changes directly into master or develop.
- Commits, branches and PR's should contain small pieces of separate logic so that it can be revisited. There is EXAMPLE, how to decompose and get started (documentation should also be also updated):
- The first PR would be enough to see poetry installed and a project structure.
- The second PR sync server.
- The third PR async server.
- The fourth PR Docker.
- The fifth PR external API call.
- Try to follow all OOP & design principles.
- Submit the codebase along with a detailed README explaining how to set up and run the monolithic application, any additional features implemented, and any challenges faced. Here is a good cheat-list how to style documentation.
- Fork this repository and do your development there.
- Use Python 3.10 or above.
- Feel free to use any additional libraries or tools you find suitable for the task.
- Try decomposing tasks into chunks and branches as described above.
- All
highlightedwords should be read in the documentation or familiarized with what they are. - Follow best practices in terms of code readability, structure, and documentation.
./
├── src/
│ ├── app/
│ │ ├── async/
│ │ │ ├── __init__.py
│ │ │ └── main.py
│ │ ├── sync/
│ │ │ ├── __init__.py
│ │ │ └── main.py
│ │ └── __init__.py
│ ├── core/
│ │ └── __init__.py
│ └── __init__.py
├── README.md
└── task.md