Start learning free

LESSON 118 OF 173 · BACKEND: PAYMENTS AND OTHER SERVICES

Check Uploads

Practice

Right now the shop stores any file of any size. Someone uploads page.html, a web page with a script in it, and the GET photo route serves it as text/html from your shop's own address: the browser runs the script as if your shop had written it. Someone else uploads a huge video, and the database fills up. So an upload checks rules before it stores anything.

A rule can be a slice of allowed values, kept in a variable at the top of the file. slices.Contains tells whether a value is in it, and ! refuses everything else. For example, on another value:

var currencies = []string{"USD", "EUR"}

app.HandleFunc("GET /prices", func(w http.ResponseWriter, r *http.Request) {
    currency := r.URL.Query().Get("currency")
    if !slices.Contains(currencies, currency) {
        writeJSON(w, 400, map[string]string{"error": "Unknown currency"})
        return
    }
    ...
})

Find a file's type from its name with mime.TypeByExtension(filepath.Ext(header.Filename)), the same way the GET photo route does when it serves it; a name with no extension gives the empty string "". Two statuses say what's wrong: 415 Unsupported Media Type ("I don't take this kind of file") and 413 Content Too Large. Exactly 1000 bytes is still fine. writeJSON sends an answer but doesn't stop the handler, so each refusal needs its own return.

POST /products/1/photo  (photo: mug.png, 16 bytes)  →  201  {"filename": "mug.png", "product_id": 1, "size": 16}
POST /products/1/photo  (photo: page.html)  →  415  {"error": "Only PNG and JPEG photos"}
POST /products/1/photo  (photo: mug, no extension)  →  415  {"error": "Only PNG and JPEG photos"}
POST /products/3/photo  (photo: lamp.jpg, 1001 bytes)  →  413  {"error": "The photo is larger than 1000 bytes"}
POST /products/3/photo  (photo: lamp.jpg, 1000 bytes)  →  201  {"filename": "lamp.jpg", "product_id": 3, "size": 1000}
POST /products/5/photo  (photo: Plant.JPG, 18 bytes)  →  201  {"filename": "Plant.JPG", "product_id": 5, "size": 18}
GET /products/1/photo  →  200  (image/png, 16 bytes)

Your task: add the variable photoTypes ("image/png" and "image/jpeg") and the constant maxPhotoBytes (1000), then make the upload route answer 415 for any other type and 413 for a file over 1000 bytes, and return before it stores anything.


Assignment
Follow the Coding Tutorial to add the two upload rules.


Hint
Check the type right after the err check of FormFile, and the size right after reading the bytes. Use > for the size, not >=: a file of exactly 1000 bytes is allowed. Put a return under each writeJSON.


STEP 1 OF 9
    Ctrl + Enter to check