Go Webサーバーを使用して静的HTMLファイルをどのように提供しますか?


91

go Webサーバーを使用してindex.html(またはその他の静的HTMLファイル)をどのように提供しますか?

go Webサーバーから提供できる基本的な静的HTMLファイル(記事など)が必要です。HTMLは、HTMLテンプレートを使用する場合と同様に、goプログラムの外部で変更可能である必要があります。

これは、ハードコードされたテキスト( "Hello world!")のみをホストする私のWebサーバーです。

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からファイルを提供

ファイルを提供したい場合、たとえば./publicURLの下のフォルダから:追加の関数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ですか?
ブライス

ファイルがハードドライブの他の場所、プロジェクト全体の外にある場合、静的htmlファイルをどのように提供しますか?
iamtoc 2018年

絶対パス/ Users / username / path / to / fileから試してみましたが、まったく同じように機能しました。
iamtoc

@Bryce、完全なサブツリーと一致させたいため(も参照)。/staticパターン(およびストリッププレフィックス)と同じように、http://example.org/staticリクエストのみがFileServerハンドラーによって処理されます。つまりhttp://example.org/static/http://example.org/static/foo.cssなどへのリクエストは失敗するか、別のハンドラーによって処理されます。
maxschlepzig

静的ファイルをRESTルートと一緒に提供することは可能ですか?

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、通常のWebサーバーのようにホームページにサービスを提供するという私が意図したものとは異なります。たとえば、ブラウザでmydomain.comにアクセスすると、index.htmlレンダリングが必要になります。

それは主に「Webアプリケーションの作成」が説明していることであり、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サーバーのようなファイルサーバーを構築する手段を提供していませんか?これは、通常のWebサーバーのようにindex.htmlホームページを提供するという私が意図したものとは異なります。たとえば、ブラウザでmydomain.comにアクセスすると、index.htmlがレンダリングされます。Webサーバーのファイルシステムに保存されているファイルのディレクトリを見たくありません。質問が誤解を招く場合は、質問を編集して言い換えることができます。
nairware 2014年

@nairwareわかりました、答えを書き直しました
VonC 2014年

では、HTMLページとサーバーページを使用する従来のWebサイトをGoで作成する方法はありませんか?静的なWebサイトまたはテンプレートベースのWebサイトのいずれかである必要がありますか?
スペロ2018

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.