Skip to content

Commit

Permalink
mime/multipart: allow setting the Writer boundary
Browse files Browse the repository at this point in the history
Fixes #4490

R=golang-dev, rsc
CC=golang-dev
https://golang.org/cl/6924044
  • Loading branch information
bradfitz committed Dec 10, 2012
1 parent 9c9e811 commit 575de93
Show file tree
Hide file tree
Showing 2 changed files with 63 additions and 1 deletion.
29 changes: 28 additions & 1 deletion src/pkg/mime/multipart/writer.go
Expand Up @@ -30,11 +30,38 @@ func NewWriter(w io.Writer) *Writer {
}
}

// Boundary returns the Writer's randomly selected boundary string.
// Boundary returns the Writer's boundary.
func (w *Writer) Boundary() string {
return w.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 1-69 bytes long.
func (w *Writer) SetBoundary(boundary string) error {
if w.lastpart != nil {
return errors.New("mime: SetBoundary called after write")
}
// rfc2046#section-5.1.1
if len(boundary) < 1 || len(boundary) > 69 {
return errors.New("mime: invalid boundary length")
}
for _, b := range boundary {
if 'A' <= b && b <= 'Z' || 'a' <= b && b <= 'z' || '0' <= b && b <= '9' {
continue
}
switch b {
case '\'', '(', ')', '+', '_', ',', '-', '.', '/', ':', '=', '?':
continue
}
return errors.New("mime: invalid boundary character")
}
w.boundary = boundary
return nil
}

// FormDataContentType returns the Content-Type for an HTTP
// multipart/form-data with this Writer's Boundary.
func (w *Writer) FormDataContentType() string {
Expand Down
35 changes: 35 additions & 0 deletions src/pkg/mime/multipart/writer_test.go
Expand Up @@ -7,6 +7,7 @@ package multipart
import (
"bytes"
"io/ioutil"
"strings"
"testing"
)

Expand Down Expand Up @@ -76,3 +77,37 @@ func TestWriter(t *testing.T) {
t.Fatalf("expected end of parts; got %v, %v", part, err)
}
}

func TestWriterSetBoundary(t *testing.T) {
var b bytes.Buffer
w := NewWriter(&b)
tests := []struct {
b string
ok bool
}{
{"abc", true},
{"", false},
{"ungültig", false},
{"!", false},
{strings.Repeat("x", 69), true},
{strings.Repeat("x", 70), false},
{"bad!ascii!", false},
{"my-separator", true},
}
for i, tt := range tests {
err := w.SetBoundary(tt.b)
got := err == nil
if got != tt.ok {
t.Errorf("%d. boundary %q = %v (%v); want %v", i, tt.b, got, err, tt.ok)
} else if tt.ok {
got := w.Boundary()
if got != tt.b {
t.Errorf("boundary = %q; want %q", got, tt.b)
}
}
}
w.Close()
if got := b.String(); !strings.Contains(got, "\r\n--my-separator--\r\n") {
t.Errorf("expected my-separator in output. got: %q", got)
}
}

0 comments on commit 575de93

Please sign in to comment.