Jak obsłużyć statyczny plik html za pomocą serwera internetowego go?

89

W jaki sposób udostępniasz plik index.html (lub inny statyczny plik HTML) za pomocą serwera internetowego go?

Chcę tylko podstawowego, statycznego pliku HTML (na przykład artykułu), który mogę wyświetlać z serwera internetowego go. Kod HTML powinien być modyfikowalny poza programem go, tak jak w przypadku korzystania z szablonów HTML.

To jest mój serwer WWW, który obsługuje tylko tekst zakodowany na stałe („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)
}
nairware
źródło

Odpowiedzi:

140

To zadanie jest bardzo łatwe z pakietem Golang net / http.

Wszystko, co musisz zrobić, to:

package main

import (
        "net/http"
)

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

zakładając, że pliki statyczne znajdują się w folderze o nazwie staticw katalogu głównym projektu.

Jeśli jest w folderze static, będziesz mieć index.htmlwywołanie pliku, http://localhost:3000/co spowoduje renderowanie tego pliku indeksu zamiast wyświetlania wszystkich dostępnych plików.

Dodatkowo wywołanie dowolnego innego pliku w tym folderze (na przykład http://localhost:3000/clients.html) pokaże ten plik, poprawnie wyrenderowany przez przeglądarkę (przynajmniej Chrome, Firefox i Safari :))

UPDATE: wyświetlanie plików z adresu URL innego niż „/”

Jeśli chcesz udostępniać pliki, powiedz z folderu ./publicpod adresem URL: localhost:3000/staticMusisz użyć dodatkowej funkcji : na func StripPrefix(prefix string, h Handler) Handlerprzykład:

package main

import (
        "net/http"
)

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

Dzięki temu wszystkie Twoje pliki ./publicsą dostępne podlocalhost:3000/static

Bez http.StripPrefixfunkcji, gdybyś próbował uzyskać dostęp do pliku localhost:3000/static/test.html, serwer szukałby go w./public/static/test.html

Dzieje się tak, ponieważ serwer traktuje cały identyfikator URI jako ścieżkę względną do pliku.

Na szczęście jest to łatwe do rozwiązania dzięki wbudowanej funkcji.

Jarema
źródło
3
dlaczego wzór uchwytu /static/nie jest /static?
Bryce
Jak udostępnić statyczny plik html, jeśli plik znajduje się w innym miejscu na dysku twardym, całkowicie poza projektem?
iamtoc
Próbowałem to z bezwzględną ścieżką: / Users / username / path / to / file i działało pomyślnie tak samo.
iamtoc
@Bryce, ponieważ chcesz dopasować całe poddrzewo ( zobacz także ). W przypadku /staticwzorca (i prefiksu strip) tylko http://example.org/staticżądania byłyby obsługiwane przez program obsługi FileServer. Oznacza to, że wnioski do http://example.org/static/i http://example.org/static/foo.cssitp zawiedzie lub być obsługiwane przez innego przewodnika.
maxschlepzig
Czy można udostępniać pliki statyczne razem z trasami odpoczynku?
Brain
13

Wolę używać http.ServeFiledo tego ponad http.FileServer. Chciałem wyłączyć przeglądanie katalogów, poprawny 404 jeśli brakuje plików i łatwy sposób na specjalne oznaczenie pliku indeksu. W ten sposób możesz po prostu upuścić wbudowany plik binarny do folderu i będzie on obsługiwał wszystko względem tego pliku binarnego. Oczywiście możesz użyć strings.Replaceon, pjeśli masz pliki zapisane w innym katalogu.


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)
}
jerblack
źródło
5

NIE serwer FTP: jest to coś innego niż to, co zamierzałem, czyli obsługiwać index.htmlstronę główną, tak jak robiłby to normalny serwer WWW. Na przykład, gdy wchodzę w przeglądarce do witryny mojadomena.com, chcę index.htmlrenderować.

To jest głównie to, co opisuje „ Pisanie aplikacji internetowych ” i co robi projekt taki jak hugo (statyczny generator witryn HTML).

Chodzi o czytanie pliku i odpowiadanie za pomocą 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)
    }
}

z renderFile()zasadniczo czytaniem i ustawieniem odpowiedniego typu:

 file, err = ioutil.ReadFile(server.MediaPath + filename)
 if ext != "" {
    w.Header().Set("Content-Type", mime.TypeByExtension(ext))
 }
VonC
źródło
Być może nie zadałem tego pytania poprawnie. Czy nie jest to sposób na zbudowanie serwera plików, podobnie do serwera FTP? To jest coś innego niż to, co zamierzałem, czyli obsługę strony głównej index.html, tak jak robiłby to normalny serwer WWW. Na przykład, gdy wchodzę w przeglądarce do witryny mojadomena.com, chcę renderować plik index.html. Nie chcę widzieć katalogu plików przechowywanych w systemie plików serwera WWW. Mogę edytować pytanie, aby przeredagować, jeśli moje pytanie wprowadzało w błąd.
nairware
@nairware ok, przepisałem odpowiedź
VonC
Więc nie ma sposobu na stworzenie klasycznej witryny w Go, która używa stron HTML i stron serwera? Czy musi to być witryna statyczna czy oparta na szablonie?
Spero,
0

W Golang jest to łatwe, ponieważ:

package main

import (
    "log"
    "net/http"
)

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

`

Możesz to zrobić i upewnić się, że plik HTML jest w formacie index.html

Nishant Raj
źródło