gin icon indicating copy to clipboard operation
gin copied to clipboard

Errors encountered during rendering do not assign the type ErrorTypeRender

Open nicholastanx opened this issue 1 year ago • 2 comments

Description

In summary, ErrorTypeRender does not appear to be used anywhere in the code.

We discovered this issue when we were having marshalling failures in context.JSON(). We tried checking context.Errors for errors with type ErrorTypeRender, and realised that nowhere in the code is that set.

Could open a PR for this but wanted to confirm if it was intended or not, since ErrorTypes are super old. I could not find any thread or issue that would suggest it though.

How to reproduce

package main

import (
	"fmt"
	"net/http"
	"net/http/httptest"

	"github.com/gin-gonic/gin"
)

type ProblemObj struct {
}

func (f *ProblemObj) MarshalJSON() ([]byte, error) {
	return nil, fmt.Errorf("this is an error")
}

func main() {
	c, _ := gin.CreateTestContext(httptest.NewRecorder())
	prob := &ProblemObj{}
	c.JSON(http.StatusOK, prob)
	for _, err := range c.Errors {
		fmt.Println(err.IsType(gin.ErrorTypeRender))
	}
}

Expectations

The test code should print true, since the error was occurred during rendering.

Actual result

The test code prints false.

Environment

  • go version: v1.21.1
  • gin version (or commit ref): v1.9.1 and v1.10.0
  • operating system: Mac AMD64

nicholastanx avatar May 07 '24 05:05 nicholastanx

I checked the relevant functions and submission history. This method is quite old and modifications may have a greater impact. I feel that it is not suitable to modify it directly. It is more appropriate to write a branch function and handle it separately for Render.

RedCrazyGhost avatar May 07 '24 14:05 RedCrazyGhost

@RedCrazyGhost What impact?

I don't see any impact, just update following code:

// Render writes the response headers and calls render.Render to render data.
func (c *Context) Render(code int, r render.Render) {
	c.Status(code)

	if !bodyAllowedForStatus(code) {
		r.WriteContentType(c.Writer)
		c.Writer.WriteHeaderNow()
		return
	}

	if err := r.Render(c.Writer); err != nil {
		// Pushing error to c.Errors
		_ = c.Error(err)
		c.Abort()
	}
}

replace _ = c.Error(err)

with _ = c.Error(err).SetType(ErrorTypeRender)

dukepan2005 avatar May 10 '24 02:05 dukepan2005