Comments (14)
we ended up rewriting application/x-www-form-urlencoded
requests as JSON prior to the grpc-gateway receiving them like this:
formWrapper := func(h http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
log.Printf("Got request: %#v\n", r)
if strings.ToLower(strings.Split(r.Header.Get("Content-Type"), ";")[0]) == "application/x-www-form-urlencoded" {
log.Println("Rewriting form data as json")
if err := r.ParseForm(); err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
log.Println("Bad form request", err.Error())
return
}
jsonMap := make(map[string]interface{}, len(r.Form))
for k, v := range r.Form {
if len(v) > 0 {
jsonMap[k] = v[0]
}
}
jsonBody, err := json.Marshal(jsonMap)
if err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
}
r.Body = ioutil.NopCloser(bytes.NewReader(jsonBody))
r.ContentLength = int64(len(jsonBody))
r.Header.Set("Content-Type", "application/json")
}
mux.ServeHTTP(w, r)
})
}
if err := http.ListenAndServe(":8080", formWrapper(mux)); err != nil {
log.Fatalf("failed to start gateway server on 8080: %v", err)
}
from grpc-gateway.
Is this supported or still open?
I'm implementing an OAuth2 server and the RFC requires the request Content-Type to be application/x-www-form-urlencoded.
from grpc-gateway.
Below is my custom marshaler for decoding the request in x-www-form-urleencoded format and returning the response in JSON. Hope this can help someone who suffer the same problem.
package marshaler
import (
"encoding/json"
"fmt"
"io"
"io/ioutil"
"net/url"
"github.com/grpc-ecosystem/grpc-gateway/v2/runtime"
"github.com/grpc-ecosystem/grpc-gateway/v2/utilities"
"google.golang.org/protobuf/proto"
)
type UrlEncodeMarshal struct {
runtime.Marshaler
}
// ContentType means the content type of the response
func (u UrlEncodeMarshal) ContentType(_ interface{}) string {
return "application/json"
}
func (u UrlEncodeMarshal) Marshal(v interface{}) ([]byte, error) {
return json.Marshal(v)
}
// NewDecoder indicates how to decode the request
func (u UrlEncodeMarshal) NewDecoder(r io.Reader) runtime.Decoder {
return runtime.DecoderFunc(func(p interface{}) error {
msg, ok := p.(proto.Message)
if !ok {
return fmt.Errorf("not proto message")
}
formData, err := ioutil.ReadAll(r)
if err != nil {
return err
}
values, err := url.ParseQuery(string(formData))
if err != nil {
return err
}
filter := &utilities.DoubleArray{}
err = runtime.PopulateQueryParameters(msg, values, filter)
if err != nil {
return err
}
return nil
})
}
from grpc-gateway.
@jhowliu do you prefer to make a PR yourself so I add the tests to your PR or should I create the PR with your code myself?
from grpc-gateway.
+1 It would be useful to have it built-in!
from grpc-gateway.
After one afternoon reading the f**king source code.
This solution is not good.
- It cannot check the input whether a int or string by pb.
- ...
The good solution is:
- make
post && form
useget
logic. - change the autogen code:
- func request_Example_GetForm_0(ctx context.Context, marshaler runtime.Marshaler, client ExampleClient, req *http.Request, pathPar
| var protoReq FormRequest
| var metadata runtime.ServerMetadata
|
| ---------------------------from form data to genrate : req.URL.Query() ------------------------------
| if err := runtime.PopulateQueryParameters(&protoReq, req.URL.Query(), filter_Example_GetForm_0); err != nil {
| return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
| }
|
| msg, err := client.GetForm(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
| return msg, metadata, err
|
| }
- change the form data to url.Values then call:
PopulateQueryParameters(msg proto.Message, values url.Values, filter *utilities.DoubleArray)
from grpc-gateway.
any update? @yugui
from grpc-gateway.
I don't know anyone working on this at the moment. Are you interested in helping add support for this?
from grpc-gateway.
@johanbrandhorst I'll try it after reading the relevant code
from grpc-gateway.
what are the protocols for this in 2022? We are trying to support receiving data from third party APIs (so we cannot control the format of the post request) and we ran into this issue. What are people doing to properly serve x-www-form-urlencoded via gprc-gateway? Is there any option besides writing our own custom marshaler?
I see this pull request but it was not merged, and it references another PR that was merged but it doesn't seem to affect whether or not we can add support for x-www-form-urlencoded requests
from grpc-gateway.
I think your only recourse today is a custom marshaler.
from grpc-gateway.
This works fine. Any chance this could get merge in here? I'm happy to contribute in unit testing as it seems that was missing part in https://github.com/grpc-ecosystem/grpc-gateway/pull/548/files
from grpc-gateway.
Yes, we'd be happy to accept a new contribution for this, thank you!
from grpc-gateway.
Hi @mickael-kerjean , sorry about waiting for a while. I have made a PR. Feel free to add the tests.
https://github.com/jhowliu/grpc-gateway/tree/feat/support-url-form-encoded-marshaler
from grpc-gateway.
Related Issues (20)
- Populating query param semantics changed since v2.15.0 HOT 3
- When the body is set to a oneof field, other fields in the same group are included as query.
- For a field of type google.protobuf.Empty, FieldMaskFromRequestBody does not generate any fieldmask HOT 3
- generate swagger schema title and description failed HOT 2
- Issue with importing "github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-grpc-gateway" HOT 3
- genopenapi: Stable openapi names for nested types HOT 1
- snake_case response HOT 1
- api_visibility doesn't transitively apply to rpc request/response messages HOT 2
- protoc-gen-grpc-gateway and protoc-gen-openapiv2 return incorrect version HOT 1
- Dependency on google.golang.org/grpc/health/grpc_health_v1 conflicts with custom proto marshallers HOT 5
- JSONPb marshaler doesn't use indent on non proto fields
- WriteHeader is not called on 200s HOT 1
- How to set cookie to http response header? Why it doesn't work. HOT 2
- Adding custom mux endpoint to openapi output HOT 3
- The API Gateway Vision HOT 2
- Support disabling default response rendering in bazel rule HOT 1
- Example and pattern annotations are not respect for query and path parameters HOT 8
- FieldMask as query param is not converted to snake case HOT 1
- an google.protobuf.Any type how to get openapiv2 output? HOT 1
- omit-enum-default-value Generates Invalid Spec for Enums with a Single Value HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from grpc-gateway.