英文:
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 (
"embed"
"fmt"
"net/http"
)
//go:embed static templates
var content embed.FS
func main() {
// Define the handler function for the page to display
http.HandleFunc("/", handler)
// Serve the static files (CSS, JS, images) from the "static" directory
http.Handle("/static/", http.StripPrefix("/static/", http.FileServer(http.FS(content))))
// Start the server on port 8080
http.ListenAndServe(":8080", nil)
}
This is my handler.go
file:
package main
import (
"html/template"
"net/http"
"time"
/* 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't sure how to handle this
}
// Parse the template file
tmpl, err := template.ParseFS(content, "templates/template.html")
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:
<!DOCTYPE html>
<html>
<head>
<title>Countdown</title>
<link rel="stylesheet" type="text/css" href="/static/style.css">
</head>
<body>
<h1>Title</h1>
/* here is code accessing the fields of the data passed to the template */
<script src="/static/script.js"></script>
</body>
</html>
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 "static" directory
http.Handle("/static/", http.FileServer(http.FS(content)))
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论