Skip to content

Latest commit

 

History

History
392 lines (323 loc) · 9.66 KB

request-response-helper.md

File metadata and controls

392 lines (323 loc) · 9.66 KB

Request Response Helper

Decode Request dan set/write response adalah suatu kode yang ditulis berulang-ulang karena sering dipanggil. Untuk efisiensi dan memudahkan pemeliharaan kode, kita akan membuat hel request dan helper response

Request Helper

  • Buatlah file libraries/api/request.go
package api

import (
    "encoding/json"
    "net/http"
)

// Decode reads the body of an HTTP request looking for a JSON document. The
// body is decoded into the provided value.
func Decode(r *http.Request, val interface{}) error {
    if err := json.NewDecoder(r.Body).Decode(val); err != nil {
        return err
    }

    return nil
}
  • Ubah method Update pada file controllers/users.go agar memanggil helper request
// Update user by id
func (u *Users) Update(w http.ResponseWriter, r *http.Request) {
    paramID := r.Context().Value(api.Ctx("ps")).(httprouter.Params).ByName("id")
    id, err := strconv.Atoi(paramID)
    if err != nil {
        u.Log.Println("convert param to id", err)
        w.WriteHeader(http.StatusInternalServerError)
        return
    }

    user := new(models.User)
    user.ID = uint64(id)
    err = user.Get(u.Db)
    if err != nil {
        u.Log.Println("Get User", err)
        w.WriteHeader(http.StatusInternalServerError)
        return
    }

    userRequest := new(request.UserRequest)
    err = api.Decode(r, &userRequest)
    if err != nil {
        u.Log.Printf("error decode user: %s", err)
        w.WriteHeader(http.StatusInternalServerError)
        return
    }

    userUpdate := userRequest.Transform(user)
    err = userUpdate.Update(u.Db)
    if err != nil {
        u.Log.Printf("error update user: %s", err)
        w.WriteHeader(http.StatusInternalServerError)
        return
    }

    resp := new(response.UserResponse)
    resp.Transform(userUpdate)
    data, err := json.Marshal(resp)
    if err != nil {
        u.Log.Println("Marshall data user", err)
        w.WriteHeader(http.StatusInternalServerError)
        return
    }

    w.Header().Set("Content-Type", "application/json; charset=utf-8")
    w.WriteHeader(http.StatusOK)
    if _, err := w.Write(data); err != nil {
        u.Log.Println("error writing result", err)
    }
}
  • Ubah method Create pada file usecases/user_usecase.go agar memanggil helper request
// Create new user
func (u *UserUsecase) Create(r *http.Request) ([]byte, error) {
    var userRequest request.NewUserRequest
    var data []byte

    err := api.Decode(r, &userRequest)
    if err != nil {
        u.Log.Printf("error decode user: %s", err)
        return data, err
    }

    if userRequest.Password != userRequest.RePassword {
        err = errors.New("Password not match")
        u.Log.Printf("error : %s", err)
        return data, err
    }

    pass, err := bcrypt.GenerateFromPassword([]byte(userRequest.Password), bcrypt.DefaultCost)
    if err != nil {
        u.Log.Printf("error generate password: %s", err)
        return data, err
    }

    userRequest.Password = string(pass)

    user := userRequest.Transform()

    err = user.Create(u.Db)
    if err != nil {
        u.Log.Printf("error call create user: %s", err)
        return data, err
    }

    var res response.UserResponse
    res.Transform(user)
    data, err = json.Marshal(res)
    if err != nil {
        u.Log.Println("error marshalling result", err)
        return data, err
    }

    return data, nil
}

Response Helper

  • Buat file libraries/api/response.go
package api

import (
    "encoding/json"
    "net/http"
)

// Response converts a Go value to JSON and sends it to the client.
func Response(w http.ResponseWriter, data interface{}, statusCode int) error {

    // Convert the response value to JSON.
    res, err := json.Marshal(data)
    if err != nil {
        return err
    }

    // Respond with the provided JSON.
    w.Header().Set("Content-Type", "application/json; charset=utf-8")
    w.WriteHeader(statusCode)
    if _, err := w.Write(res); err != nil {
        return err
    }

    return nil
}
  • Ubah file usecases/user_usecase.go menjadi
package usecases

import (
    "database/sql"
    "errors"
    "essentials/libraries/api"
    "essentials/payloads/request"
    "essentials/payloads/response"
    "log"
    "net/http"

    "golang.org/x/crypto/bcrypt"
)

// UserUsecase struct
type UserUsecase struct {
    Log *log.Logger
    Db  *sql.DB
}

// Create new user
func (u *UserUsecase) Create(r *http.Request) (response.UserResponse, error) {
    var userRequest request.NewUserRequest
    var res response.UserResponse

    err := api.Decode(r, &userRequest)
    if err != nil {
        u.Log.Printf("error decode user: %s", err)
        return res, err
    }

    if userRequest.Password != userRequest.RePassword {
        err = errors.New("Password not match")
        u.Log.Printf("error : %s", err)
        return res, err
    }

    pass, err := bcrypt.GenerateFromPassword([]byte(userRequest.Password), bcrypt.DefaultCost)
    if err != nil {
        u.Log.Printf("error generate password: %s", err)
        return res, err
    }

    userRequest.Password = string(pass)

    user := userRequest.Transform()

    err = user.Create(u.Db)
    if err != nil {
        u.Log.Printf("error call create user: %s", err)
        return res, err
    }

    res.Transform(user)
    return res, nil
}
  • Ubah file controllers/users.go menjadi
