package hws_test import ( "bytes" "net/http" "net/http/httptest" "os" "path/filepath" "testing" "git.haelnorr.com/h/golib/hws" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) func Test_SafeFileServer(t *testing.T) { t.Run("Nil filesystem returns error", func(t *testing.T) { handler, err := hws.SafeFileServer(nil) assert.Error(t, err) assert.Nil(t, handler) assert.Contains(t, err.Error(), "No file system provided") }) t.Run("Valid filesystem returns handler", func(t *testing.T) { fs := http.Dir(".") httpFS := http.FileSystem(fs) handler, err := hws.SafeFileServer(&httpFS) assert.NoError(t, err) assert.NotNil(t, handler) }) t.Run("Directory listing is blocked", func(t *testing.T) { // Create a temporary directory tmpDir := t.TempDir() // Create some test files testFile := filepath.Join(tmpDir, "test.txt") err := os.WriteFile(testFile, []byte("test content"), 0644) require.NoError(t, err) fs := http.Dir(tmpDir) httpFS := http.FileSystem(fs) handler, err := hws.SafeFileServer(&httpFS) require.NoError(t, err) // Try to access the directory req := httptest.NewRequest("GET", "/", nil) rr := httptest.NewRecorder() handler.ServeHTTP(rr, req) // Should return 404 for directory listing assert.Equal(t, http.StatusNotFound, rr.Code) }) t.Run("Individual files are accessible", func(t *testing.T) { // Create a temporary directory tmpDir := t.TempDir() // Create a test file testFile := filepath.Join(tmpDir, "test.txt") testContent := []byte("test content") err := os.WriteFile(testFile, testContent, 0644) require.NoError(t, err) fs := http.Dir(tmpDir) httpFS := http.FileSystem(fs) handler, err := hws.SafeFileServer(&httpFS) require.NoError(t, err) // Try to access the file req := httptest.NewRequest("GET", "/test.txt", nil) rr := httptest.NewRecorder() handler.ServeHTTP(rr, req) // Should return 200 for file access assert.Equal(t, http.StatusOK, rr.Code) assert.Equal(t, string(testContent), rr.Body.String()) }) t.Run("Non-existent file returns 404", func(t *testing.T) { tmpDir := t.TempDir() fs := http.Dir(tmpDir) httpFS := http.FileSystem(fs) handler, err := hws.SafeFileServer(&httpFS) require.NoError(t, err) req := httptest.NewRequest("GET", "/nonexistent.txt", nil) rr := httptest.NewRecorder() handler.ServeHTTP(rr, req) assert.Equal(t, http.StatusNotFound, rr.Code) }) t.Run("Subdirectory listing is blocked", func(t *testing.T) { tmpDir := t.TempDir() // Create a subdirectory subDir := filepath.Join(tmpDir, "subdir") err := os.Mkdir(subDir, 0755) require.NoError(t, err) // Create a file in the subdirectory testFile := filepath.Join(subDir, "test.txt") err = os.WriteFile(testFile, []byte("content"), 0644) require.NoError(t, err) fs := http.Dir(tmpDir) httpFS := http.FileSystem(fs) handler, err := hws.SafeFileServer(&httpFS) require.NoError(t, err) // Try to list the subdirectory req := httptest.NewRequest("GET", "/subdir/", nil) rr := httptest.NewRecorder() handler.ServeHTTP(rr, req) // Should return 404 for subdirectory listing assert.Equal(t, http.StatusNotFound, rr.Code) }) t.Run("Files in subdirectories are accessible", func(t *testing.T) { tmpDir := t.TempDir() // Create a subdirectory subDir := filepath.Join(tmpDir, "subdir") err := os.Mkdir(subDir, 0755) require.NoError(t, err) // Create a file in the subdirectory testFile := filepath.Join(subDir, "test.txt") testContent := []byte("subdirectory content") err = os.WriteFile(testFile, testContent, 0644) require.NoError(t, err) fs := http.Dir(tmpDir) httpFS := http.FileSystem(fs) handler, err := hws.SafeFileServer(&httpFS) require.NoError(t, err) // Try to access the file in the subdirectory req := httptest.NewRequest("GET", "/subdir/test.txt", nil) rr := httptest.NewRecorder() handler.ServeHTTP(rr, req) assert.Equal(t, http.StatusOK, rr.Code) assert.Equal(t, string(testContent), rr.Body.String()) }) t.Run("Hidden files are accessible", func(t *testing.T) { tmpDir := t.TempDir() // Create a hidden file (starting with .) testFile := filepath.Join(tmpDir, ".hidden") testContent := []byte("hidden content") err := os.WriteFile(testFile, testContent, 0644) require.NoError(t, err) fs := http.Dir(tmpDir) httpFS := http.FileSystem(fs) handler, err := hws.SafeFileServer(&httpFS) require.NoError(t, err) req := httptest.NewRequest("GET", "/.hidden", nil) rr := httptest.NewRecorder() handler.ServeHTTP(rr, req) // Hidden files should still be accessible assert.Equal(t, http.StatusOK, rr.Code) assert.Equal(t, string(testContent), rr.Body.String()) }) } func Test_SafeFileServer_Integration(t *testing.T) { var buf bytes.Buffer tmpDir := t.TempDir() // Create test files indexFile := filepath.Join(tmpDir, "index.html") err := os.WriteFile(indexFile, []byte("Test"), 0644) require.NoError(t, err) cssFile := filepath.Join(tmpDir, "style.css") err = os.WriteFile(cssFile, []byte("body { color: red; }"), 0644) require.NoError(t, err) // Create server with SafeFileServer server := createTestServer(t, &buf) fs := http.Dir(tmpDir) httpFS := http.FileSystem(fs) handler, err := hws.SafeFileServer(&httpFS) require.NoError(t, err) err = server.AddRoutes(hws.Route{ Path: "/static/", Method: hws.MethodGET, Handler: http.StripPrefix("/static", handler), }) require.NoError(t, err) err = server.Start(t.Context()) require.NoError(t, err) defer server.Shutdown(t.Context()) <-server.Ready() t.Run("Can serve static files through server", func(t *testing.T) { // This would need actual HTTP requests to the running server // Simplified for now }) }