我如何在Go中处理不同方法的对/的HTTP请求?

huangapple go评论77阅读模式
英文:

How can I handle http requests of different methods to / in Go?

问题

我正在尝试找出在Go中处理对“/”和仅“/”的请求的最佳方法,并以不同的方式处理不同的方法。这是我想出的最好的方法:

package main

import (
    "fmt"
    "html"
    "log"
    "net/http"
)

func main() {
    http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
        if r.URL.Path != "/" {
            http.NotFound(w, r)
            return
        }

        if r.Method == "GET" {
            fmt.Fprintf(w, "GET, %q", html.EscapeString(r.URL.Path))
        } else if r.Method == "POST" {
            fmt.Fprintf(w, "POST, %q", html.EscapeString(r.URL.Path))
        } else {
            http.Error(w, "Invalid request method.", 405)
        }
    })

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

这是Go的惯用写法吗?这是我在标准http库中能做的最好的吗?我更喜欢像express或Sinatra那样做一些类似http.HandleGet("/", handler)的事情。有没有一个适合编写简单REST服务的好框架?web.go看起来很有吸引力,但似乎停滞不前。

谢谢你的建议。

英文:

I'm trying to figure out the best way to handle requests to / and only / in Go and handle different methods in different ways. Here's the best I've come up with:

package main

import (
	"fmt"
	"html"
	"log"
	"net/http"
)

func main() {
	http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		if r.URL.Path != "/" {
			http.NotFound(w, r)
			return
		}

		if r.Method == "GET" {
			fmt.Fprintf(w, "GET, %q", html.EscapeString(r.URL.Path))
		} else if r.Method == "POST" {
			fmt.Fprintf(w, "POST, %q", html.EscapeString(r.URL.Path))
		} else {
			http.Error(w, "Invalid request method.", 405)
		}
	})

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

Is this idiomatic Go? Is this the best I can do with the standard http lib? I'd much rather do something like http.HandleGet("/", handler) as in express or Sinatra. Is there a good framework for writing simple REST services? web.go looks attractive but appears stagnant.

Thank you for your advice.

答案1

得分: 125

为了确保只提供根目录服务:你正在做正确的事情。在某些情况下,您可能希望调用http.FileServer对象的ServeHttp方法,而不是调用NotFound;这取决于您是否还有其他要提供的杂项文件。

为了以不同的方式处理不同的方法:我的许多HTTP处理程序只包含像这样的switch语句:

switch r.Method {
case http.MethodGet:
    // 提供资源。
case http.MethodPost:
    // 创建新记录。
case http.MethodPut:
    // 更新现有记录。
case http.MethodDelete:
    // 删除记录。
default:
    http.Error(w, "不允许的方法", http.StatusMethodNotAllowed)
}

当然,您可能会发现像gorilla这样的第三方包对您更好。

英文:

To ensure that you only serve the root: You're doing the right thing. In some cases you would want to call the ServeHttp method of an http.FileServer object instead of calling NotFound; it depends whether you have miscellaneous files that you want to serve as well.

To handle different methods differently: Many of my HTTP handlers contain nothing but a switch statement like this:

switch r.Method {
case http.MethodGet:
	// Serve the resource.
case http.MethodPost:
	// Create a new record.
case http.MethodPut:
	// Update an existing record.
case http.MethodDelete:
	// Remove the record.
default:
	http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
}

Of course, you may find that a third-party package like gorilla works better for you.

答案2

得分: 45

嗯,我实际上正准备睡觉,所以快速评论一下查看http://www.gorillatoolkit.org/pkg/mux,它非常好,并且可以做你想要的事情,只需查看文档。例如

func main() {
    r := mux.NewRouter()
    r.HandleFunc("/", HomeHandler)
    r.HandleFunc("/products", ProductsHandler)
    r.HandleFunc("/articles", ArticlesHandler)
    http.Handle("/", r)
}

r.HandleFunc("/products", ProductsHandler).
    Host("www.domain.com").
    Methods("GET").
    Schemes("http")

以及许多其他可能性和执行上述操作的方法。

但我觉得有必要解决问题的另一部分,“这是我能做的最好的吗”。如果标准库有点太简单,一个很好的资源可以查看这里:https://github.com/golang/go/wiki/Projects#web-libraries(特别链接到Web库)。

英文:

eh, I was actually heading to bed and thus the quick comment on looking at http://www.gorillatoolkit.org/pkg/mux which is really nice and does what you want, just give the docs a look over. For example

func main() {
    r := mux.NewRouter()
    r.HandleFunc("/", HomeHandler)
    r.HandleFunc("/products", ProductsHandler)
    r.HandleFunc("/articles", ArticlesHandler)
    http.Handle("/", r)
}

and

r.HandleFunc("/products", ProductsHandler).
    Host("www.domain.com").
    Methods("GET").
    Schemes("http")

and many other possibilities and ways to perform the above operations.

But I felt a need to address the other part of the question, "Is this the best I can do". If the std lib is a little too bare, a great resource to check out is here: https://github.com/golang/go/wiki/Projects#web-libraries (linked specifically to web libraries).

huangapple
  • 本文由 发表于 2013年3月6日 14:54:46
  • 转载请务必保留本文链接:https://go.coder-hub.com/15240884.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定