feat(render): add PDF renderer and tests (#4491)

* render: add PDF renderer and tests

* render: update PDF renderer copyright header

* test: add PDF rendering tests including 204 No Content in context_test.go
This commit is contained in:
Aum Patel 2026-02-28 18:34:54 +05:30 committed by GitHub
parent ff00c01e67
commit 052d1a79aa
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 76 additions and 0 deletions

View File

@ -1224,6 +1224,12 @@ func (c *Context) XML(code int, obj any) {
c.Render(code, render.XML{Data: obj})
}
// PDF writes the given PDF binary data into the response body.
// It also sets the Content-Type as "application/pdf".
func (c *Context) PDF(code int, data []byte) {
c.Render(code, render.PDF{Data: data})
}
// YAML serializes the given struct as YAML into the response body.
func (c *Context) YAML(code int, obj any) {
c.Render(code, render.YAML{Data: obj})

View File

@ -1320,6 +1320,33 @@ func TestContextRenderNoContentXML(t *testing.T) {
assert.Equal(t, "application/xml; charset=utf-8", w.Header().Get("Content-Type"))
}
// TestContextRenderPDF tests that the response is serialized as PDF
// and Content-Type is set to application/pdf
func TestContextRenderPDF(t *testing.T) {
w := httptest.NewRecorder()
c, _ := CreateTestContext(w)
data := []byte("%Test pdf content")
c.PDF(http.StatusCreated, data)
assert.Equal(t, http.StatusCreated, w.Code)
assert.Equal(t, data, w.Body.Bytes())
assert.Equal(t, "application/pdf", w.Header().Get("Content-Type"))
}
// Tests that no PDF is rendered if code is 204
func TestContextRenderNoContentPDF(t *testing.T) {
w := httptest.NewRecorder()
c, _ := CreateTestContext(w)
data := []byte("%Test pdf content")
c.PDF(http.StatusNoContent, data)
assert.Equal(t, http.StatusNoContent, w.Code)
assert.Empty(t, w.Body.Bytes())
assert.Equal(t, "application/pdf", w.Header().Get("Content-Type"))
}
// TestContextRenderString tests that the response is returned
// with Content-Type set to text/plain
func TestContextRenderString(t *testing.T) {

26
render/pdf.go Normal file
View File

@ -0,0 +1,26 @@
// Copyright 2026 Gin Core Team. All rights reserved.
// Use of this source code is governed by a MIT style
// license that can be found in the LICENSE file.
package render
import "net/http"
// PDF contains the given PDF binary data.
type PDF struct {
Data []byte
}
var pdfContentType = []string{"application/pdf"}
// Render (PDF) writes PDF data with custom ContentType.
func (r PDF) Render(w http.ResponseWriter) error {
r.WriteContentType(w)
_, err := w.Write(r.Data)
return err
}
// WriteContentType (PDF) writes PDF ContentType for response.
func (r PDF) WriteContentType(w http.ResponseWriter) {
writeContentType(w, pdfContentType)
}

View File

@ -31,6 +31,7 @@ var (
_ Render = (*AsciiJSON)(nil)
_ Render = (*ProtoBuf)(nil)
_ Render = (*TOML)(nil)
_ Render = (*PDF)(nil)
)
func writeContentType(w http.ResponseWriter, value []string) {

View File

@ -466,6 +466,22 @@ func TestRenderXMLError(t *testing.T) {
assert.Contains(t, err.Error(), "xml: unsupported type: chan int")
}
func TestRenderPDF(t *testing.T) {
w := httptest.NewRecorder()
data := []byte("%Test pdf content")
pdf := PDF{data}
pdf.WriteContentType(w)
assert.Equal(t, "application/pdf", w.Header().Get("Content-Type"))
err := pdf.Render(w)
require.NoError(t, err)
assert.Equal(t, data, w.Body.Bytes())
assert.Equal(t, "application/pdf", w.Header().Get("Content-Type"))
}
func TestRenderRedirect(t *testing.T) {
req, err := http.NewRequest(http.MethodGet, "/test-redirect", nil)
require.NoError(t, err)