Difference between revisions of "Gorelay"
Jump to navigation
Jump to search
(Created page with "# Simple HTTP Relay written in go ``` package main import ( "crypto/tls" "github.com/labstack/echo/v4" "io" "net/http" ) func main() {...") |
|||
Line 5: | Line 5: | ||
import ( | import ( | ||
"crypto/tls" | "crypto/tls" | ||
− | " | + | "flag" |
+ | "fmt" | ||
"io" | "io" | ||
+ | "log" | ||
"net/http" | "net/http" | ||
+ | "regexp" | ||
+ | "time" | ||
+ | |||
+ | "github.com/labstack/echo/v4" | ||
) | ) | ||
+ | |||
+ | func syslogLogger(next echo.HandlerFunc) echo.HandlerFunc { | ||
+ | return func(c echo.Context) error { | ||
+ | start := time.Now() | ||
+ | err := next(c) | ||
+ | stop := time.Now() | ||
+ | req := c.Request() | ||
+ | res := c.Response() | ||
+ | |||
+ | log.Printf("%s - [%s] \"%s %s %s\" %d %d %v", | ||
+ | c.RealIP(), | ||
+ | stop.Format(time.RFC3339), | ||
+ | req.Method, req.RequestURI, req.Proto, | ||
+ | res.Status, res.Size, stop.Sub(start), | ||
+ | ) | ||
+ | |||
+ | return err | ||
+ | } | ||
+ | } | ||
func main() { | func main() { | ||
+ | schema := flag.String("schema", "https", "URI schema (http or https)") | ||
+ | port := flag.Int("port", 443, "Port number of the remote HTTPS endpoint") | ||
+ | fqdn := flag.String("fqdn", "", "Fully Qualified Domain Name (required)") | ||
+ | username := flag.String("username", "", "Username for basic authentication") | ||
+ | password := flag.String("password", "", "Password for basic authentication") | ||
+ | skipTLS := flag.Bool("skip_tls_verify", false, "Skip TLS certificate verification") | ||
+ | flag.Parse() | ||
+ | |||
+ | if *fqdn == "" { | ||
+ | panic("FQDN argument is required") | ||
+ | } | ||
+ | |||
+ | uriBase := fmt.Sprintf("%s://%s:%d", *schema, *fqdn, *port) | ||
+ | |||
e := echo.New() | e := echo.New() | ||
+ | |||
+ | e.Use(syslogLogger) | ||
e.Any("/*", func(c echo.Context) error { | e.Any("/*", func(c echo.Context) error { | ||
Line 17: | Line 58: | ||
client := &http.Client{} | client := &http.Client{} | ||
− | client.Transport = &http.Transport{ | + | if *skipTLS { |
− | + | client.Transport = &http.Transport{ | |
+ | TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, | ||
+ | } | ||
} | } | ||
+ | oldFolderPattern := regexp.MustCompile(`/api/v1/uca/`) | ||
+ | newFolder := "/api/v1/cfssl/" | ||
+ | requestURI := oldFolderPattern.ReplaceAllString(req.RequestURI, newFolder) | ||
− | // | + | // newReq, err := http.NewRequest(req.Method, uriBase+req.RequestURI, req.Body) |
− | + | newReq, err := http.NewRequest(req.Method, uriBase+requestURI, req.Body) | |
if err != nil { | if err != nil { | ||
return err | return err | ||
+ | } | ||
+ | if *username != "" && *password != "" { | ||
+ | newReq.SetBasicAuth(*username, *password) | ||
} | } | ||
− | |||
for k, v := range req.Header { | for k, v := range req.Header { | ||
newReq.Header[k] = v | newReq.Header[k] = v | ||
} | } | ||
− | |||
resp, err := client.Do(newReq) | resp, err := client.Do(newReq) | ||
if err != nil { | if err != nil { | ||
Line 39: | Line 86: | ||
defer resp.Body.Close() | defer resp.Body.Close() | ||
− | |||
for k, v := range resp.Header { | for k, v := range resp.Header { | ||
c.Response().Header().Set(k, v[0]) | c.Response().Header().Set(k, v[0]) | ||
} | } | ||
− | |||
io.Copy(c.Response().Writer, resp.Body) | io.Copy(c.Response().Writer, resp.Body) | ||
Line 50: | Line 95: | ||
}) | }) | ||
− | e.Start(":8080") | + | e.Logger.Fatal(e.Start(":8080")) |
} | } | ||
``` | ``` |
Revision as of 01:58, 3 May 2024
Simple HTTP Relay written in go
package main import ( "crypto/tls" "flag" "fmt" "io" "log" "net/http" "regexp" "time" "github.com/labstack/echo/v4" ) func syslogLogger(next echo.HandlerFunc) echo.HandlerFunc { return func(c echo.Context) error { start := time.Now() err := next(c) stop := time.Now() req := c.Request() res := c.Response() log.Printf("%s - [%s] \"%s %s %s\" %d %d %v", c.RealIP(), stop.Format(time.RFC3339), req.Method, req.RequestURI, req.Proto, res.Status, res.Size, stop.Sub(start), ) return err } } func main() { schema := flag.String("schema", "https", "URI schema (http or https)") port := flag.Int("port", 443, "Port number of the remote HTTPS endpoint") fqdn := flag.String("fqdn", "", "Fully Qualified Domain Name (required)") username := flag.String("username", "", "Username for basic authentication") password := flag.String("password", "", "Password for basic authentication") skipTLS := flag.Bool("skip_tls_verify", false, "Skip TLS certificate verification") flag.Parse() if *fqdn == "" { panic("FQDN argument is required") } uriBase := fmt.Sprintf("%s://%s:%d", *schema, *fqdn, *port) e := echo.New() e.Use(syslogLogger) e.Any("/*", func(c echo.Context) error { req := c.Request() client := &http.Client{} if *skipTLS { client.Transport = &http.Transport{ TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, } } oldFolderPattern := regexp.MustCompile(`/api/v1/uca/`) newFolder := "/api/v1/cfssl/" requestURI := oldFolderPattern.ReplaceAllString(req.RequestURI, newFolder) // newReq, err := http.NewRequest(req.Method, uriBase+req.RequestURI, req.Body) newReq, err := http.NewRequest(req.Method, uriBase+requestURI, req.Body) if err != nil { return err } if *username != "" && *password != "" { newReq.SetBasicAuth(*username, *password) } for k, v := range req.Header { newReq.Header[k] = v } resp, err := client.Do(newReq) if err != nil { return err } defer resp.Body.Close() for k, v := range resp.Header { c.Response().Header().Set(k, v[0]) } io.Copy(c.Response().Writer, resp.Body) return nil }) e.Logger.Fatal(e.Start(":8080")) }