Gorelay

From UVOO Tech Wiki
Revision as of 01:58, 3 May 2024 by Busk (talk | contribs)
Jump to navigation Jump to search

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"))
}