Commit 25b39d69c86b364d30de5f8b0ab38be09a8042fc

Authored by Marko Tikvić
1 parent 8c6dd04995
Exists in master

NewServer renamed to NewODBCServer to be more precise

Showing 2 changed files with 5 additions and 1 deletions   Show diff stats
1 package webutility 1 package webutility
2 2
3 import ( 3 import (
4 "encoding/json" 4 "encoding/json"
5 "fmt" 5 "fmt"
6 "net/http" 6 "net/http"
7 ) 7 )
8 8
9 // StatusRecorder ... 9 // StatusRecorder ...
10 type StatusRecorder struct { 10 type StatusRecorder struct {
11 writer http.ResponseWriter 11 writer http.ResponseWriter
12 status int 12 status int
13 size int 13 size int
14 } 14 }
15 15
16 // NewStatusRecorder ... 16 // NewStatusRecorder ...
17 func NewStatusRecorder(w http.ResponseWriter) *StatusRecorder { 17 func NewStatusRecorder(w http.ResponseWriter) *StatusRecorder {
18 return &StatusRecorder{ 18 return &StatusRecorder{
19 writer: w, 19 writer: w,
20 status: 0, 20 status: 0,
21 size: 0, 21 size: 0,
22 } 22 }
23 } 23 }
24 24
25 // WriteHeader is a wrapper http.ResponseWriter interface 25 // WriteHeader is a wrapper http.ResponseWriter interface
26 func (r *StatusRecorder) WriteHeader(code int) { 26 func (r *StatusRecorder) WriteHeader(code int) {
27 r.status = code 27 r.status = code
28 r.writer.WriteHeader(code) 28 r.writer.WriteHeader(code)
29 } 29 }
30 30
31 // Write is a wrapper for http.ResponseWriter interface 31 // Write is a wrapper for http.ResponseWriter interface
32 func (r *StatusRecorder) Write(in []byte) (int, error) { 32 func (r *StatusRecorder) Write(in []byte) (int, error) {
33 r.size = len(in) 33 r.size = len(in)
34 return r.writer.Write(in) 34 return r.writer.Write(in)
35 } 35 }
36 36
37 // Header is a wrapper for http.ResponseWriter interface 37 // Header is a wrapper for http.ResponseWriter interface
38 func (r *StatusRecorder) Header() http.Header { 38 func (r *StatusRecorder) Header() http.Header {
39 return r.writer.Header() 39 return r.writer.Header()
40 } 40 }
41 41
42 // Status ... 42 // Status ...
43 func (r *StatusRecorder) Status() int { 43 func (r *StatusRecorder) Status() int {
44 return r.status 44 return r.status
45 } 45 }
46 46
47 // Size ... 47 // Size ...
48 func (r *StatusRecorder) Size() int { 48 func (r *StatusRecorder) Size() int {
49 return r.size 49 return r.size
50 } 50 }
51 51
52 // NotFoundHandlerFunc writes HTTP error 404 to w. 52 // NotFoundHandlerFunc writes HTTP error 404 to w.
53 func NotFoundHandlerFunc(w http.ResponseWriter, req *http.Request) { 53 func NotFoundHandlerFunc(w http.ResponseWriter, req *http.Request) {
54 SetAccessControlHeaders(w) 54 SetAccessControlHeaders(w)
55 SetContentType(w, "application/json") 55 SetContentType(w, "application/json")
56 NotFound(w, req, fmt.Sprintf("Resource you requested was not found: %s", req.URL.String())) 56 NotFound(w, req, fmt.Sprintf("Resource you requested was not found: %s", req.URL.String()))
57 } 57 }
58 58
59 // SetContentType must be called before SetResponseStatus (w.WriteHeader) (?) 59 // SetContentType must be called before SetResponseStatus (w.WriteHeader) (?)
60 func SetContentType(w http.ResponseWriter, ctype string) { 60 func SetContentType(w http.ResponseWriter, ctype string) {
61 w.Header().Set("Content-Type", ctype) 61 w.Header().Set("Content-Type", ctype)
62 } 62 }
63 63
64 // SetResponseStatus ... 64 // SetResponseStatus ...
65 func SetResponseStatus(w http.ResponseWriter, status int) { 65 func SetResponseStatus(w http.ResponseWriter, status int) {
66 w.WriteHeader(status) 66 w.WriteHeader(status)
67 } 67 }
68 68
69 // WriteResponse ... 69 // WriteResponse ...
70 func WriteResponse(w http.ResponseWriter, content []byte) { 70 func WriteResponse(w http.ResponseWriter, content []byte) {
71 w.Write(content) 71 w.Write(content)
72 } 72 }
73 73
74 // SetAccessControlHeaders set's default headers for an HTTP response. 74 // SetAccessControlHeaders set's default headers for an HTTP response.
75 func SetAccessControlHeaders(w http.ResponseWriter) { 75 func SetAccessControlHeaders(w http.ResponseWriter) {
76 w.Header().Set("Access-Control-Allow-Origin", "*") 76 w.Header().Set("Access-Control-Allow-Origin", "*")
77 w.Header().Set("Access-Control-Allow-Methods", "POST, GET, PUT, DELETE, OPTIONS") 77 w.Header().Set("Access-Control-Allow-Methods", "POST, GET, PUT, DELETE, OPTIONS")
78 w.Header().Set("Access-Control-Allow-Headers", "Accept, Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization") 78 w.Header().Set("Access-Control-Allow-Headers", "Accept, Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization")
79 } 79 }
80 80
81 // GetLocale ... 81 // GetLocale ...
82 func GetLocale(req *http.Request, dflt string) string { 82 func GetLocale(req *http.Request, dflt string) string {
83 loc := req.FormValue("locale") 83 loc := req.FormValue("locale")
84 if loc == "" { 84 if loc == "" {
85 return dflt 85 return dflt
86 } 86 }
87 return loc 87 return loc
88 } 88 }
89 89
90 // Success ... 90 // Success ...
91 func Success(w http.ResponseWriter, payload interface{}, code int) { 91 func Success(w http.ResponseWriter, payload interface{}, code int) {
92 w.WriteHeader(code) 92 w.WriteHeader(code)
93 if payload != nil { 93 if payload != nil {
94 json.NewEncoder(w).Encode(payload) 94 json.NewEncoder(w).Encode(payload)
95 } 95 }
96 } 96 }
97 97
98 // OK ... 98 // OK ...
99 func OK(w http.ResponseWriter, payload interface{}) { 99 func OK(w http.ResponseWriter, payload interface{}) {
100 SetContentType(w, "application/json") 100 SetContentType(w, "application/json")
101 Success(w, payload, http.StatusOK) 101 Success(w, payload, http.StatusOK)
102 } 102 }
103 103
104 // Created ... 104 // Created ...
105 func Created(w http.ResponseWriter, payload interface{}) { 105 func Created(w http.ResponseWriter, payload interface{}) {
106 SetContentType(w, "application/json") 106 SetContentType(w, "application/json")
107 Success(w, payload, http.StatusCreated) 107 Success(w, payload, http.StatusCreated)
108 } 108 }
109 109
110 type weberror struct { 110 type weberror struct {
111 Request string `json:"request"` 111 Request string `json:"request"`
112 Error string `json:"error"` 112 Error string `json:"error"`
113 } 113 }
114 114
115 // Error ... 115 // Error ...
116 func Error(w http.ResponseWriter, r *http.Request, code int, err string) { 116 func Error(w http.ResponseWriter, r *http.Request, code int, err string) {
117 werr := weberror{Error: err, Request: r.Method + " " + r.RequestURI} 117 werr := weberror{Error: err, Request: r.Method + " " + r.RequestURI}
118 w.WriteHeader(code) 118 w.WriteHeader(code)
119 json.NewEncoder(w).Encode(werr) 119 json.NewEncoder(w).Encode(werr)
120 } 120 }
121 121
122 // BadRequest ... 122 // BadRequest ...
123 func BadRequest(w http.ResponseWriter, r *http.Request, err string) { 123 func BadRequest(w http.ResponseWriter, r *http.Request, err string) {
124 SetContentType(w, "application/json") 124 SetContentType(w, "application/json")
125 Error(w, r, http.StatusBadRequest, err) 125 Error(w, r, http.StatusBadRequest, err)
126 } 126 }
127 127
128 // Unauthorized ... 128 // Unauthorized ...
129 func Unauthorized(w http.ResponseWriter, r *http.Request, err string) { 129 func Unauthorized(w http.ResponseWriter, r *http.Request, err string) {
130 SetContentType(w, "application/json") 130 SetContentType(w, "application/json")
131 Error(w, r, http.StatusUnauthorized, err) 131 Error(w, r, http.StatusUnauthorized, err)
132 } 132 }
133 133
134 // Forbidden ... 134 // Forbidden ...
135 func Forbidden(w http.ResponseWriter, r *http.Request, err string) { 135 func Forbidden(w http.ResponseWriter, r *http.Request, err string) {
136 SetContentType(w, "application/json") 136 SetContentType(w, "application/json")
137 Error(w, r, http.StatusForbidden, err) 137 Error(w, r, http.StatusForbidden, err)
138 } 138 }
139 139
140 // NotFound ... 140 // NotFound ...
141 func NotFound(w http.ResponseWriter, r *http.Request, err string) { 141 func NotFound(w http.ResponseWriter, r *http.Request, err string) {
142 SetContentType(w, "application/json") 142 SetContentType(w, "application/json")
143 Error(w, r, http.StatusNotFound, err) 143 Error(w, r, http.StatusNotFound, err)
144 } 144 }
145 145
146 // Conflict ... 146 // Conflict ...
147 func Conflict(w http.ResponseWriter, r *http.Request, err string) { 147 func Conflict(w http.ResponseWriter, r *http.Request, err string) {
148 SetContentType(w, "application/json") 148 SetContentType(w, "application/json")
149 Error(w, r, http.StatusConflict, err) 149 Error(w, r, http.StatusConflict, err)
150 } 150 }
151 151
152 // InternalServerError ... 152 // InternalServerError ...
153 func InternalServerError(w http.ResponseWriter, r *http.Request, err string) { 153 func InternalServerError(w http.ResponseWriter, r *http.Request, err string) {
154 SetContentType(w, "application/json") 154 SetContentType(w, "application/json")
155 Error(w, r, http.StatusInternalServerError, err) 155 Error(w, r, http.StatusInternalServerError, err)
156 } 156 }
157 157
158 func SetHeader(r *http.Request, key, val string) { 158 func SetHeader(r *http.Request, key, val string) {
159 r.Header.Set(key, val) 159 r.Header.Set(key, val)
160 } 160 }
161 161
162 func AddHeader(r *http.Request, key, val string) { 162 func AddHeader(r *http.Request, key, val string) {
163 r.Header.Add(key, val) 163 r.Header.Add(key, val)
164 } 164 }
165 165
166 func GetHeader(r *http.Request, key string) string { 166 func GetHeader(r *http.Request, key string) string {
167 return r.Header.Get(key) 167 return r.Header.Get(key)
168 } 168 }
169
170 func GetClientAgentUTCOffset(req *http.Request) int64 {
171 return StringToInt64(GetHeader(req, "X-Timezone-Offset"))
172 }
169 173
1 package webutility 1 package webutility
2 2
3 import ( 3 import (
4 "database/sql" 4 "database/sql"
5 "fmt" 5 "fmt"
6 "net/http" 6 "net/http"
7 7
8 "git.to-net.rs/marko.tikvic/gologger" 8 "git.to-net.rs/marko.tikvic/gologger"
9 "github.com/gorilla/mux" 9 "github.com/gorilla/mux"
10 ) 10 )
11 11
12 type Server struct { 12 type Server struct {
13 DB *sql.DB 13 DB *sql.DB
14 Router *mux.Router 14 Router *mux.Router
15 Logger *gologger.Logger 15 Logger *gologger.Logger
16 Port string 16 Port string
17 UTCOffset int64 17 UTCOffset int64
18 } 18 }
19 19
20 func NewServer(dsn, port, logDir string, utcOffset int64) (s *Server, err error) { 20 func NewODBCServer(dsn, port, logDir string, utcOffset int64) (s *Server, err error) {
21 s = new(Server) 21 s = new(Server)
22 22
23 s.Port = port 23 s.Port = port
24 24
25 if s.DB, err = sql.Open("odbc", fmt.Sprintf("DSN=%s;", dsn)); err != nil { 25 if s.DB, err = sql.Open("odbc", fmt.Sprintf("DSN=%s;", dsn)); err != nil {
26 return nil, err 26 return nil, err
27 } 27 }
28 28
29 s.Router = mux.NewRouter() 29 s.Router = mux.NewRouter()
30 30
31 if s.Logger, err = gologger.New("err", logDir, gologger.MaxLogSize1MB); err != nil { 31 if s.Logger, err = gologger.New("err", logDir, gologger.MaxLogSize1MB); err != nil {
32 return nil, fmt.Errorf("can't create logger: %s", err.Error()) 32 return nil, fmt.Errorf("can't create logger: %s", err.Error())
33 } 33 }
34 34
35 s.UTCOffset = utcOffset 35 s.UTCOffset = utcOffset
36 36
37 return s, nil 37 return s, nil
38 } 38 }
39 39
40 func (s *Server) Run() { 40 func (s *Server) Run() {
41 s.Logger.Print("Server listening on %s", s.Port) 41 s.Logger.Print("Server listening on %s", s.Port)
42 s.Logger.PrintAndTrace(http.ListenAndServe(s.Port, s.Router).Error()) 42 s.Logger.PrintAndTrace(http.ListenAndServe(s.Port, s.Router).Error())
43 } 43 }
44 44
45 func (s *Server) Cleanup() { 45 func (s *Server) Cleanup() {
46 if s.DB != nil { 46 if s.DB != nil {
47 s.DB.Close() 47 s.DB.Close()
48 } 48 }
49 49
50 if s.Logger != nil { 50 if s.Logger != nil {
51 s.Logger.Close() 51 s.Logger.Close()
52 } 52 }
53 } 53 }
54 54
55 func (s *Server) StartTransaction() (*sql.Tx, error) { 55 func (s *Server) StartTransaction() (*sql.Tx, error) {
56 return s.DB.Begin() 56 return s.DB.Begin()
57 } 57 }
58 58
59 func CommitChanges(tx *sql.Tx, err *error, opt ...error) { 59 func CommitChanges(tx *sql.Tx, err *error, opt ...error) {
60 if *err != nil { 60 if *err != nil {
61 tx.Rollback() 61 tx.Rollback()
62 return 62 return
63 } 63 }
64 64
65 for _, e := range opt { 65 for _, e := range opt {
66 if e != nil { 66 if e != nil {
67 tx.Rollback() 67 tx.Rollback()
68 return 68 return
69 } 69 }
70 } 70 }
71 71
72 if *err = tx.Commit(); *err != nil { 72 if *err = tx.Commit(); *err != nil {
73 tx.Rollback() 73 tx.Rollback()
74 } 74 }
75 } 75 }
76 76