Commit b80ee4b2bc37bdc1ab97b7a2eb302badaa906cd2

Authored by Marko Tikvić
1 parent 832243a5df
Exists in master

new stuff

... ... @@ -0,0 +1,41 @@
  1 +package webutility
  2 +
  3 +import (
  4 + "fmt"
  5 + "time"
  6 +)
  7 +
  8 +const (
  9 + YYYYMMDD_sl = "2006/01/02"
  10 + YYYYMMDD_ds = "2006-01-02"
  11 + YYYYMMDD_dt = "2006.01.02."
  12 +
  13 + DDMMYYYY_sl = "02/01/2006"
  14 + DDMMYYYY_ds = "02-01-2006"
  15 + DDMMYYYY_dt = "02.01.2006."
  16 +
  17 + YYYYMMDD_HHMMSS_sl = "2006/01/02 15:04:05"
  18 + YYYYMMDD_HHMMSS_ds = "2006-01-02 15:04:05"
  19 + YYYYMMDD_HHMMSS_dt = "2006.01.02. 15:04:05"
  20 +
  21 + DDMMYYYY_HHMMSS_sl = "02/01/2006 15:04:05"
  22 + DDMMYYYY_HHMMSS_ds = "02-01-2006 15:04:05"
  23 + DDMMYYYY_HHMMSS_dt = "02.01.2006. 15:04:05"
  24 +)
  25 +
  26 +func Systime() int64 {
  27 + return time.Now().Unix()
  28 +}
  29 +
  30 +func DateToEpoch(date, format string) int64 {
  31 + t, err := time.Parse(format, date)
  32 + if err != nil {
  33 + fmt.Println(err.Error())
  34 + return 0
  35 + }
  36 + return t.Unix()
  37 +}
  38 +
  39 +func EpochToDate(e int64, format string) string {
  40 + return time.Unix(e, 0).Format(format)
  41 +}
