-
Notifications
You must be signed in to change notification settings - Fork 0
/
go-restful-rail.go
130 lines (112 loc) · 3.77 KB
/
go-restful-rail.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
/* Description REST API
HTTP verb| Path |Action |Resource
---------|-------------------------------------|-------|--------
POST |/v1/trains (details as JSON body) |Create |Train
POST |/v1/station (details as JSON body) |Create |Station
GET |/v1/trains/id |Read |Train
GET |/v1/station/id |Read |Station
POST |/v1/schedule (source and destination)|Create |Route
*/
package main
import (
"database/sql"
"encoding/json"
"log"
"net/http"
"time"
"sqlite-rest-api/dbutils"
"github.com/emicklei/go-restful"
_ "github.com/mattn/go-sqlite3"
)
// DB Driver visible to whole program
var DB *sql.DB
// TrainResource is the model for holding rail information
type TrainResource struct {
ID int
DriverName string
OperatingStatus bool
}
// StationResource holds information about locations
type StationResource struct {
ID int
Name string
OpeningTime time.Time
ClosingTime time.Time
}
// ScheduleResource links both trains and stations
type ScheduleResource struct {
ID int
TrainID int
StationID int
ArrivalTime time.Time
}
// Register adds paths and routes to container
func (t *TrainResource) Register(container *restful.Container) {
ws := new(restful.WebService)
ws.Path("/v1/trains").Consumes(restful.MIME_JSON).Produces(restful.MIME_JSON) // you can specify this per route as well
ws.Route(ws.GET("/{train-id}").To(t.getTrain))
ws.Route(ws.POST("").To(t.createTrain))
ws.Route(ws.DELETE("/{train-id}").To(t.removeTrain))
container.Add(ws)
}
// GET http://localhost:8000/v1/trains/1
func (t TrainResource) getTrain(request *restful.Request, response *restful.Response) {
id := request.PathParameter("train-id")
err := DB.QueryRow("select ID, DRIVER_NAME, OPERATING_STATUS FROM train where id=?", id).Scan(&t.ID, &t.DriverName, &t.OperatingStatus)
if err != nil {
log.Println(err)
response.AddHeader("Content-Type", "text/plain")
response.WriteErrorString(http.StatusNotFound, "Train could not be found.")
} else {
response.WriteEntity(t)
}
}
// POST http://localhost:8000/v1/trains
func (t TrainResource) createTrain(request *restful.Request, response *restful.Response) {
log.Println(request.Request.Body)
decoder := json.NewDecoder(request.Request.Body)
var b TrainResource
err := decoder.Decode(&b)
if err != nil {
log.Fatal(err)
}
log.Println(b.DriverName, b.OperatingStatus)
// Error handling is obvious here. So omitting...
statement, _ := DB.Prepare("insert into train (DRIVER_NAME, OPERATING_STATUS) values (?, ?)")
result, err := statement.Exec(b.DriverName, b.OperatingStatus)
if err == nil {
newID, _ := result.LastInsertId()
b.ID = int(newID)
response.WriteHeaderAndEntity(http.StatusCreated, b)
} else {
response.AddHeader("Content-Type", "text/plain")
response.WriteErrorString(http.StatusInternalServerError, err.Error())
}
}
// DELETE http://localhost:8000/v1/trains/1
func (t TrainResource) removeTrain(request *restful.Request, response *restful.Response) {
id := request.PathParameter("train-id")
statement, _ := DB.Prepare("delete from train where id=?")
_, err := statement.Exec(id)
if err == nil {
response.WriteHeader(http.StatusOK)
} else {
response.AddHeader("Content-Type", "text/plain")
response.WriteErrorString(http.StatusInternalServerError, err.Error())
}
}
func main() {
var err error
DB, err = sql.Open("sqlite3", "./railapi.db")
if err != nil {
log.Println("Driver creation failed!")
}
dbutils.Initialize(DB)
wsContainer := restful.NewContainer()
wsContainer.Router(restful.CurlyRouter{})
t := TrainResource{}
t.Register(wsContainer)
log.Printf("start listening on localhost:8000")
server := &http.Server{Addr: ":8000", Handler: wsContainer}
log.Fatal(server.ListenAndServe())
}