Skip to content
Snippets Groups Projects
Unverified Commit af81d0c5 authored by Nedyalko Andreev's avatar Nedyalko Andreev
Browse files

Add support for HEAD and fix OPTIONS HTTP method

parent 5f1d7077
No related branches found
No related tags found
No related merge requests found
......@@ -192,6 +192,27 @@ func TestGet(t *testing.T) {
}
}
func TestHEAD(t *testing.T) {
r, _ := http.NewRequest("HEAD", "/", nil)
w := httptest.NewRecorder()
handler.ServeHTTP(w, r)
assertStatusCode(t, w, 200)
assertBodyEquals(t, w, "")
contentLengthStr := w.HeaderMap.Get("Content-Length")
if contentLengthStr == "" {
t.Fatalf("missing Content-Length header in response")
}
contentLength, err := strconv.Atoi(contentLengthStr)
if err != nil {
t.Fatalf("error converting Content-Lengh %v to integer: %s", contentLengthStr, err)
}
if contentLength <= 0 {
t.Fatalf("Content-Lengh %v should be greater than 0", contentLengthStr)
}
}
func TestCORS(t *testing.T) {
t.Run("CORS/no_request_origin", func(t *testing.T) {
r, _ := http.NewRequest("GET", "/get", nil)
......@@ -213,13 +234,15 @@ func TestCORS(t *testing.T) {
w := httptest.NewRecorder()
handler.ServeHTTP(w, r)
assertStatusCode(t, w, 200)
var headerTests = []struct {
key string
expected string
}{
{"Access-Control-Allow-Origin", "*"},
{"Access-Control-Allow-Credentials", "true"},
{"Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, PATCH, OPTIONS"},
{"Access-Control-Allow-Methods", "GET, POST, HEAD, PUT, DELETE, PATCH, OPTIONS"},
{"Access-Control-Max-Age", "3600"},
{"Access-Control-Allow-Headers", ""},
}
......@@ -234,6 +257,8 @@ func TestCORS(t *testing.T) {
w := httptest.NewRecorder()
handler.ServeHTTP(w, r)
assertStatusCode(t, w, 200)
var headerTests = []struct {
key string
expected string
......
......@@ -27,6 +27,16 @@ func getRequestHeaders(r *http.Request) http.Header {
return h
}
// Copies all headers from src to dst
// From https://golang.org/src/net/http/httputil/reverseproxy.go#L109
func copyHeader(dst, src http.Header) {
for k, vv := range src {
for _, v := range vv {
dst.Add(k, v)
}
}
}
func getOrigin(r *http.Request) string {
origin := r.Header.Get("X-Forwarded-For")
if origin == "" {
......
......@@ -175,6 +175,7 @@ func (h *HTTPBin) Handler() http.Handler {
handler = mux
handler = limitRequestSize(h.options.MaxMemory, handler)
handler = logger(handler)
handler = optionsAndHead(handler)
handler = cors(handler)
return handler
}
......
......@@ -4,9 +4,33 @@ import (
"fmt"
"log"
"net/http"
"net/http/httptest"
"time"
)
func optionsAndHead(h http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
switch r.Method {
case "OPTIONS":
w.Header().Set("Access-Control-Allow-Methods", "GET, POST, HEAD, PUT, DELETE, PATCH, OPTIONS")
w.Header().Set("Access-Control-Max-Age", "3600")
if r.Header.Get("Access-Control-Request-Headers") != "" {
w.Header().Set("Access-Control-Allow-Headers", r.Header.Get("Access-Control-Request-Headers"))
}
w.WriteHeader(200)
case "HEAD":
rwRec := httptest.NewRecorder()
r.Method = "GET"
h.ServeHTTP(rwRec, r)
copyHeader(w.Header(), rwRec.Header())
w.WriteHeader(rwRec.Code)
default:
h.ServeHTTP(w, r)
}
})
}
func cors(h http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
origin := r.Header.Get("Origin")
......@@ -17,13 +41,6 @@ func cors(h http.Handler) http.Handler {
respHeader.Set("Access-Control-Allow-Origin", origin)
respHeader.Set("Access-Control-Allow-Credentials", "true")
if r.Method == "OPTIONS" {
respHeader.Set("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, PATCH, OPTIONS")
respHeader.Set("Access-Control-Max-Age", "3600")
if r.Header.Get("Access-Control-Request-Headers") != "" {
respHeader.Set("Access-Control-Allow-Headers", r.Header.Get("Access-Control-Request-Headers"))
}
}
h.ServeHTTP(w, r)
})
}
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment