36
36
// ErrMissingFile is returned by FormFile when the provided file field name
37
37
// is either not present in the request or not a file field.
38
var ErrMissingFile = os.ErrorString("http: no such file")
38
var ErrMissingFile = os.NewError("http: no such file")
40
40
// HTTP request parsing errors.
41
41
type ProtocolError struct {
45
func (err *ProtocolError) String() string { return err.ErrorString }
46
48
ErrLineTooLong = &ProtocolError{"header line too long"}
47
49
ErrHeaderTooLong = &ProtocolError{"header too long"}
61
63
func (e *badStringError) String() string { return fmt.Sprintf("%s %q", e.what, e.str) }
63
var reqExcludeHeader = map[string]bool{
65
// Headers that Request.Write handles itself and should be skipped.
66
var reqWriteExcludeHeader = map[string]bool{
65
68
"User-Agent": true,
67
69
"Content-Length": true,
68
70
"Transfer-Encoding": true,
125
124
// or the host name given in the URL itself.
128
// The referring URL, if sent in the request.
130
// Referer is misspelled as in the request itself,
131
// a mistake from the earliest days of HTTP.
132
// This value can also be fetched from the Header map
133
// as Header["Referer"]; the benefit of making it
134
// available as a structure field is that the compiler
135
// can diagnose programs that use the alternate
136
// (correct English) spelling req.Referrer but cannot
137
// diagnose programs that use Header["Referrer"].
140
// The User-Agent: header string, if sent in the request.
143
127
// The parsed form. Only available after ParseForm is called.
176
160
r.ProtoMajor == major && r.ProtoMinor >= minor
163
// UserAgent returns the client's User-Agent, if sent in the request.
164
func (r *Request) UserAgent() string {
165
return r.Header.Get("User-Agent")
168
// Cookies parses and returns the HTTP cookies sent with the request.
169
func (r *Request) Cookies() []*Cookie {
170
return readCookies(r.Header, "")
173
var ErrNoCookie = os.NewError("http: named cookied not present")
175
// Cookie returns the named cookie provided in the request or
176
// ErrNoCookie if not found.
177
func (r *Request) Cookie(name string) (*Cookie, os.Error) {
178
for _, c := range readCookies(r.Header, name) {
181
return nil, ErrNoCookie
184
// AddCookie adds a cookie to the request. Per RFC 6265 section 5.4,
185
// AddCookie does not attach more than one Cookie header field. That
186
// means all cookies, if any, are written into the same line,
187
// separated by semicolon.
188
func (r *Request) AddCookie(c *Cookie) {
189
s := fmt.Sprintf("%s=%s", sanitizeName(c.Name), sanitizeValue(c.Value))
190
if c := r.Header.Get("Cookie"); c != "" {
191
r.Header.Set("Cookie", c+"; "+s)
193
r.Header.Set("Cookie", s)
197
// Referer returns the referring URL, if sent in the request.
199
// Referer is misspelled as in the request itself, a mistake from the
200
// earliest days of HTTP. This value can also be fetched from the
201
// Header map as Header["Referer"]; the benefit of making it available
202
// as a method is that the compiler can diagnose programs that use the
203
// alternate (correct English) spelling req.Referrer() but cannot
204
// diagnose programs that use Header["Referrer"].
205
func (r *Request) Referer() string {
206
return r.Header.Get("Referer")
179
209
// multipartByReader is a sentinel value.
180
210
// Its presence in Request.MultipartForm indicates that parsing of the request
181
211
// body has been handed off to a MultipartReader instead of ParseMultipartFrom.
188
218
// multipart/form-data POST request, else returns nil and an error.
189
219
// Use this function instead of ParseMultipartForm to
190
220
// process the request body as a stream.
191
func (r *Request) MultipartReader() (multipart.Reader, os.Error) {
221
func (r *Request) MultipartReader() (*multipart.Reader, os.Error) {
192
222
if r.MultipartForm == multipartByReader {
193
223
return nil, os.NewError("http: MultipartReader called twice")
199
229
return r.multipartReader()
202
func (r *Request) multipartReader() (multipart.Reader, os.Error) {
232
func (r *Request) multipartReader() (*multipart.Reader, os.Error) {
203
233
v := r.Header.Get("Content-Type")
205
235
return nil, ErrNotMultipart
280
fmt.Fprintf(w, "%s %s HTTP/1.1\r\n", valueOrDefault(req.Method, "GET"), uri)
307
bw := bufio.NewWriter(w)
308
fmt.Fprintf(bw, "%s %s HTTP/1.1\r\n", valueOrDefault(req.Method, "GET"), uri)
283
fmt.Fprintf(w, "Host: %s\r\n", host)
284
fmt.Fprintf(w, "User-Agent: %s\r\n", valueOrDefault(req.UserAgent, defaultUserAgent))
285
if req.Referer != "" {
286
fmt.Fprintf(w, "Referer: %s\r\n", req.Referer)
311
fmt.Fprintf(bw, "Host: %s\r\n", host)
313
// Use the defaultUserAgent unless the Header contains one, which
314
// may be blank to not send the header.
315
userAgent := defaultUserAgent
316
if req.Header != nil {
317
if ua := req.Header["User-Agent"]; len(ua) > 0 {
322
fmt.Fprintf(bw, "User-Agent: %s\r\n", userAgent)
289
325
// Process Body,ContentLength,Close,Trailer
294
err = tw.WriteHeader(w)
330
err = tw.WriteHeader(bw)
299
335
// TODO: split long values? (If so, should share code with Conn.Write)
300
// TODO: if Header includes values for Host, User-Agent, or Referer, this
301
// may conflict with the User-Agent or Referer headers we add manually.
302
// One solution would be to remove the Host, UserAgent, and Referer fields
303
// from Request, and introduce Request methods along the lines of
304
// Response.{GetHeader,AddHeader} and string constants for "Host",
305
// "User-Agent" and "Referer".
306
err = req.Header.WriteSubset(w, reqExcludeHeader)
336
err = req.Header.WriteSubset(bw, reqWriteExcludeHeader)
311
if err = writeCookies(w, req.Cookie); err != nil {
315
io.WriteString(w, "\r\n")
341
io.WriteString(bw, "\r\n")
317
343
// Write body and trailer
318
err = tw.WriteBody(w)
344
err = tw.WriteBody(bw)
485
507
req.ContentLength = int64(v.Len())
486
508
case *bytes.Buffer:
487
509
req.ContentLength = int64(v.Len())
489
req.ContentLength = -1 // chunked
491
if req.ContentLength == 0 {
492
// To prevent chunking and disambiguate this
493
// from the default ContentLength zero value.
494
req.TransferEncoding = []string{"identity"}
527
if f = strings.Split(s, " ", 3); len(f) < 3 {
542
if f = strings.SplitN(s, " ", 3); len(f) < 3 {
528
543
return nil, &badStringError{"malformed HTTP request", s}
530
545
req.Method, req.RawURL, req.Proto = f[0], f[1], f[2]
560
575
fixPragmaCacheControl(req.Header)
562
// Pull out useful fields as a convenience to clients.
563
req.Referer = req.Header.Get("Referer")
564
req.Header.Del("Referer")
566
req.UserAgent = req.Header.Get("User-Agent")
567
req.Header.Del("User-Agent")
569
577
// TODO: Parse specific header values:
571
579
// Accept-Encoding
654
660
func parseQuery(m Values, query string) (err os.Error) {
655
for _, kv := range strings.Split(query, "&", -1) {
661
for _, kv := range strings.Split(query, "&") {
656
662
if len(kv) == 0 {
659
kvPair := strings.Split(kv, "=", 2)
665
kvPair := strings.SplitN(kv, "=", 2)
661
667
var key, value string
691
697
if r.Method == "POST" {
692
698
if r.Body == nil {
693
return os.ErrorString("missing form body")
699
return os.NewError("missing form body")
695
701
ct := r.Header.Get("Content-Type")
696
switch strings.Split(ct, ";", 2)[0] {
702
switch strings.SplitN(ct, ";", 2)[0] {
697
703
case "text/plain", "application/x-www-form-urlencoded", "":
698
704
const maxFormSize = int64(10 << 20) // 10 MB is a lot of text.
699
705
b, e := ioutil.ReadAll(io.LimitReader(r.Body, maxFormSize+1))