From e0931223e4ad7a65009b61865667af563e4ec82d Mon Sep 17 00:00:00 2001 From: Maxime Delporte Date: Fri, 10 Oct 2025 16:15:30 +0200 Subject: [PATCH] Adding httprouter dependency to manage endpoints. Adding our routes to routes.go file facilitating endpoints management and adding POST /v1/movies and GET /v1/movies/:id endpoints. Updating main.go file removing ServeMux and add httprouter instead in app structure. Creating movies.go file to manage create and show movie endpoint. --- .idea/dictionaries/project.xml | 8 +++++++ cmd/api/main.go | 9 +------- cmd/api/movies.go | 40 ++++++++++++++++++++++++++++++++++ cmd/api/routes.go | 24 ++++++++++++++++++++ go.mod | 2 ++ go.sum | 2 ++ 6 files changed, 77 insertions(+), 8 deletions(-) create mode 100644 .idea/dictionaries/project.xml create mode 100644 cmd/api/movies.go create mode 100644 cmd/api/routes.go create mode 100644 go.sum diff --git a/.idea/dictionaries/project.xml b/.idea/dictionaries/project.xml new file mode 100644 index 0000000..10e27c6 --- /dev/null +++ b/.idea/dictionaries/project.xml @@ -0,0 +1,8 @@ + + + + httprouter + servemux + + + \ No newline at end of file diff --git a/cmd/api/main.go b/cmd/api/main.go index ad26af5..2ece088 100644 --- a/cmd/api/main.go +++ b/cmd/api/main.go @@ -57,13 +57,6 @@ func main() { logger: logger, } - /* - Declare a new servemux and add a /v1/healthcheck route which dispatches requests - to the healthcheckHandler method. - */ - mux := http.NewServeMux() - mux.HandleFunc("/v1/healthcheck", app.healthcheckHandler) - /* Declare a HTTP server which listens on the port provided in the config struct, uses the servemux we created above as the handler, has some sensible timeout @@ -71,7 +64,7 @@ func main() { */ srv := &http.Server{ Addr: fmt.Sprintf(":%d", cfg.port), - Handler: mux, + Handler: app.routes(), IdleTimeout: time.Minute, ReadTimeout: 5 * time.Second, WriteTimeout: 10 * time.Second, diff --git a/cmd/api/movies.go b/cmd/api/movies.go new file mode 100644 index 0000000..a06beda --- /dev/null +++ b/cmd/api/movies.go @@ -0,0 +1,40 @@ +package main + +import ( + "fmt" + "github.com/julienschmidt/httprouter" + "net/http" + "strconv" +) + +// "POST /v1/movies" endpoint. +func (app *application) createMovieHandler(w http.ResponseWriter, r *http.Request) { + fmt.Fprintln(w, "create a new movie") +} + +// "GET /v1/movies/:id" +func (app *application) showMovieHandler(w http.ResponseWriter, r *http.Request) { + /* + When httprouter is parsing a request, any interpolated URL parameters will be + stored in the request context. We can use the ParamsFromContext() function to + retrieve a slice containing these parameter names and values. + */ + params := httprouter.ParamsFromContext(r.Context()) + + /* + We can then use the ByName() method to get the value of the "id" parameter from + the slice. In our project all movies will have a unique positive integer ID, but + the value returned by ByName() is always a string. So we try to convert it to a + base 1° integer (with a bit size of 64). If the parameter couldn't be converted, + or is less than 1, we know the ID is invalid so we use the http.NotFound() + func to return a 404 Not Found Response. + */ + id, err := strconv.ParseInt(params.ByName("id"), 10, 64) + if err != nil || id < 1 { + http.NotFound(w, r) + return + } + + // Otherwise, interpolate the movie ID in a placeholder response. + fmt.Fprintf(w, "show the details of movie %d\n", id) +} diff --git a/cmd/api/routes.go b/cmd/api/routes.go new file mode 100644 index 0000000..2750931 --- /dev/null +++ b/cmd/api/routes.go @@ -0,0 +1,24 @@ +package main + +import ( + "github.com/julienschmidt/httprouter" + "net/http" +) + +func (app *application) routes() http.Handler { + // Initialize a new httprouter router instance + router := httprouter.New() + + /* + Register the relevant methods, URL patterns and handler functions for our + endpoints using the HandlerFunc() method. Note that http.MethodGet and + http.MethodPost are constants which equate to the strings "GET" and "POST" + respectively. + */ + router.HandlerFunc(http.MethodGet, "/v1/healthcheck", app.healthcheckHandler) + router.HandlerFunc(http.MethodPost, "/v1/movies", app.createMovieHandler) + router.HandlerFunc(http.MethodGet, "/v1/movies/:id", app.showMovieHandler) + + // Return the httprouter instance. + return router +} diff --git a/go.mod b/go.mod index 291b0fb..e9258b3 100644 --- a/go.mod +++ b/go.mod @@ -1,3 +1,5 @@ module greenlight.craftr.fr go 1.25.1 + +require github.com/julienschmidt/httprouter v1.3.0 // indirect diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..096c54e --- /dev/null +++ b/go.sum @@ -0,0 +1,2 @@ +github.com/julienschmidt/httprouter v1.3.0 h1:U0609e9tgbseu3rBINet9P48AI/D3oJs4dN7jwJOQ1U= +github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM=