Skip to content

Commit 68b4f7d

Browse files
committed
fix(static): preserve matched handler 404s
1 parent 70b31c2 commit 68b4f7d

2 files changed

Lines changed: 34 additions & 2 deletions

File tree

middleware/static.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -269,10 +269,12 @@ func (config StaticConfig) ToMiddleware() (echo.MiddlewareFunc, error) {
269269
}
270270

271271
var he echo.HTTPStatusCoder
272-
if !errors.As(err, &he) || !config.HTML5 || he.StatusCode() != http.StatusNotFound {
272+
if (c.Path() != "" && c.RouteInfo().Method != echo.RouteNotFound) ||
273+
!errors.As(err, &he) ||
274+
!config.HTML5 || he.StatusCode() != http.StatusNotFound {
273275
return err
274276
}
275-
// is case HTML5 mode is enabled + echo 404 we serve index to the client
277+
// In HTML5 mode, serve index for a router-level 404.
276278
file, err = currentFS.Open(config.Index)
277279
if err != nil {
278280
return err

middleware/static_test.go

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,36 @@ func TestStatic_useCaseForApiAndSPAs(t *testing.T) {
4444

4545
}
4646

47+
func TestStaticHTML5PreservesMatchedHandlerNotFound(t *testing.T) {
48+
e := echo.New()
49+
e.Use(StaticWithConfig(StaticConfig{
50+
Root: "testdata/dist/public",
51+
HTML5: true,
52+
}))
53+
e.GET("/api/users/:id", func(c *echo.Context) error {
54+
return echo.NewHTTPError(http.StatusNotFound, "user not found")
55+
})
56+
57+
req := httptest.NewRequest(http.MethodGet, "/api/users/42", nil)
58+
rec := httptest.NewRecorder()
59+
e.ServeHTTP(rec, req)
60+
61+
assert.Equal(t, http.StatusNotFound, rec.Code)
62+
assert.JSONEq(t, `{"message":"user not found"}`, rec.Body.String())
63+
64+
group := echo.New()
65+
group.Group("/app", StaticWithConfig(StaticConfig{
66+
Root: "testdata/dist/public",
67+
HTML5: true,
68+
}))
69+
req = httptest.NewRequest(http.MethodGet, "/app/dashboard", nil)
70+
rec = httptest.NewRecorder()
71+
group.ServeHTTP(rec, req)
72+
73+
assert.Equal(t, http.StatusOK, rec.Code)
74+
assert.Contains(t, rec.Body.String(), "<h1>Hello from index</h1>\n")
75+
}
76+
4777
func TestStatic(t *testing.T) {
4878
var testCases = []struct {
4979
name string

0 commit comments

Comments
 (0)