From 6a63958836f464b6bb08773b14a8ad2b628b0761 Mon Sep 17 00:00:00 2001 From: James Harris Date: Tue, 31 Oct 2023 06:29:16 +1000 Subject: [PATCH] Add support for arbitrary headers. --- CHANGELOG.md | 4 ++++ README.md | 36 +++++++++++++++++++++++++++++------- cmd/echo-server/main.go | 15 +++++++++++++-- go.mod | 4 +++- go.sum | 37 ------------------------------------- 5 files changed, 49 insertions(+), 47 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index db5b135..1bc6c8f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,10 @@ The format is based on [Keep a Changelog], and this project adheres to [keep a changelog]: https://keepachangelog.com/en/1.0.0/ [semantic versioning]: https://semver.org/spec/v2.0.0.html +## [0.3.6] - 2023-10-31 + +- Add support for sending arbitrary headers in all responses + ## [0.3.5] - 2023-03-07 - Update dependencies to patch some security vulnerabilites diff --git a/README.md b/README.md index 3b875ce..766c9e2 100644 --- a/README.md +++ b/README.md @@ -15,13 +15,35 @@ information about HTTP request headers and bodies back to the client. ## Configuration -- The `PORT` environment variable sets the server port, which defaults to `8080`. -- Set the `LOG_HTTP_BODY` environment variable to dump request bodies to `STDOUT`. -- Set the `LOG_HTTP_HEADERS` environment variable to dump request headers to `STDOUT`. -- Set the `SEND_SERVER_HOSTNAME` environment variable to `false` to prevent the - server from responding with its hostname before echoing the request. The - client may send the `X-Send-Server-Hostname` request header to `true` or - `false` to override this server-wide setting on a per-request basis. +### Port + +The `PORT` environment variable sets the server port, which defaults to `8080`. + +### Logging + +Set the `LOG_HTTP_HEADERS` environment variable to print request headers to +`STDOUT`. Additionally, set the `LOG_HTTP_BODY` environment variable to print +entire request bodies. + +### Server Hostname + +Set the `SEND_SERVER_HOSTNAME` environment variable to `false` to prevent the +server from responding with its hostname before echoing the request. The client +may send the `X-Send-Server-Hostname` request header to `true` or `false` to +override this server-wide setting on a per-request basis. + +### Arbitrary Headers + +Set the `SEND_HEADER_` variable to send arbitrary additional +headers in the response. Underscores in the variable name are converted to +hyphens in the header. For example, the following environment variables can be +used to disable CORS: + +```bash +SEND_HEADER_ACCESS_CONTROL_ALLOW_ORIGIN="*" +SEND_HEADER_ACCESS_CONTROL_ALLOW_METHODS="*" +SEND_HEADER_ACCESS_CONTROL_ALLOW_HEADERS="*" +``` ## Running the server diff --git a/cmd/echo-server/main.go b/cmd/echo-server/main.go index 7d73819..91f768e 100644 --- a/cmd/echo-server/main.go +++ b/cmd/echo-server/main.go @@ -5,7 +5,6 @@ import ( "encoding/hex" "fmt" "io" - "io/ioutil" "net/http" "os" "sort" @@ -71,7 +70,7 @@ func handler(wr http.ResponseWriter, req *http.Request) { // Replace original body with buffered version so it's still sent to the // browser. req.Body.Close() - req.Body = ioutil.NopCloser( + req.Body = io.NopCloser( bytes.NewReader(buf.Bytes()), ) } @@ -86,6 +85,18 @@ func handler(wr http.ResponseWriter, req *http.Request) { "false", ) + for _, line := range os.Environ() { + parts := strings.SplitN(line, "=", 2) + key, value := parts[0], parts[1] + + if name, ok := strings.CutPrefix(key, `SEND_HEADER_`); ok { + wr.Header().Set( + strings.ReplaceAll(name, "_", "-"), + value, + ) + } + } + if websocket.IsWebSocketUpgrade(req) { serveWebSocket(wr, req, sendServerHostname) } else if req.URL.Path == "/.ws" { diff --git a/go.mod b/go.mod index c30ff2f..0d235f8 100644 --- a/go.mod +++ b/go.mod @@ -1,8 +1,10 @@ module github.com/jmalloc/echo-server -go 1.16 +go 1.21 require ( github.com/gorilla/websocket v1.4.2 golang.org/x/net v0.17.0 ) + +require golang.org/x/text v0.13.0 // indirect diff --git a/go.sum b/go.sum index 21326da..26d4e2f 100644 --- a/go.sum +++ b/go.sum @@ -1,43 +1,6 @@ github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= -golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4= -golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= -golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= -golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= -golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= -golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U= -golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= -golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= -golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=