... ...
1 1 package webutility
2 2  
3 3 import (
4   - "fmt"
5 4 "net/http"
6 5 "net/url"
7 6 "strings"
... ... @@ -37,7 +36,7 @@ func (f Filter) ValueAt(val string, index int) string {
37 36 return ""
38 37 }
39 38  
40   -func (f Filter) validate(validFilters []string) (Filter, bool) {
  39 +func (f Filter) Validate(validFilters []string) (Filter, bool) {
41 40 goodFilters := make(Filter)
42 41 cnt, len := 0, 0
43 42 for fi := range f {
... ... @@ -82,53 +81,3 @@ func ParseFilters(req *http.Request, header string) (filters Filter) {
82 81  
83 82 return filters
84 83 }
85   -
86   -// MakeFilterString is very dodgy, needs more robustness.
87   -// TODO(marko)
88   -func MakeFilterString(prefix string, filters Filter, validFilters []string) (res string, ok bool) {
89   - if prefix != "" {
90   - prefix += "."
91   - }
92   -
93   - if filters.Count() == 0 {
94   - return "", true
95   - }
96   -
97   - filters, ok = filters.validate(validFilters)
98   - if !ok {
99   - return "", false
100   - }
101   -
102   - first := true
103   - for k, filter := range filters {
104   - symbol := "="
105   -
106   - if first {
107   - res += " where "
108   - first = false
109   - } else {
110   - res += " and "
111   - }
112   -
113   - res += "("
114   - for i, f := range filter {
115   - if strings.HasPrefix(f, "<") || strings.HasPrefix(f, ">") || strings.HasPrefix(f, "!") {
116   - symbol = string(f[0])
117   - f = strings.TrimLeft(f, "<>!")
118   - if strings.HasPrefix(f, "=") {
119   - f = strings.TrimLeft(f, "=")
120   - symbol += "="
121   - }
122   - }
123   -
124   - res += fmt.Sprintf("%s%s %s '%s'", prefix, k, symbol, f)
125   -
126   - if i < len(filter)-1 {
127   - res += " or "
128   - }
129   - }
130   - res += ")"
131   - }
132   -
133   - return res, ok
134   -}
... ...
... ... @@ -0,0 +1,59 @@
  1 +package webutility
  2 +
  3 +import (
  4 + "fmt"
  5 + "math"
  6 + "math/big"
  7 +)
  8 +
  9 +func RoundFloat64(f float64, dec int) float64 {
  10 + p := math.Pow(10, float64(dec))
  11 + return math.Round(f*p) / p
  12 +}
  13 +
  14 +func NewBF(f float64, prec uint) *big.Float {
  15 + x := big.NewFloat(f)
  16 + x.SetPrec(prec)
  17 + return x
  18 +}
  19 +
  20 +func AddBF(x, y *big.Float) *big.Float {
  21 + z := big.NewFloat(0.0)
  22 + z.SetPrec(x.Prec())
  23 + z.Add(x, y)
  24 + return z
  25 +}
  26 +
  27 +func SubBF(x, y *big.Float) *big.Float {
  28 + z := big.NewFloat(0.0)
  29 + z.SetPrec(x.Prec())
  30 +
  31 + yneg := big.NewFloat(0.0)
  32 + yneg.Neg(y)
  33 +
  34 + z.Add(x, yneg)
  35 + return z
  36 +}
  37 +
  38 +func MulBF(x, y *big.Float) *big.Float {
  39 + z := big.NewFloat(0.0)
  40 + z.SetPrec(x.Prec())
  41 + z.Mul(x, y)
  42 + return z
  43 +}
  44 +
  45 +func DivBF(x, y *big.Float) *big.Float {
  46 + z := big.NewFloat(0.0)
  47 + z.SetPrec(x.Prec())
  48 + z.Quo(x, y)
  49 + return z
  50 +}
  51 +
  52 +func BFtoFloat(f *big.Float) float64 {
  53 + v, _ := f.Float64()
  54 + return v
  55 +}
  56 +
  57 +func Float64ToString(f float64) string {
  58 + return fmt.Sprintf("%.2f", f)
  59 +}
... ...
... ... @@ -2,7 +2,6 @@ package webutility
2 2  
3 3 import (
4 4 "fmt"
5   - "strconv"
6 5 )
7 6  
8 7 // ClampInt64 ...
... ... @@ -21,18 +20,6 @@ func InRangeInt64(v, min, max int64) bool {
21 20 return (v >= min && v <= max)
22 21 }
23 22  
24   -// StringToInt64 ...
25   -func StringToInt64(s string) int64 {
26   - i, _ := strconv.ParseInt(s, 10, 64)
27   - return i
28   -}
29   -
30   -// StringToFloat64 ...
31   -func StringToFloat64(s string) float64 {
32   - f, _ := strconv.ParseFloat(s, 64)
33   - return f
34   -}
35   -
36 23 // Int64ToString ...
37 24 func Int64ToString(i int64) string {
38 25 return fmt.Sprintf("%d", i)
... ... @@ -51,10 +38,11 @@ func Int64ToBool(i int64) bool {
51 38 return i != 0
52 39 }
53 40  
54   -func StringToValidInt64(s string) (int64, bool) {
55   - i, err := strconv.ParseInt(s, 10, 64)
56   - if err != nil {
57   - return i, false
  41 +func MaxInt(vars ...int) (max int) {
  42 + for _, v := range vars {
  43 + if v > max {
  44 + max = v
  45 + }
58 46 }
59   - return i, true
  47 + return max
60 48 }
... ...
middleware/main.go
... ... @@ -4,6 +4,8 @@ import (
4 4 "fmt"
5 5 "io/ioutil"
6 6 "net/http"
  7 + "os"
  8 + "strings"
7 9  
8 10 web "git.to-net.rs/marko.tikvic/webutility"
9 11 )
... ... @@ -27,54 +29,103 @@ func LogTraffic(h http.HandlerFunc) http.HandlerFunc {
27 29 func TrafficLogsHandler(w http.ResponseWriter, req *http.Request) {
28 30 switch req.Method {
29 31 case "GET":
30   - files, err := ioutil.ReadDir(httpLogger.GetOutDir() + "/")
31   - if err != nil {
32   - web.InternalServerError(w, req, err.Error())
33   - return
34   - }
  32 + logfile := req.FormValue("logfile")
  33 + if logfile == "" {
  34 + files, err := ioutil.ReadDir(httpLogger.GetOutDir() + "/")
  35 + if err != nil {
  36 + web.InternalServerError(w, req, err.Error())
  37 + return
  38 + }
35 39  
36   - web.SetContentType(w, "text/html; charset=utf-8")
37   - web.SetResponseStatus(w, http.StatusOK)
38   -
39   - web.WriteResponse(w, []byte("<body style='background-color: black; color: white'>"))
40   - inputForm := `
41   - <div>
42   - <form action="/api/v1/logs" method="POST" target="_blank">
43   - Username:<br>
44   - <input type="text" name="username"><br>
45   - Password:<br>
46   - <input type="password" name="password"><br>
47   - Log:<br>
48   - <input type="text" name="logfile"><br>
49   - <input type="submit" value="View">
50   - </form>
51   - </div>`
52   - web.WriteResponse(w, []byte(inputForm))
53   -
54   - web.WriteResponse(w, []byte("<table>"))
55   - web.WriteResponse(w, []byte("<tr><th>Name</th><th>Size</th></tr>"))
56   - for i := range files {
57   - name := files[i].Name()
58   - size := files[i].Size()
59   - div := fmt.Sprintf(`<tr><td>%s</td><td style="text-align:right">%dB</td></tr>`, name, size)
60   - web.WriteResponse(w, []byte(div))
61   - }
62   - web.WriteResponse(w, []byte("</table></body>"))
  40 + errorLogs := make([]os.FileInfo, 0)
  41 + httpLogs := make([]os.FileInfo, 0)
63 42  
64   - case "POST":
65   - web.SetContentType(w, "text/html; charset=utf-8")
  43 + var errorLogsCount, httpLogsCount int
  44 + for _, f := range files {
  45 + if strings.HasPrefix(f.Name(), "err") {
  46 + errorLogs = append(errorLogs, f)
  47 + errorLogsCount++
  48 + } else if strings.HasPrefix(f.Name(), "http") {
  49 + httpLogs = append(httpLogs, f)
  50 + httpLogsCount++
  51 + }
  52 + }
66 53  
67   - logfile := req.FormValue("logfile")
68   - content, err := web.ReadFileContent(httpLogger.GetOutDir() + "/" + logfile)
69   - if err != nil {
70   - web.InternalServerError(w, req, err.Error())
71   - return
  54 + web.SetContentType(w, "text/html; charset=utf-8")
  55 + web.SetResponseStatus(w, http.StatusOK)
  56 +
  57 + web.WriteResponse(w, []byte(`
  58 + <body style='background-color: black; color: white'>
  59 + <table>
  60 + <tr>
  61 + <th>Error logs</th><th></th> <th style="width: 25px"></th>
  62 + <th>Traffic logs</th><th></th>
  63 + </tr>
  64 + `))
  65 +
  66 + var (
  67 + div, name string
  68 + size int64
  69 + )
  70 +
  71 + max := errorLogsCount
  72 + if httpLogsCount > errorLogsCount {
  73 + max = httpLogsCount
  74 + }
  75 +
  76 + for i := 0; i < max; i++ {
  77 + div = "<tr>"
  78 +
  79 + if i < errorLogsCount {
  80 + name = errorLogs[i].Name()
  81 + size = errorLogs[i].Size()
  82 + div += fmt.Sprintf(`
  83 + <td>
  84 + <a style="color: white"
  85 + href="/api/v1/logs?logfile=%s"
  86 + target="_blank">%s
  87 + </a>
  88 + </td>
  89 + <td style="color: white; text-align:right">%dB</td>`,
  90 + name, name, size,
  91 + )
  92 + } else {
  93 + div += fmt.Sprintf(`<td></td><td></td>`)
  94 + }
  95 +
  96 + div += "<td></td>"
  97 +
  98 + if i < httpLogsCount {
  99 + name := httpLogs[i].Name()
  100 + size := httpLogs[i].Size()
  101 + div += fmt.Sprintf(`
  102 + <td>
  103 + <a style="color: white"
  104 + href="/api/v1/logs?logfile=%s"
  105 + target="_blank">%s
  106 + </a></td>
  107 + <td style="color: white; text-align:right">%dB</td>`,
  108 + name, name, size,
  109 + )
  110 + } else {
  111 + div += fmt.Sprintf(`<td></td><td></td>`)
  112 + }
  113 +
  114 + div += "</tr>"
  115 + web.WriteResponse(w, []byte(div))
  116 + }
  117 + web.WriteResponse(w, []byte("</table></body>"))
  118 + } else {
  119 + content, err := web.ReadFileContent(httpLogger.GetOutDir() + "/" + logfile)
  120 + if err != nil {
  121 + web.InternalServerError(w, req, err.Error())
  122 + return
  123 + }
  124 + web.SetResponseStatus(w, http.StatusOK)
  125 + web.WriteResponse(w, []byte("<body style='background-color: black; color: white'>"))
  126 + web.WriteResponse(w, []byte("<pre>"))
  127 + web.WriteResponse(w, content)
  128 + web.WriteResponse(w, []byte("</pre></body>"))
72 129 }
73   - web.SetResponseStatus(w, http.StatusOK)
74   - web.WriteResponse(w, []byte("<body style='background-color: black; color: white'>"))
75   - web.WriteResponse(w, []byte("<pre>"))
76   - web.WriteResponse(w, content)
77   - web.WriteResponse(w, []byte("</pre></body>"))
78   - return
79 130 }
80 131 }
... ...
... ... @@ -123,6 +123,14 @@ func (ni *NullInt64) Scan(value interface{}) error {
123 123 return nil
124 124 }
125 125  
  126 +// ScanPtr ...
  127 +func (ni *NullInt64) ScanPtr(v interface{}) error {
  128 + if ip, ok := v.(*int64); ok && ip != nil {
  129 + return ni.Scan(*ip)
  130 + }
  131 + return nil
  132 +}
  133 +
126 134 // Value ...
127 135 func (ni *NullInt64) Value() (driver.Value, error) {
128 136 if !ni.Valid {
... ... @@ -173,6 +181,14 @@ func (nf *NullFloat64) Scan(value interface{}) error {
173 181 return nil
174 182 }
175 183  
  184 +// ScanPtr ...
  185 +func (nf *NullFloat64) ScanPtr(v interface{}) error {
  186 + if fp, ok := v.(*float64); ok && fp != nil {
  187 + return nf.Scan(*fp)
  188 + }
  189 + return nil
  190 +}
  191 +
176 192 // Value ...
177 193 func (nf *NullFloat64) Value() (driver.Value, error) {
178 194 if !nf.Valid {
... ...
... ... @@ -51,13 +51,13 @@ type Translation struct {
51 51 // Payload ...
52 52 type Payload struct {
53 53 Method string `json:"method"`
54   - Params map[string]string `json:"params"`
55   - Lang []Translation `json:"lang"`
56   - Fields []Field `json:"fields"`
57   - Correlations []CorrelationField `json:"correlationFields"`
58   - IDField string `json:"idField"`
  54 + Params map[string]string `json:"params,omitempty"`
  55 + Lang []Translation `json:"lang,omitempty"`
  56 + Fields []Field `json:"fields,omitempty"`
  57 + Correlations []CorrelationField `json:"correlationFields,omitempty"`
  58 + IDField string `json:"idField,omitempty"`
59 59  
60   - Links PaginationLinks `json:"_links"`
  60 + Links PaginationLinks `json:"_links,omitempty"`
61 61  
62 62 // Data holds JSON payload. It can't be used for itteration.
63 63 Data interface{} `json:"data"`
... ...
... ... @@ -3,8 +3,8 @@ package webutility
3 3 type QSortDirection int
4 4  
5 5 const (
6   - QSortAscending = 0
7   - QSortDescending = 1
  6 + QSortAscending QSortDirection = iota
  7 + QSortDescending
8 8 )
9 9  
10 10 // QuickSortable is an interface for quicksorting slices.
... ... @@ -30,19 +30,22 @@ func Quicksort(que QuickSortable, low, high int, dir QSortDirection) {
30 30 }
31 31  
32 32 func partition(que QuickSortable, low, high int, dir QSortDirection) int {
  33 + swap := 0
  34 + // -1 -> i > j
  35 + // 1 -> i < j
  36 + if dir == QSortDescending {
  37 + swap = -1
  38 + } else {
  39 + swap = 1
  40 + }
  41 +
33 42 i := low - 1
34 43 for j := low; j <= high-1; j++ {
35   - if dir == QSortAscending {
36   - if que.Compare(j, high) == -1 {
37   - i++
38   - que.Swap(i, j)
39   - }
40   - } else if dir == QSortDescending {
41   - if que.Compare(j, high) == 1 {
42   - i++
43   - que.Swap(i, j)
44   - }
  44 + if que.Compare(j, high) == swap {
  45 + i++
  46 + que.Swap(i, j)
45 47 }
  48 + continue
46 49 }
47 50 que.Swap(i+1, high)
48 51 return i + 1
... ...
... ... @@ -22,13 +22,14 @@ func IsWrappedWith(src, begin, end string) bool {
22 22 // ParseInt64Arr ...
23 23 func ParseInt64Arr(s, sep string) (arr []int64) {
24 24 s = strings.TrimSpace(s)
25   - if s != "" {
26   - parts := strings.Split(s, sep)
27   - arr = make([]int64, len(parts))
28   - for i, p := range parts {
29   - num := StringToInt64(p)
30   - arr[i] = num
31   - }
  25 + if s == "" {
  26 + return
  27 + }
  28 + parts := strings.Split(s, sep)
  29 + arr = make([]int64, len(parts))
  30 + for i, p := range parts {
  31 + num := StringToInt64(p)
  32 + arr[i] = num
32 33 }
33 34  
34 35 return arr
... ... @@ -174,6 +175,14 @@ func LimitMSWordTextWithThreeDots(txt string, maxLen int) string {
174 175 return txt[:maxLen] + "..."
175 176 }
176 177  
  178 +func ThreeDots(txt string, maxLen int) string {
  179 + if len(txt) <= maxLen {
  180 + return txt
  181 + }
  182 +
  183 + return txt[:maxLen] + "..."
  184 +}
  185 +
177 186 // SplitStringAtWholeWords ...
178 187 func SplitStringAtWholeWords(s string, maxLen int) (res []string) {
179 188 parts := strings.Split(s, " ")
... ... @@ -197,3 +206,23 @@ func SplitStringAtWholeWords(s string, maxLen int) (res []string) {
197 206  
198 207 return res
199 208 }
  209 +
  210 +// StringToInt64 ...
  211 +func StringToInt64(s string) int64 {
  212 + i, _ := strconv.ParseInt(s, 10, 64)
  213 + return i
  214 +}
  215 +
  216 +// StringToFloat64 ...
  217 +func StringToFloat64(s string) float64 {
  218 + f, _ := strconv.ParseFloat(s, 64)
  219 + return f
  220 +}
  221 +
  222 +func StringToValidInt64(s string) (int64, bool) {
  223 + i, err := strconv.ParseInt(s, 10, 64)
  224 + if err != nil {
  225 + return i, false
  226 + }
  227 + return i, true
  228 +}
... ...