mirror of https://github.com/k3s-io/k3s
Update go-restful
parent
b6f2f396ba
commit
535c509dd3
|
@ -215,8 +215,8 @@
|
|||
},
|
||||
{
|
||||
"ImportPath": "github.com/emicklei/go-restful",
|
||||
"Comment": "v1.1.3-76-gbfd6ff2",
|
||||
"Rev": "bfd6ff29d2961031cec64346a92bae4cde96c868"
|
||||
"Comment": "v1.1.3-98-g1f9a0ee",
|
||||
"Rev": "1f9a0ee00ff93717a275e15b30cf7df356255877"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/evanphx/json-patch",
|
||||
|
|
|
@ -1,5 +1,10 @@
|
|||
Change history of go-restful
|
||||
=
|
||||
2015-08-06
|
||||
- add support for reading entities from compressed request content
|
||||
- use sync.Pool for compressors of http response and request body
|
||||
- add Description to Parameter for documentation in Swagger UI
|
||||
|
||||
2015-03-20
|
||||
- add configurable logging
|
||||
|
||||
|
|
|
@ -47,7 +47,7 @@ func (u UserResource) findUser(request *restful.Request, response *restful.Respo
|
|||
- Filters for intercepting the request → response flow on Service or Route level
|
||||
- Request-scoped variables using attributes
|
||||
- Containers for WebServices on different HTTP endpoints
|
||||
- Content encoding (gzip,deflate) of responses
|
||||
- Content encoding (gzip,deflate) of request and response payloads
|
||||
- Automatic responses on OPTIONS (using a filter)
|
||||
- Automatic CORS request handling (using a filter)
|
||||
- API declaration for Swagger UI (see swagger package)
|
||||
|
|
|
@ -73,15 +73,13 @@ func NewCompressingResponseWriter(httpWriter http.ResponseWriter, encoding strin
|
|||
c.writer = httpWriter
|
||||
var err error
|
||||
if ENCODING_GZIP == encoding {
|
||||
c.compressor, err = gzip.NewWriterLevel(httpWriter, gzip.BestSpeed)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
w := GzipWriterPool.Get().(*gzip.Writer)
|
||||
w.Reset(httpWriter)
|
||||
c.compressor = w
|
||||
} else if ENCODING_DEFLATE == encoding {
|
||||
c.compressor, err = zlib.NewWriterLevel(httpWriter, zlib.BestSpeed)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
w := ZlibWriterPool.Get().(*zlib.Writer)
|
||||
w.Reset(httpWriter)
|
||||
c.compressor = w
|
||||
} else {
|
||||
return nil, errors.New("Unknown encoding:" + encoding)
|
||||
}
|
||||
|
|
|
@ -1,11 +1,17 @@
|
|||
package restful
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"compress/gzip"
|
||||
"compress/zlib"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// go test -v -test.run TestGzip ...restful
|
||||
func TestGzip(t *testing.T) {
|
||||
EnableContentEncoding = true
|
||||
httpRequest, _ := http.NewRequest("GET", "/test", nil)
|
||||
|
@ -27,6 +33,17 @@ func TestGzip(t *testing.T) {
|
|||
if httpWriter.Header().Get("Content-Encoding") != "gzip" {
|
||||
t.Fatal("Missing gzip header")
|
||||
}
|
||||
reader, err := gzip.NewReader(httpWriter.Body)
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
data, err := ioutil.ReadAll(reader)
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
if got, want := string(data), "Hello World"; got != want {
|
||||
t.Errorf("got %v want %v", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDeflate(t *testing.T) {
|
||||
|
@ -50,4 +67,61 @@ func TestDeflate(t *testing.T) {
|
|||
if httpWriter.Header().Get("Content-Encoding") != "deflate" {
|
||||
t.Fatal("Missing deflate header")
|
||||
}
|
||||
reader, err := zlib.NewReader(httpWriter.Body)
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
data, err := ioutil.ReadAll(reader)
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
if got, want := string(data), "Hello World"; got != want {
|
||||
t.Errorf("got %v want %v", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGzipDecompressRequestBody(t *testing.T) {
|
||||
b := new(bytes.Buffer)
|
||||
w := newGzipWriter()
|
||||
w.Reset(b)
|
||||
io.WriteString(w, `{"msg":"hi"}`)
|
||||
w.Flush()
|
||||
w.Close()
|
||||
|
||||
req := new(Request)
|
||||
httpRequest, _ := http.NewRequest("GET", "/", bytes.NewReader(b.Bytes()))
|
||||
httpRequest.Header.Set("Content-Type", "application/json")
|
||||
httpRequest.Header.Set("Content-Encoding", "gzip")
|
||||
req.Request = httpRequest
|
||||
|
||||
doCacheReadEntityBytes = false
|
||||
doc := make(map[string]interface{})
|
||||
req.ReadEntity(&doc)
|
||||
|
||||
if got, want := doc["msg"], "hi"; got != want {
|
||||
t.Errorf("got %v want %v", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestZlibDecompressRequestBody(t *testing.T) {
|
||||
b := new(bytes.Buffer)
|
||||
w := newZlibWriter()
|
||||
w.Reset(b)
|
||||
io.WriteString(w, `{"msg":"hi"}`)
|
||||
w.Flush()
|
||||
w.Close()
|
||||
|
||||
req := new(Request)
|
||||
httpRequest, _ := http.NewRequest("GET", "/", bytes.NewReader(b.Bytes()))
|
||||
httpRequest.Header.Set("Content-Type", "application/json")
|
||||
httpRequest.Header.Set("Content-Encoding", "deflate")
|
||||
req.Request = httpRequest
|
||||
|
||||
doCacheReadEntityBytes = false
|
||||
doc := make(map[string]interface{})
|
||||
req.ReadEntity(&doc)
|
||||
|
||||
if got, want := doc["msg"], "hi"; got != want {
|
||||
t.Errorf("got %v want %v", got, want)
|
||||
}
|
||||
}
|
||||
|
|
63
Godeps/_workspace/src/github.com/emicklei/go-restful/compressor_pools.go
generated
vendored
Normal file
63
Godeps/_workspace/src/github.com/emicklei/go-restful/compressor_pools.go
generated
vendored
Normal file
|
@ -0,0 +1,63 @@
|
|||
package restful
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"compress/gzip"
|
||||
"compress/zlib"
|
||||
"sync"
|
||||
)
|
||||
|
||||
// GzipWriterPool is used to get reusable zippers.
|
||||
// The Get() result must be type asserted to *gzip.Writer.
|
||||
var GzipWriterPool = &sync.Pool{
|
||||
New: func() interface{} {
|
||||
return newGzipWriter()
|
||||
},
|
||||
}
|
||||
|
||||
func newGzipWriter() *gzip.Writer {
|
||||
// create with an empty bytes writer; it will be replaced before using the gzipWriter
|
||||
writer, err := gzip.NewWriterLevel(new(bytes.Buffer), gzip.BestSpeed)
|
||||
if err != nil {
|
||||
panic(err.Error())
|
||||
}
|
||||
return writer
|
||||
}
|
||||
|
||||
// GzipReaderPool is used to get reusable zippers.
|
||||
// The Get() result must be type asserted to *gzip.Reader.
|
||||
var GzipReaderPool = &sync.Pool{
|
||||
New: func() interface{} {
|
||||
return newGzipReader()
|
||||
},
|
||||
}
|
||||
|
||||
func newGzipReader() *gzip.Reader {
|
||||
// create with an empty reader (but with GZIP header); it will be replaced before using the gzipReader
|
||||
w := GzipWriterPool.Get().(*gzip.Writer)
|
||||
b := new(bytes.Buffer)
|
||||
w.Reset(b)
|
||||
w.Flush()
|
||||
w.Close()
|
||||
reader, err := gzip.NewReader(bytes.NewReader(b.Bytes()))
|
||||
if err != nil {
|
||||
panic(err.Error())
|
||||
}
|
||||
return reader
|
||||
}
|
||||
|
||||
// ZlibWriterPool is used to get reusable zippers.
|
||||
// The Get() result must be type asserted to *zlib.Writer.
|
||||
var ZlibWriterPool = &sync.Pool{
|
||||
New: func() interface{} {
|
||||
return newZlibWriter()
|
||||
},
|
||||
}
|
||||
|
||||
func newZlibWriter() *zlib.Writer {
|
||||
writer, err := zlib.NewWriterLevel(new(bytes.Buffer), gzip.BestSpeed)
|
||||
if err != nil {
|
||||
panic(err.Error())
|
||||
}
|
||||
return writer
|
||||
}
|
|
@ -11,6 +11,7 @@ import (
|
|||
"os"
|
||||
"runtime"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/emicklei/go-restful/log"
|
||||
)
|
||||
|
@ -18,6 +19,7 @@ import (
|
|||
// Container holds a collection of WebServices and a http.ServeMux to dispatch http requests.
|
||||
// The requests are further dispatched to routes of WebServices using a RouteSelector
|
||||
type Container struct {
|
||||
webServicesLock sync.RWMutex
|
||||
webServices []*WebService
|
||||
ServeMux *http.ServeMux
|
||||
isRegisteredOnRoot bool
|
||||
|
@ -83,6 +85,8 @@ func (c *Container) EnableContentEncoding(enabled bool) {
|
|||
|
||||
// Add a WebService to the Container. It will detect duplicate root paths and panic in that case.
|
||||
func (c *Container) Add(service *WebService) *Container {
|
||||
c.webServicesLock.Lock()
|
||||
defer c.webServicesLock.Unlock()
|
||||
// If registered on root then no additional specific mapping is needed
|
||||
if !c.isRegisteredOnRoot {
|
||||
pattern := c.fixedPrefixPath(service.RootPath())
|
||||
|
@ -122,6 +126,19 @@ func (c *Container) Add(service *WebService) *Container {
|
|||
return c
|
||||
}
|
||||
|
||||
func (c *Container) Remove(ws *WebService) error {
|
||||
c.webServicesLock.Lock()
|
||||
defer c.webServicesLock.Unlock()
|
||||
newServices := []*WebService{}
|
||||
for ix := range c.webServices {
|
||||
if c.webServices[ix].rootPath != ws.rootPath {
|
||||
newServices = append(newServices, c.webServices[ix])
|
||||
}
|
||||
}
|
||||
c.webServices = newServices
|
||||
return nil
|
||||
}
|
||||
|
||||
// logStackOnRecover is the default RecoverHandleFunction and is called
|
||||
// when DoNotRecover is false and the recoverHandleFunc is not set for the container.
|
||||
// Default implementation logs the stacktrace and writes the stacktrace on the response.
|
||||
|
@ -190,9 +207,16 @@ func (c *Container) dispatch(httpWriter http.ResponseWriter, httpRequest *http.R
|
|||
}
|
||||
}
|
||||
// Find best match Route ; err is non nil if no match was found
|
||||
webService, route, err := c.router.SelectRoute(
|
||||
var webService *WebService
|
||||
var route *Route
|
||||
var err error
|
||||
func() {
|
||||
c.webServicesLock.RLock()
|
||||
defer c.webServicesLock.RUnlock()
|
||||
webService, route, err = c.router.SelectRoute(
|
||||
c.webServices,
|
||||
httpRequest)
|
||||
}()
|
||||
if err != nil {
|
||||
// a non-200 response has already been written
|
||||
// run container filters anyway ; they should not touch the response...
|
||||
|
@ -272,7 +296,13 @@ func (c *Container) Filter(filter FilterFunction) {
|
|||
|
||||
// RegisteredWebServices returns the collections of added WebServices
|
||||
func (c Container) RegisteredWebServices() []*WebService {
|
||||
return c.webServices
|
||||
c.webServicesLock.RLock()
|
||||
defer c.webServicesLock.RUnlock()
|
||||
result := make([]*WebService, len(c.webServices))
|
||||
for ix := range c.webServices {
|
||||
result[ix] = c.webServices[ix]
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
// computeAllowedMethods returns a list of HTTP methods that are valid for a Request
|
||||
|
|
|
@ -95,8 +95,14 @@ func (p *Parameter) DataType(typeName string) *Parameter {
|
|||
return p
|
||||
}
|
||||
|
||||
// DefaultValue sets the default value field and returnw the receiver
|
||||
// DefaultValue sets the default value field and returns the receiver
|
||||
func (p *Parameter) DefaultValue(stringRepresentation string) *Parameter {
|
||||
p.data.DefaultValue = stringRepresentation
|
||||
return p
|
||||
}
|
||||
|
||||
// Description sets the description value field and returns the receiver
|
||||
func (p *Parameter) Description(doc string) *Parameter {
|
||||
p.data.Description = doc
|
||||
return p
|
||||
}
|
||||
|
|
|
@ -6,6 +6,8 @@ package restful
|
|||
|
||||
import (
|
||||
"bytes"
|
||||
"compress/gzip"
|
||||
"compress/zlib"
|
||||
"encoding/json"
|
||||
"encoding/xml"
|
||||
"io"
|
||||
|
@ -82,15 +84,17 @@ func (r *Request) HeaderParameter(name string) string {
|
|||
// ReadEntity checks the Accept header and reads the content into the entityPointer
|
||||
// May be called multiple times in the request-response flow
|
||||
func (r *Request) ReadEntity(entityPointer interface{}) (err error) {
|
||||
defer r.Request.Body.Close()
|
||||
contentType := r.Request.Header.Get(HEADER_ContentType)
|
||||
contentEncoding := r.Request.Header.Get(HEADER_ContentEncoding)
|
||||
if doCacheReadEntityBytes {
|
||||
return r.cachingReadEntity(contentType, entityPointer)
|
||||
return r.cachingReadEntity(contentType, contentEncoding, entityPointer)
|
||||
}
|
||||
// unmarshall directly from request Body
|
||||
return r.decodeEntity(r.Request.Body, contentType, entityPointer)
|
||||
return r.decodeEntity(r.Request.Body, contentType, contentEncoding, entityPointer)
|
||||
}
|
||||
|
||||
func (r *Request) cachingReadEntity(contentType string, entityPointer interface{}) (err error) {
|
||||
func (r *Request) cachingReadEntity(contentType string, contentEncoding string, entityPointer interface{}) (err error) {
|
||||
var buffer []byte
|
||||
if r.bodyContent != nil {
|
||||
buffer = *r.bodyContent
|
||||
|
@ -101,22 +105,38 @@ func (r *Request) cachingReadEntity(contentType string, entityPointer interface{
|
|||
}
|
||||
r.bodyContent = &buffer
|
||||
}
|
||||
return r.decodeEntity(bytes.NewReader(buffer), contentType, entityPointer)
|
||||
return r.decodeEntity(bytes.NewReader(buffer), contentType, contentEncoding, entityPointer)
|
||||
}
|
||||
|
||||
func (r *Request) decodeEntity(reader io.Reader, contentType string, entityPointer interface{}) (err error) {
|
||||
if strings.Contains(contentType, MIME_XML) {
|
||||
return xml.NewDecoder(reader).Decode(entityPointer)
|
||||
func (r *Request) decodeEntity(reader io.Reader, contentType string, contentEncoding string, entityPointer interface{}) (err error) {
|
||||
entityReader := reader
|
||||
|
||||
// check if the request body needs decompression
|
||||
if ENCODING_GZIP == contentEncoding {
|
||||
gzipReader := GzipReaderPool.Get().(*gzip.Reader)
|
||||
gzipReader.Reset(reader)
|
||||
entityReader = gzipReader
|
||||
} else if ENCODING_DEFLATE == contentEncoding {
|
||||
zlibReader, err := zlib.NewReader(reader)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
entityReader = zlibReader
|
||||
}
|
||||
|
||||
// decode JSON
|
||||
if strings.Contains(contentType, MIME_JSON) || MIME_JSON == defaultRequestContentType {
|
||||
decoder := json.NewDecoder(reader)
|
||||
decoder := json.NewDecoder(entityReader)
|
||||
decoder.UseNumber()
|
||||
return decoder.Decode(entityPointer)
|
||||
}
|
||||
if MIME_XML == defaultRequestContentType {
|
||||
return xml.NewDecoder(reader).Decode(entityPointer)
|
||||
|
||||
// decode XML
|
||||
if strings.Contains(contentType, MIME_XML) || MIME_XML == defaultRequestContentType {
|
||||
return xml.NewDecoder(entityReader).Decode(entityPointer)
|
||||
}
|
||||
return NewError(400, "Unable to unmarshal content of type:"+contentType)
|
||||
|
||||
return NewError(http.StatusBadRequest, "Unable to unmarshal content of type:"+contentType)
|
||||
}
|
||||
|
||||
// SetAttribute adds or replaces the attribute with the given value.
|
||||
|
|
|
@ -28,11 +28,12 @@ type Response struct {
|
|||
statusCode int // HTTP status code that has been written explicity (if zero then net/http has written 200)
|
||||
contentLength int // number of bytes written for the response body
|
||||
prettyPrint bool // controls the indentation feature of XML and JSON serialization. It is initialized using var PrettyPrintResponses.
|
||||
err error // err property is kept when WriteError is called
|
||||
}
|
||||
|
||||
// Creates a new response based on a http ResponseWriter.
|
||||
func NewResponse(httpWriter http.ResponseWriter) *Response {
|
||||
return &Response{httpWriter, "", []string{}, http.StatusOK, 0, PrettyPrintResponses} // empty content-types
|
||||
return &Response{httpWriter, "", []string{}, http.StatusOK, 0, PrettyPrintResponses, nil} // empty content-types
|
||||
}
|
||||
|
||||
// If Accept header matching fails, fall back to this type, otherwise
|
||||
|
@ -182,6 +183,7 @@ func (r *Response) WriteJson(value interface{}, contentType string) error {
|
|||
|
||||
// WriteError write the http status and the error string on the response.
|
||||
func (r *Response) WriteError(httpStatus int, err error) error {
|
||||
r.err = err
|
||||
return r.WriteErrorString(httpStatus, err.Error())
|
||||
}
|
||||
|
||||
|
@ -203,21 +205,30 @@ func (r *Response) WriteErrorString(status int, errorReason string) error {
|
|||
|
||||
// WriteHeader is overridden to remember the Status Code that has been written.
|
||||
// Note that using this method, the status value is only written when
|
||||
// - calling WriteEntity,
|
||||
// - or directly calling WriteAsXml or WriteAsJson,
|
||||
// - or if the status is one for which no response is allowed (i.e.,
|
||||
// 204 (http.StatusNoContent) or 304 (http.StatusNotModified))
|
||||
// calling WriteEntity,
|
||||
// or directly calling WriteAsXml or WriteAsJson,
|
||||
// or if the status is one for which no response is allowed:
|
||||
//
|
||||
// 202 = http.StatusAccepted
|
||||
// 204 = http.StatusNoContent
|
||||
// 206 = http.StatusPartialContent
|
||||
// 304 = http.StatusNotModified
|
||||
//
|
||||
// If this behavior does not fit your need then you can write to the underlying response, such as:
|
||||
// response.ResponseWriter.WriteHeader(http.StatusAccepted)
|
||||
func (r *Response) WriteHeader(httpStatus int) {
|
||||
r.statusCode = httpStatus
|
||||
// if 201,204,304 then WriteEntity will not be called so we need to pass this code
|
||||
// if 202,204,206,304 then WriteEntity will not be called so we need to pass this code
|
||||
if http.StatusNoContent == httpStatus ||
|
||||
http.StatusNotModified == httpStatus ||
|
||||
http.StatusPartialContent == httpStatus {
|
||||
http.StatusPartialContent == httpStatus ||
|
||||
http.StatusAccepted == httpStatus {
|
||||
r.ResponseWriter.WriteHeader(httpStatus)
|
||||
}
|
||||
}
|
||||
|
||||
// StatusCode returns the code that has been written using WriteHeader.
|
||||
// If WriteHeader, WriteEntity or WriteAsXml has not been called (yet) then return 200 OK.
|
||||
func (r Response) StatusCode() int {
|
||||
if 0 == r.statusCode {
|
||||
// no status code has been written yet; assume OK
|
||||
|
@ -245,3 +256,8 @@ func (r Response) ContentLength() int {
|
|||
func (r Response) CloseNotify() <-chan bool {
|
||||
return r.ResponseWriter.(http.CloseNotifier).CloseNotify()
|
||||
}
|
||||
|
||||
// Error returns the err created by WriteError
|
||||
func (r Response) Error() error {
|
||||
return r.err
|
||||
}
|
||||
|
|
|
@ -9,7 +9,7 @@ import (
|
|||
|
||||
func TestWriteHeader(t *testing.T) {
|
||||
httpWriter := httptest.NewRecorder()
|
||||
resp := Response{httpWriter, "*/*", []string{"*/*"}, 0, 0, true}
|
||||
resp := Response{httpWriter, "*/*", []string{"*/*"}, 0, 0, true, nil}
|
||||
resp.WriteHeader(123)
|
||||
if resp.StatusCode() != 123 {
|
||||
t.Errorf("Unexpected status code:%d", resp.StatusCode())
|
||||
|
@ -18,7 +18,7 @@ func TestWriteHeader(t *testing.T) {
|
|||
|
||||
func TestNoWriteHeader(t *testing.T) {
|
||||
httpWriter := httptest.NewRecorder()
|
||||
resp := Response{httpWriter, "*/*", []string{"*/*"}, 0, 0, true}
|
||||
resp := Response{httpWriter, "*/*", []string{"*/*"}, 0, 0, true, nil}
|
||||
if resp.StatusCode() != http.StatusOK {
|
||||
t.Errorf("Unexpected status code:%d", resp.StatusCode())
|
||||
}
|
||||
|
@ -31,7 +31,7 @@ type food struct {
|
|||
// go test -v -test.run TestMeasureContentLengthXml ...restful
|
||||
func TestMeasureContentLengthXml(t *testing.T) {
|
||||
httpWriter := httptest.NewRecorder()
|
||||
resp := Response{httpWriter, "*/*", []string{"*/*"}, 0, 0, true}
|
||||
resp := Response{httpWriter, "*/*", []string{"*/*"}, 0, 0, true, nil}
|
||||
resp.WriteAsXml(food{"apple"})
|
||||
if resp.ContentLength() != 76 {
|
||||
t.Errorf("Incorrect measured length:%d", resp.ContentLength())
|
||||
|
@ -41,7 +41,7 @@ func TestMeasureContentLengthXml(t *testing.T) {
|
|||
// go test -v -test.run TestMeasureContentLengthJson ...restful
|
||||
func TestMeasureContentLengthJson(t *testing.T) {
|
||||
httpWriter := httptest.NewRecorder()
|
||||
resp := Response{httpWriter, "*/*", []string{"*/*"}, 0, 0, true}
|
||||
resp := Response{httpWriter, "*/*", []string{"*/*"}, 0, 0, true, nil}
|
||||
resp.WriteAsJson(food{"apple"})
|
||||
if resp.ContentLength() != 22 {
|
||||
t.Errorf("Incorrect measured length:%d", resp.ContentLength())
|
||||
|
@ -51,7 +51,7 @@ func TestMeasureContentLengthJson(t *testing.T) {
|
|||
// go test -v -test.run TestMeasureContentLengthJsonNotPretty ...restful
|
||||
func TestMeasureContentLengthJsonNotPretty(t *testing.T) {
|
||||
httpWriter := httptest.NewRecorder()
|
||||
resp := Response{httpWriter, "*/*", []string{"*/*"}, 0, 0, false}
|
||||
resp := Response{httpWriter, "*/*", []string{"*/*"}, 0, 0, false, nil}
|
||||
resp.WriteAsJson(food{"apple"})
|
||||
if resp.ContentLength() != 16 {
|
||||
t.Errorf("Incorrect measured length:%d", resp.ContentLength())
|
||||
|
@ -61,7 +61,7 @@ func TestMeasureContentLengthJsonNotPretty(t *testing.T) {
|
|||
// go test -v -test.run TestMeasureContentLengthWriteErrorString ...restful
|
||||
func TestMeasureContentLengthWriteErrorString(t *testing.T) {
|
||||
httpWriter := httptest.NewRecorder()
|
||||
resp := Response{httpWriter, "*/*", []string{"*/*"}, 0, 0, true}
|
||||
resp := Response{httpWriter, "*/*", []string{"*/*"}, 0, 0, true, nil}
|
||||
resp.WriteErrorString(404, "Invalid")
|
||||
if resp.ContentLength() != len("Invalid") {
|
||||
t.Errorf("Incorrect measured length:%d", resp.ContentLength())
|
||||
|
@ -79,7 +79,7 @@ func TestStatusIsPassedToResponse(t *testing.T) {
|
|||
{write: 400, read: 200},
|
||||
} {
|
||||
httpWriter := httptest.NewRecorder()
|
||||
resp := Response{httpWriter, "*/*", []string{"*/*"}, 0, 0, true}
|
||||
resp := Response{httpWriter, "*/*", []string{"*/*"}, 0, 0, true, nil}
|
||||
resp.WriteHeader(each.write)
|
||||
if got, want := httpWriter.Code, each.read; got != want {
|
||||
t.Error("got %v want %v", got, want)
|
||||
|
@ -90,7 +90,7 @@ func TestStatusIsPassedToResponse(t *testing.T) {
|
|||
// go test -v -test.run TestStatusCreatedAndContentTypeJson_Issue54 ...restful
|
||||
func TestStatusCreatedAndContentTypeJson_Issue54(t *testing.T) {
|
||||
httpWriter := httptest.NewRecorder()
|
||||
resp := Response{httpWriter, "application/json", []string{"application/json"}, 0, 0, true}
|
||||
resp := Response{httpWriter, "application/json", []string{"application/json"}, 0, 0, true, nil}
|
||||
resp.WriteHeader(201)
|
||||
resp.WriteAsJson(food{"Juicy"})
|
||||
if httpWriter.HeaderMap.Get("Content-Type") != "application/json" {
|
||||
|
@ -112,7 +112,7 @@ func (e errorOnWriteRecorder) Write(bytes []byte) (int, error) {
|
|||
// go test -v -test.run TestLastWriteErrorCaught ...restful
|
||||
func TestLastWriteErrorCaught(t *testing.T) {
|
||||
httpWriter := errorOnWriteRecorder{httptest.NewRecorder()}
|
||||
resp := Response{httpWriter, "application/json", []string{"application/json"}, 0, 0, true}
|
||||
resp := Response{httpWriter, "application/json", []string{"application/json"}, 0, 0, true, nil}
|
||||
err := resp.WriteAsJson(food{"Juicy"})
|
||||
if err.Error() != "fail" {
|
||||
t.Errorf("Unexpected error message:%v", err)
|
||||
|
@ -123,7 +123,7 @@ func TestLastWriteErrorCaught(t *testing.T) {
|
|||
func TestAcceptStarStar_Issue83(t *testing.T) {
|
||||
httpWriter := httptest.NewRecorder()
|
||||
// Accept Produces
|
||||
resp := Response{httpWriter, "application/bogus,*/*;q=0.8", []string{"application/json"}, 0, 0, true}
|
||||
resp := Response{httpWriter, "application/bogus,*/*;q=0.8", []string{"application/json"}, 0, 0, true, nil}
|
||||
resp.WriteEntity(food{"Juicy"})
|
||||
ct := httpWriter.Header().Get("Content-Type")
|
||||
if "application/json" != ct {
|
||||
|
@ -135,7 +135,7 @@ func TestAcceptStarStar_Issue83(t *testing.T) {
|
|||
func TestAcceptSkipStarStar_Issue83(t *testing.T) {
|
||||
httpWriter := httptest.NewRecorder()
|
||||
// Accept Produces
|
||||
resp := Response{httpWriter, " application/xml ,*/* ; q=0.8", []string{"application/json", "application/xml"}, 0, 0, true}
|
||||
resp := Response{httpWriter, " application/xml ,*/* ; q=0.8", []string{"application/json", "application/xml"}, 0, 0, true, nil}
|
||||
resp.WriteEntity(food{"Juicy"})
|
||||
ct := httpWriter.Header().Get("Content-Type")
|
||||
if "application/xml" != ct {
|
||||
|
@ -147,7 +147,7 @@ func TestAcceptSkipStarStar_Issue83(t *testing.T) {
|
|||
func TestAcceptXmlBeforeStarStar_Issue83(t *testing.T) {
|
||||
httpWriter := httptest.NewRecorder()
|
||||
// Accept Produces
|
||||
resp := Response{httpWriter, "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8", []string{"application/json"}, 0, 0, true}
|
||||
resp := Response{httpWriter, "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8", []string{"application/json"}, 0, 0, true, nil}
|
||||
resp.WriteEntity(food{"Juicy"})
|
||||
ct := httpWriter.Header().Get("Content-Type")
|
||||
if "application/json" != ct {
|
||||
|
@ -158,7 +158,7 @@ func TestAcceptXmlBeforeStarStar_Issue83(t *testing.T) {
|
|||
// go test -v -test.run TestWriteHeaderNoContent_Issue124 ...restful
|
||||
func TestWriteHeaderNoContent_Issue124(t *testing.T) {
|
||||
httpWriter := httptest.NewRecorder()
|
||||
resp := Response{httpWriter, "text/plain", []string{"text/plain"}, 0, 0, true}
|
||||
resp := Response{httpWriter, "text/plain", []string{"text/plain"}, 0, 0, true, nil}
|
||||
resp.WriteHeader(http.StatusNoContent)
|
||||
if httpWriter.Code != http.StatusNoContent {
|
||||
t.Errorf("got %d want %d", httpWriter.Code, http.StatusNoContent)
|
||||
|
@ -168,7 +168,7 @@ func TestWriteHeaderNoContent_Issue124(t *testing.T) {
|
|||
// go test -v -test.run TestStatusCreatedAndContentTypeJson_Issue163 ...restful
|
||||
func TestStatusCreatedAndContentTypeJson_Issue163(t *testing.T) {
|
||||
httpWriter := httptest.NewRecorder()
|
||||
resp := Response{httpWriter, "application/json", []string{"application/json"}, 0, 0, true}
|
||||
resp := Response{httpWriter, "application/json", []string{"application/json"}, 0, 0, true, nil}
|
||||
resp.WriteHeader(http.StatusNotModified)
|
||||
if httpWriter.Code != http.StatusNotModified {
|
||||
t.Errorf("Got %d want %d", httpWriter.Code, http.StatusNotModified)
|
||||
|
|
9
Godeps/_workspace/src/github.com/emicklei/go-restful/swagger/swagger_webservice.go
generated
vendored
9
Godeps/_workspace/src/github.com/emicklei/go-restful/swagger/swagger_webservice.go
generated
vendored
|
@ -173,7 +173,14 @@ func (sws SwaggerService) getDeclarations(req *restful.Request, resp *restful.Re
|
|||
} else {
|
||||
host = hostvalues[0]
|
||||
}
|
||||
(&decl).BasePath = fmt.Sprintf("http://%s", host)
|
||||
// inspect Referer for the scheme (http vs https)
|
||||
scheme := "http"
|
||||
if referer := req.Request.Header["Referer"]; len(referer) > 0 {
|
||||
if strings.HasPrefix(referer[0], "https") {
|
||||
scheme = "https"
|
||||
}
|
||||
}
|
||||
(&decl).BasePath = fmt.Sprintf("%s://%s", scheme, host)
|
||||
}
|
||||
resp.WriteAsJson(decl)
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue