|
4 | 4 | "bytes"
|
5 | 5 | stdContext "context"
|
6 | 6 | "errors"
|
| 7 | + "fmt" |
7 | 8 | "io/ioutil"
|
8 | 9 | "net/http"
|
9 | 10 | "net/http/httptest"
|
@@ -59,45 +60,105 @@ func TestEcho(t *testing.T) {
|
59 | 60 | }
|
60 | 61 |
|
61 | 62 | func TestEchoStatic(t *testing.T) {
|
62 |
| - e := New() |
63 |
| - |
64 |
| - assert := assert.New(t) |
65 |
| - |
66 |
| - // OK |
67 |
| - e.Static("/images", "_fixture/images") |
68 |
| - c, b := request(http.MethodGet, "/images/walle.png", e) |
69 |
| - assert.Equal(http.StatusOK, c) |
70 |
| - assert.NotEmpty(b) |
71 |
| - |
72 |
| - // No file |
73 |
| - e.Static("/images", "_fixture/scripts") |
74 |
| - c, _ = request(http.MethodGet, "/images/bolt.png", e) |
75 |
| - assert.Equal(http.StatusNotFound, c) |
76 |
| - |
77 |
| - // Directory |
78 |
| - e.Static("/images", "_fixture/images") |
79 |
| - c, _ = request(http.MethodGet, "/images/", e) |
80 |
| - assert.Equal(http.StatusNotFound, c) |
81 |
| - |
82 |
| - // Directory Redirect |
83 |
| - e.Static("/", "_fixture") |
84 |
| - req := httptest.NewRequest(http.MethodGet, "/folder", nil) |
85 |
| - rec := httptest.NewRecorder() |
86 |
| - e.ServeHTTP(rec, req) |
87 |
| - assert.Equal(http.StatusMovedPermanently, rec.Code) |
88 |
| - assert.Equal("/folder/", rec.HeaderMap["Location"][0]) |
89 |
| - |
90 |
| - // Directory with index.html |
91 |
| - e.Static("/", "_fixture") |
92 |
| - c, r := request(http.MethodGet, "/", e) |
93 |
| - assert.Equal(http.StatusOK, c) |
94 |
| - assert.Equal(true, strings.HasPrefix(r, "<!doctype html>")) |
| 63 | + var testCases = []struct { |
| 64 | + name string |
| 65 | + givenPrefix string |
| 66 | + givenRoot string |
| 67 | + whenURL string |
| 68 | + expectStatus int |
| 69 | + expectHeaderLocation string |
| 70 | + expectBodyStartsWith string |
| 71 | + }{ |
| 72 | + { |
| 73 | + name: "ok", |
| 74 | + givenPrefix: "/images", |
| 75 | + givenRoot: "_fixture/images", |
| 76 | + whenURL: "/images/walle.png", |
| 77 | + expectStatus: http.StatusOK, |
| 78 | + expectBodyStartsWith: string([]byte{0x89, 0x50, 0x4e, 0x47}), |
| 79 | + }, |
| 80 | + { |
| 81 | + name: "No file", |
| 82 | + givenPrefix: "/images", |
| 83 | + givenRoot: "_fixture/scripts", |
| 84 | + whenURL: "/images/bolt.png", |
| 85 | + expectStatus: http.StatusNotFound, |
| 86 | + expectBodyStartsWith: "{\"message\":\"Not Found\"}\n", |
| 87 | + }, |
| 88 | + { |
| 89 | + name: "Directory", |
| 90 | + givenPrefix: "/images", |
| 91 | + givenRoot: "_fixture/images", |
| 92 | + whenURL: "/images/", |
| 93 | + expectStatus: http.StatusNotFound, |
| 94 | + expectBodyStartsWith: "{\"message\":\"Not Found\"}\n", |
| 95 | + }, |
| 96 | + { |
| 97 | + name: "Directory Redirect", |
| 98 | + givenPrefix: "/", |
| 99 | + givenRoot: "_fixture", |
| 100 | + whenURL: "/folder", |
| 101 | + expectStatus: http.StatusMovedPermanently, |
| 102 | + expectHeaderLocation: "/folder/", |
| 103 | + expectBodyStartsWith: "", |
| 104 | + }, |
| 105 | + { |
| 106 | + name: "Directory with index.html", |
| 107 | + givenPrefix: "/", |
| 108 | + givenRoot: "_fixture", |
| 109 | + whenURL: "/", |
| 110 | + expectStatus: http.StatusOK, |
| 111 | + expectBodyStartsWith: "<!doctype html>", |
| 112 | + }, |
| 113 | + { |
| 114 | + name: "Sub-directory with index.html", |
| 115 | + givenPrefix: "/", |
| 116 | + givenRoot: "_fixture", |
| 117 | + whenURL: "/folder/", |
| 118 | + expectStatus: http.StatusOK, |
| 119 | + expectBodyStartsWith: "<!doctype html>", |
| 120 | + }, |
| 121 | + { |
| 122 | + name: "do not allow directory traversal (backslash - windows separator)", |
| 123 | + givenPrefix: "/", |
| 124 | + givenRoot: "_fixture/", |
| 125 | + whenURL: `/..\\middleware/basic_auth.go`, |
| 126 | + expectStatus: http.StatusNotFound, |
| 127 | + expectBodyStartsWith: "{\"message\":\"Not Found\"}\n", |
| 128 | + }, |
| 129 | + { |
| 130 | + name: "do not allow directory traversal (slash - unix separator)", |
| 131 | + givenPrefix: "/", |
| 132 | + givenRoot: "_fixture/", |
| 133 | + whenURL: `/../middleware/basic_auth.go`, |
| 134 | + expectStatus: http.StatusNotFound, |
| 135 | + expectBodyStartsWith: "{\"message\":\"Not Found\"}\n", |
| 136 | + }, |
| 137 | + } |
95 | 138 |
|
96 |
| - // Sub-directory with index.html |
97 |
| - c, r = request(http.MethodGet, "/folder/", e) |
98 |
| - assert.Equal(http.StatusOK, c) |
99 |
| - assert.Equal(true, strings.HasPrefix(r, "<!doctype html>")) |
| 139 | + for _, tc := range testCases { |
| 140 | + t.Run(tc.name, func(t *testing.T) { |
| 141 | + e := New() |
| 142 | + e.Static(tc.givenPrefix, tc.givenRoot) |
| 143 | + req := httptest.NewRequest(http.MethodGet, tc.whenURL, nil) |
| 144 | + rec := httptest.NewRecorder() |
| 145 | + e.ServeHTTP(rec, req) |
| 146 | + assert.Equal(t, tc.expectStatus, rec.Code) |
| 147 | + body := rec.Body.String() |
| 148 | + if tc.expectBodyStartsWith != "" { |
| 149 | + assert.True(t, strings.HasPrefix(body, tc.expectBodyStartsWith)) |
| 150 | + } else { |
| 151 | + assert.Equal(t, "", body) |
| 152 | + } |
100 | 153 |
|
| 154 | + if tc.expectHeaderLocation != "" { |
| 155 | + assert.Equal(t, tc.expectHeaderLocation, rec.Result().Header["Location"][0]) |
| 156 | + } else { |
| 157 | + _, ok := rec.Result().Header["Location"] |
| 158 | + assert.False(t, ok) |
| 159 | + } |
| 160 | + }) |
| 161 | + } |
101 | 162 | }
|
102 | 163 |
|
103 | 164 | func TestEchoFile(t *testing.T) {
|
@@ -658,6 +719,69 @@ func TestEchoShutdown(t *testing.T) {
|
658 | 719 | assert.Equal(t, err.Error(), "http: Server closed")
|
659 | 720 | }
|
660 | 721 |
|
| 722 | +var listenerNetworkTests = []struct { |
| 723 | + test string |
| 724 | + network string |
| 725 | + address string |
| 726 | +}{ |
| 727 | + {"tcp ipv4 address", "tcp", "127.0.0.1:1323"}, |
| 728 | + {"tcp ipv6 address", "tcp", "[::1]:1323"}, |
| 729 | + {"tcp4 ipv4 address", "tcp4", "127.0.0.1:1323"}, |
| 730 | + {"tcp6 ipv6 address", "tcp6", "[::1]:1323"}, |
| 731 | +} |
| 732 | + |
| 733 | +func TestEchoListenerNetwork(t *testing.T) { |
| 734 | + for _, tt := range listenerNetworkTests { |
| 735 | + t.Run(tt.test, func(t *testing.T) { |
| 736 | + e := New() |
| 737 | + e.ListenerNetwork = tt.network |
| 738 | + |
| 739 | + // HandlerFunc |
| 740 | + e.GET("/ok", func(c Context) error { |
| 741 | + return c.String(http.StatusOK, "OK") |
| 742 | + }) |
| 743 | + |
| 744 | + errCh := make(chan error) |
| 745 | + |
| 746 | + go func() { |
| 747 | + errCh <- e.Start(tt.address) |
| 748 | + }() |
| 749 | + |
| 750 | + time.Sleep(200 * time.Millisecond) |
| 751 | + |
| 752 | + if resp, err := http.Get(fmt.Sprintf("http://%s/ok", tt.address)); err == nil { |
| 753 | + defer resp.Body.Close() |
| 754 | + assert.Equal(t, http.StatusOK, resp.StatusCode) |
| 755 | + |
| 756 | + if body, err := ioutil.ReadAll(resp.Body); err == nil { |
| 757 | + assert.Equal(t, "OK", string(body)) |
| 758 | + } else { |
| 759 | + assert.Fail(t, err.Error()) |
| 760 | + } |
| 761 | + |
| 762 | + } else { |
| 763 | + assert.Fail(t, err.Error()) |
| 764 | + } |
| 765 | + |
| 766 | + if err := e.Close(); err != nil { |
| 767 | + t.Fatal(err) |
| 768 | + } |
| 769 | + }) |
| 770 | + } |
| 771 | +} |
| 772 | + |
| 773 | +func TestEchoListenerNetworkInvalid(t *testing.T) { |
| 774 | + e := New() |
| 775 | + e.ListenerNetwork = "unix" |
| 776 | + |
| 777 | + // HandlerFunc |
| 778 | + e.GET("/ok", func(c Context) error { |
| 779 | + return c.String(http.StatusOK, "OK") |
| 780 | + }) |
| 781 | + |
| 782 | + assert.Equal(t, ErrInvalidListenerNetwork, e.Start(":1323")) |
| 783 | +} |
| 784 | + |
661 | 785 | func TestEchoReverse(t *testing.T) {
|
662 | 786 | assert := assert.New(t)
|
663 | 787 |
|
|
0 commit comments