apache / apisix-go-plugin-runner

Go Plugin Runner for APISIX
https://apisix.apache.org/
Apache License 2.0
167 stars 69 forks source link

request help: How to pass headers from plugin runner to upstream #69

Open RagavMaddali opened 2 years ago

RagavMaddali commented 2 years ago

Issue description

We want to send custom headers from go plugin runner to the upstream. We have tried adding it to both request object and response object in custom plugin filter , but both are not working.

w http.ResponseWriter, r pkgHTTP.Request
r.Header().Set("x-team-info","abc")
w.Header().Add("x-team-info","abc)

Looking for a way to send headers from plugin runner filter to the upstream. We want to append new headers to the upstream.

Environment

cc: @Sudalaimuthu

juzhiyuan commented 2 years ago

Hi @bzp2010, are you familiar with this?

Slack: https://the-asf.slack.com/archives/CUC5MN17A/p1645642934073029

shuaijinchao commented 2 years ago

@RagavMaddali I have not reproduced the problem in my development environment.

Below is my configuration:

APISIX Route

curl http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
{
  "uri": "/go/runner",
  "plugins": {
    "ext-plugin-pre-req": {
      "conf": [
        { "name": "say", "value":"{\"body\":\"hello\"}"}
      ]
    }
  },
  "upstream": {
        "type": "roundrobin",
        "nodes": {
            "127.0.0.1:1980": 1
        }
    }
}'

Plugin

func init() {
    err := plugin.RegisterPlugin(&Say{})
    if err != nil {
        log.Fatalf("failed to register plugin say: %s", err)
    }
}

// Say is a demo to show how to return data directly instead of proxying
// it to the upstream.
type Say struct {
}

type SayConf struct {
    Body string `json:"body"`
}

func (p *Say) Name() string {
    return "say"
}

func (p *Say) ParseConf(in []byte) (interface{}, error) {
    conf := SayConf{}
    err := json.Unmarshal(in, &conf)
    return conf, err
}

func (p *Say) Filter(conf interface{}, w http.ResponseWriter, r pkgHTTP.Request) {
    body := conf.(SayConf).Body
    if len(body) == 0 {
        return
    }

    r.Header().Set("X-A6-Runner", "Go")
    r.Header().Set("X-A6-Hello", "World")
}

Request & Response

$ curl http://127.0.0.1:9080/go/runner                                                                                                                                                                                
---Headers
x-a6-runner:Go
x-a6-hello:World
host:127.0.0.1:9080
x-real-ip:127.0.0.1
x-forwarded-for:127.0.0.1
x-forwarded-proto:http
x-forwarded-host:127.0.0.1
x-forwarded-port:9080
user-agent:curl/7.68.0
accept:*/*
---Args
---URI
/go/runner
---Service Node
Ubuntu-DEV-1980

Note

If you want to forward the request headers set in the Runner to the upstream, do not manipulate the http.ResponseWriter object, it will terminate the request.

RagavMaddali commented 2 years ago

Tnq for the information. We will update this thread soon.

RagavMaddali commented 2 years ago

@shuaijinchao I have one question, while creating the upstream we are using adding the following attributes :

"pass_host": "rewrite",
"upstream_host": "value",

Will this configuration override the headers being generated on the go plugin ?

shuaijinchao commented 2 years ago

I think you can verify this locally. Also note that the runner plugin has two phases that can be invoked.

goxiaoy commented 2 years ago

Works for me

w http.ResponseWriter, r pkgHTTP.Request
r.Header().Set("x-team-info","abc")