summaryrefslogtreecommitdiff
path: root/util
diff options
context:
space:
mode:
authorMike Crute <mike@crute.us>2020-01-04 06:39:30 +0000
committerMike Crute <mike@crute.us>2020-08-11 02:54:46 +0000
commitedb2c73150c786126c63c96cee7dae5e1c10b6df (patch)
tree863ea8743a94c816664ebbecc9e9a68387e2ed7a /util
parent8ed9671c0b4f78711858448cf3b4ee9af0eba51e (diff)
downloadgo_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.go19
-rw-r--r--util/gin.go72
-rw-r--r--util/http.go26
-rw-r--r--util/ip.go24
-rw-r--r--util/viper.go36
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 @@
1package util
2
3import (
4 "io"
5 "io/ioutil"
6)
7
8func 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 @@
1package util
2
3import (
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
15func 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
32func 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
67func 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 @@
1package util
2
3import (
4 "fmt"
5 "net/http"
6 "net/url"
7)
8
9func 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 @@
1package util
2
3import (
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.
11var ipRegexp = regexp.MustCompile(`(?:\[([0-9a-f:]+)\]|(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}))(?::\d+)?`)
12
13func 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 @@
1package util
2
3import (
4 "strings"
5
6 "github.com/spf13/cobra"
7 "github.com/spf13/viper"
8)
9
10type ViperWrap struct {
11 cmd *cobra.Command
12}
13
14func WrapViper(cmd *cobra.Command, prefix string) *ViperWrap {
15 viper.SetEnvPrefix(prefix)
16 viper.AutomaticEnv()
17 return &ViperWrap{cmd}
18}
19
20func (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
26func (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
32func (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}