如何正确地从嵌入式文件系统中提供由html/template生成的内容?

huangapple go评论116阅读模式
英文:

How to serve content generated with html/template from an embedded filesystem correctly?

问题

当我在浏览器中访问localhost:8080时,页面会显示模板中的正确字段值,但是CSS无法正确加载。当我在浏览器上访问Web开发者工具面板时,我注意到.js.css文件有两个相同的错误,即

由于MIME类型(“text/plain”)不匹配(X-Content-Type-Options: nosniff),资源“http://localhost:8080/static/style.css”被阻止。

(我只显示与.css文件相关的错误,另一个错误是相同的)

我真的不知道还能做什么,因为我已经尝试过所有简单的解决方案,比如修改相对路径或在与main.go相同级别构建二进制文件并从那里运行服务器。

据我所知,嵌入已经对templates文件夹起作用,但是对于static文件夹的内容似乎无效。我认为我没有错地说,虽然服务器成功加载了模板,但在解析DOM时无法定位/static/styles.css.js文件也是如此)(它找不到/static/文件夹)。

在这一点上,任何人的猜测都和我的一样好。

我做错了什么?为什么服务器无法成功路由\static\文件夹?我的代码还有其他问题吗?

老实说,我现在看到的都是胡言乱语。欢迎任何帮助。谢谢。

我的代码

我的文件夹结构如下:

static
    |
    script.js
    styles.css
templates
    |
    template.html
handler.go
main.go

这是我的main.go文件:

package main

import (
    "embed"
    "fmt"
    "net/http"
)

//go:embed static templates
var content embed.FS

func main() {
    // 定义用于显示页面的处理函数
    http.HandleFunc("/", handler)

    // 从“static”目录中提供静态文件(CSS、JS、图像)
    http.Handle("/static/", http.StripPrefix("/static/", http.FileServer(http.FS(content))))

    // 在端口8080上启动服务器
    http.ListenAndServe(":8080", nil)
}

这是我的handler.go文件:

package main

import (
    "html/template"
    "net/http"
    "time"

    /* 其他导入 */
)

func handler(w http.ResponseWriter, r *http.Request) {
	// 定义模板数据
    data, err := /* 返回模板数据的代码 */
    if err != nil {
		panic(err) // 我不确定如何处理这个错误
    }

    // 解析模板文件
    tmpl, err := template.ParseFS(content, "templates/template.html")
    if err != nil {
	    http.Error(w, err.Error(), http.StatusInternalServerError)
	    return
    }

    // 使用数据执行模板
    err = tmpl.Execute(w, data)
    if err != nil {
	    http.Error(w, err.Error(), http.StatusInternalServerError)
	    return
    }
}

这是我的template.html文件:

<!DOCTYPE html>
<html>
<head>
    <title>Countdown</title>
    <link rel="stylesheet" type="text/css" href="/static/style.css">
</head>
<body>
    <h1>Title</h1>
    /* 这里是访问传递给模板的数据字段的代码 */
    <script src="/static/script.js"></script>
</body>
</html>

我没有提供script.js文件,因为它目前是空的,并且因为它引起的问题与style.css的问题相同。

英文:

When I visit localhost:8080 on my browser, I get a page displaying the correct field values from the template, however, the css does not load properly. When I visit the Web Developer Tools panel on my browser I notice that there are two identical errors for the .js and the .css files, namely

The resource from “http://localhost:8080/static/style.css” was blocked due to MIME type (“text/plain”) mismatch (X-Content-Type-Options: nosniff).

(I'm only showing the error associated with the .css file, the other is identical)

I really don't know what else to do, as I've already tried all the simple solutions like modifying the relative paths or building the binary at the same level as main.go and running the server from there.

As far as I can tell, the embedding has worked for the templates folder however it seems it somehow doesn't work for the contents of the static folder. I think I'm not wrong to say that while the server loads the template successfully, it fails to locate the /static/styles.css (same for the .js file) when parsing the DOM (it can't find the /static/ folder).

At this point, anybody's guess is as good as mine.

What am I doing wrong? Why can't the server route the \static\ folder successfully? Is there something else wrong with my code?

Honestly, I'm seeing gibberish at this point. Any help is welcome. Thanks

My code

My folder structure is the following

static
    |
    script.js
    styles.css
templates
    |
    template.html
handler.go
main.go

This is my main.go:

package main

import (
    &quot;embed&quot;
    &quot;fmt&quot;
    &quot;net/http&quot;
)

//go:embed static templates
var content embed.FS

func main() {
    // Define the handler function for the page to display
    http.HandleFunc(&quot;/&quot;, handler)

    // Serve the static files (CSS, JS, images) from the &quot;static&quot; directory
    http.Handle(&quot;/static/&quot;, http.StripPrefix(&quot;/static/&quot;, http.FileServer(http.FS(content))))

    // Start the server on port 8080
    http.ListenAndServe(&quot;:8080&quot;, nil)
}

This is my handler.go file:

package main

import (
    &quot;html/template&quot;
    &quot;net/http&quot;
    &quot;time&quot;

    /* other imports */
)

func handler(w http.ResponseWriter, r *http.Request) {
	// Define the template data
    data, err := /* code that returns data for the template */
    if err != nil {
		panic(err) // I wasn&#39;t sure how to handle this
    }

    // Parse the template file
    tmpl, err := template.ParseFS(content, &quot;templates/template.html&quot;)
    if err != nil {
	    http.Error(w, err.Error(), http.StatusInternalServerError)
	    return
    }

    // Execute the template with the data
    err = tmpl.Execute(w, data)
    if err != nil {
	    http.Error(w, err.Error(), http.StatusInternalServerError)
	    return
    }
}

This is my template.html file:

&lt;!DOCTYPE html&gt;
&lt;html&gt;
&lt;head&gt;
    &lt;title&gt;Countdown&lt;/title&gt;
    &lt;link rel=&quot;stylesheet&quot; type=&quot;text/css&quot; href=&quot;/static/style.css&quot;&gt;
&lt;/head&gt;
&lt;body&gt;
    &lt;h1&gt;Title&lt;/h1&gt;
    /* here is code accessing the fields of the data passed to the template */
    &lt;script src=&quot;/static/script.js&quot;&gt;&lt;/script&gt;
&lt;/body&gt;
&lt;/html&gt;

I don't present the script.js file because it's empty for the time being and because the problem it causes is identical to that of the style.css.

答案1

得分: 2

static不是你的文件系统的根目录,所以http.StripPrefix是不必要的。

使用它,对/static/some-file.js的请求会在文件系统中查找/some-file.js。如果没有使用它,/static/会保留,这就是你的文件系统实际布局的方式。

所以,你需要:

// 从“static”目录中提供静态文件(CSS、JS、图像)
http.Handle("/static/", http.FileServer(http.FS(content)))
英文:

static isn't the root of your filesystem, so http.StripPrefix isn't necessary.

With it, a request to /static/some-file.js looks for /some-file.js in the filesystem. Without it, the /static/ is kept, which is how your filesystem is actually laid out.

So, you want:

// Serve the static files (CSS, JS, images) from the &quot;static&quot; directory
http.Handle(&quot;/static/&quot;, http.FileServer(http.FS(content)))

huangapple
  • 本文由 发表于 2023年4月5日 00:02:23
  • 转载请务必保留本文链接:https://go.coder-hub.com/75931502.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定