Làm cách nào để bạn phân phát tệp html tĩnh bằng máy chủ web?


89

Làm cách nào để bạn phân phát index.html (hoặc một số tệp HTML tĩnh khác) bằng máy chủ web?

Tôi chỉ muốn một tệp HTML tĩnh, cơ bản (ví dụ như một bài báo) mà tôi có thể phân phát từ máy chủ web. HTML phải có thể sửa đổi được bên ngoài chương trình go, như trong trường hợp sử dụng các mẫu HTML.

Đây là máy chủ web của tôi chỉ lưu trữ văn bản được mã hóa cứng ("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)
}

Câu trả lời:


140

Nhiệm vụ đó rất dễ dàng với gói Golang net / http.

Tất cả những gì bạn cần làm là:

package main

import (
        "net/http"
)

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

giả sử rằng các tệp tĩnh nằm trong thư mục có tên statictrong thư mục gốc của dự án.

Nếu nó nằm trong thư mục static, bạn sẽ có lệnh index.htmlgọi tệp http://localhost:3000/dẫn đến hiển thị tệp chỉ mục đó thay vì liệt kê tất cả các tệp có sẵn.

Ngoài ra, việc gọi bất kỳ tệp nào khác trong thư mục đó (ví dụ http://localhost:3000/clients.html) sẽ hiển thị tệp đó, được trình duyệt hiển thị đúng cách (ít nhất là Chrome, Firefox và Safari :))

CẬP NHẬT: phân phát tệp từ url khác với "/"

Nếu Bạn muốn cung cấp tệp, hãy nói từ thư mục ./publicdưới url: localhost:3000/staticBạn phải sử dụng chức năng bổ sung : func StripPrefix(prefix string, h Handler) Handlernhư thế này:

package main

import (
        "net/http"
)

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

Nhờ đó, tất cả các tệp của bạn từ ./publicđều có sẵn tronglocalhost:3000/static

Không có http.StripPrefixchức năng, nếu bạn cố gắng truy cập tệp localhost:3000/static/test.html, máy chủ sẽ tìm kiếm nó trong./public/static/test.html

Điều này là do máy chủ coi toàn bộ URI như một đường dẫn liên quan đến tệp.

May mắn thay, nó dễ dàng được giải quyết với chức năng tích hợp.


3
tại sao xử lý /static/không phải là mẫu /static?
Bryce

Làm cách nào để bạn cung cấp tệp html tĩnh nếu tệp nằm ở nơi khác trên ổ cứng, hoàn toàn bên ngoài dự án?
iamtoc

Tôi đã thử nó từ đường dẫn tuyệt đối: / Users / username / path / to / file, và nó hoạt động thành công giống nhau.
iamtoc

@Bryce, vì bạn muốn khớp với cây con hoàn chỉnh ( xem thêm ). Chỉ /staticvới mẫu (và tiền tố dải), chỉ http://example.org/staticcác yêu cầu sẽ được trình xử lý FileServer phục vụ. Điều đó có nghĩa là các yêu cầu tới http://example.org/static/http://example.org/static/foo.cssv.v. sẽ không thành công hoặc được xử lý bởi một trình xử lý khác.
maxschlepzig

Có thể phân phát tệp tĩnh cùng với các tuyến nghỉ không?
Brain

13

Tôi thích sử dụng http.ServeFilecho điều này hơn http.FileServer. Tôi muốn tính năng duyệt thư mục bị vô hiệu hóa, mã 404 thích hợp nếu tệp bị thiếu và một cách dễ dàng để viết hoa văn đặc biệt cho tệp chỉ mục. Bằng cách này, bạn chỉ có thể thả tệp nhị phân đã xây dựng vào một thư mục và nó sẽ phục vụ mọi thứ liên quan đến tệp nhị phân đó. Tất nhiên, bạn có thể sử dụng strings.Replacetrên pnếu bạn có các tệp được lưu trữ trong một thư mục khác.


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

KHÔNG PHẢI là máy chủ FTP: Đó là một cái gì đó khác với những gì tôi dự định, nó sẽ phục vụ index.htmltrang chủ, giống như một máy chủ web bình thường. Giống như, khi tôi truy cập mydomain.com trong trình duyệt của mình, tôi muốn index.htmlhiển thị.

Đó chủ yếu là những gì " Viết ứng dụng web " mô tả và những gì một dự án như hugo (trình tạo trang web html tĩnh) làm.

Đó là về việc đọc một tệp và phản hồi bằng 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)
    }
}

với renderFile()chủ yếu đọc và thiết lập đúng loại:

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

Có lẽ tôi đã đặt câu hỏi không chính xác. Đây không phải là cung cấp một phương tiện xây dựng một máy chủ tệp, tương tự như một máy chủ FTP? Đó là một cái gì đó khác với những gì tôi dự định, sẽ phục vụ trang chủ index.html, giống như một máy chủ web bình thường. Giống như, khi tôi truy cập mydomain.com trong trình duyệt của mình, tôi muốn index.html được hiển thị. Tôi không muốn xem thư mục các tệp được lưu trữ trên hệ thống tệp của máy chủ web. Tôi có thể chỉnh sửa câu hỏi thành từ khóa nếu câu hỏi của tôi gây hiểu lầm.
nairware,

@nairware ok, tôi đã viết lại câu trả lời
VonC

Vì vậy, không có cách nào để tạo một trang web cổ điển theo Go sử dụng các trang HTML và trang máy chủ? Nó phải là một trang web tĩnh hoặc một trang web dựa trên mẫu?
Spero

0

Điều này dễ dàng trong golang như:

package main

import (
    "log"
    "net/http"
)

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

`

Bạn chỉ có thể làm điều này và đảm bảo giữ tệp HTML của bạn index.html

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.