คุณให้บริการไฟล์ html แบบคงที่โดยใช้ go web server ได้อย่างไร?


91

คุณให้บริการ index.html (หรือไฟล์ HTML แบบคงที่อื่น ๆ ) โดยใช้ go web server ได้อย่างไร

ฉันต้องการไฟล์ HTML พื้นฐานแบบคงที่ (เช่นบทความเป็นต้น) ซึ่งฉันสามารถใช้งานได้จากเว็บเซิร์ฟเวอร์ go 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)
}

คำตอบ:


144

งานนั้นง่ายมากด้วยแพ็คเกจ 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 ทั้งหมดเป็นพา ธ สัมพัทธ์ไปยังไฟล์

โชคดีที่แก้ไขได้อย่างง่ายดายด้วยฟังก์ชันในตัว


3
ทำไมรูปแบบที่จับเป็น/static/ไม่ได้/static?
Bryce

คุณจะให้บริการไฟล์ html แบบคงที่ได้อย่างไรหากไฟล์นั้นอยู่ที่อื่นในฮาร์ดไดรฟ์ภายนอกโครงการทั้งหมด
iamtoc

ฉันพยายามจากพา ธ สัมบูรณ์: / Users / username / path / to / file และมันก็ทำงานได้สำเร็จเหมือนเดิม
iamtoc

@ ไบรซ์เพราะคุณต้องการจับคู่แผนผังย่อยที่สมบูรณ์ ( ดูเพิ่มเติม ) ด้วย/staticรูปแบบเช่นเดียวกับ (และแถบคำนำหน้า) http://example.org/staticคำขอเท่านั้นที่จะให้บริการโดยตัวจัดการ FileServer นั่นหมายความว่าคำขอhttp://example.org/static/และhttp://example.org/static/foo.cssอื่น ๆ จะล้มเหลวหรือได้รับการจัดการโดยตัวจัดการอื่น
maxschlepzig

เป็นไปได้หรือไม่ที่จะให้บริการไฟล์แบบคงที่พร้อมกับเส้นทางที่เหลือ?
Brain

15

ผมชอบใช้มานานกว่านี้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)
}

5

ไม่ใช่เซิร์ฟเวอร์ 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))
 }

บางทีฉันอาจจะถามคำถามไม่ถูก นี่ไม่ใช่วิธีการสร้างไฟล์เซิร์ฟเวอร์คล้ายกับเซิร์ฟเวอร์ FTP ใช่หรือไม่? นั่นเป็นสิ่งที่แตกต่างจากที่ฉันตั้งใจไว้ซึ่งจะให้บริการหน้าแรกของ index.html เหมือนที่เว็บเซิร์ฟเวอร์ทั่วไปจะทำ เช่นเมื่อฉันไปที่ mydomain.com ในเบราว์เซอร์ของฉันฉันต้องการให้ index.html แสดงผล ฉันไม่ต้องการเห็นไดเร็กทอรีของไฟล์ที่เก็บไว้ในระบบไฟล์ของเว็บเซิร์ฟเวอร์ ฉันสามารถแก้ไขคำถามเพื่อเปลี่ยนคำซ้ำได้หากคำถามของฉันทำให้เข้าใจผิด
nairware

@nairware โอเคฉันเขียนคำตอบใหม่แล้ว
VonC

จึงไม่มีวิธีใดในการสร้างเว็บไซต์แบบคลาสสิกภายใต้ Go ที่ใช้หน้า HTML และหน้าเซิร์ฟเวอร์? ต้องเป็นเว็บไซต์แบบคงที่หรือเว็บไซต์ที่ใช้เทมเพลตหรือไม่
Spero

0

นี่เป็นเรื่องง่ายใน golang เป็น:

package main

import (
    "log"
    "net/http"
)

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

`

คุณสามารถทำได้และตรวจสอบให้แน่ใจว่าไฟล์ HTML ของคุณเป็นไฟล์ index.html


0

ตัวอย่างวิธีการให้บริการไฟล์ 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))
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.