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

Discreet response types; break apart main.go

parent 664f89cb
No related branches found
No related tags found
No related merge requests found
package main
import (
"encoding/json"
"fmt"
"html/template"
"net/http"
"net/url"
)
// Index must be wrapped by the withTemplates middleware before it can be used
func index(w http.ResponseWriter, r *http.Request, t *template.Template) {
t = t.Lookup("index.html")
if t == nil {
http.Error(w, fmt.Sprintf("error looking up index.html"), http.StatusInternalServerError)
return
}
t.Execute(w, nil)
}
// FormsPost must be wrapped by withTemplates middleware before it can be used
func formsPost(w http.ResponseWriter, r *http.Request, t *template.Template) {
t = t.Lookup("forms-post.html")
if t == nil {
http.Error(w, fmt.Sprintf("error looking up index.html"), http.StatusInternalServerError)
return
}
t.Execute(w, nil)
}
func get(w http.ResponseWriter, r *http.Request) {
args, err := url.ParseQuery(r.URL.RawQuery)
if err != nil {
http.Error(w, fmt.Sprintf("error parsing query params: %s", err), http.StatusBadRequest)
return
}
resp := &getResponse{
Args: args,
Headers: r.Header,
Origin: getOrigin(r),
URL: getURL(r),
}
body, _ := json.Marshal(resp)
writeJSON(w, body, http.StatusOK)
}
func post(w http.ResponseWriter, r *http.Request) {
args, err := url.ParseQuery(r.URL.RawQuery)
if err != nil {
http.Error(w, fmt.Sprintf("error parsing query params: %s", err), http.StatusBadRequest)
return
}
resp := &bodyResponse{
Args: args,
Headers: r.Header,
Origin: getOrigin(r),
URL: getURL(r),
}
err = parseBody(w, r, resp)
if err != nil {
http.Error(w, fmt.Sprintf("error parsing request body: %s", err), http.StatusBadRequest)
}
body, _ := json.Marshal(resp)
writeJSON(w, body, http.StatusOK)
}
func ip(w http.ResponseWriter, r *http.Request) {
body, _ := json.Marshal(&ipResponse{
Origin: getOrigin(r),
})
writeJSON(w, body, http.StatusOK)
}
func userAgent(w http.ResponseWriter, r *http.Request) {
body, _ := json.Marshal(&userAgentResponse{
UserAgent: r.Header.Get("User-Agent"),
})
writeJSON(w, body, http.StatusOK)
}
func headers(w http.ResponseWriter, r *http.Request) {
body, _ := json.Marshal(&headersResponse{
Headers: r.Header,
})
writeJSON(w, body, http.StatusOK)
}
...@@ -42,7 +42,7 @@ func TestGet__Basic(t *testing.T) { ...@@ -42,7 +42,7 @@ func TestGet__Basic(t *testing.T) {
t.Fatalf("expected status code 200, got %d", w.Code) t.Fatalf("expected status code 200, got %d", w.Code)
} }
var resp *Resp var resp *bodyResponse
err := json.Unmarshal(w.Body.Bytes(), &resp) err := json.Unmarshal(w.Body.Bytes(), &resp)
if err != nil { if err != nil {
t.Fatalf("failed to unmarshal body %s from JSON: %s", w.Body, err) t.Fatalf("failed to unmarshal body %s from JSON: %s", w.Body, err)
...@@ -160,7 +160,7 @@ func TestGet__XForwardedProto(t *testing.T) { ...@@ -160,7 +160,7 @@ func TestGet__XForwardedProto(t *testing.T) {
w := httptest.NewRecorder() w := httptest.NewRecorder()
app().ServeHTTP(w, r) app().ServeHTTP(w, r)
var resp *Resp var resp *bodyResponse
err := json.Unmarshal(w.Body.Bytes(), &resp) err := json.Unmarshal(w.Body.Bytes(), &resp)
if err != nil { if err != nil {
t.Fatalf("failed to unmarshal body %s from JSON: %s", w.Body, err) t.Fatalf("failed to unmarshal body %s from JSON: %s", w.Body, err)
...@@ -178,7 +178,7 @@ func TestIP(t *testing.T) { ...@@ -178,7 +178,7 @@ func TestIP(t *testing.T) {
w := httptest.NewRecorder() w := httptest.NewRecorder()
app().ServeHTTP(w, r) app().ServeHTTP(w, r)
var resp *IPResp var resp *ipResponse
err := json.Unmarshal(w.Body.Bytes(), &resp) err := json.Unmarshal(w.Body.Bytes(), &resp)
if err != nil { if err != nil {
t.Fatalf("failed to unmarshal body %s from JSON: %s", w.Body, err) t.Fatalf("failed to unmarshal body %s from JSON: %s", w.Body, err)
...@@ -195,7 +195,7 @@ func TestUserAgent(t *testing.T) { ...@@ -195,7 +195,7 @@ func TestUserAgent(t *testing.T) {
w := httptest.NewRecorder() w := httptest.NewRecorder()
app().ServeHTTP(w, r) app().ServeHTTP(w, r)
var resp *UserAgentResp var resp *userAgentResponse
err := json.Unmarshal(w.Body.Bytes(), &resp) err := json.Unmarshal(w.Body.Bytes(), &resp)
if err != nil { if err != nil {
t.Fatalf("failed to unmarshal body %s from JSON: %s", w.Body, err) t.Fatalf("failed to unmarshal body %s from JSON: %s", w.Body, err)
...@@ -215,7 +215,7 @@ func TestHeaders(t *testing.T) { ...@@ -215,7 +215,7 @@ func TestHeaders(t *testing.T) {
w := httptest.NewRecorder() w := httptest.NewRecorder()
app().ServeHTTP(w, r) app().ServeHTTP(w, r)
var resp *HeadersResp var resp *headersResponse
err := json.Unmarshal(w.Body.Bytes(), &resp) err := json.Unmarshal(w.Body.Bytes(), &resp)
if err != nil { if err != nil {
t.Fatalf("failed to unmarshal body %s from JSON: %s", w.Body, err) t.Fatalf("failed to unmarshal body %s from JSON: %s", w.Body, err)
...@@ -237,7 +237,7 @@ func TestPost__EmptyBody(t *testing.T) { ...@@ -237,7 +237,7 @@ func TestPost__EmptyBody(t *testing.T) {
w := httptest.NewRecorder() w := httptest.NewRecorder()
app().ServeHTTP(w, r) app().ServeHTTP(w, r)
var resp *Resp var resp *bodyResponse
err := json.Unmarshal(w.Body.Bytes(), &resp) err := json.Unmarshal(w.Body.Bytes(), &resp)
if err != nil { if err != nil {
t.Fatalf("failed to unmarshal body %s from JSON: %s", w.Body, err) t.Fatalf("failed to unmarshal body %s from JSON: %s", w.Body, err)
...@@ -262,7 +262,7 @@ func TestPost__FormEncodedBody(t *testing.T) { ...@@ -262,7 +262,7 @@ func TestPost__FormEncodedBody(t *testing.T) {
w := httptest.NewRecorder() w := httptest.NewRecorder()
app().ServeHTTP(w, r) app().ServeHTTP(w, r)
var resp *Resp var resp *bodyResponse
err := json.Unmarshal(w.Body.Bytes(), &resp) err := json.Unmarshal(w.Body.Bytes(), &resp)
if err != nil { if err != nil {
t.Fatalf("failed to unmarshal body %#v from JSON: %s", w.Body.String(), err) t.Fatalf("failed to unmarshal body %#v from JSON: %s", w.Body.String(), err)
...@@ -295,7 +295,7 @@ func TestPost__FormEncodedBodyNoContentType(t *testing.T) { ...@@ -295,7 +295,7 @@ func TestPost__FormEncodedBodyNoContentType(t *testing.T) {
w := httptest.NewRecorder() w := httptest.NewRecorder()
app().ServeHTTP(w, r) app().ServeHTTP(w, r)
var resp *Resp var resp *bodyResponse
err := json.Unmarshal(w.Body.Bytes(), &resp) err := json.Unmarshal(w.Body.Bytes(), &resp)
if err != nil { if err != nil {
t.Fatalf("failed to unmarshal body %s from JSON: %s", w.Body, err) t.Fatalf("failed to unmarshal body %s from JSON: %s", w.Body, err)
...@@ -332,7 +332,7 @@ func TestPost__JSON(t *testing.T) { ...@@ -332,7 +332,7 @@ func TestPost__JSON(t *testing.T) {
w := httptest.NewRecorder() w := httptest.NewRecorder()
app().ServeHTTP(w, r) app().ServeHTTP(w, r)
var resp *Resp var resp *bodyResponse
err := json.Unmarshal(w.Body.Bytes(), &resp) err := json.Unmarshal(w.Body.Bytes(), &resp)
if err != nil { if err != nil {
t.Fatalf("failed to unmarshal body %s from JSON: %s", w.Body, err) t.Fatalf("failed to unmarshal body %s from JSON: %s", w.Body, err)
......
...@@ -47,14 +47,8 @@ func getURL(r *http.Request) string { ...@@ -47,14 +47,8 @@ func getURL(r *http.Request) string {
return u.String() return u.String()
} }
func writeResponse(w http.ResponseWriter, r *http.Request, resp *Resp) { func writeJSON(w http.ResponseWriter, body []byte, status int) {
resp.Origin = getOrigin(r) w.WriteHeader(status)
resp.URL = getURL(r)
body, _ := json.Marshal(resp)
writeJSON(w, body)
}
func writeJSON(w http.ResponseWriter, body []byte) {
w.Header().Set("Content-Type", "application/json; encoding=utf-8") w.Header().Set("Content-Type", "application/json; encoding=utf-8")
w.Write(body) w.Write(body)
} }
...@@ -62,7 +56,7 @@ func writeJSON(w http.ResponseWriter, body []byte) { ...@@ -62,7 +56,7 @@ func writeJSON(w http.ResponseWriter, body []byte) {
// parseBody handles parsing a request body into our standard API response, // parseBody handles parsing a request body into our standard API response,
// taking care to only consume the request body once based on the Content-Type // taking care to only consume the request body once based on the Content-Type
// of the request. The given Resp will be updated. // of the request. The given Resp will be updated.
func parseBody(w http.ResponseWriter, r *http.Request, resp *Resp) error { func parseBody(w http.ResponseWriter, r *http.Request, resp *bodyResponse) error {
if r.Body == nil { if r.Body == nil {
return nil return nil
} }
......
package main package main
import ( import (
"encoding/json"
"fmt"
"html/template"
"log" "log"
"net/http" "net/http"
"net/url"
) )
// Resp is the standard JSON response from httpbin
type Resp struct {
Args url.Values `json:"args"`
Headers http.Header `json:"headers"`
Origin string `json:"origin"`
URL string `json:"url"`
Data []byte `json:"data,omitempty"`
Files map[string][]string `json:"files,omitempty"`
Form map[string][]string `json:"form,omitempty"`
JSON interface{} `json:"json,omitempty"`
}
// IPResp is the response for the /ip endpoint
type IPResp struct {
Origin string `json:"origin"`
}
// HeadersResp is the response for the /headers endpoint
type HeadersResp struct {
Headers http.Header `json:"headers"`
}
// UserAgentResp is the response for the /user-agent endpoint
type UserAgentResp struct {
UserAgent string `json:"user-agent"`
}
// Max size of a request body we'll handle // Max size of a request body we'll handle
const maxMemory = 1024*1024*5 + 1 const maxMemory = 1024*1024*5 + 1
// Index must be wrapped by the withTemplates middleware before it can be used
func index(w http.ResponseWriter, r *http.Request, t *template.Template) {
t = t.Lookup("index.html")
if t == nil {
http.Error(w, fmt.Sprintf("error looking up index.html"), http.StatusInternalServerError)
return
}
t.Execute(w, nil)
}
// FormsPost must be wrapped by withTemplates middleware before it can be used
func formsPost(w http.ResponseWriter, r *http.Request, t *template.Template) {
t = t.Lookup("forms-post.html")
if t == nil {
http.Error(w, fmt.Sprintf("error looking up index.html"), http.StatusInternalServerError)
return
}
t.Execute(w, nil)
}
func get(w http.ResponseWriter, r *http.Request) {
args, err := url.ParseQuery(r.URL.RawQuery)
if err != nil {
http.Error(w, fmt.Sprintf("error parsing query params: %s", err), http.StatusBadRequest)
return
}
resp := &Resp{
Args: args,
Headers: r.Header,
}
writeResponse(w, r, resp)
}
func post(w http.ResponseWriter, r *http.Request) {
args, err := url.ParseQuery(r.URL.RawQuery)
if err != nil {
http.Error(w, fmt.Sprintf("error parsing query params: %s", err), http.StatusBadRequest)
return
}
resp := &Resp{
Args: args,
Headers: r.Header,
}
err = parseBody(w, r, resp)
if err != nil {
http.Error(w, fmt.Sprintf("error parsing request body: %s", err), http.StatusBadRequest)
}
writeResponse(w, r, resp)
}
func ip(w http.ResponseWriter, r *http.Request) {
body, _ := json.Marshal(&IPResp{
Origin: getOrigin(r),
})
writeJSON(w, body)
}
func userAgent(w http.ResponseWriter, r *http.Request) {
body, _ := json.Marshal(&UserAgentResp{
UserAgent: r.Header.Get("User-Agent"),
})
writeJSON(w, body)
}
func headers(w http.ResponseWriter, r *http.Request) {
body, _ := json.Marshal(&HeadersResp{
Headers: r.Header,
})
writeJSON(w, body)
}
func app() http.Handler { func app() http.Handler {
h := http.NewServeMux() h := http.NewServeMux()
templateWrapper := withTemplates("templates/*.html") templateWrapper := withTemplates("templates/*.html")
......
types.go 0 → 100644
package main
import (
"net/http"
"net/url"
)
type headersResponse struct {
Headers http.Header `json:"headers"`
}
type ipResponse struct {
Origin string `json:"origin"`
}
type userAgentResponse struct {
UserAgent string `json:"user-agent"`
}
type getResponse struct {
Args url.Values `json:"args"`
Headers http.Header `json:"headers"`
Origin string `json:"origin"`
URL string `json:"url"`
}
// A generic response for any incoming request that might contain a body
type bodyResponse struct {
Args url.Values `json:"args"`
Headers http.Header `json:"headers"`
Origin string `json:"origin"`
URL string `json:"url"`
Data []byte `json:"data"`
Files map[string][]string `json:"files"`
Form map[string][]string `json:"form"`
JSON interface{} `json:"json"`
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment