07 Creating a Handler as a Data Delivery Layer
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.
1type Delivery struct {
2 articleUsecase usecase.ArticleUsecase
3}
4
5func New(articleUsecase usecase.ArticleUsecase) *Delivery {
6 return &Delivery{
7 articleUsecase: articleUsecase,
8 }
9}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.
1package util
2
3import (
4 "encoding/json"
5 "net/http"
6)
7
8func Response(w http.ResponseWriter, response interface{}, statusCode int) {
9 w.Header().Add("Content-Type", "application/json")
10 w.WriteHeader(statusCode)
11 encoder := json.NewEncoder(w)
12 err := encoder.Encode(response)
13 if err != nil {
14 panic(err)
15 }
16}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.
1func (d *Delivery) GetAll(w http.ResponseWriter, r *http.Request, params httprouter.Params) {
2 var response models.ArticleListResponse
3 var statusCode int = http.StatusBadRequest
4
5 defer func() {
6 util.Response(w, response, statusCode)
7 }()
8
9 res, err := d.articleUsecase.GetAll(r.Context())
10 if err != nil {
11 statusCode = http.StatusInternalServerError
12 response.Code = statusCode
13 response.Status = err.Error()
14 return
15 }
16
17 statusCode = http.StatusOK
18 response.Data = append(response.Data, res...)
19 response.Code = statusCode
20 response.Status = "OK"
21}Function Handler Retrieving Article ByID Data
The next process adds a function to the handler like this.
1func (d *Delivery) GetByID(w http.ResponseWriter, r *http.Request, params httprouter.Params) {
2 var response models.ArticleListResponse
3 var statusCode int
4
5 defer func() {
6 util.Response(w, response, statusCode)
7 }()
8
9 articleIDString := params.ByName("article_id")
10 articleID, err := strconv.ParseInt(articleIDString, 0, 64)
11 if err != nil {
12 statusCode = http.StatusBadRequest
13 response.Code = statusCode
14 response.Status = err.Error()
15 return
16 }
17
18 res, err := d.articleUsecase.GetByID(r.Context(), articleID)
19 if err != nil {
20 statusCode = http.StatusInternalServerError
21 response.Code = statusCode
22 response.Status = err.Error()
23 return
24 }
25
26 if res.ID == 0 {
27 statusCode = http.StatusNotFound
28 response.Code = statusCode
29 response.Status = "data not found"
30 return
31 }
32
33 statusCode = http.StatusOK
34 response.Data = append(response.Data, res)
35 response.Code = statusCode
36 response.Status = "OK"
37} 1func (d *Pengiriman) Update(w http.ResponseWriter, r *http.Request, params httprouter.Params) {
2 var response models.ArticleListResponse
3 var request models.ArticleUpdateRequest
4 var statusCode = http.StatusBadRequest
5
6 defer func() {
7 util.Response(w, response, statusCode)
8 }()
9
10 articleIDString := params.ByName("article_id")
11 articleID, err := strconv.ParseInt(articleIDString, 0, 64)
12 if err != nil {
13 statusCode = http.StatusBadRequest
14 response.Code = statusCode
15 response.Status = err.Error()
16 return
17 }
18
19 decoder := json.NewDecoder(r.Body)
20 err = decoder.Decode(&request)
21 if err != nil {
22 statusCode = http.StatusBadRequest
23 response.Code = statusCode
24 response.Status = err.Error()
25 return
26 }
27
28 request.ID = articleID
29
30 err = d.validate.Struct(request)
31 if err != nil {
32 statusCode = http.StatusBadRequest
33 response.Code = statusCode
34 response.Status = err.Error()
35 return
36 }
37
38 res, err := d.articleUsecase.Update(r.Context(), request)
39 if err != nil {
40 statusCode = http.StatusInternalServerError
41 response.Code = statusCode
42 response.Status = err.Error()
43 return
44 }
45
46 statusCode = http.StatusOK
47 response.Data = append(response.Data, res)
48 response.Code = statusCode
49 response.Status = "OK"
50}Pada saat update ini kita memerlukan article_id maka perlu ambil data tersebut dari parameter dengan mengambil id tersebut seperti di atas.
1articleIDString := 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.
1 decoder := json.NewDecoder(r.Body)
2 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.
1func (d *Pengiriman) Store(w http.ResponseWriter, r *http.Request, params httprouter.Params) {
2 var response models.ArticleListResponse
3 var request models.ArticleCreateRequest
4 var statusCode int = http.StatusBadRequest
5
6 defer func() {
7 util.Response(w, response, statusCode)
8 }()
9
10 decoder := json.NewDecoder(r.Body)
11 err := decoder.Decode(&request)
12 if err != nil {
13 statusCode = http.StatusBadRequest
14 response.Code = statusCode
15 response.Status = err.Error()
16 return
17 }
18
19 err = d.validate.Struct(request)
20 if err != nil {
21 statusCode = http.StatusBadRequest
22 response.Code = statusCode
23 response.Status = err.Error()
24 return
25 }
26
27 res, err := d.articleUsecase.Store(r.Context(), request)
28 if err != nil {
29 statusCode = http.StatusInternalServerError
30 response.Code = statusCode
31 response.Status = err.Error()
32 return
33 }
34
35 response.Data = append(response.Data, res)
36 statusCode = http.StatusOK
37 response.Code = statusCode
38 response.Status = "OK"
39}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.
1func (d *Pengiriman) Hapus(w http.ResponseWriter, r *http.Request, params httprouter.Params) {
2 var response models.ArticleListResponse
3 var statusCode int = http.StatusBadRequest
4
5 defer func() {
6 util.Response(w, response, statusCode)
7 }()
8
9 articleIDString := params.ByName("article_id")
10 articleID, err := strconv.ParseInt(articleIDString, 0, 64)
11 if err != nil {
12 statusCode = http.StatusBadRequest
13 response.Code = statusCode
14 response.Status = err.Error()
15 return
16 }
17
18 if articleID == 0 {
19 statusCode = http.StatusBadRequest
20 response.Code = statusCode
21 response.Status = "article_id bukan nol"
22 return
23 }
24
25 res, err := d.articleUsecase.Delete(r.Context(), articleID)
26 if err != nil {
27 statusCode = http.StatusInternalServerError
28 response.Code = statusCode
29 response.Status = err.Error()
30 return
31 }
32
33 if !res {
34 statusCode = http.StatusInternalServerError
35 response.Code = statusCode
36 response.Status = errors.New("error tidak diketahui").Error()
37 return
38 }
39
40 statusCode = http.StatusOK
41 response.Code = statusCode
42 response.Status = "OK"
43}