Golang http.ServeFile 处理静态文件contentType不正确
我在用golang写http server,使用http.ServeFile来处理静态的文件,但是浏览器一直就是取不到正确的contentType 错误如下
Resource interpreted as Script but transferred with MIME type text/x-js: "
http://127.0.0.1
:8080/public/js/jquery.js"
大致的代码如下:
func staticDirHandler(mux *http.ServeMux, prefix string, staticDir string, flags int) { mux.HandleFunc(prefix, func(w http.ResponseWriter, r *http.Request) { file := staticDir + r.URL.Path[len(prefix)-1:] if (flags & ListDir) == 0 { fi, err := os.Stat(file) if err != nil || fi.IsDir() { http.NotFound(w, r) return } } http.ServeFile(w, r, file) }) }
主要是http.ServeFile 这个源码我也看了下,最后他调用了 serveContent里面有一段是进行文件的mime设置的。
// If Content-Type isn't set, use the file's extension to find it. 129 ctype := w.Header().Get("Content-Type") 130 if ctype == "" { 131 ctype = mime.TypeByExtension(filepath.Ext(name)) 132 if ctype == "" { 133 // read a chunk to decide between utf-8 text and binary 134 var buf [1024]byte 135 n, _ := io.ReadFull(content, buf[:]) 136 b := buf[:n] 137 ctype = DetectContentType(b) 138 _, err := content.Seek(0, os.SEEK_SET) // rewind to output whole file 139 if err != nil { 140 Error(w, "seeker can't seek", StatusInternalServerError) 141 return 142 } 143 } 144 w.Header().Set("Content-Type", ctype) 145 }
但结果确不是正确的,不知道该如何设置才能正确,另外我也看了golang.org 官网他本身也是有这个问题的,我使用的是chrome浏览器。
@小明 给出的回复之后,我发现单独访问,确实没有任何问题的,但是html调用就会出现,下面是我准备的测试例子,大家可以帮忙看下,问题出在哪里?
package main import( "fmt" "net/http" "io/ioutil" "log" ) func Handler( w http.ResponseWriter,r *http.Request ){ path := r.URL.Path[1:] if path == "favicon.ico" { http.NotFound(w, r) return } if path == ""{ path = "index.html" } contents,err:= ioutil.ReadFile( path ) if err !=nil{ fmt.Fprintf( w,"404" ) return } fmt.Fprintf( w,"%s\n",contents ) } func StaticServer(w http.ResponseWriter, req *http.Request) { staticHandler := http.FileServer(http.Dir("./public/")) staticHandler.ServeHTTP(w, req) return } func main(){ http.HandleFunc( "/",Handler) http.HandleFunc( "/public",StaticServer) s := &http.Server{ Addr: ":8181", } log.Fatal(s.ListenAndServe()) }
index.html
<!DOCTYPE html> <html> <head> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> <title>test page</title> <link rel="stylesheet" href="public/css/base.css" type="text/css" /> </head> <body> <div id="container"> <header> <h1>test page</h1> </header> <a class='save'>Save Now</a> <section id="main-content"> <div class="form-area"> <form id="tasks-form"> <label for="task">Add a task here and hit enter</label> <input id="task" autofocus=""> </form> </div> <ul id="tasks"></ul> </section> </div> <li class="template" style="display:none"> <input type='checkbox'/> <span >" "</span> <a href=''>x</a> </li> <script type="text/javascript" src="public/js/jquery.js"></script> <script type="text/javascript" src="public/js/base.js"></script> </body> </html>
单独访问js css都没有问题,但是访问html就会出现之前的那个警告提示了。我使用godoc --http=":8080" 本地访问也会有这个问题,你也可以测试下。
---------------------------------------------
最后在 “Go语言精英群” 的帮助下解决了。
原因是我系统的mime.type的问题,因为go语言使用的是系统的mime,像nginx是有自己的mime,所以不会有问题。
详细查看:
http://golang.org/pkg/mime/#TypeByExt...
Answers
原因是我系统的mime.type的问题,因为go语言使用的是系统的mime,像nginx是有自己的mime,所以不会有问题。
/etc/mime.types
/etc/apache2/mime.types
/etc/apache/mime.types
详细查看: http://golang.org/pkg/mime/#TypeByExt...
所以如果用go写web服务最好准备一份mime.types