Commit 64041a2ea429b17719d3c5b9b8d37fa24ebfed7a
0 parents
Exists in
master
and in
1 other branch
first commit
Showing
3 changed files
with
375 additions
and
0 deletions
Show diff stats
http_utility.go
... | ... | @@ -0,0 +1,161 @@ |
1 | +package restutility | |
2 | + | |
3 | +import ( | |
4 | + "net/http" | |
5 | + "encoding/json" | |
6 | +) | |
7 | + | |
8 | +//// | |
9 | +//// ERROR UTILITY | |
10 | +//// | |
11 | + | |
12 | +const templateHttpErr500_EN = "An internal server error has occurred." | |
13 | +const templateHttpErr500_RS = "Došlo je do greške na serveru." | |
14 | +const templateHttpErr400_EN = "Bad request: invalid request body." | |
15 | +const templateHttpErr400_RS = "Neispravan zahtev." | |
16 | + | |
17 | +type HttpError struct { | |
18 | + Error []HttpErrorDesc `json:"error"` | |
19 | + Request string `json:"request"` | |
20 | +} | |
21 | + | |
22 | +type HttpErrorDesc struct { | |
23 | + Lang string `json:"lang"` | |
24 | + Desc string `json:"description"` | |
25 | +} | |
26 | + | |
27 | +func respondWithHttpError(w http.ResponseWriter, | |
28 | + req *http.Request, | |
29 | + code int, | |
30 | + httpErr []HttpErrorDesc) { | |
31 | + | |
32 | + err := HttpError{ | |
33 | + Error: httpErr, | |
34 | + Request: req.Method + " " + req.URL.Path, | |
35 | + } | |
36 | + w.WriteHeader(code) | |
37 | + json.NewEncoder(w).Encode(err) | |
38 | +} | |
39 | + | |
40 | +func respondWithHttpError400(w http.ResponseWriter, req *http.Request) { | |
41 | + respondWithHttpError(w, req, http.StatusBadRequest, | |
42 | + []HttpErrorDesc{ | |
43 | + { | |
44 | + Lang: "en", | |
45 | + Desc: templateHttpErr400_EN, | |
46 | + }, | |
47 | + { | |
48 | + Lang: "rs", | |
49 | + Desc: templateHttpErr400_RS, | |
50 | + }, | |
51 | + }) | |
52 | +} | |
53 | + | |
54 | +func respondWithHttpError500(w http.ResponseWriter, req *http.Request) { | |
55 | + respondWithHttpError(w, req, http.StatusInternalServerError, | |
56 | + []HttpErrorDesc{ | |
57 | + { | |
58 | + Lang: "en", | |
59 | + Desc: templateHttpErr500_EN, | |
60 | + }, | |
61 | + { | |
62 | + Lang: "rs", | |
63 | + Desc: templateHttpErr500_RS, | |
64 | + }, | |
65 | + }) | |
66 | +} | |
67 | + | |
68 | +func deliverPayload(w http.ResponseWriter, payload JSONPayload) { | |
69 | + json.NewEncoder(w).Encode(payload) | |
70 | + payload.Data = nil | |
71 | +} | |
72 | + | |
73 | +//// | |
74 | +//// HANDLER FUNC WRAPPER | |
75 | +//// | |
76 | + | |
77 | +// wrapHandlerFunc is as wrapper function for route handlers. | |
78 | +// Sets common headers and checks for token validity. | |
79 | +func commonHttpWrap(fn http.HandlerFunc) http.HandlerFunc { | |
80 | + return func(w http.ResponseWriter, req *http.Request) { | |
81 | +// @TODO: check Content-type header (must be application/json) | |
82 | +// ctype := w.Header.Get("Content-Type") | |
83 | +// if req.Method != "GET" && ctype != "application/json" { | |
84 | +// replyWithHttpError(w, req, http.StatusBadRequest, | |
85 | +// "Not a supported content type: " + ctype) | |
86 | +// } | |
87 | + | |
88 | + w.Header().Set("Access-Control-Allow-Origin", "*") | |
89 | + w.Header().Set("Access-Control-Allow-Methods", | |
90 | + `POST, | |
91 | + GET, | |
92 | + PUT, | |
93 | + DELETE, | |
94 | + OPTIONS`) | |
95 | + w.Header().Set("Access-Control-Allow-Headers", | |
96 | + `Accept, | |
97 | + Content-Type, | |
98 | + Content-Length, | |
99 | + Accept-Encoding, | |
100 | + X-CSRF-Token, | |
101 | + Authorization`) | |
102 | + w.Header().Set("Content-Type", "application/json; charset=utf-8") | |
103 | + | |
104 | + if req.Method == "OPTIONS" { | |
105 | + return | |
106 | + } | |
107 | + | |
108 | + if req.URL.Path != APIVersion + "/token/new" { | |
109 | + token := req.Header.Get("Authorization") | |
110 | + if _, err := parseAPIToken(token); err != nil { | |
111 | + respondWithHttpError(w, req, http.StatusUnauthorized, | |
112 | + []HttpErrorDesc{ | |
113 | + { | |
114 | + Lang: "en", | |
115 | + Desc: "Unauthorized request.", | |
116 | + }, | |
117 | + { | |
118 | + Lang: "rs", | |
119 | + Desc: "Neautorizovani zahtev.", | |
120 | + }, | |
121 | + }) | |
122 | + return | |
123 | + } | |
124 | + } | |
125 | + | |
126 | + err := req.ParseForm() | |
127 | + if err != nil { | |
128 | + respondWithHttpError(w, req, http.StatusBadRequest, | |
129 | + []HttpErrorDesc{ | |
130 | + { | |
131 | + Lang: "en", | |
132 | + Desc: templateHttpErr400_EN, | |
133 | + }, | |
134 | + { | |
135 | + Lang: "rs", | |
136 | + Desc: templateHttpErr400_RS, | |
137 | + }, | |
138 | + }) | |
139 | + return | |
140 | + } | |
141 | + fn(w, req) | |
142 | + } | |
143 | +} | |
144 | + | |
145 | +//// | |
146 | +//// NOT FOUND HANDLER | |
147 | +//// | |
148 | + | |
149 | +func notFoundHandler(w http.ResponseWriter, req *http.Request) { | |
150 | + respondWithHttpError(w, req, http.StatusNotFound, | |
151 | + []HttpErrorDesc{ | |
152 | + { | |
153 | + Lang: "en", | |
154 | + Desc: "Not found.", | |
155 | + }, | |
156 | + { | |
157 | + Lang: "rs", | |
158 | + Desc: "Traženi resurs ne postoji.", | |
159 | + }, | |
160 | + }) | |
161 | +} | ... | ... |
json_utility.go
... | ... | @@ -0,0 +1,70 @@ |
1 | +package restutility | |
2 | + | |
3 | +import ( | |
4 | + "net/http" | |
5 | + "strings" | |
6 | +) | |
7 | + | |
8 | +type LangMap map[string]map[string]string | |
9 | + | |
10 | +type Field struct { | |
11 | + Parameter string `json:"param"` | |
12 | + Type string `json:"type"` | |
13 | + Visible bool `json:"visible"` | |
14 | + Editable bool `json:"editable"` | |
15 | +} | |
16 | + | |
17 | +type JSONParams struct { | |
18 | + Lang LangMap | |
19 | + Fields []Field | |
20 | + IdField string | |
21 | + Correlations []CorrelationField `json:"correlation_fields"` | |
22 | +} | |
23 | + | |
24 | +type JSONPayload struct { | |
25 | + Method string `json:"method"` | |
26 | + Params map[string]string `json:"params"` | |
27 | + Lang LangMap `json:"lang"` | |
28 | + Fields []Field `json:"fields"` | |
29 | + Correlations []CorrelationField `json:"correlation_fields"` | |
30 | + IdField string `json:"idField"` | |
31 | + // Data can only hold slices of any type. It can't be used for itteration | |
32 | + Data interface{} `json:"data"` | |
33 | +} | |
34 | + | |
35 | +func NewJSONParams(lang LangMap, | |
36 | + fields []Field, | |
37 | + id string, | |
38 | + correlations []CorrelationField) JSONParams { | |
39 | + | |
40 | + var jp JSONParams | |
41 | + | |
42 | + jp.Lang = lang | |
43 | + jp.Fields = fields | |
44 | + jp.IdField = id | |
45 | + jp.Correlations = correlations | |
46 | + | |
47 | + return jp | |
48 | +} | |
49 | + | |
50 | +func NewJSONPayload(r *http.Request, params JSONParams) JSONPayload { | |
51 | + var obj JSONPayload | |
52 | + obj.Method = strings.ToLower(r.Method + " " + r.URL.Path) | |
53 | + obj.Params = make(map[string]string, 0) | |
54 | + obj.Lang = make(map[string]map[string]string, 0) | |
55 | + obj.Fields = make([]Field, 0) | |
56 | + obj.IdField = params.IdField | |
57 | + obj.Correlations = params.Correlations | |
58 | + | |
59 | + for k, m := range params.Lang { | |
60 | + obj.Lang[k] = m | |
61 | + } | |
62 | + for _, f := range params.Fields { | |
63 | + obj.Fields = append(obj.Fields, f) | |
64 | + } | |
65 | + | |
66 | + return obj | |
67 | +} | |
68 | + | |
69 | +func decodeRequestBody(req *http.Request, model interface{}) {} | |
70 | + | ... | ... |
tables_utility.go
... | ... | @@ -0,0 +1,144 @@ |
1 | +package restutility | |
2 | + | |
3 | +import ( | |
4 | + "encoding/json" | |
5 | + "io" | |
6 | + "io/ioutil" | |
7 | + "errors" | |
8 | + "fmt" | |
9 | + "gopkg.in/rana/ora.v3" | |
10 | +) | |
11 | + | |
12 | +type TableConfig struct { | |
13 | + Tables []Table | |
14 | +} | |
15 | + | |
16 | +type Table struct { | |
17 | + TableType string `json:"tableType"` | |
18 | + Translations []TableTranslation `json:"translations"` | |
19 | + TableFields []Field `json:"tableFields"` | |
20 | + Correlations []CorrelationField `json:"correlation_fields"` | |
21 | + IdField string `json:"idField"` | |
22 | +} | |
23 | + | |
24 | +type CorrelationField struct { | |
25 | + Result string `json:"result"` | |
26 | + Elements []string `json:"elements"` | |
27 | + Type string `json:"type"` | |
28 | +} | |
29 | + | |
30 | +type TableTranslation struct { | |
31 | + Language string `json:"language"` | |
32 | + FieldsLabels map[string]string `json:"fieldsLabels"` | |
33 | +} | |
34 | + | |
35 | +func (tl TableConfig) LoadTranslations(tableType string) LangMap { | |
36 | + translations := make(LangMap, 0) | |
37 | + | |
38 | + for _, table := range tl.Tables { | |
39 | + if tableType == table.TableType { | |
40 | + for _, t := range table.Translations { | |
41 | + translations[t.Language] = t.FieldsLabels | |
42 | + } | |
43 | + } | |
44 | + } | |
45 | + | |
46 | + return translations | |
47 | +} | |
48 | + | |
49 | +func (tl TableConfig) LoadFields(tableType string) []Field { | |
50 | + fields := make([]Field, 0) | |
51 | + | |
52 | + for _, table := range tl.Tables { | |
53 | + if tableType == table.TableType { | |
54 | + for _, f := range table.TableFields { | |
55 | + fields = append(fields, f) | |
56 | + } | |
57 | + } | |
58 | + } | |
59 | + | |
60 | + return fields | |
61 | +} | |
62 | + | |
63 | +func (tl TableConfig) LoadIdField(tableType string) string { | |
64 | + for _, table := range tl.Tables { | |
65 | + if tableType == table.TableType { | |
66 | + return table.IdField | |
67 | + } | |
68 | + } | |
69 | + return "" | |
70 | +} | |
71 | + | |
72 | +func (tl TableConfig) LoadCorrelations(tableType string) []CorrelationField { | |
73 | + resp := make([]CorrelationField, 0) | |
74 | + | |
75 | + for _, table := range tl.Tables { | |
76 | + if tableType == table.TableType { | |
77 | + for _, f := range table.Correlations { | |
78 | + resp = append(resp, f) | |
79 | + } | |
80 | + } | |
81 | + } | |
82 | + | |
83 | + return resp | |
84 | +} | |
85 | + | |
86 | +var _tables TableConfig | |
87 | +var _prevProject string | |
88 | + | |
89 | +func getTablesConfigJSON(project string) error { | |
90 | + _prevProject = project | |
91 | + stmt, err := Oracle.Ses.Prep(`SELECT | |
92 | + JSON_CLOB | |
93 | + FROM TABLES_CONFIG | |
94 | + WHERE PROJEKAT` + project, ora.S) | |
95 | + defer stmt.Close() | |
96 | + | |
97 | + if err != nil { | |
98 | + return err | |
99 | + } | |
100 | + | |
101 | + rset, err := stmt.Qry() | |
102 | + if err != nil { | |
103 | + return err | |
104 | + } | |
105 | + | |
106 | + if rset.Next() { | |
107 | + lob := rset.Row[0].(io.Reader) | |
108 | + bytes, err := ioutil.ReadAll(lob) | |
109 | + if err != nil { | |
110 | + fmt.Printf("mega error: %v\n", err) | |
111 | + } | |
112 | + json.Unmarshal(bytes, &_tables.Tables) | |
113 | + } | |
114 | + | |
115 | + return nil | |
116 | +} | |
117 | + | |
118 | +func loadTablesConfig(project string) error { | |
119 | + err := getTablesConfigJSON(putQuotes(project)) | |
120 | + //file, err := ioutil.ReadFile("./config/tables-config.json") | |
121 | + if err != nil { | |
122 | + fmt.Printf("%v\n", err); | |
123 | + return errors.New("unable to load tables config") | |
124 | + } | |
125 | + | |
126 | + //json.Unmarshal(file, &_TABLES_CONFIG.Tables) | |
127 | + | |
128 | + if len(_TABLES_CONFIG.Tables) == 0 { | |
129 | + return errors.New("tables config is corrupt") | |
130 | + } | |
131 | + | |
132 | + return nil | |
133 | +} | |
134 | + | |
135 | +func loadTable(table string) JSONParams { | |
136 | + return NewJSONParams(_tables.LoadTranslations(table), | |
137 | + _tables.LoadFields(table), | |
138 | + _tables.LoadIdField(table), | |
139 | + _tables.LoadCorrelations(table)) | |
140 | +} | |
141 | + | |
142 | +func refreshTables() error { | |
143 | + return getTablesConfigJSON(_prevProject) | |
144 | +} | ... | ... |