Structs
Form
struct
#
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.
type Form struct {
Value map[string][]string
File map[string][]*FileHeader
}
Part
struct
#
A Part represents a single part in a multipart body.
type Part struct {
Header textproto.MIMEHeader
mr *Reader
disposition string
dispositionParams map[string]string
r io.Reader
n int
total int64
err error
readErr error
}
Reader
struct
#
Reader is an iterator over parts in a MIME multipart body.
Reader's underlying parser consumes its input as needed. Seeking
isn't supported.
type Reader struct {
bufReader *bufio.Reader
tempDir string
currentPart *Part
partsRead int
nl []byte
nlDashBoundary []byte
dashBoundaryDash []byte
dashBoundary []byte
}
Writer
struct
#
A Writer generates multipart messages.
type Writer struct {
w io.Writer
boundary string
lastpart *part
}
part
struct
#
type part struct {
mw *Writer
closed bool
we error
}
partReader
struct
#
partReader implements io.Reader by reading raw bytes directly from the
wrapped *Part, without doing any Transfer-Encoding decoding.
type partReader struct {
p *Part
}
sectionReadCloser
struct
#
type sectionReadCloser struct {
*io.SectionReader
io.Closer
}
stickyErrorReader
struct
#
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)
type stickyErrorReader struct {
r io.Reader
err error
}
Functions
Boundary
method
#
Boundary returns the [Writer]'s boundary.
func (w *Writer) Boundary() string
Close
method
#
func (p *Part) Close() error
Close
method
#
Close finishes the multipart message and writes the trailing
boundary end line to the output.
func (w *Writer) Close() error
Close
method
#
func (rc sectionReadCloser) Close() error
CreateFormField
method
#
CreateFormField calls [Writer.CreatePart] with a header using the
given field name.
func (w *Writer) CreateFormField(fieldname string) (io.Writer, error)
CreateFormFile
method
#
CreateFormFile is a convenience wrapper around [Writer.CreatePart]. It creates
a new form-data header with the provided field name and file name.
func (w *Writer) CreateFormFile(fieldname string, filename string) (io.Writer, error)
CreatePart
method
#
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.
func (w *Writer) CreatePart(header textproto.MIMEHeader) (io.Writer, error)
FileName
method
#
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.
func (p *Part) FileName() string
FormDataContentType
method
#
FormDataContentType returns the Content-Type for an HTTP
multipart/form-data with this [Writer]'s Boundary.
func (w *Writer) FormDataContentType() string
FormName
method
#
FormName returns the name parameter if p has a Content-Disposition
of type "form-data". Otherwise it returns the empty string.
func (p *Part) FormName() string
NewReader
function
#
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.
func NewReader(r io.Reader, boundary string) *Reader
NewWriter
function
#
NewWriter returns a new multipart [Writer] with a random boundary,
writing to w.
func NewWriter(w io.Writer) *Writer
NextPart
method
#
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.
func (r *Reader) NextPart() (*Part, error)
Open
method
#
Open opens and returns the [FileHeader]'s associated File.
func (fh *FileHeader) Open() (File, error)
Read
method
#
Read reads the body of a part, after its headers and before the
next part (if any) begins.
func (p *Part) Read(d []byte) (n int, err error)
Read
method
#
func (pr partReader) Read(d []byte) (int, error)
Read
method
#
func (r *stickyErrorReader) Read(p []byte) (n int, _ error)
ReadForm
method
#
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.
func (r *Reader) ReadForm(maxMemory int64) (*Form, error)
RemoveAll
method
#
RemoveAll removes any temporary files associated with a [Form].
func (f *Form) RemoveAll() error
SetBoundary
method
#
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.
func (w *Writer) SetBoundary(boundary string) error
Write
method
#
func (p *part) Write(d []byte) (n int, err error)
WriteField
method
#
WriteField calls [Writer.CreateFormField] and then writes the given value.
func (w *Writer) WriteField(fieldname string, value string) error
close
method
#
func (p *part) close() error
escapeQuotes
function
#
func escapeQuotes(s string) string
isBoundaryDelimiterLine
method
#
func (r *Reader) isBoundaryDelimiterLine(line []byte) (ret bool)
isFinalBoundary
method
#
isFinalBoundary reports whether line is the final boundary line
indicating that all parts are over.
It matches `^--boundary--[ \t]*(\r\n)?$`
func (r *Reader) isFinalBoundary(line []byte) bool
matchAfterPrefix
function
#
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.
func matchAfterPrefix(buf []byte, prefix []byte, readErr error) int
newPart
function
#
func newPart(mr *Reader, rawPart bool, maxMIMEHeaderSize int64, maxMIMEHeaders int64) (*Part, error)
nextPart
method
#
func (r *Reader) nextPart(rawPart bool, maxMIMEHeaderSize int64, maxMIMEHeaders int64) (*Part, error)
parseContentDisposition
method
#
func (p *Part) parseContentDisposition()
randomBoundary
function
#
func randomBoundary() string
readForm
method
#
func (r *Reader) readForm(maxMemory int64) (_ *Form, err error)
scanUntilBoundary
function
#
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.
func scanUntilBoundary(buf []byte, dashBoundary []byte, nlDashBoundary []byte, total int64, readErr error) (int, error)
skipLWSPChar
function
#
skipLWSPChar returns b with leading spaces and tabs removed.
RFC 822 defines:
LWSP-char = SPACE / HTAB
func skipLWSPChar(b []byte) []byte