package api import ( "mime" "net/http/httptest" "testing" ) func TestSetContentDisposition(t *testing.T) { tests := []struct { name string filename string want string }{ { name: "Simple ASCII", filename: "test.txt", want: "attachment; filename=test.txt", }, { name: "With Spaces", filename: "my file.txt", want: `attachment; filename="my file.txt"`, }, { name: "Unicode Characters", filename: "á, ó, ö.txt", // Go's mime.FormatMediaType uses RFC 2231/5987 encoding for non-ASCII // encoded: UTF-8''%C3%A1%2C%20%C3%B3%2C%20%C3%B6.txt want: "attachment; filename*=UTF-8''%C3%A1%2C%20%C3%B3%2C%20%C3%B6.txt", }, { name: "Complex Unicode", filename: "résumé.pdf", want: "attachment; filename*=UTF-8''r%C3%A9sum%C3%A9.pdf", }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { w := httptest.NewRecorder() setContentDisposition(w, tt.filename) got := w.Header().Get("Content-Disposition") // Verify it parses back correctly using the same library _, params, err := mime.ParseMediaType(got) if err != nil { t.Errorf("setContentDisposition() generated invalid header %q: %v", got, err) } if params["filename"] != "" { if params["filename"] != tt.filename { t.Errorf("filename parameter = %q, want %q", params["filename"], tt.filename) } } else { // If filename param is missing/empty, it might be using filename* (extended) // Note: mime.ParseMediaType automatically handles decoding filename* into params["filename"] // if it follows the spec. If it doesn't, we need to check manual expectations. // However, for verify strict equality with expectation: } // We also check exact string match for regression/strictness, // but we allow for slight variations if the mime library changes, // so the parse check above is the most important for correctness. // But for this test, let's also check the `want` expectation if provided. if got != tt.want { t.Logf("Got header: %s", got) // We don't fail here strictly if ParseMediaType worked and decoded the right filename, // but let's see if our expectations match the stdlib output. } // Re-verify the decoded filename matches exactly what we put in // helper to checks gotFilename, ok := params["filename"] if !ok { // Depending on implementation, sometimes filename is omitted if filename* is present, // but usually legacy user agents want filename="Encoded...". // mime.FormatMediaType prefers filename* for non-ascii. } if gotFilename != tt.filename { t.Errorf("Parsed filename = %q, want %q", gotFilename, tt.filename) } }) } }