Commit 9933169c81dffadf646a7825aa721e8e297f772f
1 parent
ff2508880c
Exists in
master
and in
1 other branch
localization support
Showing
3 changed files
with
121 additions
and
23 deletions
Show diff stats
http_utility.go
... | ... | @@ -5,13 +5,98 @@ import ( |
5 | 5 | "net/http" |
6 | 6 | ) |
7 | 7 | |
8 | +type webError struct { | |
9 | + Request string `json:"request"` | |
10 | + Error string `json:"error"` | |
11 | +} | |
12 | + | |
13 | +// NotFoundHandler writes HTTP error 404 to w. | |
14 | +func NotFoundHandler(w http.ResponseWriter, req *http.Request) { | |
15 | + SetDefaultHeaders(w) | |
16 | + if req.Method == "OPTIONS" { | |
17 | + return | |
18 | + } | |
19 | + ErrorResponse(w, req, http.StatusNotFound, []HttpErrorDesc{ | |
20 | + {"en", "Not found."}, | |
21 | + {"rs", "Traženi resurs ne postoji."}, | |
22 | + }) | |
23 | +} | |
24 | + | |
25 | +// SetDefaultHeaders set's default headers for an HTTP response. | |
26 | +func SetDefaultHeaders(w http.ResponseWriter) { | |
27 | + w.Header().Set("Access-Control-Allow-Origin", "*") | |
28 | + w.Header().Set("Access-Control-Allow-Methods", "POST, GET, PUT, DELETE, OPTIONS") | |
29 | + w.Header().Set("Access-Control-Allow-Headers", `Accept, Content-Type, | |
30 | + Content-Length, Accept-Encoding, X-CSRF-Token, Authorization`) | |
31 | + w.Header().Set("Content-Type", "application/json; charset=utf-8") | |
32 | +} | |
33 | + | |
34 | +// 2xx | |
35 | +func Success(w http.ResponseWriter, payload *Payload, code int) { | |
36 | + w.WriteHeader(code) | |
37 | + if payload != nil { | |
38 | + json.NewEncoder(w).Encode(*payload) | |
39 | + } | |
40 | +} | |
41 | + | |
42 | +// 200 | |
43 | +func OK(w http.ResponseWriter, payload *Payload) { | |
44 | + Success(w, payload, http.StatusOK) | |
45 | +} | |
46 | + | |
47 | +// 201 | |
48 | +func Created(w http.ResponseWriter, payload *Payload) { | |
49 | + Success(w, payload, http.StatusCreated) | |
50 | +} | |
51 | + | |
52 | +// 4xx; 5xx | |
53 | +func Error(w http.ResponseWriter, r *http.Request, code int, err string) { | |
54 | + werr := webError{Error: err, Request: r.Method + " " + r.RequestURI} | |
55 | + w.WriteHeader(code) | |
56 | + json.NewEncoder(w).Encode(werr) | |
57 | +} | |
58 | + | |
59 | +// 400 | |
60 | +func BadRequest(w http.ResponseWriter, r *http.Request, err string) { | |
61 | + Error(w, r, http.StatusBadRequest, err) | |
62 | +} | |
63 | + | |
64 | +// 404 | |
65 | +func NotFound(w http.ResponseWriter, r *http.Request, err string) { | |
66 | + Error(w, r, http.StatusNotFound, err) | |
67 | +} | |
68 | + | |
69 | +// 401 | |
70 | +func Unauthorized(w http.ResponseWriter, r *http.Request, err string) { | |
71 | + Error(w, r, http.StatusUnauthorized, err) | |
72 | +} | |
73 | + | |
74 | +// 403 | |
75 | +func Forbidden(w http.ResponseWriter, r *http.Request, err string) { | |
76 | + Error(w, r, http.StatusForbidden, err) | |
77 | +} | |
78 | + | |
79 | +// 403 | |
80 | +func Conflict(w http.ResponseWriter, r *http.Request, err string) { | |
81 | + Error(w, r, http.StatusConflict, err) | |
82 | +} | |
83 | + | |
84 | +// 500 | |
85 | +func InternalServerError(w http.ResponseWriter, r *http.Request, err string) { | |
86 | + Error(w, r, http.StatusInternalServerError, err) | |
87 | +} | |
88 | + | |
89 | +/// | |
90 | +/// Old API | |
91 | +/// | |
92 | + | |
8 | 93 | const ( |
9 | 94 | templateHttpErr500_EN = "An internal server error has occurred." |
10 | 95 | templateHttpErr500_RS = "Došlo je do greške na serveru." |
11 | 96 | templateHttpErr400_EN = "Bad request." |
12 | 97 | templateHttpErr400_RS = "Neispravan zahtev." |
13 | 98 | templateHttpErr404_EN = "Resource not found." |
14 | - templateHttpErr404_RS = "Objekat nije pronadjen." | |
99 | + templateHttpErr404_RS = "Resurs nije pronadjen." | |
15 | 100 | templateHttpErr401_EN = "Unauthorized request." |
16 | 101 | templateHttpErr401_RS = "Neautorizovan zahtev." |
17 | 102 | ) |
... | ... | @@ -73,24 +158,3 @@ func UnauthorizedResponse(w http.ResponseWriter, req *http.Request) { |
73 | 158 | {"rs", templateHttpErr401_RS}, |
74 | 159 | }) |
75 | 160 | } |
76 | - | |
77 | -// NotFoundHandler writes HTTP error 404 to w. | |
78 | -func NotFoundHandler(w http.ResponseWriter, req *http.Request) { | |
79 | - SetDefaultHeaders(w) | |
80 | - if req.Method == "OPTIONS" { | |
81 | - return | |
82 | - } | |
83 | - ErrorResponse(w, req, http.StatusNotFound, []HttpErrorDesc{ | |
84 | - {"en", "Not found."}, | |
85 | - {"rs", "Traženi resurs ne postoji."}, | |
86 | - }) | |
87 | -} | |
88 | - | |
89 | -// SetDefaultHeaders set's default headers for an HTTP response. | |
90 | -func SetDefaultHeaders(w http.ResponseWriter) { | |
91 | - w.Header().Set("Access-Control-Allow-Origin", "*") | |
92 | - w.Header().Set("Access-Control-Allow-Methods", "POST, GET, PUT, DELETE, OPTIONS") | |
93 | - w.Header().Set("Access-Control-Allow-Headers", `Accept, Content-Type, | |
94 | - Content-Length, Accept-Encoding, X-CSRF-Token, Authorization`) | |
95 | - w.Header().Set("Content-Type", "application/json; charset=utf-8") | |
96 | -} | ... | ... |
json_utility.go
... | ... | @@ -61,7 +61,8 @@ type Payload struct { |
61 | 61 | Correlations []CorrelationField `json:"correlationFields"` |
62 | 62 | IdField string `json:"idField"` |
63 | 63 | |
64 | - // Data holds JSON payload. It can't be used for itteration. | |
64 | + // Data holds JSON payload. | |
65 | + // It can't be used for itteration. | |
65 | 66 | Data interface{} `json:"data"` |
66 | 67 | } |
67 | 68 | ... | ... |
locale_utility.go
... | ... | @@ -0,0 +1,33 @@ |
1 | +package webutility | |
2 | + | |
3 | +import ( | |
4 | + "encoding/json" | |
5 | + "io/ioutil" | |
6 | +) | |
7 | + | |
8 | +var locales = map[string]map[string]string{} | |
9 | + | |
10 | +func LoadLocale(loc, filePath string) error { | |
11 | + file, err := ioutil.ReadFile(filePath) | |
12 | + if err != nil { | |
13 | + return err | |
14 | + } | |
15 | + | |
16 | + var data interface{} | |
17 | + err = json.Unmarshal(file, &data) | |
18 | + if err != nil { | |
19 | + return err | |
20 | + } | |
21 | + | |
22 | + l := map[string]string{} | |
23 | + for k, v := range data.(map[string]interface{}) { | |
24 | + l[k] = v.(string) | |
25 | + } | |
26 | + locales[loc] = l | |
27 | + | |
28 | + return nil | |
29 | +} | |
30 | + | |
31 | +func Translate(loc, key string) string { | |
32 | + return locales[loc][key] | |
33 | +} | ... | ... |