CodeBlanks Logo Icon CodeBlanks

Challenge 2 - Microservice

Write a service with HTTP API + database + Docker.

Challenge: a robust service

You will combine three pieces that make an HTTP service production-ready: middleware that adds a request ID, recover middleware that turns panics into 500, and a mux serving only the GET /urunler/{id} route. An unknown id returns 404.

chain: recoverMW → istekID → mux
GET /urunler/1  → 200 "Kalem"
GET /urunler/9  → 404

Plan

1) urunler := map[string]string{"1": "Kalem"}. 2) Look up with r.PathValue("id") inside mux.HandleFunc("GET /urunler/{id}", ...). 3) h := recoverMW(istekID(mux)). 4) Send two requests with httptest and print the codes. Write the middleware as in earlier groups; order matters: recover outermost.

Practice Build the service

Implement the plan above. Print the status codes of GET /urunler/1 and GET /urunler/9 on one line.

Starter code

main.go
package main

import (
    "fmt"
    "net/http"
    "net/http/httptest"
)

func main() {
    // buraya yaz
}

Sample solution

main.go
package main

import (
    "fmt"
    "net/http"
    "net/http/httptest"
)

func recoverMW(next http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        defer func() {
            if v := recover(); v != nil {
                http.Error(w, "sunucu hatası", 500)
            }
        }()
        next.ServeHTTP(w, r)
    })
}

func istekID(next http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        w.Header().Set("X-Request-ID", "r1")
        next.ServeHTTP(w, r)
    })
}

func main() {
    urunler := map[string]string{"1": "Kalem"}
    mux := http.NewServeMux()
    mux.HandleFunc("GET /urunler/{id}", func(w http.ResponseWriter, r *http.Request) {
        ad, ok := urunler[r.PathValue("id")]
        if !ok {
            http.NotFound(w, r)
            return
        }
        fmt.Fprint(w, ad)
    })
    h := recoverMW(istekID(mux))
    kod := func(yol string) int {
        rec := httptest.NewRecorder()
        h.ServeHTTP(rec, httptest.NewRequest("GET", yol, nil))
        return rec.Code
    }
    fmt.Println(kod("/urunler/1"), kod("/urunler/9"))
}

Expected output

200 404

Questions and answers

Review the lesson questions together with their answers. To test yourself, solve the lesson interactively.

1 If you read the route id and don't find it in the map, what do you do?

  • Return 200 with an empty body
  • Shut the server down
  • Return 404 with http.NotFound(w, r) Correct answer
  • Call panic

Explanation: A missing resource is an expected case; it is reported with 404, not a panic.

2 Path variable

Question
ad, ok := urunler[r.____("id")]
Answer
ad, ok := urunler[r.PathValue("id")]

Explanation: PathValue reads the {id} variable from the route pattern.

3 Piece and role

Term Meaning
recoverMW Panic → 500
istekID X-Request-ID
mux Routing
http.NotFound 404 response

All lessons in Advanced