Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Is it possible to know what render was used inside a middleware function? #4094

Open
manuelarte opened this issue Nov 14, 2024 · 6 comments · May be fixed by #4095
Open

Is it possible to know what render was used inside a middleware function? #4094

manuelarte opened this issue Nov 14, 2024 · 6 comments · May be fixed by #4095

Comments

@manuelarte
Copy link

manuelarte commented Nov 14, 2024

Description

I am creating a middleware function, and I want to modify the json that is sent back after the handler function is run. The thing is that, that json could be created in different ways:

c.IndentedJSON(http.StatusOK, body)
c.JSON(http.StatusOK, body)
...

In my middleware function, I would like to modify that json, and return it with the same "rendering" it was created, so, as an example, if it was using the indented json, I want to modify the json e.g, by wrapping it in another json, but return it in indented json format too, as it was originally written in the handler function.

How to reproduce

package main

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

func myMiddleware(c *gin.Context) {
   // do something here with the json response
}

func main() {
	g := gin.Default()
        g.Use(myMiddleware)
	g.GET("/hello/:name", func(c *gin.Context) {
                body := map[string]string{"name": "Manuel", "surname":"gin"}
		c.IndentedJSON(200, body)
	})
	g.Run(":9000")
}

Expectations

So in case that the middleware wraps the response, I would expect something like:

$ curl http://localhost:9000/hello/world
{
  "data": {
    "name": "Manuel",
    "surname": "gin"
  }
}

Actual result

$ curl -i http://localhost:9000/hello/world
{"data": {"name":"Manuel","surname": "gin"}}

Because I don't know how it was "rendered", I assumed it was using the normal c.JSON

Environment

  • go version: 1.23
  • gin version (or commit ref):
  • operating system: windows

Comment

Would it make sense to add a key in the context specifying what render was used?
Something like:

c.Set("gin:render", "indentedJSON")
@manuelarte manuelarte changed the title Is it possible to know what render was used when creating a middleware function? Is it possible to know what render was used inside a middleware function? Nov 14, 2024
@ChenPuChu
Copy link

I think your request is not reasonable, because how to return formatted JSON will increase network burden and processing time. And it will make the receiving party more complicated to handle.

@manuelarte
Copy link
Author

I think your request is not reasonable, because how to return formatted JSON will increase network burden and processing time. And it will make the receiving party more complicated to handle.

I think I did not explain myself properly, I am making a middleware function, and I want to know what render was used, so I'm not increasing network burden or anything like that.

It's true that in my middleware function I want to change the output, but that's not really related to the question. The question is how can I know what render was used, in case I modify the output, so therefore I can write to the buffer again following the same render

@ChenPuChu
Copy link

I think I understand what you mean. You want to customize a json parser and register it in gin. When using c.JSON, your customized parser will be called instead of the default parser.
Is my understanding correct?

@manuelarte
Copy link
Author

I think I understand what you mean. You want to customize a json parser and register it in gin. When using c.JSON, your customized parser will be called instead of the default parser. Is my understanding correct?

That actually would be a nice feature, but my idea is the following:

func endpointHandler(c *gin.Context) {
...
c.IndentedJSON(200, body)
}

Let's imagine that that endpoint returns the following:

{
  "code": 1,
  "price": 100
}

But now, imagine that I want to create a middleware function, that wraps that output json in a json like this:

{
  "data": {
      "code": 1,
      "price": 100
  },
  "_metadata": {
    "_links": "/products/1"
  }
}

But, if I use a middleware function to modify the output, I am unable to know whether c.JSON, or c.IndentedJSON or what other render, or any other was used to create the original json.

@ChenPuChu
Copy link

I think I understand what you mean. You want to customize a json parser and register it in gin. When using c.JSON, your customized parser will be called instead of the default parser. Is my understanding correct?

That actually would be a nice feature, but my idea is the following:

func endpointHandler(c *gin.Context) {
...
c.IndentedJSON(200, body)
}

Let's imagine that that endpoint returns the following:

{
  "code": 1,
  "price": 100
}

But now, imagine that I want to create a middleware function, that wraps that output json in a json like this:

{
  "data": {
      "code": 1,
      "price": 100
  },
  "_metadata": {
    "_links": "/products/1"
  }
}

But, if I use a middleware function to modify the output, I am unable to know whether c.JSON, or c.IndentedJSON or what other render, or any other was used to create the original json.

OK, if I understand correctly, the existing gin code cannot meet your requirements, so I want to implement this function during this period.
Then I will implement this function according to the ideas I proposed above. If you have better ideas, you are welcome to share them with me.

@manuelarte
Copy link
Author

manuelarte commented Nov 15, 2024 via email

ChenPuChu added a commit to ChenPuChu/gin that referenced this issue Nov 15, 2024
…to achieve the purpose of user-defined JSON rendering, while not changing the functions implemented by the original code

Signed-off-by: 朱宗辉 <[email protected]>
@ChenPuChu ChenPuChu linked a pull request Nov 15, 2024 that will close this issue
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants