Skip to content
Snippets Groups Projects
Unverified Commit 8d00addc authored by Will McCutchen's avatar Will McCutchen Committed by GitHub
Browse files

Extract option funcs and response types into separate files for clarity (#102)

parent 688c5627
No related branches found
No related tags found
No related merge requests found
File moved
...@@ -2,7 +2,6 @@ package httpbin ...@@ -2,7 +2,6 @@ package httpbin
import ( import (
"net/http" "net/http"
"net/url"
"time" "time"
) )
...@@ -13,77 +12,19 @@ const ( ...@@ -13,77 +12,19 @@ const (
DefaultHostname = "go-httpbin" DefaultHostname = "go-httpbin"
) )
const ( // DefaultParams defines default parameter values
jsonContentType = "application/json; encoding=utf-8" type DefaultParams struct {
htmlContentType = "text/html; charset=utf-8" DripDuration time.Duration
) DripDelay time.Duration
DripNumBytes int64
type headersResponse struct {
Headers http.Header `json:"headers"`
}
type ipResponse struct {
Origin string `json:"origin"`
}
type userAgentResponse struct {
UserAgent string `json:"user-agent"`
}
// A generic response for any incoming request that should not contain a body
// (GET, HEAD, OPTIONS, etc).
type noBodyResponse struct {
Args url.Values `json:"args"`
Headers http.Header `json:"headers"`
Origin string `json:"origin"`
URL string `json:"url"`
Deflated bool `json:"deflated,omitempty"`
Gzipped bool `json:"gzipped,omitempty"`
}
// A generic response for any incoming request that might contain a body (POST,
// PUT, PATCH, etc).
type bodyResponse struct {
Args url.Values `json:"args"`
Headers http.Header `json:"headers"`
Origin string `json:"origin"`
URL string `json:"url"`
Data string `json:"data"`
Files map[string][]string `json:"files"`
Form map[string][]string `json:"form"`
JSON interface{} `json:"json"`
}
type cookiesResponse map[string]string
type authResponse struct {
Authorized bool `json:"authorized"`
User string `json:"user"`
}
// An actual stream response body will be made up of one or more of these
// structs, encoded as JSON and separated by newlines
type streamResponse struct {
ID int `json:"id"`
Args url.Values `json:"args"`
Headers http.Header `json:"headers"`
Origin string `json:"origin"`
URL string `json:"url"`
}
type uuidResponse struct {
UUID string `json:"uuid"`
}
type bearerResponse struct {
Authenticated bool `json:"authenticated"`
Token string `json:"token"`
} }
type hostnameResponse struct { // DefaultDefaultParams defines the DefaultParams that are used by default. In
Hostname string `json:"hostname"` // general, these should match the original httpbin.org's defaults.
var DefaultDefaultParams = DefaultParams{
DripDuration: 2 * time.Second,
DripDelay: 2 * time.Second,
DripNumBytes: 10,
} }
// HTTPBin contains the business logic // HTTPBin contains the business logic
...@@ -111,21 +52,29 @@ type HTTPBin struct { ...@@ -111,21 +52,29 @@ type HTTPBin struct {
handler http.Handler handler http.Handler
} }
// DefaultParams defines default parameter values // New creates a new HTTPBin instance
type DefaultParams struct { func New(opts ...OptionFunc) *HTTPBin {
DripDuration time.Duration h := &HTTPBin{
DripDelay time.Duration MaxBodySize: DefaultMaxBodySize,
DripNumBytes int64 MaxDuration: DefaultMaxDuration,
DefaultParams: DefaultDefaultParams,
hostname: DefaultHostname,
}
for _, opt := range opts {
opt(h)
}
h.handler = h.Handler()
return h
} }
// DefaultDefaultParams defines the DefaultParams that are used by default. In // ServeHTTP implememnts the http.Handler interface.
// general, these should match the original httpbin.org's defaults. func (h *HTTPBin) ServeHTTP(w http.ResponseWriter, r *http.Request) {
var DefaultDefaultParams = DefaultParams{ h.handler.ServeHTTP(w, r)
DripDuration: 2 * time.Second,
DripDelay: 2 * time.Second,
DripNumBytes: 10,
} }
// Assert that HTTPBin implements http.Handler interface
var _ http.Handler = &HTTPBin{}
// Handler returns an http.Handler that exposes all HTTPBin endpoints // Handler returns an http.Handler that exposes all HTTPBin endpoints
func (h *HTTPBin) Handler() http.Handler { func (h *HTTPBin) Handler() http.Handler {
mux := http.NewServeMux() mux := http.NewServeMux()
...@@ -227,77 +176,3 @@ func (h *HTTPBin) Handler() http.Handler { ...@@ -227,77 +176,3 @@ func (h *HTTPBin) Handler() http.Handler {
return handler return handler
} }
// New creates a new HTTPBin instance
func New(opts ...OptionFunc) *HTTPBin {
h := &HTTPBin{
MaxBodySize: DefaultMaxBodySize,
MaxDuration: DefaultMaxDuration,
DefaultParams: DefaultDefaultParams,
hostname: DefaultHostname,
}
for _, opt := range opts {
opt(h)
}
h.handler = h.Handler()
return h
}
// ServeHTTP implememnts the http.Handler interface.
func (h *HTTPBin) ServeHTTP(w http.ResponseWriter, r *http.Request) {
h.handler.ServeHTTP(w, r)
}
// Assert that HTTPBin implements http.Handler interface
var _ http.Handler = &HTTPBin{}
// OptionFunc uses the "functional options" pattern to customize an HTTPBin
// instance
type OptionFunc func(*HTTPBin)
// WithDefaultParams sets the default params handlers will use
func WithDefaultParams(defaultParams DefaultParams) OptionFunc {
return func(h *HTTPBin) {
h.DefaultParams = defaultParams
}
}
// WithMaxBodySize sets the maximum amount of memory
func WithMaxBodySize(m int64) OptionFunc {
return func(h *HTTPBin) {
h.MaxBodySize = m
}
}
// WithMaxDuration sets the maximum amount of time httpbin may take to respond
func WithMaxDuration(d time.Duration) OptionFunc {
return func(h *HTTPBin) {
h.MaxDuration = d
}
}
// WithHostname sets the hostname to return via the /hostname endpoint.
func WithHostname(s string) OptionFunc {
return func(h *HTTPBin) {
h.hostname = s
}
}
// WithObserver sets the request observer callback
func WithObserver(o Observer) OptionFunc {
return func(h *HTTPBin) {
h.Observer = o
}
}
// WithAllowedRedirectDomains limits the domains to which the /redirect-to
// endpoint will redirect traffic.
func WithAllowedRedirectDomains(hosts []string) OptionFunc {
return func(h *HTTPBin) {
hostSet := make(map[string]struct{}, len(hosts))
for _, host := range hosts {
hostSet[host] = struct{}{}
}
h.AllowedRedirectDomains = hostSet
}
}
package httpbin
import "time"
// OptionFunc uses the "functional options" pattern to customize an HTTPBin
// instance
type OptionFunc func(*HTTPBin)
// WithDefaultParams sets the default params handlers will use
func WithDefaultParams(defaultParams DefaultParams) OptionFunc {
return func(h *HTTPBin) {
h.DefaultParams = defaultParams
}
}
// WithMaxBodySize sets the maximum amount of memory
func WithMaxBodySize(m int64) OptionFunc {
return func(h *HTTPBin) {
h.MaxBodySize = m
}
}
// WithMaxDuration sets the maximum amount of time httpbin may take to respond
func WithMaxDuration(d time.Duration) OptionFunc {
return func(h *HTTPBin) {
h.MaxDuration = d
}
}
// WithHostname sets the hostname to return via the /hostname endpoint.
func WithHostname(s string) OptionFunc {
return func(h *HTTPBin) {
h.hostname = s
}
}
// WithObserver sets the request observer callback
func WithObserver(o Observer) OptionFunc {
return func(h *HTTPBin) {
h.Observer = o
}
}
// WithAllowedRedirectDomains limits the domains to which the /redirect-to
// endpoint will redirect traffic.
func WithAllowedRedirectDomains(hosts []string) OptionFunc {
return func(h *HTTPBin) {
hostSet := make(map[string]struct{}, len(hosts))
for _, host := range hosts {
hostSet[host] = struct{}{}
}
h.AllowedRedirectDomains = hostSet
}
}
package httpbin
import (
"net/http"
"net/url"
)
const (
jsonContentType = "application/json; encoding=utf-8"
htmlContentType = "text/html; charset=utf-8"
)
type headersResponse struct {
Headers http.Header `json:"headers"`
}
type ipResponse struct {
Origin string `json:"origin"`
}
type userAgentResponse struct {
UserAgent string `json:"user-agent"`
}
// A generic response for any incoming request that should not contain a body
// (GET, HEAD, OPTIONS, etc).
type noBodyResponse struct {
Args url.Values `json:"args"`
Headers http.Header `json:"headers"`
Origin string `json:"origin"`
URL string `json:"url"`
Deflated bool `json:"deflated,omitempty"`
Gzipped bool `json:"gzipped,omitempty"`
}
// A generic response for any incoming request that might contain a body (POST,
// PUT, PATCH, etc).
type bodyResponse struct {
Args url.Values `json:"args"`
Headers http.Header `json:"headers"`
Origin string `json:"origin"`
URL string `json:"url"`
Data string `json:"data"`
Files map[string][]string `json:"files"`
Form map[string][]string `json:"form"`
JSON interface{} `json:"json"`
}
type cookiesResponse map[string]string
type authResponse struct {
Authorized bool `json:"authorized"`
User string `json:"user"`
}
// An actual stream response body will be made up of one or more of these
// structs, encoded as JSON and separated by newlines
type streamResponse struct {
ID int `json:"id"`
Args url.Values `json:"args"`
Headers http.Header `json:"headers"`
Origin string `json:"origin"`
URL string `json:"url"`
}
type uuidResponse struct {
UUID string `json:"uuid"`
}
type bearerResponse struct {
Authenticated bool `json:"authenticated"`
Token string `json:"token"`
}
type hostnameResponse struct {
Hostname string `json:"hostname"`
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment