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...

go

Somehow 11 years, 7 months ago

原因是我系统的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

俺不是MT answered 11 years, 7 months ago

Your Answer