Skip to content

Instantly share code, notes, and snippets.

@pigscanflyyyy
Forked from fiorix/proxy.go
Created January 3, 2021 10:48
Show Gist options
  • Save pigscanflyyyy/36251ef6bbc98e277f685b44adffe9cc to your computer and use it in GitHub Desktop.
Save pigscanflyyyy/36251ef6bbc98e277f685b44adffe9cc to your computer and use it in GitHub Desktop.
proxy that can handle/modify html responses
package main
import (
"io"
"net/http"
"strings"
)
func main() {
p := &proxy{}
http.Handle("/proxy", p.Handler())
http.ListenAndServe(":8080", nil)
}
// proxy provides an http handler for proxying pages.
type proxy struct{}
// Handler is an http handler for net/http.
func (p *proxy) Handler() http.Handler {
f := func(w http.ResponseWriter, r *http.Request) {
if r.Method != "GET" {
http.Error(w, http.StatusText(http.StatusMethodNotAllowed), http.StatusMethodNotAllowed)
return
}
url := r.FormValue("url")
if url == "" {
http.Error(w, "Missing 'url' param", http.StatusBadRequest)
return
}
p.do(w, url)
}
return http.HandlerFunc(f)
}
// Hop-by-hop headers. These are removed when sent to the backend.
// http://www.w3.org/Protocols/rfc2616/rfc2616-sec13.html
var hopHeaders = []string{
"Connection",
"Keep-Alive",
"Proxy-Authenticate",
"Proxy-Authorization",
"Te", // canonicalized version of "TE"
"Trailers",
"Transfer-Encoding",
"Upgrade",
}
// do makes the upstream request and proxy the response back to client w.
func (p *proxy) do(w http.ResponseWriter, url string) {
resp, err := http.Get(url)
if err != nil {
http.Error(w, err.Error(), http.StatusServiceUnavailable)
return
}
defer resp.Body.Close()
// remove certain headers from the response
for _, h := range hopHeaders {
resp.Header.Del(h)
}
// copy headers
for k, vv := range resp.Header {
for _, v := range vv {
w.Header().Set(k, v)
}
}
// direct proxy non http 200 text/html
ok := strings.HasPrefix(resp.Header.Get("Content-Type"), "text/html")
if !ok || resp.StatusCode != http.StatusOK {
w.WriteHeader(resp.StatusCode)
io.Copy(w, resp.Body)
return
}
p.handleBody(w, resp.Body)
}
// handleBody handles the response body and writes to client w.
func (p *proxy) handleBody(w http.ResponseWriter, body io.Reader) {
io.Copy(w, body)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment