37
http.Handle("/", http.FileServer(http.Dir("static")))

Serves the html file in static directory.

Is there any way in Go that we can specify the html file to serve?

Something like render_template in Flask

I want to do something like:

http.Handle("/hello", http.FileServer(http.Dir("static/hello.html")))

3 Answers 3

45

Maybe using a custom http.HandlerFunc would be easier:

Except in your case, your func would be the http.ServeFile one, for serving just one file.

See for instance "Go Web Applications: Serving Static Files":

Add the following below your home handler (see below):

http.HandleFunc("/static/", func(w http.ResponseWriter, r *http.Request) {
   // do NOT do this. (see below)
    http.ServeFile(w, r, r.URL.Path[1:])
})

This is using the net/http package’s ServeFile function to serve our content.
Effectively anything that makes a request starting with the /static/ path will be handled by this function.
One thing I found I had to do in order for the request to be handled correctly was trim the leading ‘/’ using:

r.URL.Path[1:]

Actually, do not do that.
This won't be possible in Go 1.6, as sztanpet comments, with commit 9b67a5d:

If the provided file or directory name is a relative path, it is interpreted relative to the current directory and may ascend to parent directories.
If the provided name is constructed from user input, it should be sanitized before calling ServeFile.
As a precaution, ServeFile will reject requests where r.URL.Path contains a ".." path element.

That will protect against the following "url":

/../file
/..
/../
/../foo
/..\\foo
/file/a
/file/a..
/file/a/..
/file/a\\..
Sign up to request clarification or add additional context in comments.

Comments

7

You could use http.StripPrefix

Like this:

http.Handle("/hello/", http.StripPrefix("/hello/",http.FileServer(http.Dir("static"))))

Comments

1

Maybe I missed something here, but after a lot of confused searching, I put this together:

...

func downloadHandler(w http.ResponseWriter, r *http.Request) {
        r.ParseForm()
        StoredAs := r.Form.Get("StoredAs") // file name
        data, err := ioutil.ReadFile("files/"+StoredAs)
        if err != nil { fmt.Fprint(w, err) }
        http.ServeContent(w, r, StoredAs, time.Now(),   bytes.NewReader(data))
}

...

Where downloadHandler is invoked as part of a simple upload and download server:

func main() {
              http.HandleFunc("/upload", uploadHandler)
              http.HandleFunc("/download", downloadHandler)
              http.ListenAndServe(":3001", nil)
}   

Works fine with Firefox and Chrome. Doesn't even need a file type.

4 Comments

What happens if the StoredAs param contains "../../mysecrets ?
I don't know. What happens?
A directory traversal attack
always a good idea to treat URIs and user input as malicious and trying to penetrate your server. never trust those inputs. sanitize it!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.