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

Getting started

parent 0081e767
No related branches found
No related tags found
No related merge requests found
# go-httpbin
A WIP golang port of https://httpbin.org/.
## Testing
```
go test
go test -cover
go test -coverprofile=cover.out && go tool cover -html=cover.out
```
## Running
```
go build && ./go-httpbin
```
main.go 0 → 100644
package main
import (
"encoding/json"
"log"
"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 string `json:"data,omitempty"`
Files map[string][]string `json:"files,omitempty"`
Form map[string][]string `json:"form,omitempty"`
JSON map[string][]string `json:"json,omitempty"`
}
func getOrigin(r *http.Request) string {
origin := r.Header.Get("X-Forwarded-For")
if origin == "" {
origin = r.RemoteAddr
}
return origin
}
func getURL(r *http.Request) string {
scheme := r.Header.Get("X-Forwarded-Proto")
if scheme == "" {
scheme = r.Header.Get("X-Forwarded-Protocol")
}
if scheme == "" && r.Header.Get("X-Forwarded-Ssl") == "on" {
scheme = "https"
}
if scheme == "" {
scheme = "http"
}
host := r.URL.Host
if host == "" {
host = r.Host
}
u := &url.URL{
Scheme: scheme,
Opaque: r.URL.Opaque,
User: r.URL.User,
Host: host,
Path: r.URL.Path,
RawPath: r.URL.RawPath,
ForceQuery: r.URL.ForceQuery,
RawQuery: r.URL.RawQuery,
Fragment: r.URL.Fragment,
}
return u.String()
}
func writeResponse(w http.ResponseWriter, r *http.Request, resp *Resp) {
resp.Origin = getOrigin(r)
resp.URL = getURL(r)
body, err := json.Marshal(resp)
if err != nil {
log.Printf("error marshalling %v as JSON: %s", resp, err)
}
w.Write(body)
}
func logger(h http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
h.ServeHTTP(w, r)
log.Printf("%s %s %s", r.RemoteAddr, r.Method, r.URL)
})
}
func get(w http.ResponseWriter, r *http.Request) {
r.ParseForm()
resp := &Resp{
Args: r.Form,
Headers: r.Header,
}
writeResponse(w, r, resp)
}
func main() {
h := http.NewServeMux()
h.HandleFunc("/get", get)
log.Printf("listening on 9999")
err := http.ListenAndServe(":9999", logger(h))
log.Fatal(err)
}
package main
import (
"encoding/json"
"net/http"
"net/http/httptest"
"testing"
)
func TestGet(t *testing.T) {
r, _ := http.NewRequest("GET", "/get", nil)
r.Host = "localhost"
r.Header.Set("User-Agent", "test")
w := httptest.NewRecorder()
get(w, r)
if w.Code != 200 {
t.Fatalf("expected status code 200, got %d", w.Code)
}
var resp *Resp
err := json.Unmarshal(w.Body.Bytes(), &resp)
if err != nil {
t.Fatalf("failed to unmarshal body %s from JSON: %s", w.Body, err)
}
if resp.Args.Encode() != "" {
t.Fatalf("expected empty args, got %s", resp.Args.Encode())
}
if resp.Origin != "" {
t.Fatalf("expected empty origin, got %#v", resp.Origin)
}
if resp.URL != "http://localhost/get" {
t.Fatalf("unexpected url: %#v", resp.URL)
}
var headerTests = []struct {
key string
expected string
}{
{"Content-Type", ""},
{"User-Agent", "test"},
}
for _, test := range headerTests {
if resp.Headers.Get(test.key) != test.expected {
t.Fatalf("expected %s = %#v, got %#v", test.key, test.expected, resp.Headers.Get(test.key))
}
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment