diff options
author | Mike Crute <mike@crute.us> | 2020-01-04 06:39:30 +0000 |
---|---|---|
committer | Mike Crute <mike@crute.us> | 2020-08-11 02:54:46 +0000 |
commit | edb2c73150c786126c63c96cee7dae5e1c10b6df (patch) | |
tree | 863ea8743a94c816664ebbecc9e9a68387e2ed7a /util | |
parent | 8ed9671c0b4f78711858448cf3b4ee9af0eba51e (diff) | |
download | go_ddns_manager-edb2c73150c786126c63c96cee7dae5e1c10b6df.tar.bz2 go_ddns_manager-edb2c73150c786126c63c96cee7dae5e1c10b6df.tar.xz go_ddns_manager-edb2c73150c786126c63c96cee7dae5e1c10b6df.zip |
Refator using le utils
Diffstat (limited to 'util')
-rw-r--r-- | util/file.go | 19 | ||||
-rw-r--r-- | util/gin.go | 72 | ||||
-rw-r--r-- | util/http.go | 26 | ||||
-rw-r--r-- | util/ip.go | 24 | ||||
-rw-r--r-- | util/viper.go | 36 |
5 files changed, 177 insertions, 0 deletions
diff --git a/util/file.go b/util/file.go new file mode 100644 index 0000000..b6fc86f --- /dev/null +++ b/util/file.go | |||
@@ -0,0 +1,19 @@ | |||
1 | package util | ||
2 | |||
3 | import ( | ||
4 | "io" | ||
5 | "io/ioutil" | ||
6 | ) | ||
7 | |||
8 | func WriteReaderToFile(filename string, data io.Reader) error { | ||
9 | d, err := ioutil.ReadAll(data) | ||
10 | if err != nil { | ||
11 | return err | ||
12 | } | ||
13 | |||
14 | if err = ioutil.WriteFile(filename, d, 0644); err != nil { | ||
15 | return err | ||
16 | } | ||
17 | |||
18 | return nil | ||
19 | } | ||
diff --git a/util/gin.go b/util/gin.go new file mode 100644 index 0000000..9bba6ee --- /dev/null +++ b/util/gin.go | |||
@@ -0,0 +1,72 @@ | |||
1 | package util | ||
2 | |||
3 | import ( | ||
4 | "context" | ||
5 | "log" | ||
6 | "net" | ||
7 | "net/http" | ||
8 | "os" | ||
9 | "os/signal" | ||
10 | |||
11 | "github.com/gin-gonic/gin" | ||
12 | ) | ||
13 | |||
14 | // Copied from: https://github.com/gin-gonic/gin/blob/59ab588bf597f9f41faee4f217b5659893c2e925/utils.go#L137 | ||
15 | func resolveAddress(addr []string) string { | ||
16 | switch len(addr) { | ||
17 | case 0: | ||
18 | if port := os.Getenv("PORT"); port != "" { | ||
19 | log.Printf("Environment variable PORT=\"%s\"", port) | ||
20 | return ":" + port | ||
21 | } | ||
22 | log.Printf("Environment variable PORT is undefined. Using port :8080 by default") | ||
23 | return ":8080" | ||
24 | case 1: | ||
25 | return addr[0] | ||
26 | default: | ||
27 | panic("too many parameters") | ||
28 | } | ||
29 | } | ||
30 | |||
31 | // Runs a gin.Engine instance in a way that can be canceled by an SIGINT | ||
32 | func GinRun(e *gin.Engine, debug bool, a ...string) { | ||
33 | if debug { | ||
34 | gin.SetMode(gin.DebugMode) | ||
35 | } else { | ||
36 | gin.SetMode(gin.ReleaseMode) | ||
37 | } | ||
38 | |||
39 | srv := &http.Server{ | ||
40 | Addr: resolveAddress(a), | ||
41 | Handler: e, | ||
42 | } | ||
43 | |||
44 | idleConnsClosed := make(chan struct{}) | ||
45 | |||
46 | go func() { | ||
47 | sigint := make(chan os.Signal, 1) | ||
48 | signal.Notify(sigint, os.Interrupt) | ||
49 | <-sigint | ||
50 | |||
51 | log.Println("Caught SIGINT, shutting down") | ||
52 | if err := srv.Shutdown(context.Background()); err != nil { | ||
53 | log.Printf("HTTP server Shutdown: %v", err) | ||
54 | } | ||
55 | |||
56 | close(idleConnsClosed) | ||
57 | }() | ||
58 | |||
59 | log.Printf("Listening and serving HTTP on %s\n", srv.Addr) | ||
60 | if err := srv.ListenAndServe(); err != http.ErrServerClosed { | ||
61 | log.Fatalf("HTTP server ListenAndServe: %v", err) | ||
62 | } | ||
63 | |||
64 | <-idleConnsClosed | ||
65 | } | ||
66 | |||
67 | func GetRequestIP(c *gin.Context) net.IP { | ||
68 | if xff := c.Request.Header.Get("X-Forwarded-For"); xff != "" { | ||
69 | return ParseIP(xff) | ||
70 | } | ||
71 | return ParseIP(c.Request.RemoteAddr) | ||
72 | } | ||
diff --git a/util/http.go b/util/http.go new file mode 100644 index 0000000..31cd94d --- /dev/null +++ b/util/http.go | |||
@@ -0,0 +1,26 @@ | |||
1 | package util | ||
2 | |||
3 | import ( | ||
4 | "fmt" | ||
5 | "net/http" | ||
6 | "net/url" | ||
7 | ) | ||
8 | |||
9 | func MakeURL(r *http.Request, path string, subs ...interface{}) *url.URL { | ||
10 | scheme := "https" | ||
11 | if r.TLS == nil { | ||
12 | scheme = "http" | ||
13 | } | ||
14 | |||
15 | // Always defer to whatever the proxy told us it was doing because this | ||
16 | // could be a mullet-VIP in either direction. | ||
17 | if fwProto := r.Header.Get("X-Forwarded-Proto"); fwProto != "" { | ||
18 | scheme = fwProto | ||
19 | } | ||
20 | |||
21 | return &url.URL{ | ||
22 | Scheme: scheme, | ||
23 | Host: r.Host, | ||
24 | Path: fmt.Sprintf(path, subs...), | ||
25 | } | ||
26 | } | ||
diff --git a/util/ip.go b/util/ip.go new file mode 100644 index 0000000..f86d5b5 --- /dev/null +++ b/util/ip.go | |||
@@ -0,0 +1,24 @@ | |||
1 | package util | ||
2 | |||
3 | import ( | ||
4 | "net" | ||
5 | "regexp" | ||
6 | ) | ||
7 | |||
8 | // Parses an IPv4 or IPv6 address with an optional port on the end. Returns | ||
9 | // match groups for the addresses. The first match is the IPv6 address and the | ||
10 | // second the IPv4 address. | ||
11 | var ipRegexp = regexp.MustCompile(`(?:\[([0-9a-f:]+)\]|(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}))(?::\d+)?`) | ||
12 | |||
13 | func ParseIP(s string) net.IP { | ||
14 | ips := ipRegexp.FindStringSubmatch(s) | ||
15 | if ips == nil { | ||
16 | return nil | ||
17 | } | ||
18 | |||
19 | if v6, v4 := ips[1], ips[2]; v6 != "" { | ||
20 | return net.ParseIP(v6) | ||
21 | } else { | ||
22 | return net.ParseIP(v4) | ||
23 | } | ||
24 | } | ||
diff --git a/util/viper.go b/util/viper.go new file mode 100644 index 0000000..0f08a6c --- /dev/null +++ b/util/viper.go | |||
@@ -0,0 +1,36 @@ | |||
1 | package util | ||
2 | |||
3 | import ( | ||
4 | "strings" | ||
5 | |||
6 | "github.com/spf13/cobra" | ||
7 | "github.com/spf13/viper" | ||
8 | ) | ||
9 | |||
10 | type ViperWrap struct { | ||
11 | cmd *cobra.Command | ||
12 | } | ||
13 | |||
14 | func WrapViper(cmd *cobra.Command, prefix string) *ViperWrap { | ||
15 | viper.SetEnvPrefix(prefix) | ||
16 | viper.AutomaticEnv() | ||
17 | return &ViperWrap{cmd} | ||
18 | } | ||
19 | |||
20 | func (v *ViperWrap) bindViper(name, short string, defaultv interface{}, help string) { | ||
21 | vname := strings.ReplaceAll(name, "-", "_") | ||
22 | viper.BindPFlag(vname, v.cmd.Flags().Lookup(name)) | ||
23 | viper.SetDefault(vname, defaultv) | ||
24 | } | ||
25 | |||
26 | func (v *ViperWrap) BindString(name, short, defaultv, help string) *ViperWrap { | ||
27 | v.cmd.Flags().StringP(name, short, defaultv, help) | ||
28 | v.bindViper(name, short, defaultv, help) | ||
29 | return v | ||
30 | } | ||
31 | |||
32 | func (v *ViperWrap) BindBool(name, short string, defaultv bool, help string) *ViperWrap { | ||
33 | v.cmd.Flags().BoolP(name, short, defaultv, help) | ||
34 | v.bindViper(name, short, defaultv, help) | ||
35 | return v | ||
36 | } | ||