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
File was created | 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 | } | ||
162 |
json_utility.go
File was created | 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 | |||
71 |
tables_utility.go
File was created | 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 | } | ||
145 |