| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180 |
- package webapi
- import (
- "net/http"
- "net/http/httptest"
- "strings"
- "testing"
- "github.com/stretchr/testify/assert"
- )
- // formPost builds a POST carrying body as its payload, with contentType set only
- // when non-empty.
- func formPost(body, contentType string) *http.Request {
- r := httptest.NewRequest(http.MethodPost, "/x", strings.NewReader(body))
- if contentType != "" {
- r.Header.Set("Content-Type", contentType)
- }
- return r
- }
- func TestParam(t *testing.T) {
- tests := []struct {
- name string
- req *http.Request
- key string
- want string
- }{
- {
- name: "from the query string",
- req: httptest.NewRequest(http.MethodGet, "/x?aimsid=sid", nil),
- key: "aimsid",
- want: "sid",
- },
- {
- name: "from a declared form body",
- req: formPost("s=mikekelly&pwd=hunter2", "application/x-www-form-urlencoded"),
- key: "s",
- want: "mikekelly",
- },
- {
- // A body may arrive unannounced, and ParseForm ignores one it cannot
- // type.
- name: "from an untyped form body",
- req: formPost("s=mikekelly&pwd=hunter2", ""),
- key: "pwd",
- want: "hunter2",
- },
- {
- name: "query wins over body",
- req: func() *http.Request {
- r := formPost("f=xml", "")
- r.URL.RawQuery = "f=json"
- return r
- }(),
- key: "f",
- want: "json",
- },
- {
- name: "absent from both",
- req: formPost("s=mikekelly", ""),
- key: "nope",
- want: "",
- },
- {
- name: "body is not read on a GET",
- req: httptest.NewRequest(http.MethodGet, "/x", strings.NewReader("s=mikekelly")),
- key: "s",
- want: "",
- },
- }
- for _, tt := range tests {
- t.Run(tt.name, func(t *testing.T) {
- assert.Equal(t, tt.want, param(tt.req, tt.key))
- })
- }
- }
- func TestParamLeavesBinaryBodyIntact(t *testing.T) {
- // expressions/upload POSTs a raw image with its parameters on the query string,
- // arriving untyped. A parameter lookup that misses must not hand that body to
- // ParseForm, which would read it to EOF.
- image := "\xff\xd8\xff\xe0 not form data"
- var body string
- var missing string
- handler := WithBinaryBody(http.HandlerFunc(func(_ http.ResponseWriter, r *http.Request) {
- missing = param(r, "absent")
- read := make([]byte, len(image))
- n, _ := r.Body.Read(read)
- body = string(read[:n])
- }))
- req := formPost(image, "")
- req.URL.RawQuery = "type=buddyIcon"
- handler.ServeHTTP(httptest.NewRecorder(), req)
- assert.Empty(t, missing)
- assert.Equal(t, image, body, "the image body was consumed by form parsing")
- }
- func TestParamValues(t *testing.T) {
- tests := []struct {
- name string
- req *http.Request
- want []string
- }{
- {
- name: "repeated in the query string",
- req: httptest.NewRequest(http.MethodGet, "/x?t=alice&t=bob", nil),
- want: []string{"alice", "bob"},
- },
- {
- name: "repeated in an untyped body",
- req: formPost("t=alice&t=bob", ""),
- want: []string{"alice", "bob"},
- },
- {
- name: "absent",
- req: httptest.NewRequest(http.MethodGet, "/x", nil),
- want: nil,
- },
- }
- for _, tt := range tests {
- t.Run(tt.name, func(t *testing.T) {
- assert.Equal(t, tt.want, paramValues(tt.req, "t"))
- })
- }
- }
- func TestPresenceTargets(t *testing.T) {
- tests := []struct {
- name string
- url string
- want []string
- }{
- {
- // One repetition per value.
- name: "repeated parameter",
- url: "/presence/get?t=alice&t=bob&t=carol",
- want: []string{"alice", "bob", "carol"},
- },
- {
- // Comma-separated in a single parameter.
- name: "comma separated",
- url: "/presence/get?t=alice,bob,carol",
- want: []string{"alice", "bob", "carol"},
- },
- {
- name: "both, with padding and empties discarded",
- url: "/presence/get?t=alice,+bob&t=&t=carol",
- want: []string{"alice", "bob", "carol"},
- },
- {
- name: "no targets",
- url: "/presence/get?bl=1",
- want: nil,
- },
- }
- for _, tt := range tests {
- t.Run(tt.name, func(t *testing.T) {
- got := targetNames(httptest.NewRequest(http.MethodGet, tt.url, nil))
- assert.Equal(t, tt.want, got)
- })
- }
- }
- func TestRequestIDFromFormBody(t *testing.T) {
- // A client may POST its correlation id in the body and read response.requestId
- // strictly off the reply, so a query-only read would leave the field empty.
- req := formPost("t=bob&message=hi&r=cookie-42", "")
- assert.Equal(t, "cookie-42", requestIDFromRequest(req))
- rr := httptest.NewRecorder()
- SendOK(rr, req, &SendIMData{MsgID: "msg-1", State: "delivered"}, nil)
- assert.Contains(t, rr.Body.String(), `"requestId":"cookie-42"`)
- }
|