Come servite un file html statico utilizzando un server web go?


91

Come servite index.html (o qualche altro file HTML statico) utilizzando un server web go?

Voglio solo un file HTML statico di base (come un articolo, per esempio) che posso servire da un server web go. L'HTML dovrebbe essere modificabile al di fuori del programma go, come sarebbe nel caso durante l'utilizzo di modelli HTML.

Questo è il mio server web che ospita solo testo hardcoded ("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)
}

Risposte:


145

Questo compito è molto semplice con il pacchetto Golang net / http.

Tutto quello che devi fare è:

package main

import (
        "net/http"
)

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

supponendo che i file statici si trovino nella cartella denominata staticnella directory principale del progetto.

Se è nella cartella static, avrai una index.htmlchiamata di file http://localhost:3000/che comporterà il rendering di quel file indice invece di elencare tutti i file disponibili.

Inoltre, chiamare qualsiasi altro file in quella cartella (ad esempio http://localhost:3000/clients.html) mostrerà quel file, correttamente reso dal browser (almeno Chrome, Firefox e Safari :))

AGGIORNAMENTO: pubblicazione di file da un URL diverso da "/"

Se vuoi servire i file, dì dalla cartella ./publicsotto l'URL: localhost:3000/staticdevi usare una funzione aggiuntiva : func StripPrefix(prefix string, h Handler) Handlercome questa:

package main

import (
        "net/http"
)

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

Grazie a ciò, tutti i tuoi file da ./publicsono disponibili sottolocalhost:3000/static

Senza la http.StripPrefixfunzione, se provassi ad accedere al file localhost:3000/static/test.html, il server lo cercherebbe in./public/static/test.html

Questo perché il server considera l'intero URI come un percorso relativo del file.

Fortunatamente, è facilmente risolvibile con la funzione integrata.


3
perché il modello di maniglia /static/non lo è /static?
Bryce

Come servite un file html statico se il file si trova altrove sul disco rigido, completamente al di fuori del progetto?
iamtoc

L'ho provato dal percorso assoluto: / Users / username / path / to / file, e ha funzionato con successo lo stesso.
iamtoc

@Bryce, perché vuoi abbinare la sottostruttura completa ( vedi anche ). Con lo /staticstesso pattern (e strip-prefix) solo le http://example.org/staticrichieste sarebbero servite dal gestore FileServer. Ciò significa che le richieste a http://example.org/static/e così http://example.org/static/foo.cssvia falliranno o saranno gestite da un altro gestore.
maxschlepzig

È possibile servire file statici insieme a percorsi di riposo?
Brain

15

Preferisco usare http.ServeFileper questo oltre http.FileServer. Volevo che la navigazione nelle directory fosse disabilitata, un 404 corretto se mancano dei file e un modo semplice per inserire in casi speciali il file indice. In questo modo, puoi semplicemente rilasciare il binario costruito in una cartella e servirà tutto ciò che è relativo a quel binario. Naturalmente, è possibile utilizzare strings.Replacesu pse avete i file memorizzati in un'altra directory.


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)
}

5

NON è un server FTP: è qualcosa di diverso da quello che intendevo, che sarebbe servire la index.htmlhomepage, come farebbe un normale server web. Ad esempio, quando vado su miodominio.com nel mio browser, voglio index.htmlrenderizzato.

Questo è principalmente ciò che descrive " Scrivere applicazioni Web " e ciò che fa un progetto come hugo (generatore di siti HTML statici).

Si tratta di leggere un file e rispondere con un 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)
    }
}

con renderFile()essenzialmente leggere e impostare il tipo giusto:

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

Forse non ho posto la domanda correttamente. Questo non fornisce un mezzo per costruire un file server, simile a un server FTP? Questo è qualcosa di diverso da quello che intendevo, che sarebbe servire la homepage index.html, come farebbe un normale server web. Ad esempio, quando vado su miodominio.com nel mio browser, voglio che index.html venga visualizzato. Non voglio vedere una directory di file archiviati nel file system del server web. Posso modificare la domanda per riformularla se la mia domanda era fuorviante.
nairware

@nairware ok, ho riscritto la risposta
VonC

Quindi non è possibile creare un sito Web classico in Vai che utilizza pagine HTML e pagine server? Deve essere un sito Web statico o un sito Web basato su modelli?
Spero

0

Questo è facile in golang come:

package main

import (
    "log"
    "net/http"
)

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

"

Puoi semplicemente farlo e assicurarti di mantenere il tuo file HTML come index.html


0

Esempio di come personalizzare il file 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))
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.