Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

mime/multipart: add helper to build content-disposition header contents #63324

Open
wants to merge 9 commits into
base: master
Choose a base branch
from
1 change: 1 addition & 0 deletions api/next/46771.txt
@@ -0,0 +1 @@
pkg mime/multipart, func FileContentDisposition(string, string) string #46771
11 changes: 8 additions & 3 deletions src/mime/multipart/writer.go
Expand Up @@ -139,9 +139,7 @@ func escapeQuotes(s string) string {
// a new form-data header with the provided field name and file name.
func (w *Writer) CreateFormFile(fieldname, filename string) (io.Writer, error) {
h := make(textproto.MIMEHeader)
h.Set("Content-Disposition",
fmt.Sprintf(`form-data; name="%s"; filename="%s"`,
escapeQuotes(fieldname), escapeQuotes(filename)))
h.Set("Content-Disposition", FileContentDisposition(fieldname, filename))
h.Set("Content-Type", "application/octet-stream")
return w.CreatePart(h)
}
Expand All @@ -155,6 +153,13 @@ func (w *Writer) CreateFormField(fieldname string) (io.Writer, error) {
return w.CreatePart(h)
}

// FileContentDisposition returns the value of a Content-Disposition header
// with the provided field name and file name.
func FileContentDisposition(fieldname, filename string) string {
return fmt.Sprintf(`form-data; name="%s"; filename="%s"`,
escapeQuotes(fieldname), escapeQuotes(filename))
}

// WriteField calls CreateFormField and then writes the given value.
func (w *Writer) WriteField(fieldname, value string) error {
p, err := w.CreateFormField(fieldname)
Expand Down
19 changes: 19 additions & 0 deletions src/mime/multipart/writer_test.go
Expand Up @@ -172,3 +172,22 @@ func TestSortedHeader(t *testing.T) {
t.Fatalf("\n got: %q\nwant: %q\n", buf.String(), want)
}
}

func TestFileContentDisposition(t *testing.T) {
tests := []struct {
fieldname string
filename string
want string
}{
{"somefield", "somefile.txt", `form-data; name="somefield"; filename="somefile.txt"`},
{`field"withquotes"`, "somefile.txt", `form-data; name="field\"withquotes\""; filename="somefile.txt"`},
{`somefield`, `somefile"withquotes".txt`, `form-data; name="somefield"; filename="somefile\"withquotes\".txt"`},
{`somefield\withbackslash`, "somefile.txt", `form-data; name="somefield\\withbackslash"; filename="somefile.txt"`},
{"somefield", `somefile\withbackslash.txt`, `form-data; name="somefield"; filename="somefile\\withbackslash.txt"`},
}
for i, tt := range tests {
if found := FileContentDisposition(tt.fieldname, tt.filename); found != tt.want {
t.Errorf(`%d. found: "%s"; want: "%s"`, i, found, tt.want)
}
}
}