-
Notifications
You must be signed in to change notification settings - Fork 1
/
server.go
144 lines (124 loc) · 4.02 KB
/
server.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
131
132
133
134
135
136
137
138
139
140
141
142
143
144
package openape
import (
"fmt"
"log"
"net/http"
"strings"
"github.com/encima/openape/db"
"github.com/encima/openape/utils"
"github.com/getkin/kin-openapi/openapi3"
"github.com/gorilla/mux"
"github.com/spf13/viper"
)
// OpenApe object to hold objects related to the server
type OpenApe struct {
db db.Database
router *mux.Router
swagger *openapi3.Swagger
config *viper.Viper
}
const (
baseCreationString string = "CREATE TABLE IF NOT EXISTS base_type (id VARCHAR PRIMARY KEY, created_at date, updated_at date);"
)
var (
pgBaseTypes = []string{"id", "created_at", "updated_at"}
pgReservedWords = []string{"user", "group"}
)
// RootHandler responds to / request
func RootHandler(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("go APE!\n"))
}
// LoadConfig loads config file using Viper package
func LoadConfig(path string) {
viper.SetConfigName("config")
viper.AddConfigPath(path)
err := viper.ReadInConfig() // Find and read the config file
if err != nil { // Handle errors reading the config file
panic(fmt.Errorf("Fatal error config file: %s", err))
}
}
// AddRoute takes a path and a method to create a route handler for a Mux router instance
func (oape *OpenApe) AddRoute(path string, method string, model string) {
fmt.Printf("Adding route: %s %s \n", method, path)
oape.router.HandleFunc(path, func(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
var res utils.JSONResponse
print(vars)
switch method {
case "GET":
res = oape.db.GetModels(model)
break
case "POST":
m := oape.swagger.Components.Schemas[model]
res = oape.db.PostModel(model, m, r)
break
case "PUT":
m := oape.swagger.Components.Schemas[model]
res = oape.db.PutModel(vars["id"], model, m, r)
break
case "DELETE":
res = oape.db.DeleteModel(vars["id"], model, r)
break
default:
break
}
utils.SendResponse(w, res)
}).Methods(method)
}
// MapModels reads the models from the provided swagger file and creates the correspdonding tables in Postgres
func (oape *OpenApe) MapModels(models map[string]*openapi3.SchemaRef) {
for k, v := range models {
oape.db.CreateSchema(k, v.Value.Properties)
}
}
// GetModelFromPath identifies which routes maps to which models identified in the Schemas of the spec
func (oape *OpenApe) GetModelFromPath(path string) string {
for k := range oape.swagger.Components.Schemas {
if strings.Contains(strings.ToLower(path), strings.ToLower(k)) {
return k
}
}
return ""
}
// MapRoutes iterates the paths laid out in the swagger file and adds them to the router
func (oape *OpenApe) MapRoutes(paths map[string]*openapi3.PathItem) {
for k, v := range paths {
// TODO handle when user specifies function and do not pass to route
model := oape.GetModelFromPath(k)
for opName := range v.Operations() {
// op := v.GetOperation(opName)
// print(op.Parameters)
oape.AddRoute(k, opName, model)
}
}
}
// RunServer starts the openapi server on the specified port
func (oape *OpenApe) RunServer() {
port := ":8080"
if len(oape.swagger.Servers) > 0 {
port = oape.swagger.Servers[0].Variables["port"].Default.(string)
}
log.Fatal(http.ListenAndServe(port, oape.router))
}
// NewServer sets up the
func NewServer(configPath string) OpenApe {
r := mux.NewRouter()
// Routes consist of a path and a handler function.
LoadConfig(configPath)
r.HandleFunc("/", RootHandler).Methods("GET")
staticDir := viper.GetString("server.static")
dbEngine := db.DatabaseConnect()
oapiPath := viper.GetString("openapi.path")
swagger := utils.LoadSwagger(oapiPath)
odb := db.Database{Conn: dbEngine}
o := OpenApe{odb, r, swagger, viper.GetViper()}
o.router.PathPrefix("/static/").Handler(http.StripPrefix("/static/", http.FileServer(http.Dir(staticDir))))
if len(o.swagger.Servers) > 0 && o.swagger.Servers[0].Variables["basePath"] != nil {
o.router = o.router.PathPrefix("/api/v1").Subrouter()
}
o.router.Use(o.APIAuthHandler)
// set up with routes and models to DB and Router
o.MapModels(swagger.Components.Schemas)
o.MapRoutes(swagger.Paths)
return o
}