kong / go-pdk Goto Github PK
View Code? Open in Web Editor NEWWrite Kong plugins in Go! ๐ฆ
Home Page: https://pkg.go.dev/github.com/Kong/go-pdk
License: Apache License 2.0
Write Kong plugins in Go! ๐ฆ
Home Page: https://pkg.go.dev/github.com/Kong/go-pdk
License: Apache License 2.0
I want to integrate my plugin with the go-pdk server:
func main() {
log.Info().Str("version", version).Msg("Starting pdk server")
server.StartServer(New, version, 100)
}
If I run go test
I get
flag provided but not defined: -test.paniconexit0
Usage of /tmp/go-build1002799689/b001/bm-authx.test:
-dump
Dump info about plugins
-help
Show usage info
-kong-prefix string
Kong prefix path (specified by the -p argument commonly used in the kong cli) (default
"/usr/local/kong")
exit status 2
FAIL bm-authx 0.003s
After reading through docs at https://golang.org/doc/go1.13#testing
As a result, testing flags are now only registered when running a test binary, and packages that call flag.Parse during package initialization may cause tests to fail.
I think https://github.com/Kong/go-pdk/blob/master/server/server.go#L32 violates the testing rules for golang, e.g.:
func init() {
flag.Parse()
// ...
}
There only getXXX methods inkong/db/dao/plugins/go.lua
and bridge.go
, can I have a way to set kong.ctx in go plugin?
I'm talking about this method here - http://docs.konghq.com/1.4.x/pdk/kong.response/#kongresponseexitstatus-body-headers
I see a TODO here for the same in golang pdk
Line 60 in b5672ac
I'm interested to analyze and raise a PR if that's okay. In any case, I'm going to try it out. If I back out at any point, I'll report back so that someone else can pick it up ๐
This surely helps for other developer to contribute into this repo. Moreover, we can help the predefinied standard and guideline.
Currently, I don't think there's a simple way to perform expensive initialization steps that depend on each plugin instance Config
attributes.
For instance, I'm currently working on a (private) plugin that has a parameter_name
config setting, which refers to AWS SSM Parameter Store. This value is relatively stable, can be cached for long periods, and is needed on my Access
implementation.
Currently, I have to do something along these lines:
type Config struct {
ParameterName `json:"parameter_name"`
parameterValueInit sync.Once
parameterValue string
}
func (c *Config) Access(kong *pdk.Pdk) {
c.parameterValueInit.Do(func() {
c.parameterValue = actuallyGetParameter(c.ParameterName)
})
// actually use c.parameterValue
}
Which means that the first request per plugin instance is burdened with this extra latency.
At first glance, the plugin constructor function would be the place for this kind of expensive shared initialization, but at that point I don't have ParameterName
yet. Which means that I can only perform initialization that is global and doesn't depend on plugin configuration.
My suggestion here would be to introduce some kind of "init" hook, called after plugin instance construction but before any requests are served to the plugin instance. If applied to the example above, it could become something like this:
type Config struct {
ParameterName `json:"parameter_name"`
parameterValue string
// Once is no longer necessary
}
// only called once per plugin instance
// assuming ParameterName is already unmarshalled here
func (c *Config) Init() {
c.parameterValue = actuallyGetParameter(c.ParameterName)
}
func (c *Config) Access(kong *pdk.Pdk) {
// simply use c.parameterValue
}
I also feel like some kind of shutdown hook could be useful. It could be used for things like flushing/closing files etc; for instance, the current go-log example plugin leaks file descriptors as far as I can tell.
excuse me,I use the version of go:1.16 and [email protected] and [email protected],But there was a problem running the plugin.
I'm trying to create a go plugin and it looks like pdk is complaining about using kong.log.serialize
under the hood?
Kong version: 2.1 (beta)
2020/08/04 19:43:51 [notice] 65021#0: *26 [kong] go.lua:97 go-pluginserver terminated: exit 2, context: ngx.timer
2020/08/04 19:43:51 [notice] 65021#0: *26 [kong] go.lua:86 Starting go-pluginserver, context: ngx.timer
2020/08/04 19:43:51 [warn] 65021#0: *426 [kong] basic.lua:12 [guts] basic log serializer has been deprecated, please modify your plugin to use the kong.log.serialize PDK function instead while logging request, client: 127.0.0.1, server: kong, request: "POST /phoenix/api/0.1/rebuild HTTP/1.1", upstream: "https://10.34.1.201:443/api/0.1/rebuild", host: "localhost:8000"
package main
import (
"github.com/Kong/go-pdk"
)
type Config struct {
Path string
Reopen bool
}
func New() interface{} {
return &Config{}
}
func (conf Config) Access(kong *pdk.PDK) {
// after request has been sent stop timer with correct tags
uuid, err := kong.Request.GetHeader("Kong-Request-ID")
if err != nil {
kong.Log.Info("[Request]: error receiving request id", uuid)
}
}
func (conf Config) Log(kong *pdk.PDK) {
uuid, err := kong.Request.GetHeader("Kong-Request-ID")
if err != nil {
kong.Log.Err("[Response]: error receiving request id", uuid)
}
}
Are there any plans to update the supported Go versions? You're still running on Go version 1.13, which is over 2 years old at this point and has a number of security vulnerabilities.
I'm trying to debug my go-plugin by printing some debug logs with kong.Log
However, I don't know where to find the printed logs ?
I'm running kong with alpine docker image, and the logs I printed are not shown from stdout/stderr.
And where I can find the debug logs of go-pluginserver, I had an issue that sometimes my go-plugin stops to work, looks like Access() is not called. I'm trying to figure out why..
Any idea ?
i am using kong 2.1.0 , and try to get current request route as below:
func getRoute(kong *pdk.PDK) (string, error) {
var routeObj, routeErr = kong.Router.GetRoute()
if routeErr != nil {
var msg = fmt.Sprintf("unable to get current request route , error : %v", routeErr)
logger(msg)
return "", errors.New(msg)
}
....
}
but see lots errors like this:
2020/08/07 21:57:11 [debug] 37#0: *1851 [kong] go.lua:352 unable to get current request route , error : expected type: entities.Route
What caused this ?
How to fix or workaround ?
I'm trying to configure corporate proxy for go kong plugin
here is my code:
package main
import (
"github.com/Kong/go-pdk"
)
type Config struct {
Apikey string
}
func New() interface{} {
return &Config{}
}
func (conf Config) Access(kong *pdk.PDK) {
err := kong.Nginx.SetCtx("balancer_address.host", "127.0.0.1")
if err != nil {
kong.Log.Err(err.Error())
}
errC := kong.Nginx.SetCtx("balancer_address.port","8080")
if errC != nil {
kong.Log.Err(errC)
}
key, err := kong.Request.GetQueryArg("key")
apiKey := conf.Apikey
if err != nil {
kong.Log.Err(err.Error())
}
x := make(map[string][]string)
x["Content-Type"] = append(x["Content-Type"], "application/json")
if apiKey != key {
kong.Response.Exit(403, "Youu have no correct key", x)
}
}
of course i created test proxy server at my host: 127.0.0.1:8080
but it's not working
by plugin doc: kong.Nginx.SetCtx() sets a value in the ngx.ctx
request context table
i made my go plugin by example https://github.com/tfabien/kong-forward-proxy/blob/master/src/access.lua
where
ngx.ctx.balancer_address.host = plugin_conf.proxy_host
ngx.ctx.balancer_address.port = plugin_conf.proxy_port
are configuring proxy
so, anyway it's not working
my dockerfile is
FROM kong/go-plugin-tool:2.0.4-alpine-latest AS builder
RUN mkdir -p /tmp/key-checker/
COPY . /tmp/key-checker/
RUN cd /tmp/key-checker/ && \
go get github.com/Kong/go-pdk && \
go mod init kong-go-plugin && \
go get -d -v github.com/Kong/go-pluginserver && \
go build github.com/Kong/go-pluginserver && \
go build -buildmode plugin key-checker.go
FROM kong:2.3-alpine
RUN mkdir /tmp/go-plugins
COPY --from=builder /tmp/key-checker/go-pluginserver /usr/local/bin/go-pluginserver
COPY --from=builder /tmp/key-checker/key-checker.so /tmp/go-plugins
ENV KONG_PLUGINSERVER_NAMES="go"
ENV KONG_PLUGINSERVER_GO_SOCKET="/tmp/go-plugins/go_pluginserver.sock"
ENV KONG_PLUGINSERVER_GO_START_CMD="/usr/local/bin/go-pluginserver -kong-prefix /tmp/go-plugins/ -plugins-directory /tmp/go-plugins"
ENV KONG_PLUGINSERVER_GO_QUERY_CMD="/usr/local/bin/go-pluginserver -dump-all-plugins -plugins-directory /tmp/go-plugins"
COPY config.yml /tmp/config.yml
USER root
RUN chmod -R 777 /tmp
RUN /usr/local/bin/go-pluginserver -version && \
cd /tmp/go-plugins && \
/usr/local/bin/go-pluginserver -dump-plugin-info key-checker
USER kong
starting docker by:
docker run -ti --rm --name kong-go-plugins \
-e "KONG_DATABASE=off" \
-e "KONG_GO_PLUGINS_DIR=/tmp/go-plugins" \
-e "KONG_DECLARATIVE_CONFIG=/tmp/config.yml" \
-e "KONG_GO_PLUGINSERVER_EXE=/usr/local/bin/go-pluginserver" \
-e "KONG_PLUGINS=key-checker" \
-e "KONG_PROXY_LISTEN=0.0.0.0:8000" \
-p 8000:8000 \
kong-demo
how can i resolve it?
I just gave the new test library a try and ran into an issue where a call to kong.Response.Exit
in the plugin can cause errors in the testing library.
$ go test ./... -v -count=1
=== RUN TestPlugin
test.go:573: Access
test.go:573: Access
test.go:573: Access
test.go:240: Can't read method name
test.go:240: Can't read method name
test.go:573: Access
test.go:240: Can't read method name
test.go:573: Access
test.go:240: Can't read method name
--- FAIL: TestPlugin (0.00s)
FAIL
FAIL plugintest 0.005s
FAIL
Occasionally it also produces a panic when running the test repeatedly:
$ go test ./... -v -count=1
=== RUN TestPlugin
test.go:573: Access
test.go:573: Access
test.go:573: Access
test.go:240: Can't read method name
test.go:240: Can't read method name
test.go:573: Access
test.go:240: Can't read method name
test.go:573: Access
test.go:240: Can't read method name
--- FAIL: TestPlugin (0.00s)
panic: Fail in goroutine after TestPlugin has completed
goroutine 50 [running]:
testing.(*common).Fail(0xc000102780)
/usr/lib/golang/src/testing/testing.go:697 +0x125
testing.(*common).Errorf(0xc000102780, 0x88abac, 0x16, 0x0, 0x0, 0x0)
/usr/lib/golang/src/testing/testing.go:803 +0x93
github.com/Kong/go-pdk/test.TestEnv.Errorf(...)
/home/cyrill/tools/golang/pkg/mod/github.com/!kong/[email protected]/test/test.go:240
github.com/Kong/go-pdk/bridge/bridgetest.MockFunc.func1(0x9126f0, 0xc000312080, 0x90a1f8, 0xc00030e000)
/home/cyrill/tools/golang/pkg/mod/github.com/!kong/[email protected]/bridge/bridgetest/bridgetest.go:124 +0x267
created by github.com/Kong/go-pdk/bridge/bridgetest.MockFunc
/home/cyrill/tools/golang/pkg/mod/github.com/!kong/[email protected]/bridge/bridgetest/bridgetest.go:117 +0x65
FAIL plugintest 0.008s
FAIL
Here is a minimal example to reproduce the issue:
// main.go
package main
import (
"net/http"
"github.com/Kong/go-pdk"
"github.com/Kong/go-pdk/server"
)
type Config struct {
}
func New() interface{} {
return &Config{}
}
func (conf Config) Access(kong *pdk.PDK) {
kong.Response.Exit(http.StatusUnauthorized, http.StatusText(http.StatusUnauthorized), nil)
}
func main() {
server.StartServer(New, "v0.0.1", 0)
}
// main_test.go
package main
import (
"testing"
"github.com/Kong/go-pdk/test"
"github.com/stretchr/testify/assert"
)
func TestPlugin(t *testing.T) {
for i := 0; i < 5; i++ {
env, err := test.New(t, test.Request{
Method: "GET",
Url: "http://example.com?q=search&x=9",
})
assert.NoError(t, err)
env.DoHttps(&Config{})
}
}
// go.mod
module plugintest
go 1.16
require (
github.com/Kong/go-pdk v0.7.0-beta1.0.20210526164613-49a95960d27c
github.com/stretchr/testify v1.5.1
)
Am I doing something wrong here? If I reuse the env
and simply call env.DoHttps(&Config{})
within the loop, the error still appears although way less frequently (~1 out of 20 test runs). But in an actual plugin that I'm currently writing I have to create different env
instances per subtest, since I need to test with a bunch of different client headers.
If I use ExitStatus(http.StatusFound)
I get a 500
and
plugin_servers/pb_rpc.lua:45: attempt to index local 'v' (a nil value)
If I use Exit(http.StatusFound, "", nil)
everything is ok.
While inspecting the code, I would guess from the lua error, that the rpc call is missing some values.
IMHO I would just call Exit
from ExitStatus
with empty values for body
and headers
Also setting the headers in Exit
seems not to work - I had to use SetHeader
to create a "working" 302
.
the Lua plugin priority can be set as (see https://docs.konghq.com/2.1.x/plugin-development/custom-logic/) :
CustomHandler.PRIORITY=10
but in go-pdk , i don't find a place to set the priority.
I will be great if we can enable go.mod
for this repo. This surely helps for development of plugin.
Hi
I'm trying to develop go plugin for kong, I'm using go mod for dependency management by default it is using a latest tag from go-pdk which is v0.3.0, but this tag is missing kong.response.Exit.
When a new release of go-pdk will be released?
PS Yes, I know that I can use the git hash.
It seems that the Log
hook is called twice.
Also, the Ctx
data set by previous phases isn't available in the second Log
call.
To test it, I created a counter logic that runs in Access
, Response
& Log
.
Output log:
2021/01/20 08:10:02 [error] 36#0: *35 [kong] init.lua:310 [custom-udp-log] Access[counter]: 0., client: 172.17.0.1, server: kong, request: "GET /greet HTTP/1.1", host: "localhost:8000"
2021/01/20 08:10:02 [error] 36#0: *35 [kong] init.lua:310 [custom-udp-log] Response[counter]: 1. while sending to client, client: 172.17.0.1, server: kong, request: "GET /greet HTTP/1.1", host: "localhost:8000"
2021/01/20 08:10:02 [error] 36#0: *42 [kong] init.lua:310 [custom-udp-log] Log[counter]: 2., context: ngx.timer, client: 172.17.0.1, server: 0.0.0.0:8000
2021/01/20 08:10:03 [error] 36#0: *43 [kong] init.lua:310 [custom-udp-log] Log[counter]: 0., context: ngx.timer, client: 172.17.0.1, server: 0.0.0.0:8000
2021/01/20 08:10:03 [error] 36#0: *35 [kong] init.lua:310 [custom-udp-log] Access[counter]: 0., client: 172.17.0.1, server: kong, request: "GET /greet HTTP/1.1", host: "localhost:8000"
2021/01/20 08:10:03 [error] 36#0: *35 [kong] init.lua:310 [custom-udp-log] Response[counter]: 1. while sending to client, client: 172.17.0.1, server: kong, request: "GET /greet HTTP/1.1", host: "localhost:8000"
2021/01/20 08:10:03 [error] 36#0: *46 [kong] init.lua:310 [custom-udp-log] Log[counter]: 2., context: ngx.timer, client: 172.17.0.1, server: 0.0.0.0:8000
2021/01/20 08:10:03 [error] 36#0: *47 [kong] init.lua:310 [custom-udp-log] Log[counter]: 0., context: ngx.timer, client: 172.17.0.1, server: 0.0.0.0:8000
2021/01/20 08:10:03 [error] 36#0: *35 [kong] init.lua:310 [custom-udp-log] Access[counter]: 0., client: 172.17.0.1, server: kong, request: "GET /greet HTTP/1.1", host: "localhost:8000"
2021/01/20 08:10:03 [error] 36#0: *35 [kong] init.lua:310 [custom-udp-log] Response[counter]: 1. while sending to client, client: 172.17.0.1, server: kong, request: "GET /greet HTTP/1.1", host: "localhost:8000"
2021/01/20 08:10:03 [error] 36#0: *58 [kong] init.lua:310 [custom-udp-log] Log[counter]: 2., context: ngx.timer, client: 172.17.0.1, server: 0.0.0.0:8000
2021/01/20 08:10:03 [error] 36#0: *59 [kong] init.lua:310 [custom-udp-log] Log[counter]: 0., context: ngx.timer, client: 172.17.0.1, server: 0.0.0.0:8000
This is more a question than an issue. Is it possible to use "custom entities" (https://docs.konghq.com/gateway-oss/2.2.x/plugin-development/custom-entities/) and if yes, where can I read more about this?
When I request with a header such as A_SESSION
, I fail to use GetHeader function to extrace A_SESSION
.
I finally successfully get header by key a_session
.
I noticed document said that Header names in are case-insensitive and are normalized to lowercase, and dashes (-) can be written as underscores (_); that is, the header X-Custom-Header can also be retrieved as x_custom_header.
However, it is Inconsistent with the experimental results.
Thanks for such good open source tools.
I've opened a question on Kong forum but as I didn't get any answer I allow myself to ask the question here.
We wrote a custom plugins in Go (an enhance version of the JWT plugin)thanks to this new go-pdk
but we quickly faced performances problems.
In the plugin, we need to load consumers with the LoadConsumer
which basically calls the load_consumer
Lua function.
The documentation of this function says:
Returns the consumer from the datastore (or cache).
But it seems that the cache is not managed by the function actually, so every call will trigger a select in the datastore (in our case Cassandra) which leads to dramatic performances.
We saw that every plugins has to write something like that:
local consumer_cache_key = kong.db.consumers:cache_key(jwt_secret.consumer.id)
local consumer, err = kong.cache:get(consumer_cache_key, nil,
kong.client.load_consumer,
jwt_secret.consumer.id, true)
But I didn't find how to use the cache with the go-pdk
.
So my questions are:
load_consumer_with_cache
).Thanks in advance for your help.
When I was developing a go plugin. How to read cookies?
Wondering what the implications might be using exec.Cmd inside a bespoke plugin to execute another program. In my case, I want to write a plugin which processes XSLT against a legacy XML web service to transform the response body. I was able to do this with a JavaScript plugin, but was able to find an npm module which was easy to use in my code. There doesn't seem to be a comparably simple Go library to do similar (at least not that I could find), but one example I did come across was using Go to call the xlstproc executable (passing the XSLT and XML as file objects) and capture what that produces to stdout.
But I wasn't sure whether trying to do this in the context of a Kong plugin would create issues in the flow of processing an API request, so curious if anyone else has attempted it.
If there is a broken error handling in the plugin, the appropriate nginx process is stuck on shutdown
ps ax| rg nginx
4034477 ? Ss 0:01 nginx: master process /usr/local/openresty/nginx/sbin/nginx -p /usr/local/kong -c nginx.conf
4034739 ? S 0:00 nginx: worker process is shutting down
4042041 ? S 0:00 nginx: worker process is shutting down
4048195 ? S 0:00 nginx: worker process is shutting down
4054000 ? S 0:00 nginx: worker process
4054001 ? S 0:00 nginx: worker process
4054002 ? S 0:00 nginx: worker process
4054003 ? S 0:00 nginx: worker process
4054004 ? S 0:00 nginx: worker process
4054005 ? S 0:00 nginx: worker process
4054006 ? S 0:00 nginx: worker process
4054007 ? S 0:00 nginx: worker process
4060470 pts/3 S+ 0:00 rg nginx
corresponding panic:
kong_1 | 2021/03/08 15:51:19 [info] 135#0: *7568 [go:149] panic: send on closed channel, context: ngx.timer
kong_1 | 2021/03/08 15:51:19 [info] 135#0: *7568 [go:149] goroutine 49 [running]:, context: ngx.timer
kong_1 | 2021/03/08 15:51:19 [info] 135#0: *7568 [go:149] github.com/Kong/go-pdk/bridge.PdkBridge.Ask(...), context: ngx.timer
kong_1 | 2021/03/08 15:51:19 [info] 135#0: *7568 [go:149] /go/pkg/mod/github.com/!kong/[email protected]/bridge/bridge.go:24, context: ngx.timer
kong_1 | 2021/03/08 15:51:19 [info] 135#0: *7568 [go:149] github.com/Kong/go-pdk/bridge.PdkBridge.AskString(0xc000066660, 0x7f9c317e2540, 0x1a, 0xc000184410, 0x1, 0x1, 0xc0001843f0, 0x3, 0x0, 0x0), context: ngx.timer
kong_1 | 2021/03/08 15:51:19 [info] 135#0: *7568 [go:149] /go/pkg/mod/github.com/!kong/[email protected]/bridge/bridge.go:120 +0xda, context: ngx.timer
kong_1 | 2021/03/08 15:51:19 [info] 135#0: *7568 [go:149] github.com/Kong/go-pdk/request.Request.GetQueryArg(...), context: ngx.timer
kong_1 | 2021/03/08 15:51:19 [info] 135#0: *7568 [go:149] /go/pkg/mod/github.com/!kong/[email protected]/request/request.go:132, context: ngx.timer
kong_1 | 2021/03/08 15:51:19 [info] 135#0: *7568 [go:149] bm-auth.Config.Access(0x7f9c317dba96, 0x7, 0x7f9c317ddee0, 0xf, 0x7f9c317e8481, 0x28, 0x7f9c317dc14a, 0x8, 0x0, 0xc00005d0e0), context: ngx.timer
kong_1 | 2021/03/08 15:51:19 [info] 135#0: *7568 [go:149] /go-plugins/bm-authx/auth.go:274 +0xf47, context: ngx.timer
kong_1 | 2021/03/08 15:51:19 [info] 135#0: *7568 [go:149] main.(*PluginServer).HandleEvent.func1(0xc000066660, 0xc00000ec00, 0xc0000146c0, 0xc0000a4050), context: ngx.timer
kong_1 | 2021/03/08 15:51:19 [info] 135#0: *7568 [go:149] /go/pkg/mod/github.com/!kong/[email protected]/event.go:61 +0x65, context: ngx.timer
kong_1 | 2021/03/08 15:51:19 [info] 135#0: *7568 [go:149] created by main.(*PluginServer).HandleEvent, context: ngx.timer
kong_1 | 2021/03/08 15:51:19 [info] 135#0: *7568 [go:149] /go/pkg/mod/github.com/!kong/[email protected]/event.go:59 +0x236, context: ngx.timer
Client.GetPort()
should to return an int (not string
), per the documentation.Client.GetForwardedPort()
should to return an int (not string
), per the documentation.Is there anyway for me to use method Init_Worker() in Go plugins
Lot of Golang project now using golangci-lint
as linter tool, would like to check if this tool can be used.
The current golint
is kind of limited in feature.
Can it be applied to the production environment?
Hello,
We're using kong with custom plugins written in go to handle our authentication logic.
We would like to monitor these plugins by exposing metrics in the prometheus plugin (we already have the prometheus plugin in place).
I noticed that the prometheus plugin now exposes the internal prometheus object. Relevant PR here.
I was wondering if there's any way to access this prometheus object from within golang plugins to create our custom metrics.
Thank you.
In order to reuse an API client, I put it as an unexported field into the Config, like so:
package main
import (
"github.com/Kong/go-pdk/server"
management "github.com/rancher/rancher/pkg/client/generated/management/v3"
)
type Config struct {
rancherClient *management.Client
}
func New() interface{} {
return &Config{}
}
func main() {
server.StartServer(New, "v0.0.1", 0)
}
go run . -dump
Note that the above might crash your computer when run! Be ready to ctrl-c to end the process. For some reason, this particular struct causes the whole memory to fill up pretty quickly. The struct contains lots of fields and nesting levels, but I was unable to reproduce the issue with a more simple struct.
Anyway, a simple fix would be to just ignore unexported fields. My understanding is that unexported fields won't work in the config anyway, since it needs to be Unmarshaled with json.Unmarshal
later. I will post a PR with that fix but let me know if you would take a different approach here.
Go files are not gofmt-ed or goimports-ed
I'm trying to write a bespoke plugin to perform a transformation on the response body, and it looks like the headers that I'm adding in the Response() phase are not actually being sent to the client. In this case, I'm trying to set the Content-Type and X-Kong-Upstream-Status headers with kong.Response.SetHeader().
err = kong.Response.SetHeader("X-Kong-Upstream-Status", strconv.Itoa(respStatus))
...
kong.Response.SetHeader("Content-Type", conf.OutputType)
Right at the end of the Response() phase, I use this to get all the headers (which I assume are those from the upstream and the two I added):
respHeaders, err := kong.Response.GetHeaders(-1)
I put in some debugging code to sanity check what I got back, and everything I expect to see is there:
kong.Log.Debug("Number of response headers: " + strconv.Itoa(len(respHeaders)))
for header, value := range respHeaders {
for i := 0; i < len(value); i++ {
kong.Log.Debug(header + " = " + value[i])
}
}
2022/01/20 21:13:24 [debug] 2067#0: *170 [kong] pb_rpc.lua:228 Number of response headers: 6
2022/01/20 21:13:24 [debug] 2067#0: *170 [kong] pb_rpc.lua:228 connection = keep-alive
2022/01/20 21:13:24 [debug] 2067#0: *170 [kong] pb_rpc.lua:228 vary = Accept-Encoding
2022/01/20 21:13:24 [debug] 2067#0: *170 [kong] pb_rpc.lua:228 x-kong-upstream-status = 200
2022/01/20 21:13:24 [debug] 2067#0: *170 [kong] pb_rpc.lua:228 access-control-allow-origin = *
2022/01/20 21:13:24 [debug] 2067#0: *170 [kong] pb_rpc.lua:228 content-type = text/html; charset=UTF-8
2022/01/20 21:13:24 [debug] 2067#0: *170 [kong] pb_rpc.lua:228 date = Thu, 20 Jan 2022 21:13:23 GMT
I then exit the Response() phase with:
kong.Response.Exit(respStatus, string(newPayloadStr), respHeaders)
However, when I test this with curl, I'm not seeing the headers I've added:
< HTTP/1.1 200 OK
< Connection: keep-alive
< Content-Length: 1583
< X-Kong-Upstream-Latency: 329
< X-Kong-Proxy-Latency: 3
< Via: kong/2.7.0.0-enterprise-edition
When I read the PDK documentation for Response.SetHeader(), it says this:
This function should be used in the header_filter phase, as Kong is preparing headers to be sent back to the client.
However, I'm not able to figure out how you can target that phase base on this. Am I missing something basic?
.
kong_1 | 2020/03/23 04:29:12 failed to open plugin kong-plugins: plugin.Open("/usr/local/share/lua/5.1/kong/plugins/go-so/kong-plugins.so"): Dynamic loading not supported
kong_1 | 2020/03/23 04:29:12 [error] 1#0: init_by_lua error: /usr/local/share/lua/5.1/kong/db/dao/plugins/go.lua:455: bad argument #1 to 'ipairs' (table expected, got nil)
kong_1 | stack traceback:
kong_1 | [C]: in function 'ipairs'
kong_1 | /usr/local/share/lua/5.1/kong/db/dao/plugins/go.lua:455: in function 'get_plugin'
kong_1 | /usr/local/share/lua/5.1/kong/db/dao/plugins/go.lua:481: in function 'load_plugin'
kong_1 | /usr/local/share/lua/5.1/kong/db/dao/plugins.lua:151: in function 'load_plugin_handler'
kong_1 | /usr/local/share/lua/5.1/kong/db/dao/plugins.lua:227: in function 'load_plugin'
kong_1 | /usr/local/share/lua/5.1/kong/db/dao/plugins.lua:275: in function 'load_plugin_schemas'
kong_1 | /usr/local/share/lua/5.1/kong/init.lua:425: in function 'init'
kong_1 | init_by_lua:3: in main chunk
k
Hi~~~
Can we access and modify the response body in Go plugins, for doing something like making a Go version of Response Transformer plugin bundled with Kong?
As Go plugin doesn't support body_filter phase, seems like we can't do it now.
When using kong.Response.ExitStatus(400) I get the following message in log:
signal 17 (SIGCHLD) received from 5558
[notice] 5503#0: *7 [kong] go.lua:95 go-pluginserver terminated: exit 2, context: ngx.timer
[notice] 5503#0: *7 [kong] go.lua:84 Starting go-pluginserver, context: ngx.timer
The call to kong.Response.ExitStatus() is made in Access phase, and if commented out everything work well.
May be the go-pluginserver restart is intended, but then it should be better explained in documention :-). To exit without this problem use ExitStatus func.
lua plugin at body_filter
phase:
local function status()
local s = kong.response.get_status()
kong.ctx.shared.status = s
end
go plugin at log
phase:
func (conf Config) Log(kong *pdk.PDK) {
status, err := kong.Ctx.GetSharedInt("status")
if err!= nil {
kong.Log.Err(err.Error())
}
....
}
got error : null response
Hello ~~~
kong.Response.GetHeader can not work in access phase, and go-pdk do not support header_filter and body_filter phase. so, how can i get the response header?
I want to make a POST request to a plugin whose body size exceeds the default body size (http://nginx.org/en/docs/http/ngx_http_core_module.html#client_body_buffer_size) of nginx.
kong.Request.GetRawBody()
return an empty body if it is buffered, e.g.:
a client request body is buffered to a temporary file /usr/local/kong/client_body_temp/0000000001
If I increase the body size of nginx/kong
KONG_NGINX_PROXY_CLIENT_BODY_BUFFER_SIZE: 32k
I get the body via kong.Request.GetRawBody()
MY GO Plugin is
package main
import (
"fmt"
pdk "github.com/Kong/go-pdk"
"github.com/Kong/go-pdk/server"
)
type Config struct {
AppId string `json:"api_id"`
ApiSecret string `json:"api_secret"`
Discovery string `json:"discovery"`
TrasferClaimsToHeader []string `json:"trasfer_claims_to_header"`
RequiredRoles []string `json:"required_roles"`
SslVerify string `json:"ssl_verify"`
}
var Version = "1.1"
var Priority = 1000
func main() {
server.StartServer(New, Version, Priority)
}
func New() interface{} {
return &Config{}
}
func (c Config) Access(kong *pdk.PDK) {
fmt.Println("Access------------")
if true {
kong.Response.Exit(http.StatusUnauthorized,"unauthorized !", nil)
return
}
}
func (conf Config) Preread(kong *pdk.PDK) {
fmt.Println("Preread------------")
}
func (conf Config) Response(kong *pdk.PDK) {
fmt.Println("Response------------")
}
func (conf Config) Rewrite(kong *pdk.PDK) {
fmt.Println("Rewrite------------")
}
func (conf Config) Certificate(kong *pdk.PDK) {
fmt.Println("Certificate------------")
}
func (conf Config) Log(kong *pdk.PDK) {
fmt.Println("Log------------")
}
When I'm ready to deploy Kong 2.7, and run it log:
2021/12/31 18:44:00 [notice] 1108#0: *516 [lua] init.lua:260: purge(): [DB cache] purging (local) cache, client: 127.0.0.1, server: kong_admin, request: "POST /config?check_hash=1 HTTP/1.1", host: "127.0.0.1:8001"
2021/12/31 18:44:00 [notice] 1108#0: *516 [lua] init.lua:260: purge(): [DB cache] purging (local) cache, client: 127.0.0.1, server: kong_admin, request: "POST /config?check_hash=1 HTTP/1.1", host: "127.0.0.1:8001"
2021/12/31 18:44:00 [info] 1108#0: *9 [oidc-token:1112] Access------------, context: ngx.timer
31/Dec/2021:18:44:00 +0800 [401] [0.058] [gw.meda.test] "GET /api/demo?id=0007 HTTP/1.1"
2021/12/31 18:44:00 [info] 1108#0: *9 [oidc-token:1112] Log------------, context: ngx.timer
2021/12/31 18:44:00 [info] 1108#0: *527 client 10.244.0.0 closed keepalive connection
2021/12/31 18:44:00 [info] 1108#0: *516 client 127.0.0.1 closed keepalive connection
Im trying to write a config schema which looks like this
type Config struct {
ApiEndPoint string
AuthModules []Module
}
type Module struct {
Name string
Routes []string
}
and trying to load the configuration from a declarative config file.
config:
apiendpoint: "http://localhost:5050/api/v1/permission/validate"
authmodules:
-
name: application_mgmt
routes:
- /api/v1/random
This configuration is resulting in an error
docker-compose up ๎ฒ โ ๎ฒ 17:19:32
Recreating plugin_kong-demo_1 ... done
Attaching to plugin_kong-demo_1
kong-demo_1 | 2020/03/23 16:19:35 [error] 1#0: init_by_lua error: /usr/local/share/lua/5.1/kong/init.lua:431: error parsing declarative config file /home/kong/config.yml:
kong-demo_1 | in 'services':
kong-demo_1 | - in entry 1 of 'services':
kong-demo_1 | in 'plugins':
kong-demo_1 | - in entry 1 of 'plugins':
kong-demo_1 | in 'config':
kong-demo_1 | in 'authmodules': unknown field
I made sure the yaml is valid so there's no issue there. I'm able to parse the other fields though.
Can anyone help me explain what am I doing wrong here or if it is a bug in the go-pdk itself?
At this point I'm stuck and any help would be appreciated. Thanks
Is it possible to use tracing (OpenTracing, OpenTelemetry or OpenCensus) inside the go plugin?
We've been using kong.Ctx
to pass information between the different phases, because some of the information we want to use exists in the Access
phase, some in Report
phase, and we want to use it in the Log
phase.
However, after upgrading to v0.7.1
(which includes the move to protobuf) it stopped working.
From my debugging, it seems like no data is passed.
This is plan to use golang to replace lua write plugin?
Hello there!
In my plugin.go, can I use the init()
method? such as:
var cache Cache
func init() {
cache = doSomething()
go timedCache()
}
func timedCache() {
for {
select {
case: <- time.After(...):
cache = doSomething()
}
}
}
func (conf Config) Access(...) {
...
}
Thank you!
Ive noticed that the session plugin uses kong.db
for storage yet this does not seem to be supported in Golang. Is this supported or is there another mechanism?
Context: we are migrating user credentials out of a monolith so during the migration period, we would like to support both session types and hence might need to write our custom plugin for that.
Trying the new test library and getting an error trying to set a header
go test ./... -v
=== RUN TestPlugin
test.go:571: Access
panic: assignment to entry in nil map
goroutine 19 [running]:
net/textproto.MIMEHeader.Set(...)
/usr/local/Cellar/go/1.16.4/libexec/src/net/textproto/header.go:22
net/http.Header.Set(...)
/usr/local/Cellar/go/1.16.4/libexec/src/net/http/header.go:37
github.com/Kong/go-pdk/test.(*TestEnv).Handle(0xc0000f6000, 0xc0000b00d8, 0x18, 0xc00020c1c0, 0xc, 0xc, 0x0, 0x2b2d37, 0x1792440)
[redacted]/vendor/github.com/Kong/go-pdk/test/test.go:409 +0x209a
github.com/Kong/go-pdk/bridge/bridgetest.MockFunc.func1(0x1529910, 0xc0000da180, 0x15212f8, 0xc0000f6000)
[redacted]/vendor/github.com/Kong/go-pdk/bridge/bridgetest/bridgetest.go:132 +0xea
created by github.com/Kong/go-pdk/bridge/bridgetest.MockFunc
[redacted]/vendor/github.com/Kong/go-pdk/bridge/bridgetest/bridgetest.go:117 +0x65
FAIL plugintest 0.168s
FAIL
here is the code
// main.go
package main
import (
"log"
"github.com/Kong/go-pdk"
"github.com/Kong/go-pdk/server"
)
func main() {
server.StartServer(New, Version, Priority)
}
var Version = "0.0.1"
var Priority = 1
type Config struct{}
func New() interface{} {
return &Config{}
}
func (conf Config) Access(kong *pdk.PDK) {
err := kong.Response.SetHeader("foo", "bar")
if err != nil {
log.Printf("Error getting setting header: %s", err.Error())
}
}
// main_test.go
package main
import (
"testing"
"github.com/Kong/go-pdk/test"
"github.com/stretchr/testify/assert"
)
func TestPlugin(t *testing.T) {
env, err := test.New(t, test.Request{
Method: "GET",
Url: "http://example.com?q=search&x=9",
})
if assert.NoError(t, err) {
env.DoHttps(&Config{})
assert.Equal(t, 200, env.ClientRes.Status)
assert.Equal(t, "bar", env.ClientRes.Headers.Get("foo"))
}
}
// go.mod
module plugintest
go 1.16
require (
github.com/Kong/go-pdk v0.7.0-beta1.0.20210526164613-49a95960d27c
github.com/stretchr/testify v1.5.1
)
A change was introduced in the pdk.Init interface and the go-pluginserver fails to be built:
#18 35.78 # github.com/Kong/go-pluginserver
#18 35.78 src/github.com/Kong/go-pluginserver/event.go:49:21: cannot use ipc (type chan interface {}) as type net.Conn in argument to pdk.Init:
#18 35.78 chan interface {} does not implement net.Conn (missing Close method)
------
executor failed running [/bin/sh -c go get github.com/Kong/go-pluginserver]: exit code: 2
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.