diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..2fdc5c2 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright © 2024 NAME HERE + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/err_404.go b/err_404.go new file mode 100644 index 0000000..6e232db --- /dev/null +++ b/err_404.go @@ -0,0 +1,13 @@ +package static + +import ( + "fmt" + "net/http" +) + +func Err404(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Content-Type", "text/html") + fmt.Println("404: " + r.URL.Path) + w.WriteHeader(404) + w.Write([]byte("file not found.")) +} diff --git a/example_static/robots.txt b/example_static/robots.txt new file mode 100644 index 0000000..82d6422 --- /dev/null +++ b/example_static/robots.txt @@ -0,0 +1,6 @@ +# Your Site +User-agent: Google-Extended +Disallow: / + +User-agent: GPTBot +Disallow: / \ No newline at end of file diff --git a/example_test.go b/example_test.go new file mode 100644 index 0000000..132abcc --- /dev/null +++ b/example_test.go @@ -0,0 +1,35 @@ +package static_test + +import ( + "embed" + "fmt" + "io" + "net/http" + "net/http/httptest" + + "git.bivouac.wiki/use/static" +) + +//go:embed example_static +var static_files embed.FS + +func ExampleStatic() { + s := static.NewStatic("example_static/", static_files) + mux := http.NewServeMux() + // for files outside a static directory: + mux.HandleFunc("/robots.txt", s.WrapStatic("/robots.txt", "robots.txt")) + // for an entire subdirectory: + mux.HandleFunc("/static/{filename}", s.StaticRoute) + w := httptest.NewRecorder() + ts := httptest.NewServer(mux) + ts.URL = "robots.txt" + ts.Start() + res := w.Result() + defer res.Body.Close() + data, err := io.ReadAll(res.Body) + if err != nil { + fmt.Errorf("expected error to be nil got %v", err) + } + fmt.Println(string(data)) + +} diff --git a/init.go b/init.go new file mode 100644 index 0000000..6eabe47 --- /dev/null +++ b/init.go @@ -0,0 +1,17 @@ +package static + +import "embed" + +type Static struct { + prefix string + FS embed.FS +} + +// NewStatic creates a new static wrapper (prefix should have trailing slash) +func NewStatic(prefix string, fs embed.FS) Static { + // todo later: support embed.FS and io/fs.FS. + return Static{ + prefix: prefix, + FS: fs, + } +} diff --git a/middleware.go b/middleware.go deleted file mode 100644 index 4a9e036..0000000 --- a/middleware.go +++ /dev/null @@ -1 +0,0 @@ -package static diff --git a/static_route.go b/static_route.go new file mode 100644 index 0000000..451073e --- /dev/null +++ b/static_route.go @@ -0,0 +1,18 @@ +package static + +import ( + "net/http" + "strings" +) + +func (s Static) StaticRoute(w http.ResponseWriter, r *http.Request) { + f, err := s.FS.ReadFile(s.prefix + r.PathValue("filename")) + if strings.HasSuffix(r.URL.Path, ".css") { + w.Header().Set("Content-Type", "text/css") + } + if err != nil { + Err404(w, r) + return + } + w.Write(f) +} diff --git a/wrap_static.go b/wrap_static.go new file mode 100644 index 0000000..4279295 --- /dev/null +++ b/wrap_static.go @@ -0,0 +1,22 @@ +package static + +import ( + "fmt" + "net/http" +) + +func (s Static) WrapStatic(url string, truefile string) func(w http.ResponseWriter, r *http.Request) { + return func(w http.ResponseWriter, r *http.Request) { + if r.URL.Path != url { + fmt.Println("404: " + r.URL.Path) + Err404(w, r) + return + } + f, err := s.FS.ReadFile(s.prefix + truefile) + if err != nil { + Err404(w, r) + return + } + w.Write(f) + } +}