luraproject / lura

Ultra performant API Gateway with middlewares. A project hosted at The Linux Foundation
https://luraproject.org
Other
6.35k stars 563 forks source link

How can I convert the `Post` request as `Get` request which respond `Post` from the backend? #212

Closed Michael2008S closed 5 years ago

Michael2008S commented 5 years ago

I want the config like this:

      {
        "endpoint": "/gcapi/coupon.CouponTemplate/View?id=1", 
        "method": "GET", 
        "backend": [
          {
            "host": ["micro-rpc-coupon"], 
            "disable_host_sanitize": true, 
            "url_pattern": "/gcrpc/coupon.CouponTemplate/View", 
            "encoding": "no-op", 
            "sd": "etcd"
          }
        ], 
        "output_encoding": "no-op"
      }, 

And the backend side request like this:

curl -X POST "https://dt.xxxxxxxxx.com/gcrpc/coupon.CouponTemplate/View" -H "accept: application/json" -H "Content-Type: application/json" -d "{ \"id\": \"1\"}"

It need to convert the 'GET' query param ?id=1 to the 'POST' payload "{ \"id\": \"1\"}" .

kpacha commented 5 years ago

hi, @Michael2008S

the krakend already supports changing the request method:

{
    "endpoint": "/get-to-post/{id}",
    "headers_to_pass": ["Content-Type"],
    "backend": [{
        "method": "POST",
        "url_pattern": "/__debug/?id={id}",
        "host": ["http://localhost:8000"]
    }]
}

after a request like this one curl -i localhost:8000/get-to-post/1234, you'll see something like this at the logs:

[KRAKEND] 2019/03/13 - 18:45:42.642 ▶ DEBUG Method: POST
[KRAKEND] 2019/03/13 - 18:45:42.642 ▶ DEBUG URL: /__debug/?id=1234
[KRAKEND] 2019/03/13 - 18:45:42.642 ▶ DEBUG Query: map[id:[1234]]
[KRAKEND] 2019/03/13 - 18:45:42.642 ▶ DEBUG Params: [{param /}]
[KRAKEND] 2019/03/13 - 18:45:42.642 ▶ DEBUG Headers: map[User-Agent:[KrakenD Version 0.8.0] Content-Length:[0] X-Forwarded-For:[::1] Accept-Encoding:[gzip]]
[KRAKEND] 2019/03/13 - 18:45:42.642 ▶ DEBUG Body:

there is no integrated request body manipulator in the default implementation, so you should add your custom martian modifier responsible for extracting the querystring params from the request URL and injecting them as the body request. for more details/examples on this:

db3net commented 5 years ago

I'm disappointed to see this reply - KrakenD has been the front-runner of our evaluations for its simple vertical integration. If I was a little more skilled, I'd fork and contribute something akin to #211 . Not denying the comprehensiveness of Martian, but it's an additional layer of dependency and complexity. To our evaluators, this means fragility and a loss of performance when the majority of our microservice endpoints consume POSTed JSON.

kpacha commented 5 years ago

I've just created a martian modifier covering the requested logic (https://github.com/kpacha/martian-components/tree/master/body/querystring2body). I'd say it's quite easy to use.

I think it is already possible to inject those modifiers without recompiling the binary (golang plugins to the rescue) but I'm quite open to add the required imports into the CE so the modifers are already available out-of-the-box.

regarding the performance impact: 'playing' with the request body will always impact the overall performance since KrakenD sends the request body as is.

Michael2008S commented 5 years ago

Is there something wrong with the plugin?

./krakend run -c krakend_proxy.json

console ouput:

[KRAKEND-sequential] 2019/03/14 - 14:03:39.750 ▶ ERROR {<nil> parse: unknown modifier: body.ESQuery} map[github.com/devopsfaith/krakend-martian:map[body.ESQuery:map[keys:[foo bar x]]]]

