// FormDataContentType returns the Content-Type for an HTTP
// multipart/form-data with this Writer's Boundary.
func (w *Writer) FormDataContentType() string {
- return "multipart/form-data; boundary=" + w.boundary
+ b := w.boundary
+ // We must quote the boundary if it contains any of the
+ // tspecials characters defined by RFC 2045, or space.
+ if strings.ContainsAny(b, `()<>@,;:\"/[]?= `) {
+ b = `"` + b + `"`
+ }
+ return "multipart/form-data; boundary=" + b
}
func randomBoundary() string {
import (
"bytes"
"io/ioutil"
+ "mime"
"net/textproto"
"strings"
"testing"
{"my-separator", true},
{"with space", true},
{"badspace ", false},
+ {"(boundary)", true},
}
for i, tt := range tests {
var b bytes.Buffer
if got != tt.b {
t.Errorf("boundary = %q; want %q", got, tt.b)
}
+
+ ct := w.FormDataContentType()
+ mt, params, err := mime.ParseMediaType(ct)
+ if err != nil {
+ t.Errorf("could not parse Content-Type %q: %v", ct, err)
+ } else if mt != "multipart/form-data" {
+ t.Errorf("unexpected media type %q; want %q", mt, "multipart/form-data")
+ } else if b := params["boundary"]; b != tt.b {
+ t.Errorf("unexpected boundary parameter %q; want %q", b, tt.b)
+ }
+
w.Close()
wantSub := "\r\n--" + tt.b + "--\r\n"
if got := b.String(); !strings.Contains(got, wantSub) {