|
|
|
@ -1,14 +1,12 @@
|
|
|
|
|
package main
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"errors"
|
|
|
|
|
"fmt"
|
|
|
|
|
"net/http"
|
|
|
|
|
"strconv"
|
|
|
|
|
"time"
|
|
|
|
|
|
|
|
|
|
"git.runcible.io/learning/pulley/internal/data"
|
|
|
|
|
"git.runcible.io/learning/pulley/internal/validator"
|
|
|
|
|
"github.com/julienschmidt/httprouter"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
func (app *application) createMovieHandler(w http.ResponseWriter, r *http.Request) {
|
|
|
|
@ -49,13 +47,23 @@ func (app *application) createMovieHandler(w http.ResponseWriter, r *http.Reques
|
|
|
|
|
app.failedValidationResponse(w, r, v.Errors)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// TODO save to DB
|
|
|
|
|
// We can implement a timeout context if we would like here
|
|
|
|
|
ctx := r.Context()
|
|
|
|
|
|
|
|
|
|
// Dump the contents of the input struct in a HTTP response
|
|
|
|
|
// +v is the default format value plus field names for structs
|
|
|
|
|
w.WriteHeader(http.StatusCreated)
|
|
|
|
|
fmt.Fprintf(w, "%+v\n", input)
|
|
|
|
|
err = app.models.Movies.Insert(ctx, m)
|
|
|
|
|
if err != nil {
|
|
|
|
|
app.serverErrorResponse(w, r, err)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Include location headers in HTTP response for newly created resource
|
|
|
|
|
headers := make(http.Header)
|
|
|
|
|
headers.Set("Location", fmt.Sprintf("/v1/movies/%d", m.ID))
|
|
|
|
|
|
|
|
|
|
// Write a JSON 201 Response with movie data in the response body and Location header
|
|
|
|
|
err = app.writeJSON(w, http.StatusCreated, envelope{"movie": m}, headers)
|
|
|
|
|
if err != nil {
|
|
|
|
|
app.serverErrorResponse(w, r, err)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (app *application) getMovieHandler(w http.ResponseWriter, r *http.Request) {
|
|
|
|
@ -64,25 +72,28 @@ func (app *application) getMovieHandler(w http.ResponseWriter, r *http.Request)
|
|
|
|
|
// retrieve a slice containing these parameter names and values.
|
|
|
|
|
|
|
|
|
|
// TODO refactor id retrieval to an app.readIDParam receiver
|
|
|
|
|
params := httprouter.ParamsFromContext(r.Context())
|
|
|
|
|
// params := httprouter.ParamsFromContext(r.Context())
|
|
|
|
|
|
|
|
|
|
// id, err := strconv.ParseInt(params.ByName("id"), 10, 64)
|
|
|
|
|
|
|
|
|
|
id, err := strconv.ParseInt(params.ByName("id"), 10, 64)
|
|
|
|
|
id, err := app.readIDParam(r)
|
|
|
|
|
|
|
|
|
|
if err != nil || id < 1 {
|
|
|
|
|
// http.NotFound(w, r)
|
|
|
|
|
if err != nil {
|
|
|
|
|
app.notFoundResponse(w, r)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
movie := data.Movie{
|
|
|
|
|
ID: id,
|
|
|
|
|
CreatedAt: time.Now(),
|
|
|
|
|
Title: "Eisenhorn",
|
|
|
|
|
// Runtime: 102,
|
|
|
|
|
Genres: []string{"sci-fi", "action"},
|
|
|
|
|
Version: 1,
|
|
|
|
|
movie, err := app.models.Movies.Get(r.Context(), id)
|
|
|
|
|
if err != nil {
|
|
|
|
|
switch {
|
|
|
|
|
case errors.Is(err, data.ErrRecordNotFound):
|
|
|
|
|
app.notFoundResponse(w, r)
|
|
|
|
|
return
|
|
|
|
|
default:
|
|
|
|
|
app.serverErrorResponse(w, r, err)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
app.logger.Info("Hit the get movies and found", "movie", movie.Title)
|
|
|
|
|
|
|
|
|
|
err = app.writeJSON(w, http.StatusOK, envelope{"movie": movie}, nil)
|
|
|
|
|
if err != nil {
|
|
|
|
@ -92,6 +103,62 @@ func (app *application) getMovieHandler(w http.ResponseWriter, r *http.Request)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (app *application) updateMovieHandler(w http.ResponseWriter, r *http.Request) {
|
|
|
|
|
|
|
|
|
|
id, err := app.readIDParam(r)
|
|
|
|
|
if err != nil {
|
|
|
|
|
app.notFoundResponse(w, r)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
movie, err := app.models.Movies.Get(r.Context(), id)
|
|
|
|
|
if err != nil {
|
|
|
|
|
switch {
|
|
|
|
|
case errors.Is(err, data.ErrRecordNotFound):
|
|
|
|
|
app.notFoundResponse(w, r)
|
|
|
|
|
default:
|
|
|
|
|
app.serverErrorResponse(w, r, err)
|
|
|
|
|
}
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var input struct {
|
|
|
|
|
Title string `json:"title"`
|
|
|
|
|
Year int32 `json:"year"`
|
|
|
|
|
Runtime data.Runtime `json:"runtime"`
|
|
|
|
|
Genres []string `json:"genres"`
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
err = app.readJSON(w, r, &input)
|
|
|
|
|
if err != nil {
|
|
|
|
|
app.badRequestResponse(w, r, err)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
movie.Title = input.Title
|
|
|
|
|
movie.Year = input.Year
|
|
|
|
|
movie.Runtime = input.Runtime
|
|
|
|
|
movie.Genres = input.Genres
|
|
|
|
|
|
|
|
|
|
v := validator.New()
|
|
|
|
|
|
|
|
|
|
if validator.ValidateMovie(v, movie); !v.Valid() {
|
|
|
|
|
app.failedValidationResponse(w, r, v.Errors)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
err = app.models.Movies.Update(r.Context(), movie)
|
|
|
|
|
if err != nil {
|
|
|
|
|
app.serverErrorResponse(w, r, err)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
err = app.writeJSON(w, http.StatusOK, envelope{"movie": movie}, nil)
|
|
|
|
|
if err != nil {
|
|
|
|
|
app.serverErrorResponse(w, r, err)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (app *application) healthCheckHandler(w http.ResponseWriter, r *http.Request) {
|
|
|
|
|
// JSON has to be double quoted. FYI you would never really do this
|
|
|
|
|
// js := `{"status": "available", "environment": %q, "version": %q}`
|
|
|
|
|