multipart

Imports

Imports #

"bytes"
"errors"
"internal/godebug"
"io"
"math"
"net/textproto"
"os"
"strconv"
"bufio"
"bytes"
"fmt"
"internal/godebug"
"io"
"mime"
"mime/quotedprintable"
"net/textproto"
"path/filepath"
"strconv"
"strings"
"net/textproto"
_ "unsafe"
"bytes"
"crypto/rand"
"errors"
"fmt"
"io"
"maps"
"net/textproto"
"slices"
"strings"

Constants & Variables

ErrMessageTooLarge var #

ErrMessageTooLarge is returned by ReadForm if the message form data is too large to be processed.

var ErrMessageTooLarge = *ast.CallExpr

emptyParams var #

var emptyParams = *ast.CallExpr

maxMIMEHeaderSize const #

maxMIMEHeaderSize is the maximum size of a MIME header we will parse, including header keys, values, and map overhead.

const maxMIMEHeaderSize = *ast.BinaryExpr

multipartfiles var #

var multipartfiles = *ast.CallExpr

multipartmaxheaders var #

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.

var multipartmaxheaders = *ast.CallExpr

multipartmaxparts var #

var multipartmaxparts = *ast.CallExpr

peekBufferSize const #

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.

const peekBufferSize = 4096

quoteEscaper var #

var quoteEscaper = *ast.CallExpr

Interfaces

File interface #

File is an interface to access the file part of a multipart message. Its contents may be either stored in memory or on disk. If stored on disk, the File's underlying concrete type will be an *os.File.

type File interface {
io.Reader
io.ReaderAt
io.Seeker
io.Closer
}

Structs

FileHeader struct #

A FileHeader describes a file part of a multipart request.

type FileHeader struct {
Filename string
Header textproto.MIMEHeader
Size int64
content []byte
tmpfile string
tmpoff int64
tmpshared bool
}

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)

NextRawPart method #

NextRawPart returns the next part in the multipart or an error. When there are no more parts, the error [io.EOF] is returned. Unlike [Reader.NextPart], it does not have special handling for "Content-Transfer-Encoding: quoted-printable".

func (r *Reader) NextRawPart() (*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

maxMIMEHeaders function #

func maxMIMEHeaders() int64

mimeHeaderSize function #

func mimeHeaderSize(h textproto.MIMEHeader) (size int64)

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()

populateHeaders method #

func (p *Part) populateHeaders(maxMIMEHeaderSize int64, maxMIMEHeaders int64) error

randomBoundary function #

func randomBoundary() string

readForm method #

func (r *Reader) readForm(maxMemory int64) (_ *Form, err error)

readMIMEHeader function #

readMIMEHeader is defined in package [net/textproto]. go:linkname readMIMEHeader net/textproto.readMIMEHeader

func readMIMEHeader(r *textproto.Reader, maxMemory int64, maxHeaders int64) (textproto.MIMEHeader, 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

Generated with Arrow