1 2 3 4 5 6 7 package http 8 9 import ( 10 "bufio" 11 "bytes" 12 "context" 13 "crypto/tls" 14 "encoding/base64" 15 "errors" 16 "fmt" 17 "io" 18 "maps" 19 "mime" 20 "mime/multipart" 21 "net/http/httptrace" 22 "net/http/internal/ascii" 23 "net/textproto" 24 "net/url" 25 urlpkg "net/url" 26 "strconv" 27 "strings" 28 "sync" 29 _ "unsafe" 30 31 "golang.org/x/net/http/httpguts" 32 "golang.org/x/net/idna" 33 ) 34 35 const ( 36 defaultMaxMemory = 32 << 20 37 ) 38 39 40 41 var ErrMissingFile = errors.New("http: no such file") 42 43 44 45 46 47 type ProtocolError struct { 48 ErrorString string 49 } 50 51 func (pe *ProtocolError) Error() string { return pe.ErrorString } 52 53 54 func (pe *ProtocolError) Is(err error) bool { 55 return pe == ErrNotSupported && err == errors.ErrUnsupported 56 } 57 58 var ( 59 60 61 62 63 64 65 ErrNotSupported = &ProtocolError{"feature not supported"} 66 67 68 69 70 ErrUnexpectedTrailer = &ProtocolError{"trailer header without chunked transfer encoding"} 71 72 73 74 ErrMissingBoundary = &ProtocolError{"no multipart boundary param in Content-Type"} 75 76 77 78 ErrNotMultipart = &ProtocolError{"request Content-Type isn't multipart/form-data"} 79 80 81 82 83 ErrHeaderTooLong = &ProtocolError{"header too long"} 84 85 86 87 88 ErrShortBody = &ProtocolError{"entity body too short"} 89 90 91 92 93 ErrMissingContentLength = &ProtocolError{"missing ContentLength in HEAD response"} 94 ) 95 96 func badStringError(what, val string) error { return fmt.Errorf("%s %q", what, val) } 97 98 99 var reqWriteExcludeHeader = map[string]bool{ 100 "Host": true, 101 "User-Agent": true, 102 "Content-Length": true, 103 "Transfer-Encoding": true, 104 "Trailer": true, 105 } 106 107 108 109 110 111 112 113 type Request struct { 114 115 116 Method string 117 118 119 120 121 122 123 124 125 126 127 128 129 130 URL *url.URL 131 132 133 134 135 136 137 Proto string 138 ProtoMajor int 139 ProtoMinor int 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 Header Header 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 Body io.ReadCloser 189 190 191 192 193 194 195 196 GetBody func() (io.ReadCloser, error) 197 198 199 200 201 202 203 204 205 ContentLength int64 206 207 208 209 210 211 212 TransferEncoding []string 213 214 215 216 217 218 219 220 221 222 223 224 Close bool 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 Host string 246 247 248 249 250 251 Form url.Values 252 253 254 255 256 257 258 PostForm url.Values 259 260 261 262 263 MultipartForm *multipart.Form 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 Trailer Header 284 285 286 287 288 289 290 291 292 RemoteAddr string 293 294 295 296 297 298 RequestURI string 299 300 301 302 303 304 305 306 307 TLS *tls.ConnectionState 308 309 310 311 312 313 314 315 316 317 318 Cancel <-chan struct{} 319 320 321 322 323 Response *Response 324 325 326 327 Pattern string 328 329 330 331 332 333 ctx context.Context 334 335 336 pat *pattern 337 matches []string 338 otherValues map[string]string 339 } 340 341 342 343 344 345 346 347 348 349 350 351 352 func (r *Request) Context() context.Context { 353 if r.ctx != nil { 354 return r.ctx 355 } 356 return context.Background() 357 } 358 359 360 361 362 363 364 365 366 367 368 func (r *Request) WithContext(ctx context.Context) *Request { 369 if ctx == nil { 370 panic("nil context") 371 } 372 r2 := new(Request) 373 *r2 = *r 374 r2.ctx = ctx 375 return r2 376 } 377 378 379 380 381 382 383 384 385 386 func (r *Request) Clone(ctx context.Context) *Request { 387 if ctx == nil { 388 panic("nil context") 389 } 390 r2 := new(Request) 391 *r2 = *r 392 r2.ctx = ctx 393 r2.URL = cloneURL(r.URL) 394 r2.Header = r.Header.Clone() 395 r2.Trailer = r.Trailer.Clone() 396 if s := r.TransferEncoding; s != nil { 397 s2 := make([]string, len(s)) 398 copy(s2, s) 399 r2.TransferEncoding = s2 400 } 401 r2.Form = cloneURLValues(r.Form) 402 r2.PostForm = cloneURLValues(r.PostForm) 403 r2.MultipartForm = cloneMultipartForm(r.MultipartForm) 404 405 406 if s := r.matches; s != nil { 407 s2 := make([]string, len(s)) 408 copy(s2, s) 409 r2.matches = s2 410 } 411 r2.otherValues = maps.Clone(r.otherValues) 412 return r2 413 } 414 415 416 417 func (r *Request) ProtoAtLeast(major, minor int) bool { 418 return r.ProtoMajor > major || 419 r.ProtoMajor == major && r.ProtoMinor >= minor 420 } 421 422 423 func (r *Request) UserAgent() string { 424 return r.Header.Get("User-Agent") 425 } 426 427 428 func (r *Request) Cookies() []*Cookie { 429 return readCookies(r.Header, "") 430 } 431 432 433 434 func (r *Request) CookiesNamed(name string) []*Cookie { 435 if name == "" { 436 return []*Cookie{} 437 } 438 return readCookies(r.Header, name) 439 } 440 441 442 var ErrNoCookie = errors.New("http: named cookie not present") 443 444 445 446 447 448 func (r *Request) Cookie(name string) (*Cookie, error) { 449 if name == "" { 450 return nil, ErrNoCookie 451 } 452 for _, c := range readCookies(r.Header, name) { 453 return c, nil 454 } 455 return nil, ErrNoCookie 456 } 457 458 459 460 461 462 463 464 func (r *Request) AddCookie(c *Cookie) { 465 s := fmt.Sprintf("%s=%s", sanitizeCookieName(c.Name), sanitizeCookieValue(c.Value, c.Quoted)) 466 if c := r.Header.Get("Cookie"); c != "" { 467 r.Header.Set("Cookie", c+"; "+s) 468 } else { 469 r.Header.Set("Cookie", s) 470 } 471 } 472 473 474 475 476 477 478 479 480 481 func (r *Request) Referer() string { 482 return r.Header.Get("Referer") 483 } 484 485 486 487 488 var multipartByReader = &multipart.Form{ 489 Value: make(map[string][]string), 490 File: make(map[string][]*multipart.FileHeader), 491 } 492 493 494 495 496 497 func (r *Request) MultipartReader() (*multipart.Reader, error) { 498 if r.MultipartForm == multipartByReader { 499 return nil, errors.New("http: MultipartReader called twice") 500 } 501 if r.MultipartForm != nil { 502 return nil, errors.New("http: multipart handled by ParseMultipartForm") 503 } 504 r.MultipartForm = multipartByReader 505 return r.multipartReader(true) 506 } 507 508 func (r *Request) multipartReader(allowMixed bool) (*multipart.Reader, error) { 509 v := r.Header.Get("Content-Type") 510 if v == "" { 511 return nil, ErrNotMultipart 512 } 513 if r.Body == nil { 514 return nil, errors.New("missing form body") 515 } 516 d, params, err := mime.ParseMediaType(v) 517 if err != nil || !(d == "multipart/form-data" || allowMixed && d == "multipart/mixed") { 518 return nil, ErrNotMultipart 519 } 520 boundary, ok := params["boundary"] 521 if !ok { 522 return nil, ErrMissingBoundary 523 } 524 return multipart.NewReader(r.Body, boundary), nil 525 } 526 527 528 529 func (r *Request) isH2Upgrade() bool { 530 return r.Method == "PRI" && len(r.Header) == 0 && r.URL.Path == "*" && r.Proto == "HTTP/2.0" 531 } 532 533 534 func valueOrDefault(value, def string) string { 535 if value != "" { 536 return value 537 } 538 return def 539 } 540 541 542 543 544 545 const defaultUserAgent = "Go-http-client/1.1" 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 func (r *Request) Write(w io.Writer) error { 562 return r.write(w, false, nil, nil) 563 } 564 565 566 567 568 569 570 571 func (r *Request) WriteProxy(w io.Writer) error { 572 return r.write(w, true, nil, nil) 573 } 574 575 576 577 var errMissingHost = errors.New("http: Request.Write on Request with no Host or URL set") 578 579 580 581 582 func (r *Request) write(w io.Writer, usingProxy bool, extraHeaders Header, waitForContinue func() bool) (err error) { 583 trace := httptrace.ContextClientTrace(r.Context()) 584 if trace != nil && trace.WroteRequest != nil { 585 defer func() { 586 trace.WroteRequest(httptrace.WroteRequestInfo{ 587 Err: err, 588 }) 589 }() 590 } 591 closed := false 592 defer func() { 593 if closed { 594 return 595 } 596 if closeErr := r.closeBody(); closeErr != nil && err == nil { 597 err = closeErr 598 } 599 }() 600 601 602 603 604 605 host := r.Host 606 if host == "" { 607 if r.URL == nil { 608 return errMissingHost 609 } 610 host = r.URL.Host 611 } 612 host, err = httpguts.PunycodeHostPort(host) 613 if err != nil { 614 return err 615 } 616 617 618 619 620 621 if !httpguts.ValidHostHeader(host) { 622 623 624 625 626 627 628 629 630 631 632 633 634 if !usingProxy { 635 host = "" 636 } else { 637 return errors.New("http: invalid Host header") 638 } 639 } 640 641 642 643 644 host = removeZone(host) 645 646 ruri := r.URL.RequestURI() 647 if usingProxy && r.URL.Scheme != "" && r.URL.Opaque == "" { 648 ruri = r.URL.Scheme + "://" + host + ruri 649 } else if r.Method == "CONNECT" && r.URL.Path == "" { 650 651 ruri = host 652 if r.URL.Opaque != "" { 653 ruri = r.URL.Opaque 654 } 655 } 656 if stringContainsCTLByte(ruri) { 657 return errors.New("net/http: can't write control character in Request.URL") 658 } 659 660 661 662 663 664 665 666 667 var bw *bufio.Writer 668 if _, ok := w.(io.ByteWriter); !ok { 669 bw = bufio.NewWriter(w) 670 w = bw 671 } 672 673 _, err = fmt.Fprintf(w, "%s %s HTTP/1.1\r\n", valueOrDefault(r.Method, "GET"), ruri) 674 if err != nil { 675 return err 676 } 677 678 679 _, err = fmt.Fprintf(w, "Host: %s\r\n", host) 680 if err != nil { 681 return err 682 } 683 if trace != nil && trace.WroteHeaderField != nil { 684 trace.WroteHeaderField("Host", []string{host}) 685 } 686 687 688 689 userAgent := defaultUserAgent 690 if r.Header.has("User-Agent") { 691 userAgent = r.Header.Get("User-Agent") 692 } 693 if userAgent != "" { 694 userAgent = headerNewlineToSpace.Replace(userAgent) 695 userAgent = textproto.TrimString(userAgent) 696 _, err = fmt.Fprintf(w, "User-Agent: %s\r\n", userAgent) 697 if err != nil { 698 return err 699 } 700 if trace != nil && trace.WroteHeaderField != nil { 701 trace.WroteHeaderField("User-Agent", []string{userAgent}) 702 } 703 } 704 705 706 tw, err := newTransferWriter(r) 707 if err != nil { 708 return err 709 } 710 err = tw.writeHeader(w, trace) 711 if err != nil { 712 return err 713 } 714 715 err = r.Header.writeSubset(w, reqWriteExcludeHeader, trace) 716 if err != nil { 717 return err 718 } 719 720 if extraHeaders != nil { 721 err = extraHeaders.write(w, trace) 722 if err != nil { 723 return err 724 } 725 } 726 727 _, err = io.WriteString(w, "\r\n") 728 if err != nil { 729 return err 730 } 731 732 if trace != nil && trace.WroteHeaders != nil { 733 trace.WroteHeaders() 734 } 735 736 737 if waitForContinue != nil { 738 if bw, ok := w.(*bufio.Writer); ok { 739 err = bw.Flush() 740 if err != nil { 741 return err 742 } 743 } 744 if trace != nil && trace.Wait100Continue != nil { 745 trace.Wait100Continue() 746 } 747 if !waitForContinue() { 748 closed = true 749 r.closeBody() 750 return nil 751 } 752 } 753 754 if bw, ok := w.(*bufio.Writer); ok && tw.FlushHeaders { 755 if err := bw.Flush(); err != nil { 756 return err 757 } 758 } 759 760 761 closed = true 762 err = tw.writeBody(w) 763 if err != nil { 764 if tw.bodyReadError == err { 765 err = requestBodyReadError{err} 766 } 767 return err 768 } 769 770 if bw != nil { 771 return bw.Flush() 772 } 773 return nil 774 } 775 776 777 778 779 type requestBodyReadError struct{ error } 780 781 func idnaASCII(v string) (string, error) { 782 783 784 785 786 787 788 789 790 791 if ascii.Is(v) { 792 return v, nil 793 } 794 return idna.Lookup.ToASCII(v) 795 } 796 797 798 799 func removeZone(host string) string { 800 if !strings.HasPrefix(host, "[") { 801 return host 802 } 803 i := strings.LastIndex(host, "]") 804 if i < 0 { 805 return host 806 } 807 j := strings.LastIndex(host[:i], "%") 808 if j < 0 { 809 return host 810 } 811 return host[:j] + host[i:] 812 } 813 814 815 816 817 func ParseHTTPVersion(vers string) (major, minor int, ok bool) { 818 switch vers { 819 case "HTTP/1.1": 820 return 1, 1, true 821 case "HTTP/1.0": 822 return 1, 0, true 823 } 824 if !strings.HasPrefix(vers, "HTTP/") { 825 return 0, 0, false 826 } 827 if len(vers) != len("HTTP/X.Y") { 828 return 0, 0, false 829 } 830 if vers[6] != '.' { 831 return 0, 0, false 832 } 833 maj, err := strconv.ParseUint(vers[5:6], 10, 0) 834 if err != nil { 835 return 0, 0, false 836 } 837 min, err := strconv.ParseUint(vers[7:8], 10, 0) 838 if err != nil { 839 return 0, 0, false 840 } 841 return int(maj), int(min), true 842 } 843 844 func validMethod(method string) bool { 845 858 return isToken(method) 859 } 860 861 862 func NewRequest(method, url string, body io.Reader) (*Request, error) { 863 return NewRequestWithContext(context.Background(), method, url, body) 864 } 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 func NewRequestWithContext(ctx context.Context, method, url string, body io.Reader) (*Request, error) { 890 if method == "" { 891 892 893 894 method = "GET" 895 } 896 if !validMethod(method) { 897 return nil, fmt.Errorf("net/http: invalid method %q", method) 898 } 899 if ctx == nil { 900 return nil, errors.New("net/http: nil Context") 901 } 902 u, err := urlpkg.Parse(url) 903 if err != nil { 904 return nil, err 905 } 906 rc, ok := body.(io.ReadCloser) 907 if !ok && body != nil { 908 rc = io.NopCloser(body) 909 } 910 911 u.Host = removeEmptyPort(u.Host) 912 req := &Request{ 913 ctx: ctx, 914 Method: method, 915 URL: u, 916 Proto: "HTTP/1.1", 917 ProtoMajor: 1, 918 ProtoMinor: 1, 919 Header: make(Header), 920 Body: rc, 921 Host: u.Host, 922 } 923 if body != nil { 924 switch v := body.(type) { 925 case *bytes.Buffer: 926 req.ContentLength = int64(v.Len()) 927 buf := v.Bytes() 928 req.GetBody = func() (io.ReadCloser, error) { 929 r := bytes.NewReader(buf) 930 return io.NopCloser(r), nil 931 } 932 case *bytes.Reader: 933 req.ContentLength = int64(v.Len()) 934 snapshot := *v 935 req.GetBody = func() (io.ReadCloser, error) { 936 r := snapshot 937 return io.NopCloser(&r), nil 938 } 939 case *strings.Reader: 940 req.ContentLength = int64(v.Len()) 941 snapshot := *v 942 req.GetBody = func() (io.ReadCloser, error) { 943 r := snapshot 944 return io.NopCloser(&r), nil 945 } 946 default: 947 948 949 950 951 952 } 953 954 955 956 957 958 959 960 961 if req.GetBody != nil && req.ContentLength == 0 { 962 req.Body = NoBody 963 req.GetBody = func() (io.ReadCloser, error) { return NoBody, nil } 964 } 965 } 966 967 return req, nil 968 } 969 970 971 972 973 func (r *Request) BasicAuth() (username, password string, ok bool) { 974 auth := r.Header.Get("Authorization") 975 if auth == "" { 976 return "", "", false 977 } 978 return parseBasicAuth(auth) 979 } 980 981 982 983 984 985 986 987 988 989 990 991 992 993 func parseBasicAuth(auth string) (username, password string, ok bool) { 994 const prefix = "Basic " 995 996 if len(auth) < len(prefix) || !ascii.EqualFold(auth[:len(prefix)], prefix) { 997 return "", "", false 998 } 999 c, err := base64.StdEncoding.DecodeString(auth[len(prefix):]) 1000 if err != nil { 1001 return "", "", false 1002 } 1003 cs := string(c) 1004 username, password, ok = strings.Cut(cs, ":") 1005 if !ok { 1006 return "", "", false 1007 } 1008 return username, password, true 1009 } 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 func (r *Request) SetBasicAuth(username, password string) { 1023 r.Header.Set("Authorization", "Basic "+basicAuth(username, password)) 1024 } 1025 1026 1027 func parseRequestLine(line string) (method, requestURI, proto string, ok bool) { 1028 method, rest, ok1 := strings.Cut(line, " ") 1029 requestURI, proto, ok2 := strings.Cut(rest, " ") 1030 if !ok1 || !ok2 { 1031 return "", "", "", false 1032 } 1033 return method, requestURI, proto, true 1034 } 1035 1036 var textprotoReaderPool sync.Pool 1037 1038 func newTextprotoReader(br *bufio.Reader) *textproto.Reader { 1039 if v := textprotoReaderPool.Get(); v != nil { 1040 tr := v.(*textproto.Reader) 1041 tr.R = br 1042 return tr 1043 } 1044 return textproto.NewReader(br) 1045 } 1046 1047 func putTextprotoReader(r *textproto.Reader) { 1048 r.R = nil 1049 textprotoReaderPool.Put(r) 1050 } 1051 1052 1053 1054 1055 1056 1057 1058 func ReadRequest(b *bufio.Reader) (*Request, error) { 1059 req, err := readRequest(b) 1060 if err != nil { 1061 return nil, err 1062 } 1063 1064 delete(req.Header, "Host") 1065 return req, nil 1066 } 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 func readRequest(b *bufio.Reader) (req *Request, err error) { 1080 tp := newTextprotoReader(b) 1081 defer putTextprotoReader(tp) 1082 1083 req = new(Request) 1084 1085 1086 var s string 1087 if s, err = tp.ReadLine(); err != nil { 1088 return nil, err 1089 } 1090 defer func() { 1091 if err == io.EOF { 1092 err = io.ErrUnexpectedEOF 1093 } 1094 }() 1095 1096 var ok bool 1097 req.Method, req.RequestURI, req.Proto, ok = parseRequestLine(s) 1098 if !ok { 1099 return nil, badStringError("malformed HTTP request", s) 1100 } 1101 if !validMethod(req.Method) { 1102 return nil, badStringError("invalid method", req.Method) 1103 } 1104 rawurl := req.RequestURI 1105 if req.ProtoMajor, req.ProtoMinor, ok = ParseHTTPVersion(req.Proto); !ok { 1106 return nil, badStringError("malformed HTTP version", req.Proto) 1107 } 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 justAuthority := req.Method == "CONNECT" && !strings.HasPrefix(rawurl, "/") 1119 if justAuthority { 1120 rawurl = "http://" + rawurl 1121 } 1122 1123 if req.URL, err = url.ParseRequestURI(rawurl); err != nil { 1124 return nil, err 1125 } 1126 1127 if justAuthority { 1128 1129 req.URL.Scheme = "" 1130 } 1131 1132 1133 mimeHeader, err := tp.ReadMIMEHeader() 1134 if err != nil { 1135 return nil, err 1136 } 1137 req.Header = Header(mimeHeader) 1138 if len(req.Header["Host"]) > 1 { 1139 return nil, fmt.Errorf("too many Host headers") 1140 } 1141 1142 1143 1144 1145 1146 1147 1148 1149 req.Host = req.URL.Host 1150 if req.Host == "" { 1151 req.Host = req.Header.get("Host") 1152 } 1153 1154 fixPragmaCacheControl(req.Header) 1155 1156 req.Close = shouldClose(req.ProtoMajor, req.ProtoMinor, req.Header, false) 1157 1158 err = readTransfer(req, b) 1159 if err != nil { 1160 return nil, err 1161 } 1162 1163 if req.isH2Upgrade() { 1164 1165 req.ContentLength = -1 1166 1167 1168 1169 1170 1171 req.Close = true 1172 } 1173 return req, nil 1174 } 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 func MaxBytesReader(w ResponseWriter, r io.ReadCloser, n int64) io.ReadCloser { 1187 if n < 0 { 1188 n = 0 1189 } 1190 return &maxBytesReader{w: w, r: r, i: n, n: n} 1191 } 1192 1193 1194 type MaxBytesError struct { 1195 Limit int64 1196 } 1197 1198 func (e *MaxBytesError) Error() string { 1199 1200 return "http: request body too large" 1201 } 1202 1203 type maxBytesReader struct { 1204 w ResponseWriter 1205 r io.ReadCloser 1206 i int64 1207 n int64 1208 err error 1209 } 1210 1211 func (l *maxBytesReader) Read(p []byte) (n int, err error) { 1212 if l.err != nil { 1213 return 0, l.err 1214 } 1215 if len(p) == 0 { 1216 return 0, nil 1217 } 1218 1219 1220 1221 1222 if int64(len(p))-1 > l.n { 1223 p = p[:l.n+1] 1224 } 1225 n, err = l.r.Read(p) 1226 1227 if int64(n) <= l.n { 1228 l.n -= int64(n) 1229 l.err = err 1230 return n, err 1231 } 1232 1233 n = int(l.n) 1234 l.n = 0 1235 1236 1237 1238 1239 1240 1241 1242 1243 type requestTooLarger interface { 1244 requestTooLarge() 1245 } 1246 if res, ok := l.w.(requestTooLarger); ok { 1247 res.requestTooLarge() 1248 } 1249 l.err = &MaxBytesError{l.i} 1250 return n, l.err 1251 } 1252 1253 func (l *maxBytesReader) Close() error { 1254 return l.r.Close() 1255 } 1256 1257 func copyValues(dst, src url.Values) { 1258 for k, vs := range src { 1259 dst[k] = append(dst[k], vs...) 1260 } 1261 } 1262 1263 func parsePostForm(r *Request) (vs url.Values, err error) { 1264 if r.Body == nil { 1265 err = errors.New("missing form body") 1266 return 1267 } 1268 ct := r.Header.Get("Content-Type") 1269 1270 1271 if ct == "" { 1272 ct = "application/octet-stream" 1273 } 1274 ct, _, err = mime.ParseMediaType(ct) 1275 switch { 1276 case ct == "application/x-www-form-urlencoded": 1277 var reader io.Reader = r.Body 1278 maxFormSize := int64(1<<63 - 1) 1279 if _, ok := r.Body.(*maxBytesReader); !ok { 1280 maxFormSize = int64(10 << 20) 1281 reader = io.LimitReader(r.Body, maxFormSize+1) 1282 } 1283 b, e := io.ReadAll(reader) 1284 if e != nil { 1285 if err == nil { 1286 err = e 1287 } 1288 break 1289 } 1290 if int64(len(b)) > maxFormSize { 1291 err = errors.New("http: POST too large") 1292 return 1293 } 1294 vs, e = url.ParseQuery(string(b)) 1295 if err == nil { 1296 err = e 1297 } 1298 case ct == "multipart/form-data": 1299 1300 1301 1302 1303 1304 1305 } 1306 return 1307 } 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 func (r *Request) ParseForm() error { 1328 var err error 1329 if r.PostForm == nil { 1330 if r.Method == "POST" || r.Method == "PUT" || r.Method == "PATCH" { 1331 r.PostForm, err = parsePostForm(r) 1332 } 1333 if r.PostForm == nil { 1334 r.PostForm = make(url.Values) 1335 } 1336 } 1337 if r.Form == nil { 1338 if len(r.PostForm) > 0 { 1339 r.Form = make(url.Values) 1340 copyValues(r.Form, r.PostForm) 1341 } 1342 var newValues url.Values 1343 if r.URL != nil { 1344 var e error 1345 newValues, e = url.ParseQuery(r.URL.RawQuery) 1346 if err == nil { 1347 err = e 1348 } 1349 } 1350 if newValues == nil { 1351 newValues = make(url.Values) 1352 } 1353 if r.Form == nil { 1354 r.Form = newValues 1355 } else { 1356 copyValues(r.Form, newValues) 1357 } 1358 } 1359 return err 1360 } 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 func (r *Request) ParseMultipartForm(maxMemory int64) error { 1371 if r.MultipartForm == multipartByReader { 1372 return errors.New("http: multipart handled by MultipartReader") 1373 } 1374 var parseFormErr error 1375 if r.Form == nil { 1376 1377 1378 parseFormErr = r.ParseForm() 1379 } 1380 if r.MultipartForm != nil { 1381 return nil 1382 } 1383 1384 mr, err := r.multipartReader(false) 1385 if err != nil { 1386 return err 1387 } 1388 1389 f, err := mr.ReadForm(maxMemory) 1390 if err != nil { 1391 return err 1392 } 1393 1394 if r.PostForm == nil { 1395 r.PostForm = make(url.Values) 1396 } 1397 for k, v := range f.Value { 1398 r.Form[k] = append(r.Form[k], v...) 1399 1400 r.PostForm[k] = append(r.PostForm[k], v...) 1401 } 1402 1403 r.MultipartForm = f 1404 1405 return parseFormErr 1406 } 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 func (r *Request) FormValue(key string) string { 1420 if r.Form == nil { 1421 r.ParseMultipartForm(defaultMaxMemory) 1422 } 1423 if vs := r.Form[key]; len(vs) > 0 { 1424 return vs[0] 1425 } 1426 return "" 1427 } 1428 1429 1430 1431 1432 1433 1434 func (r *Request) PostFormValue(key string) string { 1435 if r.PostForm == nil { 1436 r.ParseMultipartForm(defaultMaxMemory) 1437 } 1438 if vs := r.PostForm[key]; len(vs) > 0 { 1439 return vs[0] 1440 } 1441 return "" 1442 } 1443 1444 1445 1446 func (r *Request) FormFile(key string) (multipart.File, *multipart.FileHeader, error) { 1447 if r.MultipartForm == multipartByReader { 1448 return nil, nil, errors.New("http: multipart handled by MultipartReader") 1449 } 1450 if r.MultipartForm == nil { 1451 err := r.ParseMultipartForm(defaultMaxMemory) 1452 if err != nil { 1453 return nil, nil, err 1454 } 1455 } 1456 if r.MultipartForm != nil && r.MultipartForm.File != nil { 1457 if fhs := r.MultipartForm.File[key]; len(fhs) > 0 { 1458 f, err := fhs[0].Open() 1459 return f, fhs[0], err 1460 } 1461 } 1462 return nil, nil, ErrMissingFile 1463 } 1464 1465 1466 1467 1468 1469 func (r *Request) PathValue(name string) string { 1470 if i := r.patIndex(name); i >= 0 { 1471 return r.matches[i] 1472 } 1473 return r.otherValues[name] 1474 } 1475 1476 1477 1478 func (r *Request) SetPathValue(name, value string) { 1479 if i := r.patIndex(name); i >= 0 { 1480 r.matches[i] = value 1481 } else { 1482 if r.otherValues == nil { 1483 r.otherValues = map[string]string{} 1484 } 1485 r.otherValues[name] = value 1486 } 1487 } 1488 1489 1490 1491 func (r *Request) patIndex(name string) int { 1492 1493 1494 if r.pat == nil { 1495 return -1 1496 } 1497 i := 0 1498 for _, seg := range r.pat.segments { 1499 if seg.wild && seg.s != "" { 1500 if name == seg.s { 1501 return i 1502 } 1503 i++ 1504 } 1505 } 1506 return -1 1507 } 1508 1509 func (r *Request) expectsContinue() bool { 1510 return hasToken(r.Header.get("Expect"), "100-continue") 1511 } 1512 1513 func (r *Request) wantsHttp10KeepAlive() bool { 1514 if r.ProtoMajor != 1 || r.ProtoMinor != 0 { 1515 return false 1516 } 1517 return hasToken(r.Header.get("Connection"), "keep-alive") 1518 } 1519 1520 func (r *Request) wantsClose() bool { 1521 if r.Close { 1522 return true 1523 } 1524 return hasToken(r.Header.get("Connection"), "close") 1525 } 1526 1527 func (r *Request) closeBody() error { 1528 if r.Body == nil { 1529 return nil 1530 } 1531 return r.Body.Close() 1532 } 1533 1534 func (r *Request) isReplayable() bool { 1535 if r.Body == nil || r.Body == NoBody || r.GetBody != nil { 1536 switch valueOrDefault(r.Method, "GET") { 1537 case "GET", "HEAD", "OPTIONS", "TRACE": 1538 return true 1539 } 1540 1541 1542 1543 if r.Header.has("Idempotency-Key") || r.Header.has("X-Idempotency-Key") { 1544 return true 1545 } 1546 } 1547 return false 1548 } 1549 1550 1551 1552 func (r *Request) outgoingLength() int64 { 1553 if r.Body == nil || r.Body == NoBody { 1554 return 0 1555 } 1556 if r.ContentLength != 0 { 1557 return r.ContentLength 1558 } 1559 return -1 1560 } 1561 1562 1563 1564 1565 1566 1567 1568 1569 func requestMethodUsuallyLacksBody(method string) bool { 1570 switch method { 1571 case "GET", "HEAD", "DELETE", "OPTIONS", "PROPFIND", "SEARCH": 1572 return true 1573 } 1574 return false 1575 } 1576 1577 1578 1579 func (r *Request) requiresHTTP1() bool { 1580 return hasToken(r.Header.Get("Connection"), "upgrade") && 1581 ascii.EqualFold(r.Header.Get("Upgrade"), "websocket") 1582 } 1583
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4