Skip to content
Snippets Groups Projects
Commit 877cf2d6 authored by Will McCutchen's avatar Will McCutchen
Browse files

Add /basic-auth/:user/:pass handler

parent af89c09d
No related branches found
No related tags found
No related merge requests found
...@@ -284,3 +284,28 @@ func (h *HTTPBin) DeleteCookies(w http.ResponseWriter, r *http.Request) { ...@@ -284,3 +284,28 @@ func (h *HTTPBin) DeleteCookies(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Location", "/cookies") w.Header().Set("Location", "/cookies")
w.WriteHeader(http.StatusFound) w.WriteHeader(http.StatusFound)
} }
// BasicAuth requires basic authentication
func (h *HTTPBin) BasicAuth(w http.ResponseWriter, r *http.Request) {
parts := strings.Split(r.URL.Path, "/")
if len(parts) != 4 {
http.Error(w, "Not Found", http.StatusNotFound)
return
}
expectedUser := parts[2]
expectedPass := parts[3]
givenUser, givenPass, _ := r.BasicAuth()
status := http.StatusOK
authorized := givenUser == expectedUser && givenPass == expectedPass
if !authorized {
status = http.StatusUnauthorized
}
body, _ := json.Marshal(&authResponse{
Authorized: authorized,
User: givenUser,
})
writeJSON(w, body, status)
}
...@@ -908,3 +908,85 @@ func TestDeleteCookies(t *testing.T) { ...@@ -908,3 +908,85 @@ func TestDeleteCookies(t *testing.T) {
} }
} }
} }
func TestBasicAuth(t *testing.T) {
t.Run("ok", func(t *testing.T) {
r, _ := http.NewRequest("GET", "/basic-auth/user/pass", nil)
r.SetBasicAuth("user", "pass")
w := httptest.NewRecorder()
handler.ServeHTTP(w, r)
assertStatusCode(t, w, http.StatusOK)
assertContentType(t, w, jsonContentType)
resp := &authResponse{}
json.Unmarshal(w.Body.Bytes(), resp)
expectedResp := &authResponse{
Authorized: true,
User: "user",
}
if !reflect.DeepEqual(resp, expectedResp) {
t.Fatalf("expected response %#v, got %#v", expectedResp, resp)
}
})
t.Run("error/no auth", func(t *testing.T) {
r, _ := http.NewRequest("GET", "/basic-auth/user/pass", nil)
w := httptest.NewRecorder()
handler.ServeHTTP(w, r)
assertStatusCode(t, w, http.StatusUnauthorized)
assertContentType(t, w, jsonContentType)
resp := &authResponse{}
json.Unmarshal(w.Body.Bytes(), resp)
expectedResp := &authResponse{
Authorized: false,
User: "",
}
if !reflect.DeepEqual(resp, expectedResp) {
t.Fatalf("expected response %#v, got %#v", expectedResp, resp)
}
})
t.Run("error/bad auth", func(t *testing.T) {
r, _ := http.NewRequest("GET", "/basic-auth/user/pass", nil)
r.SetBasicAuth("bad", "auth")
w := httptest.NewRecorder()
handler.ServeHTTP(w, r)
assertStatusCode(t, w, http.StatusUnauthorized)
assertContentType(t, w, jsonContentType)
resp := &authResponse{}
json.Unmarshal(w.Body.Bytes(), resp)
expectedResp := &authResponse{
Authorized: false,
User: "bad",
}
if !reflect.DeepEqual(resp, expectedResp) {
t.Fatalf("expected response %#v, got %#v", expectedResp, resp)
}
})
var errorTests = []struct {
url string
status int
}{
{"/basic-auth", http.StatusNotFound},
{"/basic-auth/user", http.StatusNotFound},
{"/basic-auth/user/pass/extra", http.StatusNotFound},
}
for _, test := range errorTests {
t.Run("error"+test.url, func(t *testing.T) {
r, _ := http.NewRequest("GET", test.url, nil)
r.SetBasicAuth("foo", "bar")
w := httptest.NewRecorder()
handler.ServeHTTP(w, r)
assertStatusCode(t, w, test.status)
})
}
}
...@@ -41,6 +41,11 @@ type bodyResponse struct { ...@@ -41,6 +41,11 @@ type bodyResponse struct {
type cookiesResponse map[string]string type cookiesResponse map[string]string
type authResponse struct {
Authorized bool `json:"authorized"`
User string `json:"user"`
}
// Options are used to configure HTTPBin // Options are used to configure HTTPBin
type Options struct { type Options struct {
MaxMemory int64 MaxMemory int64
...@@ -79,13 +84,16 @@ func (h *HTTPBin) Handler() http.Handler { ...@@ -79,13 +84,16 @@ func (h *HTTPBin) Handler() http.Handler {
mux.HandleFunc("/cookies/set", h.SetCookies) mux.HandleFunc("/cookies/set", h.SetCookies)
mux.HandleFunc("/cookies/delete", h.DeleteCookies) mux.HandleFunc("/cookies/delete", h.DeleteCookies)
mux.HandleFunc("/basic-auth/", h.BasicAuth)
// Make sure our ServeMux doesn't "helpfully" redirect these invalid // Make sure our ServeMux doesn't "helpfully" redirect these invalid
// endpoints by adding a trailing slash. See the ServeMux docs for more // endpoints by adding a trailing slash. See the ServeMux docs for more
// info: https://golang.org/pkg/net/http/#ServeMux // info: https://golang.org/pkg/net/http/#ServeMux
mux.HandleFunc("/status", http.NotFound) mux.HandleFunc("/absolute-redirect", http.NotFound)
mux.HandleFunc("/basic-auth", http.NotFound)
mux.HandleFunc("/redirect", http.NotFound) mux.HandleFunc("/redirect", http.NotFound)
mux.HandleFunc("/relative-redirect", http.NotFound) mux.HandleFunc("/relative-redirect", http.NotFound)
mux.HandleFunc("/absolute-redirect", http.NotFound) mux.HandleFunc("/status", http.NotFound)
return logger(cors(mux)) return logger(cors(mux))
} }
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment