diff --git a/examples/gno.land/p/demo/flow/LICENSE.md b/examples/gno.land/p/demo/flow/LICENSE similarity index 100% rename from examples/gno.land/p/demo/flow/LICENSE.md rename to examples/gno.land/p/demo/flow/LICENSE diff --git a/gno.land/pkg/gnoweb/gnoweb.go b/gno.land/pkg/gnoweb/gnoweb.go index d8919fb0913..b997de7840d 100644 --- a/gno.land/pkg/gnoweb/gnoweb.go +++ b/gno.land/pkg/gnoweb/gnoweb.go @@ -111,7 +111,7 @@ func MakeApp(logger *slog.Logger, cfg Config) gotuna.App { } // realm routes // NOTE: see rePathPart. - app.Router.Handle("/r/{rlmname:[a-z][a-z0-9_]*(?:/[a-z][a-z0-9_]*)+}/{filename:(?:.*\\.(?:gno|md|txt|mod)$)?}", handlerRealmFile(logger, app, &cfg)) + app.Router.Handle("/r/{rlmname:[a-z][a-z0-9_]*(?:/[a-z][a-z0-9_]*)+}/{filename:(?:(?:.*\\.(?:gno|md|txt|mod)$)|(?:LICENSE$))?}", handlerRealmFile(logger, app, &cfg)) app.Router.Handle("/r/{rlmname:[a-z][a-z0-9_]*(?:/[a-z][a-z0-9_]*)+}", handlerRealmMain(logger, app, &cfg)) app.Router.Handle("/r/{rlmname:[a-z][a-z0-9_]*(?:/[a-z][a-z0-9_]*)+}:{querystr:.*}", handlerRealmRender(logger, app, &cfg)) app.Router.Handle("/p/{filepath:.*}", handlerPackageFile(logger, app, &cfg)) diff --git a/gno.land/pkg/gnoweb/gnoweb_test.go b/gno.land/pkg/gnoweb/gnoweb_test.go index 55434e3b9fc..d6b93b37d69 100644 --- a/gno.land/pkg/gnoweb/gnoweb_test.go +++ b/gno.land/pkg/gnoweb/gnoweb_test.go @@ -46,6 +46,7 @@ func TestRoutes(t *testing.T) { {"/%ED%85%8C%EC%8A%A4%ED%8A%B8", notFound, "/테스트"}, {"/グノー", notFound, "/グノー"}, {"/⚛️", notFound, "/⚛️"}, + {"/p/demo/flow/LICENSE", ok, "BSD 3-Clause"}, } config, _ := integration.TestingNodeConfig(t, gnoenv.RootDir()) @@ -67,7 +68,6 @@ func TestRoutes(t *testing.T) { response := httptest.NewRecorder() app.Router.ServeHTTP(response, request) assert.Equal(t, r.status, response.Code) - assert.Contains(t, response.Body.String(), r.substring) }) } diff --git a/tm2/pkg/std/memfile.go b/tm2/pkg/std/memfile.go index f41619b56bd..ce73995a22a 100644 --- a/tm2/pkg/std/memfile.go +++ b/tm2/pkg/std/memfile.go @@ -90,18 +90,23 @@ func (mempkg *MemPackage) Validate() error { return nil } +const licenseName = "LICENSE" + // Splits a path into the dirpath and filename. func SplitFilepath(filepath string) (dirpath string, filename string) { parts := strings.Split(filepath, "/") if len(parts) == 1 { return parts[0], "" } - last := parts[len(parts)-1] - if strings.Contains(last, ".") { + + switch last := parts[len(parts)-1]; { + case strings.Contains(last, "."): return strings.Join(parts[:len(parts)-1], "/"), last - } else if last == "" { + case last == "": return strings.Join(parts[:len(parts)-1], "/"), "" - } else { - return strings.Join(parts, "/"), "" + case last == licenseName: + return strings.Join(parts[:len(parts)-1], "/"), licenseName } + + return strings.Join(parts, "/"), "" } diff --git a/tm2/pkg/std/memfile_test.go b/tm2/pkg/std/memfile_test.go index 7b944f75c4f..3e1fb49e131 100644 --- a/tm2/pkg/std/memfile_test.go +++ b/tm2/pkg/std/memfile_test.go @@ -270,3 +270,54 @@ func TestMemPackage_Validate(t *testing.T) { }) } } + +func TestSplitFilepath(t *testing.T) { + t.Parallel() + tests := []struct { + name string + filepath string + expDirPath string + expFilename string + }{ + { + name: "empty", + }, + { + name: "one part", + filepath: "root", + expDirPath: "root", + }, + { + name: "file", + filepath: "gno.land/r/demo/avl/avl.gno", + expDirPath: "gno.land/r/demo/avl", + expFilename: "avl.gno", + }, + { + name: "trailing slash", + filepath: "gno.land/r/demo/avl/", + expDirPath: "gno.land/r/demo/avl", + }, + { + name: "license", + filepath: "gno.land/r/demo/avl/LICENSE", + expDirPath: "gno.land/r/demo/avl", + expFilename: "LICENSE", + }, + { + name: "regular path", + filepath: "gno.land/p/demo/avl", + expDirPath: "gno.land/p/demo/avl", + }, + } + + for _, tt := range tests { + tt := tt + t.Run(tt.name, func(t *testing.T) { + t.Parallel() + dirPath, filename := SplitFilepath(tt.filepath) + assert.Equal(t, tt.expDirPath, dirPath) + assert.Equal(t, tt.expFilename, filename) + }) + } +}