我的應用程式運行一個 HTTP 服務器,該服務器提供一些靜態檔案。大多數檔案都可以在根目錄下訪問,/static/但有些檔案(例如index.html)必須在根目錄下才能訪問。
這段代碼試圖通過將檔案嵌入到embed.FS(為了演示,我只index.html在此處嵌入)來實作:
package main
import (
"net/http"
"embed"
"io/fs"
"log"
)
//go:embed index.html
var files embed.FS
type primaryFiles struct {}
func (pf *primaryFiles) Open(name string) (fs.File, error) {
// name will be "." for paths / and /index.html, I guess that's a feature
if name == "." {
return files.Open("index.html")
}
return nil, fs.ErrNotExist
}
func main() {
http.Handle("/", http.FileServer(http.FS(&primaryFiles{})))
http.Handle("/static/", http.StripPrefix("/static/", http.FileServer(http.FS(files))))
log.Fatal(http.ListenAndServe(":8080", nil))
}
現在,在運行代碼時,我可以index.html在http://localhost:8080/static/和 上查詢都很好http://localhost:8080/static/index.html。但是,在http://localhost:8080/和http://localhost:8080/index.html,瀏覽器會給我ERR_TOO_MANY_REDIRECTS. 為什么會這樣?我該如何解決?
我已經嘗試通過".",它會產生一個檔案串列而不是index.html內容。我在go version go1.17.3 darwin/arm64。我還試圖弄清楚發生了什么curl:
$ curl -v http://localhost:8080/index.html
* Trying ::1:8080...
* Connected to localhost (::1) port 8080 (#0)
> GET /index.html HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.77.0
> Accept: */*
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 301 Moved Permanently
< Location: ./
< Date: Mon, 06 Dec 2021 22:05:50 GMT
< Content-Length: 0
<
* Connection #0 to host localhost left intact
$ curl -v http://localhost:8080/
* Trying ::1:8080...
* Connected to localhost (::1) port 8080 (#0)
> GET / HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.77.0
> Accept: */*
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 301 Moved Permanently
< Location: ..//
< Date: Mon, 06 Dec 2021 22:05:12 GMT
< Content-Length: 0
<
* Connection #0 to host localhost left intact
這并不能幫助我理解發生了什么——好吧。/index.html被重定向到./,這似乎是有道理的。但是/被重定向到..//......我不知道該怎么做。
uj5u.com熱心網友回復:
您的primaryFiles.Open實作,當給出時".",回傳一個檔案而不是一個目錄。這是一個錯誤。
上的檔案fs.FS.Open應該會引導您查看fs.ValidPath其 godoc 宣告如下。
包 fs // 匯入“io/fs”
func ValidPath(name string) bool
ValidPath 報告給定的路徑名??在呼叫 Open 時是否有效。傳遞給 open 的路徑名稱是 UTF-8 編碼、無根、斜線分隔的路徑元素序列,如“x/y/z”。路徑名不得包含“.”元素。或“..”或空字串,但根目錄名為“.”的特殊情況除外 . 路徑不得以斜杠開頭或結尾:“/x”和“x/”無效。
請注意,路徑在所有系統上都是用斜線分隔的,甚至是 Windows。包含反斜杠和冒號等其他字符的路徑被接受為有效,但這些字符絕不能被 FS 實作解釋為路徑元素分隔符。
net/http.FileServer依靠遞回重定向最終../應該到達某個目錄的事實,但是根據您的primaryFiles.Open作業方式沒有找到任何目錄。可以說這是一個提升 的機會net/http.FileServer,但目前尚不清楚。
uj5u.com熱心網友回復:
發生的事情部分記錄在http 包中:
作為一種特殊情況,回傳的檔案服務器會將任何以“/index.html”結尾的請求重定向到相同的路徑,而沒有最終的“index.html”。
所以index.html在我的Openfn中看不到任何請求,因為它重定向到..
檔案沒有說明請求.似乎按如下方式處理:
.通過 查詢的目錄Open。這應該回傳一個目錄,我的原始代碼沒有并導致錯誤。- 如果回傳目錄,則搜索檔案
index.html,如果存在,則向Open發出另一個請求。這是我錯過的。
因此,要修復代碼,我需要通過管道將請求都.與index.html實際的檔案:
func (pf *primaryFiles) Open(name string) (fs.File, error) {
if name == "." || name == "index.html" {
return files.Open(name)
}
return nil, fs.ErrNotExist
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/378738.html
上一篇:如何將https重定向到新域?
