40

Golang では、ホームページを提供するためのルート ディレクトリ ハンドラを保持しながら、ルート ディレクトリから静的コンテンツを提供するにはどうすればよいですか。

例として、次の単純な Web サーバーを使用します。

package main

import (
    "fmt"
    "net/http"
)

func main() {
    http.HandleFunc("/", HomeHandler) // homepage
    http.ListenAndServe(":8080", nil)
}

func HomeHandler(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, "HomeHandler")
}

私が行った場合

http.Handle("/", http.FileServer(http.Dir("./")))

「/」に 2 つの登録があるというパニックが発生します。私がインターネットで見つけたすべての Golang の例は、静的コンテンツを異なるディレクトリから提供することを提案していますが、それは、sitemap.xml、favicon.ico、robots.txt などの慣習的または慣習的なファイルにはあま​​り役に立ちません。常にルートから提供されることが義務付けられています。

私が求めている動作は、Apache、Nginx、または IIS などのほとんどの Web サーバーで見られる動作であり、最初にルールをトラバースし、ルールが見つからない場合は実際のファイルを探し、ファイルが見つからない場合はそれを探します。 404s。私の推測では、a を書く代わりに、拡張子を持つファイルを参照しているかどうかをチェックhttp.HandlerFuncする a を書く必要があり、http.Handlerそうであればファイルの存在をチェックしてファイルを提供し、それ以外の場合は 404 またはホームページを提供する必要があります。 "/"。残念ながら、そのようなタスクを開始する方法さえわかりません。

私の一部は、状況を非常に複雑にしすぎて、何かが欠けていると思わせると言っていますか? 任意のガイダンスをいただければ幸いです。

4

3 に答える 3

40

別の ( ServeMuxを使用しない) ソリューションは、ルート ディレクトリにある各ファイルを明示的に提供することです。背後にある考え方は、ルートベースのファイルの数を非常に少なく保つことです。 sitemap.xmlfavicon.icorobots.txtは、ルートから提供することが実際に義務付けられています。

package main

import (
    "fmt"
    "net/http"
)

func HomeHandler(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, "HomeHandler")
}

func serveSingle(pattern string, filename string) {
    http.HandleFunc(pattern, func(w http.ResponseWriter, r *http.Request) {
        http.ServeFile(w, r, filename)
    })
}

func main() {
    http.HandleFunc("/", HomeHandler) // homepage

    // Mandatory root-based resources
    serveSingle("/sitemap.xml", "./sitemap.xml")
    serveSingle("/favicon.ico", "./favicon.ico")
    serveSingle("/robots.txt", "./robots.txt")

    // Normal resources
    http.Handle("/static", http.FileServer(http.Dir("./static/")))

    http.ListenAndServe(":8080", nil)
}

他のすべてのリソース (CSS、JS など) を適切なサブディレクトリに移動してください/static/

于 2013-01-06T23:29:27.023 に答える
24

役立つかもしれないと私が考えた 1 つのことは、独自の ServeMux を作成できるということです。chttp が静的ファイルを提供できる ServeMux になるように、例に追加しました。次に、HomeHandler は、ファイルを提供する必要があるかどうかを確認します。「。」をチェックするだけです。しかし、あなたは多くのことをすることができました。単なるアイデアで、あなたが探しているものではないかもしれません。

package main

import (
    "fmt"
    "net/http"
    "strings"
)   

var chttp = http.NewServeMux()

func main() {

    chttp.Handle("/", http.FileServer(http.Dir("./")))

    http.HandleFunc("/", HomeHandler) // homepage
    http.ListenAndServe(":8080", nil)
}   

func HomeHandler(w http.ResponseWriter, r *http.Request) {

    if (strings.Contains(r.URL.Path, ".")) {
        chttp.ServeHTTP(w, r)
    } else {
        fmt.Fprintf(w, "HomeHandler")
    }   
} 
于 2012-12-29T22:41:57.473 に答える
20

Gorilla mux パッケージの使用:

r := mux.NewRouter()

//put your regular handlers here

//then comes root handler
r.HandleFunc("/", homePageHandler)
//if a path not found until now, e.g. "/image/tiny.png" 
//this will look at "./public/image/tiny.png" at filesystem
r.PathPrefix("/").Handler(http.FileServer(http.Dir("./public/")))

http.Handle("/", r)
http.ListenAndServe(":8080", nil)
于 2013-10-16T23:06:59.263 に答える