Skip to content

Instantly share code, notes, and snippets.

@reedobrien
Created May 2, 2015 17:55
Show Gist options
  • Save reedobrien/ec82d2bd3a92104152cb to your computer and use it in GitHub Desktop.
Save reedobrien/ec82d2bd3a92104152cb to your computer and use it in GitHub Desktop.
A basic auth protected proxy server
package main
import (
"encoding/base64"
"flag"
"io"
"log"
"net/http"
"strings"
)
var (
listen = flag.String("listen", "localhost:8080", "listen on address")
logit = flag.Bool("log", false, "enable logging")
)
func main() {
flag.Parse()
proxyHandler := http.HandlerFunc(proxyHandlerFunc)
log.Fatal(http.ListenAndServe(*listen, basicAuth(proxyHandler)))
}
func proxyHandlerFunc(w http.ResponseWriter, r *http.Request) {
// Log it.
if *logit {
log.Println(r.URL)
}
client := &http.Client{}
// Set up the request.
r.RequestURI = ""
r.Host = "avail-fe-dev.s3-website-us-east-1.amazonaws.com"
r.URL.Scheme = "http"
r.URL.Host = r.Host
// Proxy it!
resp, err := client.Do(r)
if err != nil {
log.Fatal(err)
}
// Set up the response
for k, vv := range resp.Header {
for _, v := range vv {
w.Header().Add(k, v)
}
}
io.Copy(w, resp.Body)
resp.Body.Close()
}
// Set up an unauthorized response with auth header
func unauthorized(w http.ResponseWriter) {
w.Header().Add("WWW-Authenticate", "Basic realm=\"AVAIL\"")
http.Error(w, "Unauthorized", http.StatusUnauthorized)
}
// A basic auth HandleFunc to wrap our proxy handler in.
func basicAuth(next http.HandlerFunc) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
if len(r.Header["Authorization"]) == 0 {
unauthorized(w)
return
}
auth := strings.SplitN(r.Header["Authorization"][0], " ", 2)
if len(auth) != 2 || auth[0] != "Basic" {
http.Error(w, "bad syntax", http.StatusBadRequest)
return
}
payload, _ := base64.StdEncoding.DecodeString(auth[1])
pair := strings.SplitN(string(payload), ":", 2)
if len(pair) != 2 || !validate(pair[0], pair[1]) {
unauthorized(w)
return
}
next(w, r)
}
}
func validate(username, password string) bool {
if username == "specialuser" && password == "so seekrity" {
return true
}
return false
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment