Как вы обслуживаете статический HTML-файл, используя веб-сервер Go?

Как вы обслуживаете index.html (или другой статический HTML-файл) с помощью веб-сервера go?

Мне просто нужен базовый статический HTML-файл (например, статья), который я могу обслуживать с веб-сервера. HTML должен быть изменяем за пределами программы go, как это было бы в случае использования шаблонов HTML.

Это мой веб-сервер, на котором размещается только жестко закодированный текст ("Hello world!").

package main

import (
  "fmt"
  "net/http"
)

func handler(w http.ResponseWriter, r *http.Request) {
  fmt.Fprintf(w, "Hello world!")
}

func main() {
  http.HandleFunc("/", handler)
  http.ListenAndServe(":3000", nil)
}

8 ответов

Решение

Эта задача очень проста с пакетом Golang net/http.

Все, что вам нужно сделать, это:

package main

import (
        "net/http"
)

func main() {
        http.Handle("/", http.FileServer(http.Dir("./static")))
        http.ListenAndServe(":3000", nil)
}

при условии, что статические файлы находятся в папке с именем static в корневой директории проекта.

Если это в папке staticвы будете иметь index.html вызов файла http://localhost:3000/ что приведет к отображению этого индексного файла вместо перечисления всех доступных файлов.

Кроме того, вызывая любой другой файл в этой папке (например, http://localhost:3000/clients.html) покажет этот файл, правильно отображенный браузером (по крайней мере, Chrome, Firefox и Safari:))

ОБНОВЛЕНИЕ: обслуживание файлов с URL, отличного от "/"

Если вы хотите обслуживать файлы, скажем, из папки ./public под URL: localhost:3000/static Вы должны использовать дополнительную функцию: func StripPrefix(prefix string, h Handler) Handler как это:

package main

import (
        "net/http"
)

func main() {
        http.Handle("/static/", http.StripPrefix("/static/", http.FileServer(http.Dir("./public"))))
        http.ListenAndServe(":3000", nil)
}

Благодаря этому все ваши файлы из ./public доступны под localhost:3000/static

Без http.StripPrefix функция, если вы попытаетесь получить доступ к файлу localhost:3000/static/test.html, сервер будет искать его в ./public/static/test.html

Это связано с тем, что сервер обрабатывает весь URI как относительный путь к файлу.

К счастью, это легко решается с помощью встроенной функции.

Я предпочитаю использовать http.ServeFile для этого http.FileServer. Я хотел отключить просмотр каталогов, правильный 404, если файлы отсутствуют, и простой способ особого случая индексного файла. Таким образом, вы можете просто перетащить встроенный двоичный файл в папку, и он будет обслуживать все, что связано с этим двоичным файлом. Конечно, вы можете использоватьstrings.Replace на p если у вас есть файлы, хранящиеся в другом каталоге.


func main() {
    fmt.Println("Now Listening on 80")
    http.HandleFunc("/", serveFiles)
    log.Fatal(http.ListenAndServe(":80", nil))
}

func serveFiles(w http.ResponseWriter, r *http.Request) {
    fmt.Println(r.URL.Path)
    p := "." + r.URL.Path
    if p == "./" {
        p = "./static/index.html"
    }
    http.ServeFile(w, r, p)
}

Если вы хотите обслуживать только 1 файл, а не полный каталог, вы можете использовать http.ServeFile

      http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
    http.ServeFile(w, r, "index.html")
})

НЕ FTP-сервер: это нечто отличное от того, что я намеревался, что бы служить index.html Домашняя страница, как обычный веб-сервер. Мол, когда я захожу на mydomain.com в моем браузере, я хочу index.html оказаны.

Это в основном то, что описывает " Написание веб-приложений", и то, что делает такой проект, как hugo (генератор статических сайтов html).

Речь идет о чтении файла и ответе с помощью ContentType "text/html":

func (server *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
    err := server.renderFile(w, r.URL.Path)
    if err != nil {
        w.Header().Set("Content-Type", "text/html; charset=utf-8")
        w.WriteHeader(http.StatusNotFound)
        server.fn404(w, r)
    }
}

с renderFile() по сути, чтение и установка правильного типа:

 file, err = ioutil.ReadFile(server.MediaPath + filename)
 if ext != "" {
    w.Header().Set("Content-Type", mime.TypeByExtension(ext))
 }

Вы также можете использовать Gorilla Mux Router для сервера статических файлов. Предположим, у вас есть статическая папка и файл index.html в корне.

      import  "github.com/gorilla/mux"

  func main(){
    router := mux.NewRouter()
        fs := http.FileServer(http.Dir("./static/"))
        router.PathPrefix("/static/").Handler(http.StripPrefix("/static/", fs))
        log.Fatal(http.ListenAndServe(":8080", router))
}

Пример того, как пользовательский файл mp3:

      r := http.NewServeMux()
r.HandleFunc("/file/*", func(w http.ResponseWriter, r *http.Request) {

    // Prepare file path
    pathFile := strings.ReplaceAll(r.RequestURI, "/file/", "./my_path/")
    f, err := os.Open(pathFile)
    if f == nil || err != nil {
        return
    }

    // Read file into memory
    fileBytes, err := ioutil.ReadAll(f)
    if err != nil {
        log.Println(err)
        _, _ = fmt.Fprintf(w, "Error file bytes")
        return
    }

    // Check mime type
    mime := http.DetectContentType(fileBytes)
    if mime != "audio/mpeg" {
        log.Println("Error file type")
        _, _ = fmt.Fprintf(w, "Error file type")
        return
    }

    // Custom headers
    r.Header.Add("Content-Type", "audio/mpeg")
    r.Header.Add("Cache-Control", "must-revalidate, post-check=0, pre-check=0")
    r.Header.Add("Content-Description", "File Transfer")
    r.Header.Add("Content-Disposition", "attachment; filename=file.mp3")
    r.Header.Add("Content-Transfer-Encoding", "binary")
    r.Header.Add("Expires", "0")
    r.Header.Add("Pragma", "public")
    r.Header.Add("Content-Length", strconv.Itoa(len(fileBytes)))
    http.ServeFile(w, r, pathFile)
})
log.Fatal(http.ListenAndServe(":80", r))

В голанге это просто:

package main

import (
    "log"
    "net/http"
)

func main() {
    log.Fatal(http.ListenAndServe(":8080", http.FileServer(http.Dir("."))))
}

`

Вы можете просто сделать это и сохранить свой HTML-файл как index.html

Это будет обслуживать файл index.html (если он у вас в корне) в браузере на localhost:8080

      func main() {
    port := flag.String("p", "8080", "port to serve on")
    directory := flag.String("d", ".", "static file folder")
    flag.Parse()

    http.Handle("/", http.FileServer(http.Dir(*directory)))

    log.Printf("Serving %s on HTTP port: %s\n", *directory, *port)
    log.Fatal(http.ListenAndServe(":"+*port, nil))
}
Другие вопросы по тегам