POST /device -> Device 아이템 추가 (포스팅 완료) / curl -X POST -H "Content-Type: application/json" -d '{"name":"iPhone19","mac":"ff:11:11:22:33:11"}' http://localhost:8000/v1.0/device
GET /device -> Device 아이템 리스트 조회 (포스팅 완료) / curl -X GET -H "Content-Type: application/json" -d '{}' http://localhost:8000/v1.0/device
GET /device/{pk} -> Device 아이템 조회 (포스팅 완료) / curl -X GET -H "Content-Type: application/json" -d '{}' http://localhost:8000/v1.0/device/1
PUT /device/{pk} -> Device 아이템 수정 (진행중)
DELETE /device/{pk} -> Device 아이템 삭제 (진행중)
이번 포스팅에는 PUT, DELETE를 업데이트하였습니다.
사실상 이번 예제는 POST와 GET item과 차이가 거의 없습니다.
업무에서는 PUT이 들어오는 파라미터에 따라 query 문 조합을 하겠지만 예제답게 넘기겠습니다.
DELETE 결과.
curl --location --request DELETE 'http://127.0.0.1:8000/v1.0/device/2' \
--header 'Content-Type: application/json' \
--data '{"name":"iPhone19","mac":"ff:11:11:22:33:11"}'

PUT 결과
curl --location --request PUT 'http://127.0.0.1:8000/v1.0/device/14' \
--header 'Content-Type: application/json' \
--data '{
"name": "iPhone2234",
"mac": "ff:11:11:22:33:11"
}'

