I've created a server in Go and I'm trying to run an html file in the browser. But the browser just prints out the code like a txt file instead of rendering the html formatting. My index.html file is saved in the /public directory.
My go code looks like this:
package main
import (
"net/http"
"io/ioutil"
)
func main() {
http.Handle("/", new(MyHandler))
http.ListenAndServe(":8000", nil)
}
type MyHandler struct {
http.Handler
}
func (this *MyHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
path := "public/" + req.URL.Path
data, err := ioutil.ReadFile(string(path))
if err == nil {
w.Write(data)
} else {
w.WriteHeader(404)
w.Write([]byte("404 - " + http.StatusText(404)))
}
}
In your main try using http.HandleFunc("/", ServeHTTP)
then edit the ServeHTTP
method so it doesn't have a reciever ie; func ServeHTTP(w http.ResponseWriter, req *http.Request)
You attempt to use that object and the Handle
method may work fine too (if implemented correctly) but most of the examples use HandleFunc
and if you do as well I bet your problem will go away.
The only other thing that would be causing the issues you're observing is a failure to read the file who's contents are assigned to data
or some misconception about what the data in that file actually is.
Right now you're just reading the contents of the file and writing it out. Since Go can't tell what type of file it is, it can't set the header.
Thankfully, there's a useful http.ServeFile
function in the net/http package that can help you.
func (this *MyHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
path := "public/" + req.URL.Path
http.ServeFile(w, r, filepath.Join("path/to/file", path))
}
http.ServeFile
attempts to set the Content-Type
based on the file extension or first handful of bytes (for a HTML file it should get it right).
A better solution is to make your route handler the http.FileServer
func main() {
http.Handle("/", http.FileServer(http.Dir("./public"))
http.ListenAndServe(":8000", nil)
}
Take a look at the examples in the Go docs for how to use it in other ways.
Shameless plug: I wrote a small middleware library that makes it a bit easier to serve static files in Go that you may find use in (or read just read the code for insight): https://github.com/elithrar/station
Start with getting the HTML up and running. Then, build in your HTTP error handling (e.g. 404). I recommend using the text/template
from the start, even if you're not adding any dynamism to your app... yet!
package main
import (
"io/ioutil"
"log"
"net/http"
"text/template"
)
func main() {
http.HandleFunc("/", RootHandler)
if err := http.ListenAndServe(":8080", nil); err != nil {
log.Fatal(err)
}
}
func RootHandler(res http.ResponseWriter, req *http.Request) {
file, _ := ioutil.ReadFile("public/index.html")
t := template.New("")
t, _ = t.Parse(string(file))
t.Execute(res, nil)
}
In case you want to hold off on using the text/template
package and just serve the HTML straight up, simply read your index.html
file and write it to the response writer (e.g. res
for response in my example, however many folks also use w
for writer).
package main
import (
"io/ioutil"
"log"
"net/http"
)
func main() {
http.HandleFunc("/", RootHandler)
if err := http.ListenAndServe(":8080", nil); err != nil {
log.Fatal(err)
}
}
func RootHandler(res http.ResponseWriter, req *http.Request) {
file, _ := ioutil.ReadFile("public/index.html")
res.Write(file)
}