github.com/teacat/davai@v1.1.1-0.20200831221114-b14311e2e4c9/main_test.go (about)

     1  package davai
     2  
     3  import (
     4  	"net/http"
     5  	"os"
     6  	"path/filepath"
     7  	"sort"
     8  	"strings"
     9  	"testing"
    10  	"time"
    11  
    12  	"context"
    13  
    14  	rcontext "github.com/gorilla/context"
    15  	"github.com/parnurzeal/gorequest"
    16  	"github.com/stretchr/testify/assert"
    17  )
    18  
    19  const (
    20  	methodPost    = "POST"
    21  	methodGet     = "GET"
    22  	methodDelete  = "DELETE"
    23  	methodOptions = "OPTIONS"
    24  	methodPut     = "PUT"
    25  	methodPatch   = "PATCH"
    26  )
    27  
    28  type testRequest struct {
    29  	Path       string
    30  	Method     string
    31  	StatusCode int
    32  	Body       string
    33  }
    34  
    35  func sendTestRequests(a *assert.Assertions, reqs []testRequest) {
    36  	request := gorequest.New()
    37  	for _, r := range reqs {
    38  		if r.StatusCode == 0 {
    39  			r.StatusCode = http.StatusOK
    40  		}
    41  		if r.Method == "" {
    42  			r.Method = methodGet
    43  		}
    44  		var resp gorequest.Response
    45  		var body string
    46  		var errs []error
    47  		switch r.Method {
    48  		case methodGet:
    49  			resp, body, errs = request.Get(r.Path).End()
    50  		case methodPost:
    51  			resp, body, errs = request.Post(r.Path).End()
    52  		case methodDelete:
    53  			resp, body, errs = request.Delete(r.Path).End()
    54  		case methodOptions:
    55  			resp, body, errs = request.Options(r.Path).End()
    56  		case methodPut:
    57  			resp, body, errs = request.Put(r.Path).End()
    58  		case methodPatch:
    59  			resp, body, errs = request.Patch(r.Path).End()
    60  		}
    61  		a.Len(errs, 0)
    62  		a.Equal(r.Body, body)
    63  		a.NotNil(resp)
    64  		a.Equal(r.StatusCode, resp.StatusCode, r.Path)
    65  	}
    66  }
    67  
    68  func varsToString(vars map[string]string) string {
    69  	var slice []string
    70  
    71  	for _, v := range vars {
    72  		slice = append(slice, v)
    73  	}
    74  	sort.Slice(slice, func(i, j int) bool {
    75  		return slice[i] < slice[j]
    76  	})
    77  	a := strings.Join(slice, ",")
    78  	return a
    79  }
    80  
    81  func TestBasicRoute(t *testing.T) {
    82  	assert := assert.New(t)
    83  	r := New()
    84  	r.Get("/", func(w http.ResponseWriter, r *http.Request) {
    85  		w.Write([]byte("Root"))
    86  	})
    87  	r.Get("/one", func(w http.ResponseWriter, r *http.Request) {
    88  		w.Write([]byte("One"))
    89  	})
    90  	r.Get("/one/two", func(w http.ResponseWriter, r *http.Request) {
    91  		w.Write([]byte("Two"))
    92  	})
    93  	r.Get("/one/two/three", func(w http.ResponseWriter, r *http.Request) {
    94  		w.Write([]byte("Three"))
    95  	})
    96  	r.Get("/four-four", func(w http.ResponseWriter, r *http.Request) {
    97  		w.Write([]byte("Four"))
    98  	})
    99  	r.Get("/five-five/five-five", func(w http.ResponseWriter, r *http.Request) {
   100  		w.Write([]byte("Five"))
   101  	})
   102  	r.Get("/six_six", func(w http.ResponseWriter, r *http.Request) {
   103  		w.Write([]byte("Six"))
   104  	})
   105  	r.Get("/seven_", func(w http.ResponseWriter, r *http.Request) {
   106  		w.Write([]byte("Seven"))
   107  	})
   108  	go func() {
   109  		err := r.Run()
   110  		if err != nil && err != http.ErrServerClosed {
   111  			assert.NoError(err)
   112  		}
   113  	}()
   114  	<-time.After(time.Millisecond * 200)
   115  	sendTestRequests(assert, []testRequest{
   116  		{
   117  			Path: "http://localhost:8080/",
   118  			Body: "Root",
   119  		},
   120  		{
   121  			Path: "http://localhost:8080/one",
   122  			Body: "One",
   123  		},
   124  		{
   125  			Path: "http://localhost:8080/one/two",
   126  			Body: "Two",
   127  		},
   128  		{
   129  			Path: "http://localhost:8080/one/two/three",
   130  			Body: "Three",
   131  		},
   132  		{
   133  			Path: "http://localhost:8080/four-four",
   134  			Body: "Four",
   135  		},
   136  		{
   137  			Path: "http://localhost:8080/five-five/five-five",
   138  			Body: "Five",
   139  		},
   140  		{
   141  			Path: "http://localhost:8080/six_six",
   142  			Body: "Six",
   143  		},
   144  		{
   145  			Path: "http://localhost:8080/seven_",
   146  			Body: "Seven",
   147  		},
   148  		{
   149  			Path:       "http://localhost:8080/one/two/three/four",
   150  			StatusCode: http.StatusNotFound,
   151  			Body:       "404 page not found\n",
   152  		},
   153  	})
   154  	r.Shutdown(context.Background())
   155  	<-time.After(time.Millisecond * 200)
   156  }
   157  
   158  func TestAddPriority(t *testing.T) {
   159  	assert := assert.New(t)
   160  	r := New()
   161  	r.Get("/", func(w http.ResponseWriter, r *http.Request) {
   162  		w.Write([]byte("Root"))
   163  	})
   164  	r.Get("/{a}", func(w http.ResponseWriter, r *http.Request) {
   165  		w.Write([]byte("a"))
   166  	}).AddPriority(100)
   167  	r.Get("/{a}/{*:b}", func(w http.ResponseWriter, r *http.Request) {
   168  		w.Write([]byte("a|b"))
   169  	})
   170  	go func() {
   171  		err := r.Run()
   172  		if err != nil && err != http.ErrServerClosed {
   173  			assert.NoError(err)
   174  		}
   175  	}()
   176  	<-time.After(time.Millisecond * 200)
   177  	sendTestRequests(assert, []testRequest{
   178  		{
   179  			Path: "http://localhost:8080/",
   180  			Body: "Root",
   181  		},
   182  		{
   183  			Path: "http://localhost:8080/one",
   184  			Body: "a",
   185  		},
   186  		{
   187  			Path: "http://localhost:8080/one/two",
   188  			Body: "a|b",
   189  		},
   190  		{
   191  			Path: "http://localhost:8080/one/two/three",
   192  			Body: "a|b",
   193  		},
   194  	})
   195  	r.Shutdown(context.Background())
   196  	<-time.After(time.Millisecond * 200)
   197  
   198  	r = New()
   199  	r.Get("/", func(w http.ResponseWriter, r *http.Request) {
   200  		w.Write([]byte("Root"))
   201  	})
   202  	r.Get("/{a}", func(w http.ResponseWriter, r *http.Request) {
   203  		w.Write([]byte("a"))
   204  	})
   205  	r.Get("/{a}/{*:b}", func(w http.ResponseWriter, r *http.Request) {
   206  		w.Write([]byte("a|b"))
   207  	})
   208  	go func() {
   209  		err := r.Run()
   210  		if err != nil && err != http.ErrServerClosed {
   211  			assert.NoError(err)
   212  		}
   213  	}()
   214  	<-time.After(time.Millisecond * 200)
   215  	sendTestRequests(assert, []testRequest{
   216  		{
   217  			Path: "http://localhost:8080/",
   218  			Body: "Root",
   219  		},
   220  		{
   221  			Path: "http://localhost:8080/one",
   222  			Body: "a|b",
   223  		},
   224  		{
   225  			Path: "http://localhost:8080/one/two",
   226  			Body: "a|b",
   227  		},
   228  		{
   229  			Path: "http://localhost:8080/one/two/three",
   230  			Body: "a|b",
   231  		},
   232  	})
   233  	r.Shutdown(context.Background())
   234  	<-time.After(time.Millisecond * 200)
   235  }
   236  
   237  func TestBasicMethodRoute(t *testing.T) {
   238  	assert := assert.New(t)
   239  	r := New()
   240  	r.Get("/get", func(w http.ResponseWriter, r *http.Request) {
   241  		w.Write([]byte("Get"))
   242  	})
   243  	r.Post("/post", func(w http.ResponseWriter, r *http.Request) {
   244  		w.Write([]byte("Post"))
   245  	})
   246  	r.Put("/put", func(w http.ResponseWriter, r *http.Request) {
   247  		w.Write([]byte("Put"))
   248  	})
   249  	r.Patch("/patch", func(w http.ResponseWriter, r *http.Request) {
   250  		w.Write([]byte("Patch"))
   251  	})
   252  	r.Delete("/delete", func(w http.ResponseWriter, r *http.Request) {
   253  		w.Write([]byte("Delete"))
   254  	})
   255  	r.Options("/options", func(w http.ResponseWriter, r *http.Request) {
   256  		w.Write([]byte("Options"))
   257  	})
   258  	go func() {
   259  		err := r.Run()
   260  		if err != nil && err != http.ErrServerClosed {
   261  			assert.NoError(err)
   262  		}
   263  	}()
   264  	<-time.After(time.Millisecond * 200)
   265  	sendTestRequests(assert, []testRequest{
   266  		{
   267  			Path: "http://localhost:8080/get",
   268  			Body: "Get",
   269  		},
   270  		{
   271  			Path:   "http://localhost:8080/post",
   272  			Method: methodPost,
   273  			Body:   "Post",
   274  		},
   275  		{
   276  			Path:   "http://localhost:8080/put",
   277  			Method: methodPut,
   278  			Body:   "Put",
   279  		},
   280  		{
   281  			Path:   "http://localhost:8080/patch",
   282  			Method: methodPatch,
   283  			Body:   "Patch",
   284  		},
   285  		{
   286  			Path:   "http://localhost:8080/delete",
   287  			Method: methodDelete,
   288  			Body:   "Delete",
   289  		},
   290  		{
   291  			Path:   "http://localhost:8080/options",
   292  			Method: methodOptions,
   293  			Body:   "Options",
   294  		},
   295  		{
   296  			Path:       "http://localhost:8080/post",
   297  			Method:     methodGet,
   298  			StatusCode: http.StatusNotFound,
   299  			Body:       "404 page not found\n",
   300  		},
   301  	})
   302  	r.Shutdown(context.Background())
   303  	<-time.After(time.Millisecond * 200)
   304  }
   305  
   306  func TestParamRoute(t *testing.T) {
   307  	assert := assert.New(t)
   308  	r := New()
   309  	r.Get("/", func(w http.ResponseWriter, r *http.Request) {
   310  		w.Write([]byte("Root"))
   311  	})
   312  	r.Get("/{one}", func(w http.ResponseWriter, r *http.Request) {
   313  		w.Write([]byte(varsToString(Vars(r))))
   314  	})
   315  	r.Get("/{one}/{two}", func(w http.ResponseWriter, r *http.Request) {
   316  		w.Write([]byte(varsToString(Vars(r))))
   317  	})
   318  	r.Get("/{one}/{two}/{three}", func(w http.ResponseWriter, r *http.Request) {
   319  		w.Write([]byte(varsToString(Vars(r))))
   320  	})
   321  	go func() {
   322  		err := r.Run()
   323  		if err != nil && err != http.ErrServerClosed {
   324  			assert.NoError(err)
   325  		}
   326  	}()
   327  	<-time.After(time.Millisecond * 200)
   328  	sendTestRequests(assert, []testRequest{
   329  		{
   330  			Path: "http://localhost:8080/",
   331  			Body: "Root",
   332  		},
   333  		{
   334  			Path: "http://localhost:8080/1",
   335  			Body: "1",
   336  		},
   337  		{
   338  			Path: "http://localhost:8080/1/2",
   339  			Body: "1,2",
   340  		},
   341  		{
   342  			Path: "http://localhost:8080/1/2/3",
   343  			Body: "1,2,3",
   344  		},
   345  		{
   346  			Path:       "http://localhost:8080/1/2/3/4",
   347  			StatusCode: http.StatusNotFound,
   348  			Body:       "404 page not found\n",
   349  		},
   350  	})
   351  	r.Shutdown(context.Background())
   352  	<-time.After(time.Millisecond * 200)
   353  }
   354  
   355  func TestOptionalParamRoute(t *testing.T) {
   356  	assert := assert.New(t)
   357  	r := New()
   358  	r.Get("/{one?}", func(w http.ResponseWriter, r *http.Request) {
   359  		w.Write([]byte("one:" + varsToString(Vars(r))))
   360  	})
   361  	r.Get("/{one}/{two?}", func(w http.ResponseWriter, r *http.Request) {
   362  		w.Write([]byte("two:" + varsToString(Vars(r))))
   363  	})
   364  	r.Get("/{one}/{two}/{three?}", func(w http.ResponseWriter, r *http.Request) {
   365  		w.Write([]byte("three:" + varsToString(Vars(r))))
   366  	})
   367  	go func() {
   368  		err := r.Run()
   369  		if err != nil && err != http.ErrServerClosed {
   370  			assert.NoError(err)
   371  		}
   372  	}()
   373  	<-time.After(time.Millisecond * 200)
   374  	sendTestRequests(assert, []testRequest{
   375  		{
   376  			Path: "http://localhost:8080/",
   377  			Body: "one:",
   378  		},
   379  		{
   380  			Path: "http://localhost:8080/1",
   381  			Body: "two:,1",
   382  		},
   383  		{
   384  			Path: "http://localhost:8080/1/2",
   385  			Body: "three:,1,2",
   386  		},
   387  		{
   388  			Path: "http://localhost:8080/1/2/3",
   389  			Body: "three:1,2,3",
   390  		},
   391  		{
   392  			Path:       "http://localhost:8080/1/2/3/4",
   393  			StatusCode: http.StatusNotFound,
   394  			Body:       "404 page not found\n",
   395  		},
   396  	})
   397  	r.Shutdown(context.Background())
   398  	<-time.After(time.Millisecond * 200)
   399  }
   400  
   401  func TestOptionalParamRoute2(t *testing.T) {
   402  	assert := assert.New(t)
   403  	r := New()
   404  	r.Get("/fixed/{one?}", func(w http.ResponseWriter, r *http.Request) {
   405  		w.Write([]byte("one:" + varsToString(Vars(r))))
   406  	})
   407  	r.Get("/fixed/{one}/fixed", func(w http.ResponseWriter, r *http.Request) {
   408  		w.Write([]byte("one/fixed:" + varsToString(Vars(r))))
   409  	})
   410  	r.Get("/fixed/{one}/fixed/{two?}", func(w http.ResponseWriter, r *http.Request) {
   411  		w.Write([]byte("two:" + varsToString(Vars(r))))
   412  	})
   413  	r.Get("/fixed/{one}/fixed/{two}/fixed", func(w http.ResponseWriter, r *http.Request) {
   414  		w.Write([]byte("two/fixed:" + varsToString(Vars(r))))
   415  	})
   416  	r.Get("/fixed/{one}/fixed/{two}/fixed/{three?}", func(w http.ResponseWriter, r *http.Request) {
   417  		w.Write([]byte("three:" + varsToString(Vars(r))))
   418  	})
   419  	go func() {
   420  		err := r.Run()
   421  		if err != nil && err != http.ErrServerClosed {
   422  			assert.NoError(err)
   423  		}
   424  	}()
   425  	<-time.After(time.Millisecond * 200)
   426  	sendTestRequests(assert, []testRequest{
   427  		{
   428  			Path:       "http://localhost:8080/",
   429  			StatusCode: http.StatusNotFound,
   430  			Body:       "404 page not found\n",
   431  		},
   432  		{
   433  			Path: "http://localhost:8080/fixed",
   434  			Body: "one:",
   435  		},
   436  		{
   437  			Path: "http://localhost:8080/fixed/1",
   438  			Body: "one:1",
   439  		},
   440  		{
   441  			Path: "http://localhost:8080/fixed/1/fixed",
   442  			Body: "two:,1",
   443  		},
   444  		{
   445  			Path: "http://localhost:8080/fixed/1/fixed/2",
   446  			Body: "two:1,2",
   447  		},
   448  		{
   449  			Path: "http://localhost:8080/fixed/1/fixed/2/fixed",
   450  			Body: "three:,1,2",
   451  		},
   452  		{
   453  			Path: "http://localhost:8080/fixed/1/fixed/2/fixed/3",
   454  			Body: "three:1,2,3",
   455  		},
   456  		{
   457  			Path:       "http://localhost:8080/fixed/1/fixed/2/fixed/3/fixed",
   458  			StatusCode: http.StatusNotFound,
   459  			Body:       "404 page not found\n",
   460  		},
   461  	})
   462  	r.Shutdown(context.Background())
   463  	<-time.After(time.Millisecond * 200)
   464  }
   465  
   466  func TestRegExParamRoute(t *testing.T) {
   467  	assert := assert.New(t)
   468  	r := New()
   469  	r.Rule("a", "[A-Za-z]+")
   470  	r.Get("/", func(w http.ResponseWriter, r *http.Request) {
   471  		w.Write([]byte("Root"))
   472  	})
   473  	r.Get("/{i:one}", func(w http.ResponseWriter, r *http.Request) {
   474  		w.Write([]byte("i|one:" + varsToString(Vars(r))))
   475  	})
   476  	r.Get("/{a:one}", func(w http.ResponseWriter, r *http.Request) {
   477  		w.Write([]byte("a|one:" + varsToString(Vars(r))))
   478  	})
   479  	r.Get("/{i:one}/{i:two}", func(w http.ResponseWriter, r *http.Request) {
   480  		w.Write([]byte("i|two:" + varsToString(Vars(r))))
   481  	})
   482  	r.Get("/{i:one}/{a:two}", func(w http.ResponseWriter, r *http.Request) {
   483  		w.Write([]byte("a|two:" + varsToString(Vars(r))))
   484  	})
   485  	r.Get("/{i:one}/{a:two}/{i:three}", func(w http.ResponseWriter, r *http.Request) {
   486  		w.Write([]byte("i|three:" + varsToString(Vars(r))))
   487  	})
   488  	r.Get("/{i:one}/{a:two}/{a:three}", func(w http.ResponseWriter, r *http.Request) {
   489  		w.Write([]byte("a|three:" + varsToString(Vars(r))))
   490  	})
   491  	go func() {
   492  		err := r.Run()
   493  		if err != nil && err != http.ErrServerClosed {
   494  			assert.NoError(err)
   495  		}
   496  	}()
   497  	<-time.After(time.Millisecond * 200)
   498  	sendTestRequests(assert, []testRequest{
   499  		{
   500  			Path: "http://localhost:8080/",
   501  			Body: "Root",
   502  		},
   503  		{
   504  			Path: "http://localhost:8080/1",
   505  			Body: "i|one:1",
   506  		},
   507  		{
   508  			Path: "http://localhost:8080/a",
   509  			Body: "a|one:a",
   510  		},
   511  		{
   512  			Path: "http://localhost:8080/1/2",
   513  			Body: "i|two:1,2",
   514  		},
   515  		{
   516  			Path: "http://localhost:8080/1/b",
   517  			Body: "a|two:1,b",
   518  		},
   519  		{
   520  			Path: "http://localhost:8080/1/b/3",
   521  			Body: "i|three:1,3,b",
   522  		},
   523  		{
   524  			Path: "http://localhost:8080/1/b/c",
   525  			Body: "a|three:1,b,c",
   526  		},
   527  		{
   528  			Path:       "http://localhost:8080/測試",
   529  			StatusCode: http.StatusNotFound,
   530  			Body:       "404 page not found\n",
   531  		},
   532  		{
   533  			Path:       "http://localhost:8080/a/2",
   534  			StatusCode: http.StatusNotFound,
   535  			Body:       "404 page not found\n",
   536  		},
   537  	})
   538  	r.Shutdown(context.Background())
   539  	<-time.After(time.Millisecond * 200)
   540  }
   541  
   542  func TestOptionalRegExParamRoute(t *testing.T) {
   543  	assert := assert.New(t)
   544  	r := New()
   545  	r.Get("/{i:one?}", func(w http.ResponseWriter, r *http.Request) {
   546  		w.Write([]byte("one:" + varsToString(Vars(r))))
   547  	})
   548  	r.Get("/{i:one}/{i:two?}", func(w http.ResponseWriter, r *http.Request) {
   549  		w.Write([]byte("two:" + varsToString(Vars(r))))
   550  	})
   551  	r.Get("/{i:one}/{i:two}/{i:three?}", func(w http.ResponseWriter, r *http.Request) {
   552  		w.Write([]byte("three:" + varsToString(Vars(r))))
   553  	})
   554  	go func() {
   555  		err := r.Run()
   556  		if err != nil && err != http.ErrServerClosed {
   557  			assert.NoError(err)
   558  		}
   559  	}()
   560  	<-time.After(time.Millisecond * 200)
   561  	sendTestRequests(assert, []testRequest{
   562  		{
   563  			Path: "http://localhost:8080/",
   564  			Body: "one:",
   565  		},
   566  		{
   567  			Path: "http://localhost:8080/1",
   568  			Body: "two:,1",
   569  		},
   570  		{
   571  			Path: "http://localhost:8080/1/2",
   572  			Body: "three:,1,2",
   573  		},
   574  		{
   575  			Path: "http://localhost:8080/1/2/3",
   576  			Body: "three:1,2,3",
   577  		},
   578  		{
   579  			Path:       "http://localhost:8080/a",
   580  			StatusCode: http.StatusNotFound,
   581  			Body:       "404 page not found\n",
   582  		},
   583  		{
   584  			Path:       "http://localhost:8080/a/2",
   585  			StatusCode: http.StatusNotFound,
   586  			Body:       "404 page not found\n",
   587  		},
   588  		{
   589  			Path:       "http://localhost:8080/a/b/3",
   590  			StatusCode: http.StatusNotFound,
   591  			Body:       "404 page not found\n",
   592  		},
   593  		{
   594  			Path:       "http://localhost:8080/a/b/c/d",
   595  			StatusCode: http.StatusNotFound,
   596  			Body:       "404 page not found\n",
   597  		},
   598  	})
   599  	r.Shutdown(context.Background())
   600  	<-time.After(time.Millisecond * 200)
   601  }
   602  
   603  func TestAnyRegExParamRoute(t *testing.T) {
   604  	assert := assert.New(t)
   605  	r := New()
   606  	r.Get("/", func(w http.ResponseWriter, r *http.Request) {
   607  		w.Write([]byte("Root"))
   608  	})
   609  	r.Get("/{*:one}", func(w http.ResponseWriter, r *http.Request) {
   610  		w.Write([]byte("*|one:" + varsToString(Vars(r))))
   611  	})
   612  	r.Get("/two", func(w http.ResponseWriter, r *http.Request) {
   613  		w.Write([]byte("two:" + varsToString(Vars(r))))
   614  	})
   615  	r.Get("/two/{*:three}", func(w http.ResponseWriter, r *http.Request) {
   616  		w.Write([]byte("two,*|three:" + varsToString(Vars(r))))
   617  	})
   618  	r.Get("/{one}/two/{*:three}", func(w http.ResponseWriter, r *http.Request) {
   619  		w.Write([]byte("*|three:" + varsToString(Vars(r))))
   620  	})
   621  	r.Get("/{one}/two/three/four/{*:five?}", func(w http.ResponseWriter, r *http.Request) {
   622  		w.Write([]byte("*|five:" + varsToString(Vars(r))))
   623  	})
   624  	go func() {
   625  		err := r.Run()
   626  		if err != nil && err != http.ErrServerClosed {
   627  			assert.NoError(err)
   628  		}
   629  	}()
   630  	<-time.After(time.Millisecond * 200)
   631  	sendTestRequests(assert, []testRequest{
   632  		{
   633  			Path: "http://localhost:8080/",
   634  			Body: "Root",
   635  		},
   636  		{
   637  			Path: "http://localhost:8080/one",
   638  			Body: "*|one:one",
   639  		},
   640  		{
   641  			Path: "http://localhost:8080/two",
   642  			Body: "two:",
   643  		},
   644  		{
   645  			Path: "http://localhost:8080/two/three",
   646  			Body: "two,*|three:three",
   647  		},
   648  		{
   649  			Path: "http://localhost:8080/one/two/three",
   650  			Body: "*|three:one,three",
   651  		},
   652  		{
   653  			Path: "http://localhost:8080/one/two/three/three/three",
   654  			Body: "*|three:one,three/three/three",
   655  		},
   656  		{
   657  			Path: "http://localhost:8080/one/two/three/four",
   658  			Body: "*|five:,one",
   659  		},
   660  		{
   661  			Path: "http://localhost:8080/1/two/three/four/5",
   662  			Body: "*|five:1,5",
   663  		},
   664  		{
   665  			Path: "http://localhost:8080/1/two/three/four/5/6",
   666  			Body: "*|five:1,5/6",
   667  		},
   668  	})
   669  	r.Shutdown(context.Background())
   670  	<-time.After(time.Millisecond * 200)
   671  }
   672  
   673  func TestPrefixSuffixRoute(t *testing.T) {
   674  	assert := assert.New(t)
   675  	r := New()
   676  	r.Get("/", func(w http.ResponseWriter, r *http.Request) {
   677  		w.Write([]byte("Root"))
   678  	})
   679  	r.Get("/{one}.sub", func(w http.ResponseWriter, r *http.Request) {
   680  		w.Write([]byte(varsToString(Vars(r))))
   681  	})
   682  	r.Get("/pre.{one}.suf", func(w http.ResponseWriter, r *http.Request) {
   683  		w.Write([]byte(varsToString(Vars(r))))
   684  	})
   685  	r.Get("/pre.{one}.suf/pre.{two}.suf", func(w http.ResponseWriter, r *http.Request) {
   686  		w.Write([]byte(varsToString(Vars(r))))
   687  	})
   688  	go func() {
   689  		err := r.Run()
   690  		if err != nil && err != http.ErrServerClosed {
   691  			assert.NoError(err)
   692  		}
   693  	}()
   694  	<-time.After(time.Millisecond * 200)
   695  	sendTestRequests(assert, []testRequest{
   696  		{
   697  			Path: "http://localhost:8080/",
   698  			Body: "Root",
   699  		},
   700  		{
   701  			Path: "http://localhost:8080/1.sub",
   702  			Body: "1",
   703  		},
   704  		{
   705  			Path: "http://localhost:8080/pre.1.suf",
   706  			Body: "1",
   707  		},
   708  		{
   709  			Path: "http://localhost:8080/pre.1.suf/pre.2.suf",
   710  			Body: "1,2",
   711  		},
   712  		{
   713  			Path:       "http://localhost:8080/1",
   714  			StatusCode: http.StatusNotFound,
   715  			Body:       "404 page not found\n",
   716  		},
   717  		{
   718  			Path:       "http://localhost:8080/.sub",
   719  			StatusCode: http.StatusNotFound,
   720  			Body:       "404 page not found\n",
   721  		},
   722  		{
   723  			Path:       "http://localhost:8080/pre..suf",
   724  			StatusCode: http.StatusNotFound,
   725  			Body:       "404 page not found\n",
   726  		},
   727  		{
   728  			Path:       "http://localhost:8080/pre..suf/pre.1.suf",
   729  			StatusCode: http.StatusNotFound,
   730  			Body:       "404 page not found\n",
   731  		},
   732  		{
   733  			Path:       "http://localhost:8080/pre..suf/pre..suf",
   734  			StatusCode: http.StatusNotFound,
   735  			Body:       "404 page not found\n",
   736  		},
   737  	})
   738  	r.Shutdown(context.Background())
   739  	<-time.After(time.Millisecond * 200)
   740  }
   741  
   742  func TestOptionalPrefixSuffixRoute(t *testing.T) {
   743  	assert := assert.New(t)
   744  	r := New()
   745  	r.Get("/", func(w http.ResponseWriter, r *http.Request) {
   746  		w.Write([]byte("Root"))
   747  	})
   748  	r.Get("/{one?}.sub", func(w http.ResponseWriter, r *http.Request) {
   749  		w.Write([]byte(varsToString(Vars(r))))
   750  	})
   751  	r.Get("/pre.{one?}.suf", func(w http.ResponseWriter, r *http.Request) {
   752  		w.Write([]byte(varsToString(Vars(r))))
   753  	})
   754  	r.Get("/pre.{one?}.suf/pre.{two?}.suf", func(w http.ResponseWriter, r *http.Request) {
   755  		w.Write([]byte(varsToString(Vars(r))))
   756  	})
   757  	r.Get("/pre.{one}.suf/pre.{two}.suf/pre.{three}.suf/pre.{four?}.suf", func(w http.ResponseWriter, r *http.Request) {
   758  		w.Write([]byte(varsToString(Vars(r))))
   759  	})
   760  	go func() {
   761  		err := r.Run()
   762  		if err != nil && err != http.ErrServerClosed {
   763  			assert.NoError(err)
   764  		}
   765  	}()
   766  	<-time.After(time.Millisecond * 200)
   767  	sendTestRequests(assert, []testRequest{
   768  		{
   769  			Path: "http://localhost:8080/",
   770  			Body: "Root",
   771  		},
   772  		{
   773  			Path: "http://localhost:8080/1.sub",
   774  			Body: "1",
   775  		},
   776  		{
   777  			Path: "http://localhost:8080/.sub",
   778  			Body: "",
   779  		},
   780  		{
   781  			Path: "http://localhost:8080/pre.1.suf",
   782  			Body: ",1",
   783  		},
   784  		{
   785  			Path: "http://localhost:8080/pre..suf",
   786  			Body: "",
   787  		},
   788  		{
   789  			Path: "http://localhost:8080/pre.1.suf/pre.2.suf",
   790  			Body: "1,2",
   791  		},
   792  		{
   793  			Path: "http://localhost:8080/pre..suf/pre..suf",
   794  			Body: ",",
   795  		},
   796  		{
   797  			Path: "http://localhost:8080/pre.1.suf/pre.2.suf/pre.3.suf/pre..suf",
   798  			Body: ",1,2,3",
   799  		},
   800  		{
   801  			Path: "http://localhost:8080/pre.1.suf/pre.2.suf/pre.3.suf/pre.4.suf",
   802  			Body: "1,2,3,4",
   803  		},
   804  		{
   805  			Path:       "http://localhost:8080/1",
   806  			StatusCode: http.StatusNotFound,
   807  			Body:       "404 page not found\n",
   808  		},
   809  		{
   810  			Path:       "http://localhost:8080/1/2",
   811  			StatusCode: http.StatusNotFound,
   812  			Body:       "404 page not found\n",
   813  		},
   814  		{
   815  			Path:       "http://localhost:8080/pre.1",
   816  			StatusCode: http.StatusNotFound,
   817  			Body:       "404 page not found\n",
   818  		},
   819  		{
   820  			Path:       "http://localhost:8080/pre.1/pre.2.suf",
   821  			StatusCode: http.StatusNotFound,
   822  			Body:       "404 page not found\n",
   823  		},
   824  	})
   825  	r.Shutdown(context.Background())
   826  	<-time.After(time.Millisecond * 200)
   827  }
   828  
   829  func TestPrefixSuffixRegExRoute(t *testing.T) {
   830  	assert := assert.New(t)
   831  	r := New()
   832  	r.Rule("a", "[A-Za-z]+")
   833  	r.Get("/", func(w http.ResponseWriter, r *http.Request) {
   834  		w.Write([]byte("Root"))
   835  	})
   836  	r.Get("/{a:one?}.sub", func(w http.ResponseWriter, r *http.Request) {
   837  		w.Write([]byte(varsToString(Vars(r))))
   838  	})
   839  	r.Get("/pre.{a:one?}.suf", func(w http.ResponseWriter, r *http.Request) {
   840  		w.Write([]byte(varsToString(Vars(r))))
   841  	})
   842  	r.Get("/foo.{a:one}.bar", func(w http.ResponseWriter, r *http.Request) {
   843  		w.Write([]byte(varsToString(Vars(r))))
   844  	})
   845  	go func() {
   846  		err := r.Run()
   847  		if err != nil && err != http.ErrServerClosed {
   848  			assert.NoError(err)
   849  		}
   850  	}()
   851  	<-time.After(time.Millisecond * 200)
   852  	sendTestRequests(assert, []testRequest{
   853  		{
   854  			Path: "http://localhost:8080/",
   855  			Body: "Root",
   856  		},
   857  		{
   858  			Path: "http://localhost:8080/a.sub",
   859  			Body: "a",
   860  		},
   861  		{
   862  			Path: "http://localhost:8080/.sub",
   863  			Body: "",
   864  		},
   865  		{
   866  			Path: "http://localhost:8080/pre.a.suf",
   867  			Body: "a",
   868  		},
   869  		{
   870  			Path: "http://localhost:8080/pre..suf",
   871  			Body: "",
   872  		},
   873  		{
   874  			Path: "http://localhost:8080/foo.a.bar",
   875  			Body: "a",
   876  		},
   877  		{
   878  			Path:       "http://localhost:8080/1",
   879  			StatusCode: http.StatusNotFound,
   880  			Body:       "404 page not found\n",
   881  		},
   882  		{
   883  			Path:       "http://localhost:8080/1.sub",
   884  			StatusCode: http.StatusNotFound,
   885  			Body:       "404 page not found\n",
   886  		},
   887  		{
   888  			Path:       "http://localhost:8080/pre.1.suf",
   889  			StatusCode: http.StatusNotFound,
   890  			Body:       "404 page not found\n",
   891  		},
   892  		{
   893  			Path:       "http://localhost:8080/foo..bar",
   894  			StatusCode: http.StatusNotFound,
   895  			Body:       "404 page not found\n",
   896  		},
   897  		{
   898  			Path:       "http://localhost:8080/foo.1.bar",
   899  			StatusCode: http.StatusNotFound,
   900  			Body:       "404 page not found\n",
   901  		},
   902  	})
   903  	r.Shutdown(context.Background())
   904  	<-time.After(time.Millisecond * 200)
   905  }
   906  
   907  func TestLookbehindRoute(t *testing.T) {
   908  	assert := assert.New(t)
   909  	r := New()
   910  	r.Get("/", func(w http.ResponseWriter, r *http.Request) {
   911  		w.Write([]byte("Root"))
   912  	})
   913  	r.Rule("e", "(?:.html)")
   914  	r.Get("/detail{e:one}", func(w http.ResponseWriter, r *http.Request) {
   915  		w.Write([]byte(varsToString(Vars(r))))
   916  	})
   917  	r.Rule("u", "(?:.html)?")
   918  	r.Get("/user{u:one}", func(w http.ResponseWriter, r *http.Request) {
   919  		w.Write([]byte(varsToString(Vars(r))))
   920  	})
   921  	go func() {
   922  		err := r.Run()
   923  		if err != nil && err != http.ErrServerClosed {
   924  			assert.NoError(err)
   925  		}
   926  	}()
   927  	<-time.After(time.Millisecond * 200)
   928  	sendTestRequests(assert, []testRequest{
   929  		{
   930  			Path: "http://localhost:8080/",
   931  			Body: "Root",
   932  		},
   933  		{
   934  			Path: "http://localhost:8080/detail.html",
   935  			Body: ".html",
   936  		},
   937  		{
   938  			Path: "http://localhost:8080/user",
   939  			Body: "",
   940  		},
   941  		{
   942  			Path: "http://localhost:8080/user.html",
   943  			Body: ".html",
   944  		},
   945  		{
   946  			Path:       "http://localhost:8080/detail",
   947  			StatusCode: http.StatusNotFound,
   948  			Body:       "404 page not found\n",
   949  		},
   950  		{
   951  			Path:       "http://localhost:8080/user.htmli",
   952  			StatusCode: http.StatusNotFound,
   953  			Body:       "404 page not found\n",
   954  		},
   955  		{
   956  			Path:       "http://localhost:8080/user.htm",
   957  			StatusCode: http.StatusNotFound,
   958  			Body:       "404 page not found\n",
   959  		},
   960  	})
   961  	r.Shutdown(context.Background())
   962  	<-time.After(time.Millisecond * 200)
   963  }
   964  func TestMiddleware(t *testing.T) {
   965  	assert := assert.New(t)
   966  	r := New()
   967  	middleware := func(next http.Handler) http.Handler {
   968  		return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
   969  			rcontext.Set(r, "foo1", "bar1")
   970  			next.ServeHTTP(w, r)
   971  		})
   972  	}
   973  	middleware2 := func(next http.Handler) http.Handler {
   974  		return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
   975  			rcontext.Set(r, "foo2", "bar2")
   976  			next.ServeHTTP(w, r)
   977  		})
   978  	}
   979  	r.Get("/", middleware, middleware2, func(w http.ResponseWriter, r *http.Request) {
   980  		w.Write([]byte(rcontext.Get(r, "foo1").(string) + rcontext.Get(r, "foo2").(string)))
   981  	})
   982  	go func() {
   983  		err := r.Run()
   984  		if err != nil && err != http.ErrServerClosed {
   985  			assert.NoError(err)
   986  		}
   987  	}()
   988  	<-time.After(time.Millisecond * 200)
   989  	sendTestRequests(assert, []testRequest{
   990  		{
   991  			Path: "http://localhost:8080/",
   992  			Body: "bar1bar2",
   993  		},
   994  	})
   995  	r.Shutdown(context.Background())
   996  	<-time.After(time.Millisecond * 200)
   997  }
   998  
   999  func TestRouteGroup(t *testing.T) {
  1000  	assert := assert.New(t)
  1001  	r := New()
  1002  	handler := func(w http.ResponseWriter, r *http.Request) {
  1003  		w.Write([]byte("OK"))
  1004  	}
  1005  	v1 := r.Group("/v1")
  1006  	{
  1007  		v1.Get("/", handler)
  1008  		v1.Get("/user/{id}", handler)
  1009  		v1.Get("/post/{title?}", handler)
  1010  		v1.Get("/login", handler)
  1011  	}
  1012  	v2 := r.Group("/v2")
  1013  	{
  1014  		v2.Get("/", handler)
  1015  		v2.Get("/user/{id}", handler)
  1016  		v2.Get("/post/{title?}", handler)
  1017  		v2.Get("/login", handler)
  1018  	}
  1019  	go func() {
  1020  		err := r.Run()
  1021  		if err != nil && err != http.ErrServerClosed {
  1022  			assert.NoError(err)
  1023  		}
  1024  	}()
  1025  	<-time.After(time.Millisecond * 200)
  1026  	sendTestRequests(assert, []testRequest{
  1027  		{
  1028  			Path: "http://localhost:8080/v1/user/123",
  1029  			Body: "OK",
  1030  		},
  1031  		{
  1032  			Path: "http://localhost:8080/v1",
  1033  			Body: "OK",
  1034  		},
  1035  		{
  1036  			Path: "http://localhost:8080/v1/post",
  1037  			Body: "OK",
  1038  		},
  1039  		{
  1040  			Path: "http://localhost:8080/v1/post/1234",
  1041  			Body: "OK",
  1042  		},
  1043  		{
  1044  			Path: "http://localhost:8080/v1/login",
  1045  			Body: "OK",
  1046  		},
  1047  		{
  1048  			Path: "http://localhost:8080/v2/user/123",
  1049  			Body: "OK",
  1050  		},
  1051  		{
  1052  			Path: "http://localhost:8080/v2",
  1053  			Body: "OK",
  1054  		},
  1055  		{
  1056  			Path: "http://localhost:8080/v2/post",
  1057  			Body: "OK",
  1058  		},
  1059  		{
  1060  			Path: "http://localhost:8080/v2/post/1234",
  1061  			Body: "OK",
  1062  		},
  1063  		{
  1064  			Path: "http://localhost:8080/v2/login",
  1065  			Body: "OK",
  1066  		},
  1067  		{
  1068  			Path:       "http://localhost:8080/v1/user",
  1069  			StatusCode: http.StatusNotFound,
  1070  			Body:       "404 page not found\n",
  1071  		},
  1072  		{
  1073  			Path:       "http://localhost:8080/v1/post/123/456",
  1074  			StatusCode: http.StatusNotFound,
  1075  			Body:       "404 page not found\n",
  1076  		},
  1077  	})
  1078  	r.Shutdown(context.Background())
  1079  	<-time.After(time.Millisecond * 200)
  1080  }
  1081  
  1082  func TestRouteGroupMiddleware(t *testing.T) {
  1083  	assert := assert.New(t)
  1084  	r := New()
  1085  	handler := func(w http.ResponseWriter, r *http.Request) {
  1086  		w.Write([]byte(rcontext.Get(r, "foo1").(string) + rcontext.Get(r, "foo2").(string) + rcontext.Get(r, "foo3").(string)))
  1087  	}
  1088  	middleware := func(next http.Handler) http.Handler {
  1089  		return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  1090  			rcontext.Set(r, "foo1", "bar1")
  1091  			next.ServeHTTP(w, r)
  1092  		})
  1093  	}
  1094  	middleware2 := func(next http.Handler) http.Handler {
  1095  		return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  1096  			rcontext.Set(r, "foo2", "bar2")
  1097  			next.ServeHTTP(w, r)
  1098  		})
  1099  	}
  1100  	middleware3 := func(next http.Handler) http.Handler {
  1101  		return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  1102  			rcontext.Set(r, "foo3", "bar3")
  1103  			next.ServeHTTP(w, r)
  1104  		})
  1105  	}
  1106  	v1 := r.Group("/v1", middleware, middleware2)
  1107  	{
  1108  		v1.Get("/user/{id}", middleware3, handler)
  1109  		v1.Get("/post/{title?}", middleware3, handler)
  1110  		v1.Get("/login", middleware3, handler)
  1111  	}
  1112  	go func() {
  1113  		err := r.Run()
  1114  		if err != nil && err != http.ErrServerClosed {
  1115  			assert.NoError(err)
  1116  		}
  1117  	}()
  1118  	<-time.After(time.Millisecond * 200)
  1119  	sendTestRequests(assert, []testRequest{
  1120  		{
  1121  			Path: "http://localhost:8080/v1/user/123",
  1122  			Body: "bar1bar2bar3",
  1123  		},
  1124  		{
  1125  			Path: "http://localhost:8080/v1/post",
  1126  			Body: "bar1bar2bar3",
  1127  		},
  1128  		{
  1129  			Path: "http://localhost:8080/v1/post/1234",
  1130  			Body: "bar1bar2bar3",
  1131  		},
  1132  		{
  1133  			Path: "http://localhost:8080/v1/login",
  1134  			Body: "bar1bar2bar3",
  1135  		},
  1136  	})
  1137  	r.Shutdown(context.Background())
  1138  	<-time.After(time.Millisecond * 200)
  1139  }
  1140  
  1141  func TestGlobalMiddleware(t *testing.T) {
  1142  	assert := assert.New(t)
  1143  	r := New()
  1144  	handler := func(w http.ResponseWriter, r *http.Request) {
  1145  		w.Write([]byte(rcontext.Get(r, "foo1").(string) + rcontext.Get(r, "foo2").(string) + rcontext.Get(r, "foo3").(string)))
  1146  	}
  1147  	middleware := func(next http.Handler) http.Handler {
  1148  		return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  1149  			rcontext.Set(r, "foo1", "bar1")
  1150  			next.ServeHTTP(w, r)
  1151  		})
  1152  	}
  1153  	middleware2 := func(next http.Handler) http.Handler {
  1154  		return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  1155  			rcontext.Set(r, "foo2", "bar2")
  1156  			next.ServeHTTP(w, r)
  1157  		})
  1158  	}
  1159  	middleware3 := func(next http.Handler) http.Handler {
  1160  		return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  1161  			rcontext.Set(r, "foo3", "bar3")
  1162  			next.ServeHTTP(w, r)
  1163  		})
  1164  	}
  1165  	r.Use(middleware)
  1166  	r.Get("/", middleware2, middleware3, handler)
  1167  	v1 := r.Group("/foo", middleware2)
  1168  	{
  1169  		v1.Get("/bar", middleware3, handler)
  1170  	}
  1171  	go func() {
  1172  		err := r.Run()
  1173  		if err != nil && err != http.ErrServerClosed {
  1174  			assert.NoError(err)
  1175  		}
  1176  	}()
  1177  	<-time.After(time.Millisecond * 200)
  1178  	sendTestRequests(assert, []testRequest{
  1179  		{
  1180  			Path: "http://localhost:8080/",
  1181  			Body: "bar1bar2bar3",
  1182  		},
  1183  		{
  1184  			Path: "http://localhost:8080/foo/bar",
  1185  			Body: "bar1bar2bar3",
  1186  		},
  1187  	})
  1188  	r.Shutdown(context.Background())
  1189  	<-time.After(time.Millisecond * 200)
  1190  }
  1191  
  1192  func TestGenerateRoute(t *testing.T) {
  1193  	assert := assert.New(t)
  1194  	r := New()
  1195  	r.Get("/one", func(w http.ResponseWriter, r *http.Request) {}).Name("One")
  1196  	r.Get("/one/two", func(w http.ResponseWriter, r *http.Request) {}).Name("Two")
  1197  	r.Get("/one/two/{three}", func(w http.ResponseWriter, r *http.Request) {}).Name("Three")
  1198  	r.Get("/one/two/{three}/{four}", func(w http.ResponseWriter, r *http.Request) {}).Name("Four")
  1199  	r.Get("/one/two/{three}/{four}/{five?}", func(w http.ResponseWriter, r *http.Request) {}).Name("Five")
  1200  	r.Get("/one/two/{three}/{four}/{five?}/{s:six}", func(w http.ResponseWriter, r *http.Request) {}).Name("Six")
  1201  	go func() {
  1202  		err := r.Run()
  1203  		if err != nil && err != http.ErrServerClosed {
  1204  			assert.NoError(err)
  1205  		}
  1206  	}()
  1207  	<-time.After(time.Millisecond * 200)
  1208  	sendTestRequests(assert, []testRequest{
  1209  		{
  1210  			Path: "http://localhost:8080/one",
  1211  			Body: "",
  1212  		},
  1213  	})
  1214  	assert.Equal("/one", r.Generate("One"))
  1215  	assert.Equal("/one/two", r.Generate("Two"))
  1216  	assert.Panics(func() {
  1217  		r.Generate("Three")
  1218  	})
  1219  	assert.Equal("/one/two/1", r.Generate("Three", map[string]string{
  1220  		"three": "1",
  1221  	}))
  1222  	assert.Equal("/one/two/1/2", r.Generate("Four", map[string]string{
  1223  		"three": "1",
  1224  		"four":  "2",
  1225  	}))
  1226  	assert.Panics(func() {
  1227  		r.Generate("Five")
  1228  	})
  1229  	assert.Panics(func() {
  1230  		r.Generate("Five", map[string]string{
  1231  			"three": "1",
  1232  		})
  1233  	})
  1234  	assert.Panics(func() {
  1235  		r.Generate("Five", map[string]string{
  1236  			"three": "1",
  1237  			"four":  "2",
  1238  		})
  1239  	})
  1240  	assert.Equal("/one/two/1/2/3", r.Generate("Five", map[string]string{
  1241  		"three": "1",
  1242  		"four":  "2",
  1243  		"five":  "3",
  1244  	}))
  1245  	assert.Equal("/one/two/1/2/3/4", r.Generate("Six", map[string]string{
  1246  		"three": "1",
  1247  		"four":  "2",
  1248  		"five":  "3",
  1249  		"six":   "4",
  1250  	}))
  1251  	r.Shutdown(context.Background())
  1252  	<-time.After(time.Millisecond * 200)
  1253  }
  1254  
  1255  func TestStaticDirRoute(t *testing.T) {
  1256  	assert := assert.New(t)
  1257  	r := New()
  1258  	f, err := filepath.Abs(".")
  1259  	assert.NoError(err)
  1260  	assert.NoError(os.Chdir(f))
  1261  	r.Get("/{*:filename}", http.FileServer(http.Dir("test")))
  1262  	r.Get("/static/{*:filename}", http.StripPrefix("/static", http.FileServer(http.Dir("test"))))
  1263  	r.Get("/prefix/{*:filename}", http.StripPrefix("/prefix", http.FileServer(http.Dir("."))))
  1264  	go func() {
  1265  		err := r.Run()
  1266  		if err != nil && err != http.ErrServerClosed {
  1267  			assert.NoError(err)
  1268  		}
  1269  	}()
  1270  	<-time.After(time.Millisecond * 200)
  1271  	sendTestRequests(assert, []testRequest{
  1272  		{
  1273  			Path: "http://localhost:8080/file.txt",
  1274  			Body: "This is file.txt.",
  1275  		},
  1276  		{
  1277  			Path: "http://localhost:8080/file.txt/",
  1278  			Body: "This is file.txt.",
  1279  		},
  1280  		{
  1281  			Path: "http://localhost:8080/directory/file.txt",
  1282  			Body: "This is directory/file.txt.",
  1283  		},
  1284  		{
  1285  			Path: "http://localhost:8080/directory/file.txt/",
  1286  			Body: "This is directory/file.txt.",
  1287  		},
  1288  		{
  1289  			Path: "http://localhost:8080/static/file.txt",
  1290  			Body: "This is file.txt.",
  1291  		},
  1292  		{
  1293  			Path: "http://localhost:8080/static/file.txt/",
  1294  			Body: "This is file.txt.",
  1295  		},
  1296  		{
  1297  			Path: "http://localhost:8080/static/directory/file.txt",
  1298  			Body: "This is directory/file.txt.",
  1299  		},
  1300  		{
  1301  			Path: "http://localhost:8080/static/directory/file.txt/",
  1302  			Body: "This is directory/file.txt.",
  1303  		},
  1304  		{
  1305  			Path: "http://localhost:8080/prefix/test/file.txt",
  1306  			Body: "This is file.txt.",
  1307  		},
  1308  		{
  1309  			Path: "http://localhost:8080/prefix/test/file.txt/",
  1310  			Body: "This is file.txt.",
  1311  		},
  1312  		{
  1313  			Path: "http://localhost:8080/prefix/test/directory/file.txt",
  1314  			Body: "This is directory/file.txt.",
  1315  		},
  1316  		{
  1317  			Path: "http://localhost:8080/prefix/test/directory/file.txt/",
  1318  			Body: "This is directory/file.txt.",
  1319  		},
  1320  		{
  1321  			Path: "http://localhost:8080",
  1322  			Body: "<pre>\n<a href=\"directory/\">directory/</a>\n<a href=\"file.txt\">file.txt</a>\n<a href=\"main.go\">main.go</a>\n</pre>\n",
  1323  		},
  1324  		{
  1325  			Path: "http://localhost:8080/",
  1326  			Body: "<pre>\n<a href=\"directory/\">directory/</a>\n<a href=\"file.txt\">file.txt</a>\n<a href=\"main.go\">main.go</a>\n</pre>\n",
  1327  		},
  1328  		{
  1329  			Path: "http://localhost:8080/static",
  1330  			Body: "<pre>\n<a href=\"directory/\">directory/</a>\n<a href=\"file.txt\">file.txt</a>\n<a href=\"main.go\">main.go</a>\n</pre>\n",
  1331  		},
  1332  		{
  1333  			Path: "http://localhost:8080/static/",
  1334  			Body: "<pre>\n<a href=\"directory/\">directory/</a>\n<a href=\"file.txt\">file.txt</a>\n<a href=\"main.go\">main.go</a>\n</pre>\n",
  1335  		},
  1336  		{
  1337  			Path: "http://localhost:8080/prefix/test",
  1338  			Body: "<pre>\n<a href=\"directory/\">directory/</a>\n<a href=\"file.txt\">file.txt</a>\n<a href=\"main.go\">main.go</a>\n</pre>\n",
  1339  		},
  1340  		{
  1341  			Path: "http://localhost:8080/prefix/test/",
  1342  			Body: "<pre>\n<a href=\"directory/\">directory/</a>\n<a href=\"file.txt\">file.txt</a>\n<a href=\"main.go\">main.go</a>\n</pre>\n",
  1343  		},
  1344  		{
  1345  			Path:       "http://localhost:8080/wow.txt",
  1346  			StatusCode: http.StatusNotFound,
  1347  			Body:       "404 page not found\n",
  1348  		},
  1349  	})
  1350  	r.Shutdown(context.Background())
  1351  	<-time.After(time.Millisecond * 200)
  1352  }
  1353  
  1354  func TestServeFilesDirRoute(t *testing.T) {
  1355  	assert := assert.New(t)
  1356  	r := New()
  1357  	f, err := filepath.Abs(".")
  1358  	assert.NoError(err)
  1359  	assert.NoError(os.Chdir(f))
  1360  	r.ServeFiles("/", http.Dir("test"))
  1361  	r.ServeFiles("/static", http.Dir("test"))
  1362  	r.ServeFiles("/prefix", http.Dir("."))
  1363  	go func() {
  1364  		err := r.Run()
  1365  		if err != nil && err != http.ErrServerClosed {
  1366  			assert.NoError(err)
  1367  		}
  1368  	}()
  1369  	<-time.After(time.Millisecond * 200)
  1370  	sendTestRequests(assert, []testRequest{
  1371  		{
  1372  			Path: "http://localhost:8080/file.txt",
  1373  			Body: "This is file.txt.",
  1374  		},
  1375  		{
  1376  			Path: "http://localhost:8080/file.txt/",
  1377  			Body: "This is file.txt.",
  1378  		},
  1379  		{
  1380  			Path: "http://localhost:8080/directory/file.txt",
  1381  			Body: "This is directory/file.txt.",
  1382  		},
  1383  		{
  1384  			Path: "http://localhost:8080/directory/file.txt/",
  1385  			Body: "This is directory/file.txt.",
  1386  		},
  1387  		{
  1388  			Path: "http://localhost:8080/static/file.txt",
  1389  			Body: "This is file.txt.",
  1390  		},
  1391  		{
  1392  			Path: "http://localhost:8080/static/file.txt/",
  1393  			Body: "This is file.txt.",
  1394  		},
  1395  		{
  1396  			Path: "http://localhost:8080/static/directory/file.txt",
  1397  			Body: "This is directory/file.txt.",
  1398  		},
  1399  		{
  1400  			Path: "http://localhost:8080/static/directory/file.txt/",
  1401  			Body: "This is directory/file.txt.",
  1402  		},
  1403  		{
  1404  			Path: "http://localhost:8080/prefix/test/file.txt",
  1405  			Body: "This is file.txt.",
  1406  		},
  1407  		{
  1408  			Path: "http://localhost:8080/prefix/test/file.txt/",
  1409  			Body: "This is file.txt.",
  1410  		},
  1411  		{
  1412  			Path: "http://localhost:8080/prefix/test/directory/file.txt",
  1413  			Body: "This is directory/file.txt.",
  1414  		},
  1415  		{
  1416  			Path: "http://localhost:8080/prefix/test/directory/file.txt/",
  1417  			Body: "This is directory/file.txt.",
  1418  		},
  1419  		{
  1420  			Path: "http://localhost:8080",
  1421  			Body: "<pre>\n<a href=\"directory/\">directory/</a>\n<a href=\"file.txt\">file.txt</a>\n<a href=\"main.go\">main.go</a>\n</pre>\n",
  1422  		},
  1423  		{
  1424  			Path: "http://localhost:8080/",
  1425  			Body: "<pre>\n<a href=\"directory/\">directory/</a>\n<a href=\"file.txt\">file.txt</a>\n<a href=\"main.go\">main.go</a>\n</pre>\n",
  1426  		},
  1427  		{
  1428  			Path: "http://localhost:8080/static",
  1429  			Body: "<pre>\n<a href=\"directory/\">directory/</a>\n<a href=\"file.txt\">file.txt</a>\n<a href=\"main.go\">main.go</a>\n</pre>\n",
  1430  		},
  1431  		{
  1432  			Path: "http://localhost:8080/static/",
  1433  			Body: "<pre>\n<a href=\"directory/\">directory/</a>\n<a href=\"file.txt\">file.txt</a>\n<a href=\"main.go\">main.go</a>\n</pre>\n",
  1434  		},
  1435  		{
  1436  			Path: "http://localhost:8080/prefix/test",
  1437  			Body: "<pre>\n<a href=\"directory/\">directory/</a>\n<a href=\"file.txt\">file.txt</a>\n<a href=\"main.go\">main.go</a>\n</pre>\n",
  1438  		},
  1439  		{
  1440  			Path: "http://localhost:8080/prefix/test/",
  1441  			Body: "<pre>\n<a href=\"directory/\">directory/</a>\n<a href=\"file.txt\">file.txt</a>\n<a href=\"main.go\">main.go</a>\n</pre>\n",
  1442  		},
  1443  		{
  1444  			Path:       "http://localhost:8080/wow.txt",
  1445  			StatusCode: http.StatusNotFound,
  1446  			Body:       "404 page not found\n",
  1447  		},
  1448  	})
  1449  	r.Shutdown(context.Background())
  1450  	<-time.After(time.Millisecond * 200)
  1451  }
  1452  
  1453  func TestServeFilesRoute(t *testing.T) {
  1454  	assert := assert.New(t)
  1455  	r := New()
  1456  	f, err := filepath.Abs(".")
  1457  	assert.NoError(err)
  1458  	assert.NoError(os.Chdir(f))
  1459  	r.ServeFiles("/", "test").DirectoryListing = true
  1460  	r.ServeFiles("/static", "test").DirectoryListing = true
  1461  	r.ServeFiles("/prefix", ".").DirectoryListing = true
  1462  	r.ServeFiles("/nolisting", "test")
  1463  	go func() {
  1464  		err := r.Run()
  1465  		if err != nil && err != http.ErrServerClosed {
  1466  			assert.NoError(err)
  1467  		}
  1468  	}()
  1469  	<-time.After(time.Millisecond * 200)
  1470  	sendTestRequests(assert, []testRequest{
  1471  		{
  1472  			Path: "http://localhost:8080/file.txt",
  1473  			Body: "This is file.txt.",
  1474  		},
  1475  		{
  1476  			Path: "http://localhost:8080/file.txt/",
  1477  			Body: "This is file.txt.",
  1478  		},
  1479  		{
  1480  			Path: "http://localhost:8080/directory/file.txt",
  1481  			Body: "This is directory/file.txt.",
  1482  		},
  1483  		{
  1484  			Path: "http://localhost:8080/directory/file.txt/",
  1485  			Body: "This is directory/file.txt.",
  1486  		},
  1487  		{
  1488  			Path: "http://localhost:8080/static/file.txt",
  1489  			Body: "This is file.txt.",
  1490  		},
  1491  		{
  1492  			Path: "http://localhost:8080/static/file.txt/",
  1493  			Body: "This is file.txt.",
  1494  		},
  1495  		{
  1496  			Path: "http://localhost:8080/static/directory/file.txt",
  1497  			Body: "This is directory/file.txt.",
  1498  		},
  1499  		{
  1500  			Path: "http://localhost:8080/static/directory/file.txt/",
  1501  			Body: "This is directory/file.txt.",
  1502  		},
  1503  		{
  1504  			Path: "http://localhost:8080/prefix/test/file.txt",
  1505  			Body: "This is file.txt.",
  1506  		},
  1507  		{
  1508  			Path: "http://localhost:8080/prefix/test/file.txt/",
  1509  			Body: "This is file.txt.",
  1510  		},
  1511  		{
  1512  			Path: "http://localhost:8080/prefix/test/directory/file.txt",
  1513  			Body: "This is directory/file.txt.",
  1514  		},
  1515  		{
  1516  			Path: "http://localhost:8080/prefix/test/directory/file.txt/",
  1517  			Body: "This is directory/file.txt.",
  1518  		},
  1519  		{
  1520  			Path: "http://localhost:8080",
  1521  			Body: "<pre>\n<a href=\"directory/\">directory/</a>\n<a href=\"file.txt\">file.txt</a>\n<a href=\"main.go\">main.go</a>\n</pre>\n",
  1522  		},
  1523  		{
  1524  			Path: "http://localhost:8080/",
  1525  			Body: "<pre>\n<a href=\"directory/\">directory/</a>\n<a href=\"file.txt\">file.txt</a>\n<a href=\"main.go\">main.go</a>\n</pre>\n",
  1526  		},
  1527  		{
  1528  			Path: "http://localhost:8080/static",
  1529  			Body: "<pre>\n<a href=\"directory/\">directory/</a>\n<a href=\"file.txt\">file.txt</a>\n<a href=\"main.go\">main.go</a>\n</pre>\n",
  1530  		},
  1531  		{
  1532  			Path: "http://localhost:8080/static/",
  1533  			Body: "<pre>\n<a href=\"directory/\">directory/</a>\n<a href=\"file.txt\">file.txt</a>\n<a href=\"main.go\">main.go</a>\n</pre>\n",
  1534  		},
  1535  		{
  1536  			Path: "http://localhost:8080/prefix/test",
  1537  			Body: "<pre>\n<a href=\"directory/\">directory/</a>\n<a href=\"file.txt\">file.txt</a>\n<a href=\"main.go\">main.go</a>\n</pre>\n",
  1538  		},
  1539  		{
  1540  			Path: "http://localhost:8080/prefix/test/",
  1541  			Body: "<pre>\n<a href=\"directory/\">directory/</a>\n<a href=\"file.txt\">file.txt</a>\n<a href=\"main.go\">main.go</a>\n</pre>\n",
  1542  		},
  1543  		{
  1544  			Path: "http://localhost:8080/nolisting/file.txt",
  1545  			Body: "This is file.txt.",
  1546  		},
  1547  		{
  1548  			Path: "http://localhost:8080/nolisting/directory/file.txt",
  1549  			Body: "This is directory/file.txt.",
  1550  		},
  1551  		{
  1552  			Path:       "http://localhost:8080/wow.txt",
  1553  			StatusCode: http.StatusNotFound,
  1554  			Body:       "404 page not found\n",
  1555  		},
  1556  		{
  1557  			Path:       "http://localhost:8080/nolisting",
  1558  			StatusCode: http.StatusForbidden,
  1559  			Body:       "",
  1560  		},
  1561  		{
  1562  			Path:       "http://localhost:8080/nolisting/",
  1563  			StatusCode: http.StatusForbidden,
  1564  			Body:       "",
  1565  		},
  1566  		{
  1567  			Path:       "http://localhost:8080/nolisting/directory",
  1568  			StatusCode: http.StatusForbidden,
  1569  			Body:       "",
  1570  		},
  1571  		{
  1572  			Path:       "http://localhost:8080/nolisting/directory/",
  1573  			StatusCode: http.StatusForbidden,
  1574  			Body:       "",
  1575  		},
  1576  	})
  1577  	r.Shutdown(context.Background())
  1578  	<-time.After(time.Millisecond * 200)
  1579  }
  1580  
  1581  func TestServeFileRoute(t *testing.T) {
  1582  	assert := assert.New(t)
  1583  	r := New()
  1584  	f, err := filepath.Abs(".")
  1585  	assert.NoError(err)
  1586  	assert.NoError(os.Chdir(f))
  1587  	r.ServeFile("/one", "test/file.txt")
  1588  	r.ServeFile("/one/two", "test/directory/file.txt")
  1589  	go func() {
  1590  		err := r.Run()
  1591  		if err != nil && err != http.ErrServerClosed {
  1592  			assert.NoError(err)
  1593  		}
  1594  	}()
  1595  	<-time.After(time.Millisecond * 200)
  1596  	<-time.After(time.Millisecond * 200)
  1597  	sendTestRequests(assert, []testRequest{
  1598  		{
  1599  			Path: "http://localhost:8080/one",
  1600  			Body: "This is file.txt.",
  1601  		},
  1602  		{
  1603  			Path: "http://localhost:8080/one/",
  1604  			Body: "This is file.txt.",
  1605  		},
  1606  		{
  1607  			Path: "http://localhost:8080/one//",
  1608  			Body: "This is file.txt.",
  1609  		},
  1610  		{
  1611  			Path: "http://localhost:8080/one/two",
  1612  			Body: "This is directory/file.txt.",
  1613  		},
  1614  		{
  1615  			Path: "http://localhost:8080/one/two/",
  1616  			Body: "This is directory/file.txt.",
  1617  		},
  1618  		{
  1619  			Path: "http://localhost:8080/one/two//",
  1620  			Body: "This is directory/file.txt.",
  1621  		},
  1622  		{
  1623  			Path:       "http://localhost:8080/wow.txt",
  1624  			StatusCode: http.StatusNotFound,
  1625  			Body:       "404 page not found\n",
  1626  		},
  1627  	})
  1628  	r.Shutdown(context.Background())
  1629  	<-time.After(time.Millisecond * 200)
  1630  }
  1631  
  1632  func TestServeFilesAndStaticRoute(t *testing.T) {
  1633  	assert := assert.New(t)
  1634  	r := New()
  1635  	f, err := filepath.Abs(".")
  1636  	assert.NoError(err)
  1637  	assert.NoError(os.Chdir(f))
  1638  	r.Get("/one", func(w http.ResponseWriter, r *http.Request) {
  1639  		w.Write([]byte("One"))
  1640  	})
  1641  	r.Get("/{i:one}", func(w http.ResponseWriter, r *http.Request) {
  1642  		w.Write([]byte("{i:one}"))
  1643  	})
  1644  	r.ServeFiles("/", http.Dir("test"))
  1645  	r.ServeFiles("/resource/static", http.Dir("test"))
  1646  	r.ServeFiles("/static", http.Dir("test"))
  1647  	r.ServeFiles("/prefix", http.Dir("."))
  1648  	go func() {
  1649  		err := r.Run()
  1650  		if err != nil && err != http.ErrServerClosed {
  1651  			assert.NoError(err)
  1652  		}
  1653  	}()
  1654  	<-time.After(time.Millisecond * 200)
  1655  	sendTestRequests(assert, []testRequest{
  1656  		{
  1657  			Path: "http://localhost:8080/one",
  1658  			Body: "One",
  1659  		},
  1660  		{
  1661  			Path: "http://localhost:8080/123",
  1662  			Body: "{i:one}",
  1663  		},
  1664  		{
  1665  			Path: "http://localhost:8080/file.txt",
  1666  			Body: "This is file.txt.",
  1667  		},
  1668  		{
  1669  			Path: "http://localhost:8080/file.txt/",
  1670  			Body: "This is file.txt.",
  1671  		},
  1672  		{
  1673  			Path: "http://localhost:8080/directory/file.txt",
  1674  			Body: "This is directory/file.txt.",
  1675  		},
  1676  		{
  1677  			Path: "http://localhost:8080/directory/file.txt/",
  1678  			Body: "This is directory/file.txt.",
  1679  		},
  1680  		{
  1681  			Path: "http://localhost:8080/static/file.txt",
  1682  			Body: "This is file.txt.",
  1683  		},
  1684  		{
  1685  			Path: "http://localhost:8080/static/file.txt/",
  1686  			Body: "This is file.txt.",
  1687  		},
  1688  		{
  1689  			Path: "http://localhost:8080/static/directory/file.txt",
  1690  			Body: "This is directory/file.txt.",
  1691  		},
  1692  		{
  1693  			Path: "http://localhost:8080/static/directory/file.txt/",
  1694  			Body: "This is directory/file.txt.",
  1695  		},
  1696  		{
  1697  			Path: "http://localhost:8080/prefix/test/file.txt",
  1698  			Body: "This is file.txt.",
  1699  		},
  1700  		{
  1701  			Path: "http://localhost:8080/prefix/test/file.txt/",
  1702  			Body: "This is file.txt.",
  1703  		},
  1704  		{
  1705  			Path: "http://localhost:8080/prefix/test/directory/file.txt",
  1706  			Body: "This is directory/file.txt.",
  1707  		},
  1708  		{
  1709  			Path: "http://localhost:8080/prefix/test/directory/file.txt/",
  1710  			Body: "This is directory/file.txt.",
  1711  		},
  1712  		{
  1713  			Path: "http://localhost:8080/resource/static/file.txt",
  1714  			Body: "This is file.txt.",
  1715  		},
  1716  		{
  1717  			Path: "http://localhost:8080",
  1718  			Body: "<pre>\n<a href=\"directory/\">directory/</a>\n<a href=\"file.txt\">file.txt</a>\n<a href=\"main.go\">main.go</a>\n</pre>\n",
  1719  		},
  1720  		{
  1721  			Path: "http://localhost:8080/",
  1722  			Body: "<pre>\n<a href=\"directory/\">directory/</a>\n<a href=\"file.txt\">file.txt</a>\n<a href=\"main.go\">main.go</a>\n</pre>\n",
  1723  		},
  1724  		{
  1725  			Path: "http://localhost:8080/static",
  1726  			Body: "<pre>\n<a href=\"directory/\">directory/</a>\n<a href=\"file.txt\">file.txt</a>\n<a href=\"main.go\">main.go</a>\n</pre>\n",
  1727  		},
  1728  		{
  1729  			Path: "http://localhost:8080/static/",
  1730  			Body: "<pre>\n<a href=\"directory/\">directory/</a>\n<a href=\"file.txt\">file.txt</a>\n<a href=\"main.go\">main.go</a>\n</pre>\n",
  1731  		},
  1732  		{
  1733  			Path: "http://localhost:8080/prefix/test",
  1734  			Body: "<pre>\n<a href=\"directory/\">directory/</a>\n<a href=\"file.txt\">file.txt</a>\n<a href=\"main.go\">main.go</a>\n</pre>\n",
  1735  		},
  1736  		{
  1737  			Path: "http://localhost:8080/prefix/test/",
  1738  			Body: "<pre>\n<a href=\"directory/\">directory/</a>\n<a href=\"file.txt\">file.txt</a>\n<a href=\"main.go\">main.go</a>\n</pre>\n",
  1739  		},
  1740  		{
  1741  			Path:       "http://localhost:8080/wow.txt",
  1742  			StatusCode: http.StatusNotFound,
  1743  			Body:       "404 page not found\n",
  1744  		},
  1745  	})
  1746  	r.Shutdown(context.Background())
  1747  	<-time.After(time.Millisecond * 200)
  1748  }
  1749  
  1750  func TestTrailingSlashesRoute(t *testing.T) {
  1751  	assert := assert.New(t)
  1752  	r := New()
  1753  	r.Get("/", func(w http.ResponseWriter, r *http.Request) {
  1754  		w.Write([]byte("Root"))
  1755  	})
  1756  	r.Get("/one", func(w http.ResponseWriter, r *http.Request) {
  1757  		w.Write([]byte("One"))
  1758  	})
  1759  	r.Get("/one/two", func(w http.ResponseWriter, r *http.Request) {
  1760  		w.Write([]byte("Two"))
  1761  	})
  1762  	go func() {
  1763  		err := r.Run()
  1764  		if err != nil && err != http.ErrServerClosed {
  1765  			assert.NoError(err)
  1766  		}
  1767  	}()
  1768  	<-time.After(time.Millisecond * 200)
  1769  	sendTestRequests(assert, []testRequest{
  1770  		{
  1771  			Path: "http://localhost:8080",
  1772  			Body: "Root",
  1773  		},
  1774  		{
  1775  			Path: "http://localhost:8080/",
  1776  			Body: "Root",
  1777  		},
  1778  		{
  1779  			Path: "http://localhost:8080/one",
  1780  			Body: "One",
  1781  		},
  1782  		{
  1783  			Path: "http://localhost:8080/one/",
  1784  			Body: "One",
  1785  		},
  1786  		{
  1787  			Path: "http://localhost:8080/one/two",
  1788  			Body: "Two",
  1789  		},
  1790  		{
  1791  			Path: "http://localhost:8080/one/two/",
  1792  			Body: "Two",
  1793  		},
  1794  	})
  1795  	r.Shutdown(context.Background())
  1796  	<-time.After(time.Millisecond * 200)
  1797  }