Fixing an API You Inherited
Goal
You will be able to find and fix four defects, judging only by the symptoms, in an API handed over to you in a state where neither the tests nor the documentation can be trusted.
Why it matters
The defects in this lab are all of the kind that return 200 while giving a wrong value. Monitoring catches bugs that throw exceptions, but bugs that return plausible-looking numbers are discovered months later when the accounting does not add up. That is why you need the procedure of first turning the spec into an input/output table and trying boundary values.
The status code distinction in the last step is not decoration either. 400 means "you sent it wrong," and 500 means "I broke while handling it," and most client libraries treat only 5xx as retryable. If you return 500 for a wrong parameter, a request that will fail forever is retried endlessly and only raises the server load. A status code is a promise read by machines, not by people.
The original spec is written in the docstring of /opt/app/server.py. The places where the code disagrees with that spec are the bug list.
Steps
- Copy
/opt/app/server.pyto/root/app/server.py. From then on, edit only this copy. - Run the copy so that
127.0.0.1:8000/healthresponds. - Fix it so that
/sum?a=2&b=3returns5. - Check that
/sum?a=10&b=32returns42and/sum?a=-4&b=9returns5. - Fix it so that
/avg?nums=2,4,9returns5and/avg?nums=10returns10. It is a floor average. - Fix it so that
/upper?s=fdereturnsFDE. - Fix it so that
/orders/totalreturns130400with 200. The conditions for a valid row are in the docstring. - Make
/sum?a=2and/sum?a=x&b=1each return400. The original code already returns the404for/nope, so you only need to check it — the only thing to fix is the argument handling of/sum. The knack of this step is to first measure what is already working.
Notes
- After fixing, you must restart the server for the change to take effect. Use
kill %1and run it again, or usepkill -f server.py. - With
curl -s -o /dev/null -w '%{http_code}\n' URLyou can see only the status code. - Common mistake 1: editing the original
/opt/app/server.pydirectly. Grading looks only at the behavior on port 8000, but the habit of not touching the customer's files matters far more in the field. - Common mistake 2: deleting the malformed row from the file in step 7. The data must stay as it is, and the code must filter it.
Make a working copy
Copy /opt/app/server.py to /root/app/server.py. From then on, edit only this copy.
Not editing the original directly is the basic rule in the field. Copy /opt/app/server.py under /root/app/.
Start the server
Run the copy so that 127.0.0.1:8000/health responds.
If you run it with python3, it waits on 127.0.0.1:8000. You must restart it each time you fix something for the change to take effect.
Fix the addition result
Fix it so that /sum?a=2&b=3 returns 5.
Looking at the value that comes out for 2 and 3 immediately shows which operator was used. Find that one character in the file.
Check negative inputs too
Check that /sum?a=10&b=32 returns 42 and /sum?a=-4&b=9 returns 5.
This is the boundary value check step. If it is right even when the signs are mixed, you know it is truly addition.
Fix the average calculation
Fix it so that /avg?nums=2,4,9 returns 5 and /avg?nums=10 returns 10. It is a floor average.
Try it with three elements and with one element. It shows how far the divisor is off from the number of elements.
Fix the case conversion
Fix it so that /upper?s=fde returns FDE.
Check whether the endpoint name matches the string method that is actually called.
Keep the order total from crashing
Fix it so that /orders/total returns 130400 with 200. The conditions for a valid row are in the docstring.
The docstring lists three conditions for a valid row, but the code has no such branch. Just filter as the document says.
Return the right code for bad requests
Make /sum?a=2 and /sum?a=x&b=1 each return 400. The original code already returns the 404 for /nope, so you only need to check it — the only thing to fix is the argument handling of /sum. The knack of this step is to first measure what is already working.
When the parameter is missing or not a number, the server currently dies. A client's fault is a 4xx.