Skip to content
Santekno.com | Level Up Your Engineering Skills
ID
📖 0%
27 Jan 2024 · 5 mnt baca ·Artikel 84 / 119
Go

07 Membuat Handler Sebagai Data Delivery Layer

IH
Ihsan Arif
Penulis di Santekno · Backend Engineer

Pada tahapan ini kita akan melanjutkan projek yang sudah kita buat dengan membuat Delivery Layer. Layer ini seperti yang dijelaskan sebelumnya yaitu layer yang menghubungkan request user dengan logic layer.

Pada layer ini kita biasanya memberikan beberapa validasi untuk setiap request yang dikirim oleh user sehingga nanti pada saat dikirim ke usecase layer data request itu tidak ada yang kosong atau perlu di validasi kembali.

Baiklah, kita langsung saja ke folder delivery/http dan buat file article.go. Kita buat folder http karena handler yang kita buat itu merupakan handler REST API yang mana itu adalah protokol http.

Isi file diatas itu dengan seperti dibawah ini.

go
1type Delivery struct {
2	articleUsecase usecase.ArticleUsecase
3}
4
5func New(articleUsecase usecase.ArticleUsecase) *Delivery {
6	return &Delivery{
7		articleUsecase: articleUsecase,
8	}
9}

Dan kita juga akan membuat folder pkg/util/ yang mana akan diisi oleh file yang menghandle response dari API yang sudah kita buat menjadi tipe data json. Berikut file pkg/util/response.go dibawah ini.

go
 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}

Handler Fungsi Mengambil Semua Data Article

Pada usecase ini, kita akan coba membuat fungsi untuk mengambil semua data artikel dengan nama fungsi GetAll() seperti dibawah ini.

go
 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}

Handler Fungsi Mengambil Data Article ByID

Proses selanjutnya tambahkan fungsi pada handler seperti ini.

go
 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}

Handler Fungsi Update Data Article

Seperti dikatakan diatas pernah disinggung, handler untuk mengupdate data tersebut akan mengakses usecase fungsi update seperti dibawah ini.

go
 1func (d *Delivery) 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 diatas.

go
1articleIDString := params.ByName("article_id")

Lalu ketika kita ingin mengambil body dari suatu request protokol http kita bisa menggunakan decode juga untuk dikonversikan ke dalam struct yang sudah kita buat.

go
1	decoder := json.NewDecoder(r.Body)
2	err = decoder.Decode(&request)

Handler Fungsi Tambah Data Article

Pada proses handler untuk tambah data artikel bisa kita lihat seperti dibawah ini.

go
 1func (d *Delivery) 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}

Handler Fungsi Hapus Data Article

Pada proses usecase hapus data kita membutuhkan parameter dan body request untuk diteruskan ke usecase seperti dibawah ini.

go
 1func (d *Delivery) Delete(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 was not zero"
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("unknown error").Error()
37		return
38	}
39
40	statusCode = http.StatusOK
41	response.Code = statusCode
42	response.Status = "OK"
43}

Artikel Terkait

💬 Komentar