At this stage we will continue the project that we have created by creating a Delivery Layer. This layer as explained earlier is a layer that connects user requests with the logic layer.
In this layer we usually provide some validation for each request sent by the user so that later when sent to the usecase layer the request data is not empty or needs to be validated again.
Alright, let’s go straight to the delivery/http
folder and create the article.go
file. We created the http
folder because the handler we created is a REST API handler which is the http protocol.
Fill the above file with the following.
type Delivery struct {
articleUsecase usecase.ArticleUsecase
}
func New(articleUsecase usecase.ArticleUsecase) *Delivery {
return &Delivery{
articleUsecase: articleUsecase,
}
}
And we will also create the pkg/util/
folder which will be filled with files that handle the response from the API that we have created into the json
data type. Here is the pkg/util/response.go
file below.
package util
import (
"encoding/json"
"net/http"
)
func Response(w http.ResponseWriter, response interface{}, statusCode int) {
w.Header().Add("Content-Type", "application/json")
w.WriteHeader(statusCode)
encoder := json.NewEncoder(w)
err := encoder.Encode(response)
if err != nil {
panic(err)
}
}
Function Handler to Retrieve All Article Data
In this usecase, we will try to create a function to retrieve all article data with the function name GetAll()
as below.
func (d *Delivery) GetAll(w http.ResponseWriter, r *http.Request, params httprouter.Params) {
var response models.ArticleListResponse
var statusCode int = http.StatusBadRequest
defer func() {
util.Response(w, response, statusCode)
}()
res, err := d.articleUsecase.GetAll(r.Context())
if err != nil {
statusCode = http.StatusInternalServerError
response.Code = statusCode
response.Status = err.Error()
return
}
statusCode = http.StatusOK
response.Data = append(response.Data, res...)
response.Code = statusCode
response.Status = "OK"
}
Function Handler Retrieving Article ByID Data
The next process adds a function to the handler like this.
func (d *Delivery) GetByID(w http.ResponseWriter, r *http.Request, params httprouter.Params) {
var response models.ArticleListResponse
var statusCode int
defer func() {
util.Response(w, response, statusCode)
}()
articleIDString := params.ByName("article_id")
articleID, err := strconv.ParseInt(articleIDString, 0, 64)
if err != nil {
statusCode = http.StatusBadRequest
response.Code = statusCode
response.Status = err.Error()
return
}
res, err := d.articleUsecase.GetByID(r.Context(), articleID)
if err != nil {
statusCode = http.StatusInternalServerError
response.Code = statusCode
response.Status = err.Error()
return
}
if res.ID == 0 {
statusCode = http.StatusNotFound
response.Code = statusCode
response.Status = "data not found"
return
}
statusCode = http.StatusOK
response.Data = append(response.Data, res)
response.Code = statusCode
response.Status = "OK"
}
Kode Sumber 4.3. ## Handler Fungsi Update Data Artikel Seperti yang telah disinggung di atas, handler untuk mengupdate data tersebut akan mengakses usecase fungsi update seperti di bawah ini.
func (d *Pengiriman) Update(w http.ResponseWriter, r *http.Request, params httprouter.Params) {
var response models.ArticleListResponse
var request models.ArticleUpdateRequest
var statusCode = http.StatusBadRequest
defer func() {
util.Response(w, response, statusCode)
}()
articleIDString := params.ByName("article_id")
articleID, err := strconv.ParseInt(articleIDString, 0, 64)
if err != nil {
statusCode = http.StatusBadRequest
response.Code = statusCode
response.Status = err.Error()
return
}
decoder := json.NewDecoder(r.Body)
err = decoder.Decode(&request)
if err != nil {
statusCode = http.StatusBadRequest
response.Code = statusCode
response.Status = err.Error()
return
}
request.ID = articleID
err = d.validate.Struct(request)
if err != nil {
statusCode = http.StatusBadRequest
response.Code = statusCode
response.Status = err.Error()
return
}
res, err := d.articleUsecase.Update(r.Context(), request)
if err != nil {
statusCode = http.StatusInternalServerError
response.Code = statusCode
response.Status = err.Error()
return
}
statusCode = http.StatusOK
response.Data = append(response.Data, res)
response.Code = statusCode
response.Status = "OK"
}
Pada saat update ini kita memerlukan article_id
maka perlu ambil data tersebut dari parameter dengan mengambil id tersebut seperti di atas.
articleIDString := params.ByName("article_id")
Kemudian ketika kita ingin mengambil body dari suatu request protokol http kita bisa menggunakan decode juga untuk dikonversikan ke dalam struct yang sudah kita buat.
decoder := json.NewDecoder(r.Body)
err = decoder.Decode(&request)
Kode Sumber 4.4. ## Fungsi Handler Tambah Data Artikel Pada proses handler untuk menambah data artikel dapat kita lihat seperti di bawah ini.
func (d *Pengiriman) Store(w http.ResponseWriter, r *http.Request, params httprouter.Params) {
var response models.ArticleListResponse
var request models.ArticleCreateRequest
var statusCode int = http.StatusBadRequest
defer func() {
util.Response(w, response, statusCode)
}()
decoder := json.NewDecoder(r.Body)
err := decoder.Decode(&request)
if err != nil {
statusCode = http.StatusBadRequest
response.Code = statusCode
response.Status = err.Error()
return
}
err = d.validate.Struct(request)
if err != nil {
statusCode = http.StatusBadRequest
response.Code = statusCode
response.Status = err.Error()
return
}
res, err := d.articleUsecase.Store(r.Context(), request)
if err != nil {
statusCode = http.StatusInternalServerError
response.Code = statusCode
response.Status = err.Error()
return
}
response.Data = append(response.Data, res)
statusCode = http.StatusOK
response.Code = statusCode
response.Status = "OK"
}
Kode Sumber 4.7. ## Handler Fungsi Hapus Data Artikel Pada proses usecase hapus data kita membutuhkan parameter dan body request untuk diteruskan ke usecase seperti di bawah ini.
func (d *Pengiriman) Hapus(w http.ResponseWriter, r *http.Request, params httprouter.Params) {
var response models.ArticleListResponse
var statusCode int = http.StatusBadRequest
defer func() {
util.Response(w, response, statusCode)
}()
articleIDString := params.ByName("article_id")
articleID, err := strconv.ParseInt(articleIDString, 0, 64)
if err != nil {
statusCode = http.StatusBadRequest
response.Code = statusCode
response.Status = err.Error()
return
}
if articleID == 0 {
statusCode = http.StatusBadRequest
response.Code = statusCode
response.Status = "article_id bukan nol"
return
}
res, err := d.articleUsecase.Delete(r.Context(), articleID)
if err != nil {
statusCode = http.StatusInternalServerError
response.Code = statusCode
response.Status = err.Error()
return
}
if !res {
statusCode = http.StatusInternalServerError
response.Code = statusCode
response.Status = errors.New("error tidak diketahui").Error()
return
}
statusCode = http.StatusOK
response.Code = statusCode
response.Status = "OK"
}