Ошибка 404 при обслуживании файлов по не корневым путям
Я запускаю эту команду "иди, запустите webapp / main.go". Причина в том, что движок приложения будет вызывать мое приложение из корневого каталога, поэтому я изменил пути для работы с вызовом файла из корневого каталога. Я также не против, если у вас есть советы по использованию Go.
└── webapp
├── app.yaml
├── assets
│ ├── css
│ │ └── index.css
│ └── img
├── main.go
├── main_test.go
└── templates
└── index.html
Не понимаю, как такая банальная вещь может ошибаться. localhost:8080 / css / index.css работает нормально. У меня также есть другая функция-обработчик для обслуживания localhost:8080 / static / css / index.css, но я получаю ошибку 404. Все работало без сбоев, когда я использовал команду "запустить main.go" и удалить "webapp" из кода. Тем не менее, как это может работать с /, а не с / static /. Как видно из этого ответа /questions/13550483/pochemu-mne-nuzhno-ispolzovat-httpstripprefix-dlya-dostupa-k-moim-staticheskim-fajlam/13550488#13550488, он должен служить./webapp/assets/static как каталог. Я также пробовал http.StripPrefix, но тоже не повезло.
package main
import (
"flag"
"log"
"net/http"
"os"
"path/filepath"
"sync"
"text/template"
)
type templateHandler struct {
once sync.Once
filename string
templ *template.Template
}
// ServeHTTP handles the HTTP request.
func (t *templateHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
t.once.Do(func() {
t.templ = template.Must(template.ParseFiles(filepath.Join("webapp", "templates", t.filename)))
})
if err := t.templ.Execute(w, r); err != nil {
log.Printf("Error executing template: %v", err)
http.Error(w, "Internal server error", http.StatusInternalServerError)
}
}
func main() {
dir, err := os.Getwd()
if err != nil {
log.Printf(err.Error())
}
log.Printf("dir: %s", dir)
// command flags
var addr = flag.String("addr", ":8080", "The addr of the application.")
flag.Parse()
// env variables
envPort := os.Getenv("PORT")
if envPort != "" {
envPort = ":" + envPort
addr = &envPort
}
fs := http.FileServer(http.Dir("./webapp/assets"))
http.Handle("/static/", fs)
log.Printf("Listening on port %s", *addr)
// http.Handle("/", &templateHandler{filename: "index.html"})
if err := http.ListenAndServe(*addr, fs); err != nil {
log.Fatal(err)
}
}
1 ответ
"как это может работать с /, а не с /static/"
Потому что вы проходите
fs
прямо к
ListenAndServe
, это означает, что DefaultServeMux
который используется
http.Handle("/static/", fs)
игнорируется / отменяется.
Handle регистрирует обработчик для данного шаблона в DefaultServeMux. В документации по ServeMux объясняется, как сопоставляются шаблоны.
ListenAndServe прослушивает адрес сетевого адреса TCP, а затем вызывает Serve с обработчиком для обработки запросов на входящих соединениях. Принятые подключения настроены для включения поддержки активности TCP.
Обработчик обычно равен нулю, и в этом случае используется DefaultServeMux.
ListenAndServe всегда возвращает ошибку, отличную от нуля.
В общем, что вам нужно сделать, это примерно так:
fs := http.FileServer(http.Dir("./webapp/assets"))
// register fs for "/static/" in DefaultServeMux
http.Handle("/static/", fs)
// start listening at addr and serve incoming requests
// using DefaultServeMux as the router (because nil).
if err := http.ListenAndServe(*addr, nil); err != nil {
log.Fatal(err)
}
Если в вашей настройке есть другие проблемы, возможно, что ваше приложение может сразу не работать должным образом, однако это изменение, безусловно, является требованием, чтобы приблизиться к этой цели.