wip
This commit is contained in:
51
config.go
Normal file
51
config.go
Normal file
@@ -0,0 +1,51 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"gopkg.in/yaml.v2"
|
||||
)
|
||||
|
||||
type (
|
||||
Config struct {
|
||||
Cert Cert
|
||||
Port int
|
||||
Endpoints map[string]Endpoint
|
||||
}
|
||||
|
||||
Cert struct {
|
||||
CRT string
|
||||
Key string
|
||||
}
|
||||
|
||||
Endpoint struct {
|
||||
From string
|
||||
To string
|
||||
BasicAuth string
|
||||
}
|
||||
)
|
||||
|
||||
func NewConfig() (Config, error) {
|
||||
var c Config
|
||||
|
||||
fs := flag.NewFlagSet(os.Args[0], flag.ContinueOnError)
|
||||
fs.StringVar(&c.Cert.CRT, "crt", "", "path to .crt")
|
||||
fs.StringVar(&c.Cert.Key, "key", "", "path to .key")
|
||||
fs.IntVar(&c.Port, "p", 56112, "port to listen on")
|
||||
f := fs.String("f", "/dev/null", `file of {endpoints:{"": {from:"", to:"", basicAuth:""}}}`)
|
||||
if err := fs.Parse(os.Args[1:]); err != nil {
|
||||
return c, err
|
||||
}
|
||||
|
||||
if b, err := os.ReadFile(*f); err != nil {
|
||||
return c, err
|
||||
} else if err := yaml.Unmarshal(b, &c); err != nil {
|
||||
return c, err
|
||||
} else if len(c.Endpoints) == 0 {
|
||||
return c, fmt.Errorf("no endpoints configured")
|
||||
}
|
||||
|
||||
return c, nil
|
||||
}
|
||||
5
go.mod
Normal file
5
go.mod
Normal file
@@ -0,0 +1,5 @@
|
||||
module rproxy4
|
||||
|
||||
go 1.24.2
|
||||
|
||||
require gopkg.in/yaml.v2 v2.4.0
|
||||
4
go.sum
Normal file
4
go.sum
Normal file
@@ -0,0 +1,4 @@
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
||||
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||
90
main.go
Normal file
90
main.go
Normal file
@@ -0,0 +1,90 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"net/http"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func main() {
|
||||
c, err := NewConfig()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
s := &http.Server{
|
||||
Addr: fmt.Sprintf(":%d", c.Port),
|
||||
Handler: c,
|
||||
}
|
||||
foo := s.ListenAndServe
|
||||
if c.Cert.CRT != "" {
|
||||
foo = func() error {
|
||||
return s.ListenAndServeTLS(c.Cert.CRT, c.Cert.Key)
|
||||
}
|
||||
}
|
||||
log.Printf("listening on %v...", s.Addr)
|
||||
if err := foo(); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
func (c Config) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
if r.Method == http.MethodOptions {
|
||||
cors(w)
|
||||
return
|
||||
}
|
||||
|
||||
if r.URL.Scheme == "https" {
|
||||
w.Header().Set("X-Forwarded-Proto", "https")
|
||||
}
|
||||
|
||||
if c.handleAdmin(w, r) {
|
||||
return
|
||||
}
|
||||
|
||||
if !c.basicAuth(w, r) {
|
||||
return
|
||||
}
|
||||
|
||||
http.Error(w, "not yet", http.StatusNotImplemented)
|
||||
}
|
||||
|
||||
func cors(w http.ResponseWriter) {
|
||||
w.Header().Set("Access-Control-Allow-Origin", "*")
|
||||
w.Header().Set("Access-Control-Allow-Headers", "X-Auth-Token, content-type, Content-Type")
|
||||
w.Header().Set("Content-Length", "0")
|
||||
w.Header().Set("Content-Type", "text/plain")
|
||||
w.Header().Set("Access-Control-Allow-Methods", "GET, POST, PUT, OPTIONS, TRACE, PATCH, HEAD, DELETE")
|
||||
w.WriteHeader(http.StatusOK)
|
||||
}
|
||||
|
||||
func (c Config) endpoint(r *http.Request) string {
|
||||
return strings.Split(r.Host, ".")[0]
|
||||
}
|
||||
|
||||
func (c Config) handleAdmin(w http.ResponseWriter, r *http.Request) bool {
|
||||
switch c.endpoint(r) {
|
||||
case "_":
|
||||
panic("not impl: list")
|
||||
case "home":
|
||||
panic("not impl: home")
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (c Config) basicAuth(w http.ResponseWriter, r *http.Request) bool {
|
||||
basicAuth := c.Endpoints[c.endpoint(r)].BasicAuth
|
||||
if noAuth := basicAuth == ""; noAuth {
|
||||
return true
|
||||
}
|
||||
|
||||
u, p, _ := r.BasicAuth()
|
||||
if fmt.Sprintf("%s:%s", u, p) != basicAuth {
|
||||
w.Header().Set("WWW-Authenticate", "Basic")
|
||||
http.Error(w, "unexpected basic auth", http.StatusUnauthorized)
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
6
testdata/test.yaml
vendored
Normal file
6
testdata/test.yaml
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
#port: 51552 # priority over cli
|
||||
endpoints:
|
||||
foo:
|
||||
from: foo.blapointe.com
|
||||
to: http://192.168.0.86:51552
|
||||
basicAuth: u:p
|
||||
Reference in New Issue
Block a user