mime/multipart: switch from map to MIMEHeader

R=rsc
CC=golang-dev
https://golang.org/cl/4253058
diff --git a/src/pkg/mime/multipart/multipart.go b/src/pkg/mime/multipart/multipart.go
index 1d855c7..0a65a44 100644
--- a/src/pkg/mime/multipart/multipart.go
+++ b/src/pkg/mime/multipart/multipart.go
@@ -17,6 +17,7 @@
 	"bytes"
 	"io"
 	"mime"
+	"net/textproto"
 	"os"
 	"regexp"
 	"strings"
@@ -40,7 +41,7 @@
 	// The headers of the body, if any, with the keys canonicalized
 	// in the same fashion that the Go http.Request headers are.
 	// i.e. "foo-bar" changes case to "Foo-Bar"
-	Header map[string]string
+	Header textproto.MIMEHeader
 
 	buffer *bytes.Buffer
 	mr     *multiReader
@@ -51,8 +52,8 @@
 func (p *Part) FormName() string {
 	// See http://tools.ietf.org/html/rfc2183 section 2 for EBNF
 	// of Content-Disposition value format.
-	v, ok := p.Header["Content-Disposition"]
-	if !ok {
+	v := p.Header.Get("Content-Disposition")
+	if v == "" {
 		return ""
 	}
 	d, params := mime.ParseMediaType(v)
@@ -85,7 +86,7 @@
 
 func newPart(mr *multiReader) (bp *Part, err os.Error) {
 	bp = new(Part)
-	bp.Header = make(map[string]string)
+	bp.Header = make(map[string][]string)
 	bp.mr = mr
 	bp.buffer = new(bytes.Buffer)
 	if err = bp.populateHeaders(); err != nil {
@@ -104,10 +105,7 @@
 			return nil
 		}
 		if matches := headerRegexp.FindStringSubmatch(line); len(matches) == 3 {
-			key := matches[1]
-			value := matches[2]
-			// TODO: canonicalize headers ala http.Request.Header?
-			bp.Header[key] = value
+			bp.Header.Add(matches[1], matches[2])
 			continue
 		}
 		return os.NewError("Unexpected header line found parsing multipart body")
diff --git a/src/pkg/mime/multipart/multipart_test.go b/src/pkg/mime/multipart/multipart_test.go
index 7e1ed13..1f3d32d 100644
--- a/src/pkg/mime/multipart/multipart_test.go
+++ b/src/pkg/mime/multipart/multipart_test.go
@@ -58,7 +58,7 @@
 
 func TestFormName(t *testing.T) {
 	p := new(Part)
-	p.Header = make(map[string]string)
+	p.Header = make(map[string][]string)
 	tests := [...][2]string{
 		{`form-data; name="foo"`, "foo"},
 		{` form-data ; name=foo`, "foo"},
@@ -69,7 +69,7 @@
 		{` FORM-DATA ; filename="foo.txt"; name=foo; baz=quux`, "foo"},
 	}
 	for _, test := range tests {
-		p.Header["Content-Disposition"] = test[0]
+		p.Header.Set("Content-Disposition", test[0])
 		expected := test[1]
 		actual := p.FormName()
 		if actual != expected {
@@ -114,12 +114,15 @@
 		t.Error("Expected part1")
 		return
 	}
-	if part.Header["Header1"] != "value1" {
+	if part.Header.Get("Header1") != "value1" {
 		t.Error("Expected Header1: value")
 	}
-	if part.Header["foo-bar"] != "baz" {
+	if part.Header.Get("foo-bar") != "baz" {
 		t.Error("Expected foo-bar: baz")
 	}
+	if part.Header.Get("Foo-Bar") != "baz" {
+		t.Error("Expected Foo-Bar: baz")
+	}
 	buf.Reset()
 	io.Copy(buf, part)
 	expectEq(t, "My value\r\nThe end.",
@@ -131,7 +134,7 @@
 		t.Error("Expected part2")
 		return
 	}
-	if part.Header["foo-bar"] != "bazb" {
+	if part.Header.Get("foo-bar") != "bazb" {
 		t.Error("Expected foo-bar: bazb")
 	}
 	buf.Reset()