File Server - index.html quirk

Hi, I’m currently learning Go’s File Server, and I found a little quirk when working on index.html that I can’t get my head around. So here’s the situation …

File structure

|— cmd/
|    |— main.go
|— resources/
     |— hello/
     |    |— hello.html
     |    |— hello.js
     |— index/
          |— index.html
          |— index.js

main.go

func newRouter() *mux.Router {
	r := mux.NewRouter()
	r.HandleFunc("/", indexHandler).Methods("GET")
	r.HandleFunc("/hello", helloHandler).Methods("GET")
	r.PathPrefix("/static/").Handler(staticFileHandler()).Methods("GET")
	return r
}

func indexHandler(w http.ResponseWriter, r *http.Request) {
	b, err := os.ReadFile("../resources/index/index.html")
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
	}
	fmt.Fprintf(w, string(b))
}

func helloHandler(w http.ResponseWriter, r *http.Request) {
	b, err := os.ReadFile("../resources/hello/hello.html")
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
	}
	fmt.Fprintf(w, string(b))
}

func staticFileHandler() http.Handler {
	dir := http.Dir("../")
	return http.StripPrefix("/static/", http.FileServer(dir))
}

func main() {
	r := newRouter()
	http.ListenAndServe(":8080", r)
}

So if we run main.go, and send a GET request of
http://localhost:8080/static/resources/hello
This is what we will get from the response …

<pre>
<a href="hello.html">hello.html</a>
<a href="hello.js">hello.js</a>
</pre>

… which is the files in “hello” folder, as expected.

So if we send another GET request of
http://localhost:8080/static/resources/index
Guess what? we will get the content of index.html directly. Say,

<!DOCTYPE html>
<html lang="en">
	<head>
		<meta charset="UTF-8">
		<title>index</title>
	</head>
	<body>
		<h1>index</h1>
		<script src="/static/resources/index/index.js"></script>
	</body>
</html>

To further prove that, I changed the name of index.html to, maybe, default.html
then only I got this …

<pre>
<a href="default.html">default.html</a>
<a href="index.js">index.js</a>
</pre>

So my question is, what so special about index.html? I thought index.html was just a naming convention thing. Why Go http.FileServer() treats it differently? Is there any rationale behind it?

Thanks.

Hi @naixyeur,

Indeed, this is a behavior of ServeFile() that FileServer calls internally.

This is historic Web server behavior. If the URL maps to a directory, the standard action is to see if an index.html file is inside, and serve that instead of the directory contents.

See e.g., Webserver directory index - Wikipedia:

When an HTTP client (generally a web browser) requests a URL that points to a directory structure instead of an actual web page within the directory, the web server will generally serve a default page, which is often referred to as a main or “index” page.

1 Like

It seems like I’ve asked a silly question due to lack of understanding of fundamental knowledge about web service.
Thanks for your reply, Christoph.

Not your fault at all! No one can have all the historically grown peculiarities of IT tools and protocols in the back of their head. IMHO the net/http docs should mention that behavior.

1 Like

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.