Welcome to beginning of Act II – we will begin to use the Python programming language to work towards creating cloud-based services for the remaining of the semester.
Many cloud services are wrappers around other tools with easy-to-use API interfaces for users and developers to easily interact with the tools. For this MP, you will create a web service that “wraps” your
mp2 solution to create a web-based microservice that will extracts hidden GIFs from within PNGs.
For extra credit, you can place it all in a docker container!
In your CS 240 directory, merge the initial starting files with the following commands:
git fetch release git merge release/mp6 --allow-unrelated-histories -m "Merging initial files"
MP Overview Session
An MP Overview was held by Eunice on Monday, March 7 at 11:00am.
The recording can be found at https://mediaspace.illinois.edu/media/t/1_s3fc5aui.
The slide can be found at https://courses.grainger.illinois.edu/cs240/sp2022/static/mp-overviews/MP6 Overview Session.pdf.
We have split the implementation into two parts:
- Implementing a flask-based web service.
- Packaging the above flask-application in a docker container (extra credit).
In your solution, you can modify any file in your
/mp6 directory except the following files:
Part 1: Flask Application
app.py program using the Python
flask library to create a web-based service that accepts a PNG file (as
png in the
POST data) via a HTTP
POST request to
- If the PNG file has a hidden GIF image (as defined by mp2), the hidden GIF file is returned.
- If the PNG file does not have a hidden GIF image (or is an invalid PNG file), an
HTTP 500response is returned with some useful status text.
This MP requires a modern version of Python (ex: 3.8+). If you are running on the VM, follow our guide to getting your VM setup with Python.
Once Python is installed, you will need to install the Flask library. Using native Python, this can be done via:
pip install flask
For this MP, the complete
flask code is provided for you in the provided
from flask import Flask app = Flask(__name__) # Route for "/" for a web-based interface to this microservice: @app.route('/') def index(): return render_template("index.html") # Extract a hidden "uiuc" GIF from a PNG image: @app.route('/extract', methods=["POST"]) def extract_hidden_gif(): # ...your code here...
To run this program, run:
python3.9 -m flask run(or
python3 -m flask runon some systems, or
python -m flask runor the shorthand
flask run) to launch your
- Follow the instructions on the console to view your microservice in your web browser.
Now you need to complete the
extract_hidden_gif to make your microservice work! :)
Using Your MP2
As part of the
extract_hidden_gif, you will need to use your mp2
png-extractGIF program. You may want to verify that your
png-extractGIF program is complete and functional and that you can run the following commands:
- We have provided a
Makefileso you can use
png-extractGIF. This uses your code from your
- Testing using a PNG with a hidden GIF:
./png-extractGIF sample/waf.png taylor.gif. (This should successfully save
- Testing using a PNG without a
./png-extractGIF sample/no-uiuc-chunk.png nothing.gif. (This should run, not crash, and probably return a non-zero value from
You may need to modify your MP2 program slightly to fix any bugs to ensure your program can work with your new microservice.
Useful Python Functions
There will be a few tasks you will need to complete in Python:
- You will need to save the contents of the
.pngfile). For this purpose, your application should create a
tempdirectory if it doesn’t exist, so you can save the contents in this directory with a unique filename.
- You can use the python
- The contents of the data sent via
POSTis stored by flask in the variable
- You can find many examples of reading and writing files in Python via a search.
- You can use the python
You will need to programmatically run your
./png-extractGIFprogram. To do this, you will likely use the python
os.systemfunction. This function will return the exit value from
png-extractGIF. If you followed our code style, the exit value should be
0on success and non-zero on failure.
Once you have the GIF file saved, you will likely want to use flask’s
send_filefunction to send the GIF file.
- If anything goes wrong, you can
return "Error Message", 500to return an error (but change “Error Message” to something useful).
Testing Your Microservice
You can test your program in two different ways:
By using your web browser and visiting your flask server (ex:
By the command line, using
curlto make a request to your web server:
curl -f -o output.gif http://localhost:5000/extract -F "png=@sample/waf.png"
- You can replace
@sample/waf.pngwith another file. Ensure that you keep the
@symbol to tell
curlto send the contents of the file.
- You should inspect
output.gifto ensure the extraction was successful.
- Make sure that you get an error when sending it an invalid PNG file.
- Make sure you also get an error when sending it a PNG file without a hidden
- You can replace
Extra Credit: Packaging as a Docker Container
For +5 extra credit points, you will wrap your above flask application in a docker container.
You need to complete the
Dockerfile that will run your flask application in a container. Specifically, it must:
- Launch the
- Be accessible on the host computer at
http://127.0.0.1:5000/just like you weren’t running in docker.
You will need to have
docker to complete this extra credit. The easiest way to install
docker is to download the free Docker Desktop.
Building and Running the Docker
You need to make sure you specify the correct
DOCKER_RUN_COMMAND in the
.env file. We will use the command specified in the
.env file to launch your docker container.
pytest test_docker.py to run tests corresponding to the docker container.
Note: Running these tests locally will require you to install other python dependencies included in the
requirements.txt. You can install these python libraries using
pip install -r requirements.txt.
Note: The test script doesn’t automatically kill the docker container it launches. Once you run the tests for the docker container, run
docker container ls to identify the container name and then run
docker kill <container-name> to kill the corresponding container, otherwise you might get an error saying the port is already occupied.
Python Debugger in VSCode
If you are using VS Code and would like to set up a visual debugger for Python, we recommend checking out this guide.
When you have completed your program, double-check that your server runs as expected with a GIF image that has hidden data and a GIF image without hidden data. When you are ready, submit the code via the following git commands:
Note: Please run
make clean before submitting your code.
git add -u git commit -m "MP6 submission" git push origin master
You can verify your code was successfully submitted by viewing your git repo on https://github.com.