Involved Source Filesformdata.go Package multipart implements MIME multipart parsing, as defined in RFC
2046.
The implementation is sufficient for HTTP (RFC 2388) and the multipart
bodies generated by popular browsers.
# Limits
To protect against malicious inputs, this package sets limits on the size
of the MIME data it processes.
Reader.NextPart and Reader.NextRawPart limit the number of headers in a
part to 10000 and Reader.ReadForm limits the total number of headers in all
FileHeaders to 10000.
These limits may be adjusted with the GODEBUG=multipartmaxheaders=<values>
setting.
Reader.ReadForm further limits the number of parts in a form to 1000.
This limit may be adjusted with the GODEBUG=multipartmaxparts=<value>
setting. Copyright 2023 The Go Authors. All rights reserved.
Use of this source code is governed by a BSD-style
license that can be found in the LICENSE file.writer.go
Form is a parsed multipart form.
Its File parts are stored either in memory or on disk,
and are accessible via the *FileHeader's Open method.
Its Value parts are stored as strings.
Both are keyed by field name.Filemap[string][]*FileHeaderValuemap[string][]string RemoveAll removes any temporary files associated with a Form.
func (*Reader).ReadForm(maxMemory int64) (*Form, error)
func (*Reader).readForm(maxMemory int64) (_ *Form, err error)
func net/http.cloneMultipartForm(f *Form) *Form
func net/http.cloneMultipartForm(f *Form) *Form
var net/http.multipartByReader *Form
A Part represents a single part in a multipart body. The headers of the body, if any, with the keys canonicalized
in the same fashion that the Go http.Request headers are.
For example, "foo-bar" changes case to "Foo-Bar"dispositionstringdispositionParamsmap[string]string // error to return when n == 0mr*Reader // known data bytes waiting in mr.bufReader r is either a reader directly reading from mr, or it's a
wrapper around such a reader, decoding the
Content-Transfer-Encoding // read error observed from mr.bufReader // total data bytes read already(*Part) Close() error FileName returns the filename parameter of the Part's Content-Disposition
header. If not empty, the filename is passed through filepath.Base (which is
platform dependent) before being returned. FormName returns the name parameter if p has a Content-Disposition
of type "form-data". Otherwise it returns the empty string. Read reads the body of a part, after its headers and before the
next part (if any) begins.(*Part) parseContentDisposition()(*Part) populateHeaders(maxMIMEHeaderSize, maxMIMEHeaders int64) error
*Part : io.Closer
*Part : io.ReadCloser
*Part : io.Reader
func (*Reader).NextPart() (*Part, error)
func (*Reader).NextRawPart() (*Part, error)
func newPart(mr *Reader, rawPart bool, maxMIMEHeaderSize, maxMIMEHeaders int64) (*Part, error)
func (*Reader).nextPart(rawPart bool, maxMIMEHeaderSize, maxMIMEHeaders int64) (*Part, error)
Reader is an iterator over parts in a MIME multipart body.
Reader's underlying parser consumes its input as needed. Seeking
isn't supported.bufReader*bufio.ReadercurrentPart*Part // "--boundary" // "--boundary--" // "\r\n" or "\n" (set after seeing first boundary line) // nl + "--boundary"partsReadint // used in tests NextPart returns the next part in the multipart or an error.
When there are no more parts, the error io.EOF is returned.
As a special case, if the "Content-Transfer-Encoding" header
has a value of "quoted-printable", that header is instead
hidden and the body is transparently decoded during Read calls. NextRawPart returns the next part in the multipart or an error.
When there are no more parts, the error io.EOF is returned.
Unlike NextPart, it does not have special handling for
"Content-Transfer-Encoding: quoted-printable". ReadForm parses an entire multipart message whose parts have
a Content-Disposition of "form-data".
It stores up to maxMemory bytes + 10MB (reserved for non-file parts)
in memory. File parts which can't be stored in memory will be stored on
disk in temporary files.
It returns ErrMessageTooLarge if all non-file parts can't be stored in
memory.(*Reader) isBoundaryDelimiterLine(line []byte) (ret bool) isFinalBoundary reports whether line is the final boundary line
indicating that all parts are over.
It matches `^--boundary--[ \t]*(\r\n)?$`(*Reader) nextPart(rawPart bool, maxMIMEHeaderSize, maxMIMEHeaders int64) (*Part, error)(*Reader) readForm(maxMemory int64) (_ *Form, err error)
func NewReader(r io.Reader, boundary string) *Reader
func net/http.(*Request).MultipartReader() (*Reader, error)
func net/http.(*Request).multipartReader(allowMixed bool) (*Reader, error)
func newPart(mr *Reader, rawPart bool, maxMIMEHeaderSize, maxMIMEHeaders int64) (*Part, error)
A Writer generates multipart messages.boundarystringlastpart*partwio.Writer Boundary returns the Writer's boundary. Close finishes the multipart message and writes the trailing
boundary end line to the output. CreateFormField calls CreatePart with a header using the
given field name. CreateFormFile is a convenience wrapper around CreatePart. It creates
a new form-data header with the provided field name and file name. CreatePart creates a new multipart section with the provided
header. The body of the part should be written to the returned
Writer. After calling CreatePart, any previous part may no longer
be written to. FormDataContentType returns the Content-Type for an HTTP
multipart/form-data with this Writer's Boundary. SetBoundary overrides the Writer's default randomly-generated
boundary separator with an explicit value.
SetBoundary must be called before any parts are created, may only
contain certain ASCII characters, and must be non-empty and
at most 70 bytes long. WriteField calls CreateFormField and then writes the given value.
*Writer : io.Closer
func NewWriter(w io.Writer) *Writer
partReader implements io.Reader by reading raw bytes directly from the
wrapped *Part, without doing any Transfer-Encoding decoding.p*Part( partReader) Read(d []byte) (int, error)
partReader : io.Reader
stickyErrorReader is an io.Reader which never calls Read on its
underlying Reader once an error has been seen. (the io.Reader
interface's contract promises nothing about the return values of
Read calls after an error, yet this package does do multiple Reads
after error)errerrorrio.Reader(*stickyErrorReader) Read(p []byte) (n int, _ error)
*stickyErrorReader : io.Reader
Package-Level Functions (total 11, in which 2 are exported)
NewReader creates a new multipart Reader reading from r using the
given MIME boundary.
The boundary is usually obtained from the "boundary" parameter of
the message's "Content-Type" header. Use mime.ParseMediaType to
parse such headers.
NewWriter returns a new multipart Writer with a random boundary,
writing to w.
matchAfterPrefix checks whether buf should be considered to match the boundary.
The prefix is "--boundary" or "\r\n--boundary" or "\n--boundary",
and the caller has verified already that bytes.HasPrefix(buf, prefix) is true.
matchAfterPrefix returns +1 if the buffer does match the boundary,
meaning the prefix is followed by a double dash, space, tab, cr, nl,
or end of input.
It returns -1 if the buffer definitely does NOT match the boundary,
meaning the prefix is followed by some other character.
For example, "--foobar" does not match "--foo".
It returns 0 more input needs to be read to make the decision,
meaning that len(buf) == len(prefix) and readErr == nil.
readMIMEHeader is defined in package net/textproto.
scanUntilBoundary scans buf to identify how much of it can be safely
returned as part of the Part body.
dashBoundary is "--boundary".
nlDashBoundary is "\r\n--boundary" or "\n--boundary", depending on what mode we are in.
The comments below (and the name) assume "\n--boundary", but either is accepted.
total is the number of bytes read out so far. If total == 0, then a leading "--boundary" is recognized.
readErr is the read error, if any, that followed reading the bytes in buf.
scanUntilBoundary returns the number of data bytes from buf that can be
returned as part of the Part body and also the error to return (if any)
once those data bytes are done.
skipLWSPChar returns b with leading spaces and tabs removed.
RFC 822 defines:
LWSP-char = SPACE / HTAB
Package-Level Variables (total 6, in which 1 is exported)
ErrMessageTooLarge is returned by ReadForm if the message form
data is too large to be processed.
multipartMaxHeaders is the maximum number of header entries NextPart will return,
as well as the maximum combined total of header entries Reader.ReadForm will return
in FileHeaders.
Package-Level Constants (total 2, neither is exported)
maxMIMEHeaderSize is the maximum size of a MIME header we will parse,
including header keys, values, and map overhead.
This constant needs to be at least 76 for this package to work correctly.
This is because \r\n--separator_of_len_70- would fill the buffer and it
wouldn't be safe to consume a single byte from it.
The pages are generated with Goldsv0.6.7. (GOOS=linux GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu.
PR and bug reports are welcome and can be submitted to the issue list.
Please follow @Go100and1 (reachable from the left QR code) to get the latest news of Golds.