This is my config:

    {
      "endpoint": "/get-to-post/{id}",
      "method": "GET",
      "headers_to_pass": [
        "Content-Type"
      ],
      "backend": [
        {
          "url_pattern": "/__debug/gcrpc/coupon.CouponShop/View?id={id}",
          "method": "POST",
          "encoding": "JSON",
          "host": [
            "http://localhost:8008"
          ],
          "extra_config": {
            "github.com/devopsfaith/krakend-martian": {
              "body.ESQuery": {
                "keys" : ["foo", "bar", "x"]
              }
            }
          }
        }
      ]
    }

image

And I found that the Plugin didn't load ?

image

Now ,I try to load the plugins .

        i, err := plugin.Load(*cfg.Plugin, plugin.NewRegister())
        fmt.Println("plugin:", i, err)

It show me this err:

Parsing configuration file: ./krakend_proxy.json
/private/var/folders/f1/jn3rv4550qd3gmvwb23dlzg00000gp/T/___run_local_config flag redefined: v
unable to find the registrable symbol: plugin: symbol Registrable not found in plugin github.com/kpacha/martian-components/krakend-plugin/querystring2body
plugin: 0 plugin loader found 2 error(s): 
opening plugin 0 (./plugins/krakend-martian_es.so): /private/var/folders/f1/jn3rv4550qd3gmvwb23dlzg00000gp/T/___run_local_config flag redefined: v
opening plugin 1 (./plugins/krakend-martian_querystring2body.so): plugin: symbol Registrable not found in plugin github.com/kpacha/martian-components/krakend-plugin/querystring2body
[KRAKEND-sequential] 2019/03/14 - 18:07:39.615 ▶ ERROR unable to create the GELF writer: getting the extra config for the krakend-gelf module
Michael2008S commented 5 years ago

Hi, @kpacha .
I import _ "github.com/kpacha/martian-components/body/querystring2body" in the krakend-ce/main.go file. It work fine with this config:

{
      "endpoint": "/get-to-post/{id}",
      "method": "GET",
      "headers_to_pass": [
        "Content-Type"
      ],
      "backend": [
        {
          "url_pattern": "/gcrpc/coupon.CouponShop/View?id={id}",
          "method": "POST",
          "encoding": "JSON",
          "host": [
            "https://dt.xxx.com"
          ],
          "extra_config": {
            "github.com/devopsfaith/krakend-martian": {
              "body.FromQuerystring": {
                "keys_to_extract": [
                  "id"
                ],
                "template": "{\"id\":\"{{index .id 0}}\"}",
                "method": "POST"
              }
            }
          }
        }
      ]
    },

And I try to merge two post request with the config below:

{
      "endpoint": "/get-to-merge-post/{id}",
      "method": "GET",
      "headers_to_pass": [
        "Content-Type"
      ],
      "backend": [
        {
          "url_pattern": "/gcrpc/coupon.CouponShop/View?id={id}",
          "method": "POST",
          "encoding": "JSON",
          "host": [
            "https://dt.xxx.com"
          ],
          "extra_config": {
            "github.com/devopsfaith/krakend-martian": {
              "body.FromQuerystring": {
                "keys_to_extract": [
                  "id"
                ],
                "template": "{\"id\":\"{{index .id 0}}\"}",
                "method": "POST"
              }
            }
          }
        },
        {
          "url_pattern": "/gcrpc/coupon.CouponTemplate/View?id={id}",
          "method": "POST",
          "encoding": "JSON",
          "host": [
            "https://dt.xxx.com"
          ],
          "extra_config": {
            "github.com/devopsfaith/krakend-martian": {
              "body.FromQuerystring": {
                "keys_to_extract": [
                  "id"
                ],
                "template": "{\"id\":\"{{index .id 0}}\"}",
                "method": "POST"
              }
            }
          }
        }
      ]
    },

When the backend both return 200 is ok. But when the backend one of them return 500 or both return 500. The proxy alway return 200. So how did I fix this problem?

kpacha commented 5 years ago

@Michael2008S it looks like you spotted a bug there (sequential merge)!

I'm opening a new issue (I'm already working on it)

regarding the plugins, I'm not sure if they were enabled by default at the CE...

thanks

github-actions[bot] commented 2 years ago

This issue was marked as resolved a long time ago and now has been automatically locked as there has not been any recent activity after it. You can still open a new issue and reference this link.