Каталог файлового сервера для динамического маршрута

Мой сценарий

Скомпилированные угловые проекты сохраняются как

.
├── branch1
│   ├── commitC
│   │   ├── app1
│   │   │   ├── index.html
│   │   │   └── stylesheet.css
│   └── commitD
│       ├── app1
│       │   ├── index.html
│       │   └── stylesheet.css
│       └── app2
│           ├── index.html
│           └── stylesheet.css
├── branch2
│   ├── commitE
│      ├── app1
│      │   ├── index.html
│      │   └── stylesheet.css
│      └── app2
│          ├── index.html
│          └── stylesheet.css
└── master
    ├── commitA
    │   ├── app1
    │   │   ├── index.html
    │   │   └── stylesheet.css
    └── commitB
        ├── app1
            ├── index.html
            └── stylesheet.css

База данных

TABLE data(id , branch, commit)

Записи: напр.

id branch commit
abc branch1 commitC
def branch1 commitD
ghi master commitA

Теперь я хочу получить доступ

:8080/приложения/{id}

например: localhost:8080/apps/abc

путь должен быть сгенерирован после запроса записи в БД

а файловый сервер обслуживает каталог ./files/branch1/commitC/

теперь я ожидал увидеть папки app1 и app2

Что у меня есть

func main() {
    mux = mux.NewRouter()
    mux.HandleFunc("/apps/{id}/{app}", s.serveApp).Methods("GET")
}

func (s *Server) serveApp(w http.ResponseWriter, r *http.Request) {
    params := mux.Vars(r)

    app := params["app"]
    id := params["id"]

    entry, err := getFromDB(id)
    if err != nil {
        w.Header().Set("Content-Type", "text/html")
        respondWithError(w, http.StatusInternalServerError, err.Error())
        return
    }

    file := filepath.Join(DefaultFolder, entry.Branch, entry.Commit, app, "index.html")

    fmt.Printf("redirecting to %s", file)
    http.ServeFile(w, r, file)
}

как я могу обслуживать весь каталог таким образом, чтобы все файлы css и js могли быть доступны правильно?

Я думаю, мне нужно что-то вроде этого

http.Handle("/tmpfiles/", http.StripPrefix("/tmpfiles/", http.FileServer(http.Dir("/tmp"))))

но как получить доступ к mux.Vars(request) для создания пути к каталогу?

############ О проблеме с отображением CSS

import (
    "log"
    "net/http"

    "github.com/gorilla/mux"
)

func main() {

    mux := mux.NewRouter()

    fs := http.FileServer(http.Dir("static"))
    mux.Handle("/", fs)

    log.Println("Listening...")
    http.ListenAndServe(":3000", mux)
}

Файлы CSS обслуживаются как «текстовые/простые».

Файлы:

  • main.go
  • static/
    • index.html
    • main.css

index.html

<!doctype html>
<html>
<head>
  <meta charset="utf-8">
  <title>A static page</title>
  <link rel="stylesheet" href="main.css">
</head>
<body>
  <h1>Hello from a static page</h1>
</body>
</html>

main.css

body {color: #c0392b}

person Philipp Schartlmüller    schedule 09.12.2020    source источник


Ответы (1)


http.FileServer возвращает обработчик. Этот обработчик можно вызывать вручную вместо регистрации в пути исправления.

Вы передаете ему исходные параметры w http.ResponseWriter, r *http.Request, чтобы http.FileServer мог получить доступ к запросу и написать ответ.

Вам, вероятно, потребуется обернуть http.FileServer в обработчик http.StripPrefix, чтобы путь в исходном запросе был сокращен до пути относительно переменной path.

func main() {
    mux = mux.NewRouter()
    mux.HandleFunc("/apps/{id}/{app}", s.serveApp).Methods("GET")
}

func (s *Server) serveApp(w http.ResponseWriter, r *http.Request) {
    params := mux.Vars(r)

    app := params["app"]
    id := params["id"]

    entry, err := getFromDB(id)
    if err != nil {
        w.Header().Set("Content-Type", "text/html")
        respondWithError(w, http.StatusInternalServerError, err.Error())
        return
    }

    path := filepath.Join(DefaultFolder, entry.Branch, entry.Commit, app)
    // the part already handled by serveApp handler must be stripped.
    baseURL := fmt.Sprintf("/apps/%s/%s/", id, app)

    pathHandler := http.FileServer(http.Dir(path))
    http.StripPrefix(baseURL, pathHandler).ServeHTTP(w, r)

    // or in one line
    // http.FileServer(http.StripPrefix(baseURL, http.Dir(path)).ServeHTTP(w, r)
}
person TehSphinX    schedule 09.12.2020
comment
Часть зачистки может потребовать некоторой настройки. - person TehSphinX; 09.12.2020
comment
Спасибо за вашу помощь, теперь эта часть работает. Следующая проблема заключается в том, что файлы css обслуживаются неправильно... Отказался применять стиль из «localhost: 3000/main.css», потому что его тип MIME («text/plain ') не является поддерживаемым типом MIME таблицы стилей, и включена строгая проверка MIME ... где я должен установить тип MIME? .. Добавлен пример в конце вопроса .. может быть, у вас есть идея :) - person Philipp Schartlmüller; 09.12.2020
comment
Тип MIME устанавливается через заголовок Content-Type. Таким образом, вы можете установить его с помощью w.Header().Set("Content-Type", "text/html"). Но мне интересно, почему http.FileServer не устанавливает его правильно. Вы уже установили заголовок самостоятельно? - person TehSphinX; 09.12.2020
comment
Примечание. Задавать дополнительный вопрос лучше всего в новом вопросе или в комментариях. Редактирование исходного вопроса немного проблематично, так как ответы не обязательно будут редактироваться снова, чтобы учесть дополнительный вопрос. - person TehSphinX; 09.12.2020