Wie können Sie eine statische HTML-Datei über einen Go-Webserver bereitstellen?

89

Wie können Sie index.html (oder eine andere statische HTML-Datei) über einen go-Webserver bereitstellen?

Ich möchte nur eine einfache, statische HTML-Datei (wie zum Beispiel einen Artikel), die ich von einem Go-Webserver aus bereitstellen kann. Der HTML-Code sollte außerhalb des go-Programms geändert werden können, wie dies bei Verwendung von HTML-Vorlagen der Fall wäre.

Dies ist mein Webserver, auf dem nur fest codierter Text gehostet wird ("Hallo Welt!").

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
quelle

Antworten:

140

Diese Aufgabe ist mit dem Golang net / http-Paket sehr einfach.

Alles was Sie tun müssen ist:

package main

import (
        "net/http"
)

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

Angenommen, statische Dateien befinden sich in einem Ordner staticim Stammverzeichnis des Projekts.

Wenn es sich im Ordner befindet static, wird eine index.htmlDatei http://localhost:3000/aufgerufen , die dazu führt, dass diese Indexdatei gerendert wird, anstatt alle verfügbaren Dateien aufzulisten.

Wenn Sie beispielsweise eine andere Datei in diesem Ordner aufrufen (z. B. http://localhost:3000/clients.html), wird diese Datei angezeigt, die vom Browser ordnungsgemäß gerendert wurde (mindestens Chrome, Firefox und Safari :)).

UPDATE: Serving von Dateien mit einer anderen URL als "/"

Wenn Sie Dateien ./publicbereitstellen möchten, sagen Sie aus dem Ordner unter URL: localhost:3000/staticSie müssen zusätzliche Funktionen verwenden : func StripPrefix(prefix string, h Handler) Handlerwie folgt:

package main

import (
        "net/http"
)

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

Dank dessen sind alle Ihre Dateien ./publicunter verfügbarlocalhost:3000/static

http.StripPrefixWenn Sie ohne Funktion versuchen würden, auf eine Datei zuzugreifen localhost:3000/static/test.html, würde der Server danach suchen./public/static/test.html

Dies liegt daran, dass der Server den gesamten URI als relativen Pfad zur Datei behandelt.

Glücklicherweise ist es mit der eingebauten Funktion leicht zu lösen.

Jarema
quelle
3
Warum ist Griffmuster /static/nicht /static?
Bryce
Wie können Sie eine statische HTML-Datei bereitstellen, wenn sich die Datei an einer anderen Stelle auf der Festplatte außerhalb des Projekts befindet?
iamtoc
Ich habe es vom absoluten Pfad aus versucht: / Users / username / path / to / file, und es hat trotzdem erfolgreich funktioniert.
iamtoc
@Bryce, weil Sie den vollständigen Teilbaum abgleichen möchten ( siehe auch ). Mit genau /staticwie Muster (und Streifenpräfix) würden nur http://example.org/staticAnforderungen vom FileServer-Handler bedient. Das bedeutet, dass Anfragen an http://example.org/static/und http://example.org/static/foo.cssusw. fehlschlagen oder von einem anderen Handler bearbeitet werden.
Maxschlepzig
Ist es möglich, statische Dateien zusammen mit Restrouten bereitzustellen?
Gehirn
13

Ich benutze es lieber http.ServeFiledafür http.FileServer. Ich wollte, dass das Durchsuchen von Verzeichnissen deaktiviert wird, eine richtige 404, wenn Dateien fehlen, und eine einfache Möglichkeit, die Indexdatei in Sonderfällen zu erstellen. Auf diese Weise können Sie die erstellte Binärdatei einfach in einem Ordner ablegen und alles, was mit dieser Binärdatei zu tun hat, wird bereitgestellt. Natürlich können Sie strings.Replaceon verwenden, pwenn Sie die Dateien in einem anderen Verzeichnis gespeichert haben.


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
quelle
5

KEIN FTP-Server: Das ist etwas anderes als das, was ich beabsichtigt hatte, nämlich die index.htmlHomepage zu bedienen , wie es ein normaler Webserver tun würde. Wenn ich in meinem Browser zu mydomain.com gehe, möchte ich index.htmlgerendert werden.

Dies ist hauptsächlich das, was " Schreiben von Webanwendungen " beschreibt und was ein Projekt wie hugo (statischer HTML-Site-Generator) tut.

Es geht darum, eine Datei zu lesen und mit einem ContentType "text / html" zu antworten:

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

mit im renderFile()Wesentlichen Lesen und Einstellen des richtigen Typs:

 file, err = ioutil.ReadFile(server.MediaPath + filename)
 if ext != "" {
    w.Header().Set("Content-Type", mime.TypeByExtension(ext))
 }
VonC
quelle
Vielleicht habe ich die Frage nicht richtig gestellt. Bietet dies nicht eine Möglichkeit zum Erstellen eines Dateiservers, ähnlich einem FTP-Server? Das ist etwas anderes als das, was ich beabsichtigt hatte, nämlich die index.html-Homepage zu bedienen, wie es ein normaler Webserver tun würde. Wenn ich in meinem Browser zu mydomain.com gehe, möchte ich, dass index.html gerendert wird. Ich möchte kein Verzeichnis von Dateien sehen, die im Dateisystem des Webservers gespeichert sind. Ich kann die Frage bearbeiten, um sie neu zu formulieren, wenn meine Frage irreführend war.
Nairware
@airware ok, ich habe die Antwort umgeschrieben
VonC
Es gibt also keine Möglichkeit, unter Go eine klassische Website zu erstellen, die HTML-Seiten und Serverseiten verwendet. Muss es sich entweder um eine statische Website oder eine vorlagenbasierte Website handeln?
Spero
0

Dies ist in Golang einfach als:

package main

import (
    "log"
    "net/http"
)

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

`

Sie können dies einfach tun und sicherstellen, dass Ihre HTML-Datei wie folgt bleibt index.html

Nishant Raj
quelle