Serving static content with a root URL with the Gorilla toolkit

Web ApplicationsGoMux

Web Applications Problem Overview


I am attempting to use the Gorilla toolkit's mux package to route URLs in a Go web server. Using this question as a guide I have the following Go code:

func main() {
	r := mux.NewRouter()
	r.Handle("/", http.FileServer(http.Dir("./static/")))
	r.HandleFunc("/search/{searchTerm}", Search)
	r.HandleFunc("/load/{dataId}", Load)
	http.Handle("/", r)
	http.ListenAndServe(":8100", nil)
}

The directory structure is:

...
main.go
static\
  | index.html
  | js\
     | <js files>
  | css\
     | <css files>

The Javascript and CSS files are referenced in index.html like this:

...
<link rel="stylesheet" href="css/redmond/jquery-ui.min.css"/>
<script src="js/jquery.min.js"></script>
...

When I access http://localhost:8100 in my web browser the index.html content is delivered successfully, however, all the js and css URLs return 404s.

How can I get the program to serve files out of static sub-directories?

Web Applications Solutions


Solution 1 - Web Applications

I think you might be looking for PathPrefix...

func main() {
    r := mux.NewRouter()
    r.HandleFunc("/search/{searchTerm}", Search)
    r.HandleFunc("/load/{dataId}", Load)
    r.PathPrefix("/").Handler(http.FileServer(http.Dir("./static/")))
    http.ListenAndServe(":8100", r)
}

Solution 2 - Web Applications

After a lot of trial and error, both above answers helped me in coming up with what worked for me. I have static folder in web app's root directory.

Along with PathPrefix I had to use StripPrefix for getting route to work recursively.

package main

import (
	"log"
	"net/http"
    "github.com/gorilla/mux"
)

func main() {
	r := mux.NewRouter()
	s := http.StripPrefix("/static/", http.FileServer(http.Dir("./static/")))
	r.PathPrefix("/static/").Handler(s)
	http.Handle("/", r)
	err := http.ListenAndServe(":8081", nil)
}

I hope it helps somebody else having problems.

Solution 3 - Web Applications

I have this code here that works quite nice and is re-usable.

func ServeStatic(router *mux.Router, staticDirectory string) {
    staticPaths := map[string]string{
        "styles":           staticDirectory + "/styles/",
        "bower_components": staticDirectory + "/bower_components/",
        "images":           staticDirectory + "/images/",
        "scripts":          staticDirectory + "/scripts/",
    }
    for pathName, pathValue := range staticPaths {
        pathPrefix := "/" + pathName + "/"
        router.PathPrefix(pathPrefix).Handler(http.StripPrefix(pathPrefix,
            http.FileServer(http.Dir(pathValue))))
    }
}
router := mux.NewRouter()
ServeStatic(router, "/static/")

Solution 4 - Web Applications

Try this:

fileHandler := http.StripPrefix("/static/", http.FileServer(http.Dir("/absolute/path/static")))
http.Handle("/static/", fileHandler)

Solution 5 - Web Applications

This serve all files inside the folder flag, as well as serving index.html at the root.

#Usage //port default values is 8500 //folder defaults to the current directory go run main.go

   //your case, dont forget the last slash
   go run main.go -folder static/

   //dont
   go run main.go -folder ./

#Code

    package main

import (
	"flag"
	"fmt"
	"net/http"
	"os"
	"strconv"
	"strings"

	"github.com/gorilla/handlers"
	"github.com/gorilla/mux"
	"github.com/kr/fs"
)

func main() {
	mux := mux.NewRouter()

	var port int
	var folder string
	flag.IntVar(&port, "port", 8500, "help message for port")
	flag.StringVar(&folder, "folder", "", "help message for folder")

	flag.Parse()

	walker := fs.Walk("./" + folder)
	for walker.Step() {
		var www string

		if err := walker.Err(); err != nil {
			fmt.Fprintln(os.Stderr, "eroooooo")
			continue
		}
		www = walker.Path()
		if info, err := os.Stat(www); err == nil && !info.IsDir() {
			mux.HandleFunc("/"+strings.Replace(www, folder, "", -1), func(w http.ResponseWriter, r *http.Request) {
				http.ServeFile(w, r, www)
			})
		}
	}
	mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		http.ServeFile(w, r, folder+"index.html")
	})
	http.ListenAndServe(":"+strconv.Itoa(port), handlers.LoggingHandler(os.Stdout, mux))
}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionjasonView Question on Stackoverflow
Solution 1 - Web ApplicationsChris FarmiloeView Answer on Stackoverflow
Solution 2 - Web ApplicationscodefreakView Answer on Stackoverflow
Solution 3 - Web ApplicationsThomas ModeneisView Answer on Stackoverflow
Solution 4 - Web ApplicationsJoeView Answer on Stackoverflow
Solution 5 - Web ApplicationsCESCOView Answer on Stackoverflow