Bir go web sunucusu kullanarak statik bir html dosyasını nasıl sunarsınız?


91

Bir go web sunucusu kullanarak index.html'yi (veya başka bir statik HTML dosyasını) nasıl sunarsınız?

Bir go web sunucusundan sunabileceğim basit, statik bir HTML dosyası (örneğin bir makale gibi) istiyorum. HTML şablonlarını kullanırken olduğu gibi, HTML go programının dışında değiştirilebilir olmalıdır.

Bu, yalnızca sabit kodlanmış metinleri barındıran web sunucumdur ("Merhaba dünya!").

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

Yanıtlar:


144

Golang net / http paketi ile bu görev çok kolaydır.

Yapmanız gereken tek şey:

package main

import (
        "net/http"
)

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

Statik dosyaların staticprojenin kök dizininde belirtilen klasörde olduğunu varsayarsak .

Klasörde ise static, mevcut tüm dosyaları listelemek yerine bu dizin dosyasını oluşturmaya neden olacak index.htmldosya çağrısına http://localhost:3000/sahip olacaksınız.

Ek olarak, bu klasördeki diğer herhangi bir dosyanın çağrılması (örneğin http://localhost:3000/clients.html), bu dosyanın tarayıcı tarafından düzgün bir şekilde oluşturulmuş olduğunu gösterecektir (en azından Chrome, Firefox ve Safari :))

GÜNCELLEME: "/" dışında url'den dosya sunma

Dosyaları sunmak istiyorsanız, URL'nin ./publicaltındaki klasörden diyelim : Ek işlevi kullanmanızlocalhost:3000/static gerekir : bunun gibi: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)
}

Bunun sayesinde, tüm dosyalarınız ./publicşu adresten temin edilebilir:localhost:3000/static

http.StripPrefixİşlev olmadan , dosyaya erişmeye çalışırsanız localhost:3000/static/test.html, sunucu dosyayı./public/static/test.html

Bunun nedeni, sunucunun tüm URI'yi dosyaya giden göreceli bir yol olarak ele almasıdır.

Neyse ki, yerleşik işlevle kolayca çözülür.


3
neden kalıp /static/değil /static?
Bryce

Dosya sabit sürücüde başka bir yerde, projenin tamamen dışında ise statik bir html dosyasını nasıl sunarsınız?
iamtoc

Mutlak yoldan denedim: / Kullanıcılar / kullanıcı adı / yol / / dosyaya ve aynı şekilde başarılı bir şekilde çalıştı.
iamtoc

@Bryce, çünkü tüm alt ağaçla eşleştirmek istiyorsunuz ( ayrıca bakınız ). Sadece ile /staticsadece desen (ve şerit-öneki) olarak http://example.org/staticistekleri Fileserver işleyicisi tarafından hizmet verilebilir. İçin araçlar istekleri O http://example.org/static/ve http://example.org/static/foo.cssvb başarısız olur veya başka bir işleyici tarafından işlenmelidir.
maxschlepzig

Statik dosyaları dinlenme yolları ile birlikte sunmak mümkün mü?
Beyin

15

Bunun http.ServeFileiçin kullanmayı tercih ederim http.FileServer. Dizine göz atmanın devre dışı bırakılmasını, dosyalar eksikse uygun bir 404 ve dizin dosyasını özel duruma getirmenin kolay bir yolunu istedim. Bu şekilde, yerleşik ikiliyi bir klasöre bırakabilirsiniz ve bu ikiliye göre her şeye hizmet edecektir. Elbette, başka bir dizinde depolanan dosyalarınız varsa strings.Replaceon kullanabilirsiniz 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)
}

5

Bir FTP sunucusu DEĞİL: Bu, amaçladığımdan farklı bir şey index.html, normal bir web sunucusunun yapacağı gibi ana sayfaya hizmet vermek olabilir . Mesela, tarayıcımda alanadim.com'a gittiğimde, işlenmesini istiyorum index.html.

Bu esas olarak " Web Uygulamaları Yazmak " ın tanımladığı ve hugo (statik html site oluşturucu) gibi bir projenin yaptığı şeydir .

Bu, bir dosyayı okumak ve bir ContentType "text / html" ile yanıt vermekle ilgilidir:

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

ile renderFile()esasen okuma ve sağ türünü ayarlayarak:

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

Belki de soruyu doğru sormadım. Bu, bir FTP sunucusuna benzer bir dosya sunucusu oluşturmanın bir yolunu sağlamıyor mu? Bu, normal bir web sunucusunun yapacağı gibi index.html ana sayfasına hizmet etmek istediğimden farklı bir şey. Mesela, tarayıcımda alanadim.com'a gittiğimde index.html'nin işlenmesini istiyorum. Web sunucusunun dosya sisteminde depolanan dosyaların dizinini görmek istemiyorum. Sorum yanıltıcıysa, soruyu yeniden kelime olarak düzenleyebilirim.
nairware

@nairware tamam, cevabı yeniden yazdım
VonC

Yani, Go altında HTML sayfaları ve sunucu sayfaları kullanan klasik bir web sitesi oluşturmanın bir yolu yok mu? Statik bir web sitesi mi yoksa şablon tabanlı bir web sitesi mi olmalı?
Spero

0

Bu golang'da şu şekilde kolaydır:

package main

import (
    "log"
    "net/http"
)

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

'

Bunu yapabilir ve HTML dosyanızı şu şekilde sakladığınızdan emin olabilirsiniz: index.html


0

Nasıl özel servis mp3 dosyası örneği:

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))
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.