Git Product home page Git Product logo

Comments (9)

zenazn avatar zenazn commented on July 28, 2024

I'd probably use it as an endpoint, not a middleware:

goji.Get("/assets/*", http.FileServer(http.Dir("/path/to/assets")))

from goji.

sporto avatar sporto commented on July 28, 2024

Thanks

from goji.

bernhardw avatar bernhardw commented on July 28, 2024

How would you do it if files like index.html or favicon.ico should be available under /?

Maybe it makes sense - performance wise - to attach it through goji.NotFound(), in order to try the routes first and only then access the file system.

from goji.

elcct avatar elcct commented on July 28, 2024

I did it this way:

https://github.com/elcct/defaultproject/blob/master/server.go#L43-L44

But ideally, I would serve those files directly via nginx

from goji.

bernhardw avatar bernhardw commented on July 28, 2024

Those lines are actually what reminded me to take these "root files" into account :) But I would prefer a way without specifying a separate route each.

What do you think of attaching a FileServer to goji.NotFound() if the file requested exists, and otherwise handle the 404?

from goji.

zenazn avatar zenazn commented on July 28, 2024

If there are only a few of them and they change infrequently, I'd recommend adding them by hand (or maybe writing yourself a short script that codegens them for you). Don't overengineer a solution to a problem you don't have.

If you can't do that or otherwise don't want to, I'd write a middleware that goes something like this (entirely untested!)

type tryFiles struct {
    dir   string
    inner http.Handler
}

func (t tryFiles) ServeHTTP(w http.ResponseWriter, r *http.Request) {
    clean := filepath.Clean(r.URL.Path)
    fname := filepath.Join(t.dir, clean)
    f, err := os.Open(fname)
    if err != nil {
        t.inner.ServeHTTP(w, r)
        return
    }
    defer f.Close()

    s, err := f.Stat()
    if err != nil {
        t.inner.ServeHTTP(w, r)
        return
    }

    http.ServeContent(w, r, fname, s.ModTime(), f)
}

func TryFiles(dir string) func(http.Handler) http.Handler {
    return func(h http.Handler) http.Handler {
        return tryFiles{dir, h}
    }
}

which can be used like this: goji.Use(TryFiles("path/to/public"))

Maybe I'll make a real repo out of this :)

from goji.

bernhardw avatar bernhardw commented on July 28, 2024

True, but I prefer a static file serving middleware. Here's what I use:

type static struct {
    dir string
    h   http.Handler
}

func (s static) ServeHTTP(w http.ResponseWriter, r *http.Request) {
    fname := filepath.Join(s.dir, r.URL.Path)

    _, err := os.Stat(fname)
    if err != nil {
        s.h.ServeHTTP(w, r)
        return
    }

    server := http.FileServer(http.Dir(s.dir))
    server.ServeHTTP(w, r)
}

func Static(dir string) func(http.Handler) http.Handler {
    return func(h http.Handler) http.Handler {
        return static{dir, h}
    }
}

I'm using FileServer() because it already Clean()s, Open()s, serves /index.html under / and probably does some more.

It would be great to have an official one added to https://github.com/goji :)

from goji.

colthreepv avatar colthreepv commented on July 28, 2024

👍 +1 to this Issue

The use case I'm interested is:

  • goji serve static files in development (using env variables), on /* and api on /api/v1/*
  • in production static file serving gets handled by nginx/apache/whatever

Would be useful to only register API endpoints, and put on a clever NotFound handler like @zenazn posted before.
If I succeed in creating a decent middleware I'll post it

from goji.

colthreepv avatar colthreepv commented on July 28, 2024

I don't think I'm able to make a plugin out of it.. yet (my skills in go + goji are like... well.. forget it!).
But in the meantime I've solved implementing a reverse string pattern

It's very simple. Posting it here so if you have ideas, I may also benefit!

// ReverseStringPattern is a simple struct keeping the raw string
// and the prefix to skip in requests
type ReverseStringPattern struct {
    raw    string
    prefix string
}

// prefix returns "" so goji doesn't ever skip the matching function
func (s ReverseStringPattern) Prefix() string {
    return ""
}
func (s ReverseStringPattern) Match(r *http.Request, c *web.C) bool {
    path := r.URL.Path
    return !strings.HasPrefix(path, s.prefix)
}
func (s ReverseStringPattern) Run(r *http.Request, c *web.C) {}

func NewReverseStringPattern(s string) ReverseStringPattern {
    var prefix string = s
    if strings.HasSuffix(s, "*") {
        prefix = s[:len(s)-1]
    }
    return ReverseStringPattern{raw: s, prefix: prefix}
}

// serveStatic makes sure that if running for development
// purposes, it serves static content from /static
func serveStatic() {
    buildMode := os.Getenv("mode")
    switch buildMode {
    case "development", "":
        reverseApiPattern := NewReverseStringPattern("/api/*")
        goji.Handle(reverseApiPattern, http.FileServer(http.Dir("static")))
    case "production":
        return
    default:
        return
    }
}

from goji.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.