github.com/hxx258456/ccgo@v0.0.5-0.20230213014102-48b35f46f66f/handlers/handlers_test.go (about)

     1  // Copyright 2013 The Gorilla Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package handlers
     6  
     7  import (
     8  	"net/url"
     9  	"strings"
    10  	"testing"
    11  
    12  	http "github.com/hxx258456/ccgo/gmhttp"
    13  	"github.com/hxx258456/ccgo/gmhttp/httptest"
    14  )
    15  
    16  const (
    17  	ok         = "ok\n"
    18  	notAllowed = "Method not allowed\n"
    19  )
    20  
    21  var okHandler = http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
    22  	w.Write([]byte(ok))
    23  })
    24  
    25  func newRequest(method, url string) *http.Request {
    26  	req, err := http.NewRequest(method, url, nil)
    27  	if err != nil {
    28  		panic(err)
    29  	}
    30  	return req
    31  }
    32  
    33  func TestMethodHandler(t *testing.T) {
    34  	tests := []struct {
    35  		req     *http.Request
    36  		handler http.Handler
    37  		code    int
    38  		allow   string // Contents of the Allow header
    39  		body    string
    40  	}{
    41  		// No handlers
    42  		{newRequest("GET", "/foo"), MethodHandler{}, http.StatusMethodNotAllowed, "", notAllowed},
    43  		{newRequest("OPTIONS", "/foo"), MethodHandler{}, http.StatusOK, "", ""},
    44  
    45  		// A single handler
    46  		{newRequest("GET", "/foo"), MethodHandler{"GET": okHandler}, http.StatusOK, "", ok},
    47  		{newRequest("POST", "/foo"), MethodHandler{"GET": okHandler}, http.StatusMethodNotAllowed, "GET", notAllowed},
    48  
    49  		// Multiple handlers
    50  		{newRequest("GET", "/foo"), MethodHandler{"GET": okHandler, "POST": okHandler}, http.StatusOK, "", ok},
    51  		{newRequest("POST", "/foo"), MethodHandler{"GET": okHandler, "POST": okHandler}, http.StatusOK, "", ok},
    52  		{newRequest("DELETE", "/foo"), MethodHandler{"GET": okHandler, "POST": okHandler}, http.StatusMethodNotAllowed, "GET, POST", notAllowed},
    53  		{newRequest("OPTIONS", "/foo"), MethodHandler{"GET": okHandler, "POST": okHandler}, http.StatusOK, "GET, POST", ""},
    54  
    55  		// Override OPTIONS
    56  		{newRequest("OPTIONS", "/foo"), MethodHandler{"OPTIONS": okHandler}, http.StatusOK, "", ok},
    57  	}
    58  
    59  	for i, test := range tests {
    60  		rec := httptest.NewRecorder()
    61  		test.handler.ServeHTTP(rec, test.req)
    62  		if rec.Code != test.code {
    63  			t.Fatalf("%d: wrong code, got %d want %d", i, rec.Code, test.code)
    64  		}
    65  		if allow := rec.HeaderMap.Get("Allow"); allow != test.allow {
    66  			t.Fatalf("%d: wrong Allow, got %s want %s", i, allow, test.allow)
    67  		}
    68  		if body := rec.Body.String(); body != test.body {
    69  			t.Fatalf("%d: wrong body, got %q want %q", i, body, test.body)
    70  		}
    71  	}
    72  }
    73  
    74  func TestContentTypeHandler(t *testing.T) {
    75  	tests := []struct {
    76  		Method            string
    77  		AllowContentTypes []string
    78  		ContentType       string
    79  		Code              int
    80  	}{
    81  		{"POST", []string{"application/json"}, "application/json", http.StatusOK},
    82  		{"POST", []string{"application/json", "application/xml"}, "application/json", http.StatusOK},
    83  		{"POST", []string{"application/json"}, "application/json; charset=utf-8", http.StatusOK},
    84  		{"POST", []string{"application/json"}, "application/json+xxx", http.StatusUnsupportedMediaType},
    85  		{"POST", []string{"application/json"}, "text/plain", http.StatusUnsupportedMediaType},
    86  		{"GET", []string{"application/json"}, "", http.StatusOK},
    87  		{"GET", []string{}, "", http.StatusOK},
    88  	}
    89  	for _, test := range tests {
    90  		r, err := http.NewRequest(test.Method, "/", nil)
    91  		if err != nil {
    92  			t.Error(err)
    93  			continue
    94  		}
    95  
    96  		h := ContentTypeHandler(okHandler, test.AllowContentTypes...)
    97  		r.Header.Set("Content-Type", test.ContentType)
    98  		w := httptest.NewRecorder()
    99  		h.ServeHTTP(w, r)
   100  		if w.Code != test.Code {
   101  			t.Errorf("expected %d, got %d", test.Code, w.Code)
   102  		}
   103  	}
   104  }
   105  
   106  func TestHTTPMethodOverride(t *testing.T) {
   107  	var tests = []struct {
   108  		Method         string
   109  		OverrideMethod string
   110  		ExpectedMethod string
   111  	}{
   112  		{"POST", "PUT", "PUT"},
   113  		{"POST", "PATCH", "PATCH"},
   114  		{"POST", "DELETE", "DELETE"},
   115  		{"PUT", "DELETE", "PUT"},
   116  		{"GET", "GET", "GET"},
   117  		{"HEAD", "HEAD", "HEAD"},
   118  		{"GET", "PUT", "GET"},
   119  		{"HEAD", "DELETE", "HEAD"},
   120  	}
   121  
   122  	for _, test := range tests {
   123  		h := HTTPMethodOverrideHandler(okHandler)
   124  		reqs := make([]*http.Request, 0, 2)
   125  
   126  		rHeader, err := http.NewRequest(test.Method, "/", nil)
   127  		if err != nil {
   128  			t.Error(err)
   129  		}
   130  		rHeader.Header.Set(HTTPMethodOverrideHeader, test.OverrideMethod)
   131  		reqs = append(reqs, rHeader)
   132  
   133  		f := url.Values{HTTPMethodOverrideFormKey: []string{test.OverrideMethod}}
   134  		rForm, err := http.NewRequest(test.Method, "/", strings.NewReader(f.Encode()))
   135  		if err != nil {
   136  			t.Error(err)
   137  		}
   138  		rForm.Header.Set("Content-Type", "application/x-www-form-urlencoded")
   139  		reqs = append(reqs, rForm)
   140  
   141  		for _, r := range reqs {
   142  			w := httptest.NewRecorder()
   143  			h.ServeHTTP(w, r)
   144  			if r.Method != test.ExpectedMethod {
   145  				t.Errorf("Expected %s, got %s", test.ExpectedMethod, r.Method)
   146  			}
   147  		}
   148  	}
   149  }