Last active
June 20, 2022 09:22
-
-
Save fiorix/372801082efb50cb7fc2 to your computer and use it in GitHub Desktop.
proxy that can handle/modify html responses
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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