在Go中使用HTML/TEMPLATE包时如何设置不同的内容类型

nos*_*bee 5 html http go go-templates

当我尝试将值传递给.html代码时,我正在使用该html/template包.

但是,我似乎无法设置.css我的.html文件中引用的内容类型.它以纯文本形式提供给浏览器,因此忽略了格式化.

在一个静态.html文件中,我可以使用内置函数http.Fileserver来处理内容类型,但然后模板化不起作用.我无法传递变量.它只显示为{{.}}

有没有办法将content-type内置文件服务器的便利性http.Fileserver与模板能力结合起来http.HandleFunc

这是我的代码,因为它没有使用http.Fileserver.注意,我的Go文件位于起始目录中,index.html而且.css文件位于子目录中/hello/:

package main

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

var Message string = "test page"

func servePipe(w http.ResponseWriter, req *http.Request) {

        dat, err := ioutil.ReadFile("hello/index.html")
        if err != nil {
                log.Fatal("couldn't read file:", err)
        }   

        templ, err := template.New("Test").Parse(string(dat))

        if err != nil {
                log.Fatal("couldn't parse page:", err)
        }   

        templ.Execute(w, Message)

}

func main() {

        http.HandleFunc("/hello/", servePipe)
        http.ListenAndServe(":8080", nil)
}
Run Code Online (Sandbox Code Playgroud)

这是我的.html档案.正在提供html页面没有任何问题.它.css是未提供的单独文件(在.html文件中链接),因此不会发生格式化.

<!DOCTYPE html>
<html>
<head>
<title>Test Page</title>

        <link rel="stylesheet" type="text/css" href="style.css"/>
</head>

<body>

        <p>{{.}}</p>

</body>
</html>
Run Code Online (Sandbox Code Playgroud)

icz*_*cza 5

Template.Execute()将通过调用Write()传递的方法来“传递”内容io.Writer,在您的情况下是http.ResponseWriter.

如果您在第一次调用之前没有设置内容类型ResponseWriter.Write()(在您的示例中没有设置),那么net/http包将尝试检测内容类型(基于写入的前 512 个字节),并将自动设置它为您(以及WriteHeader(http.StatusOK)ifResponseWriter.WriteHeader()尚未被调用)。

这是记录在http.ResponseWriter.Write()

// Write writes the data to the connection as part of an HTTP reply.
//
// If WriteHeader has not yet been called, Write calls
// WriteHeader(http.StatusOK) before writing the data. If the Header
// does not contain a Content-Type line, Write adds a Content-Type set
// to the result of passing the initial 512 bytes of written data to
// DetectContentType.
//
// ...
Write([]byte) (int, error)
Run Code Online (Sandbox Code Playgroud)

所以如果你index.html看起来像这样:

<html>
  <body>
    This is the body!
  </body>
</html>
Run Code Online (Sandbox Code Playgroud)

然后这将被正确地检测为 HTML 文档,因此text/html将自动设置内容类型。如果您没有出现这种情况,则意味着您index.html的文件未被识别为 HTML 文档。所以只要确保你的模板文件是有效的 HTML / CSS / 等。文档和内容类型将被自动和正确地推断出来。

另请注意,如果它在某些“极端”情况下不起作用,您始终可以通过在调用之前手动设置它来“覆盖”它,Template.Execute()如下所示:

w.Header().Set("Content-Type", "text/html")
templ.Execute(w, Message)
Run Code Online (Sandbox Code Playgroud)

旁注:不要在处理程序中读取和解析模板,有关详细信息,请参阅相关问题:在 golang 中使用“模板”包为客户端生成动态网页需要花费太多时间


如果您提供的模板引用了其他模板,它们将不会被神奇地加载和执行。在这种情况下,您应该有一个包含所有模板的“预加载”模板。template.ParseFiles()并且template.ParseGlob()是一次加载多个模板文件的好“工具”。

所以,如果你的index.html引用style.css,那么你必须要对服务照顾style.css过。如果它不是模板(但例如静态文件),您可以使用此处提供的多个选项提供它:在 Go 模板中包含 js 文件

如果它也是一个模板,那么您还必须加载它并通过调用Template.ExecuteTemplate().

一个示例解决方案是使用template.ParseFiles(),并使用路径来“指定”您想要提供的模板(从客户端/浏览器端)。

例如,请求路径/hello/index.html可以为"index.html"模板提供服务,请求路径/hello/style.css这将在接收和处理 之后由浏览器自动完成index.html)可以为"style.css"模板提供服务。它可能看起来像这样(为简洁起见省略了错误检查):

parts := strings.Split(req.URL.Path, "/") // Parts of the path
templName := parts[len(parts)-1]          // The last part
templ.ExecuteTemplate(w, templName, someDataForTemplate)
Run Code Online (Sandbox Code Playgroud)


归档时间:

查看次数:

1943 次

最近记录:

7 年,7 月 前