DetectContentType return wrong content type

I try to use DetectContentType func to return correct content type. But for my css file, it return text/plain.
Can anybody help me?

package main

import (
	"io/ioutil"
	"net/http"
)

func main() {

	http.Handle("/", new(MyHandler))

	http.ListenAndServe(":8000", nil)
}

type MyHandler struct{}

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.Header().Add("Content-Type", http.DetectContentType(data))
		w.Write(data)
	} else {
		w.WriteHeader(404)
		w.Write([]byte("404 - " + http.StatusText(404)))
	}
}

CSS is not one of the file types identified by DetectContentType. You should match that based on the file extension instead. See also mime.TypeByExtension. I typically end up doing something like this, when I know I’m serving a limited set of files:


func (s *staticsServer) mimeTypeForFile(file string) string {
	// We use a built in table of the common types since the system
	// TypeByExtension might be unreliable. But if we don't know, we delegate
	// to the system.
	ext := filepath.Ext(file)
	switch ext {
	case ".htm", ".html":
		return "text/html"
	case ".css":
		return "text/css"
	case ".js":
		return "application/javascript"

    // ...

	default:
		return mime.TypeByExtension(ext)
	}
}
1 Like

Hey @Stephanus_Budiwijaya.

I’m not sure if the reason you are trying to get the content type is because you are trying to serve your assets or not, but if you are, here’s a simple structure that you can use instead of what you are currently doing:


main.go
index.html
assets/
- styles.css


main.go

package main

import (
	"html/template"
	"log"
	"net/http"
)

var tmpls = template.Must(template.ParseFiles("index.html"))

// Index page handler
func IndexHandler(w http.ResponseWriter, r *http.Request) {
	if err := tmpls.ExecuteTemplate(w, "index.html", nil); err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
	}
}

func main() {
	// Serve the index page
	http.HandleFunc("/", IndexHandler)

	// Serve assets
	http.Handle("/assets/", http.StripPrefix("/assets/",
		http.FileServer(http.Dir("assets/"))))

	log.Fatalln(http.ListenAndServe(":8000", nil))
}

index.html

<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
		<title>Serving Assets</title>
		<link rel="stylesheet" href="assets/styles.css" />
	</head>
	<body>
		<h1>Serving Assets</h1>
	</body>
</html>

assets/styles.css

body {
	background: #1af;
}
1 Like

Yeah my purpose is to serve that asset. Since I am new in Go, I didn’t know this technique is available.
Thank you

1 Like

Since you’re serving up CSS files using Go, you might be interested in my gzipped.FileServer project, which is a drop-in replacement for the standard Go http.FileServer (minus directory browsing) and allows you to serve zopfli-precompressed versions of your CSS files. With Bootstrap, this cuts the (already minimized) CSS file from 122KB bytes to 19KB during transit.

Currently I’m using it with httprouter:

router.Handler("GET", "/assets/*filepath", 
  http.StripPrefix("/assets/", gzipped.FileServer(http.Dir("assets/"))))

It also works with standard Go ServeMux, and I just double checked that it serves up .css / .css.gz files as text/css correctly.

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