mirror of
https://github.com/octoleo/syncthing.git
synced 2024-11-19 11:35:10 +00:00
1083 lines
31 KiB
Go
1083 lines
31 KiB
Go
|
package ghttp_test
|
||
|
|
||
|
import (
|
||
|
"bytes"
|
||
|
"io"
|
||
|
"io/ioutil"
|
||
|
"net/http"
|
||
|
"net/url"
|
||
|
"regexp"
|
||
|
|
||
|
"github.com/golang/protobuf/proto"
|
||
|
"github.com/onsi/gomega/gbytes"
|
||
|
"github.com/onsi/gomega/ghttp/protobuf"
|
||
|
|
||
|
. "github.com/onsi/ginkgo"
|
||
|
. "github.com/onsi/gomega"
|
||
|
. "github.com/onsi/gomega/ghttp"
|
||
|
)
|
||
|
|
||
|
var _ = Describe("TestServer", func() {
|
||
|
var (
|
||
|
resp *http.Response
|
||
|
err error
|
||
|
s *Server
|
||
|
)
|
||
|
|
||
|
BeforeEach(func() {
|
||
|
s = NewServer()
|
||
|
})
|
||
|
|
||
|
AfterEach(func() {
|
||
|
s.Close()
|
||
|
})
|
||
|
|
||
|
Describe("Resetting the server", func() {
|
||
|
BeforeEach(func() {
|
||
|
s.RouteToHandler("GET", "/", func(w http.ResponseWriter, req *http.Request) {})
|
||
|
s.AppendHandlers(func(w http.ResponseWriter, req *http.Request) {})
|
||
|
http.Get(s.URL() + "/")
|
||
|
|
||
|
Ω(s.ReceivedRequests()).Should(HaveLen(1))
|
||
|
})
|
||
|
|
||
|
It("clears all handlers and call counts", func() {
|
||
|
s.Reset()
|
||
|
Ω(s.ReceivedRequests()).Should(HaveLen(0))
|
||
|
Ω(func() { s.GetHandler(0) }).Should(Panic())
|
||
|
})
|
||
|
})
|
||
|
|
||
|
Describe("closing client connections", func() {
|
||
|
It("closes", func() {
|
||
|
s.RouteToHandler("GET", "/",
|
||
|
func(w http.ResponseWriter, req *http.Request) {
|
||
|
io.WriteString(w, req.RemoteAddr)
|
||
|
},
|
||
|
)
|
||
|
|
||
|
resp, err := http.Get(s.URL())
|
||
|
Ω(err).ShouldNot(HaveOccurred())
|
||
|
Ω(resp.StatusCode).Should(Equal(200))
|
||
|
|
||
|
body, err := ioutil.ReadAll(resp.Body)
|
||
|
resp.Body.Close()
|
||
|
Ω(err).ShouldNot(HaveOccurred())
|
||
|
|
||
|
s.CloseClientConnections()
|
||
|
|
||
|
resp, err = http.Get(s.URL())
|
||
|
Ω(err).ShouldNot(HaveOccurred())
|
||
|
Ω(resp.StatusCode).Should(Equal(200))
|
||
|
|
||
|
body2, err := ioutil.ReadAll(resp.Body)
|
||
|
resp.Body.Close()
|
||
|
Ω(err).ShouldNot(HaveOccurred())
|
||
|
|
||
|
Ω(body2).ShouldNot(Equal(body))
|
||
|
})
|
||
|
})
|
||
|
|
||
|
Describe("allowing unhandled requests", func() {
|
||
|
Context("when true", func() {
|
||
|
BeforeEach(func() {
|
||
|
s.AllowUnhandledRequests = true
|
||
|
s.UnhandledRequestStatusCode = http.StatusForbidden
|
||
|
resp, err = http.Get(s.URL() + "/foo")
|
||
|
Ω(err).ShouldNot(HaveOccurred())
|
||
|
})
|
||
|
|
||
|
It("should allow unhandled requests and respond with the passed in status code", func() {
|
||
|
Ω(err).ShouldNot(HaveOccurred())
|
||
|
Ω(resp.StatusCode).Should(Equal(http.StatusForbidden))
|
||
|
|
||
|
data, err := ioutil.ReadAll(resp.Body)
|
||
|
Ω(err).ShouldNot(HaveOccurred())
|
||
|
Ω(data).Should(BeEmpty())
|
||
|
})
|
||
|
|
||
|
It("should record the requests", func() {
|
||
|
Ω(s.ReceivedRequests()).Should(HaveLen(1))
|
||
|
Ω(s.ReceivedRequests()[0].URL.Path).Should(Equal("/foo"))
|
||
|
})
|
||
|
})
|
||
|
|
||
|
Context("when false", func() {
|
||
|
It("should fail when attempting a request", func() {
|
||
|
failures := InterceptGomegaFailures(func() {
|
||
|
http.Get(s.URL() + "/foo")
|
||
|
})
|
||
|
|
||
|
Ω(failures[0]).Should(ContainSubstring("Received Unhandled Request"))
|
||
|
})
|
||
|
})
|
||
|
})
|
||
|
|
||
|
Describe("Managing Handlers", func() {
|
||
|
var called []string
|
||
|
BeforeEach(func() {
|
||
|
called = []string{}
|
||
|
s.RouteToHandler("GET", "/routed", func(w http.ResponseWriter, req *http.Request) {
|
||
|
called = append(called, "r1")
|
||
|
})
|
||
|
s.RouteToHandler("POST", regexp.MustCompile(`/routed\d`), func(w http.ResponseWriter, req *http.Request) {
|
||
|
called = append(called, "r2")
|
||
|
})
|
||
|
s.AppendHandlers(func(w http.ResponseWriter, req *http.Request) {
|
||
|
called = append(called, "A")
|
||
|
}, func(w http.ResponseWriter, req *http.Request) {
|
||
|
called = append(called, "B")
|
||
|
})
|
||
|
})
|
||
|
|
||
|
It("should prefer routed handlers if there is a match", func() {
|
||
|
http.Get(s.URL() + "/routed")
|
||
|
http.Post(s.URL()+"/routed7", "application/json", nil)
|
||
|
http.Get(s.URL() + "/foo")
|
||
|
http.Get(s.URL() + "/routed")
|
||
|
http.Post(s.URL()+"/routed9", "application/json", nil)
|
||
|
http.Get(s.URL() + "/bar")
|
||
|
|
||
|
failures := InterceptGomegaFailures(func() {
|
||
|
http.Get(s.URL() + "/foo")
|
||
|
http.Get(s.URL() + "/routed/not/a/match")
|
||
|
http.Get(s.URL() + "/routed7")
|
||
|
http.Post(s.URL()+"/routed", "application/json", nil)
|
||
|
})
|
||
|
|
||
|
Ω(failures[0]).Should(ContainSubstring("Received Unhandled Request"))
|
||
|
Ω(failures).Should(HaveLen(4))
|
||
|
|
||
|
http.Post(s.URL()+"/routed3", "application/json", nil)
|
||
|
|
||
|
Ω(called).Should(Equal([]string{"r1", "r2", "A", "r1", "r2", "B", "r2"}))
|
||
|
})
|
||
|
|
||
|
It("should override routed handlers when reregistered", func() {
|
||
|
s.RouteToHandler("GET", "/routed", func(w http.ResponseWriter, req *http.Request) {
|
||
|
called = append(called, "r3")
|
||
|
})
|
||
|
s.RouteToHandler("POST", regexp.MustCompile(`/routed\d`), func(w http.ResponseWriter, req *http.Request) {
|
||
|
called = append(called, "r4")
|
||
|
})
|
||
|
|
||
|
http.Get(s.URL() + "/routed")
|
||
|
http.Post(s.URL()+"/routed7", "application/json", nil)
|
||
|
|
||
|
Ω(called).Should(Equal([]string{"r3", "r4"}))
|
||
|
})
|
||
|
|
||
|
It("should call the appended handlers, in order, as requests come in", func() {
|
||
|
http.Get(s.URL() + "/foo")
|
||
|
Ω(called).Should(Equal([]string{"A"}))
|
||
|
|
||
|
http.Get(s.URL() + "/foo")
|
||
|
Ω(called).Should(Equal([]string{"A", "B"}))
|
||
|
|
||
|
failures := InterceptGomegaFailures(func() {
|
||
|
http.Get(s.URL() + "/foo")
|
||
|
})
|
||
|
|
||
|
Ω(failures[0]).Should(ContainSubstring("Received Unhandled Request"))
|
||
|
})
|
||
|
|
||
|
Describe("Overwriting an existing handler", func() {
|
||
|
BeforeEach(func() {
|
||
|
s.SetHandler(0, func(w http.ResponseWriter, req *http.Request) {
|
||
|
called = append(called, "C")
|
||
|
})
|
||
|
})
|
||
|
|
||
|
It("should override the specified handler", func() {
|
||
|
http.Get(s.URL() + "/foo")
|
||
|
http.Get(s.URL() + "/foo")
|
||
|
Ω(called).Should(Equal([]string{"C", "B"}))
|
||
|
})
|
||
|
})
|
||
|
|
||
|
Describe("Getting an existing handler", func() {
|
||
|
It("should return the handler func", func() {
|
||
|
s.GetHandler(1)(nil, nil)
|
||
|
Ω(called).Should(Equal([]string{"B"}))
|
||
|
})
|
||
|
})
|
||
|
|
||
|
Describe("Wrapping an existing handler", func() {
|
||
|
BeforeEach(func() {
|
||
|
s.WrapHandler(0, func(w http.ResponseWriter, req *http.Request) {
|
||
|
called = append(called, "C")
|
||
|
})
|
||
|
})
|
||
|
|
||
|
It("should wrap the existing handler in a new handler", func() {
|
||
|
http.Get(s.URL() + "/foo")
|
||
|
http.Get(s.URL() + "/foo")
|
||
|
Ω(called).Should(Equal([]string{"A", "C", "B"}))
|
||
|
})
|
||
|
})
|
||
|
})
|
||
|
|
||
|
Describe("When a handler fails", func() {
|
||
|
BeforeEach(func() {
|
||
|
s.UnhandledRequestStatusCode = http.StatusForbidden //just to be clear that 500s aren't coming from unhandled requests
|
||
|
})
|
||
|
|
||
|
Context("because the handler has panicked", func() {
|
||
|
BeforeEach(func() {
|
||
|
s.AppendHandlers(func(w http.ResponseWriter, req *http.Request) {
|
||
|
panic("bam")
|
||
|
})
|
||
|
})
|
||
|
|
||
|
It("should respond with a 500 and make a failing assertion", func() {
|
||
|
var resp *http.Response
|
||
|
var err error
|
||
|
|
||
|
failures := InterceptGomegaFailures(func() {
|
||
|
resp, err = http.Get(s.URL())
|
||
|
})
|
||
|
|
||
|
Ω(err).ShouldNot(HaveOccurred())
|
||
|
Ω(resp.StatusCode).Should(Equal(http.StatusInternalServerError))
|
||
|
Ω(failures).Should(ConsistOf(ContainSubstring("Handler Panicked")))
|
||
|
})
|
||
|
})
|
||
|
|
||
|
Context("because an assertion has failed", func() {
|
||
|
BeforeEach(func() {
|
||
|
s.AppendHandlers(func(w http.ResponseWriter, req *http.Request) {
|
||
|
// Ω(true).Should(BeFalse()) <-- would be nice to do it this way, but the test just can't be written this way
|
||
|
|
||
|
By("We're cheating a bit here -- we're throwing a GINKGO_PANIC which simulates a failed assertion")
|
||
|
panic(GINKGO_PANIC)
|
||
|
})
|
||
|
})
|
||
|
|
||
|
It("should respond with a 500 and *not* make a failing assertion, instead relying on Ginkgo to have already been notified of the error", func() {
|
||
|
resp, err := http.Get(s.URL())
|
||
|
|
||
|
Ω(err).ShouldNot(HaveOccurred())
|
||
|
Ω(resp.StatusCode).Should(Equal(http.StatusInternalServerError))
|
||
|
})
|
||
|
})
|
||
|
})
|
||
|
|
||
|
Describe("Logging to the Writer", func() {
|
||
|
var buf *gbytes.Buffer
|
||
|
BeforeEach(func() {
|
||
|
buf = gbytes.NewBuffer()
|
||
|
s.Writer = buf
|
||
|
s.AppendHandlers(func(w http.ResponseWriter, req *http.Request) {})
|
||
|
s.AppendHandlers(func(w http.ResponseWriter, req *http.Request) {})
|
||
|
})
|
||
|
|
||
|
It("should write to the buffer when a request comes in", func() {
|
||
|
http.Get(s.URL() + "/foo")
|
||
|
Ω(buf).Should(gbytes.Say("GHTTP Received Request: GET - /foo\n"))
|
||
|
|
||
|
http.Post(s.URL()+"/bar", "", nil)
|
||
|
Ω(buf).Should(gbytes.Say("GHTTP Received Request: POST - /bar\n"))
|
||
|
})
|
||
|
})
|
||
|
|
||
|
Describe("Request Handlers", func() {
|
||
|
Describe("VerifyRequest", func() {
|
||
|
BeforeEach(func() {
|
||
|
s.AppendHandlers(VerifyRequest("GET", "/foo"))
|
||
|
})
|
||
|
|
||
|
It("should verify the method, path", func() {
|
||
|
resp, err = http.Get(s.URL() + "/foo?baz=bar")
|
||
|
Ω(err).ShouldNot(HaveOccurred())
|
||
|
})
|
||
|
|
||
|
It("should verify the method, path", func() {
|
||
|
failures := InterceptGomegaFailures(func() {
|
||
|
http.Get(s.URL() + "/foo2")
|
||
|
})
|
||
|
Ω(failures).Should(HaveLen(1))
|
||
|
})
|
||
|
|
||
|
It("should verify the method, path", func() {
|
||
|
failures := InterceptGomegaFailures(func() {
|
||
|
http.Post(s.URL()+"/foo", "application/json", nil)
|
||
|
})
|
||
|
Ω(failures).Should(HaveLen(1))
|
||
|
})
|
||
|
|
||
|
Context("when passed a rawQuery", func() {
|
||
|
It("should also be possible to verify the rawQuery", func() {
|
||
|
s.SetHandler(0, VerifyRequest("GET", "/foo", "baz=bar"))
|
||
|
resp, err = http.Get(s.URL() + "/foo?baz=bar")
|
||
|
Ω(err).ShouldNot(HaveOccurred())
|
||
|
})
|
||
|
|
||
|
It("should match irregardless of query parameter ordering", func() {
|
||
|
s.SetHandler(0, VerifyRequest("GET", "/foo", "type=get&name=money"))
|
||
|
u, _ := url.Parse(s.URL() + "/foo")
|
||
|
u.RawQuery = url.Values{
|
||
|
"type": []string{"get"},
|
||
|
"name": []string{"money"},
|
||
|
}.Encode()
|
||
|
|
||
|
resp, err = http.Get(u.String())
|
||
|
Ω(err).ShouldNot(HaveOccurred())
|
||
|
})
|
||
|
})
|
||
|
|
||
|
Context("when passed a matcher for path", func() {
|
||
|
It("should apply the matcher", func() {
|
||
|
s.SetHandler(0, VerifyRequest("GET", MatchRegexp(`/foo/[a-f]*/3`)))
|
||
|
resp, err = http.Get(s.URL() + "/foo/abcdefa/3")
|
||
|
Ω(err).ShouldNot(HaveOccurred())
|
||
|
})
|
||
|
})
|
||
|
})
|
||
|
|
||
|
Describe("VerifyContentType", func() {
|
||
|
BeforeEach(func() {
|
||
|
s.AppendHandlers(CombineHandlers(
|
||
|
VerifyRequest("GET", "/foo"),
|
||
|
VerifyContentType("application/octet-stream"),
|
||
|
))
|
||
|
})
|
||
|
|
||
|
It("should verify the content type", func() {
|
||
|
req, err := http.NewRequest("GET", s.URL()+"/foo", nil)
|
||
|
Ω(err).ShouldNot(HaveOccurred())
|
||
|
req.Header.Set("Content-Type", "application/octet-stream")
|
||
|
|
||
|
resp, err = http.DefaultClient.Do(req)
|
||
|
Ω(err).ShouldNot(HaveOccurred())
|
||
|
})
|
||
|
|
||
|
It("should verify the content type", func() {
|
||
|
req, err := http.NewRequest("GET", s.URL()+"/foo", nil)
|
||
|
Ω(err).ShouldNot(HaveOccurred())
|
||
|
req.Header.Set("Content-Type", "application/json")
|
||
|
|
||
|
failures := InterceptGomegaFailures(func() {
|
||
|
http.DefaultClient.Do(req)
|
||
|
})
|
||
|
Ω(failures).Should(HaveLen(1))
|
||
|
})
|
||
|
})
|
||
|
|
||
|
Describe("Verify BasicAuth", func() {
|
||
|
BeforeEach(func() {
|
||
|
s.AppendHandlers(CombineHandlers(
|
||
|
VerifyRequest("GET", "/foo"),
|
||
|
VerifyBasicAuth("bob", "password"),
|
||
|
))
|
||
|
})
|
||
|
|
||
|
It("should verify basic auth", func() {
|
||
|
req, err := http.NewRequest("GET", s.URL()+"/foo", nil)
|
||
|
Ω(err).ShouldNot(HaveOccurred())
|
||
|
req.SetBasicAuth("bob", "password")
|
||
|
|
||
|
resp, err = http.DefaultClient.Do(req)
|
||
|
Ω(err).ShouldNot(HaveOccurred())
|
||
|
})
|
||
|
|
||
|
It("should verify basic auth", func() {
|
||
|
req, err := http.NewRequest("GET", s.URL()+"/foo", nil)
|
||
|
Ω(err).ShouldNot(HaveOccurred())
|
||
|
req.SetBasicAuth("bob", "bassword")
|
||
|
|
||
|
failures := InterceptGomegaFailures(func() {
|
||
|
http.DefaultClient.Do(req)
|
||
|
})
|
||
|
Ω(failures).Should(HaveLen(1))
|
||
|
})
|
||
|
|
||
|
It("should require basic auth header", func() {
|
||
|
req, err := http.NewRequest("GET", s.URL()+"/foo", nil)
|
||
|
Ω(err).ShouldNot(HaveOccurred())
|
||
|
|
||
|
failures := InterceptGomegaFailures(func() {
|
||
|
http.DefaultClient.Do(req)
|
||
|
})
|
||
|
Ω(failures).Should(ContainElement(ContainSubstring("Authorization header must be specified")))
|
||
|
})
|
||
|
})
|
||
|
|
||
|
Describe("VerifyHeader", func() {
|
||
|
BeforeEach(func() {
|
||
|
s.AppendHandlers(CombineHandlers(
|
||
|
VerifyRequest("GET", "/foo"),
|
||
|
VerifyHeader(http.Header{
|
||
|
"accept": []string{"jpeg", "png"},
|
||
|
"cache-control": []string{"omicron"},
|
||
|
"Return-Path": []string{"hobbiton"},
|
||
|
}),
|
||
|
))
|
||
|
})
|
||
|
|
||
|
It("should verify the headers", func() {
|
||
|
req, err := http.NewRequest("GET", s.URL()+"/foo", nil)
|
||
|
Ω(err).ShouldNot(HaveOccurred())
|
||
|
req.Header.Add("Accept", "jpeg")
|
||
|
req.Header.Add("Accept", "png")
|
||
|
req.Header.Add("Cache-Control", "omicron")
|
||
|
req.Header.Add("return-path", "hobbiton")
|
||
|
|
||
|
resp, err = http.DefaultClient.Do(req)
|
||
|
Ω(err).ShouldNot(HaveOccurred())
|
||
|
})
|
||
|
|
||
|
It("should verify the headers", func() {
|
||
|
req, err := http.NewRequest("GET", s.URL()+"/foo", nil)
|
||
|
Ω(err).ShouldNot(HaveOccurred())
|
||
|
req.Header.Add("Schmaccept", "jpeg")
|
||
|
req.Header.Add("Schmaccept", "png")
|
||
|
req.Header.Add("Cache-Control", "omicron")
|
||
|
req.Header.Add("return-path", "hobbiton")
|
||
|
|
||
|
failures := InterceptGomegaFailures(func() {
|
||
|
http.DefaultClient.Do(req)
|
||
|
})
|
||
|
Ω(failures).Should(HaveLen(1))
|
||
|
})
|
||
|
})
|
||
|
|
||
|
Describe("VerifyHeaderKV", func() {
|
||
|
BeforeEach(func() {
|
||
|
s.AppendHandlers(CombineHandlers(
|
||
|
VerifyRequest("GET", "/foo"),
|
||
|
VerifyHeaderKV("accept", "jpeg", "png"),
|
||
|
VerifyHeaderKV("cache-control", "omicron"),
|
||
|
VerifyHeaderKV("Return-Path", "hobbiton"),
|
||
|
))
|
||
|
})
|
||
|
|
||
|
It("should verify the headers", func() {
|
||
|
req, err := http.NewRequest("GET", s.URL()+"/foo", nil)
|
||
|
Ω(err).ShouldNot(HaveOccurred())
|
||
|
req.Header.Add("Accept", "jpeg")
|
||
|
req.Header.Add("Accept", "png")
|
||
|
req.Header.Add("Cache-Control", "omicron")
|
||
|
req.Header.Add("return-path", "hobbiton")
|
||
|
|
||
|
resp, err = http.DefaultClient.Do(req)
|
||
|
Ω(err).ShouldNot(HaveOccurred())
|
||
|
})
|
||
|
|
||
|
It("should verify the headers", func() {
|
||
|
req, err := http.NewRequest("GET", s.URL()+"/foo", nil)
|
||
|
Ω(err).ShouldNot(HaveOccurred())
|
||
|
req.Header.Add("Accept", "jpeg")
|
||
|
req.Header.Add("Cache-Control", "omicron")
|
||
|
req.Header.Add("return-path", "hobbiton")
|
||
|
|
||
|
failures := InterceptGomegaFailures(func() {
|
||
|
http.DefaultClient.Do(req)
|
||
|
})
|
||
|
Ω(failures).Should(HaveLen(1))
|
||
|
})
|
||
|
})
|
||
|
|
||
|
Describe("VerifyBody", func() {
|
||
|
BeforeEach(func() {
|
||
|
s.AppendHandlers(CombineHandlers(
|
||
|
VerifyRequest("POST", "/foo"),
|
||
|
VerifyBody([]byte("some body")),
|
||
|
))
|
||
|
})
|
||
|
|
||
|
It("should verify the body", func() {
|
||
|
resp, err = http.Post(s.URL()+"/foo", "", bytes.NewReader([]byte("some body")))
|
||
|
Ω(err).ShouldNot(HaveOccurred())
|
||
|
})
|
||
|
|
||
|
It("should verify the body", func() {
|
||
|
failures := InterceptGomegaFailures(func() {
|
||
|
http.Post(s.URL()+"/foo", "", bytes.NewReader([]byte("wrong body")))
|
||
|
})
|
||
|
Ω(failures).Should(HaveLen(1))
|
||
|
})
|
||
|
})
|
||
|
|
||
|
Describe("VerifyJSON", func() {
|
||
|
BeforeEach(func() {
|
||
|
s.AppendHandlers(CombineHandlers(
|
||
|
VerifyRequest("POST", "/foo"),
|
||
|
VerifyJSON(`{"a":3, "b":2}`),
|
||
|
))
|
||
|
})
|
||
|
|
||
|
It("should verify the json body and the content type", func() {
|
||
|
resp, err = http.Post(s.URL()+"/foo", "application/json", bytes.NewReader([]byte(`{"b":2, "a":3}`)))
|
||
|
Ω(err).ShouldNot(HaveOccurred())
|
||
|
})
|
||
|
|
||
|
It("should verify the json body and the content type", func() {
|
||
|
failures := InterceptGomegaFailures(func() {
|
||
|
http.Post(s.URL()+"/foo", "application/json", bytes.NewReader([]byte(`{"b":2, "a":4}`)))
|
||
|
})
|
||
|
Ω(failures).Should(HaveLen(1))
|
||
|
})
|
||
|
|
||
|
It("should verify the json body and the content type", func() {
|
||
|
failures := InterceptGomegaFailures(func() {
|
||
|
http.Post(s.URL()+"/foo", "application/not-json", bytes.NewReader([]byte(`{"b":2, "a":3}`)))
|
||
|
})
|
||
|
Ω(failures).Should(HaveLen(1))
|
||
|
})
|
||
|
})
|
||
|
|
||
|
Describe("VerifyJSONRepresenting", func() {
|
||
|
BeforeEach(func() {
|
||
|
s.AppendHandlers(CombineHandlers(
|
||
|
VerifyRequest("POST", "/foo"),
|
||
|
VerifyJSONRepresenting([]int{1, 3, 5}),
|
||
|
))
|
||
|
})
|
||
|
|
||
|
It("should verify the json body and the content type", func() {
|
||
|
resp, err = http.Post(s.URL()+"/foo", "application/json", bytes.NewReader([]byte(`[1,3,5]`)))
|
||
|
Ω(err).ShouldNot(HaveOccurred())
|
||
|
})
|
||
|
|
||
|
It("should verify the json body and the content type", func() {
|
||
|
failures := InterceptGomegaFailures(func() {
|
||
|
http.Post(s.URL()+"/foo", "application/json", bytes.NewReader([]byte(`[1,3]`)))
|
||
|
})
|
||
|
Ω(failures).Should(HaveLen(1))
|
||
|
})
|
||
|
})
|
||
|
|
||
|
Describe("VerifyForm", func() {
|
||
|
var formValues url.Values
|
||
|
|
||
|
BeforeEach(func() {
|
||
|
formValues = make(url.Values)
|
||
|
formValues.Add("users", "user1")
|
||
|
formValues.Add("users", "user2")
|
||
|
formValues.Add("group", "users")
|
||
|
})
|
||
|
|
||
|
Context("when encoded in the URL", func() {
|
||
|
BeforeEach(func() {
|
||
|
s.AppendHandlers(CombineHandlers(
|
||
|
VerifyRequest("GET", "/foo"),
|
||
|
VerifyForm(url.Values{
|
||
|
"users": []string{"user1", "user2"},
|
||
|
"group": []string{"users"},
|
||
|
}),
|
||
|
))
|
||
|
})
|
||
|
|
||
|
It("should verify form values", func() {
|
||
|
resp, err = http.Get(s.URL() + "/foo?" + formValues.Encode())
|
||
|
Ω(err).ShouldNot(HaveOccurred())
|
||
|
})
|
||
|
|
||
|
It("should ignore extra values", func() {
|
||
|
formValues.Add("extra", "value")
|
||
|
resp, err = http.Get(s.URL() + "/foo?" + formValues.Encode())
|
||
|
Ω(err).ShouldNot(HaveOccurred())
|
||
|
})
|
||
|
|
||
|
It("fail on missing values", func() {
|
||
|
formValues.Del("group")
|
||
|
failures := InterceptGomegaFailures(func() {
|
||
|
resp, err = http.Get(s.URL() + "/foo?" + formValues.Encode())
|
||
|
})
|
||
|
Ω(failures).Should(HaveLen(1))
|
||
|
})
|
||
|
|
||
|
It("fail on incorrect values", func() {
|
||
|
formValues.Set("group", "wheel")
|
||
|
failures := InterceptGomegaFailures(func() {
|
||
|
resp, err = http.Get(s.URL() + "/foo?" + formValues.Encode())
|
||
|
})
|
||
|
Ω(failures).Should(HaveLen(1))
|
||
|
})
|
||
|
})
|
||
|
|
||
|
Context("when present in the body", func() {
|
||
|
BeforeEach(func() {
|
||
|
s.AppendHandlers(CombineHandlers(
|
||
|
VerifyRequest("POST", "/foo"),
|
||
|
VerifyForm(url.Values{
|
||
|
"users": []string{"user1", "user2"},
|
||
|
"group": []string{"users"},
|
||
|
}),
|
||
|
))
|
||
|
})
|
||
|
|
||
|
It("should verify form values", func() {
|
||
|
resp, err = http.PostForm(s.URL()+"/foo", formValues)
|
||
|
Ω(err).ShouldNot(HaveOccurred())
|
||
|
})
|
||
|
|
||
|
It("should ignore extra values", func() {
|
||
|
formValues.Add("extra", "value")
|
||
|
resp, err = http.PostForm(s.URL()+"/foo", formValues)
|
||
|
Ω(err).ShouldNot(HaveOccurred())
|
||
|
})
|
||
|
|
||
|
It("fail on missing values", func() {
|
||
|
formValues.Del("group")
|
||
|
failures := InterceptGomegaFailures(func() {
|
||
|
resp, err = http.PostForm(s.URL()+"/foo", formValues)
|
||
|
})
|
||
|
Ω(failures).Should(HaveLen(1))
|
||
|
})
|
||
|
|
||
|
It("fail on incorrect values", func() {
|
||
|
formValues.Set("group", "wheel")
|
||
|
failures := InterceptGomegaFailures(func() {
|
||
|
resp, err = http.PostForm(s.URL()+"/foo", formValues)
|
||
|
})
|
||
|
Ω(failures).Should(HaveLen(1))
|
||
|
})
|
||
|
})
|
||
|
})
|
||
|
|
||
|
Describe("VerifyFormKV", func() {
|
||
|
Context("when encoded in the URL", func() {
|
||
|
BeforeEach(func() {
|
||
|
s.AppendHandlers(CombineHandlers(
|
||
|
VerifyRequest("GET", "/foo"),
|
||
|
VerifyFormKV("users", "user1", "user2"),
|
||
|
))
|
||
|
})
|
||
|
|
||
|
It("verifies the form value", func() {
|
||
|
resp, err = http.Get(s.URL() + "/foo?users=user1&users=user2")
|
||
|
Ω(err).ShouldNot(HaveOccurred())
|
||
|
})
|
||
|
|
||
|
It("verifies the form value", func() {
|
||
|
failures := InterceptGomegaFailures(func() {
|
||
|
resp, err = http.Get(s.URL() + "/foo?users=user1")
|
||
|
})
|
||
|
Ω(failures).Should(HaveLen(1))
|
||
|
})
|
||
|
})
|
||
|
|
||
|
Context("when present in the body", func() {
|
||
|
BeforeEach(func() {
|
||
|
s.AppendHandlers(CombineHandlers(
|
||
|
VerifyRequest("POST", "/foo"),
|
||
|
VerifyFormKV("users", "user1", "user2"),
|
||
|
))
|
||
|
})
|
||
|
|
||
|
It("verifies the form value", func() {
|
||
|
resp, err = http.PostForm(s.URL()+"/foo", url.Values{"users": []string{"user1", "user2"}})
|
||
|
Ω(err).ShouldNot(HaveOccurred())
|
||
|
})
|
||
|
|
||
|
It("verifies the form value", func() {
|
||
|
failures := InterceptGomegaFailures(func() {
|
||
|
resp, err = http.PostForm(s.URL()+"/foo", url.Values{"users": []string{"user1"}})
|
||
|
})
|
||
|
Ω(failures).Should(HaveLen(1))
|
||
|
})
|
||
|
})
|
||
|
})
|
||
|
|
||
|
Describe("VerifyProtoRepresenting", func() {
|
||
|
var message *protobuf.SimpleMessage
|
||
|
|
||
|
BeforeEach(func() {
|
||
|
message = new(protobuf.SimpleMessage)
|
||
|
message.Description = proto.String("A description")
|
||
|
message.Id = proto.Int32(0)
|
||
|
|
||
|
s.AppendHandlers(CombineHandlers(
|
||
|
VerifyRequest("POST", "/proto"),
|
||
|
VerifyProtoRepresenting(message),
|
||
|
))
|
||
|
})
|
||
|
|
||
|
It("verifies the proto body and the content type", func() {
|
||
|
serialized, err := proto.Marshal(message)
|
||
|
Ω(err).ShouldNot(HaveOccurred())
|
||
|
|
||
|
resp, err = http.Post(s.URL()+"/proto", "application/x-protobuf", bytes.NewReader(serialized))
|
||
|
Ω(err).ShouldNot(HaveOccurred())
|
||
|
})
|
||
|
|
||
|
It("should verify the proto body and the content type", func() {
|
||
|
serialized, err := proto.Marshal(&protobuf.SimpleMessage{
|
||
|
Description: proto.String("A description"),
|
||
|
Id: proto.Int32(0),
|
||
|
Metadata: proto.String("some metadata"),
|
||
|
})
|
||
|
Ω(err).ShouldNot(HaveOccurred())
|
||
|
|
||
|
failures := InterceptGomegaFailures(func() {
|
||
|
http.Post(s.URL()+"/proto", "application/x-protobuf", bytes.NewReader(serialized))
|
||
|
})
|
||
|
Ω(failures).Should(HaveLen(1))
|
||
|
})
|
||
|
|
||
|
It("should verify the proto body and the content type", func() {
|
||
|
serialized, err := proto.Marshal(message)
|
||
|
Ω(err).ShouldNot(HaveOccurred())
|
||
|
|
||
|
failures := InterceptGomegaFailures(func() {
|
||
|
http.Post(s.URL()+"/proto", "application/not-x-protobuf", bytes.NewReader(serialized))
|
||
|
})
|
||
|
Ω(failures).Should(HaveLen(1))
|
||
|
})
|
||
|
})
|
||
|
|
||
|
Describe("RespondWith", func() {
|
||
|
Context("without headers", func() {
|
||
|
BeforeEach(func() {
|
||
|
s.AppendHandlers(CombineHandlers(
|
||
|
VerifyRequest("POST", "/foo"),
|
||
|
RespondWith(http.StatusCreated, "sweet"),
|
||
|
), CombineHandlers(
|
||
|
VerifyRequest("POST", "/foo"),
|
||
|
RespondWith(http.StatusOK, []byte("sour")),
|
||
|
))
|
||
|
})
|
||
|
|
||
|
It("should return the response", func() {
|
||
|
resp, err = http.Post(s.URL()+"/foo", "application/json", nil)
|
||
|
Ω(err).ShouldNot(HaveOccurred())
|
||
|
|
||
|
Ω(resp.StatusCode).Should(Equal(http.StatusCreated))
|
||
|
|
||
|
body, err := ioutil.ReadAll(resp.Body)
|
||
|
Ω(err).ShouldNot(HaveOccurred())
|
||
|
Ω(body).Should(Equal([]byte("sweet")))
|
||
|
|
||
|
resp, err = http.Post(s.URL()+"/foo", "application/json", nil)
|
||
|
Ω(err).ShouldNot(HaveOccurred())
|
||
|
|
||
|
Ω(resp.StatusCode).Should(Equal(http.StatusOK))
|
||
|
|
||
|
body, err = ioutil.ReadAll(resp.Body)
|
||
|
Ω(err).ShouldNot(HaveOccurred())
|
||
|
Ω(body).Should(Equal([]byte("sour")))
|
||
|
})
|
||
|
})
|
||
|
|
||
|
Context("with headers", func() {
|
||
|
BeforeEach(func() {
|
||
|
s.AppendHandlers(CombineHandlers(
|
||
|
VerifyRequest("POST", "/foo"),
|
||
|
RespondWith(http.StatusCreated, "sweet", http.Header{"X-Custom-Header": []string{"my header"}}),
|
||
|
))
|
||
|
})
|
||
|
|
||
|
It("should return the headers too", func() {
|
||
|
resp, err = http.Post(s.URL()+"/foo", "application/json", nil)
|
||
|
Ω(err).ShouldNot(HaveOccurred())
|
||
|
|
||
|
Ω(resp.StatusCode).Should(Equal(http.StatusCreated))
|
||
|
Ω(ioutil.ReadAll(resp.Body)).Should(Equal([]byte("sweet")))
|
||
|
Ω(resp.Header.Get("X-Custom-Header")).Should(Equal("my header"))
|
||
|
})
|
||
|
})
|
||
|
})
|
||
|
|
||
|
Describe("RespondWithPtr", func() {
|
||
|
var code int
|
||
|
var byteBody []byte
|
||
|
var stringBody string
|
||
|
BeforeEach(func() {
|
||
|
code = http.StatusOK
|
||
|
byteBody = []byte("sweet")
|
||
|
stringBody = "sour"
|
||
|
|
||
|
s.AppendHandlers(CombineHandlers(
|
||
|
VerifyRequest("POST", "/foo"),
|
||
|
RespondWithPtr(&code, &byteBody),
|
||
|
), CombineHandlers(
|
||
|
VerifyRequest("POST", "/foo"),
|
||
|
RespondWithPtr(&code, &stringBody),
|
||
|
))
|
||
|
})
|
||
|
|
||
|
It("should return the response", func() {
|
||
|
code = http.StatusCreated
|
||
|
byteBody = []byte("tasty")
|
||
|
stringBody = "treat"
|
||
|
|
||
|
resp, err = http.Post(s.URL()+"/foo", "application/json", nil)
|
||
|
Ω(err).ShouldNot(HaveOccurred())
|
||
|
|
||
|
Ω(resp.StatusCode).Should(Equal(http.StatusCreated))
|
||
|
|
||
|
body, err := ioutil.ReadAll(resp.Body)
|
||
|
Ω(err).ShouldNot(HaveOccurred())
|
||
|
Ω(body).Should(Equal([]byte("tasty")))
|
||
|
|
||
|
resp, err = http.Post(s.URL()+"/foo", "application/json", nil)
|
||
|
Ω(err).ShouldNot(HaveOccurred())
|
||
|
|
||
|
Ω(resp.StatusCode).Should(Equal(http.StatusCreated))
|
||
|
|
||
|
body, err = ioutil.ReadAll(resp.Body)
|
||
|
Ω(err).ShouldNot(HaveOccurred())
|
||
|
Ω(body).Should(Equal([]byte("treat")))
|
||
|
})
|
||
|
|
||
|
Context("when passed a nil body", func() {
|
||
|
BeforeEach(func() {
|
||
|
s.SetHandler(0, CombineHandlers(
|
||
|
VerifyRequest("POST", "/foo"),
|
||
|
RespondWithPtr(&code, nil),
|
||
|
))
|
||
|
})
|
||
|
|
||
|
It("should return an empty body and not explode", func() {
|
||
|
resp, err = http.Post(s.URL()+"/foo", "application/json", nil)
|
||
|
|
||
|
Ω(err).ShouldNot(HaveOccurred())
|
||
|
Ω(resp.StatusCode).Should(Equal(http.StatusOK))
|
||
|
body, err := ioutil.ReadAll(resp.Body)
|
||
|
Ω(err).ShouldNot(HaveOccurred())
|
||
|
Ω(body).Should(BeEmpty())
|
||
|
|
||
|
Ω(s.ReceivedRequests()).Should(HaveLen(1))
|
||
|
})
|
||
|
})
|
||
|
})
|
||
|
|
||
|
Describe("RespondWithJSON", func() {
|
||
|
Context("when no optional headers are set", func() {
|
||
|
BeforeEach(func() {
|
||
|
s.AppendHandlers(CombineHandlers(
|
||
|
VerifyRequest("POST", "/foo"),
|
||
|
RespondWithJSONEncoded(http.StatusCreated, []int{1, 2, 3}),
|
||
|
))
|
||
|
})
|
||
|
|
||
|
It("should return the response", func() {
|
||
|
resp, err = http.Post(s.URL()+"/foo", "application/json", nil)
|
||
|
Ω(err).ShouldNot(HaveOccurred())
|
||
|
|
||
|
Ω(resp.StatusCode).Should(Equal(http.StatusCreated))
|
||
|
|
||
|
body, err := ioutil.ReadAll(resp.Body)
|
||
|
Ω(err).ShouldNot(HaveOccurred())
|
||
|
Ω(body).Should(MatchJSON("[1,2,3]"))
|
||
|
})
|
||
|
|
||
|
It("should set the Content-Type header to application/json", func() {
|
||
|
resp, err = http.Post(s.URL()+"/foo", "application/json", nil)
|
||
|
Ω(err).ShouldNot(HaveOccurred())
|
||
|
|
||
|
Ω(resp.Header["Content-Type"]).Should(Equal([]string{"application/json"}))
|
||
|
})
|
||
|
})
|
||
|
|
||
|
Context("when optional headers are set", func() {
|
||
|
var headers http.Header
|
||
|
BeforeEach(func() {
|
||
|
headers = http.Header{"Stuff": []string{"things"}}
|
||
|
})
|
||
|
|
||
|
JustBeforeEach(func() {
|
||
|
s.AppendHandlers(CombineHandlers(
|
||
|
VerifyRequest("POST", "/foo"),
|
||
|
RespondWithJSONEncoded(http.StatusCreated, []int{1, 2, 3}, headers),
|
||
|
))
|
||
|
})
|
||
|
|
||
|
It("should preserve those headers", func() {
|
||
|
resp, err = http.Post(s.URL()+"/foo", "application/json", nil)
|
||
|
Ω(err).ShouldNot(HaveOccurred())
|
||
|
|
||
|
Ω(resp.Header["Stuff"]).Should(Equal([]string{"things"}))
|
||
|
})
|
||
|
|
||
|
It("should set the Content-Type header to application/json", func() {
|
||
|
resp, err = http.Post(s.URL()+"/foo", "application/json", nil)
|
||
|
Ω(err).ShouldNot(HaveOccurred())
|
||
|
|
||
|
Ω(resp.Header["Content-Type"]).Should(Equal([]string{"application/json"}))
|
||
|
})
|
||
|
|
||
|
Context("when setting the Content-Type explicitly", func() {
|
||
|
BeforeEach(func() {
|
||
|
headers["Content-Type"] = []string{"not-json"}
|
||
|
})
|
||
|
|
||
|
It("should use the Content-Type header that was explicitly set", func() {
|
||
|
resp, err = http.Post(s.URL()+"/foo", "application/json", nil)
|
||
|
Ω(err).ShouldNot(HaveOccurred())
|
||
|
|
||
|
Ω(resp.Header["Content-Type"]).Should(Equal([]string{"not-json"}))
|
||
|
})
|
||
|
})
|
||
|
})
|
||
|
})
|
||
|
|
||
|
Describe("RespondWithJSONPtr", func() {
|
||
|
type testObject struct {
|
||
|
Key string
|
||
|
Value string
|
||
|
}
|
||
|
|
||
|
var code int
|
||
|
var object testObject
|
||
|
|
||
|
Context("when no optional headers are set", func() {
|
||
|
BeforeEach(func() {
|
||
|
code = http.StatusOK
|
||
|
object = testObject{}
|
||
|
s.AppendHandlers(CombineHandlers(
|
||
|
VerifyRequest("POST", "/foo"),
|
||
|
RespondWithJSONEncodedPtr(&code, &object),
|
||
|
))
|
||
|
})
|
||
|
|
||
|
It("should return the response", func() {
|
||
|
code = http.StatusCreated
|
||
|
object = testObject{
|
||
|
Key: "Jim",
|
||
|
Value: "Codes",
|
||
|
}
|
||
|
resp, err = http.Post(s.URL()+"/foo", "application/json", nil)
|
||
|
Ω(err).ShouldNot(HaveOccurred())
|
||
|
|
||
|
Ω(resp.StatusCode).Should(Equal(http.StatusCreated))
|
||
|
|
||
|
body, err := ioutil.ReadAll(resp.Body)
|
||
|
Ω(err).ShouldNot(HaveOccurred())
|
||
|
Ω(body).Should(MatchJSON(`{"Key": "Jim", "Value": "Codes"}`))
|
||
|
})
|
||
|
|
||
|
It("should set the Content-Type header to application/json", func() {
|
||
|
resp, err = http.Post(s.URL()+"/foo", "application/json", nil)
|
||
|
Ω(err).ShouldNot(HaveOccurred())
|
||
|
|
||
|
Ω(resp.Header["Content-Type"]).Should(Equal([]string{"application/json"}))
|
||
|
})
|
||
|
})
|
||
|
|
||
|
Context("when optional headers are set", func() {
|
||
|
var headers http.Header
|
||
|
BeforeEach(func() {
|
||
|
headers = http.Header{"Stuff": []string{"things"}}
|
||
|
})
|
||
|
|
||
|
JustBeforeEach(func() {
|
||
|
code = http.StatusOK
|
||
|
object = testObject{}
|
||
|
s.AppendHandlers(CombineHandlers(
|
||
|
VerifyRequest("POST", "/foo"),
|
||
|
RespondWithJSONEncodedPtr(&code, &object, headers),
|
||
|
))
|
||
|
})
|
||
|
|
||
|
It("should preserve those headers", func() {
|
||
|
resp, err = http.Post(s.URL()+"/foo", "application/json", nil)
|
||
|
Ω(err).ShouldNot(HaveOccurred())
|
||
|
|
||
|
Ω(resp.Header["Stuff"]).Should(Equal([]string{"things"}))
|
||
|
})
|
||
|
|
||
|
It("should set the Content-Type header to application/json", func() {
|
||
|
resp, err = http.Post(s.URL()+"/foo", "application/json", nil)
|
||
|
Ω(err).ShouldNot(HaveOccurred())
|
||
|
|
||
|
Ω(resp.Header["Content-Type"]).Should(Equal([]string{"application/json"}))
|
||
|
})
|
||
|
|
||
|
Context("when setting the Content-Type explicitly", func() {
|
||
|
BeforeEach(func() {
|
||
|
headers["Content-Type"] = []string{"not-json"}
|
||
|
})
|
||
|
|
||
|
It("should use the Content-Type header that was explicitly set", func() {
|
||
|
resp, err = http.Post(s.URL()+"/foo", "application/json", nil)
|
||
|
Ω(err).ShouldNot(HaveOccurred())
|
||
|
|
||
|
Ω(resp.Header["Content-Type"]).Should(Equal([]string{"not-json"}))
|
||
|
})
|
||
|
})
|
||
|
})
|
||
|
})
|
||
|
|
||
|
Describe("RespondWithProto", func() {
|
||
|
var message *protobuf.SimpleMessage
|
||
|
|
||
|
BeforeEach(func() {
|
||
|
message = new(protobuf.SimpleMessage)
|
||
|
message.Description = proto.String("A description")
|
||
|
message.Id = proto.Int32(99)
|
||
|
})
|
||
|
|
||
|
Context("when no optional headers are set", func() {
|
||
|
BeforeEach(func() {
|
||
|
s.AppendHandlers(CombineHandlers(
|
||
|
VerifyRequest("POST", "/proto"),
|
||
|
RespondWithProto(http.StatusCreated, message),
|
||
|
))
|
||
|
})
|
||
|
|
||
|
It("should return the response", func() {
|
||
|
resp, err = http.Post(s.URL()+"/proto", "application/x-protobuf", nil)
|
||
|
Ω(err).ShouldNot(HaveOccurred())
|
||
|
|
||
|
Ω(resp.StatusCode).Should(Equal(http.StatusCreated))
|
||
|
|
||
|
var received protobuf.SimpleMessage
|
||
|
body, err := ioutil.ReadAll(resp.Body)
|
||
|
err = proto.Unmarshal(body, &received)
|
||
|
Ω(err).ShouldNot(HaveOccurred())
|
||
|
})
|
||
|
|
||
|
It("should set the Content-Type header to application/x-protobuf", func() {
|
||
|
resp, err = http.Post(s.URL()+"/proto", "application/x-protobuf", nil)
|
||
|
Ω(err).ShouldNot(HaveOccurred())
|
||
|
|
||
|
Ω(resp.Header["Content-Type"]).Should(Equal([]string{"application/x-protobuf"}))
|
||
|
})
|
||
|
})
|
||
|
|
||
|
Context("when optional headers are set", func() {
|
||
|
var headers http.Header
|
||
|
BeforeEach(func() {
|
||
|
headers = http.Header{"Stuff": []string{"things"}}
|
||
|
})
|
||
|
|
||
|
JustBeforeEach(func() {
|
||
|
s.AppendHandlers(CombineHandlers(
|
||
|
VerifyRequest("POST", "/proto"),
|
||
|
RespondWithProto(http.StatusCreated, message, headers),
|
||
|
))
|
||
|
})
|
||
|
|
||
|
It("should preserve those headers", func() {
|
||
|
resp, err = http.Post(s.URL()+"/proto", "application/x-protobuf", nil)
|
||
|
Ω(err).ShouldNot(HaveOccurred())
|
||
|
|
||
|
Ω(resp.Header["Stuff"]).Should(Equal([]string{"things"}))
|
||
|
})
|
||
|
|
||
|
It("should set the Content-Type header to application/x-protobuf", func() {
|
||
|
resp, err = http.Post(s.URL()+"/proto", "application/x-protobuf", nil)
|
||
|
Ω(err).ShouldNot(HaveOccurred())
|
||
|
|
||
|
Ω(resp.Header["Content-Type"]).Should(Equal([]string{"application/x-protobuf"}))
|
||
|
})
|
||
|
|
||
|
Context("when setting the Content-Type explicitly", func() {
|
||
|
BeforeEach(func() {
|
||
|
headers["Content-Type"] = []string{"not-x-protobuf"}
|
||
|
})
|
||
|
|
||
|
It("should use the Content-Type header that was explicitly set", func() {
|
||
|
resp, err = http.Post(s.URL()+"/proto", "application/x-protobuf", nil)
|
||
|
Ω(err).ShouldNot(HaveOccurred())
|
||
|
|
||
|
Ω(resp.Header["Content-Type"]).Should(Equal([]string{"not-x-protobuf"}))
|
||
|
})
|
||
|
})
|
||
|
})
|
||
|
})
|
||
|
})
|
||
|
})
|