diff --git a/pkg/app/client/client_test.go b/pkg/app/client/client_test.go index 8862d8401..84c6a918e 100644 --- a/pkg/app/client/client_test.go +++ b/pkg/app/client/client_test.go @@ -975,7 +975,7 @@ func TestClientFollowRedirects(t *testing.T) { u.Update("/bar") ctx.Redirect(consts.StatusFound, u.FullURI()) default: - ctx.SetContentType("text/plain") + ctx.SetContentType(consts.MIMETextPlain) ctx.Response.SetBody(ctx.Path()) } } @@ -1440,13 +1440,13 @@ func TestSetMultipartFields(t *testing.T) { { Param: "file_1", FileName: files[0], - ContentType: "application/json", + ContentType: consts.MIMEApplicationJSON, Reader: strings.NewReader(jsonStr1), }, { Param: "file_2", FileName: files[1], - ContentType: "application/json", + ContentType: consts.MIMEApplicationJSON, Reader: strings.NewReader(jsonStr2), }, } diff --git a/pkg/app/context_test.go b/pkg/app/context_test.go index 31d6da07d..7853d2a72 100644 --- a/pkg/app/context_test.go +++ b/pkg/app/context_test.go @@ -431,7 +431,7 @@ tailfoobar` t.Fatalf("unexpected filename %q. Expecting %q", v.Filename, "TODO") } ct := v.Header.Get("Content-Type") - if ct != "application/octet-stream" { + if ct != consts.MIMEApplicationOctetStream { t.Fatalf("unexpected content-type %q. Expecting %q", ct, "application/octet-stream") } } @@ -472,7 +472,7 @@ func TestContextRenderFileFromFS(t *testing.T) { assert.DeepEqual(t, consts.StatusOK, ctx.Response.StatusCode()) assert.True(t, strings.Contains(resp.GetHTTP1Response(&ctx.Response).String(), "func (fs *FS) initRequestHandler() {")) - assert.DeepEqual(t, "text/plain; charset=utf-8", string(ctx.Response.Header.Peek("Content-Type"))) + assert.DeepEqual(t, consts.MIMETextPlainUTF8, string(ctx.Response.Header.Peek("Content-Type"))) assert.DeepEqual(t, "/some/path", string(ctx.Request.URI().Path())) } @@ -489,7 +489,7 @@ func TestContextRenderFile(t *testing.T) { assert.DeepEqual(t, consts.StatusOK, ctx.Response.StatusCode()) assert.True(t, strings.Contains(resp.GetHTTP1Response(&ctx.Response).String(), "func (fs *FS) initRequestHandler() {")) - assert.DeepEqual(t, "text/plain; charset=utf-8", string(ctx.Response.Header.Peek("Content-Type"))) + assert.DeepEqual(t, consts.MIMETextPlainUTF8, string(ctx.Response.Header.Peek("Content-Type"))) } func TestContextRenderAttachment(t *testing.T) { @@ -625,7 +625,7 @@ func TestRender(t *testing.T) { c := NewContext(0) c.Render(consts.StatusOK, &render.Data{ - ContentType: "application/json; charset=utf-8", + ContentType: consts.MIMEApplicationJSONUTF8, Data: []byte("{\"test\":1}"), }) @@ -666,8 +666,8 @@ func TestContextReset(t *testing.T) { func TestContextContentType(t *testing.T) { c := NewContext(0) - c.Request.Header.Set("Content-Type", "application/json; charset=utf-8") - assert.DeepEqual(t, "application/json; charset=utf-8", bytesconv.B2s(c.ContentType())) + c.Request.Header.Set("Content-Type", consts.MIMEApplicationJSONUTF8) + assert.DeepEqual(t, consts.MIMEApplicationJSONUTF8, bytesconv.B2s(c.ContentType())) } func TestClientIp(t *testing.T) { @@ -735,7 +735,7 @@ func TestGetQuery(t *testing.T) { func TestGetPostForm(t *testing.T) { c := NewContext(0) - c.Request.Header.SetContentTypeBytes([]byte("application/x-www-form-urlencoded")) + c.Request.Header.SetContentTypeBytes([]byte(consts.MIMEApplicationHTMLForm)) c.Request.SetBodyString("a=1&b=") v, exists := c.GetPostForm("b") assert.DeepEqual(t, "", v) @@ -794,7 +794,7 @@ func TestContextAbortWithStatusJSON(t *testing.T) { assert.True(t, c.IsAborted()) contentType := c.Response.Header.Peek("Content-Type") - assert.DeepEqual(t, "application/json; charset=utf-8", string(contentType)) + assert.DeepEqual(t, consts.MIMEApplicationJSONUTF8, string(contentType)) jsonStringBody := c.Response.Body() assert.DeepEqual(t, "{\"foo\":\"fooValue\",\"bar\":\"barValue\"}", string(jsonStringBody)) @@ -803,7 +803,7 @@ func TestContextAbortWithStatusJSON(t *testing.T) { func TestRequestCtxFormValue(t *testing.T) { ctx := NewContext(0) ctx.Request.SetRequestURI("/foo/bar?baz=123&aaa=bbb") - ctx.Request.Header.SetContentTypeBytes([]byte("application/x-www-form-urlencoded")) + ctx.Request.Header.SetContentTypeBytes([]byte(consts.MIMEApplicationHTMLForm)) ctx.Request.SetBodyString("qqq=port&mmm=sddd") v := ctx.FormValue("baz") @@ -831,7 +831,7 @@ func TestRequestCtxFormValue(t *testing.T) { func TestSetCustomFormValueFunc(t *testing.T) { ctx := NewContext(0) ctx.Request.SetRequestURI("/foo/bar?aaa=bbb") - ctx.Request.Header.SetContentTypeBytes([]byte("application/x-www-form-urlencoded")) + ctx.Request.Header.SetContentTypeBytes([]byte(consts.MIMEApplicationHTMLForm)) ctx.Request.SetBodyString("aaa=port") ctx.SetFormValueFunc(func(ctx *RequestContext, key string) []byte { @@ -1154,9 +1154,9 @@ func TestReset(t *testing.T) { func TestGetHeader(t *testing.T) { ctx := NewContext(0) - ctx.Request.Header.SetContentTypeBytes([]byte("text/plain; charset=utf-8")) + ctx.Request.Header.SetContentTypeBytes([]byte(consts.MIMETextPlainUTF8)) val := ctx.GetHeader("Content-Type") - assert.DeepEqual(t, "text/plain; charset=utf-8", string(val)) + assert.DeepEqual(t, consts.MIMETextPlainUTF8, string(val)) } func TestGetRawData(t *testing.T) { diff --git a/pkg/app/fs_test.go b/pkg/app/fs_test.go index 389fe9e40..1cd545e8c 100644 --- a/pkg/app/fs_test.go +++ b/pkg/app/fs_test.go @@ -655,7 +655,7 @@ func TestServeFileContentType(t *testing.T) { t.Fatalf("unexpected error: %s", err) } - expected := []byte("image/png") + expected := []byte(consts.MIMEImagePNG) if !bytes.Equal(r.Header.ContentType(), expected) { t.Fatalf("Unexpected Content-Type, expected: %q got %q", expected, r.Header.ContentType()) } diff --git a/pkg/app/server/render/render_test.go b/pkg/app/server/render/render_test.go index bc839e0c0..338d151df 100644 --- a/pkg/app/server/render/render_test.go +++ b/pkg/app/server/render/render_test.go @@ -48,6 +48,7 @@ import ( "github.com/bytedance/sonic" "github.com/cloudwego/hertz/pkg/common/test/assert" "github.com/cloudwego/hertz/pkg/protocol" + "github.com/cloudwego/hertz/pkg/protocol/consts" ) type xmlmap map[string]interface{} @@ -82,13 +83,13 @@ func TestRenderJSON(t *testing.T) { } (JSONRender{data}).WriteContentType(resp) - assert.DeepEqual(t, []byte("application/json; charset=utf-8"), resp.Header.Peek("Content-Type")) + assert.DeepEqual(t, []byte(consts.MIMEApplicationJSONUTF8), resp.Header.Peek("Content-Type")) err := (JSONRender{data}).Render(resp) assert.Nil(t, err) assert.DeepEqual(t, []byte("{\"foo\":\"bar\",\"html\":\"\\u003cb\\u003e\"}"), resp.Body()) - assert.DeepEqual(t, []byte("application/json; charset=utf-8"), resp.Header.Peek("Content-Type")) + assert.DeepEqual(t, []byte(consts.MIMEApplicationJSONUTF8), resp.Header.Peek("Content-Type")) } func TestRenderJSONError(t *testing.T) { @@ -106,7 +107,7 @@ func TestRenderString(t *testing.T) { Format: "hello %s %d", Data: []interface{}{}, }).WriteContentType(resp) - assert.DeepEqual(t, []byte("text/plain; charset=utf-8"), resp.Header.Peek("Content-Type")) + assert.DeepEqual(t, []byte(consts.MIMETextPlainUTF8), resp.Header.Peek("Content-Type")) err := (String{ Format: "hola %s %d", @@ -115,7 +116,7 @@ func TestRenderString(t *testing.T) { assert.Nil(t, err) assert.DeepEqual(t, []byte("hola manu 2"), resp.Body()) - assert.DeepEqual(t, []byte("text/plain; charset=utf-8"), resp.Header.Peek("Content-Type")) + assert.DeepEqual(t, []byte(consts.MIMETextPlainUTF8), resp.Header.Peek("Content-Type")) } func TestRenderStringLenZero(t *testing.T) { @@ -128,7 +129,7 @@ func TestRenderStringLenZero(t *testing.T) { assert.Nil(t, err) assert.DeepEqual(t, []byte("hola %s %d"), resp.Body()) - assert.DeepEqual(t, []byte("text/plain; charset=utf-8"), resp.Header.Peek("Content-Type")) + assert.DeepEqual(t, []byte(consts.MIMETextPlainUTF8), resp.Header.Peek("Content-Type")) } func TestRenderData(t *testing.T) { @@ -142,7 +143,7 @@ func TestRenderData(t *testing.T) { assert.Nil(t, err) assert.DeepEqual(t, []byte("#!PNG some raw data"), resp.Body()) - assert.DeepEqual(t, []byte("image/png"), resp.Header.Peek("Content-Type")) + assert.DeepEqual(t, []byte(consts.MIMEImagePNG), resp.Header.Peek("Content-Type")) } func TestRenderXML(t *testing.T) { @@ -152,13 +153,13 @@ func TestRenderXML(t *testing.T) { } (XML{data}).WriteContentType(resp) - assert.DeepEqual(t, []byte("application/xml; charset=utf-8"), resp.Header.Peek("Content-Type")) + assert.DeepEqual(t, []byte(consts.MIMEApplicationXMLUTF8), resp.Header.Peek("Content-Type")) err := (XML{data}).Render(resp) assert.Nil(t, err) assert.DeepEqual(t, []byte("bar"), resp.Body()) - assert.DeepEqual(t, []byte("application/xml; charset=utf-8"), resp.Header.Peek("Content-Type")) + assert.DeepEqual(t, []byte(consts.MIMEApplicationXMLUTF8), resp.Header.Peek("Content-Type")) } func TestRenderIndentedJSON(t *testing.T) { @@ -169,7 +170,7 @@ func TestRenderIndentedJSON(t *testing.T) { t.Run("TestHeader", func(t *testing.T) { resp := &protocol.Response{} (IndentedJSON{data}).WriteContentType(resp) - assert.DeepEqual(t, []byte("application/json; charset=utf-8"), resp.Header.Peek("Content-Type")) + assert.DeepEqual(t, []byte(consts.MIMEApplicationJSONUTF8), resp.Header.Peek("Content-Type")) }) t.Run("TestBody", func(t *testing.T) { ResetStdJSONMarshal() @@ -177,7 +178,7 @@ func TestRenderIndentedJSON(t *testing.T) { err := (IndentedJSON{data}).Render(resp) assert.Nil(t, err) assert.DeepEqual(t, []byte("{\n \"foo\": \"bar\",\n \"html\": \"h1\"\n}"), resp.Body()) - assert.DeepEqual(t, []byte("application/json; charset=utf-8"), resp.Header.Peek("Content-Type")) + assert.DeepEqual(t, []byte(consts.MIMEApplicationJSONUTF8), resp.Header.Peek("Content-Type")) ResetJSONMarshal(sonic.Marshal) }) t.Run("TestError", func(t *testing.T) { diff --git a/pkg/protocol/consts/headers.go b/pkg/protocol/consts/headers.go index d01af5a5f..3c2b82e7e 100644 --- a/pkg/protocol/consts/headers.go +++ b/pkg/protocol/consts/headers.go @@ -85,4 +85,79 @@ const ( HTTP11 = "HTTP/1.1" HTTP10 = "HTTP/1.0" HTTP20 = "HTTP/2.0" + + // MIME text + MIMETextPlain = "text/plain" + MIMETextPlainUTF8 = "text/plain; charset=utf-8" + MIMETextPlainISO88591 = "text/plain; charset=iso-8859-1" + MIMETextPlainFormatFlowed = "text/plain; format=flowed" + MIMETextPlainDelSpaceYes = "text/plain; delsp=yes" + MiMETextPlainDelSpaceNo = "text/plain; delsp=no" + MIMETextHtml = "text/html" + MIMETextCss = "text/css" + MIMETextJavascript = "text/javascript" + + // MIME application + MIMEApplicationOctetStream = "application/octet-stream" + MIMEApplicationFlash = "application/x-shockwave-flash" + MIMEApplicationHTMLForm = "application/x-www-form-urlencoded" + MIMEApplicationHTMLFormUTF8 = "application/x-www-form-urlencoded; charset=UTF-8" + MIMEApplicationTar = "application/x-tar" + MIMEApplicationGZip = "application/gzip" + MIMEApplicationXGZip = "application/x-gzip" + MIMEApplicationBZip2 = "application/bzip2" + MIMEApplicationXBZip2 = "application/x-bzip2" + MIMEApplicationShell = "application/x-sh" + MIMEApplicationDownload = "application/x-msdownload" + MIMEApplicationJSON = "application/json" + MIMEApplicationJSONUTF8 = "application/json; charset=utf-8" + MIMEApplicationXML = "application/xml" + MIMEApplicationXMLUTF8 = "application/xml; charset=utf-8" + MIMEApplicationZip = "application/zip" + MIMEApplicationPdf = "application/pdf" + MIMEApplicationWord = "application/msword" + MIMEApplicationExcel = "application/vnd.ms-excel" + MIMEApplicationPPT = "application/vnd.ms-powerpoint" + MIMEApplicationOpenXMLWord = "application/vnd.openxmlformats-officedocument.wordprocessingml.document" + MIMEApplicationOpenXMLExcel = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" + MIMEApplicationOpenXMLPPT = "application/vnd.openxmlformats-officedocument.presentationml.presentation" + + // MIME image + MIMEImageJPEG = "image/jpeg" + MIMEImagePNG = "image/png" + MIMEImageGIF = "image/gif" + MIMEImageBitmap = "image/bmp" + MIMEImageWebP = "image/webp" + MIMEImageIco = "image/x-icon" + MIMEImageMicrosoftICO = "image/vnd.microsoft.icon" + MIMEImageTIFF = "image/tiff" + MIMEImageSVG = "image/svg+xml" + MIMEImagePhotoshop = "image/vnd.adobe.photoshop" + + // MIME audio + MIMEAudioBasic = "audio/basic" + MIMEAudioL24 = "audio/L24" + MIMEAudioMP3 = "audio/mp3" + MIMEAudioMP4 = "audio/mp4" + MIMEAudioMPEG = "audio/mpeg" + MIMEAudioOggVorbis = "audio/ogg" + MIMEAudioWAVE = "audio/vnd.wave" + MIMEAudioWebM = "audio/webm" + MIMEAudioAAC = "audio/x-aac" + MIMEAudioAIFF = "audio/x-aiff" + MIMEAudioMIDI = "audio/x-midi" + MIMEAudioM3U = "audio/x-mpegurl" + MIMEAudioRealAudio = "audio/x-pn-realaudio" + + // MIME video + MIMEVideoMPEG = "video/mpeg" + MIMEVideoOgg = "video/ogg" + MIMEVideoMP4 = "video/mp4" + MIMEVideoQuickTime = "video/quicktime" + MIMEVideoWinMediaVideo = "video/x-ms-wmv" + MIMEVideWebM = "video/webm" + MIMEVideoFlashVideo = "video/x-flv" + MIMEVideo3GPP = "video/3gpp" + MIMEVideoAVI = "video/x-msvideo" + MIMEVideoMatroska = "video/x-matroska" ) diff --git a/pkg/protocol/http1/req/request_test.go b/pkg/protocol/http1/req/request_test.go index a0a29de12..e123da406 100644 --- a/pkg/protocol/http1/req/request_test.go +++ b/pkg/protocol/http1/req/request_test.go @@ -532,7 +532,7 @@ func TestRequestHostFromHeader(t *testing.T) { func TestRequestContentTypeWithCharset(t *testing.T) { t.Parallel() - expectedContentType := "application/x-www-form-urlencoded; charset=UTF-8" + expectedContentType := consts.MIMEApplicationHTMLFormUTF8 expectedBody := "0123=56789" s := fmt.Sprintf("POST / HTTP/1.1\r\nContent-Type: %s\r\nContent-Length: %d\r\n\r\n%s", expectedContentType, len(expectedBody), expectedBody) diff --git a/pkg/protocol/request_test.go b/pkg/protocol/request_test.go index 0f5268685..fda96cd47 100644 --- a/pkg/protocol/request_test.go +++ b/pkg/protocol/request_test.go @@ -56,6 +56,7 @@ import ( "github.com/cloudwego/hertz/pkg/common/compress" "github.com/cloudwego/hertz/pkg/common/config" "github.com/cloudwego/hertz/pkg/common/test/assert" + "github.com/cloudwego/hertz/pkg/protocol/consts" ) type errorReader struct{} @@ -369,7 +370,7 @@ func TestRequestSetFormData(t *testing.T) { assert.DeepEqual(t, "username", string(r.postArgs.args[0].key)) assert.DeepEqual(t, "admin", string(r.postArgs.args[0].value)) assert.DeepEqual(t, true, r.parsedPostArgs) - assert.DeepEqual(t, "application/x-www-form-urlencoded", string(r.Header.contentType)) + assert.DeepEqual(t, consts.MIMEApplicationHTMLForm, string(r.Header.contentType)) r = &Request{} value := map[string][]string{"item": {"apple", "peach"}} @@ -573,7 +574,7 @@ func TestRequestPostArgs(t *testing.T) { mr := strings.NewReader(s) r := &Request{} r.SetBodyStream(mr, len(s)) - r.Header.contentType = []byte("application/x-www-form-urlencoded") + r.Header.contentType = []byte(consts.MIMEApplicationHTMLForm) arg := r.PostArgs() assert.DeepEqual(t, "username", string(arg.args[0].key)) assert.DeepEqual(t, "admin", string(arg.args[0].value))