Skip to content

Commit e94e1db

Browse files
committed
Add a helper command to inspect PROXY connections
The server can be run as follows: cd cmd/http-echo go run main.go Then in a separate shell: curl http://127.0.0.1/proxy-protocol/used --haproxy-protocol false curl http://127.0.0.1/proxy-protocol/used --haproxy-protocol true This tool could live outside this repository and may one day just do that, once it has more fetures and could replace the nginx hello server used in other places.
1 parent 0a82dba commit e94e1db

File tree

3 files changed

+80
-0
lines changed

3 files changed

+80
-0
lines changed

cmd/http-echo/go.mod

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
module github.com/cloudscale-ch/cloudscale-cloud-controller-manager/cmd/http-echo
2+
3+
go 1.23.0
4+
5+
require github.com/pires/go-proxyproto v0.7.0

cmd/http-echo/go.sum

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
github.com/pires/go-proxyproto v0.7.0 h1:IukmRewDQFWC7kfnb66CSomk2q/seBuilHBYFwyq0Hs=
2+
github.com/pires/go-proxyproto v0.7.0/go.mod h1:Vz/1JPY/OACxWGQNIRY2BeyDmpoaWmEP40O9LbuiFR4=

cmd/http-echo/main.go

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
// A http echo server to get information about connections made to it.
2+
package main
3+
4+
import (
5+
"context"
6+
"flag"
7+
"fmt"
8+
"net"
9+
"net/http"
10+
"time"
11+
12+
proxyproto "github.com/pires/go-proxyproto"
13+
)
14+
15+
func main() {
16+
host := flag.String("host", "127.0.0.1", "Host to connect to")
17+
port := flag.Int("port", 8080, "Port to connect to")
18+
19+
flag.Parse()
20+
21+
serve(*host, *port)
22+
}
23+
24+
// log http requests in basic fashion
25+
func log(h http.Handler) http.Handler {
26+
return http.HandlerFunc(
27+
func(w http.ResponseWriter, r *http.Request) {
28+
h.ServeHTTP(w, r)
29+
fmt.Printf("%s %s (%s)\n", r.Method, r.RequestURI, r.RemoteAddr)
30+
})
31+
}
32+
33+
// serve HTTP API on the given host and port
34+
func serve(host string, port int) {
35+
router := http.NewServeMux()
36+
37+
// Returns 'true' if the PROXY protocol was used for the given connection
38+
router.HandleFunc("GET /proxy-protocol/used",
39+
func(w http.ResponseWriter, r *http.Request) {
40+
fmt.Fprintln(w, r.Context().Value("HasProxyHeader"))
41+
})
42+
43+
addr := fmt.Sprintf("%s:%d", host, port)
44+
45+
server := http.Server{
46+
Addr: addr,
47+
Handler: log(router),
48+
ConnContext: func(ctx context.Context, c net.Conn) context.Context {
49+
hasProxyHeader := false
50+
51+
if c, ok := c.(*proxyproto.Conn); ok {
52+
hasProxyHeader = c.ProxyHeader() != nil
53+
}
54+
55+
return context.WithValue(ctx, "HasProxyHeader", hasProxyHeader)
56+
},
57+
}
58+
59+
listener, err := net.Listen("tcp", server.Addr)
60+
if err != nil {
61+
panic(err)
62+
}
63+
64+
fmt.Printf("Listening on %s\n", addr)
65+
66+
proxyListener := &proxyproto.Listener{
67+
Listener: listener,
68+
ReadHeaderTimeout: 10 * time.Second,
69+
}
70+
defer proxyListener.Close()
71+
72+
server.Serve(proxyListener)
73+
}

0 commit comments

Comments
 (0)