github.com/vugu/vugu@v0.3.6-0.20240430171613-3f6f402e014b/devutil/file-server_test.go (about) 1 package devutil 2 3 import ( 4 "bytes" 5 "net/http" 6 "net/http/httptest" 7 "net/http/httputil" 8 "os" 9 "path/filepath" 10 "testing" 11 ) 12 13 func TestFileServer(t *testing.T) { 14 15 tmpDir, err := os.MkdirTemp("", "TestFileServer") 16 must(err) 17 defer os.RemoveAll(tmpDir) 18 t.Logf("Using temporary dir: %s", tmpDir) 19 20 fs := NewFileServer().SetDir(tmpDir) 21 22 // redirect /dir to /dir/ 23 err = os.Mkdir(filepath.Join(tmpDir, "dir"), 0755) 24 must(err) 25 wr := httptest.NewRecorder() 26 r, _ := http.NewRequest("GET", "/dir", nil) 27 fs.ServeHTTP(wr, r) 28 checkStatus(t, r, wr.Result(), 301) 29 checkHeader(t, r, wr.Result(), "Location", "dir/") 30 31 // should error in a sane way on /dir/ if no listings 32 wr = httptest.NewRecorder() 33 r, _ = http.NewRequest("GET", "/dir/", nil) 34 fs.ServeHTTP(wr, r) 35 checkStatus(t, r, wr.Result(), 404) 36 37 // serve index.html from /dir/ 38 must(os.WriteFile(filepath.Join(tmpDir, "dir/index.html"), []byte(`<html><body>index page here</body></html>`), 0644)) 39 wr = httptest.NewRecorder() 40 r, _ = http.NewRequest("GET", "/dir/", nil) 41 fs.ServeHTTP(wr, r) 42 checkStatus(t, r, wr.Result(), 200) 43 checkBody(t, r, wr.Result(), "index page here") 44 45 // listing for /dir/ 46 os.Remove(filepath.Join(tmpDir, "dir/index.html")) 47 must(os.WriteFile(filepath.Join(tmpDir, "dir/blerg.html"), []byte(`<html><body>blerg page here</body></html>`), 0644)) 48 fs.SetListings(true) 49 wr = httptest.NewRecorder() 50 r, _ = http.NewRequest("GET", "/dir/", nil) 51 fs.ServeHTTP(wr, r) 52 checkStatus(t, r, wr.Result(), 200) 53 checkBody(t, r, wr.Result(), "blerg.html") 54 checkHeader(t, r, wr.Result(), "Content-Type", "text/html; charset=utf-8") 55 56 fs.SetListings(false) 57 58 // /a.html should serve a.html 59 must(os.WriteFile(filepath.Join(tmpDir, "a.html"), []byte(`<html><body>a page here</body></html>`), 0644)) 60 wr = httptest.NewRecorder() 61 r, _ = http.NewRequest("GET", "/a.html", nil) 62 fs.ServeHTTP(wr, r) 63 checkStatus(t, r, wr.Result(), 200) 64 checkBody(t, r, wr.Result(), "a page here") 65 checkHeader(t, r, wr.Result(), "Content-Type", "text/html; charset=utf-8") 66 67 // /a should also serve a.html 68 wr = httptest.NewRecorder() 69 r, _ = http.NewRequest("GET", "/a", nil) 70 fs.ServeHTTP(wr, r) 71 checkStatus(t, r, wr.Result(), 200) 72 checkBody(t, r, wr.Result(), "a page here") 73 checkHeader(t, r, wr.Result(), "Content-Type", "text/html; charset=utf-8") 74 75 // not found should serve 404.html if present 76 must(os.WriteFile(filepath.Join(tmpDir, "404.html"), []byte(`<html><body>custom not found page here</body></html>`), 0644)) 77 wr = httptest.NewRecorder() 78 r, _ = http.NewRequest("GET", "/ainthere", nil) 79 fs.ServeHTTP(wr, r) 80 checkStatus(t, r, wr.Result(), 404) 81 checkBody(t, r, wr.Result(), "custom not found page here") 82 checkHeader(t, r, wr.Result(), "Content-Type", "text/html; charset=utf-8") 83 84 // default not found 85 os.Remove(filepath.Join(tmpDir, "404.html")) 86 wr = httptest.NewRecorder() 87 r, _ = http.NewRequest("GET", "/ainthere", nil) 88 fs.ServeHTTP(wr, r) 89 checkStatus(t, r, wr.Result(), 404) 90 checkBody(t, r, wr.Result(), "404 page not found") 91 92 // custom not found 93 fs.SetNotFoundHandler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 94 w.WriteHeader(403) 95 _, _ = w.Write([]byte("some other response here")) 96 })) 97 wr = httptest.NewRecorder() 98 r, _ = http.NewRequest("GET", "/ainthere", nil) 99 fs.ServeHTTP(wr, r) 100 checkStatus(t, r, wr.Result(), 403) 101 checkBody(t, r, wr.Result(), "some other response here") 102 103 } 104 105 func checkBody(t *testing.T, req *http.Request, res *http.Response, text string) { 106 b, err := httputil.DumpResponse(res, true) 107 if err != nil { 108 t.Logf("response dump failed: %v", err) 109 return 110 } 111 if !bytes.Contains(b, []byte(text)) { 112 t.Errorf("for %q expected response body to contain %q but it did not, full body: %s", req.URL.Path, text, b) 113 } 114 115 } 116 117 func checkStatus(t *testing.T, req *http.Request, res *http.Response, status int) { 118 st := res.StatusCode 119 if st != status { 120 t.Errorf("for %q expected status to be %v but got %v", req.URL.Path, status, st) 121 } 122 } 123 124 func checkHeader(t *testing.T, req *http.Request, res *http.Response, key, val string) { 125 hval := res.Header.Get(key) 126 if hval != val { 127 t.Errorf("for %q expected header %q to be %q but got %q", req.URL.Path, key, val, hval) 128 } 129 }