Updated Dependencies

This commit is contained in:
claudemiro
2015-01-16 22:35:41 -03:00
parent f6e1993eb6
commit a4e08d1e85
7 changed files with 0 additions and 811 deletions
-4
View File
@@ -14,10 +14,6 @@
"ImportPath": "github.com/gorilla/context",
"Rev": "215affda49addc4c8ef7e2534915df2c8c35c6cd"
},
{
"ImportPath": "github.com/gorilla/handlers",
"Rev": "0e84b7d810c16aed432217e330206be156bafae0"
},
{
"ImportPath": "github.com/gorilla/mux",
"Rev": "e444e69cbd2e2e3e0749a2f3c717cec491552bbf"
-8
View File
@@ -1,8 +0,0 @@
language: go
go:
- 1.0
- 1.1
- 1.2
- 1.3
- tip
-6
View File
@@ -1,6 +0,0 @@
gorilla/handlers
================
[![Build Status](https://travis-ci.org/gorilla/handlers.png?branch=master)](https://travis-ci.org/gorilla/handlers)
*Warning:* This package is a work in progress and the APIs are subject to change.
Consider this a v0 project.
-67
View File
@@ -1,67 +0,0 @@
// Copyright 2013 The Gorilla Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package handlers
import (
"compress/flate"
"compress/gzip"
"io"
"net/http"
"strings"
)
type compressResponseWriter struct {
io.Writer
http.ResponseWriter
}
func (w *compressResponseWriter) Header() http.Header {
return w.ResponseWriter.Header()
}
func (w *compressResponseWriter) Write(b []byte) (int, error) {
h := w.ResponseWriter.Header()
if h.Get("Content-Type") == "" {
h.Set("Content-Type", http.DetectContentType(b))
}
return w.Writer.Write(b)
}
func CompressHandler(h http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
L:
for _, enc := range strings.Split(r.Header.Get("Accept-Encoding"), ",") {
switch strings.TrimSpace(enc) {
case "gzip":
w.Header().Set("Content-Encoding", "gzip")
w.Header().Add("Vary", "Accept-Encoding")
gw := gzip.NewWriter(w)
defer gw.Close()
w = &compressResponseWriter{
Writer: gw,
ResponseWriter: w,
}
break L
case "deflate":
w.Header().Set("Content-Encoding", "deflate")
w.Header().Add("Vary", "Accept-Encoding")
fw, _ := flate.NewWriter(w, flate.DefaultCompression)
defer fw.Close()
w = &compressResponseWriter{
Writer: fw,
ResponseWriter: w,
}
break L
}
}
h.ServeHTTP(w, r)
})
}
-65
View File
@@ -1,65 +0,0 @@
// Copyright 2013 The Gorilla Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package handlers
import (
"io"
"net/http"
"net/http/httptest"
"testing"
)
func compressedRequest(w *httptest.ResponseRecorder, compression string) {
CompressHandler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
for i := 0; i < 1024; i++ {
io.WriteString(w, "Gorilla!\n")
}
})).ServeHTTP(w, &http.Request{
Method: "GET",
Header: http.Header{
"Accept-Encoding": []string{compression},
},
})
}
func TestCompressHandlerGzip(t *testing.T) {
w := httptest.NewRecorder()
compressedRequest(w, "gzip")
if w.HeaderMap.Get("Content-Encoding") != "gzip" {
t.Fatalf("wrong content encoding, got %d want %d", w.HeaderMap.Get("Content-Encoding"), "gzip")
}
if w.HeaderMap.Get("Content-Type") != "text/plain; charset=utf-8" {
t.Fatalf("wrong content type, got %s want %s", w.HeaderMap.Get("Content-Type"), "text/plain; charset=utf-8")
}
if w.Body.Len() != 72 {
t.Fatalf("wrong len, got %d want %d", w.Body.Len(), 72)
}
}
func TestCompressHandlerDeflate(t *testing.T) {
w := httptest.NewRecorder()
compressedRequest(w, "deflate")
if w.HeaderMap.Get("Content-Encoding") != "deflate" {
t.Fatalf("wrong content encoding, got %d want %d", w.HeaderMap.Get("Content-Encoding"), "deflate")
}
if w.HeaderMap.Get("Content-Type") != "text/plain; charset=utf-8" {
t.Fatalf("wrong content type, got %s want %s", w.HeaderMap.Get("Content-Type"), "text/plain; charset=utf-8")
}
if w.Body.Len() != 54 {
t.Fatalf("wrong len, got %d want %d", w.Body.Len(), 54)
}
}
func TestCompressHandlerGzipDeflate(t *testing.T) {
w := httptest.NewRecorder()
compressedRequest(w, "gzip, deflate ")
if w.HeaderMap.Get("Content-Encoding") != "gzip" {
t.Fatalf("wrong content encoding, got %s want %s", w.HeaderMap.Get("Content-Encoding"), "gzip")
}
if w.HeaderMap.Get("Content-Type") != "text/plain; charset=utf-8" {
t.Fatalf("wrong content type, got %s want %s", w.HeaderMap.Get("Content-Type"), "text/plain; charset=utf-8")
}
}
-356
View File
@@ -1,356 +0,0 @@
// Copyright 2013 The Gorilla Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
/*
Package handlers is a collection of handlers for use with Go's net/http package.
*/
package handlers
import (
"bufio"
"fmt"
"io"
"net"
"net/http"
"net/url"
"sort"
"strconv"
"strings"
"time"
"unicode/utf8"
)
// MethodHandler is an http.Handler that dispatches to a handler whose key in the MethodHandler's
// map matches the name of the HTTP request's method, eg: GET
//
// If the request's method is OPTIONS and OPTIONS is not a key in the map then the handler
// responds with a status of 200 and sets the Allow header to a comma-separated list of
// available methods.
//
// If the request's method doesn't match any of its keys the handler responds with
// a status of 406, Method not allowed and sets the Allow header to a comma-separated list
// of available methods.
type MethodHandler map[string]http.Handler
func (h MethodHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
if handler, ok := h[req.Method]; ok {
handler.ServeHTTP(w, req)
} else {
allow := []string{}
for k := range h {
allow = append(allow, k)
}
sort.Strings(allow)
w.Header().Set("Allow", strings.Join(allow, ", "))
if req.Method == "OPTIONS" {
w.WriteHeader(http.StatusOK)
} else {
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
}
}
}
// loggingHandler is the http.Handler implementation for LoggingHandlerTo and its friends
type loggingHandler struct {
writer io.Writer
handler http.Handler
}
// combinedLoggingHandler is the http.Handler implementation for LoggingHandlerTo and its friends
type combinedLoggingHandler struct {
writer io.Writer
handler http.Handler
}
func (h loggingHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
t := time.Now()
var logger loggingResponseWriter
if _, ok := w.(http.Hijacker); ok {
logger = &hijackLogger{responseLogger: responseLogger{w: w}}
} else {
logger = &responseLogger{w: w}
}
url := *req.URL
h.handler.ServeHTTP(logger, req)
writeLog(h.writer, req, url, t, logger.Status(), logger.Size())
}
func (h combinedLoggingHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
t := time.Now()
var logger loggingResponseWriter
if _, ok := w.(http.Hijacker); ok {
logger = &hijackLogger{responseLogger: responseLogger{w: w}}
} else {
logger = &responseLogger{w: w}
}
url := *req.URL
h.handler.ServeHTTP(logger, req)
writeCombinedLog(h.writer, req, url, t, logger.Status(), logger.Size())
}
type loggingResponseWriter interface {
http.ResponseWriter
Status() int
Size() int
}
// responseLogger is wrapper of http.ResponseWriter that keeps track of its HTTP status
// code and body size
type responseLogger struct {
w http.ResponseWriter
status int
size int
}
func (l *responseLogger) Header() http.Header {
return l.w.Header()
}
func (l *responseLogger) Write(b []byte) (int, error) {
if l.status == 0 {
// The status will be StatusOK if WriteHeader has not been called yet
l.status = http.StatusOK
}
size, err := l.w.Write(b)
l.size += size
return size, err
}
func (l *responseLogger) WriteHeader(s int) {
l.w.WriteHeader(s)
l.status = s
}
func (l *responseLogger) Status() int {
return l.status
}
func (l *responseLogger) Size() int {
return l.size
}
type hijackLogger struct {
responseLogger
}
func (l *hijackLogger) Hijack() (net.Conn, *bufio.ReadWriter, error) {
h := l.responseLogger.w.(http.Hijacker)
conn, rw, err := h.Hijack()
if err == nil && l.responseLogger.status == 0 {
// The status will be StatusSwitchingProtocols if there was no error and WriteHeader has not been called yet
l.responseLogger.status = http.StatusSwitchingProtocols
}
return conn, rw, err
}
const lowerhex = "0123456789abcdef"
func appendQuoted(buf []byte, s string) []byte {
var runeTmp [utf8.UTFMax]byte
for width := 0; len(s) > 0; s = s[width:] {
r := rune(s[0])
width = 1
if r >= utf8.RuneSelf {
r, width = utf8.DecodeRuneInString(s)
}
if width == 1 && r == utf8.RuneError {
buf = append(buf, `\x`...)
buf = append(buf, lowerhex[s[0]>>4])
buf = append(buf, lowerhex[s[0]&0xF])
continue
}
if r == rune('"') || r == '\\' { // always backslashed
buf = append(buf, '\\')
buf = append(buf, byte(r))
continue
}
if strconv.IsPrint(r) {
n := utf8.EncodeRune(runeTmp[:], r)
buf = append(buf, runeTmp[:n]...)
continue
}
switch r {
case '\a':
buf = append(buf, `\a`...)
case '\b':
buf = append(buf, `\b`...)
case '\f':
buf = append(buf, `\f`...)
case '\n':
buf = append(buf, `\n`...)
case '\r':
buf = append(buf, `\r`...)
case '\t':
buf = append(buf, `\t`...)
case '\v':
buf = append(buf, `\v`...)
default:
switch {
case r < ' ':
buf = append(buf, `\x`...)
buf = append(buf, lowerhex[s[0]>>4])
buf = append(buf, lowerhex[s[0]&0xF])
case r > utf8.MaxRune:
r = 0xFFFD
fallthrough
case r < 0x10000:
buf = append(buf, `\u`...)
for s := 12; s >= 0; s -= 4 {
buf = append(buf, lowerhex[r>>uint(s)&0xF])
}
default:
buf = append(buf, `\U`...)
for s := 28; s >= 0; s -= 4 {
buf = append(buf, lowerhex[r>>uint(s)&0xF])
}
}
}
}
return buf
}
// buildCommonLogLine builds a log entry for req in Apache Common Log Format.
// ts is the timestamp with which the entry should be logged.
// status and size are used to provide the response HTTP status and size.
func buildCommonLogLine(req *http.Request, url url.URL, ts time.Time, status int, size int) []byte {
username := "-"
if url.User != nil {
if name := url.User.Username(); name != "" {
username = name
}
}
host, _, err := net.SplitHostPort(req.RemoteAddr)
if err != nil {
host = req.RemoteAddr
}
uri := url.RequestURI()
buf := make([]byte, 0, 3*(len(host)+len(username)+len(req.Method)+len(uri)+len(req.Proto)+50)/2)
buf = append(buf, host...)
buf = append(buf, " - "...)
buf = append(buf, username...)
buf = append(buf, " ["...)
buf = append(buf, ts.Format("02/Jan/2006:15:04:05 -0700")...)
buf = append(buf, `] "`...)
buf = append(buf, req.Method...)
buf = append(buf, " "...)
buf = appendQuoted(buf, uri)
buf = append(buf, " "...)
buf = append(buf, req.Proto...)
buf = append(buf, `" `...)
buf = append(buf, strconv.Itoa(status)...)
buf = append(buf, " "...)
buf = append(buf, strconv.Itoa(size)...)
return buf
}
// writeLog writes a log entry for req to w in Apache Common Log Format.
// ts is the timestamp with which the entry should be logged.
// status and size are used to provide the response HTTP status and size.
func writeLog(w io.Writer, req *http.Request, url url.URL, ts time.Time, status, size int) {
buf := buildCommonLogLine(req, url, ts, status, size)
buf = append(buf, '\n')
w.Write(buf)
}
// writeCombinedLog writes a log entry for req to w in Apache Combined Log Format.
// ts is the timestamp with which the entry should be logged.
// status and size are used to provide the response HTTP status and size.
func writeCombinedLog(w io.Writer, req *http.Request, url url.URL, ts time.Time, status, size int) {
buf := buildCommonLogLine(req, url, ts, status, size)
buf = append(buf, ` "`...)
buf = appendQuoted(buf, req.Referer())
buf = append(buf, `" "`...)
buf = appendQuoted(buf, req.UserAgent())
buf = append(buf, '"', '\n')
w.Write(buf)
}
// CombinedLoggingHandler return a http.Handler that wraps h and logs requests to out in
// Apache Combined Log Format.
//
// See http://httpd.apache.org/docs/2.2/logs.html#combined for a description of this format.
//
// LoggingHandler always sets the ident field of the log to -
func CombinedLoggingHandler(out io.Writer, h http.Handler) http.Handler {
return combinedLoggingHandler{out, h}
}
// LoggingHandler return a http.Handler that wraps h and logs requests to out in
// Apache Common Log Format (CLF).
//
// See http://httpd.apache.org/docs/2.2/logs.html#common for a description of this format.
//
// LoggingHandler always sets the ident field of the log to -
func LoggingHandler(out io.Writer, h http.Handler) http.Handler {
return loggingHandler{out, h}
}
// isContentType validates the Content-Type header
// is contentType. That is, its type and subtype match.
func isContentType(h http.Header, contentType string) bool {
ct := h.Get("Content-Type")
if i := strings.IndexRune(ct, ';'); i != -1 {
ct = ct[0:i]
}
return ct == contentType
}
// ContentTypeHandler wraps and returns a http.Handler, validating the request content type
// is acompatible with the contentTypes list.
// It writes a HTTP 415 error if that fails.
//
// Only PUT, POST, and PATCH requests are considered.
func ContentTypeHandler(h http.Handler, contentTypes ...string) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if !(r.Method == "PUT" || r.Method == "POST" || r.Method == "PATCH") {
h.ServeHTTP(w, r)
return
}
for _, ct := range contentTypes {
if isContentType(r.Header, ct) {
h.ServeHTTP(w, r)
return
}
}
http.Error(w, fmt.Sprintf("Unsupported content type %q; expected one of %q", r.Header.Get("Content-Type"), contentTypes), http.StatusUnsupportedMediaType)
})
}
const (
// HTTPMethodOverrideHeader is a commonly used
// http header to override a request method.
HTTPMethodOverrideHeader = "X-HTTP-Method-Override"
// HTTPMethodOverrideFormKey is a commonly used
// HTML form key to override a request method.
HTTPMethodOverrideFormKey = "_method"
)
// HTTPMethodOverrideHandler wraps and returns a http.Handler which checks for the X-HTTP-Method-Override header
// or the _method form key, and overrides (if valid) request.Method with its value.
//
// This is especially useful for http clients that don't support many http verbs.
// It isn't secure to override e.g a GET to a POST, so only POST requests are considered.
// Likewise, the override method can only be a "write" method: PUT, PATCH or DELETE.
//
// Form method takes precedence over header method.
func HTTPMethodOverrideHandler(h http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if r.Method == "POST" {
om := r.FormValue(HTTPMethodOverrideFormKey)
if om == "" {
om = r.Header.Get(HTTPMethodOverrideHeader)
}
if om == "PUT" || om == "PATCH" || om == "DELETE" {
r.Method = om
}
}
h.ServeHTTP(w, r)
})
}
-305
View File
@@ -1,305 +0,0 @@
// Copyright 2013 The Gorilla Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package handlers
import (
"bytes"
"net"
"net/http"
"net/http/httptest"
"net/url"
"strings"
"testing"
"time"
)
const (
ok = "ok\n"
notAllowed = "Method not allowed\n"
)
var okHandler = http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
w.Write([]byte(ok))
})
func newRequest(method, url string) *http.Request {
req, err := http.NewRequest(method, url, nil)
if err != nil {
panic(err)
}
return req
}
func TestMethodHandler(t *testing.T) {
tests := []struct {
req *http.Request
handler http.Handler
code int
allow string // Contents of the Allow header
body string
}{
// No handlers
{newRequest("GET", "/foo"), MethodHandler{}, http.StatusMethodNotAllowed, "", notAllowed},
{newRequest("OPTIONS", "/foo"), MethodHandler{}, http.StatusOK, "", ""},
// A single handler
{newRequest("GET", "/foo"), MethodHandler{"GET": okHandler}, http.StatusOK, "", ok},
{newRequest("POST", "/foo"), MethodHandler{"GET": okHandler}, http.StatusMethodNotAllowed, "GET", notAllowed},
// Multiple handlers
{newRequest("GET", "/foo"), MethodHandler{"GET": okHandler, "POST": okHandler}, http.StatusOK, "", ok},
{newRequest("POST", "/foo"), MethodHandler{"GET": okHandler, "POST": okHandler}, http.StatusOK, "", ok},
{newRequest("DELETE", "/foo"), MethodHandler{"GET": okHandler, "POST": okHandler}, http.StatusMethodNotAllowed, "GET, POST", notAllowed},
{newRequest("OPTIONS", "/foo"), MethodHandler{"GET": okHandler, "POST": okHandler}, http.StatusOK, "GET, POST", ""},
// Override OPTIONS
{newRequest("OPTIONS", "/foo"), MethodHandler{"OPTIONS": okHandler}, http.StatusOK, "", ok},
}
for i, test := range tests {
rec := httptest.NewRecorder()
test.handler.ServeHTTP(rec, test.req)
if rec.Code != test.code {
t.Fatalf("%d: wrong code, got %d want %d", i, rec.Code, test.code)
}
if allow := rec.HeaderMap.Get("Allow"); allow != test.allow {
t.Fatalf("%d: wrong Allow, got %s want %s", i, allow, test.allow)
}
if body := rec.Body.String(); body != test.body {
t.Fatalf("%d: wrong body, got %q want %q", i, body, test.body)
}
}
}
func TestWriteLog(t *testing.T) {
loc, err := time.LoadLocation("Europe/Warsaw")
if err != nil {
panic(err)
}
ts := time.Date(1983, 05, 26, 3, 30, 45, 0, loc)
// A typical request with an OK response
req := newRequest("GET", "http://example.com")
req.RemoteAddr = "192.168.100.5"
buf := new(bytes.Buffer)
writeLog(buf, req, *req.URL, ts, http.StatusOK, 100)
log := buf.String()
expected := "192.168.100.5 - - [26/May/1983:03:30:45 +0200] \"GET / HTTP/1.1\" 200 100\n"
if log != expected {
t.Fatalf("wrong log, got %q want %q", log, expected)
}
// Request with an unauthorized user
req = newRequest("GET", "http://example.com")
req.RemoteAddr = "192.168.100.5"
req.URL.User = url.User("kamil")
buf.Reset()
writeLog(buf, req, *req.URL, ts, http.StatusUnauthorized, 500)
log = buf.String()
expected = "192.168.100.5 - kamil [26/May/1983:03:30:45 +0200] \"GET / HTTP/1.1\" 401 500\n"
if log != expected {
t.Fatalf("wrong log, got %q want %q", log, expected)
}
// Request with url encoded parameters
req = newRequest("GET", "http://example.com/test?abc=hello%20world&a=b%3F")
req.RemoteAddr = "192.168.100.5"
buf.Reset()
writeLog(buf, req, *req.URL, ts, http.StatusOK, 100)
log = buf.String()
expected = "192.168.100.5 - - [26/May/1983:03:30:45 +0200] \"GET /test?abc=hello%20world&a=b%3F HTTP/1.1\" 200 100\n"
if log != expected {
t.Fatalf("wrong log, got %q want %q", log, expected)
}
}
func TestWriteCombinedLog(t *testing.T) {
loc, err := time.LoadLocation("Europe/Warsaw")
if err != nil {
panic(err)
}
ts := time.Date(1983, 05, 26, 3, 30, 45, 0, loc)
// A typical request with an OK response
req := newRequest("GET", "http://example.com")
req.RemoteAddr = "192.168.100.5"
req.Header.Set("Referer", "http://example.com")
req.Header.Set(
"User-Agent",
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_2) AppleWebKit/537.33 "+
"(KHTML, like Gecko) Chrome/27.0.1430.0 Safari/537.33",
)
buf := new(bytes.Buffer)
writeCombinedLog(buf, req, *req.URL, ts, http.StatusOK, 100)
log := buf.String()
expected := "192.168.100.5 - - [26/May/1983:03:30:45 +0200] \"GET / HTTP/1.1\" 200 100 \"http://example.com\" " +
"\"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_2) " +
"AppleWebKit/537.33 (KHTML, like Gecko) Chrome/27.0.1430.0 Safari/537.33\"\n"
if log != expected {
t.Fatalf("wrong log, got %q want %q", log, expected)
}
// Request with an unauthorized user
req.URL.User = url.User("kamil")
buf.Reset()
writeCombinedLog(buf, req, *req.URL, ts, http.StatusUnauthorized, 500)
log = buf.String()
expected = "192.168.100.5 - kamil [26/May/1983:03:30:45 +0200] \"GET / HTTP/1.1\" 401 500 \"http://example.com\" " +
"\"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_2) " +
"AppleWebKit/537.33 (KHTML, like Gecko) Chrome/27.0.1430.0 Safari/537.33\"\n"
if log != expected {
t.Fatalf("wrong log, got %q want %q", log, expected)
}
// Test with remote ipv6 address
req.RemoteAddr = "::1"
buf.Reset()
writeCombinedLog(buf, req, *req.URL, ts, http.StatusOK, 100)
log = buf.String()
expected = "::1 - kamil [26/May/1983:03:30:45 +0200] \"GET / HTTP/1.1\" 200 100 \"http://example.com\" " +
"\"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_2) " +
"AppleWebKit/537.33 (KHTML, like Gecko) Chrome/27.0.1430.0 Safari/537.33\"\n"
if log != expected {
t.Fatalf("wrong log, got %q want %q", log, expected)
}
// Test remote ipv6 addr, with port
req.RemoteAddr = net.JoinHostPort("::1", "65000")
buf.Reset()
writeCombinedLog(buf, req, *req.URL, ts, http.StatusOK, 100)
log = buf.String()
expected = "::1 - kamil [26/May/1983:03:30:45 +0200] \"GET / HTTP/1.1\" 200 100 \"http://example.com\" " +
"\"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_2) " +
"AppleWebKit/537.33 (KHTML, like Gecko) Chrome/27.0.1430.0 Safari/537.33\"\n"
if log != expected {
t.Fatalf("wrong log, got %q want %q", log, expected)
}
}
func TestLogPathRewrites(t *testing.T) {
var buf bytes.Buffer
handler := http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
req.URL.Path = "/" // simulate http.StripPrefix and friends
w.WriteHeader(200)
})
logger := LoggingHandler(&buf, handler)
logger.ServeHTTP(httptest.NewRecorder(), newRequest("GET", "/subdir/asdf"))
if !strings.Contains(buf.String(), "GET /subdir/asdf HTTP") {
t.Fatalf("Got log %#v, wanted substring %#v", buf.String(), "GET /subdir/asdf HTTP")
}
}
func BenchmarkWriteLog(b *testing.B) {
loc, err := time.LoadLocation("Europe/Warsaw")
if err != nil {
b.Fatalf(err.Error())
}
ts := time.Date(1983, 05, 26, 3, 30, 45, 0, loc)
req := newRequest("GET", "http://example.com")
req.RemoteAddr = "192.168.100.5"
b.ResetTimer()
buf := &bytes.Buffer{}
for i := 0; i < b.N; i++ {
buf.Reset()
writeLog(buf, req, *req.URL, ts, http.StatusUnauthorized, 500)
}
}
func TestContentTypeHandler(t *testing.T) {
tests := []struct {
Method string
AllowContentTypes []string
ContentType string
Code int
}{
{"POST", []string{"application/json"}, "application/json", http.StatusOK},
{"POST", []string{"application/json", "application/xml"}, "application/json", http.StatusOK},
{"POST", []string{"application/json"}, "application/json; charset=utf-8", http.StatusOK},
{"POST", []string{"application/json"}, "application/json+xxx", http.StatusUnsupportedMediaType},
{"POST", []string{"application/json"}, "text/plain", http.StatusUnsupportedMediaType},
{"GET", []string{"application/json"}, "", http.StatusOK},
{"GET", []string{}, "", http.StatusOK},
}
for _, test := range tests {
r, err := http.NewRequest(test.Method, "/", nil)
if err != nil {
t.Error(err)
continue
}
h := ContentTypeHandler(okHandler, test.AllowContentTypes...)
r.Header.Set("Content-Type", test.ContentType)
w := httptest.NewRecorder()
h.ServeHTTP(w, r)
if w.Code != test.Code {
t.Errorf("expected %d, got %d", test.Code, w.Code)
}
}
}
func TestHTTPMethodOverride(t *testing.T) {
var tests = []struct {
Method string
OverrideMethod string
ExpectedMethod string
}{
{"POST", "PUT", "PUT"},
{"POST", "PATCH", "PATCH"},
{"POST", "DELETE", "DELETE"},
{"PUT", "DELETE", "PUT"},
{"GET", "GET", "GET"},
{"HEAD", "HEAD", "HEAD"},
{"GET", "PUT", "GET"},
{"HEAD", "DELETE", "HEAD"},
}
for _, test := range tests {
h := HTTPMethodOverrideHandler(okHandler)
reqs := make([]*http.Request, 0, 2)
rHeader, err := http.NewRequest(test.Method, "/", nil)
if err != nil {
t.Error(err)
}
rHeader.Header.Set(HTTPMethodOverrideHeader, test.OverrideMethod)
reqs = append(reqs, rHeader)
f := url.Values{HTTPMethodOverrideFormKey: []string{test.OverrideMethod}}
rForm, err := http.NewRequest(test.Method, "/", strings.NewReader(f.Encode()))
if err != nil {
t.Error(err)
}
rForm.Header.Set("Content-Type", "application/x-www-form-urlencoded")
reqs = append(reqs, rForm)
for _, r := range reqs {
w := httptest.NewRecorder()
h.ServeHTTP(w, r)
if r.Method != test.ExpectedMethod {
t.Errorf("Expected %s, got %s", test.ExpectedMethod, r.Method)
}
}
}
}