package main
import (
"database/sql"
"encoding/json"
"fmt"
"net/http"
"strings"
_ "github.com/go-sql-driver/mysql"
"github.com/gorilla/mux"
)
type Device struct {
Id int `json:"id"`
Name string `json:"name"`
Mac string `json:"mac"`
}
const (
httpPort = ":8000"
driverName = "mysql"
dataSourceName = "TheGolangOfFuture:TheGolangOfFuture@tcp(127.0.0.1:3306)/TheGolangOfFuture"
)
func device(res http.ResponseWriter, req *http.Request) {
db, err := sql.Open(driverName, dataSourceName)
if err != nil {
fmt.Printf(err.Error())
res.WriteHeader(http.StatusInternalServerError)
return
}
defer db.Close()
fmt.Println("[DEBUG]", req.Method, req.URL)
if req.Method == http.MethodPost {
var device Device
err := json.NewDecoder(req.Body).Decode(&device)
if err != nil {
res.WriteHeader(http.StatusBadRequest)
return
}
fmt.Printf("[POST] Name=%s,Mac=%s\n", device.Name, device.Mac) // DB insert
tmpMac := strings.Replace(device.Mac, ":", "", -1) // 맥은 ":", "-", "." 등 여러가지가 올 수 있지만 예제에서는 ":"만 처리 하겠습니다.
query := fmt.Sprintf("INSERT INTO Device (name, mac, mac_bin) VALUES('%s', '%s', unhex('%s'))", device.Name, device.Mac, tmpMac) // 이코드는 사실상 너무나 취약합니다.
insert, err := db.Exec(query)
if err != nil {
fmt.Println(err.Error())
res.WriteHeader(http.StatusInternalServerError)
return
}
if i, err := insert.RowsAffected(); err != nil {
fmt.Println(err.Error())
res.WriteHeader(http.StatusInternalServerError)
return
} else {
res.Header().Set("Content-Type", "application/json")
res.WriteHeader(http.StatusOK)
json.NewEncoder(res).Encode(map[string]interface{}{
"success": true,
"messages": fmt.Sprintf("Post success : %d item", i),
})
}
} else if req.Method == http.MethodGet {
vars := mux.Vars(req)
if id, ok := vars["id"]; ok == true {
rs, err := db.Query(fmt.Sprintf("SELECT id, name FROM Device where id = %s", id))
if err != nil {
fmt.Println(err.Error())
res.WriteHeader(http.StatusInternalServerError)
return
}
defer rs.Close()
for rs.Next() {
var d Device
err := rs.Scan(&d.Id, &d.Name)
if err != nil {
fmt.Println(err.Error())
res.WriteHeader(http.StatusInternalServerError)
return
}
json.NewEncoder(res).Encode(map[string]interface{}{
"success": true,
"data": d,
})
}
} else {
rs, err := db.Query("SELECT id, name FROM Device")
if err != nil {
fmt.Println(err.Error())
res.WriteHeader(http.StatusInternalServerError)
return
}
defer rs.Close()
var result []Device
for rs.Next() {
var d Device
err := rs.Scan(&d.Id, &d.Name)
if err != nil {
fmt.Println(err.Error())
res.WriteHeader(http.StatusInternalServerError)
return
}
result = append(result, d)
}
json.NewEncoder(res).Encode(map[string]interface{}{
"success": true,
"data": result,
})
}
res.Header().Set("Content-Type", "application/json")
res.WriteHeader(http.StatusOK)
} else if req.Method == http.MethodPut {
res.Header().Set("Content-Type", "application/json")
res.WriteHeader(http.StatusOK)
vars := mux.Vars(req)
if id, ok := vars["id"]; ok == true {
var device Device
err := json.NewDecoder(req.Body).Decode(&device)
if err != nil {
res.WriteHeader(http.StatusBadRequest)
return
}
fmt.Printf("[PUT] Id=%s, Name=%s, Mac=%s\n", id, device.Name, device.Mac) // DB insert
tmpMac := strings.Replace(device.Mac, ":", "", -1) // 맥은 ":", "-", "." 등 여러가지가 올 수 있지만 예제에서는 ":"만 처리 하겠습니다.
query := fmt.Sprintf("UPDATE Device SET name = '%s', mac = '%s', mac_bin = unhex('%s') WHERE id = %s", device.Name, device.Mac, tmpMac, id) // 이코드는 사실상 너무나 취약합니다.
fmt.Println(query)
insert, err := db.Exec(query)
if err != nil {
fmt.Println(err.Error())
res.WriteHeader(http.StatusInternalServerError)
return
}
if i, err := insert.RowsAffected(); err != nil {
fmt.Println(err.Error())
res.WriteHeader(http.StatusInternalServerError)
return
} else {
res.Header().Set("Content-Type", "application/json")
res.WriteHeader(http.StatusOK)
json.NewEncoder(res).Encode(map[string]interface{}{
"success": true,
"messages": fmt.Sprintf("Post success : %d item", i),
})
}
}
} else if req.Method == http.MethodDelete {
vars := mux.Vars(req)
if id, ok := vars["id"]; ok == true {
rs, err := db.Exec(fmt.Sprintf("DELETE FROM Device where id = %s", id))
if err != nil {
fmt.Println(err.Error())
res.WriteHeader(http.StatusInternalServerError)
return
}
if i, err := rs.RowsAffected(); err != nil {
fmt.Println(err.Error())
res.WriteHeader(http.StatusInternalServerError)
return
} else {
json.NewEncoder(res).Encode(map[string]interface{}{
"success": true,
"data": fmt.Sprintf("success %d item", i),
})
res.Header().Set("Content-Type", "application/json")
res.WriteHeader(http.StatusOK)
}
} else {
res.WriteHeader(http.StatusForbidden)
}
} else {
fmt.Println("NotAllowed", req.RemoteAddr)
res.WriteHeader(http.StatusMethodNotAllowed) // 나머지 메소드는 허용안함
}
}
func main() {
fmt.Println("Start WEB", httpPort)
m := mux.NewRouter()
m.HandleFunc("/v1.0/device/{id:[0-9]+}", device).Methods("GET", "PUT", "DELETE", "POST")
http.HandleFunc("/v1.0/device", device)
http.Handle("/", m)
http.ListenAndServe(httpPort, nil)
}
'Go언어 golang' 카테고리의 다른 글
2023-03-24 json decoder 주석 허용 하는 기능 구현 (0) | 2023.03.24 |
---|---|
golang JSON 설정 파일 로더 / JSON 주석 처리 (0) | 2023.03.23 |
golang REST API / go언어 REST API 서버 #5 METHOD GET item (0) | 2023.03.21 |
golang REST API / go언어 REST API 서버. #2 docker mariadb 설치 및 접속 확인 (0) | 2023.03.16 |
golang Syslog server / Go언어 Syslog collector - 파싱 추가 RFC5424 (0) | 2023.03.12 |