summaryrefslogtreecommitdiff
path: root/libgo/go/net/http/request.go
diff options
context:
space:
mode:
Diffstat (limited to 'libgo/go/net/http/request.go')
-rw-r--r--libgo/go/net/http/request.go63
1 files changed, 34 insertions, 29 deletions
diff --git a/libgo/go/net/http/request.go b/libgo/go/net/http/request.go
index fb6bb0aab58..13f367c1a8f 100644
--- a/libgo/go/net/http/request.go
+++ b/libgo/go/net/http/request.go
@@ -27,8 +27,6 @@ import (
"sync"
"golang_org/x/net/idna"
- "golang_org/x/text/unicode/norm"
- "golang_org/x/text/width"
)
const (
@@ -331,6 +329,16 @@ func (r *Request) WithContext(ctx context.Context) *Request {
r2 := new(Request)
*r2 = *r
r2.ctx = ctx
+
+ // Deep copy the URL because it isn't
+ // a map and the URL is mutable by users
+ // of WithContext.
+ if r.URL != nil {
+ r2URL := new(url.URL)
+ *r2URL = *r.URL
+ r2.URL = r2URL
+ }
+
return r2
}
@@ -341,18 +349,6 @@ func (r *Request) ProtoAtLeast(major, minor int) bool {
r.ProtoMajor == major && r.ProtoMinor >= minor
}
-// protoAtLeastOutgoing is like ProtoAtLeast, but is for outgoing
-// requests (see issue 18407) where these fields aren't supposed to
-// matter. As a minor fix for Go 1.8, at least treat (0, 0) as
-// matching HTTP/1.1 or HTTP/1.0. Only HTTP/1.1 is used.
-// TODO(bradfitz): ideally remove this whole method. It shouldn't be used.
-func (r *Request) protoAtLeastOutgoing(major, minor int) bool {
- if r.ProtoMajor == 0 && r.ProtoMinor == 0 && major == 1 && minor <= 1 {
- return true
- }
- return r.ProtoAtLeast(major, minor)
-}
-
// UserAgent returns the client's User-Agent, if sent in the request.
func (r *Request) UserAgent() string {
return r.Header.Get("User-Agent")
@@ -621,6 +617,9 @@ func (req *Request) write(w io.Writer, usingProxy bool, extraHeaders Header, wai
// Write body and trailer
err = tw.WriteBody(w)
if err != nil {
+ if tw.bodyReadError == err {
+ err = requestBodyReadError{err}
+ }
return err
}
@@ -630,17 +629,25 @@ func (req *Request) write(w io.Writer, usingProxy bool, extraHeaders Header, wai
return nil
}
+// requestBodyReadError wraps an error from (*Request).write to indicate
+// that the error came from a Read call on the Request.Body.
+// This error type should not escape the net/http package to users.
+type requestBodyReadError struct{ error }
+
func idnaASCII(v string) (string, error) {
+ // TODO: Consider removing this check after verifying performance is okay.
+ // Right now punycode verification, length checks, context checks, and the
+ // permissible character tests are all omitted. It also prevents the ToASCII
+ // call from salvaging an invalid IDN, when possible. As a result it may be
+ // possible to have two IDNs that appear identical to the user where the
+ // ASCII-only version causes an error downstream whereas the non-ASCII
+ // version does not.
+ // Note that for correct ASCII IDNs ToASCII will only do considerably more
+ // work, but it will not cause an allocation.
if isASCII(v) {
return v, nil
}
- // The idna package doesn't do everything from
- // https://tools.ietf.org/html/rfc5895 so we do it here.
- // TODO(bradfitz): should the idna package do this instead?
- v = strings.ToLower(v)
- v = width.Fold.String(v)
- v = norm.NFC.String(v)
- return idna.ToASCII(v)
+ return idna.Lookup.ToASCII(v)
}
// cleanHost cleans up the host sent in request's Host header.
@@ -755,7 +762,7 @@ func validMethod(method string) bool {
// exact value (instead of -1), GetBody is populated (so 307 and 308
// redirects can replay the body), and Body is set to NoBody if the
// ContentLength is 0.
-func NewRequest(method, urlStr string, body io.Reader) (*Request, error) {
+func NewRequest(method, url string, body io.Reader) (*Request, error) {
if method == "" {
// We document that "" means "GET" for Request.Method, and people have
// relied on that from NewRequest, so keep that working.
@@ -765,7 +772,7 @@ 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)
+ u, err := parseURL(url) // Just url.Parse (url is shadowed for godoc).
if err != nil {
return nil, err
}
@@ -930,6 +937,9 @@ func readRequest(b *bufio.Reader, deleteHostHeader bool) (req *Request, err erro
if !ok {
return nil, &badStringError{"malformed HTTP request", s}
}
+ if !validMethod(req.Method) {
+ return nil, &badStringError{"invalid method", req.Method}
+ }
rawurl := req.RequestURI
if req.ProtoMajor, req.ProtoMinor, ok = ParseHTTPVersion(req.Proto); !ok {
return nil, &badStringError{"malformed HTTP version", req.Proto}
@@ -1021,11 +1031,6 @@ type maxBytesReader struct {
err error // sticky error
}
-func (l *maxBytesReader) tooLarge() (n int, err error) {
- l.err = errors.New("http: request body too large")
- return 0, l.err
-}
-
func (l *maxBytesReader) Read(p []byte) (n int, err error) {
if l.err != nil {
return 0, l.err
@@ -1297,7 +1302,7 @@ func (r *Request) closeBody() {
}
func (r *Request) isReplayable() bool {
- if r.Body == nil {
+ if r.Body == nil || r.Body == NoBody || r.GetBody != nil {
switch valueOrDefault(r.Method, "GET") {
case "GET", "HEAD", "OPTIONS", "TRACE":
return true