Skip to content
File

Blob: gateway/internal_proxy.go

go78 lines
1package gateway
2 
3import (
4 "context"
5 "fmt"
6 "net"
7 "net/http"
8 "net/http/httputil"
9 "net/url"
10 
11 "go.miragespace.co/specter/spec/protocol"
12 "go.miragespace.co/specter/spec/rpc"
13 "go.miragespace.co/specter/spec/transport"
14 
15 "go.uber.org/zap"
16)
17 
18const (
19 internalProxyNodeAddress = "x-internal-proxy-node-address"
20 internalProxyForwarded = "x-internal-proxy-forwarded"
21)
22 
23func (g *Gateway) getInternalProxyHandler() func(http.Handler) http.Handler {
24 targetURL := &url.URL{
25 Scheme: "http",
26 Host: g.RootDomains[0],
27 }
28 proxy := &httputil.ReverseProxy{}
29 proxy.Transport = &http.Transport{
30 DisableKeepAlives: true,
31 MaxIdleConnsPerHost: -1,
32 DialContext: func(ctx context.Context, network, addr string) (conn net.Conn, err error) {
33 defer func() {
34 if pr := recover(); pr != nil {
35 err = fmt.Errorf("internalDialer panic: %v", pr)
36 }
37 }()
38 
39 target := rpc.GetNode(ctx)
40 if target == nil {
41 return nil, transport.ErrNoDirect
42 }
43 return g.TunnelServer.DialInternal(ctx, target)
44 },
45 }
46 proxy.Rewrite = func(preq *httputil.ProxyRequest) {
47 preq.SetURL(targetURL)
48 preq.Out.Host = preq.Out.URL.Host
49 preq.SetXForwarded()
50 preq.Out.Header.Set(internalProxyForwarded, "true")
51 preq.Out.Header.Del(internalProxyNodeAddress)
52 }
53 proxy.ErrorHandler = func(w http.ResponseWriter, r *http.Request, err error) {
54 w.WriteHeader(http.StatusBadGateway)
55 fmt.Fprintf(w, "error proxying internal request: %v", err)
56 }
57 return func(h http.Handler) http.Handler {
58 return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
59 var (
60 forwarded = r.Header.Get(internalProxyForwarded) != ""
61 targetAddress = r.Header.Get(internalProxyNodeAddress)
62 )
63 if forwarded || targetAddress == "" {
64 h.ServeHTTP(w, r)
65 return
66 }
67 
68 target := &protocol.Node{
69 Address: targetAddress,
70 }
71 r = r.WithContext(rpc.WithNode(r.Context(), target))
72 
73 g.Logger.Debug("Proxying internal request", zap.Object("target", target))
74 proxy.ServeHTTP(w, r)
75 })
76 }
77}