Reputation: 3190
How do you serve index.html (or some other static HTML file) using a go web server?
I just want a basic, static HTML file (like an article, for example) which I can serve from a go web server. The HTML should be modifiable outside of the go program, as it would be in the case while using HTML templates.
This is my web server which only hosts hard-coded text ("Hello world!").
package main
import (
"fmt"
"net/http"
)
func handler(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Hello world!")
}
func main() {
http.HandleFunc("/", handler)
http.ListenAndServe(":3000", nil)
}
Upvotes: 125
Views: 145084
Reputation: 2414
You can also use the Gorilla Mux Router to server static files. Assuming you have a static folder and an index.html file in the root.
import "github.com/gorilla/mux"
func main(){
router := mux.NewRouter()
fs := http.FileServer(http.Dir("./static/"))
router.PathPrefix("/static/").Handler(http.StripPrefix("/static/", fs))
log.Fatal(http.ListenAndServe(":8080", router))
}
Upvotes: 4
Reputation: 2414
This will serve the index.html file (if you have in the root) to the browser on localhost:8080
func main() {
port := flag.String("p", "8080", "port to serve on")
directory := flag.String("d", ".", "static file folder")
flag.Parse()
http.Handle("/", http.FileServer(http.Dir(*directory)))
log.Printf("Serving %s on HTTP port: %s\n", *directory, *port)
log.Fatal(http.ListenAndServe(":"+*port, nil))
}
Upvotes: 0
Reputation: 20420
If you only want to serve 1 file and not a full directory, you can use http.ServeFile
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
http.ServeFile(w, r, "index.html")
})
Upvotes: 16
Reputation: 635
Example how custom serve mp3 file:
r := http.NewServeMux()
r.HandleFunc("/file/*", func(w http.ResponseWriter, r *http.Request) {
// Prepare file path
pathFile := strings.ReplaceAll(r.RequestURI, "/file/", "./my_path/")
f, err := os.Open(pathFile)
if f == nil || err != nil {
return
}
// Read file into memory
fileBytes, err := ioutil.ReadAll(f)
if err != nil {
log.Println(err)
_, _ = fmt.Fprintf(w, "Error file bytes")
return
}
// Check mime type
mime := http.DetectContentType(fileBytes)
if mime != "audio/mpeg" {
log.Println("Error file type")
_, _ = fmt.Fprintf(w, "Error file type")
return
}
// Custom headers
r.Header.Add("Content-Type", "audio/mpeg")
r.Header.Add("Cache-Control", "must-revalidate, post-check=0, pre-check=0")
r.Header.Add("Content-Description", "File Transfer")
r.Header.Add("Content-Disposition", "attachment; filename=file.mp3")
r.Header.Add("Content-Transfer-Encoding", "binary")
r.Header.Add("Expires", "0")
r.Header.Add("Pragma", "public")
r.Header.Add("Content-Length", strconv.Itoa(len(fileBytes)))
http.ServeFile(w, r, pathFile)
})
log.Fatal(http.ListenAndServe(":80", r))
Upvotes: 2
Reputation: 189
This is easy in golang as:
package main
import (
"log"
"net/http"
)
func main() {
log.Fatal(http.ListenAndServe(":8080", http.FileServer(http.Dir("."))))
}
`
You can just do this and make sure to keep your HTML file as index.html
Upvotes: 1
Reputation: 1287
I prefer using http.ServeFile
for this over http.FileServer
. I wanted directory browsing disabled, a proper 404 if files are missing and an easy way to special case the index file. This way, you can just drop the built binary into a folder and it will serve everything relative to that binary. Of course, you can use strings.Replace
on p
if you have the files stored in another directory.
func main() {
fmt.Println("Now Listening on 80")
http.HandleFunc("/", serveFiles)
log.Fatal(http.ListenAndServe(":80", nil))
}
func serveFiles(w http.ResponseWriter, r *http.Request) {
fmt.Println(r.URL.Path)
p := "." + r.URL.Path
if p == "./" {
p = "./static/index.html"
}
http.ServeFile(w, r, p)
}
Upvotes: 28
Reputation: 1323115
NOT a FTP server: That is something different than what I intended, which would be to serve the
index.html
homepage, like a normal web server would. Like, when I go to mydomain.com in my browser, I wantindex.html
rendered.
That is mainly what "Writing Web Applications" describes, and what a project like hugo (static html site generator) does.
It is about reading a file, and responsing with a ContentType "text/html":
func (server *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
err := server.renderFile(w, r.URL.Path)
if err != nil {
w.Header().Set("Content-Type", "text/html; charset=utf-8")
w.WriteHeader(http.StatusNotFound)
server.fn404(w, r)
}
}
with renderFile()
essentially reading and setting the right type:
file, err = ioutil.ReadFile(server.MediaPath + filename)
if ext != "" {
w.Header().Set("Content-Type", mime.TypeByExtension(ext))
}
Upvotes: 8
Reputation: 3586
That task is very easy with Golang net/http package.
All You need to do is:
package main
import (
"net/http"
)
func main() {
http.Handle("/", http.FileServer(http.Dir("./static")))
http.ListenAndServe(":3000", nil)
}
assuming that static files are in folder named static
in the root directory of the project.
If it's in folder static
, you'll have index.html
file calling http://localhost:3000/
which will result in rendering that index file instead of listing all the files availible.
Additionally, calling any other file in that folder (for example http://localhost:3000/clients.html
) will show that file, properly rendered by the browser (at least Chrome, Firefox and Safari :))
If You want to serve files, say from folder ./public
under url: localhost:3000/static
You have to use additional function: func StripPrefix(prefix string, h Handler) Handler
like this:
package main
import (
"net/http"
)
func main() {
http.Handle("/static/", http.StripPrefix("/static/", http.FileServer(http.Dir("./public"))))
http.ListenAndServe(":3000", nil)
}
Thanks to that, all your files from ./public
are avalible under localhost:3000/static
Without http.StripPrefix
function, if you would try to access file localhost:3000/static/test.html
, the server would look for it in ./public/static/test.html
This is because the server treats the whole URI as a relative path to the file.
Fortunately, it's easily solved with the built-in function.
Upvotes: 192