go-chi / render Goto Github PK
View Code? Open in Web Editor NEWeasily manage HTTP request / response payloads of Go HTTP services
License: MIT License
easily manage HTTP request / response payloads of Go HTTP services
License: MIT License
Sometimes I don't need to validate anything in request.
Would you consider a PR where render.Bind accepts r *http.Request, v interface{}
, and if v
implements Bind() method only then execute it?
Referenced issue: go-chi/chi#177
Why not add Validator option, but not inside the code, only a default struct that after each one can config with the validator that want.
Like:
render.Validator := &DefaultValidator{...} ....
and after use something like:
render.Validate(...)
or something inside de Bind.
What do you think?
How do I render protobuf messages with go-chi/render?
In the responder, render.JSON() function takes in an "http.Request" object which will be used to get the http response status code
I'm customizing the behavior of the function, by wrapping it with a wrapper function in my project. So I can call one function to pass in the response body as well as the status code, like so
func (r *responder) JSON(w http.ResponseWriter, v interface{}, s int) {
// Write http response status
w.WriteHeader(s)
render.JSON(w, nil, v)
}
When "nil" is passed is shown above instead of an http.Request object, the function throws an error.
--- FAIL: TestJSON (0.00s)
panic: runtime error: invalid memory address or nil pointer dereference [recovered]
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0xf0 pc=0x12a9ca0]
Here is the test I wrote to test the wrapper:
func TestJSON(t *testing.T) {
type mockResponse struct {
MockField string `json:"field"`
}
responder := NewResponder()
recorder := httptest.NewRecorder()
responder.JSON(recorder, mockResponse{MockField: "test"}, http.StatusOK)
assert.Equal(t, recorder.Code, 200)
assert.JSONEq(t, `{"field": "test"}`, recorder.Body.String())
}
I did some debugging, it seems like the error is caused by line 103 in JSON function in responder.go, which is the following:
if status, ok := r.Context().Value(StatusCtxKey).(int); ok {
w.WriteHeader(status)
}
How about adding a check for when the request object is nil, it skips this whole check and only writes the body to the buffer?
I was writing some unit tests for my http handlers and I came across a weird scenario where there was a new line /n
char being added to the end of my JSON response (and hence my test failing when comparing the string responses).
On investigating it seems to be exected behaviour when using the the json.NewEncoder(buf)
. Apparently its useful for logging programs etc when you want to be able to ouput things to your terminal or a logging program and the newline is particularly useful, however I'm not sure why its being used here.
Could someome please explain to me why this function uses json.NewEncoder(buf)
rather than json.Marshal(v interface{})
I'd really appreciate it.
Is it a performance reason?
🙋🏻♂️ Hello! I am starting with chi for my personal project. Is there some way to return an error if the received json request has an additional unexpected field?
Using the json.NewDecode(r.body) we can set dec.DisallowUnknownFields()
and when we unmarshal the json object via Decode method we get that information error in the err value err := dec.Decode(&someStructType)
I am seeing the chi examples but I don't find examples about it.
Thanks for your assistance!
I want to use github.com/goccy/go-json
as JSON serializer.
I'd like to see an API to easily replace the serializer, like echo.
This is an example about echo.
https://github.com/fujiwara/isucon11-f/pull/9/files
The documentation for SetContentType
only mentions responses and says nothing of requests:
SetContentType is a middleware that forces response Content-Type.
However, this breaks Content-Type detection for requests in the DefaultDecoder
because SetContentType
and GetRequestContentType
share the same context key.
It's not obvious to me why GetRequestContentType
even looks at the context, as that seems to betray the function name. But if that behavior is going to stay, I suggest using a separate context key so that SetContentType
does not interfere.
Hi.
I would like to find out (for educational purposes) why "reflect.Select ()" is used instead of "select {}"?
I do not see any advantages using the "reflect" package.
...
switch chosen, recv, ok := reflect.Select([]reflect.SelectCase{
{Dir: reflect.SelectRecv, Chan: reflect.ValueOf(ctx.Done())},
{Dir: reflect.SelectRecv, Chan: reflect.ValueOf(v)},
}); chosen {
case 0:
...
default:
...
}
...
https://github.com/go-chi/render/blob/master/responder.go#L160-L163
vs
select {
case <- ctx.Done():
...
case recv, ok <- v:
...
}
Hello,
I'm a long time go-chi user and in the last year I started using render as well.
Recently I noticed that there have been some changes merged to master
that haven't been yet tagged. This means that currently you're unable
to use the latest version of render, unless you pin the version to a commit hash
or master directly. Have you considered tagging a new v1.0.2
version? v1.0.1
is quite old – created on the 31st of may 2018.
in this line:
https://github.com/go-chi/render/blob/master/responder.go#L109
it says:
// XML marshals 'v' to JSON, setting the Content-Type as application/xml. It
But that should be
// XML marshals 'v' to XML, setting the Content-Type as application/xml. It
type req struct {
PerPage string `query:"per_page"`
APIKey string `query:"key"`
}
// an alternative to render.Bind to check query params and convert into req
In the responder.go
file, the JSON function sets escapeHTML
to true.
However, the json.NewEncoder
defaults to escapeHTML: true
.
This appears to be redundant.
Source code for json.NewEncoder:
func NewEncoder(w io.Writer) *Encoder {
return &Encoder{w: w, escapeHTML: true}
}
One of the properties inside my JSON payload is a slice. In my case the children
property.
type Body struct {
Name string `json:"name"`
Children Children `json:"children"`
}
func (b Body) Bind(r *http.Request) error {
if b.Name == "" {
return errors.New("empty body name")
}
return nil
}
type Children []Child
func (c Children) Bind(r *http.Request) error {
if c == nil {
return errors.New("no children provided")
}
return nil
}
type Child struct {
Name string `json:"name"`
}
func (c Child) Bind(r *http.Request) error {
if c.Name == "" {
return errors.New("empty child name")
}
return nil
}
I implemented the Bind
interface for each of the types, but the Child
elements are not validated when calling render.Bind
on the Body
struct.
Here a full example:
https://go.dev/play/p/fGMSdjRDrtg
Is this expected or am i doing something wrong?
Sometimes we need the DB object to do more complex work in Bind or Render... what is the suggested way to do this (putting db in context feels wrong), or is it a smell?
Hi,
I wanted to use the package, due to Bind and already using chi (of course), but I missed an easier way to encode structs like I do with @unrolled/render:
render.JSON(w, http.StatusOK, data)
Could you explain why that is a bad idea (if it is) ?
Thanks for chi!
Hi,
I have been using the go-chi/render
library in my projects, and I've found it very helpful. I noticed that there have been some commits in the master branch since the last tagged release v1.0.2
.
The code in master is not tagged. Latest tagged version is v1.0.2
which doesn't match latest commit in master c196354
Thank you for your work on go-chi/render
. Your continued maintenance of this project is much appreciated!
It seems there is some special handling done for accepting status and response in a predefined order.
When I try to set the JSON response before setting the HTTP status, it seems the HTTP status is not updated.
if err == nil {
....
....
s := http.StatusInternalServerError
if err == nil {
s = http.StatusOK
render.JSON(w, r, response)
}
}
render.Status(r, s)
So basically, I only render JSON if it's not an error and then set status as part of common code.
But It looks like render.Status(r, s)
does not work after you have done the render JSON.
The response from the server is always 200.
On Changing this to the below it seems to be working fine.
if err == nil {
....
....
s := http.StatusInternalServerError
if err == nil {
s = http.StatusOK
}
}
render.Status(r, s)
render.JSON(w, r, response)
but this now sends a zero object response even though the status code is 500
It seems the form library used is dead.
Line 5 in b30a1a0
No commit since 2020, last tagged release 2016.
I'm just pointing it out, as we were looking to replace gorilla/schema
in our project with render
. However, it might not be that suitable if it suffers the same (indirect) fate as gorilla/schema
.
Because json.NewDecoder expects to decode a stream of objects, it lets malicious clients add garbage data to the end of a request, which may lead to a "confused deputy" security bug.
See golang/go#36225.
Quite often the response to my API is a file such as an image or pdf. It would be nice to be able to use render.Data and be able to set the Content-Type to something other than application/octet-stream.
To get around this limitation at the moment I use render.JSON or render.XML for sending back JSON or XML data and then fall back to useing http.ResponseWriter.Write for files.
It would be nice not to have to fall back to using the http.ResponseWriter and just use the render.Data to handle files.
Please include more docs and let users know about breaking changes after an update.
decorder does not support application/x-www-form-urlencoded
yet
Line 28 in 7bbdb19
The most recent issues have no answers and some of these issues are reporting security concerns.
Is this project still maintained?
I can give a PR for the same, however, as defined in the travis config, we will lose out support for go v1.7.x and v1.8.x.
Line 30 in 3215478
If the returned error are defined var, it would be possible to compare and know what exactly happened. The error message from render package cannot be directly to client in most cases, but application developer would like to return some custom error.
var (
ErrContentTypeNotSet = errors.New("render: missing content-type, unable to automatically decode the request content")
)
would be helpful.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.