package controllers

import (
    "database/sql"
    "essentials/libraries/api"
    "essentials/models"
    "essentials/payloads/request"
    "essentials/payloads/response"
    "essentials/usecases"
    "log"
    "net/http"
    "strconv"

    "github.com/julienschmidt/httprouter"
)

// Users : struct for set Users Dependency Injection
type Users struct {
    Db  *sql.DB
    Log *log.Logger
}

// List : http handler for returning list of users
func (u *Users) List(w http.ResponseWriter, r *http.Request) {
    user := new(models.User)
    list, err := user.List(u.Db)
    if err != nil {
        u.Log.Println("get user list", err)
        w.WriteHeader(http.StatusInternalServerError)
        return
    }

    var respList []response.UserResponse
    for _, l := range list {
        var resp response.UserResponse
        resp.Transform(&l)
        respList = append(respList, resp)
    }

    if err = api.Response(w, respList, http.StatusOK); err != nil {
        u.Log.Println("error response", err)
        w.WriteHeader(http.StatusInternalServerError)
        return
    }
}

// Create new user
func (u *Users) Create(w http.ResponseWriter, r *http.Request) {

    uc := usecases.UserUsecase{Log: u.Log, Db: u.Db}
    resp, err := uc.Create(r)
    if err != nil {
        w.WriteHeader(http.StatusInternalServerError)
        return
    }

    if err = api.Response(w, resp, http.StatusOK); err != nil {
        u.Log.Println("error response", err)
        w.WriteHeader(http.StatusInternalServerError)
        return
    }
}

// View user by id
func (u *Users) View(w http.ResponseWriter, r *http.Request) {
    paramID := r.Context().Value(api.Ctx("ps")).(httprouter.Params).ByName("id")
    id, err := strconv.Atoi(paramID)
    if err != nil {
        u.Log.Println("convert param to id", err)
        w.WriteHeader(http.StatusInternalServerError)
        return
    }

    user := new(models.User)
    user.ID = uint64(id)
    err = user.Get(u.Db)
    if err != nil {
        u.Log.Println("Get User", err)
        w.WriteHeader(http.StatusInternalServerError)
        return
    }

    resp := new(response.UserResponse)
    resp.Transform(user)
    if err = api.Response(w, resp, http.StatusOK); err != nil {
        u.Log.Println("error response", err)
        w.WriteHeader(http.StatusInternalServerError)
        return
    }
}

// Update user by id
func (u *Users) Update(w http.ResponseWriter, r *http.Request) {
    paramID := r.Context().Value(api.Ctx("ps")).(httprouter.Params).ByName("id")
    id, err := strconv.Atoi(paramID)
    if err != nil {
        u.Log.Println("convert param to id", err)
        w.WriteHeader(http.StatusInternalServerError)
        return
    }

    user := new(models.User)
    user.ID = uint64(id)
    err = user.Get(u.Db)
    if err != nil {
        u.Log.Println("Get User", err)
        w.WriteHeader(http.StatusInternalServerError)
        return
    }

    userRequest := new(request.UserRequest)
    err = api.Decode(r, &userRequest)
    if err != nil {
        u.Log.Printf("error decode user: %s", err)
        w.WriteHeader(http.StatusInternalServerError)
        return
    }

    userUpdate := userRequest.Transform(user)
    err = userUpdate.Update(u.Db)
    if err != nil {
        u.Log.Printf("error update user: %s", err)
        w.WriteHeader(http.StatusInternalServerError)
        return
    }

    resp := new(response.UserResponse)
    resp.Transform(userUpdate)
    if err = api.Response(w, resp, http.StatusOK); err != nil {
        u.Log.Println("error response", err)
        w.WriteHeader(http.StatusInternalServerError)
        return
    }
}

// Delete user by id
func (u *Users) Delete(w http.ResponseWriter, r *http.Request) {
    paramID := r.Context().Value(api.Ctx("ps")).(httprouter.Params).ByName("id")
    id, err := strconv.Atoi(paramID)
    if err != nil {
        u.Log.Println("convert param to id", err)
        w.WriteHeader(http.StatusInternalServerError)
        return
    }

    user := new(models.User)
    user.ID = uint64(id)
    err = user.Get(u.Db)
    if err != nil {
        u.Log.Println("Get User", err)
        w.WriteHeader(http.StatusInternalServerError)
        return
    }

    err = user.Delete(u.Db)
    if err != nil {
        u.Log.Println("Delete User", err)
        w.WriteHeader(http.StatusInternalServerError)
        return
    }

    w.Header().Set("Content-Type", "application/json; charset=utf-8")
    w.WriteHeader(http.StatusNoContent)
}