return major, minor, true
}
+func validMethod(method string) bool {
+ /*
+ Method = "OPTIONS" ; Section 9.2
+ | "GET" ; Section 9.3
+ | "HEAD" ; Section 9.4
+ | "POST" ; Section 9.5
+ | "PUT" ; Section 9.6
+ | "DELETE" ; Section 9.7
+ | "TRACE" ; Section 9.8
+ | "CONNECT" ; Section 9.9
+ | extension-method
+ extension-method = token
+ token = 1*<any CHAR except CTLs or separators>
+ */
+ return len(method) > 0 && strings.IndexFunc(method, isNotToken) == -1
+}
+
// NewRequest returns a new Request given a method, URL, and optional body.
//
// If the provided body is also an io.Closer, the returned
// type's documentation for the difference between inbound and outbound
// request fields.
func NewRequest(method, urlStr string, body io.Reader) (*Request, error) {
+ if !validMethod(method) {
+ return nil, fmt.Errorf("net/http: invalid method %q", method)
+ }
u, err := url.Parse(urlStr)
if err != nil {
return nil, err
}
}
+func TestRequestInvalidMethod(t *testing.T) {
+ _, err := NewRequest("bad method", "http://foo.com/", nil)
+ if err == nil {
+ t.Error("expected error from NewRequest with invalid method")
+ }
+ req, err := NewRequest("GET", "http://foo.example/", nil)
+ if err != nil {
+ t.Fatal(err)
+ }
+ req.Method = "bad method"
+ _, err = DefaultClient.Do(req)
+ if err == nil || !strings.Contains(err.Error(), "invalid method") {
+ t.Errorf("Transport error = %v; want invalid method", err)
+ }
+}
+
func TestNewRequestContentLength(t *testing.T) {
readByte := func(r io.Reader) io.Reader {
var b [1]byte
req.closeBody()
return nil, &badStringError{"unsupported protocol scheme", s}
}
+ if !validMethod(req.Method) {
+ return nil, fmt.Errorf("net/http: invalid method %q", req.Method)
+ }
if req.URL.Host == "" {
req.closeBody()
return nil, errors.New("http: no Host in request URL")