+
+
\ No newline at end of file
diff --git a/kong-versions/3.9.0.0/kong/spec/fixtures/error_templates/error_template.json b/kong-versions/3.9.0.0/kong/spec/fixtures/error_templates/error_template.json
new file mode 100644
index 00000000..e9c4c30c
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/fixtures/error_templates/error_template.json
@@ -0,0 +1,4 @@
+{
+ "custom_template_message":"%s",
+ "request_id":"%s"
+}
\ No newline at end of file
diff --git a/kong-versions/3.9.0.0/kong/spec/fixtures/error_templates/error_template.plain b/kong-versions/3.9.0.0/kong/spec/fixtures/error_templates/error_template.plain
new file mode 100644
index 00000000..fcf08c89
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/fixtures/error_templates/error_template.plain
@@ -0,0 +1,2 @@
+custom plain template: %s\n
+request_id: %s\n
\ No newline at end of file
diff --git a/kong-versions/3.9.0.0/kong/spec/fixtures/error_templates/error_template.xml b/kong-versions/3.9.0.0/kong/spec/fixtures/error_templates/error_template.xml
new file mode 100644
index 00000000..c5039f20
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/fixtures/error_templates/error_template.xml
@@ -0,0 +1,6 @@
+
+
+ custom template
+ %s
+ %s
+
\ No newline at end of file
diff --git a/kong-versions/3.9.0.0/kong/spec/fixtures/external_plugins/go/go-hello.go b/kong-versions/3.9.0.0/kong/spec/fixtures/external_plugins/go/go-hello.go
new file mode 100644
index 00000000..f55099a1
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/fixtures/external_plugins/go/go-hello.go
@@ -0,0 +1,79 @@
+/*
+A "hello world" plugin in Go,
+which reads a request header and sets a response header.
+*/
+package main
+
+import (
+ "fmt"
+ "github.com/Kong/go-pdk"
+ "github.com/Kong/go-pdk/server"
+)
+
+type Config struct {
+ Message string
+}
+
+func New() interface{} {
+ return &Config{}
+}
+
+func main() {
+ server.StartServer(New, "0.1", 1)
+}
+
+func (conf Config) Access(kong *pdk.PDK) {
+ host, err := kong.Request.GetHeader("host")
+ if err != nil {
+ kong.Log.Err(err.Error())
+ }
+ message := conf.Message
+ if message == "" {
+ message = "hello"
+ }
+ kong.Response.SetHeader("x-hello-from-go", fmt.Sprintf("Go says %s to %s", message, host))
+ kong.Ctx.SetShared("shared_msg", message)
+}
+
+func (conf Config) Log(kong *pdk.PDK) {
+ access_start, err := kong.Nginx.GetCtxFloat("KONG_ACCESS_START")
+ if err != nil {
+ kong.Log.Err(err.Error())
+ }
+ kong.Log.Debug("access_start: ", access_start)
+
+ header_value, err := kong.Request.GetHeader("X-Loose-Data")
+ if err != nil {
+ kong.Log.Err(err.Error())
+ }
+ kong.Log.Debug("request_header: ", header_value)
+
+ header_value, err = kong.Response.GetHeader("X-Powered-By")
+ if err != nil {
+ kong.Log.Err(err.Error())
+ }
+ kong.Log.Debug("response_header: ", header_value)
+
+ shared_msg, err := kong.Ctx.GetSharedString("shared_msg")
+ if err != nil {
+ kong.Log.Err(err.Error())
+ }
+
+ kong.Log.Debug("shared_msg: ", shared_msg)
+
+ serialized, err := kong.Log.Serialize()
+ if err != nil {
+ kong.Log.Err(err.Error())
+ }
+
+ kong.Log.Debug("serialized:", serialized)
+}
+
+func (conf Config) Response(kong *pdk.PDK) {
+ srvr, err := kong.ServiceResponse.GetHeader("Server")
+ if err != nil {
+ kong.Log.Err(err.Error())
+ }
+
+ kong.Response.SetHeader("x-hello-from-go-at-response", fmt.Sprintf("got from server '%s'", srvr))
+}
diff --git a/kong-versions/3.9.0.0/kong/spec/fixtures/external_plugins/go/go.mod b/kong-versions/3.9.0.0/kong/spec/fixtures/external_plugins/go/go.mod
new file mode 100644
index 00000000..def3ac47
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/fixtures/external_plugins/go/go.mod
@@ -0,0 +1,5 @@
+module go-plugins
+
+go 1.13
+
+require github.com/Kong/go-pdk v0.7.1
diff --git a/kong-versions/3.9.0.0/kong/spec/fixtures/external_plugins/go/go.sum b/kong-versions/3.9.0.0/kong/spec/fixtures/external_plugins/go/go.sum
new file mode 100644
index 00000000..382f9ec5
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/fixtures/external_plugins/go/go.sum
@@ -0,0 +1,84 @@
+cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
+github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
+github.com/Kong/go-pdk v0.7.1 h1:DWpmvuafH/35xws0VsXPyiGVtQmUuICnok9Hqolgdgg=
+github.com/Kong/go-pdk v0.7.1/go.mod h1:48+yltNveiFYTo6/I1AnmGn3m8goSQbtkfamH1zkwhw=
+github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
+github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
+github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
+github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
+github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
+github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
+github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
+github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
+github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
+github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
+github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
+github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
+github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
+github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
+github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
+github.com/golang/protobuf v1.4.3 h1:JjCZWpVbqXDqFVmTfYWEVTMIYrL/NPdPSCHPJ0T/raM=
+github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
+github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
+github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
+github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
+github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.5.0 h1:/QaMHBdZ26BB3SSst0Iwl10Epc+xhTquomWX0oZEB6w=
+github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
+github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
+github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
+github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
+github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4=
+github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
+github.com/ugorji/go v1.2.1 h1:dz+JxTe7GZQdErTo7SREc1jQj/hFP1k7jyIAwODoW+k=
+github.com/ugorji/go v1.2.1/go.mod h1:cSVypSfTLm2o9fKxXvQgn3rMmkPXovcWor6Qn5tbFmI=
+github.com/ugorji/go/codec v1.2.1 h1:/TRfW3XKkvWvmAYyCUaQlhoCDGjcvNR8xVVA/l5p/jQ=
+github.com/ugorji/go/codec v1.2.1/go.mod h1:s/WxCRi46t8rA+fowL40EnmD7ec0XhR7ZypxeBNdzsM=
+golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
+golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
+golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
+golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
+golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
+golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
+golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
+golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
+golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
+golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
+golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
+golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
+golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
+google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
+google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
+google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
+google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
+google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
+google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
+google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
+google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
+google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
+google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
+google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
+google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
+google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
+google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
+google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
+google.golang.org/protobuf v1.25.0 h1:Ejskq+SyPohKW+1uil0JJMtmHCgJPJ/qWTxr8qp+R4c=
+google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
+gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
+gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
+gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
+honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
diff --git a/kong-versions/3.9.0.0/kong/spec/fixtures/external_plugins/js/js-hello.js b/kong-versions/3.9.0.0/kong/spec/fixtures/external_plugins/js/js-hello.js
new file mode 100644
index 00000000..b1141644
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/fixtures/external_plugins/js/js-hello.js
@@ -0,0 +1,33 @@
+'use strict';
+
+// This is an example plugin that add a header to the response
+
+class KongPlugin {
+ constructor(config) {
+ this.config = config
+ }
+
+ async access(kong) {
+ let host = await kong.request.getHeader("host")
+ if (host === undefined) {
+ return await kong.log.err("unable to get header for request")
+ }
+
+ let message = this.config.message || "hello"
+
+ // the following can be "parallel"ed
+ await Promise.all([
+ kong.response.setHeader("x-hello-from-javascript", "Javascript says " + message + " to " + host),
+ kong.response.setHeader("x-javascript-pid", process.pid),
+ ])
+ }
+}
+
+module.exports = {
+ Plugin: KongPlugin,
+ Schema: [
+ { message: { type: "string" } },
+ ],
+ Version: '0.1.0',
+ Priority: 0,
+}
\ No newline at end of file
diff --git a/kong-versions/3.9.0.0/kong/spec/fixtures/external_plugins/py/py-hello.py b/kong-versions/3.9.0.0/kong/spec/fixtures/external_plugins/py/py-hello.py
new file mode 100755
index 00000000..3301e059
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/fixtures/external_plugins/py/py-hello.py
@@ -0,0 +1,37 @@
+#!/usr/bin/env python3
+import os
+import kong_pdk.pdk.kong as kong
+
+Schema = (
+ {"message": {"type": "string"}},
+)
+
+version = '0.1.0'
+priority = 100
+
+# This is an example plugin that add a header to the response
+
+class Plugin(object):
+ def __init__(self, config):
+ self.config = config
+
+ def access(self, kong: kong.kong):
+ host, err = kong.request.get_header("host")
+ if err:
+ pass # error handling
+ # if run with --no-lua-style
+ # try:
+ # host = kong.request.get_header("host")
+ # except Exception as ex:
+ # pass # error handling
+ message = "hello"
+ if 'message' in self.config:
+ message = self.config['message']
+ kong.response.set_header("x-hello-from-python", "Python says %s to %s" % (message, host))
+ kong.response.set_header("x-python-pid", str(os.getpid()))
+
+
+# add below section to allow this plugin optionally be running in a dedicated process
+if __name__ == "__main__":
+ from kong_pdk.cli import start_dedicated_server
+ start_dedicated_server("py-hello", Plugin, version, priority, Schema)
diff --git a/kong-versions/3.9.0.0/kong/spec/fixtures/external_plugins/py/requirements.txt b/kong-versions/3.9.0.0/kong/spec/fixtures/external_plugins/py/requirements.txt
new file mode 100644
index 00000000..0f887887
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/fixtures/external_plugins/py/requirements.txt
@@ -0,0 +1 @@
+kong-pdk
diff --git a/kong-versions/3.9.0.0/kong/spec/fixtures/factories/plugins.lua b/kong-versions/3.9.0.0/kong/spec/fixtures/factories/plugins.lua
new file mode 100644
index 00000000..3e6fecf0
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/fixtures/factories/plugins.lua
@@ -0,0 +1,161 @@
+-- This software is copyright Kong Inc. and its licensors.
+-- Use of the software is subject to the agreement between your organization
+-- and Kong Inc. If there is no such agreement, use is governed by and
+-- subject to the terms of the Kong Master Software License Agreement found
+-- at https://konghq.com/enterprisesoftwarelicense/.
+-- [ END OF LICENSE 0867164ffc95e54f04670b5169c09574bdbd9bba ]
+
+local helpers = require "spec.helpers"
+
+local EntitiesFactory = {}
+
+function EntitiesFactory:setup(strategy)
+ local bp, _ = helpers.get_db_utils(strategy,
+ { "plugins",
+ "routes",
+ "services",
+ "consumers", },
+ { "key-auth", "request-transformer" })
+
+
+ local alice = assert(bp.consumers:insert {
+ custom_id = "alice"
+ })
+
+ local bob = assert(bp.consumers:insert {
+ username = "bob",
+ })
+
+ local eve = assert(bp.consumers:insert{
+ username = "eve"
+ })
+
+ assert(bp.keyauth_credentials:insert {
+ key = "bob",
+ consumer = { id = bob.id },
+ })
+ assert(bp.keyauth_credentials:insert {
+ key = "alice",
+ consumer = { id = alice.id },
+ })
+ assert(bp.keyauth_credentials:insert {
+ key = "eve",
+ consumer = { id = eve.id },
+ })
+
+ local service = assert(bp.services:insert {
+ path = "/anything",
+ })
+
+ local route = assert(bp.routes:insert {
+ service = { id = service.id },
+ hosts = { "route.test" },
+ })
+ assert(bp.key_auth_plugins:insert())
+
+ self.bp = bp
+ self.alice_id = alice.id
+ self.bob_id = bob.id
+ self.eve_id = eve.id
+ self.route_id = route.id
+ self.service_id = service.id
+ return self
+end
+
+local PluginFactory = {}
+function PluginFactory:setup(ef)
+ self.bp = ef.bp
+ self.bob_id = ef.bob_id
+ self.alice_id = ef.alice_id
+ self.eve_id = ef.eve_id
+ self.route_id = ef.route_id
+ self.service_id = ef.service_id
+ return self
+end
+
+function PluginFactory:produce(header_name, plugin_scopes)
+ local plugin_cfg = {
+ name = "request-transformer",
+ config = {
+ add = {
+ headers = { ("%s:true"):format(header_name) }
+ }
+ }
+ }
+ for k, v in pairs(plugin_scopes) do
+ plugin_cfg[k] = v
+ end
+ return assert(self.bp.plugins:insert(plugin_cfg))
+end
+
+function PluginFactory:consumer_route_service()
+ local header_name = "x-consumer-and-service-and-route"
+ self:produce(header_name, {
+ consumer = { id = self.alice_id },
+ service = { id = self.service_id },
+ route = { id = self.route_id },
+ })
+ return header_name
+end
+
+function PluginFactory:consumer_route()
+ local header_name = "x-consumer-and-route"
+ self:produce(header_name, {
+ consumer = { id = self.alice_id },
+ route = { id = self.route_id },
+ })
+ return header_name
+end
+
+function PluginFactory:consumer_service()
+ local header_name = "x-consumer-and-service"
+ self:produce(header_name, {
+ consumer = { id = self.alice_id },
+ service = { id = self.service_id },
+ })
+ return header_name
+end
+
+function PluginFactory:route_service()
+ local header_name = "x-route-and-service"
+ self:produce(header_name, {
+ route = { id = self.route_id },
+ service = { id = self.service_id },
+ })
+ return header_name
+end
+
+function PluginFactory:consumer()
+ local header_name = "x-consumer"
+ self:produce(header_name, {
+ consumer = { id = self.alice_id }
+ })
+ return header_name
+end
+
+function PluginFactory:route()
+ local header_name = "x-route"
+ self:produce(header_name, {
+ route = { id = self.route_id }
+ })
+ return header_name
+end
+
+function PluginFactory:service()
+ local header_name = "x-service"
+ self:produce(header_name, {
+ service = { id = self.service_id }
+ })
+ return header_name
+end
+
+function PluginFactory:global()
+ local header_name = "x-global"
+ self:produce(header_name, {})
+ return header_name
+end
+
+return {
+ PluginFactory = PluginFactory,
+ EntitiesFactory = EntitiesFactory
+}
diff --git a/kong-versions/3.9.0.0/kong/spec/fixtures/forward-proxy-server.lua b/kong-versions/3.9.0.0/kong/spec/fixtures/forward-proxy-server.lua
new file mode 100644
index 00000000..ddedf576
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/fixtures/forward-proxy-server.lua
@@ -0,0 +1,153 @@
+-- This software is copyright Kong Inc. and its licensors.
+-- Use of the software is subject to the agreement between your organization
+-- and Kong Inc. If there is no such agreement, use is governed by and
+-- subject to the terms of the Kong Master Software License Agreement found
+-- at https://konghq.com/enterprisesoftwarelicense/.
+-- [ END OF LICENSE 0867164ffc95e54f04670b5169c09574bdbd9bba ]
+
+local _M = {}
+
+local split = require("kong.tools.string").split
+
+local header_mt = {
+ __index = function(self, name)
+ name = name:lower():gsub("_", "-")
+ return rawget(self, name)
+ end,
+
+ __newindex = function(self, name, value)
+ name = name:lower():gsub("_", "-")
+ rawset(self, name, value)
+ end,
+}
+
+local function new_headers()
+ return setmetatable({}, header_mt)
+end
+
+-- This is a very naive forward proxy, which accepts a CONNECT over HTTP, and
+-- then starts tunnelling the bytes blind (for end-to-end SSL).
+function _M.connect(opts)
+ local req_sock = ngx.req.socket(true)
+ req_sock:settimeouts(1000, 1000, 1000)
+
+ -- receive request line
+ local req_line = req_sock:receive()
+ ngx.log(ngx.DEBUG, "request line: ", req_line)
+
+ local method, host_port = unpack(split(req_line, " "))
+ if method ~= "CONNECT" then
+ return ngx.exit(400)
+ end
+
+ local upstream_host, upstream_port = unpack(split(host_port, ":"))
+
+ local headers = new_headers()
+
+ -- receive headers
+ repeat
+ local line = req_sock:receive("*l")
+ local name, value = line:match("^([^:]+):%s*(.+)$")
+ if name and value then
+ ngx.log(ngx.DEBUG, "header: ", name, " => ", value)
+ headers[name] = value
+ end
+ until ngx.re.find(line, "^\\s*$", "jo")
+
+
+ local basic_auth = opts and opts.basic_auth
+ if basic_auth then
+ ngx.log(ngx.DEBUG, "checking proxy-authorization...")
+
+ local found = headers["proxy-authorization"]
+ if not found then
+ ngx.log(ngx.NOTICE, "client did not send proxy-authorization header")
+ ngx.print("HTTP/1.1 401 Unauthorized\r\n\r\n")
+ return ngx.exit(ngx.OK)
+ end
+
+ local auth = ngx.re.gsub(found, [[^Basic\s*]], "", "oji")
+
+ if auth ~= basic_auth then
+ ngx.log(ngx.NOTICE, "client sent incorrect proxy-authorization")
+ ngx.print("HTTP/1.1 403 Forbidden\r\n\r\n")
+ return ngx.exit(ngx.OK)
+ end
+
+ ngx.log(ngx.DEBUG, "accepted basic proxy-authorization")
+ end
+
+
+ -- Connect to requested upstream
+ local upstream_sock = ngx.socket.tcp()
+ upstream_sock:settimeouts(1000, 1000, 1000)
+ local ok, err = upstream_sock:connect(upstream_host, upstream_port)
+ if not ok then
+ ngx.log(ngx.ERR, "connect to upstream ", upstream_host, ":", upstream_port,
+ " failed: ", err)
+ return ngx.exit(504)
+ end
+
+ -- Tell the client we are good to go
+ ngx.print("HTTP/1.1 200 OK\r\n\r\n")
+ ngx.flush()
+
+ ngx.log(ngx.DEBUG, "tunneling started")
+
+ -- 10Kb in either direction should be plenty
+ local max_bytes = 10 * 1024
+
+ local should_exit = false
+
+ local upload = ngx.thread.spawn(function()
+ while not should_exit do
+ local req_data, err = req_sock:receiveany(max_bytes)
+ if req_data then
+ ngx.log(ngx.DEBUG, "client RCV ", #req_data, " bytes")
+
+ local bytes, err = upstream_sock:send(req_data)
+ if bytes then
+ ngx.log(ngx.DEBUG, "upstream SND ", bytes, " bytes")
+ elseif err then
+ ngx.log(ngx.ERR, "upstream SND failed: ", err)
+ break
+ end
+ elseif err ~= "timeout" then
+ ngx.log(ngx.ERR, "client RCV failed: ", err)
+ break
+ end
+ end
+ should_exit = true
+ end)
+
+ local download = ngx.thread.spawn(function()
+ while not should_exit do
+ local res_data, err = upstream_sock:receiveany(max_bytes)
+ if res_data then
+ ngx.log(ngx.DEBUG, "upstream RCV ", #res_data, " bytes")
+
+ local bytes, err = req_sock:send(res_data)
+ if bytes then
+ ngx.log(ngx.DEBUG, "client SND: ", bytes, " bytes")
+ elseif err then
+ ngx.log(ngx.ERR, "client SND failed: ", err)
+ break
+ end
+ elseif err ~= "timeout" then
+ ngx.log(ngx.ERR, "upstream RCV failed: ", err)
+ break
+ end
+ end
+ should_exit = true
+ end)
+
+ ngx.thread.wait(upload, download)
+ ngx.thread.kill(upload)
+ ngx.thread.kill(download)
+
+ upstream_sock:close()
+
+ ngx.log(ngx.DEBUG, "tunneling ended")
+end
+
+return _M
diff --git a/kong-versions/3.9.0.0/kong/spec/fixtures/forward-proxy/mtls_certs/ca.crt b/kong-versions/3.9.0.0/kong/spec/fixtures/forward-proxy/mtls_certs/ca.crt
new file mode 100644
index 00000000..6b5555eb
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/fixtures/forward-proxy/mtls_certs/ca.crt
@@ -0,0 +1,33 @@
+-----BEGIN CERTIFICATE-----
+MIIFoTCCA4mgAwIBAgIUQDBLwIychoRbVRO44IzBBk9R4oYwDQYJKoZIhvcNAQEL
+BQAwWDELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExFTATBgNVBAoM
+DEtvbmcgVGVzdGluZzEdMBsGA1UEAwwUS29uZyBUZXN0aW5nIFJvb3QgQ0EwHhcN
+MTkwNTAyMTkzNDQyWhcNMzkwNDI3MTkzNDQyWjBYMQswCQYDVQQGEwJVUzETMBEG
+A1UECAwKQ2FsaWZvcm5pYTEVMBMGA1UECgwMS29uZyBUZXN0aW5nMR0wGwYDVQQD
+DBRLb25nIFRlc3RpbmcgUm9vdCBDQTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCC
+AgoCggIBAMp6IggUp3aSNRbLAac8oOkrbUnFuxtlKGYgg8vfA2UU71qTktigdwO6
+Kod0/M+daO3RDqJJXQL2rD14NDO3MaextICanoQSEe+nYyMFUIk+QplXLD3fbshU
+nHoJcMS2w0x4cm1os4ebxR2Evndo6luz39ivcjau+BL+9iBAYL1g6+eGOjcSy7ft
+1nAMvbxcQ7dmbAH2KP6OmF8cok+eQWVqXEjqtVx5GDMDlj1BjX6Kulmh/vhNi3Hr
+NEi+kPrw/YtRgnqnN0sv3NnAyKnantxy7w0TDicFjiBsSIhjB5aUfWYErBR+Nj/m
+uumwc/kRJcHWklqDzxrZKCIyOyWcE5Dyjjr46cnF8HxhYwgZcwkmgTtaXOLpBMlo
+XUTgOQrWpm9HYg2vOJMMA/ZPUJ2tJ34/4RgiA00EJ5xG8r24suZmT775l+XFLFzp
+Ihxvs3BMbrWsXlcZkI5neNk7Q/1jLoBhWeTYjMpUS7bJ/49YVGQZFs3xu2IcLqeD
+5WsB1i+EqBAI0jm4vWEynsyX+kS2BqAiDtCsS6WYT2q00DTeP5eIHh/vHsm75jJ+
+yUEb1xFxGnNevLKNTcHUeXxPUnowdC6wqFnaJm7l09qVGDom7tLX9i6MCojgpAP0
+hMpBxzh8jLxHh+zZQdiORSFdYxNnlnWwbic2GUJruiQVLuhpseenAgMBAAGjYzBh
+MB0GA1UdDgQWBBQHT/IIheEC2kdBxI/TfGqUxWJw9zAfBgNVHSMEGDAWgBQHT/II
+heEC2kdBxI/TfGqUxWJw9zAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIB
+hjANBgkqhkiG9w0BAQsFAAOCAgEAqXZjy4EltJCRtBmN0ohAHPWqH4ZJQCI2HrM3
+wHB6c4oPWcJ+M2PfmYPUJo9VMjvn4S3sZuAysyoHduvRdGDnElW4wglL1xxpoUOx
+FqoZUoYWV8hDFmUTWM5b4CtJxOPdTAd8VgypulM3iUEzBQrjR6tnMOdkiFMOmVag
+0/Nnr+Tcfk/crMCx3xsVnisYjJoQBFBH4UY+gWE/V/MS1Sya4/qTbuuCUq+Qym5P
+r8TkWAJlg7iVVLbZ2j94VUdpiQPWJEGMtJck/NEmOTruhhQlT7c1u/lqXCGj7uci
+LmhLsBVmdtWT9AWS8Rl7Qo5GXbjxKIaP3IM9axhDLm8WHwPRLx7DuIFEc+OBxJhz
+wkr0g0yLS0AMZpaC6UGbWX01ed10U01mQ/qPU5uZiB0GvruwsYWZsyL1QXUeqLz3
+/KKrx3XsXjtBu3ZG4LAnwuxfeZCNw9ofg8CqF9c20ko+7tZAv6DCu9UL+2oZnEyQ
+CboRDwpnAlQ7qJVSp2xMgunO3xxVMlhD5LZpEJz1lRT0nQV3uuLpMYNM4FS9OW/X
+MZSzwHhDdCTDWtc/iRszimOnYYV8Y0ubJcb59uhwcsHmdfnwL9DVO6X5xyzb8wsf
+wWaPbub8SN2jKnT0g6ZWuca4VwEo1fRaBkzSZDqXwhkBDWP8UBqLXMXWHdZaT8NK
+0NEO74c=
+-----END CERTIFICATE-----
diff --git a/kong-versions/3.9.0.0/kong/spec/fixtures/forward-proxy/mtls_certs/ca.key b/kong-versions/3.9.0.0/kong/spec/fixtures/forward-proxy/mtls_certs/ca.key
new file mode 100644
index 00000000..22f7391c
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/fixtures/forward-proxy/mtls_certs/ca.key
@@ -0,0 +1,51 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIJKAIBAAKCAgEAynoiCBSndpI1FssBpzyg6SttScW7G2UoZiCDy98DZRTvWpOS
+2KB3A7oqh3T8z51o7dEOokldAvasPXg0M7cxp7G0gJqehBIR76djIwVQiT5CmVcs
+Pd9uyFSceglwxLbDTHhybWizh5vFHYS+d2jqW7Pf2K9yNq74Ev72IEBgvWDr54Y6
+NxLLt+3WcAy9vFxDt2ZsAfYo/o6YXxyiT55BZWpcSOq1XHkYMwOWPUGNfoq6WaH+
++E2Lces0SL6Q+vD9i1GCeqc3Sy/c2cDIqdqe3HLvDRMOJwWOIGxIiGMHlpR9ZgSs
+FH42P+a66bBz+RElwdaSWoPPGtkoIjI7JZwTkPKOOvjpycXwfGFjCBlzCSaBO1pc
+4ukEyWhdROA5Ctamb0diDa84kwwD9k9Qna0nfj/hGCIDTQQnnEbyvbiy5mZPvvmX
+5cUsXOkiHG+zcExutaxeVxmQjmd42TtD/WMugGFZ5NiMylRLtsn/j1hUZBkWzfG7
+Yhwup4PlawHWL4SoEAjSObi9YTKezJf6RLYGoCIO0KxLpZhParTQNN4/l4geH+8e
+ybvmMn7JQRvXEXEac168so1NwdR5fE9SejB0LrCoWdombuXT2pUYOibu0tf2LowK
+iOCkA/SEykHHOHyMvEeH7NlB2I5FIV1jE2eWdbBuJzYZQmu6JBUu6Gmx56cCAwEA
+AQKCAgBh8MQHbp42r7B4bwhEsgIP5868kaXZMYxiIjY+ZojI22CQSrQMj0oihmnO
+Dhu//Z9k8ewHOj+AkHtuXHe70FB3knECiEhHEEqWxzwgE5EKYhBrBgzDfRGkW7E5
+ItnmfZVopxaKr8uvu/yUM8LCFgDPDOopcWxo4SfkYGoD3cAtuvVBj98XBsN+G9DP
+cIpS07p5u1RheoYH5Ef2Me6dXqq5eMJdDxNdQMIg4wpIZS4hWM+dTcv8pd3e4+vt
+iCivCeVK/8mCtOH9P5Cv0B4Ac1zGu93AUEhXPcurCVXoiyZ/gyJJN9dZLlflfyFI
+qu7eOpot8jHnEL0cepB8Qhn0LlQTuv6rjJqmnl3tJA3S6rcM/mOjihkk1uo7JdDK
+vH498XR5qZPDlXZ8PVu3nI5EgXpmFIcCBuuVFS5QI63NZ32YqoGYXK37K7C9lQsL
+L/iR+YpwuQqDmM+UEETjBCIMKvxghFH0ICR041yg9tkjRhNKCAGc6n70wQDUq57s
+jjZmTQ4ZydxCsWVjLo7fCcoyQ9B7IUGPUUn8WavPUwtz1kG6VK7RDGa0KtgCD0vc
+iEwbWi9uwkZdoZdHcB8qLgCPjMGgRJLOyJ67xQ0RP+r+WkhUAjYcaucFonyyBhtv
+OrqNyEM3SEpgrzgttyyg+dP/cDvPbp4NXoxKAMyd8c7mjPploQKCAQEA+BL/qxLe
+LTKwe3TKpjAeyTB2iOxoWjtCqe3/xKbTS32Tn/VGwqhXyNeh+FTRhQu7fg5iL2C2
+JCOdYXWxRYIBwUh4HfApkgYzznUAU2vOh653MzW6LsOtDdgYF2cijN1ZFcbRTGpw
+eoA6U/cijuglwpTHF7zmRd9rSsv+PZ/fTDgY82MOdeaOUwyKuVyPUpNWfqSwxPd9
+tWEdOYjgq1llPbl1mktR0gYHIdHcSr1By7kmFw3/TQuic5Nm+FDidtfJYO36xFI1
+/CfwGVYeH42iul+KzdlITLAMRm2PAcWFjvxpw78T+xeUNpZlnZSgCIjtpfjywmXb
+uQvJoMMEX5PN1wKCAQEA0PIx4sgXiwqASa/foBB0Tk5jG3QWxucpqnLJURZeRqLQ
+BmF4WRrjs5V2y6iizegIcNmL0ZfwFBU79HwtAgFiTELLQL2xivhpMVjXL7QHeE4r
+A/9+49iO8wu8W/hwKxCDdGqXKyCKtW9b1yfUVB09j29GtApcV9v8KCTmDwYGrHI0
+DcEMtNLUbJvUeWFYFadJNFKxbsBtJPJIrYaiIyv2sL+Y3tZrYES72tTAYhMFwd0r
+9ooL5Ufrpuh4pHOxxA0Sh0EVUhNmyoq/ZJZ5wia+WB5NXBSD9JbciC5M4J8BMl/u
+Bx5RZbJSoAktYiOzev//6NHUmXsDjg3Kh9P48JVasQKCAQBVjt/k1bYQ6pmZirdV
+x+TmSLOpF7gJ3sRoLTB4V30qXR4sHgEQo9Ta7RvstPwqIdjBah6M7pMDNdFSyq+g
+JG2Mhvz+flUoCsGVZB7/pn/tpctwuwgClvQ5gR0V/TkaUkEmVJLdAxzV8yGq0eJ2
+XTSgvoVH95uH3712Z5LBGEGAXRyl3LUhDqpplDrIIVdBCJXdSdm5pQ4TH3Jf5Ihw
+MH3NYwhfdbi7cd7F2EZc9Jcbtzie3PH/VZLqv5zU6bihelz29Dz3ts7tr6yMYHo1
+Mbk9BDSwOE9KO7GQHLskxkYBAadMnrs6b3Brv0U+qwLizq7//jNjvpOgZ6Nbscbx
+W92zAoIBAQCNCK17cavSgggNtNSw6epXYLmssjMdlrKdBlW0kfCYpRTc+bWOD4Ra
+lyxUU0Nw0InCAlVJ59B4/cw2PgrzK5P5/avLyz6nmv0F/f1hiZbxMXH/hNlVWbtD
+ekxtl8e+iarxTXEz/wchaEUJeSzsicAfrPCAXe3ur+IIBr/yrBKdG4jfL8sv0o7n
+sFc+huI522yiEJ8LLn99TLyZxCJ0sxwUOX8qCnj3xe02zBv/Fu/v5yXhh1R4Mo9x
+XcDw39bBikFTYi7N86KSXAzMDHWrAxO/ztRQrthSo/G/SeFCTJE2O2IjE+fFSRRU
+SV2EvKxM/bbyo49o+YtwuwZVoFKLsYRBAoIBADaL9sx49XTHIIFGqEQP7NLEhs7D
+eJgSKP5oQ54J0iaoVpsoxng8DrTBkMVW75hiWzTW75EJnMXrauo/YfAbvsMM//3e
+BfRWvYpS5xKcHmXg2QJxy2VpvElHLg5Y2lligEZhO+5Sm2OG/hixBmiFvEvxPEB8
+8YIvYKcRAGA/HgDY9hGWSNsBP7qDXWP5kRm8qnB6zn33TVZMsXwUv6TP0cwsBKf7
+XDbnPBpOQK9nicehY7oscy9yTB9Q3bUHecYLY822ueCwaJgwJWFUH+Xe4u6xIH5l
+A/IyIfyOqxjUc34Me+37ehNmbTIxZ1BqLddppm9QsSAD7cDMurfb3pRpju4=
+-----END RSA PRIVATE KEY-----
diff --git a/kong-versions/3.9.0.0/kong/spec/fixtures/forward-proxy/mtls_certs/example.com.crt b/kong-versions/3.9.0.0/kong/spec/fixtures/forward-proxy/mtls_certs/example.com.crt
new file mode 100644
index 00000000..8a3257f9
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/fixtures/forward-proxy/mtls_certs/example.com.crt
@@ -0,0 +1,63 @@
+-----BEGIN CERTIFICATE-----
+MIIFTDCCAzSgAwIBAgICIAAwDQYJKoZIhvcNAQELBQAwYDELMAkGA1UEBhMCVVMx
+EzARBgNVBAgMCkNhbGlmb3JuaWExFTATBgNVBAoMDEtvbmcgVGVzdGluZzElMCMG
+A1UEAwwcS29uZyBUZXN0aW5nIEludGVybWlkaWF0ZSBDQTAeFw0xOTA1MDIxOTU1
+MjFaFw0yOTA0MjgxOTU1MjFaME8xCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxp
+Zm9ybmlhMRUwEwYDVQQKDAxLb25nIFRlc3RpbmcxFDASBgNVBAMMC2V4YW1wbGUu
+Y29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqCozbPPts2H7CsUf
+4KlyKwbCOjqUa7ZhBcXfX5KuEHOvAUZfJOlm2TCNbO1wMTI1QHwjn6a9HM1njhBG
+4r9HH8CLckF83b247iJQbqUEjjvbb6DMTxjbC7dBunIikv6gUXeWGlRHupy/UEh8
+K0Y2KM2fm+HEbKI6zvjg/wb7zb0agzNaKV6fyEourKL0Xjz8ePm3kH58HaUmqhfk
+PPf7GnGW1xk/aIm6tsi9wzj2VBI/T3E5hVnMGrJTYnXh5DoFQrbuLvWtOB6MdZcM
+BWN/he8ISvvhKrctjWvUjpWgoZE9bRoMxkzxpHF/agM++WlHJrJ7my3yRHN3LspF
+4ER+/QIDAQABo4IBHzCCARswCQYDVR0TBAIwADARBglghkgBhvhCAQEEBAMCBkAw
+MwYJYIZIAYb4QgENBCYWJE9wZW5TU0wgR2VuZXJhdGVkIFNlcnZlciBDZXJ0aWZp
+Y2F0ZTAdBgNVHQ4EFgQUlpSl7QvKjdvJLx/sI3CXST3SqwowgYEGA1UdIwR6MHiA
+FAsOBA6X+G1iTyTwO8Zv0go7jRERoVykWjBYMQswCQYDVQQGEwJVUzETMBEGA1UE
+CAwKQ2FsaWZvcm5pYTEVMBMGA1UECgwMS29uZyBUZXN0aW5nMR0wGwYDVQQDDBRL
+b25nIFRlc3RpbmcgUm9vdCBDQYICEAAwDgYDVR0PAQH/BAQDAgWgMBMGA1UdJQQM
+MAoGCCsGAQUFBwMBMA0GCSqGSIb3DQEBCwUAA4ICAQA6kfAONRKeg0ygcyY8OwVi
+y9SGPKnKtOGjF2BSk74UF3bj63kx7utIQ0w5LZA3CwjcE2VzdPx+lQEDy/dbv442
+2bWrc7kG0/Dcr92KoUbzuuI0kPRoM/4rcOb8shKG9txFL1j44a60SWlbvkoNUD88
+vKZy2uSJ++OeQ7vuxrt2UDsfO2jRk74p/ztQibTX/cpwjvHrz2JcLTSxUZXK342x
+o7bWl1f7XMn8o7nPtNWHZq418uwFJ6OZO/rLc+FxE+31SnHYJUYC6/TSAg9kGomk
+Ws+K453QVoiPsG08Uz1JRjUQWotlEmqFAwax3kmfnrsiKmKy451CcwVAlyEIvnSb
+s2hEePHUaJltsatvFNPLnjcsOtqA46zJN0mv63BKuoa9fWAYr81D8wilcPgx534j
+KQcSv24cAoWesp/KhERK5G+F5mE0qnlCfMpFJFtfMjh+CDLbR//L4/0KQrSS/eRn
+ooeXinTpO5S2WOxk0W96rZMsBL2rBUI2qhfjBW8aQAiew4cMtddxryyUKskDlJPx
+bZXB2OmPibOOOTrTrBFkQ+tjKCuPKbOQDsIPTasZQKc2jK0boixXE8AXhN/A+3J4
+muvYnypmWGb0jMLEQT2u+RQzCNDjIOEHBP50XnoEX3jkOgEwknje89VDm/JXcClR
+l5HH4/9/AbS7rFCRnphOjQ==
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIIFmjCCA4KgAwIBAgICEAAwDQYJKoZIhvcNAQELBQAwWDELMAkGA1UEBhMCVVMx
+EzARBgNVBAgMCkNhbGlmb3JuaWExFTATBgNVBAoMDEtvbmcgVGVzdGluZzEdMBsG
+A1UEAwwUS29uZyBUZXN0aW5nIFJvb3QgQ0EwHhcNMTkwNTAyMTk0MDQ4WhcNMjkw
+NDI5MTk0MDQ4WjBgMQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEV
+MBMGA1UECgwMS29uZyBUZXN0aW5nMSUwIwYDVQQDDBxLb25nIFRlc3RpbmcgSW50
+ZXJtaWRpYXRlIENBMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA0dnj
+oHlJmNM94vQnK2FIIQJm9OAVvyMtAAkBKL7Cxt8G062GHDhq6gjQ9enuNQE0l3Vv
+mSAh7N9gNlma6YbRB9VeG54BCuRQwCxveOBiwQvC2qrTzYI34kF/AeflrDOdzuLb
+zj5cLADKXGCbGDtrSPKUwdlkuLs3pRr/YAyIQr7zJtlLz+E0GBYp0GWnLs0FiLSP
+qSBWllC9u8gt2MiKyNlXw+kZ8lofOehCJzfFr6qagVklPw+8IpU6OGmRLFQVwVhp
+zdAJmAGmSo/AGNKGqDdjzC4N2l4uYGH6n2KmY2yxsLBGZgwtLDst3fK4a3Wa5Tj7
+cUwCcGLGtfVTaIXZYbqQ0nGsaYUd/mhx3B3Jk1p3ILZ72nVYowhpj22ipPGal5hp
+ABh1MX3s/B+2ybWyDTtSaspcyhsRQsS6axB3DwLOLRy5Xp/kqEdConCtGCsjgm+U
+FzdupubXK+KIAmTKXDx8OM7Af/K7kLDfFTre40sEB6fwrWwH8yFojeqkA/Uqhn5S
+CzB0o4F3ON0xajsw2dRCziiq7pSe6ALLXetKpBr+xnVbUswH6BANUoDvh9thVPPx
+1trkv+OuoJalkruZaT+38+iV9xwdqxnR7PUawqSyvrEAxjqUo7dDPsEuOpx1DJjO
+XwRJCUjd7Ux913Iks24BqpPhEQz/rZzJLBApRVsCAwEAAaNmMGQwHQYDVR0OBBYE
+FAsOBA6X+G1iTyTwO8Zv0go7jRERMB8GA1UdIwQYMBaAFAdP8giF4QLaR0HEj9N8
+apTFYnD3MBIGA1UdEwEB/wQIMAYBAf8CAQAwDgYDVR0PAQH/BAQDAgGGMA0GCSqG
+SIb3DQEBCwUAA4ICAQAWzIvIVM32iurqM451Amz0HNDG9j84cORnnaRR5opFTr3P
+EqI3QkgCyP6YOs9t0QSbA4ur9WUzd3c9Ktj3qRRgTE+98JBOPO0rv+Kjj48aANDV
+5tcbI9TZ9ap6g0jYr4XNT+KOO7E8QYlpY/wtokudCUDJE9vrsp1on4Bal2gjvCdh
+SU0C1lnj6q6kBdQSYHrcjiEIGJH21ayVoNaBVP/fxyCHz472w1xN220dxUI/GqB6
+pjcuy9cHjJHJKJbrkdt2eDRAFP5cILXc3mzUoGUDHY2JA1gtOHV0p4ix9R9AfI9x
+snBEFiD8oIpcQay8MJH/z3NLEPLoBW+JaAAs89P+jcppea5N9vbiAkrPi687BFTP
+PWPdstyttw6KrvtPQR1+FsVFcGeTjo32/UrckJixdiOEZgHk+deXpp7JoRdcsgzD
++okrsG79/LgS4icLmzNEp0IV36QckEq0+ALKDu6BXvWTkb5DB/FUrovZKJgkYeWj
+GKogyrPIXrYi725Ff306124kLbxiA+6iBbKUtCutQnvut78puC6iP+a2SrfsbUJ4
+qpvBFOY29Mlww88oWNGTA8QeW84Y1EJbRkHavzSsMFB73sxidQW0cHNC5t9RCKAQ
+uibeZgK1Yk7YQKXdvbZvXwrgTcAjCdbppw2L6e0Uy+OGgNjnIps8K460SdaIiA==
+-----END CERTIFICATE-----
diff --git a/kong-versions/3.9.0.0/kong/spec/fixtures/forward-proxy/mtls_certs/example.com.key b/kong-versions/3.9.0.0/kong/spec/fixtures/forward-proxy/mtls_certs/example.com.key
new file mode 100644
index 00000000..c8ad8f2e
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/fixtures/forward-proxy/mtls_certs/example.com.key
@@ -0,0 +1,27 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIEpAIBAAKCAQEAqCozbPPts2H7CsUf4KlyKwbCOjqUa7ZhBcXfX5KuEHOvAUZf
+JOlm2TCNbO1wMTI1QHwjn6a9HM1njhBG4r9HH8CLckF83b247iJQbqUEjjvbb6DM
+TxjbC7dBunIikv6gUXeWGlRHupy/UEh8K0Y2KM2fm+HEbKI6zvjg/wb7zb0agzNa
+KV6fyEourKL0Xjz8ePm3kH58HaUmqhfkPPf7GnGW1xk/aIm6tsi9wzj2VBI/T3E5
+hVnMGrJTYnXh5DoFQrbuLvWtOB6MdZcMBWN/he8ISvvhKrctjWvUjpWgoZE9bRoM
+xkzxpHF/agM++WlHJrJ7my3yRHN3LspF4ER+/QIDAQABAoIBACHkx5KpI3qpP+ju
+zDsCzAECDrmfvvRqwOlh9WCU9sJYHqi6H0kYReN2lrqirJ8tyG/j1WZDPBCHEd0f
+SLpA5TvwGesAagNjTteoUN/MILvuMo8wMJ2sm9GjsPq8MF3CNlvVJ4rM+9wP5btv
+sJ8kOpxEvWu0uFtQ41t97BNau/u+UtMk3oNCYBhiUWDg0rWPrUeX8cKzFSM8VAt4
+vvsybRHPbBmSLW01xO1Hq5cZdqbN4SxyQC1Ug9gW/afJQNRK7CubpWjOOQAsla0j
+ExyBxMMwDLLZfYCQpRn92ZB4x+LiaXqnbrtyfA+GLLjtlUPY6ClpdXa7KSN/mEuE
+LIIjiV0CgYEA2YsCt1+Yak+GOX6tSx1YUDz6UpZyOo2OKwqJ+G+SKT7JLT84A5nP
+rn6r6UUpNKhK3glpU1A1VJKiFnZ9qJi/gHJcNiSEIcUFHNFflDSmiZc6MyfcIkCZ
+xLUCrYHpETubTnB5P5jOhmsA3/uApaAc/Pv5hfSRzQv524k08TRgCU8CgYEAxeSQ
+MIRV1SKDYsEdEfXJE+WJLz2rlpR19l/9Wfuc5QVgAgDhFCCvHUX1ULU8yGQUSHqz
+DseR3iQF+Jvo3MK7pgC2fH6UePjakWOCXqXey1CpAzUHM/Qhwd451VqAGAT+Pabj
+tzPJ0cSC7sszxhwmAzotIUrjZDbuAzwQyRXdh/MCgYEApP2KVNt69H5V9bs+4W5j
+MY/d5s9V2VTNE5XNqI+uEfwdhmShLhH08on+BlC+/MH67kXDDT4TBI6lwlWh3kHj
+VB7oEuRFFnuf8ghV7ki0WjxJFs1PZucJ+Ke0XTXfN4O2uZoSS4qwcEAtjLLqEjPK
+aJEO4WrpPdOsb7WzYpDvmX8CgYEAwPunXZkAN0xkAl8+4S/mup+Ci+5BMiRvcSek
+4yaLl5AJU4rV9JH3E74QgHdt4iIu4Yu+qHAYoSBSLmKk0PyakEVrsLakReCxDU2U
+aoapYW60k6sX7iNq9CuqDJUoC8R6x1bEBPndG9LeuM6zG8SBkW4farMkU6t5qu/d
+kqvfEN8CgYAQphK9AoATrEomLbGwmcW+8JkjU9Sxnq+zo8io75wFAY2cUnQJQEId
+zGWwYjwHxXQCNCZ3ZwD7+iYgFHfxbPaiTWELkV2nEpBHQI0cLgzlcEBwo+uoFiYK
+33Yxb6EhNFSy7d2GPVZMjIR+KifCIem+i/3BiIlzneuFSRlnKORekQ==
+-----END RSA PRIVATE KEY-----
diff --git a/kong-versions/3.9.0.0/kong/spec/fixtures/forward-proxy/mtls_certs/example2.com.crt b/kong-versions/3.9.0.0/kong/spec/fixtures/forward-proxy/mtls_certs/example2.com.crt
new file mode 100644
index 00000000..85756548
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/fixtures/forward-proxy/mtls_certs/example2.com.crt
@@ -0,0 +1,25 @@
+-----BEGIN CERTIFICATE-----
+MIIEJzCCAg8CFAQ6oTnLBUHbumx1bxyY9kV0W21BMA0GCSqGSIb3DQEBCwUAMFgx
+CzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRUwEwYDVQQKDAxLb25n
+IFRlc3RpbmcxHTAbBgNVBAMMFEtvbmcgVGVzdGluZyBSb290IENBMB4XDTIwMDQx
+MzIzNDg0MVoXDTMwMDQxMTIzNDg0MVowSDELMAkGA1UEBhMCVVMxCzAJBgNVBAgM
+AkNBMRUwEwYDVQQKDAxLb25nIFRlc3RpbmcxFTATBgNVBAMMDGV4YW1wbGUyLmNv
+bTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAK+kZhxdN8PA3SW9cXiv
+xgtANq57PIWNnSDsg9Yxn0/+JKR45pSU+SKYtZUJJJuOdkv4IIJLm6uG6LbOPUDO
+g9EaV0Zw7RQtbY6EDFDFzeyq0/Mwl9wLJtXf0fPsXGyFIdeelBjzoSVsGGJKPWbP
+rlUtSHCrpFX53NTPnNVUJz9V6CdzZJgbyoiWP7ggKJeRPq6jCW5pt+cd+sR4+EPh
+daBmEVWeifLEKCbBvsQaOGfU1aVG1AlX0RpLBkTxOOFIIk/3dgWOsrek2ofjku4F
+g0MeWmD8oXOHUX2JxO77/BbLDQt0lzD27y/EkDoqy6mMAH85/LTYrU+P0WsEyexg
+CHcCAwEAATANBgkqhkiG9w0BAQsFAAOCAgEAwWAxQjQOoGxU5LQu4ZmsCkps9y0B
+kNj8MUpLcFmK+02VIUh3hM4vuB6Gct2Ph+6zqCge3oqTXltU0Bs2MTwAKs/scsxq
+Mtanz4W00UlmG3QdgHaEs196tYQ8cKIaGZsNBv15VgBBduUG478pKqYE8bJKBbw7
+1Ym390hSPo0dNe7jLFXx6AaJvlEYh09P4FgfkXuY5VVTGXfN7XgJI073pLRY6iGH
+Qd+Egymh86AQtnoNpmqSCMNcjRVAyR8Ti3qnyro8ruZCnNYHieGeh/ZsZvhGDeWX
+v4YXjW2NDQ5+Ok6Gtvhf/l6RSrnXLbZtv8NStqwQJ+ydu05BJglZ/7Sb0uQYVNq2
+H8V+MtApFT6fG6ANM6hadNFG+p8Hwz6k4BLrc9ZxeWYKWIIusqExR9JIlGzEjvFJ
+6NmNjm3eZE9Ue4YgURj1KTr53wAso4LbJpz/zuZS+m9PMz7n8fRL25/Z5b/92L3a
+w0vsxUJyTDeMvYf8oT6OkxNVJ0zBRZNtEg5AJKdP6nU53V998jHP9vUisrU2ALhu
+Jw3QiWiDKnRtx8PiiRx7dWo+Xwn9+xVypytqNz3w/XJlOjMwOg73q399w+vMiFTl
+qdr7eYvaQBGOZVc3OdiP8afyVxlhHBowUoi8G+iPbgOsARHv/j4UeMVyIThzxv73
+a2EQ5BzyOzQ81H4=
+-----END CERTIFICATE-----
diff --git a/kong-versions/3.9.0.0/kong/spec/fixtures/forward-proxy/mtls_certs/example2.com.key b/kong-versions/3.9.0.0/kong/spec/fixtures/forward-proxy/mtls_certs/example2.com.key
new file mode 100644
index 00000000..05c29251
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/fixtures/forward-proxy/mtls_certs/example2.com.key
@@ -0,0 +1,27 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIEpAIBAAKCAQEAr6RmHF03w8DdJb1xeK/GC0A2rns8hY2dIOyD1jGfT/4kpHjm
+lJT5Ipi1lQkkm452S/gggkubq4bots49QM6D0RpXRnDtFC1tjoQMUMXN7KrT8zCX
+3Asm1d/R8+xcbIUh156UGPOhJWwYYko9Zs+uVS1IcKukVfnc1M+c1VQnP1XoJ3Nk
+mBvKiJY/uCAol5E+rqMJbmm35x36xHj4Q+F1oGYRVZ6J8sQoJsG+xBo4Z9TVpUbU
+CVfRGksGRPE44UgiT/d2BY6yt6Tah+OS7gWDQx5aYPyhc4dRfYnE7vv8FssNC3SX
+MPbvL8SQOirLqYwAfzn8tNitT4/RawTJ7GAIdwIDAQABAoIBAHMJzgdN1rRToYSS
+a7uMBL5htG7bMGyYsA1cW4zyu1F9NyqyNPOkDvjl5ChU8LEhwcFIJqKwOqlBlzIE
+KoJDwHo4MmlklSLeDh+FxTsyEwmraV6iuRPaCfmSusR0TqSVHfFHX+Bn0WfdQKs/
+zK+F3rzTB9sj0GKvYD/SKvpeP8Zuu9EBqo4N7PU3VHwDq5t32Ut/+M5XWtulsQcs
+qXr2R3agj/DnODANT6Dn/mJboTrYOSV18S/Yw/+OnWBcLzlT5sj0aLgrtXvIputv
+9caux4HklAQr29+lKB8nBTfjhXnBntMaEgqCVJ3ri83MuEfVDhmjwo6PnX22/J0h
+2XbCyUECgYEA2v8m+CTBTjdAqOuje34+UiWRzT2P9OFONV8nYgzEcQW5JkUoFCun
+KgQQIvjCsX4jY6/8w/IPF1ieTconZYJUWSyMZFtBBDCVif1GZRiiM2C4Zcero1KV
+U0V3wZcnYkzafzIHkqFUYZwamvdKWVI4c6F5MhSEKCgcbgKKI52TEokCgYEAzVHr
+KjQt+dqNkbipYoGH2ywLdcogDwKoyUFbgcvz/q625gu4am025wF25yRKExm7Dyjx
+eCQC+KOsBfJSc78fG5R6KPIDK1JrpUEGSCeqFICiqGv9kUzPf5zeGZVf9cU4tyPT
+5wYUEM7NX8VRoasZ4OUvYyYBw1Cx8vMdvQn/gv8CgYAIhxcFYqkEWrJx4XskO+5B
+VKUw0MziREO/YE0wTD76B7cF/ntpDaocwLvAIN+z+a13HEtDdhGQXysK7GxMT57p
+OgrdfZAykZHBJdOv7B2k0odbr0LHwVd/Pp1DNJecBFId0dzpoM6gXmvKzQZgJAt+
+tTL6+EGNLsKspfyrFl+7wQKBgQDAt2VuJbAJ1xQOdS+4IDCujfbrxp60uCBJVylW
++WK56LAP2WxtqLlhtsQuTKeiqgIkRp/vzo1jZ+0tX7f4oKnIL2NCT3aeESys3g3R
+aDmCKQOD5mkJGvmgpFLr3INHoqiLbfuV2uS2qgWnIQRwJLOTnksOWzxIYdPFYGDH
+cTz9bQKBgQDGv929DUinrKXe/uKJHLAcq+MjmF/+kZU9yn+svq6SSdplqp7xbXX4
+3T5HCWqD4Sy+PVzGaDg5YfXC8yaFPPfY0/35T2FoQEiCAPQO+07Smg6RqJ3yVpIm
+LTsbLleJTc8CX0bI4SukQ7MVQsiHimzyEzx3eyLt1S8aBdJuRFZ2mg==
+-----END RSA PRIVATE KEY-----
diff --git a/kong-versions/3.9.0.0/kong/spec/fixtures/grpc/direct_imports.proto b/kong-versions/3.9.0.0/kong/spec/fixtures/grpc/direct_imports.proto
new file mode 100644
index 00000000..1a4bb350
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/fixtures/grpc/direct_imports.proto
@@ -0,0 +1,7 @@
+syntax = "proto3";
+
+import "helloworld.proto";
+
+service Own {
+ rpc Open(hello.HelloRequest) returns (hello.HelloResponse);
+}
diff --git a/kong-versions/3.9.0.0/kong/spec/fixtures/grpc/google/api/annotations.proto b/kong-versions/3.9.0.0/kong/spec/fixtures/grpc/google/api/annotations.proto
new file mode 100644
index 00000000..85c361b4
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/fixtures/grpc/google/api/annotations.proto
@@ -0,0 +1,31 @@
+// Copyright (c) 2015, Google Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+syntax = "proto3";
+
+package google.api;
+
+import "google/api/http.proto";
+import "google/protobuf/descriptor.proto";
+
+option go_package = "google.golang.org/genproto/googleapis/api/annotations;annotations";
+option java_multiple_files = true;
+option java_outer_classname = "AnnotationsProto";
+option java_package = "com.google.api";
+option objc_class_prefix = "GAPI";
+
+extend google.protobuf.MethodOptions {
+ // See `HttpRule`.
+ HttpRule http = 72295728;
+}
diff --git a/kong-versions/3.9.0.0/kong/spec/fixtures/grpc/google/api/http.proto b/kong-versions/3.9.0.0/kong/spec/fixtures/grpc/google/api/http.proto
new file mode 100644
index 00000000..285d7a3e
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/fixtures/grpc/google/api/http.proto
@@ -0,0 +1,318 @@
+// Copyright 2018 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+syntax = "proto3";
+
+package google.api;
+
+option cc_enable_arenas = true;
+option go_package = "google.golang.org/genproto/googleapis/api/annotations;annotations";
+option java_multiple_files = true;
+option java_outer_classname = "HttpProto";
+option java_package = "com.google.api";
+option objc_class_prefix = "GAPI";
+
+
+// Defines the HTTP configuration for an API service. It contains a list of
+// [HttpRule][google.api.HttpRule], each specifying the mapping of an RPC method
+// to one or more HTTP REST API methods.
+message Http {
+ // A list of HTTP configuration rules that apply to individual API methods.
+ //
+ // **NOTE:** All service configuration rules follow "last one wins" order.
+ repeated HttpRule rules = 1;
+
+ // When set to true, URL path parameters will be fully URI-decoded except in
+ // cases of single segment matches in reserved expansion, where "%2F" will be
+ // left encoded.
+ //
+ // The default behavior is to not decode RFC 6570 reserved characters in multi
+ // segment matches.
+ bool fully_decode_reserved_expansion = 2;
+}
+
+// `HttpRule` defines the mapping of an RPC method to one or more HTTP
+// REST API methods. The mapping specifies how different portions of the RPC
+// request message are mapped to URL path, URL query parameters, and
+// HTTP request body. The mapping is typically specified as an
+// `google.api.http` annotation on the RPC method,
+// see "google/api/annotations.proto" for details.
+//
+// The mapping consists of a field specifying the path template and
+// method kind. The path template can refer to fields in the request
+// message, as in the example below which describes a REST GET
+// operation on a resource collection of messages:
+//
+//
+// service Messaging {
+// rpc GetMessage(GetMessageRequest) returns (Message) {
+// option (google.api.http).get = "/v1/messages/{message_id}/{sub.subfield}";
+// }
+// }
+// message GetMessageRequest {
+// message SubMessage {
+// string subfield = 1;
+// }
+// string message_id = 1; // mapped to the URL
+// SubMessage sub = 2; // `sub.subfield` is url-mapped
+// }
+// message Message {
+// string text = 1; // content of the resource
+// }
+//
+// The same http annotation can alternatively be expressed inside the
+// `GRPC API Configuration` YAML file.
+//
+// http:
+// rules:
+// - selector: .Messaging.GetMessage
+// get: /v1/messages/{message_id}/{sub.subfield}
+//
+// This definition enables an automatic, bidrectional mapping of HTTP
+// JSON to RPC. Example:
+//
+// HTTP | RPC
+// -----|-----
+// `GET /v1/messages/123456/foo` | `GetMessage(message_id: "123456" sub: SubMessage(subfield: "foo"))`
+//
+// In general, not only fields but also field paths can be referenced
+// from a path pattern. Fields mapped to the path pattern cannot be
+// repeated and must have a primitive (non-message) type.
+//
+// Any fields in the request message which are not bound by the path
+// pattern automatically become (optional) HTTP query
+// parameters. Assume the following definition of the request message:
+//
+//
+// service Messaging {
+// rpc GetMessage(GetMessageRequest) returns (Message) {
+// option (google.api.http).get = "/v1/messages/{message_id}";
+// }
+// }
+// message GetMessageRequest {
+// message SubMessage {
+// string subfield = 1;
+// }
+// string message_id = 1; // mapped to the URL
+// int64 revision = 2; // becomes a parameter
+// SubMessage sub = 3; // `sub.subfield` becomes a parameter
+// }
+//
+//
+// This enables a HTTP JSON to RPC mapping as below:
+//
+// HTTP | RPC
+// -----|-----
+// `GET /v1/messages/123456?revision=2&sub.subfield=foo` | `GetMessage(message_id: "123456" revision: 2 sub: SubMessage(subfield: "foo"))`
+//
+// Note that fields which are mapped to HTTP parameters must have a
+// primitive type or a repeated primitive type. Message types are not
+// allowed. In the case of a repeated type, the parameter can be
+// repeated in the URL, as in `...?param=A¶m=B`.
+//
+// For HTTP method kinds which allow a request body, the `body` field
+// specifies the mapping. Consider a REST update method on the
+// message resource collection:
+//
+//
+// service Messaging {
+// rpc UpdateMessage(UpdateMessageRequest) returns (Message) {
+// option (google.api.http) = {
+// put: "/v1/messages/{message_id}"
+// body: "message"
+// };
+// }
+// }
+// message UpdateMessageRequest {
+// string message_id = 1; // mapped to the URL
+// Message message = 2; // mapped to the body
+// }
+//
+//
+// The following HTTP JSON to RPC mapping is enabled, where the
+// representation of the JSON in the request body is determined by
+// protos JSON encoding:
+//
+// HTTP | RPC
+// -----|-----
+// `PUT /v1/messages/123456 { "text": "Hi!" }` | `UpdateMessage(message_id: "123456" message { text: "Hi!" })`
+//
+// The special name `*` can be used in the body mapping to define that
+// every field not bound by the path template should be mapped to the
+// request body. This enables the following alternative definition of
+// the update method:
+//
+// service Messaging {
+// rpc UpdateMessage(Message) returns (Message) {
+// option (google.api.http) = {
+// put: "/v1/messages/{message_id}"
+// body: "*"
+// };
+// }
+// }
+// message Message {
+// string message_id = 1;
+// string text = 2;
+// }
+//
+//
+// The following HTTP JSON to RPC mapping is enabled:
+//
+// HTTP | RPC
+// -----|-----
+// `PUT /v1/messages/123456 { "text": "Hi!" }` | `UpdateMessage(message_id: "123456" text: "Hi!")`
+//
+// Note that when using `*` in the body mapping, it is not possible to
+// have HTTP parameters, as all fields not bound by the path end in
+// the body. This makes this option more rarely used in practice of
+// defining REST APIs. The common usage of `*` is in custom methods
+// which don't use the URL at all for transferring data.
+//
+// It is possible to define multiple HTTP methods for one RPC by using
+// the `additional_bindings` option. Example:
+//
+// service Messaging {
+// rpc GetMessage(GetMessageRequest) returns (Message) {
+// option (google.api.http) = {
+// get: "/v1/messages/{message_id}"
+// additional_bindings {
+// get: "/v1/users/{user_id}/messages/{message_id}"
+// }
+// };
+// }
+// }
+// message GetMessageRequest {
+// string message_id = 1;
+// string user_id = 2;
+// }
+//
+//
+// This enables the following two alternative HTTP JSON to RPC
+// mappings:
+//
+// HTTP | RPC
+// -----|-----
+// `GET /v1/messages/123456` | `GetMessage(message_id: "123456")`
+// `GET /v1/users/me/messages/123456` | `GetMessage(user_id: "me" message_id: "123456")`
+//
+// # Rules for HTTP mapping
+//
+// The rules for mapping HTTP path, query parameters, and body fields
+// to the request message are as follows:
+//
+// 1. The `body` field specifies either `*` or a field path, or is
+// omitted. If omitted, it indicates there is no HTTP request body.
+// 2. Leaf fields (recursive expansion of nested messages in the
+// request) can be classified into three types:
+// (a) Matched in the URL template.
+// (b) Covered by body (if body is `*`, everything except (a) fields;
+// else everything under the body field)
+// (c) All other fields.
+// 3. URL query parameters found in the HTTP request are mapped to (c) fields.
+// 4. Any body sent with an HTTP request can contain only (b) fields.
+//
+// The syntax of the path template is as follows:
+//
+// Template = "/" Segments [ Verb ] ;
+// Segments = Segment { "/" Segment } ;
+// Segment = "*" | "**" | LITERAL | Variable ;
+// Variable = "{" FieldPath [ "=" Segments ] "}" ;
+// FieldPath = IDENT { "." IDENT } ;
+// Verb = ":" LITERAL ;
+//
+// The syntax `*` matches a single path segment. The syntax `**` matches zero
+// or more path segments, which must be the last part of the path except the
+// `Verb`. The syntax `LITERAL` matches literal text in the path.
+//
+// The syntax `Variable` matches part of the URL path as specified by its
+// template. A variable template must not contain other variables. If a variable
+// matches a single path segment, its template may be omitted, e.g. `{var}`
+// is equivalent to `{var=*}`.
+//
+// If a variable contains exactly one path segment, such as `"{var}"` or
+// `"{var=*}"`, when such a variable is expanded into a URL path, all characters
+// except `[-_.~0-9a-zA-Z]` are percent-encoded. Such variables show up in the
+// Discovery Document as `{var}`.
+//
+// If a variable contains one or more path segments, such as `"{var=foo/*}"`
+// or `"{var=**}"`, when such a variable is expanded into a URL path, all
+// characters except `[-_.~/0-9a-zA-Z]` are percent-encoded. Such variables
+// show up in the Discovery Document as `{+var}`.
+//
+// NOTE: While the single segment variable matches the semantics of
+// [RFC 6570](https://tools.ietf.org/html/rfc6570) Section 3.2.2
+// Simple String Expansion, the multi segment variable **does not** match
+// RFC 6570 Reserved Expansion. The reason is that the Reserved Expansion
+// does not expand special characters like `?` and `#`, which would lead
+// to invalid URLs.
+//
+// NOTE: the field paths in variables and in the `body` must not refer to
+// repeated fields or map fields.
+message HttpRule {
+ // Selects methods to which this rule applies.
+ //
+ // Refer to [selector][google.api.DocumentationRule.selector] for syntax details.
+ string selector = 1;
+
+ // Determines the URL pattern is matched by this rules. This pattern can be
+ // used with any of the {get|put|post|delete|patch} methods. A custom method
+ // can be defined using the 'custom' field.
+ oneof pattern {
+ // Used for listing and getting information about resources.
+ string get = 2;
+
+ // Used for updating a resource.
+ string put = 3;
+
+ // Used for creating a resource.
+ string post = 4;
+
+ // Used for deleting a resource.
+ string delete = 5;
+
+ // Used for updating a resource.
+ string patch = 6;
+
+ // The custom pattern is used for specifying an HTTP method that is not
+ // included in the `pattern` field, such as HEAD, or "*" to leave the
+ // HTTP method unspecified for this rule. The wild-card rule is useful
+ // for services that provide content to Web (HTML) clients.
+ CustomHttpPattern custom = 8;
+ }
+
+ // The name of the request field whose value is mapped to the HTTP body, or
+ // `*` for mapping all fields not captured by the path pattern to the HTTP
+ // body. NOTE: the referred field must not be a repeated field and must be
+ // present at the top-level of request message type.
+ string body = 7;
+
+ // Optional. The name of the response field whose value is mapped to the HTTP
+ // body of response. Other response fields are ignored. When
+ // not set, the response message will be used as HTTP body of response.
+ string response_body = 12;
+
+ // Additional HTTP bindings for the selector. Nested bindings must
+ // not contain an `additional_bindings` field themselves (that is,
+ // the nesting may only be one level deep).
+ repeated HttpRule additional_bindings = 11;
+}
+
+// A custom pattern is used for defining custom HTTP verb.
+message CustomHttpPattern {
+ // The name of this custom HTTP verb.
+ string kind = 1;
+
+ // The path matched by this custom verb.
+ string path = 2;
+}
diff --git a/kong-versions/3.9.0.0/kong/spec/fixtures/grpc/google/api/httpbody.proto b/kong-versions/3.9.0.0/kong/spec/fixtures/grpc/google/api/httpbody.proto
new file mode 100644
index 00000000..4428515c
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/fixtures/grpc/google/api/httpbody.proto
@@ -0,0 +1,78 @@
+// Copyright 2018 Google LLC.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+syntax = "proto3";
+
+package google.api;
+
+import "google/protobuf/any.proto";
+
+option cc_enable_arenas = true;
+option go_package = "google.golang.org/genproto/googleapis/api/httpbody;httpbody";
+option java_multiple_files = true;
+option java_outer_classname = "HttpBodyProto";
+option java_package = "com.google.api";
+option objc_class_prefix = "GAPI";
+
+// Message that represents an arbitrary HTTP body. It should only be used for
+// payload formats that can't be represented as JSON, such as raw binary or
+// an HTML page.
+//
+//
+// This message can be used both in streaming and non-streaming API methods in
+// the request as well as the response.
+//
+// It can be used as a top-level request field, which is convenient if one
+// wants to extract parameters from either the URL or HTTP template into the
+// request fields and also want access to the raw HTTP body.
+//
+// Example:
+//
+// message GetResourceRequest {
+// // A unique request id.
+// string request_id = 1;
+//
+// // The raw HTTP body is bound to this field.
+// google.api.HttpBody http_body = 2;
+// }
+//
+// service ResourceService {
+// rpc GetResource(GetResourceRequest) returns (google.api.HttpBody);
+// rpc UpdateResource(google.api.HttpBody) returns
+// (google.protobuf.Empty);
+// }
+//
+// Example with streaming methods:
+//
+// service CaldavService {
+// rpc GetCalendar(stream google.api.HttpBody)
+// returns (stream google.api.HttpBody);
+// rpc UpdateCalendar(stream google.api.HttpBody)
+// returns (stream google.api.HttpBody);
+// }
+//
+// Use of this type only changes how the request and response bodies are
+// handled, all other features will continue to work unchanged.
+message HttpBody {
+ // The HTTP Content-Type header value specifying the content type of the body.
+ string content_type = 1;
+
+ // The HTTP request/response body as raw binary.
+ bytes data = 2;
+
+ // Application specific response metadata. Must be set in the first response
+ // for streaming APIs.
+ repeated google.protobuf.Any extensions = 3;
+}
\ No newline at end of file
diff --git a/kong-versions/3.9.0.0/kong/spec/fixtures/grpc/google/protobuf/any.proto b/kong-versions/3.9.0.0/kong/spec/fixtures/grpc/google/protobuf/any.proto
new file mode 100644
index 00000000..49329425
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/fixtures/grpc/google/protobuf/any.proto
@@ -0,0 +1,154 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+syntax = "proto3";
+
+package google.protobuf;
+
+option csharp_namespace = "Google.Protobuf.WellKnownTypes";
+option go_package = "github.com/golang/protobuf/ptypes/any";
+option java_package = "com.google.protobuf";
+option java_outer_classname = "AnyProto";
+option java_multiple_files = true;
+option objc_class_prefix = "GPB";
+
+// `Any` contains an arbitrary serialized protocol buffer message along with a
+// URL that describes the type of the serialized message.
+//
+// Protobuf library provides support to pack/unpack Any values in the form
+// of utility functions or additional generated methods of the Any type.
+//
+// Example 1: Pack and unpack a message in C++.
+//
+// Foo foo = ...;
+// Any any;
+// any.PackFrom(foo);
+// ...
+// if (any.UnpackTo(&foo)) {
+// ...
+// }
+//
+// Example 2: Pack and unpack a message in Java.
+//
+// Foo foo = ...;
+// Any any = Any.pack(foo);
+// ...
+// if (any.is(Foo.class)) {
+// foo = any.unpack(Foo.class);
+// }
+//
+// Example 3: Pack and unpack a message in Python.
+//
+// foo = Foo(...)
+// any = Any()
+// any.Pack(foo)
+// ...
+// if any.Is(Foo.DESCRIPTOR):
+// any.Unpack(foo)
+// ...
+//
+// Example 4: Pack and unpack a message in Go
+//
+// foo := &pb.Foo{...}
+// any, err := ptypes.MarshalAny(foo)
+// ...
+// foo := &pb.Foo{}
+// if err := ptypes.UnmarshalAny(any, foo); err != nil {
+// ...
+// }
+//
+// The pack methods provided by protobuf library will by default use
+// 'type.googleapis.com/full.type.name' as the type URL and the unpack
+// methods only use the fully qualified type name after the last '/'
+// in the type URL, for example "foo.bar.com/x/y.z" will yield type
+// name "y.z".
+//
+//
+// JSON
+// ====
+// The JSON representation of an `Any` value uses the regular
+// representation of the deserialized, embedded message, with an
+// additional field `@type` which contains the type URL. Example:
+//
+// package google.profile;
+// message Person {
+// string first_name = 1;
+// string last_name = 2;
+// }
+//
+// {
+// "@type": "type.googleapis.com/google.profile.Person",
+// "firstName": ,
+// "lastName":
+// }
+//
+// If the embedded message type is well-known and has a custom JSON
+// representation, that representation will be embedded adding a field
+// `value` which holds the custom JSON in addition to the `@type`
+// field. Example (for message [google.protobuf.Duration][]):
+//
+// {
+// "@type": "type.googleapis.com/google.protobuf.Duration",
+// "value": "1.212s"
+// }
+//
+message Any {
+ // A URL/resource name that uniquely identifies the type of the serialized
+ // protocol buffer message. The last segment of the URL's path must represent
+ // the fully qualified name of the type (as in
+ // `path/google.protobuf.Duration`). The name should be in a canonical form
+ // (e.g., leading "." is not accepted).
+ //
+ // In practice, teams usually precompile into the binary all types that they
+ // expect it to use in the context of Any. However, for URLs which use the
+ // scheme `http`, `https`, or no scheme, one can optionally set up a type
+ // server that maps type URLs to message definitions as follows:
+ //
+ // * If no scheme is provided, `https` is assumed.
+ // * An HTTP GET on the URL must yield a [google.protobuf.Type][]
+ // value in binary format, or produce an error.
+ // * Applications are allowed to cache lookup results based on the
+ // URL, or have them precompiled into a binary to avoid any
+ // lookup. Therefore, binary compatibility needs to be preserved
+ // on changes to types. (Use versioned type names to manage
+ // breaking changes.)
+ //
+ // Note: this functionality is not currently available in the official
+ // protobuf release, and it is not used for type URLs beginning with
+ // type.googleapis.com.
+ //
+ // Schemes other than `http`, `https` (or the empty scheme) might be
+ // used with implementation specific semantics.
+ //
+ string type_url = 1;
+
+ // Must be a valid serialized protocol buffer of the above specified type.
+ bytes value = 2;
+}
diff --git a/kong-versions/3.9.0.0/kong/spec/fixtures/grpc/google/protobuf/api.proto b/kong-versions/3.9.0.0/kong/spec/fixtures/grpc/google/protobuf/api.proto
new file mode 100644
index 00000000..f37ee2fa
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/fixtures/grpc/google/protobuf/api.proto
@@ -0,0 +1,210 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+syntax = "proto3";
+
+package google.protobuf;
+
+import "google/protobuf/source_context.proto";
+import "google/protobuf/type.proto";
+
+option csharp_namespace = "Google.Protobuf.WellKnownTypes";
+option java_package = "com.google.protobuf";
+option java_outer_classname = "ApiProto";
+option java_multiple_files = true;
+option objc_class_prefix = "GPB";
+option go_package = "google.golang.org/genproto/protobuf/api;api";
+
+// Api is a light-weight descriptor for an API Interface.
+//
+// Interfaces are also described as "protocol buffer services" in some contexts,
+// such as by the "service" keyword in a .proto file, but they are different
+// from API Services, which represent a concrete implementation of an interface
+// as opposed to simply a description of methods and bindings. They are also
+// sometimes simply referred to as "APIs" in other contexts, such as the name of
+// this message itself. See https://cloud.google.com/apis/design/glossary for
+// detailed terminology.
+message Api {
+
+ // The fully qualified name of this interface, including package name
+ // followed by the interface's simple name.
+ string name = 1;
+
+ // The methods of this interface, in unspecified order.
+ repeated Method methods = 2;
+
+ // Any metadata attached to the interface.
+ repeated Option options = 3;
+
+ // A version string for this interface. If specified, must have the form
+ // `major-version.minor-version`, as in `1.10`. If the minor version is
+ // omitted, it defaults to zero. If the entire version field is empty, the
+ // major version is derived from the package name, as outlined below. If the
+ // field is not empty, the version in the package name will be verified to be
+ // consistent with what is provided here.
+ //
+ // The versioning schema uses [semantic
+ // versioning](http://semver.org) where the major version number
+ // indicates a breaking change and the minor version an additive,
+ // non-breaking change. Both version numbers are signals to users
+ // what to expect from different versions, and should be carefully
+ // chosen based on the product plan.
+ //
+ // The major version is also reflected in the package name of the
+ // interface, which must end in `v`, as in
+ // `google.feature.v1`. For major versions 0 and 1, the suffix can
+ // be omitted. Zero major versions must only be used for
+ // experimental, non-GA interfaces.
+ //
+ //
+ string version = 4;
+
+ // Source context for the protocol buffer service represented by this
+ // message.
+ SourceContext source_context = 5;
+
+ // Included interfaces. See [Mixin][].
+ repeated Mixin mixins = 6;
+
+ // The source syntax of the service.
+ Syntax syntax = 7;
+}
+
+// Method represents a method of an API interface.
+message Method {
+
+ // The simple name of this method.
+ string name = 1;
+
+ // A URL of the input message type.
+ string request_type_url = 2;
+
+ // If true, the request is streamed.
+ bool request_streaming = 3;
+
+ // The URL of the output message type.
+ string response_type_url = 4;
+
+ // If true, the response is streamed.
+ bool response_streaming = 5;
+
+ // Any metadata attached to the method.
+ repeated Option options = 6;
+
+ // The source syntax of this method.
+ Syntax syntax = 7;
+}
+
+// Declares an API Interface to be included in this interface. The including
+// interface must redeclare all the methods from the included interface, but
+// documentation and options are inherited as follows:
+//
+// - If after comment and whitespace stripping, the documentation
+// string of the redeclared method is empty, it will be inherited
+// from the original method.
+//
+// - Each annotation belonging to the service config (http,
+// visibility) which is not set in the redeclared method will be
+// inherited.
+//
+// - If an http annotation is inherited, the path pattern will be
+// modified as follows. Any version prefix will be replaced by the
+// version of the including interface plus the [root][] path if
+// specified.
+//
+// Example of a simple mixin:
+//
+// package google.acl.v1;
+// service AccessControl {
+// // Get the underlying ACL object.
+// rpc GetAcl(GetAclRequest) returns (Acl) {
+// option (google.api.http).get = "/v1/{resource=**}:getAcl";
+// }
+// }
+//
+// package google.storage.v2;
+// service Storage {
+// rpc GetAcl(GetAclRequest) returns (Acl);
+//
+// // Get a data record.
+// rpc GetData(GetDataRequest) returns (Data) {
+// option (google.api.http).get = "/v2/{resource=**}";
+// }
+// }
+//
+// Example of a mixin configuration:
+//
+// apis:
+// - name: google.storage.v2.Storage
+// mixins:
+// - name: google.acl.v1.AccessControl
+//
+// The mixin construct implies that all methods in `AccessControl` are
+// also declared with same name and request/response types in
+// `Storage`. A documentation generator or annotation processor will
+// see the effective `Storage.GetAcl` method after inherting
+// documentation and annotations as follows:
+//
+// service Storage {
+// // Get the underlying ACL object.
+// rpc GetAcl(GetAclRequest) returns (Acl) {
+// option (google.api.http).get = "/v2/{resource=**}:getAcl";
+// }
+// ...
+// }
+//
+// Note how the version in the path pattern changed from `v1` to `v2`.
+//
+// If the `root` field in the mixin is specified, it should be a
+// relative path under which inherited HTTP paths are placed. Example:
+//
+// apis:
+// - name: google.storage.v2.Storage
+// mixins:
+// - name: google.acl.v1.AccessControl
+// root: acls
+//
+// This implies the following inherited HTTP annotation:
+//
+// service Storage {
+// // Get the underlying ACL object.
+// rpc GetAcl(GetAclRequest) returns (Acl) {
+// option (google.api.http).get = "/v2/acls/{resource=**}:getAcl";
+// }
+// ...
+// }
+message Mixin {
+ // The fully qualified name of the interface which is included.
+ string name = 1;
+
+ // If non-empty specifies a path under which inherited HTTP paths
+ // are rooted.
+ string root = 2;
+}
diff --git a/kong-versions/3.9.0.0/kong/spec/fixtures/grpc/google/protobuf/descriptor.proto b/kong-versions/3.9.0.0/kong/spec/fixtures/grpc/google/protobuf/descriptor.proto
new file mode 100644
index 00000000..25addc92
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/fixtures/grpc/google/protobuf/descriptor.proto
@@ -0,0 +1,883 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Author: kenton@google.com (Kenton Varda)
+// Based on original Protocol Buffers design by
+// Sanjay Ghemawat, Jeff Dean, and others.
+//
+// The messages in this file describe the definitions found in .proto files.
+// A valid .proto file can be translated directly to a FileDescriptorProto
+// without any other information (e.g. without reading its imports).
+
+
+syntax = "proto2";
+
+package google.protobuf;
+option go_package = "github.com/golang/protobuf/protoc-gen-go/descriptor;descriptor";
+option java_package = "com.google.protobuf";
+option java_outer_classname = "DescriptorProtos";
+option csharp_namespace = "Google.Protobuf.Reflection";
+option objc_class_prefix = "GPB";
+option cc_enable_arenas = true;
+
+// descriptor.proto must be optimized for speed because reflection-based
+// algorithms don't work during bootstrapping.
+option optimize_for = SPEED;
+
+// The protocol compiler can output a FileDescriptorSet containing the .proto
+// files it parses.
+message FileDescriptorSet {
+ repeated FileDescriptorProto file = 1;
+}
+
+// Describes a complete .proto file.
+message FileDescriptorProto {
+ optional string name = 1; // file name, relative to root of source tree
+ optional string package = 2; // e.g. "foo", "foo.bar", etc.
+
+ // Names of files imported by this file.
+ repeated string dependency = 3;
+ // Indexes of the public imported files in the dependency list above.
+ repeated int32 public_dependency = 10;
+ // Indexes of the weak imported files in the dependency list.
+ // For Google-internal migration only. Do not use.
+ repeated int32 weak_dependency = 11;
+
+ // All top-level definitions in this file.
+ repeated DescriptorProto message_type = 4;
+ repeated EnumDescriptorProto enum_type = 5;
+ repeated ServiceDescriptorProto service = 6;
+ repeated FieldDescriptorProto extension = 7;
+
+ optional FileOptions options = 8;
+
+ // This field contains optional information about the original source code.
+ // You may safely remove this entire field without harming runtime
+ // functionality of the descriptors -- the information is needed only by
+ // development tools.
+ optional SourceCodeInfo source_code_info = 9;
+
+ // The syntax of the proto file.
+ // The supported values are "proto2" and "proto3".
+ optional string syntax = 12;
+}
+
+// Describes a message type.
+message DescriptorProto {
+ optional string name = 1;
+
+ repeated FieldDescriptorProto field = 2;
+ repeated FieldDescriptorProto extension = 6;
+
+ repeated DescriptorProto nested_type = 3;
+ repeated EnumDescriptorProto enum_type = 4;
+
+ message ExtensionRange {
+ optional int32 start = 1;
+ optional int32 end = 2;
+
+ optional ExtensionRangeOptions options = 3;
+ }
+ repeated ExtensionRange extension_range = 5;
+
+ repeated OneofDescriptorProto oneof_decl = 8;
+
+ optional MessageOptions options = 7;
+
+ // Range of reserved tag numbers. Reserved tag numbers may not be used by
+ // fields or extension ranges in the same message. Reserved ranges may
+ // not overlap.
+ message ReservedRange {
+ optional int32 start = 1; // Inclusive.
+ optional int32 end = 2; // Exclusive.
+ }
+ repeated ReservedRange reserved_range = 9;
+ // Reserved field names, which may not be used by fields in the same message.
+ // A given name may only be reserved once.
+ repeated string reserved_name = 10;
+}
+
+message ExtensionRangeOptions {
+ // The parser stores options it doesn't recognize here. See above.
+ repeated UninterpretedOption uninterpreted_option = 999;
+
+ // Clients can define custom options in extensions of this message. See above.
+ extensions 1000 to max;
+}
+
+// Describes a field within a message.
+message FieldDescriptorProto {
+ enum Type {
+ // 0 is reserved for errors.
+ // Order is weird for historical reasons.
+ TYPE_DOUBLE = 1;
+ TYPE_FLOAT = 2;
+ // Not ZigZag encoded. Negative numbers take 10 bytes. Use TYPE_SINT64 if
+ // negative values are likely.
+ TYPE_INT64 = 3;
+ TYPE_UINT64 = 4;
+ // Not ZigZag encoded. Negative numbers take 10 bytes. Use TYPE_SINT32 if
+ // negative values are likely.
+ TYPE_INT32 = 5;
+ TYPE_FIXED64 = 6;
+ TYPE_FIXED32 = 7;
+ TYPE_BOOL = 8;
+ TYPE_STRING = 9;
+ // Tag-delimited aggregate.
+ // Group type is deprecated and not supported in proto3. However, Proto3
+ // implementations should still be able to parse the group wire format and
+ // treat group fields as unknown fields.
+ TYPE_GROUP = 10;
+ TYPE_MESSAGE = 11; // Length-delimited aggregate.
+
+ // New in version 2.
+ TYPE_BYTES = 12;
+ TYPE_UINT32 = 13;
+ TYPE_ENUM = 14;
+ TYPE_SFIXED32 = 15;
+ TYPE_SFIXED64 = 16;
+ TYPE_SINT32 = 17; // Uses ZigZag encoding.
+ TYPE_SINT64 = 18; // Uses ZigZag encoding.
+ };
+
+ enum Label {
+ // 0 is reserved for errors
+ LABEL_OPTIONAL = 1;
+ LABEL_REQUIRED = 2;
+ LABEL_REPEATED = 3;
+ };
+
+ optional string name = 1;
+ optional int32 number = 3;
+ optional Label label = 4;
+
+ // If type_name is set, this need not be set. If both this and type_name
+ // are set, this must be one of TYPE_ENUM, TYPE_MESSAGE or TYPE_GROUP.
+ optional Type type = 5;
+
+ // For message and enum types, this is the name of the type. If the name
+ // starts with a '.', it is fully-qualified. Otherwise, C++-like scoping
+ // rules are used to find the type (i.e. first the nested types within this
+ // message are searched, then within the parent, on up to the root
+ // namespace).
+ optional string type_name = 6;
+
+ // For extensions, this is the name of the type being extended. It is
+ // resolved in the same manner as type_name.
+ optional string extendee = 2;
+
+ // For numeric types, contains the original text representation of the value.
+ // For booleans, "true" or "false".
+ // For strings, contains the default text contents (not escaped in any way).
+ // For bytes, contains the C escaped value. All bytes >= 128 are escaped.
+ // TODO(kenton): Base-64 encode?
+ optional string default_value = 7;
+
+ // If set, gives the index of a oneof in the containing type's oneof_decl
+ // list. This field is a member of that oneof.
+ optional int32 oneof_index = 9;
+
+ // JSON name of this field. The value is set by protocol compiler. If the
+ // user has set a "json_name" option on this field, that option's value
+ // will be used. Otherwise, it's deduced from the field's name by converting
+ // it to camelCase.
+ optional string json_name = 10;
+
+ optional FieldOptions options = 8;
+}
+
+// Describes a oneof.
+message OneofDescriptorProto {
+ optional string name = 1;
+ optional OneofOptions options = 2;
+}
+
+// Describes an enum type.
+message EnumDescriptorProto {
+ optional string name = 1;
+
+ repeated EnumValueDescriptorProto value = 2;
+
+ optional EnumOptions options = 3;
+
+ // Range of reserved numeric values. Reserved values may not be used by
+ // entries in the same enum. Reserved ranges may not overlap.
+ //
+ // Note that this is distinct from DescriptorProto.ReservedRange in that it
+ // is inclusive such that it can appropriately represent the entire int32
+ // domain.
+ message EnumReservedRange {
+ optional int32 start = 1; // Inclusive.
+ optional int32 end = 2; // Inclusive.
+ }
+
+ // Range of reserved numeric values. Reserved numeric values may not be used
+ // by enum values in the same enum declaration. Reserved ranges may not
+ // overlap.
+ repeated EnumReservedRange reserved_range = 4;
+
+ // Reserved enum value names, which may not be reused. A given name may only
+ // be reserved once.
+ repeated string reserved_name = 5;
+}
+
+// Describes a value within an enum.
+message EnumValueDescriptorProto {
+ optional string name = 1;
+ optional int32 number = 2;
+
+ optional EnumValueOptions options = 3;
+}
+
+// Describes a service.
+message ServiceDescriptorProto {
+ optional string name = 1;
+ repeated MethodDescriptorProto method = 2;
+
+ optional ServiceOptions options = 3;
+}
+
+// Describes a method of a service.
+message MethodDescriptorProto {
+ optional string name = 1;
+
+ // Input and output type names. These are resolved in the same way as
+ // FieldDescriptorProto.type_name, but must refer to a message type.
+ optional string input_type = 2;
+ optional string output_type = 3;
+
+ optional MethodOptions options = 4;
+
+ // Identifies if client streams multiple client messages
+ optional bool client_streaming = 5 [default=false];
+ // Identifies if server streams multiple server messages
+ optional bool server_streaming = 6 [default=false];
+}
+
+
+// ===================================================================
+// Options
+
+// Each of the definitions above may have "options" attached. These are
+// just annotations which may cause code to be generated slightly differently
+// or may contain hints for code that manipulates protocol messages.
+//
+// Clients may define custom options as extensions of the *Options messages.
+// These extensions may not yet be known at parsing time, so the parser cannot
+// store the values in them. Instead it stores them in a field in the *Options
+// message called uninterpreted_option. This field must have the same name
+// across all *Options messages. We then use this field to populate the
+// extensions when we build a descriptor, at which point all protos have been
+// parsed and so all extensions are known.
+//
+// Extension numbers for custom options may be chosen as follows:
+// * For options which will only be used within a single application or
+// organization, or for experimental options, use field numbers 50000
+// through 99999. It is up to you to ensure that you do not use the
+// same number for multiple options.
+// * For options which will be published and used publicly by multiple
+// independent entities, e-mail protobuf-global-extension-registry@google.com
+// to reserve extension numbers. Simply provide your project name (e.g.
+// Objective-C plugin) and your project website (if available) -- there's no
+// need to explain how you intend to use them. Usually you only need one
+// extension number. You can declare multiple options with only one extension
+// number by putting them in a sub-message. See the Custom Options section of
+// the docs for examples:
+// https://developers.google.com/protocol-buffers/docs/proto#options
+// If this turns out to be popular, a web service will be set up
+// to automatically assign option numbers.
+
+
+message FileOptions {
+
+ // Sets the Java package where classes generated from this .proto will be
+ // placed. By default, the proto package is used, but this is often
+ // inappropriate because proto packages do not normally start with backwards
+ // domain names.
+ optional string java_package = 1;
+
+
+ // If set, all the classes from the .proto file are wrapped in a single
+ // outer class with the given name. This applies to both Proto1
+ // (equivalent to the old "--one_java_file" option) and Proto2 (where
+ // a .proto always translates to a single class, but you may want to
+ // explicitly choose the class name).
+ optional string java_outer_classname = 8;
+
+ // If set true, then the Java code generator will generate a separate .java
+ // file for each top-level message, enum, and service defined in the .proto
+ // file. Thus, these types will *not* be nested inside the outer class
+ // named by java_outer_classname. However, the outer class will still be
+ // generated to contain the file's getDescriptor() method as well as any
+ // top-level extensions defined in the file.
+ optional bool java_multiple_files = 10 [default=false];
+
+ // This option does nothing.
+ optional bool java_generate_equals_and_hash = 20 [deprecated=true];
+
+ // If set true, then the Java2 code generator will generate code that
+ // throws an exception whenever an attempt is made to assign a non-UTF-8
+ // byte sequence to a string field.
+ // Message reflection will do the same.
+ // However, an extension field still accepts non-UTF-8 byte sequences.
+ // This option has no effect on when used with the lite runtime.
+ optional bool java_string_check_utf8 = 27 [default=false];
+
+
+ // Generated classes can be optimized for speed or code size.
+ enum OptimizeMode {
+ SPEED = 1; // Generate complete code for parsing, serialization,
+ // etc.
+ CODE_SIZE = 2; // Use ReflectionOps to implement these methods.
+ LITE_RUNTIME = 3; // Generate code using MessageLite and the lite runtime.
+ }
+ optional OptimizeMode optimize_for = 9 [default=SPEED];
+
+ // Sets the Go package where structs generated from this .proto will be
+ // placed. If omitted, the Go package will be derived from the following:
+ // - The basename of the package import path, if provided.
+ // - Otherwise, the package statement in the .proto file, if present.
+ // - Otherwise, the basename of the .proto file, without extension.
+ optional string go_package = 11;
+
+
+
+ // Should generic services be generated in each language? "Generic" services
+ // are not specific to any particular RPC system. They are generated by the
+ // main code generators in each language (without additional plugins).
+ // Generic services were the only kind of service generation supported by
+ // early versions of google.protobuf.
+ //
+ // Generic services are now considered deprecated in favor of using plugins
+ // that generate code specific to your particular RPC system. Therefore,
+ // these default to false. Old code which depends on generic services should
+ // explicitly set them to true.
+ optional bool cc_generic_services = 16 [default=false];
+ optional bool java_generic_services = 17 [default=false];
+ optional bool py_generic_services = 18 [default=false];
+ optional bool php_generic_services = 42 [default=false];
+
+ // Is this file deprecated?
+ // Depending on the target platform, this can emit Deprecated annotations
+ // for everything in the file, or it will be completely ignored; in the very
+ // least, this is a formalization for deprecating files.
+ optional bool deprecated = 23 [default=false];
+
+ // Enables the use of arenas for the proto messages in this file. This applies
+ // only to generated classes for C++.
+ optional bool cc_enable_arenas = 31 [default=false];
+
+
+ // Sets the objective c class prefix which is prepended to all objective c
+ // generated classes from this .proto. There is no default.
+ optional string objc_class_prefix = 36;
+
+ // Namespace for generated classes; defaults to the package.
+ optional string csharp_namespace = 37;
+
+ // By default Swift generators will take the proto package and CamelCase it
+ // replacing '.' with underscore and use that to prefix the types/symbols
+ // defined. When this options is provided, they will use this value instead
+ // to prefix the types/symbols defined.
+ optional string swift_prefix = 39;
+
+ // Sets the php class prefix which is prepended to all php generated classes
+ // from this .proto. Default is empty.
+ optional string php_class_prefix = 40;
+
+ // Use this option to change the namespace of php generated classes. Default
+ // is empty. When this option is empty, the package name will be used for
+ // determining the namespace.
+ optional string php_namespace = 41;
+
+
+ // Use this option to change the namespace of php generated metadata classes.
+ // Default is empty. When this option is empty, the proto file name will be used
+ // for determining the namespace.
+ optional string php_metadata_namespace = 44;
+
+ // Use this option to change the package of ruby generated classes. Default
+ // is empty. When this option is not set, the package name will be used for
+ // determining the ruby package.
+ optional string ruby_package = 45;
+
+ // The parser stores options it doesn't recognize here.
+ // See the documentation for the "Options" section above.
+ repeated UninterpretedOption uninterpreted_option = 999;
+
+ // Clients can define custom options in extensions of this message.
+ // See the documentation for the "Options" section above.
+ extensions 1000 to max;
+
+ reserved 38;
+}
+
+message MessageOptions {
+ // Set true to use the old proto1 MessageSet wire format for extensions.
+ // This is provided for backwards-compatibility with the MessageSet wire
+ // format. You should not use this for any other reason: It's less
+ // efficient, has fewer features, and is more complicated.
+ //
+ // The message must be defined exactly as follows:
+ // message Foo {
+ // option message_set_wire_format = true;
+ // extensions 4 to max;
+ // }
+ // Note that the message cannot have any defined fields; MessageSets only
+ // have extensions.
+ //
+ // All extensions of your type must be singular messages; e.g. they cannot
+ // be int32s, enums, or repeated messages.
+ //
+ // Because this is an option, the above two restrictions are not enforced by
+ // the protocol compiler.
+ optional bool message_set_wire_format = 1 [default=false];
+
+ // Disables the generation of the standard "descriptor()" accessor, which can
+ // conflict with a field of the same name. This is meant to make migration
+ // from proto1 easier; new code should avoid fields named "descriptor".
+ optional bool no_standard_descriptor_accessor = 2 [default=false];
+
+ // Is this message deprecated?
+ // Depending on the target platform, this can emit Deprecated annotations
+ // for the message, or it will be completely ignored; in the very least,
+ // this is a formalization for deprecating messages.
+ optional bool deprecated = 3 [default=false];
+
+ // Whether the message is an automatically generated map entry type for the
+ // maps field.
+ //
+ // For maps fields:
+ // map map_field = 1;
+ // The parsed descriptor looks like:
+ // message MapFieldEntry {
+ // option map_entry = true;
+ // optional KeyType key = 1;
+ // optional ValueType value = 2;
+ // }
+ // repeated MapFieldEntry map_field = 1;
+ //
+ // Implementations may choose not to generate the map_entry=true message, but
+ // use a native map in the target language to hold the keys and values.
+ // The reflection APIs in such implementations still need to work as
+ // if the field is a repeated message field.
+ //
+ // NOTE: Do not set the option in .proto files. Always use the maps syntax
+ // instead. The option should only be implicitly set by the proto compiler
+ // parser.
+ optional bool map_entry = 7;
+
+ reserved 8; // javalite_serializable
+ reserved 9; // javanano_as_lite
+
+ // The parser stores options it doesn't recognize here. See above.
+ repeated UninterpretedOption uninterpreted_option = 999;
+
+ // Clients can define custom options in extensions of this message. See above.
+ extensions 1000 to max;
+}
+
+message FieldOptions {
+ // The ctype option instructs the C++ code generator to use a different
+ // representation of the field than it normally would. See the specific
+ // options below. This option is not yet implemented in the open source
+ // release -- sorry, we'll try to include it in a future version!
+ optional CType ctype = 1 [default = STRING];
+ enum CType {
+ // Default mode.
+ STRING = 0;
+
+ CORD = 1;
+
+ STRING_PIECE = 2;
+ }
+ // The packed option can be enabled for repeated primitive fields to enable
+ // a more efficient representation on the wire. Rather than repeatedly
+ // writing the tag and type for each element, the entire array is encoded as
+ // a single length-delimited blob. In proto3, only explicit setting it to
+ // false will avoid using packed encoding.
+ optional bool packed = 2;
+
+ // The jstype option determines the JavaScript type used for values of the
+ // field. The option is permitted only for 64 bit integral and fixed types
+ // (int64, uint64, sint64, fixed64, sfixed64). A field with jstype JS_STRING
+ // is represented as JavaScript string, which avoids loss of precision that
+ // can happen when a large value is converted to a floating point JavaScript.
+ // Specifying JS_NUMBER for the jstype causes the generated JavaScript code to
+ // use the JavaScript "number" type. The behavior of the default option
+ // JS_NORMAL is implementation dependent.
+ //
+ // This option is an enum to permit additional types to be added, e.g.
+ // goog.math.Integer.
+ optional JSType jstype = 6 [default = JS_NORMAL];
+ enum JSType {
+ // Use the default type.
+ JS_NORMAL = 0;
+
+ // Use JavaScript strings.
+ JS_STRING = 1;
+
+ // Use JavaScript numbers.
+ JS_NUMBER = 2;
+ }
+
+ // Should this field be parsed lazily? Lazy applies only to message-type
+ // fields. It means that when the outer message is initially parsed, the
+ // inner message's contents will not be parsed but instead stored in encoded
+ // form. The inner message will actually be parsed when it is first accessed.
+ //
+ // This is only a hint. Implementations are free to choose whether to use
+ // eager or lazy parsing regardless of the value of this option. However,
+ // setting this option true suggests that the protocol author believes that
+ // using lazy parsing on this field is worth the additional bookkeeping
+ // overhead typically needed to implement it.
+ //
+ // This option does not affect the public interface of any generated code;
+ // all method signatures remain the same. Furthermore, thread-safety of the
+ // interface is not affected by this option; const methods remain safe to
+ // call from multiple threads concurrently, while non-const methods continue
+ // to require exclusive access.
+ //
+ //
+ // Note that implementations may choose not to check required fields within
+ // a lazy sub-message. That is, calling IsInitialized() on the outer message
+ // may return true even if the inner message has missing required fields.
+ // This is necessary because otherwise the inner message would have to be
+ // parsed in order to perform the check, defeating the purpose of lazy
+ // parsing. An implementation which chooses not to check required fields
+ // must be consistent about it. That is, for any particular sub-message, the
+ // implementation must either *always* check its required fields, or *never*
+ // check its required fields, regardless of whether or not the message has
+ // been parsed.
+ optional bool lazy = 5 [default=false];
+
+ // Is this field deprecated?
+ // Depending on the target platform, this can emit Deprecated annotations
+ // for accessors, or it will be completely ignored; in the very least, this
+ // is a formalization for deprecating fields.
+ optional bool deprecated = 3 [default=false];
+
+ // For Google-internal migration only. Do not use.
+ optional bool weak = 10 [default=false];
+
+
+ // The parser stores options it doesn't recognize here. See above.
+ repeated UninterpretedOption uninterpreted_option = 999;
+
+ // Clients can define custom options in extensions of this message. See above.
+ extensions 1000 to max;
+
+ reserved 4; // removed jtype
+}
+
+message OneofOptions {
+ // The parser stores options it doesn't recognize here. See above.
+ repeated UninterpretedOption uninterpreted_option = 999;
+
+ // Clients can define custom options in extensions of this message. See above.
+ extensions 1000 to max;
+}
+
+message EnumOptions {
+
+ // Set this option to true to allow mapping different tag names to the same
+ // value.
+ optional bool allow_alias = 2;
+
+ // Is this enum deprecated?
+ // Depending on the target platform, this can emit Deprecated annotations
+ // for the enum, or it will be completely ignored; in the very least, this
+ // is a formalization for deprecating enums.
+ optional bool deprecated = 3 [default=false];
+
+ reserved 5; // javanano_as_lite
+
+ // The parser stores options it doesn't recognize here. See above.
+ repeated UninterpretedOption uninterpreted_option = 999;
+
+ // Clients can define custom options in extensions of this message. See above.
+ extensions 1000 to max;
+}
+
+message EnumValueOptions {
+ // Is this enum value deprecated?
+ // Depending on the target platform, this can emit Deprecated annotations
+ // for the enum value, or it will be completely ignored; in the very least,
+ // this is a formalization for deprecating enum values.
+ optional bool deprecated = 1 [default=false];
+
+ // The parser stores options it doesn't recognize here. See above.
+ repeated UninterpretedOption uninterpreted_option = 999;
+
+ // Clients can define custom options in extensions of this message. See above.
+ extensions 1000 to max;
+}
+
+message ServiceOptions {
+
+ // Note: Field numbers 1 through 32 are reserved for Google's internal RPC
+ // framework. We apologize for hoarding these numbers to ourselves, but
+ // we were already using them long before we decided to release Protocol
+ // Buffers.
+
+ // Is this service deprecated?
+ // Depending on the target platform, this can emit Deprecated annotations
+ // for the service, or it will be completely ignored; in the very least,
+ // this is a formalization for deprecating services.
+ optional bool deprecated = 33 [default=false];
+
+ // The parser stores options it doesn't recognize here. See above.
+ repeated UninterpretedOption uninterpreted_option = 999;
+
+ // Clients can define custom options in extensions of this message. See above.
+ extensions 1000 to max;
+}
+
+message MethodOptions {
+
+ // Note: Field numbers 1 through 32 are reserved for Google's internal RPC
+ // framework. We apologize for hoarding these numbers to ourselves, but
+ // we were already using them long before we decided to release Protocol
+ // Buffers.
+
+ // Is this method deprecated?
+ // Depending on the target platform, this can emit Deprecated annotations
+ // for the method, or it will be completely ignored; in the very least,
+ // this is a formalization for deprecating methods.
+ optional bool deprecated = 33 [default=false];
+
+ // Is this method side-effect-free (or safe in HTTP parlance), or idempotent,
+ // or neither? HTTP based RPC implementation may choose GET verb for safe
+ // methods, and PUT verb for idempotent methods instead of the default POST.
+ enum IdempotencyLevel {
+ IDEMPOTENCY_UNKNOWN = 0;
+ NO_SIDE_EFFECTS = 1; // implies idempotent
+ IDEMPOTENT = 2; // idempotent, but may have side effects
+ }
+ optional IdempotencyLevel idempotency_level =
+ 34 [default=IDEMPOTENCY_UNKNOWN];
+
+ // The parser stores options it doesn't recognize here. See above.
+ repeated UninterpretedOption uninterpreted_option = 999;
+
+ // Clients can define custom options in extensions of this message. See above.
+ extensions 1000 to max;
+}
+
+
+// A message representing a option the parser does not recognize. This only
+// appears in options protos created by the compiler::Parser class.
+// DescriptorPool resolves these when building Descriptor objects. Therefore,
+// options protos in descriptor objects (e.g. returned by Descriptor::options(),
+// or produced by Descriptor::CopyTo()) will never have UninterpretedOptions
+// in them.
+message UninterpretedOption {
+ // The name of the uninterpreted option. Each string represents a segment in
+ // a dot-separated name. is_extension is true iff a segment represents an
+ // extension (denoted with parentheses in options specs in .proto files).
+ // E.g.,{ ["foo", false], ["bar.baz", true], ["qux", false] } represents
+ // "foo.(bar.baz).qux".
+ message NamePart {
+ required string name_part = 1;
+ required bool is_extension = 2;
+ }
+ repeated NamePart name = 2;
+
+ // The value of the uninterpreted option, in whatever type the tokenizer
+ // identified it as during parsing. Exactly one of these should be set.
+ optional string identifier_value = 3;
+ optional uint64 positive_int_value = 4;
+ optional int64 negative_int_value = 5;
+ optional double double_value = 6;
+ optional bytes string_value = 7;
+ optional string aggregate_value = 8;
+}
+
+// ===================================================================
+// Optional source code info
+
+// Encapsulates information about the original source file from which a
+// FileDescriptorProto was generated.
+message SourceCodeInfo {
+ // A Location identifies a piece of source code in a .proto file which
+ // corresponds to a particular definition. This information is intended
+ // to be useful to IDEs, code indexers, documentation generators, and similar
+ // tools.
+ //
+ // For example, say we have a file like:
+ // message Foo {
+ // optional string foo = 1;
+ // }
+ // Let's look at just the field definition:
+ // optional string foo = 1;
+ // ^ ^^ ^^ ^ ^^^
+ // a bc de f ghi
+ // We have the following locations:
+ // span path represents
+ // [a,i) [ 4, 0, 2, 0 ] The whole field definition.
+ // [a,b) [ 4, 0, 2, 0, 4 ] The label (optional).
+ // [c,d) [ 4, 0, 2, 0, 5 ] The type (string).
+ // [e,f) [ 4, 0, 2, 0, 1 ] The name (foo).
+ // [g,h) [ 4, 0, 2, 0, 3 ] The number (1).
+ //
+ // Notes:
+ // - A location may refer to a repeated field itself (i.e. not to any
+ // particular index within it). This is used whenever a set of elements are
+ // logically enclosed in a single code segment. For example, an entire
+ // extend block (possibly containing multiple extension definitions) will
+ // have an outer location whose path refers to the "extensions" repeated
+ // field without an index.
+ // - Multiple locations may have the same path. This happens when a single
+ // logical declaration is spread out across multiple places. The most
+ // obvious example is the "extend" block again -- there may be multiple
+ // extend blocks in the same scope, each of which will have the same path.
+ // - A location's span is not always a subset of its parent's span. For
+ // example, the "extendee" of an extension declaration appears at the
+ // beginning of the "extend" block and is shared by all extensions within
+ // the block.
+ // - Just because a location's span is a subset of some other location's span
+ // does not mean that it is a descendent. For example, a "group" defines
+ // both a type and a field in a single declaration. Thus, the locations
+ // corresponding to the type and field and their components will overlap.
+ // - Code which tries to interpret locations should probably be designed to
+ // ignore those that it doesn't understand, as more types of locations could
+ // be recorded in the future.
+ repeated Location location = 1;
+ message Location {
+ // Identifies which part of the FileDescriptorProto was defined at this
+ // location.
+ //
+ // Each element is a field number or an index. They form a path from
+ // the root FileDescriptorProto to the place where the definition. For
+ // example, this path:
+ // [ 4, 3, 2, 7, 1 ]
+ // refers to:
+ // file.message_type(3) // 4, 3
+ // .field(7) // 2, 7
+ // .name() // 1
+ // This is because FileDescriptorProto.message_type has field number 4:
+ // repeated DescriptorProto message_type = 4;
+ // and DescriptorProto.field has field number 2:
+ // repeated FieldDescriptorProto field = 2;
+ // and FieldDescriptorProto.name has field number 1:
+ // optional string name = 1;
+ //
+ // Thus, the above path gives the location of a field name. If we removed
+ // the last element:
+ // [ 4, 3, 2, 7 ]
+ // this path refers to the whole field declaration (from the beginning
+ // of the label to the terminating semicolon).
+ repeated int32 path = 1 [packed=true];
+
+ // Always has exactly three or four elements: start line, start column,
+ // end line (optional, otherwise assumed same as start line), end column.
+ // These are packed into a single field for efficiency. Note that line
+ // and column numbers are zero-based -- typically you will want to add
+ // 1 to each before displaying to a user.
+ repeated int32 span = 2 [packed=true];
+
+ // If this SourceCodeInfo represents a complete declaration, these are any
+ // comments appearing before and after the declaration which appear to be
+ // attached to the declaration.
+ //
+ // A series of line comments appearing on consecutive lines, with no other
+ // tokens appearing on those lines, will be treated as a single comment.
+ //
+ // leading_detached_comments will keep paragraphs of comments that appear
+ // before (but not connected to) the current element. Each paragraph,
+ // separated by empty lines, will be one comment element in the repeated
+ // field.
+ //
+ // Only the comment content is provided; comment markers (e.g. //) are
+ // stripped out. For block comments, leading whitespace and an asterisk
+ // will be stripped from the beginning of each line other than the first.
+ // Newlines are included in the output.
+ //
+ // Examples:
+ //
+ // optional int32 foo = 1; // Comment attached to foo.
+ // // Comment attached to bar.
+ // optional int32 bar = 2;
+ //
+ // optional string baz = 3;
+ // // Comment attached to baz.
+ // // Another line attached to baz.
+ //
+ // // Comment attached to qux.
+ // //
+ // // Another line attached to qux.
+ // optional double qux = 4;
+ //
+ // // Detached comment for corge. This is not leading or trailing comments
+ // // to qux or corge because there are blank lines separating it from
+ // // both.
+ //
+ // // Detached comment for corge paragraph 2.
+ //
+ // optional string corge = 5;
+ // /* Block comment attached
+ // * to corge. Leading asterisks
+ // * will be removed. */
+ // /* Block comment attached to
+ // * grault. */
+ // optional int32 grault = 6;
+ //
+ // // ignored detached comments.
+ optional string leading_comments = 3;
+ optional string trailing_comments = 4;
+ repeated string leading_detached_comments = 6;
+ }
+}
+
+// Describes the relationship between generated code and its original source
+// file. A GeneratedCodeInfo message is associated with only one generated
+// source file, but may contain references to different source .proto files.
+message GeneratedCodeInfo {
+ // An Annotation connects some span of text in generated code to an element
+ // of its generating .proto file.
+ repeated Annotation annotation = 1;
+ message Annotation {
+ // Identifies the element in the original source .proto file. This field
+ // is formatted the same as SourceCodeInfo.Location.path.
+ repeated int32 path = 1 [packed=true];
+
+ // Identifies the filesystem path to the original source .proto.
+ optional string source_file = 2;
+
+ // Identifies the starting offset in bytes in the generated code
+ // that relates to the identified object.
+ optional int32 begin = 3;
+
+ // Identifies the ending offset in bytes in the generated code that
+ // relates to the identified offset. The end offset should be one past
+ // the last relevant byte (so the length of the text = end - begin).
+ optional int32 end = 4;
+ }
+}
diff --git a/kong-versions/3.9.0.0/kong/spec/fixtures/grpc/google/protobuf/duration.proto b/kong-versions/3.9.0.0/kong/spec/fixtures/grpc/google/protobuf/duration.proto
new file mode 100644
index 00000000..975fce41
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/fixtures/grpc/google/protobuf/duration.proto
@@ -0,0 +1,117 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+syntax = "proto3";
+
+package google.protobuf;
+
+option csharp_namespace = "Google.Protobuf.WellKnownTypes";
+option cc_enable_arenas = true;
+option go_package = "github.com/golang/protobuf/ptypes/duration";
+option java_package = "com.google.protobuf";
+option java_outer_classname = "DurationProto";
+option java_multiple_files = true;
+option objc_class_prefix = "GPB";
+
+// A Duration represents a signed, fixed-length span of time represented
+// as a count of seconds and fractions of seconds at nanosecond
+// resolution. It is independent of any calendar and concepts like "day"
+// or "month". It is related to Timestamp in that the difference between
+// two Timestamp values is a Duration and it can be added or subtracted
+// from a Timestamp. Range is approximately +-10,000 years.
+//
+// # Examples
+//
+// Example 1: Compute Duration from two Timestamps in pseudo code.
+//
+// Timestamp start = ...;
+// Timestamp end = ...;
+// Duration duration = ...;
+//
+// duration.seconds = end.seconds - start.seconds;
+// duration.nanos = end.nanos - start.nanos;
+//
+// if (duration.seconds < 0 && duration.nanos > 0) {
+// duration.seconds += 1;
+// duration.nanos -= 1000000000;
+// } else if (durations.seconds > 0 && duration.nanos < 0) {
+// duration.seconds -= 1;
+// duration.nanos += 1000000000;
+// }
+//
+// Example 2: Compute Timestamp from Timestamp + Duration in pseudo code.
+//
+// Timestamp start = ...;
+// Duration duration = ...;
+// Timestamp end = ...;
+//
+// end.seconds = start.seconds + duration.seconds;
+// end.nanos = start.nanos + duration.nanos;
+//
+// if (end.nanos < 0) {
+// end.seconds -= 1;
+// end.nanos += 1000000000;
+// } else if (end.nanos >= 1000000000) {
+// end.seconds += 1;
+// end.nanos -= 1000000000;
+// }
+//
+// Example 3: Compute Duration from datetime.timedelta in Python.
+//
+// td = datetime.timedelta(days=3, minutes=10)
+// duration = Duration()
+// duration.FromTimedelta(td)
+//
+// # JSON Mapping
+//
+// In JSON format, the Duration type is encoded as a string rather than an
+// object, where the string ends in the suffix "s" (indicating seconds) and
+// is preceded by the number of seconds, with nanoseconds expressed as
+// fractional seconds. For example, 3 seconds with 0 nanoseconds should be
+// encoded in JSON format as "3s", while 3 seconds and 1 nanosecond should
+// be expressed in JSON format as "3.000000001s", and 3 seconds and 1
+// microsecond should be expressed in JSON format as "3.000001s".
+//
+//
+message Duration {
+
+ // Signed seconds of the span of time. Must be from -315,576,000,000
+ // to +315,576,000,000 inclusive. Note: these bounds are computed from:
+ // 60 sec/min * 60 min/hr * 24 hr/day * 365.25 days/year * 10000 years
+ int64 seconds = 1;
+
+ // Signed fractions of a second at nanosecond resolution of the span
+ // of time. Durations less than one second are represented with a 0
+ // `seconds` field and a positive or negative `nanos` field. For durations
+ // of one second or more, a non-zero value for the `nanos` field must be
+ // of the same sign as the `seconds` field. Must be from -999,999,999
+ // to +999,999,999 inclusive.
+ int32 nanos = 2;
+}
diff --git a/kong-versions/3.9.0.0/kong/spec/fixtures/grpc/google/protobuf/empty.proto b/kong-versions/3.9.0.0/kong/spec/fixtures/grpc/google/protobuf/empty.proto
new file mode 100644
index 00000000..03cacd23
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/fixtures/grpc/google/protobuf/empty.proto
@@ -0,0 +1,52 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+syntax = "proto3";
+
+package google.protobuf;
+
+option csharp_namespace = "Google.Protobuf.WellKnownTypes";
+option go_package = "github.com/golang/protobuf/ptypes/empty";
+option java_package = "com.google.protobuf";
+option java_outer_classname = "EmptyProto";
+option java_multiple_files = true;
+option objc_class_prefix = "GPB";
+option cc_enable_arenas = true;
+
+// A generic empty message that you can re-use to avoid defining duplicated
+// empty messages in your APIs. A typical example is to use it as the request
+// or the response type of an API method. For instance:
+//
+// service Foo {
+// rpc Bar(google.protobuf.Empty) returns (google.protobuf.Empty);
+// }
+//
+// The JSON representation for `Empty` is empty JSON object `{}`.
+message Empty {}
diff --git a/kong-versions/3.9.0.0/kong/spec/fixtures/grpc/google/protobuf/field_mask.proto b/kong-versions/3.9.0.0/kong/spec/fixtures/grpc/google/protobuf/field_mask.proto
new file mode 100644
index 00000000..76e09f39
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/fixtures/grpc/google/protobuf/field_mask.proto
@@ -0,0 +1,252 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+syntax = "proto3";
+
+package google.protobuf;
+
+option csharp_namespace = "Google.Protobuf.WellKnownTypes";
+option java_package = "com.google.protobuf";
+option java_outer_classname = "FieldMaskProto";
+option java_multiple_files = true;
+option objc_class_prefix = "GPB";
+option go_package = "google.golang.org/genproto/protobuf/field_mask;field_mask";
+
+// `FieldMask` represents a set of symbolic field paths, for example:
+//
+// paths: "f.a"
+// paths: "f.b.d"
+//
+// Here `f` represents a field in some root message, `a` and `b`
+// fields in the message found in `f`, and `d` a field found in the
+// message in `f.b`.
+//
+// Field masks are used to specify a subset of fields that should be
+// returned by a get operation or modified by an update operation.
+// Field masks also have a custom JSON encoding (see below).
+//
+// # Field Masks in Projections
+//
+// When used in the context of a projection, a response message or
+// sub-message is filtered by the API to only contain those fields as
+// specified in the mask. For example, if the mask in the previous
+// example is applied to a response message as follows:
+//
+// f {
+// a : 22
+// b {
+// d : 1
+// x : 2
+// }
+// y : 13
+// }
+// z: 8
+//
+// The result will not contain specific values for fields x,y and z
+// (their value will be set to the default, and omitted in proto text
+// output):
+//
+//
+// f {
+// a : 22
+// b {
+// d : 1
+// }
+// }
+//
+// A repeated field is not allowed except at the last position of a
+// paths string.
+//
+// If a FieldMask object is not present in a get operation, the
+// operation applies to all fields (as if a FieldMask of all fields
+// had been specified).
+//
+// Note that a field mask does not necessarily apply to the
+// top-level response message. In case of a REST get operation, the
+// field mask applies directly to the response, but in case of a REST
+// list operation, the mask instead applies to each individual message
+// in the returned resource list. In case of a REST custom method,
+// other definitions may be used. Where the mask applies will be
+// clearly documented together with its declaration in the API. In
+// any case, the effect on the returned resource/resources is required
+// behavior for APIs.
+//
+// # Field Masks in Update Operations
+//
+// A field mask in update operations specifies which fields of the
+// targeted resource are going to be updated. The API is required
+// to only change the values of the fields as specified in the mask
+// and leave the others untouched. If a resource is passed in to
+// describe the updated values, the API ignores the values of all
+// fields not covered by the mask.
+//
+// If a repeated field is specified for an update operation, the existing
+// repeated values in the target resource will be overwritten by the new values.
+// Note that a repeated field is only allowed in the last position of a `paths`
+// string.
+//
+// If a sub-message is specified in the last position of the field mask for an
+// update operation, then the existing sub-message in the target resource is
+// overwritten. Given the target message:
+//
+// f {
+// b {
+// d : 1
+// x : 2
+// }
+// c : 1
+// }
+//
+// And an update message:
+//
+// f {
+// b {
+// d : 10
+// }
+// }
+//
+// then if the field mask is:
+//
+// paths: "f.b"
+//
+// then the result will be:
+//
+// f {
+// b {
+// d : 10
+// }
+// c : 1
+// }
+//
+// However, if the update mask was:
+//
+// paths: "f.b.d"
+//
+// then the result would be:
+//
+// f {
+// b {
+// d : 10
+// x : 2
+// }
+// c : 1
+// }
+//
+// In order to reset a field's value to the default, the field must
+// be in the mask and set to the default value in the provided resource.
+// Hence, in order to reset all fields of a resource, provide a default
+// instance of the resource and set all fields in the mask, or do
+// not provide a mask as described below.
+//
+// If a field mask is not present on update, the operation applies to
+// all fields (as if a field mask of all fields has been specified).
+// Note that in the presence of schema evolution, this may mean that
+// fields the client does not know and has therefore not filled into
+// the request will be reset to their default. If this is unwanted
+// behavior, a specific service may require a client to always specify
+// a field mask, producing an error if not.
+//
+// As with get operations, the location of the resource which
+// describes the updated values in the request message depends on the
+// operation kind. In any case, the effect of the field mask is
+// required to be honored by the API.
+//
+// ## Considerations for HTTP REST
+//
+// The HTTP kind of an update operation which uses a field mask must
+// be set to PATCH instead of PUT in order to satisfy HTTP semantics
+// (PUT must only be used for full updates).
+//
+// # JSON Encoding of Field Masks
+//
+// In JSON, a field mask is encoded as a single string where paths are
+// separated by a comma. Fields name in each path are converted
+// to/from lower-camel naming conventions.
+//
+// As an example, consider the following message declarations:
+//
+// message Profile {
+// User user = 1;
+// Photo photo = 2;
+// }
+// message User {
+// string display_name = 1;
+// string address = 2;
+// }
+//
+// In proto a field mask for `Profile` may look as such:
+//
+// mask {
+// paths: "user.display_name"
+// paths: "photo"
+// }
+//
+// In JSON, the same mask is represented as below:
+//
+// {
+// mask: "user.displayName,photo"
+// }
+//
+// # Field Masks and Oneof Fields
+//
+// Field masks treat fields in oneofs just as regular fields. Consider the
+// following message:
+//
+// message SampleMessage {
+// oneof test_oneof {
+// string name = 4;
+// SubMessage sub_message = 9;
+// }
+// }
+//
+// The field mask can be:
+//
+// mask {
+// paths: "name"
+// }
+//
+// Or:
+//
+// mask {
+// paths: "sub_message"
+// }
+//
+// Note that oneof type names ("test_oneof" in this case) cannot be used in
+// paths.
+//
+// ## Field Mask Verification
+//
+// The implementation of any API method which has a FieldMask type field in the
+// request should verify the included field paths, and return an
+// `INVALID_ARGUMENT` error if any path is duplicated or unmappable.
+message FieldMask {
+ // The set of field mask paths.
+ repeated string paths = 1;
+}
diff --git a/kong-versions/3.9.0.0/kong/spec/fixtures/grpc/google/protobuf/source_context.proto b/kong-versions/3.9.0.0/kong/spec/fixtures/grpc/google/protobuf/source_context.proto
new file mode 100644
index 00000000..f3b2c966
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/fixtures/grpc/google/protobuf/source_context.proto
@@ -0,0 +1,48 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+syntax = "proto3";
+
+package google.protobuf;
+
+option csharp_namespace = "Google.Protobuf.WellKnownTypes";
+option java_package = "com.google.protobuf";
+option java_outer_classname = "SourceContextProto";
+option java_multiple_files = true;
+option objc_class_prefix = "GPB";
+option go_package = "google.golang.org/genproto/protobuf/source_context;source_context";
+
+// `SourceContext` represents information about the source of a
+// protobuf element, like the file in which it is defined.
+message SourceContext {
+ // The path-qualified name of the .proto file that contained the associated
+ // protobuf element. For example: `"google/protobuf/source_context.proto"`.
+ string file_name = 1;
+}
diff --git a/kong-versions/3.9.0.0/kong/spec/fixtures/grpc/google/protobuf/struct.proto b/kong-versions/3.9.0.0/kong/spec/fixtures/grpc/google/protobuf/struct.proto
new file mode 100644
index 00000000..7d7808e7
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/fixtures/grpc/google/protobuf/struct.proto
@@ -0,0 +1,96 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+syntax = "proto3";
+
+package google.protobuf;
+
+option csharp_namespace = "Google.Protobuf.WellKnownTypes";
+option cc_enable_arenas = true;
+option go_package = "github.com/golang/protobuf/ptypes/struct;structpb";
+option java_package = "com.google.protobuf";
+option java_outer_classname = "StructProto";
+option java_multiple_files = true;
+option objc_class_prefix = "GPB";
+
+
+// `Struct` represents a structured data value, consisting of fields
+// which map to dynamically typed values. In some languages, `Struct`
+// might be supported by a native representation. For example, in
+// scripting languages like JS a struct is represented as an
+// object. The details of that representation are described together
+// with the proto support for the language.
+//
+// The JSON representation for `Struct` is JSON object.
+message Struct {
+ // Unordered map of dynamically typed values.
+ map fields = 1;
+}
+
+// `Value` represents a dynamically typed value which can be either
+// null, a number, a string, a boolean, a recursive struct value, or a
+// list of values. A producer of value is expected to set one of that
+// variants, absence of any variant indicates an error.
+//
+// The JSON representation for `Value` is JSON value.
+message Value {
+ // The kind of value.
+ oneof kind {
+ // Represents a null value.
+ NullValue null_value = 1;
+ // Represents a double value.
+ double number_value = 2;
+ // Represents a string value.
+ string string_value = 3;
+ // Represents a boolean value.
+ bool bool_value = 4;
+ // Represents a structured value.
+ Struct struct_value = 5;
+ // Represents a repeated `Value`.
+ ListValue list_value = 6;
+ }
+}
+
+// `NullValue` is a singleton enumeration to represent the null value for the
+// `Value` type union.
+//
+// The JSON representation for `NullValue` is JSON `null`.
+enum NullValue {
+ // Null value.
+ NULL_VALUE = 0;
+}
+
+// `ListValue` is a wrapper around a repeated field of values.
+//
+// The JSON representation for `ListValue` is JSON array.
+message ListValue {
+ // Repeated field of dynamically typed values.
+ repeated Value values = 1;
+}
diff --git a/kong-versions/3.9.0.0/kong/spec/fixtures/grpc/google/protobuf/timestamp.proto b/kong-versions/3.9.0.0/kong/spec/fixtures/grpc/google/protobuf/timestamp.proto
new file mode 100644
index 00000000..eafb3fa0
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/fixtures/grpc/google/protobuf/timestamp.proto
@@ -0,0 +1,135 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+syntax = "proto3";
+
+package google.protobuf;
+
+option csharp_namespace = "Google.Protobuf.WellKnownTypes";
+option cc_enable_arenas = true;
+option go_package = "github.com/golang/protobuf/ptypes/timestamp";
+option java_package = "com.google.protobuf";
+option java_outer_classname = "TimestampProto";
+option java_multiple_files = true;
+option objc_class_prefix = "GPB";
+
+// A Timestamp represents a point in time independent of any time zone
+// or calendar, represented as seconds and fractions of seconds at
+// nanosecond resolution in UTC Epoch time. It is encoded using the
+// Proleptic Gregorian Calendar which extends the Gregorian calendar
+// backwards to year one. It is encoded assuming all minutes are 60
+// seconds long, i.e. leap seconds are "smeared" so that no leap second
+// table is needed for interpretation. Range is from
+// 0001-01-01T00:00:00Z to 9999-12-31T23:59:59.999999999Z.
+// By restricting to that range, we ensure that we can convert to
+// and from RFC 3339 date strings.
+// See [https://www.ietf.org/rfc/rfc3339.txt](https://www.ietf.org/rfc/rfc3339.txt).
+//
+// # Examples
+//
+// Example 1: Compute Timestamp from POSIX `time()`.
+//
+// Timestamp timestamp;
+// timestamp.set_seconds(time(NULL));
+// timestamp.set_nanos(0);
+//
+// Example 2: Compute Timestamp from POSIX `gettimeofday()`.
+//
+// struct timeval tv;
+// gettimeofday(&tv, NULL);
+//
+// Timestamp timestamp;
+// timestamp.set_seconds(tv.tv_sec);
+// timestamp.set_nanos(tv.tv_usec * 1000);
+//
+// Example 3: Compute Timestamp from Win32 `GetSystemTimeAsFileTime()`.
+//
+// FILETIME ft;
+// GetSystemTimeAsFileTime(&ft);
+// UINT64 ticks = (((UINT64)ft.dwHighDateTime) << 32) | ft.dwLowDateTime;
+//
+// // A Windows tick is 100 nanoseconds. Windows epoch 1601-01-01T00:00:00Z
+// // is 11644473600 seconds before Unix epoch 1970-01-01T00:00:00Z.
+// Timestamp timestamp;
+// timestamp.set_seconds((INT64) ((ticks / 10000000) - 11644473600LL));
+// timestamp.set_nanos((INT32) ((ticks % 10000000) * 100));
+//
+// Example 4: Compute Timestamp from Java `System.currentTimeMillis()`.
+//
+// long millis = System.currentTimeMillis();
+//
+// Timestamp timestamp = Timestamp.newBuilder().setSeconds(millis / 1000)
+// .setNanos((int) ((millis % 1000) * 1000000)).build();
+//
+//
+// Example 5: Compute Timestamp from current time in Python.
+//
+// timestamp = Timestamp()
+// timestamp.GetCurrentTime()
+//
+// # JSON Mapping
+//
+// In JSON format, the Timestamp type is encoded as a string in the
+// [RFC 3339](https://www.ietf.org/rfc/rfc3339.txt) format. That is, the
+// format is "{year}-{month}-{day}T{hour}:{min}:{sec}[.{frac_sec}]Z"
+// where {year} is always expressed using four digits while {month}, {day},
+// {hour}, {min}, and {sec} are zero-padded to two digits each. The fractional
+// seconds, which can go up to 9 digits (i.e. up to 1 nanosecond resolution),
+// are optional. The "Z" suffix indicates the timezone ("UTC"); the timezone
+// is required. A proto3 JSON serializer should always use UTC (as indicated by
+// "Z") when printing the Timestamp type and a proto3 JSON parser should be
+// able to accept both UTC and other timezones (as indicated by an offset).
+//
+// For example, "2017-01-15T01:30:15.01Z" encodes 15.01 seconds past
+// 01:30 UTC on January 15, 2017.
+//
+// In JavaScript, one can convert a Date object to this format using the
+// standard [toISOString()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toISOString]
+// method. In Python, a standard `datetime.datetime` object can be converted
+// to this format using [`strftime`](https://docs.python.org/2/library/time.html#time.strftime)
+// with the time format spec '%Y-%m-%dT%H:%M:%S.%fZ'. Likewise, in Java, one
+// can use the Joda Time's [`ISODateTimeFormat.dateTime()`](
+// http://www.joda.org/joda-time/apidocs/org/joda/time/format/ISODateTimeFormat.html#dateTime--
+// ) to obtain a formatter capable of generating timestamps in this format.
+//
+//
+message Timestamp {
+
+ // Represents seconds of UTC time since Unix epoch
+ // 1970-01-01T00:00:00Z. Must be from 0001-01-01T00:00:00Z to
+ // 9999-12-31T23:59:59Z inclusive.
+ int64 seconds = 1;
+
+ // Non-negative fractions of a second at nanosecond resolution. Negative
+ // second values with fractions must still have non-negative nanos values
+ // that count forward in time. Must be from 0 to 999,999,999
+ // inclusive.
+ int32 nanos = 2;
+}
diff --git a/kong-versions/3.9.0.0/kong/spec/fixtures/grpc/google/protobuf/type.proto b/kong-versions/3.9.0.0/kong/spec/fixtures/grpc/google/protobuf/type.proto
new file mode 100644
index 00000000..624c15ee
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/fixtures/grpc/google/protobuf/type.proto
@@ -0,0 +1,187 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+syntax = "proto3";
+
+package google.protobuf;
+
+import "google/protobuf/any.proto";
+import "google/protobuf/source_context.proto";
+
+option csharp_namespace = "Google.Protobuf.WellKnownTypes";
+option cc_enable_arenas = true;
+option java_package = "com.google.protobuf";
+option java_outer_classname = "TypeProto";
+option java_multiple_files = true;
+option objc_class_prefix = "GPB";
+option go_package = "google.golang.org/genproto/protobuf/ptype;ptype";
+
+// A protocol buffer message type.
+message Type {
+ // The fully qualified message name.
+ string name = 1;
+ // The list of fields.
+ repeated Field fields = 2;
+ // The list of types appearing in `oneof` definitions in this type.
+ repeated string oneofs = 3;
+ // The protocol buffer options.
+ repeated Option options = 4;
+ // The source context.
+ SourceContext source_context = 5;
+ // The source syntax.
+ Syntax syntax = 6;
+}
+
+// A single field of a message type.
+message Field {
+ // Basic field types.
+ enum Kind {
+ // Field type unknown.
+ TYPE_UNKNOWN = 0;
+ // Field type double.
+ TYPE_DOUBLE = 1;
+ // Field type float.
+ TYPE_FLOAT = 2;
+ // Field type int64.
+ TYPE_INT64 = 3;
+ // Field type uint64.
+ TYPE_UINT64 = 4;
+ // Field type int32.
+ TYPE_INT32 = 5;
+ // Field type fixed64.
+ TYPE_FIXED64 = 6;
+ // Field type fixed32.
+ TYPE_FIXED32 = 7;
+ // Field type bool.
+ TYPE_BOOL = 8;
+ // Field type string.
+ TYPE_STRING = 9;
+ // Field type group. Proto2 syntax only, and deprecated.
+ TYPE_GROUP = 10;
+ // Field type message.
+ TYPE_MESSAGE = 11;
+ // Field type bytes.
+ TYPE_BYTES = 12;
+ // Field type uint32.
+ TYPE_UINT32 = 13;
+ // Field type enum.
+ TYPE_ENUM = 14;
+ // Field type sfixed32.
+ TYPE_SFIXED32 = 15;
+ // Field type sfixed64.
+ TYPE_SFIXED64 = 16;
+ // Field type sint32.
+ TYPE_SINT32 = 17;
+ // Field type sint64.
+ TYPE_SINT64 = 18;
+ };
+
+ // Whether a field is optional, required, or repeated.
+ enum Cardinality {
+ // For fields with unknown cardinality.
+ CARDINALITY_UNKNOWN = 0;
+ // For optional fields.
+ CARDINALITY_OPTIONAL = 1;
+ // For required fields. Proto2 syntax only.
+ CARDINALITY_REQUIRED = 2;
+ // For repeated fields.
+ CARDINALITY_REPEATED = 3;
+ };
+
+ // The field type.
+ Kind kind = 1;
+ // The field cardinality.
+ Cardinality cardinality = 2;
+ // The field number.
+ int32 number = 3;
+ // The field name.
+ string name = 4;
+ // The field type URL, without the scheme, for message or enumeration
+ // types. Example: `"type.googleapis.com/google.protobuf.Timestamp"`.
+ string type_url = 6;
+ // The index of the field type in `Type.oneofs`, for message or enumeration
+ // types. The first type has index 1; zero means the type is not in the list.
+ int32 oneof_index = 7;
+ // Whether to use alternative packed wire representation.
+ bool packed = 8;
+ // The protocol buffer options.
+ repeated Option options = 9;
+ // The field JSON name.
+ string json_name = 10;
+ // The string value of the default value of this field. Proto2 syntax only.
+ string default_value = 11;
+}
+
+// Enum type definition.
+message Enum {
+ // Enum type name.
+ string name = 1;
+ // Enum value definitions.
+ repeated EnumValue enumvalue = 2;
+ // Protocol buffer options.
+ repeated Option options = 3;
+ // The source context.
+ SourceContext source_context = 4;
+ // The source syntax.
+ Syntax syntax = 5;
+}
+
+// Enum value definition.
+message EnumValue {
+ // Enum value name.
+ string name = 1;
+ // Enum value number.
+ int32 number = 2;
+ // Protocol buffer options.
+ repeated Option options = 3;
+}
+
+// A protocol buffer option, which can be attached to a message, field,
+// enumeration, etc.
+message Option {
+ // The option's name. For protobuf built-in options (options defined in
+ // descriptor.proto), this is the short name. For example, `"map_entry"`.
+ // For custom options, it should be the fully-qualified name. For example,
+ // `"google.api.http"`.
+ string name = 1;
+ // The option's value packed in an Any message. If the value is a primitive,
+ // the corresponding wrapper type defined in google/protobuf/wrappers.proto
+ // should be used. If the value is an enum, it should be stored as an int32
+ // value using the google.protobuf.Int32Value type.
+ Any value = 2;
+}
+
+// The syntax in which a protocol buffer element is defined.
+enum Syntax {
+ // Syntax `proto2`.
+ SYNTAX_PROTO2 = 0;
+ // Syntax `proto3`.
+ SYNTAX_PROTO3 = 1;
+}
diff --git a/kong-versions/3.9.0.0/kong/spec/fixtures/grpc/google/protobuf/wrappers.proto b/kong-versions/3.9.0.0/kong/spec/fixtures/grpc/google/protobuf/wrappers.proto
new file mode 100644
index 00000000..01947639
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/fixtures/grpc/google/protobuf/wrappers.proto
@@ -0,0 +1,118 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Wrappers for primitive (non-message) types. These types are useful
+// for embedding primitives in the `google.protobuf.Any` type and for places
+// where we need to distinguish between the absence of a primitive
+// typed field and its default value.
+
+syntax = "proto3";
+
+package google.protobuf;
+
+option csharp_namespace = "Google.Protobuf.WellKnownTypes";
+option cc_enable_arenas = true;
+option go_package = "github.com/golang/protobuf/ptypes/wrappers";
+option java_package = "com.google.protobuf";
+option java_outer_classname = "WrappersProto";
+option java_multiple_files = true;
+option objc_class_prefix = "GPB";
+
+// Wrapper message for `double`.
+//
+// The JSON representation for `DoubleValue` is JSON number.
+message DoubleValue {
+ // The double value.
+ double value = 1;
+}
+
+// Wrapper message for `float`.
+//
+// The JSON representation for `FloatValue` is JSON number.
+message FloatValue {
+ // The float value.
+ float value = 1;
+}
+
+// Wrapper message for `int64`.
+//
+// The JSON representation for `Int64Value` is JSON string.
+message Int64Value {
+ // The int64 value.
+ int64 value = 1;
+}
+
+// Wrapper message for `uint64`.
+//
+// The JSON representation for `UInt64Value` is JSON string.
+message UInt64Value {
+ // The uint64 value.
+ uint64 value = 1;
+}
+
+// Wrapper message for `int32`.
+//
+// The JSON representation for `Int32Value` is JSON number.
+message Int32Value {
+ // The int32 value.
+ int32 value = 1;
+}
+
+// Wrapper message for `uint32`.
+//
+// The JSON representation for `UInt32Value` is JSON number.
+message UInt32Value {
+ // The uint32 value.
+ uint32 value = 1;
+}
+
+// Wrapper message for `bool`.
+//
+// The JSON representation for `BoolValue` is JSON `true` and `false`.
+message BoolValue {
+ // The bool value.
+ bool value = 1;
+}
+
+// Wrapper message for `string`.
+//
+// The JSON representation for `StringValue` is JSON string.
+message StringValue {
+ // The string value.
+ string value = 1;
+}
+
+// Wrapper message for `bytes`.
+//
+// The JSON representation for `BytesValue` is JSON string.
+message BytesValue {
+ // The bytes value.
+ bytes value = 1;
+}
diff --git a/kong-versions/3.9.0.0/kong/spec/fixtures/grpc/hello.proto b/kong-versions/3.9.0.0/kong/spec/fixtures/grpc/hello.proto
new file mode 100644
index 00000000..273a41fb
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/fixtures/grpc/hello.proto
@@ -0,0 +1,21 @@
+// from https://github.com/moul/pb
+// based on https://grpc.io/docs/guides/concepts.html
+
+syntax = "proto2";
+
+package hello;
+
+service HelloService {
+ rpc SayHello(HelloRequest) returns (HelloResponse);
+ rpc LotsOfReplies(HelloRequest) returns (stream HelloResponse);
+ rpc LotsOfGreetings(stream HelloRequest) returns (HelloResponse);
+ rpc BidiHello(stream HelloRequest) returns (stream HelloResponse);
+}
+
+message HelloRequest {
+ optional string greeting = 1;
+}
+
+message HelloResponse {
+ required string reply = 1;
+}
diff --git a/kong-versions/3.9.0.0/kong/spec/fixtures/grpc/helloworld.proto b/kong-versions/3.9.0.0/kong/spec/fixtures/grpc/helloworld.proto
new file mode 100644
index 00000000..6967b3ab
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/fixtures/grpc/helloworld.proto
@@ -0,0 +1,35 @@
+syntax = "proto3";
+
+package hello;
+
+service HelloService {
+ rpc SayHello(HelloRequest) returns (HelloResponse) {
+ option (google.api.http) = {
+ // https://github.com/googleapis/googleapis/blob/master/google/api/http.proto
+ // HTTP | gRPC
+ // -----|-----
+ // `GET /v1/messages/123456` | `HelloRequest(greeting: "123456")`
+ get: "/v1/messages/{greeting}"
+ additional_bindings {
+ get: "/v1/messages/legacy/{greeting=**}"
+ }
+ post: "/v1/messages/"
+ body: "*"
+ }
+ };
+
+ // define a gRPC method that's not implemented in grpcbin
+ rpc UnknownMethod(HelloRequest) returns (HelloResponse) {
+ option (google.api.http) = {
+ get: "/v1/unknown/{greeting}"
+ }
+ };
+}
+
+message HelloRequest {
+ required string greeting = 1;
+}
+
+message HelloResponse {
+ required string reply = 1;
+}
diff --git a/kong-versions/3.9.0.0/kong/spec/fixtures/grpc/second_level_imports.proto b/kong-versions/3.9.0.0/kong/spec/fixtures/grpc/second_level_imports.proto
new file mode 100644
index 00000000..7edce70a
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/fixtures/grpc/second_level_imports.proto
@@ -0,0 +1,7 @@
+syntax = "proto3";
+
+import "direct_imports.proto";
+
+service Added {
+ rpc Final(hello.HelloRequest) returns (hello.HelloResponse);
+}
diff --git a/kong-versions/3.9.0.0/kong/spec/fixtures/grpc/target/go.mod b/kong-versions/3.9.0.0/kong/spec/fixtures/grpc/target/go.mod
new file mode 100644
index 00000000..24a43b89
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/fixtures/grpc/target/go.mod
@@ -0,0 +1,10 @@
+module target
+
+go 1.15
+
+require (
+ github.com/golang/protobuf v1.5.2
+ google.golang.org/genproto v0.0.0-20210716133855-ce7ef5c701ea
+ google.golang.org/grpc v1.39.0
+ google.golang.org/protobuf v1.27.1
+)
diff --git a/kong-versions/3.9.0.0/kong/spec/fixtures/grpc/target/go.sum b/kong-versions/3.9.0.0/kong/spec/fixtures/grpc/target/go.sum
new file mode 100644
index 00000000..780a5f3f
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/fixtures/grpc/target/go.sum
@@ -0,0 +1,170 @@
+cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
+cloud.google.com/go v0.34.0 h1:eOI3/cP2VTU6uZLDYAoic+eyzzB9YyGmJ7eIjl8rOPg=
+cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
+github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
+github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
+github.com/antihax/optional v1.0.0 h1:xK2lYat7ZLaVVcIuj82J8kIro4V6kDe0AUDFboUCwcg=
+github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
+github.com/census-instrumentation/opencensus-proto v0.2.1 h1:glEXhBS5PSLLv4IXzLA5yPRVX4bilULVyxxbrfOtDAk=
+github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
+github.com/client9/misspell v0.3.4 h1:ta993UF76GwbvJcIo3Y68y/M3WxlpEHPWIGDkJYwzJI=
+github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
+github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
+github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403 h1:cqQfy1jclcSy/FwLjemeg3SR1yaINm74aQyupQ0Bl8M=
+github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
+github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed h1:OZmjad4L3H8ncOIR8rnb5MREYqG8ixi5+WbeUsquF0c=
+github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
+github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
+github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
+github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
+github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
+github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
+github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0 h1:dulLQAYQFYtG5MTplgNGHWuV2D+OBD+Z8lmDBmbLg+s=
+github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ=
+github.com/envoyproxy/protoc-gen-validate v0.1.0 h1:EQciDnbrYxy13PgWoY8AqoxGiPrpgBZ1R8UNe3ddc+A=
+github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
+github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk=
+github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
+github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58=
+github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
+github.com/golang/mock v1.1.1 h1:G5FRp8JnTd7RQH5kemVNlMeyXQAztQ3mOWV95KxsXH8=
+github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
+github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
+github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
+github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
+github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
+github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
+github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
+github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
+github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
+github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
+github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
+github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
+github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
+github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
+github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
+github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
+github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
+github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
+github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
+github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/uuid v1.1.2 h1:EVhdT+1Kseyi1/pUmXKaFxYsDNy9RQYkMWRH68J/W7Y=
+github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
+github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo=
+github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
+github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
+github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
+github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4 h1:gQz4mCbXsO+nc9n1hCxHcGA3Zx3Eo+UHZoInFGUIXNM=
+github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
+github.com/rogpeppe/fastuuid v1.2.0 h1:Ppwyp6VYCF1nvBTXL3trRso7mXMlRrw9ooo375wvi2s=
+github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
+github.com/stretchr/objx v0.1.0 h1:4G4v2dO3VZwixGIRoQ5Lfboy6nUhCyYzaqnIAPPhYs4=
+github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
+github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4=
+github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
+github.com/yuin/goldmark v1.3.5 h1:dPmz1Snjq0kmkz159iL7S6WzdahUTHnHB5M56WFVifs=
+github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
+go.opentelemetry.io/proto/otlp v0.7.0 h1:rwOQPCuKAKmwGKq2aVNnYIibI6wnV7EvzgfTCzcdGg8=
+go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI=
+golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
+golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
+golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI=
+golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
+golang.org/x/exp v0.0.0-20190121172915-509febef88a4 h1:c2HOrn5iMezYjSlGPncknSEr/8x5LELb/ilJbXi9DEA=
+golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
+golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
+golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
+golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
+golang.org/x/lint v0.0.0-20210508222113-6edffad5e616 h1:VLliZ0d+/avPrXXH+OakdXhpJuEoBZuwh1m2j7U6Iug=
+golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
+golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
+golang.org/x/mod v0.4.2 h1:Gz96sIWK3OalVv/I/qNygP42zyoKp3xptRVCWRFEBvo=
+golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
+golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
+golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4 h1:4nGaVu0QrbjT/AK2PRLuQfQuh6DJve+pELhqTdAj3x0=
+golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
+golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
+golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d h1:TzXSXBo42m9gQenoE3b9BGiEpg5IG2JkU5FkPIawgtw=
+golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
+golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ=
+golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210510120138-977fb7262007 h1:gG67DSER+11cZvqIMb8S8bt0vZtiN6xWYARwirrOSfE=
+golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 h1:v+OssWQX+hTHEmOBgwxdZxK4zHq3yOs8F9J7mk0PY8E=
+golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
+golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
+golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
+golang.org/x/text v0.3.5 h1:i6eZZ+zk0SOf0xgBpEpPD18qWcJda6q1sxt3S0kzyUQ=
+golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
+golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
+golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
+golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
+golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
+golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
+golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
+golang.org/x/tools v0.1.4 h1:cVngSRcfgyZCzys3KYOpCFa+4dqX/Oub9tAq00ttGVs=
+golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
+golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
+golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
+google.golang.org/appengine v1.4.0 h1:/wp5JvzpHIxhs/dumFmF7BXTf3Z+dd4uXta4kVyO508=
+google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
+google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
+google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
+google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
+google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
+google.golang.org/genproto v0.0.0-20210716133855-ce7ef5c701ea h1:8ZyCcgugUqamxp/vZSEJw9CMy7VZlSWYJLLJPi/dSDA=
+google.golang.org/genproto v0.0.0-20210716133855-ce7ef5c701ea/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k=
+google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
+google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
+google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
+google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
+google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0=
+google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
+google.golang.org/grpc v1.39.0 h1:Klz8I9kdtkIN6EpHHUOMLCYhTn/2WAe5a0s1hcBkdTI=
+google.golang.org/grpc v1.39.0/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE=
+google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
+google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
+google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
+google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
+google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
+google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
+google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
+google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
+google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
+google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
+google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
+google.golang.org/protobuf v1.27.1 h1:SnqbnDw1V7RiZcXPx5MEeqPv2s79L9i7BJUlG/+RurQ=
+google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
+gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
+gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v2 v2.2.3 h1:fvjTMHxHEw/mxHbtzPi3JCcKXQRAnQTBRo6YCJSVHKI=
+gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
+honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc h1:/hemPrYIhOhy8zYrNj+069zDB68us2sMGsfkFJO0iZs=
+honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
diff --git a/kong-versions/3.9.0.0/kong/spec/fixtures/grpc/target/grpc-target.go b/kong-versions/3.9.0.0/kong/spec/fixtures/grpc/target/grpc-target.go
new file mode 100644
index 00000000..de15cd4c
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/fixtures/grpc/target/grpc-target.go
@@ -0,0 +1,67 @@
+package main
+
+import (
+ "context"
+ "fmt"
+ "log"
+ "net"
+ "time"
+
+ pb "target/targetservice"
+
+ "google.golang.org/grpc"
+ "google.golang.org/protobuf/types/known/timestamppb"
+)
+
+const (
+ port = ":15010"
+)
+
+type server struct {
+ pb.UnimplementedBouncerServer
+}
+
+func (s *server) SayHello(ctx context.Context, in *pb.HelloRequest) (*pb.HelloResponse, error) {
+ return &pb.HelloResponse{
+ Reply: fmt.Sprintf("hello %s", in.GetGreeting()),
+ BooleanTest: in.GetBooleanTest(),
+ }, nil
+}
+
+func (s *server) BounceIt(ctx context.Context, in *pb.BallIn) (*pb.BallOut, error) {
+ w := in.GetWhen().AsTime()
+ now := in.GetNow().AsTime()
+ ago := now.Sub(w)
+
+ reply := fmt.Sprintf("hello %s", in.GetMessage())
+ time_message := fmt.Sprintf("%s was %v ago", w.Format(time.RFC3339), ago.Truncate(time.Second))
+
+ return &pb.BallOut{
+ Reply: reply,
+ TimeMessage: time_message,
+ Now: timestamppb.New(now),
+ }, nil
+}
+
+func (s *server) GrowTail(ctx context.Context, in *pb.Body) (*pb.Body, error) {
+ in.Tail.Count += 1
+
+ return in, nil
+}
+
+func (s *server) Echo(ctx context.Context, in *pb.EchoMsg) (*pb.EchoMsg, error) {
+ return in, nil
+}
+
+func main() {
+ lis, err := net.Listen("tcp", port)
+ if err != nil {
+ log.Fatalf("failed to listen: %v", err)
+ }
+ s := grpc.NewServer()
+ pb.RegisterBouncerServer(s, &server{})
+ log.Printf("server listening at %v", lis.Addr())
+ if err := s.Serve(lis); err != nil {
+ log.Fatalf("failed to serve: %v", err)
+ }
+}
diff --git a/kong-versions/3.9.0.0/kong/spec/fixtures/grpc/target/targetservice/targetservice.pb.go b/kong-versions/3.9.0.0/kong/spec/fixtures/grpc/target/targetservice/targetservice.pb.go
new file mode 100644
index 00000000..43cf2421
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/fixtures/grpc/target/targetservice/targetservice.pb.go
@@ -0,0 +1,685 @@
+// Code generated by protoc-gen-go. DO NOT EDIT.
+// versions:
+// protoc-gen-go v1.28.1
+// protoc v3.21.7
+// source: targetservice.proto
+
+package targetservice
+
+import (
+ timestamp "github.com/golang/protobuf/ptypes/timestamp"
+ _ "google.golang.org/genproto/googleapis/api/annotations"
+ protoreflect "google.golang.org/protobuf/reflect/protoreflect"
+ protoimpl "google.golang.org/protobuf/runtime/protoimpl"
+ reflect "reflect"
+ sync "sync"
+)
+
+const (
+ // Verify that this generated code is sufficiently up-to-date.
+ _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
+ // Verify that runtime/protoimpl is sufficiently up-to-date.
+ _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
+)
+
+type HelloRequest struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ Greeting string `protobuf:"bytes,1,opt,name=greeting,proto3" json:"greeting,omitempty"`
+ BooleanTest bool `protobuf:"varint,2,opt,name=boolean_test,json=booleanTest,proto3" json:"boolean_test,omitempty"`
+}
+
+func (x *HelloRequest) Reset() {
+ *x = HelloRequest{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_targetservice_proto_msgTypes[0]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *HelloRequest) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*HelloRequest) ProtoMessage() {}
+
+func (x *HelloRequest) ProtoReflect() protoreflect.Message {
+ mi := &file_targetservice_proto_msgTypes[0]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use HelloRequest.ProtoReflect.Descriptor instead.
+func (*HelloRequest) Descriptor() ([]byte, []int) {
+ return file_targetservice_proto_rawDescGZIP(), []int{0}
+}
+
+func (x *HelloRequest) GetGreeting() string {
+ if x != nil {
+ return x.Greeting
+ }
+ return ""
+}
+
+func (x *HelloRequest) GetBooleanTest() bool {
+ if x != nil {
+ return x.BooleanTest
+ }
+ return false
+}
+
+type HelloResponse struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ Reply string `protobuf:"bytes,1,opt,name=reply,proto3" json:"reply,omitempty"`
+ BooleanTest bool `protobuf:"varint,2,opt,name=boolean_test,json=booleanTest,proto3" json:"boolean_test,omitempty"`
+}
+
+func (x *HelloResponse) Reset() {
+ *x = HelloResponse{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_targetservice_proto_msgTypes[1]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *HelloResponse) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*HelloResponse) ProtoMessage() {}
+
+func (x *HelloResponse) ProtoReflect() protoreflect.Message {
+ mi := &file_targetservice_proto_msgTypes[1]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use HelloResponse.ProtoReflect.Descriptor instead.
+func (*HelloResponse) Descriptor() ([]byte, []int) {
+ return file_targetservice_proto_rawDescGZIP(), []int{1}
+}
+
+func (x *HelloResponse) GetReply() string {
+ if x != nil {
+ return x.Reply
+ }
+ return ""
+}
+
+func (x *HelloResponse) GetBooleanTest() bool {
+ if x != nil {
+ return x.BooleanTest
+ }
+ return false
+}
+
+type BallIn struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ Message string `protobuf:"bytes,1,opt,name=message,proto3" json:"message,omitempty"`
+ When *timestamp.Timestamp `protobuf:"bytes,2,opt,name=when,proto3" json:"when,omitempty"`
+ Now *timestamp.Timestamp `protobuf:"bytes,3,opt,name=now,proto3" json:"now,omitempty"`
+}
+
+func (x *BallIn) Reset() {
+ *x = BallIn{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_targetservice_proto_msgTypes[2]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *BallIn) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*BallIn) ProtoMessage() {}
+
+func (x *BallIn) ProtoReflect() protoreflect.Message {
+ mi := &file_targetservice_proto_msgTypes[2]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use BallIn.ProtoReflect.Descriptor instead.
+func (*BallIn) Descriptor() ([]byte, []int) {
+ return file_targetservice_proto_rawDescGZIP(), []int{2}
+}
+
+func (x *BallIn) GetMessage() string {
+ if x != nil {
+ return x.Message
+ }
+ return ""
+}
+
+func (x *BallIn) GetWhen() *timestamp.Timestamp {
+ if x != nil {
+ return x.When
+ }
+ return nil
+}
+
+func (x *BallIn) GetNow() *timestamp.Timestamp {
+ if x != nil {
+ return x.Now
+ }
+ return nil
+}
+
+type BallOut struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ Reply string `protobuf:"bytes,1,opt,name=reply,proto3" json:"reply,omitempty"`
+ TimeMessage string `protobuf:"bytes,2,opt,name=time_message,json=timeMessage,proto3" json:"time_message,omitempty"`
+ Now *timestamp.Timestamp `protobuf:"bytes,3,opt,name=now,proto3" json:"now,omitempty"`
+}
+
+func (x *BallOut) Reset() {
+ *x = BallOut{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_targetservice_proto_msgTypes[3]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *BallOut) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*BallOut) ProtoMessage() {}
+
+func (x *BallOut) ProtoReflect() protoreflect.Message {
+ mi := &file_targetservice_proto_msgTypes[3]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use BallOut.ProtoReflect.Descriptor instead.
+func (*BallOut) Descriptor() ([]byte, []int) {
+ return file_targetservice_proto_rawDescGZIP(), []int{3}
+}
+
+func (x *BallOut) GetReply() string {
+ if x != nil {
+ return x.Reply
+ }
+ return ""
+}
+
+func (x *BallOut) GetTimeMessage() string {
+ if x != nil {
+ return x.TimeMessage
+ }
+ return ""
+}
+
+func (x *BallOut) GetNow() *timestamp.Timestamp {
+ if x != nil {
+ return x.Now
+ }
+ return nil
+}
+
+type Limb struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ Count int32 `protobuf:"varint,1,opt,name=count,proto3" json:"count,omitempty"`
+ Endings string `protobuf:"bytes,2,opt,name=endings,proto3" json:"endings,omitempty"`
+}
+
+func (x *Limb) Reset() {
+ *x = Limb{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_targetservice_proto_msgTypes[4]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *Limb) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*Limb) ProtoMessage() {}
+
+func (x *Limb) ProtoReflect() protoreflect.Message {
+ mi := &file_targetservice_proto_msgTypes[4]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use Limb.ProtoReflect.Descriptor instead.
+func (*Limb) Descriptor() ([]byte, []int) {
+ return file_targetservice_proto_rawDescGZIP(), []int{4}
+}
+
+func (x *Limb) GetCount() int32 {
+ if x != nil {
+ return x.Count
+ }
+ return 0
+}
+
+func (x *Limb) GetEndings() string {
+ if x != nil {
+ return x.Endings
+ }
+ return ""
+}
+
+type Body struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
+ Hands *Limb `protobuf:"bytes,2,opt,name=hands,proto3" json:"hands,omitempty"`
+ Legs *Limb `protobuf:"bytes,3,opt,name=legs,proto3" json:"legs,omitempty"`
+ Tail *Limb `protobuf:"bytes,4,opt,name=tail,proto3" json:"tail,omitempty"`
+}
+
+func (x *Body) Reset() {
+ *x = Body{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_targetservice_proto_msgTypes[5]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *Body) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*Body) ProtoMessage() {}
+
+func (x *Body) ProtoReflect() protoreflect.Message {
+ mi := &file_targetservice_proto_msgTypes[5]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use Body.ProtoReflect.Descriptor instead.
+func (*Body) Descriptor() ([]byte, []int) {
+ return file_targetservice_proto_rawDescGZIP(), []int{5}
+}
+
+func (x *Body) GetName() string {
+ if x != nil {
+ return x.Name
+ }
+ return ""
+}
+
+func (x *Body) GetHands() *Limb {
+ if x != nil {
+ return x.Hands
+ }
+ return nil
+}
+
+func (x *Body) GetLegs() *Limb {
+ if x != nil {
+ return x.Legs
+ }
+ return nil
+}
+
+func (x *Body) GetTail() *Limb {
+ if x != nil {
+ return x.Tail
+ }
+ return nil
+}
+
+type EchoMsg struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ Array []string `protobuf:"bytes,1,rep,name=array,proto3" json:"array,omitempty"`
+ Nullable string `protobuf:"bytes,2,opt,name=nullable,proto3" json:"nullable,omitempty"`
+}
+
+func (x *EchoMsg) Reset() {
+ *x = EchoMsg{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_targetservice_proto_msgTypes[6]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *EchoMsg) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*EchoMsg) ProtoMessage() {}
+
+func (x *EchoMsg) ProtoReflect() protoreflect.Message {
+ mi := &file_targetservice_proto_msgTypes[6]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use EchoMsg.ProtoReflect.Descriptor instead.
+func (*EchoMsg) Descriptor() ([]byte, []int) {
+ return file_targetservice_proto_rawDescGZIP(), []int{6}
+}
+
+func (x *EchoMsg) GetArray() []string {
+ if x != nil {
+ return x.Array
+ }
+ return nil
+}
+
+func (x *EchoMsg) GetNullable() string {
+ if x != nil {
+ return x.Nullable
+ }
+ return ""
+}
+
+var File_targetservice_proto protoreflect.FileDescriptor
+
+var file_targetservice_proto_rawDesc = []byte{
+ 0x0a, 0x13, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e,
+ 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0d, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x65, 0x72,
+ 0x76, 0x69, 0x63, 0x65, 0x1a, 0x1c, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x61, 0x70, 0x69,
+ 0x2f, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x70, 0x72, 0x6f,
+ 0x74, 0x6f, 0x1a, 0x1f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f,
+ 0x62, 0x75, 0x66, 0x2f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72,
+ 0x6f, 0x74, 0x6f, 0x22, 0x4d, 0x0a, 0x0c, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x52, 0x65, 0x71, 0x75,
+ 0x65, 0x73, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x67, 0x72, 0x65, 0x65, 0x74, 0x69, 0x6e, 0x67, 0x18,
+ 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x67, 0x72, 0x65, 0x65, 0x74, 0x69, 0x6e, 0x67, 0x12,
+ 0x21, 0x0a, 0x0c, 0x62, 0x6f, 0x6f, 0x6c, 0x65, 0x61, 0x6e, 0x5f, 0x74, 0x65, 0x73, 0x74, 0x18,
+ 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x62, 0x6f, 0x6f, 0x6c, 0x65, 0x61, 0x6e, 0x54, 0x65,
+ 0x73, 0x74, 0x22, 0x48, 0x0a, 0x0d, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f,
+ 0x6e, 0x73, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x72, 0x65, 0x70, 0x6c, 0x79, 0x18, 0x01, 0x20, 0x01,
+ 0x28, 0x09, 0x52, 0x05, 0x72, 0x65, 0x70, 0x6c, 0x79, 0x12, 0x21, 0x0a, 0x0c, 0x62, 0x6f, 0x6f,
+ 0x6c, 0x65, 0x61, 0x6e, 0x5f, 0x74, 0x65, 0x73, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52,
+ 0x0b, 0x62, 0x6f, 0x6f, 0x6c, 0x65, 0x61, 0x6e, 0x54, 0x65, 0x73, 0x74, 0x22, 0x80, 0x01, 0x0a,
+ 0x06, 0x42, 0x61, 0x6c, 0x6c, 0x49, 0x6e, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61,
+ 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67,
+ 0x65, 0x12, 0x2e, 0x0a, 0x04, 0x77, 0x68, 0x65, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32,
+ 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75,
+ 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x04, 0x77, 0x68, 0x65,
+ 0x6e, 0x12, 0x2c, 0x0a, 0x03, 0x6e, 0x6f, 0x77, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a,
+ 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66,
+ 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x03, 0x6e, 0x6f, 0x77, 0x22,
+ 0x70, 0x0a, 0x07, 0x42, 0x61, 0x6c, 0x6c, 0x4f, 0x75, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x72, 0x65,
+ 0x70, 0x6c, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x72, 0x65, 0x70, 0x6c, 0x79,
+ 0x12, 0x21, 0x0a, 0x0c, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65,
+ 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x74, 0x69, 0x6d, 0x65, 0x4d, 0x65, 0x73, 0x73,
+ 0x61, 0x67, 0x65, 0x12, 0x2c, 0x0a, 0x03, 0x6e, 0x6f, 0x77, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b,
+ 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62,
+ 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x03, 0x6e, 0x6f,
+ 0x77, 0x22, 0x36, 0x0a, 0x04, 0x4c, 0x69, 0x6d, 0x62, 0x12, 0x14, 0x0a, 0x05, 0x63, 0x6f, 0x75,
+ 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x12,
+ 0x18, 0x0a, 0x07, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09,
+ 0x52, 0x07, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x73, 0x22, 0x97, 0x01, 0x0a, 0x04, 0x42, 0x6f,
+ 0x64, 0x79, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09,
+ 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x29, 0x0a, 0x05, 0x68, 0x61, 0x6e, 0x64, 0x73, 0x18,
+ 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x65,
+ 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x4c, 0x69, 0x6d, 0x62, 0x52, 0x05, 0x68, 0x61, 0x6e, 0x64,
+ 0x73, 0x12, 0x27, 0x0a, 0x04, 0x6c, 0x65, 0x67, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32,
+ 0x13, 0x2e, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e,
+ 0x4c, 0x69, 0x6d, 0x62, 0x52, 0x04, 0x6c, 0x65, 0x67, 0x73, 0x12, 0x27, 0x0a, 0x04, 0x74, 0x61,
+ 0x69, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x74, 0x61, 0x72, 0x67, 0x65,
+ 0x74, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x4c, 0x69, 0x6d, 0x62, 0x52, 0x04, 0x74,
+ 0x61, 0x69, 0x6c, 0x22, 0x3b, 0x0a, 0x07, 0x45, 0x63, 0x68, 0x6f, 0x4d, 0x73, 0x67, 0x12, 0x14,
+ 0x0a, 0x05, 0x61, 0x72, 0x72, 0x61, 0x79, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x05, 0x61,
+ 0x72, 0x72, 0x61, 0x79, 0x12, 0x1a, 0x0a, 0x08, 0x6e, 0x75, 0x6c, 0x6c, 0x61, 0x62, 0x6c, 0x65,
+ 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x6e, 0x75, 0x6c, 0x6c, 0x61, 0x62, 0x6c, 0x65,
+ 0x32, 0x80, 0x04, 0x0a, 0x07, 0x42, 0x6f, 0x75, 0x6e, 0x63, 0x65, 0x72, 0x12, 0x9f, 0x01, 0x0a,
+ 0x08, 0x53, 0x61, 0x79, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x12, 0x1b, 0x2e, 0x74, 0x61, 0x72, 0x67,
+ 0x65, 0x74, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x52,
+ 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x73,
+ 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x52, 0x65, 0x73, 0x70,
+ 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x58, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x52, 0x12, 0x17, 0x2f, 0x76,
+ 0x31, 0x2f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x2f, 0x7b, 0x67, 0x72, 0x65, 0x65,
+ 0x74, 0x69, 0x6e, 0x67, 0x7d, 0x3a, 0x01, 0x2a, 0x5a, 0x34, 0x12, 0x21, 0x2f, 0x76, 0x31, 0x2f,
+ 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x2f, 0x6c, 0x65, 0x67, 0x61, 0x63, 0x79, 0x2f,
+ 0x7b, 0x67, 0x72, 0x65, 0x65, 0x74, 0x69, 0x6e, 0x67, 0x3d, 0x2a, 0x2a, 0x7d, 0x5a, 0x0f, 0x22,
+ 0x0d, 0x2f, 0x76, 0x31, 0x2f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x2f, 0x12, 0x6a,
+ 0x0a, 0x0d, 0x55, 0x6e, 0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x12,
+ 0x1b, 0x2e, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e,
+ 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x74,
+ 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x48, 0x65, 0x6c,
+ 0x6c, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1e, 0x82, 0xd3, 0xe4, 0x93,
+ 0x02, 0x18, 0x12, 0x16, 0x2f, 0x76, 0x31, 0x2f, 0x75, 0x6e, 0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x2f,
+ 0x7b, 0x67, 0x72, 0x65, 0x65, 0x74, 0x69, 0x6e, 0x67, 0x7d, 0x12, 0x4d, 0x0a, 0x08, 0x42, 0x6f,
+ 0x75, 0x6e, 0x63, 0x65, 0x49, 0x74, 0x12, 0x15, 0x2e, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x73,
+ 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x42, 0x61, 0x6c, 0x6c, 0x49, 0x6e, 0x1a, 0x16, 0x2e,
+ 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x42, 0x61,
+ 0x6c, 0x6c, 0x4f, 0x75, 0x74, 0x22, 0x12, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x0c, 0x22, 0x07, 0x2f,
+ 0x62, 0x6f, 0x75, 0x6e, 0x63, 0x65, 0x3a, 0x01, 0x2a, 0x12, 0x4b, 0x0a, 0x08, 0x47, 0x72, 0x6f,
+ 0x77, 0x54, 0x61, 0x69, 0x6c, 0x12, 0x13, 0x2e, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x65,
+ 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x1a, 0x13, 0x2e, 0x74, 0x61, 0x72,
+ 0x67, 0x65, 0x74, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x22,
+ 0x15, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x0f, 0x12, 0x0d, 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x72, 0x6f,
+ 0x77, 0x2f, 0x74, 0x61, 0x69, 0x6c, 0x12, 0x4b, 0x0a, 0x04, 0x45, 0x63, 0x68, 0x6f, 0x12, 0x16,
+ 0x2e, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x45,
+ 0x63, 0x68, 0x6f, 0x4d, 0x73, 0x67, 0x1a, 0x16, 0x2e, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x73,
+ 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x45, 0x63, 0x68, 0x6f, 0x4d, 0x73, 0x67, 0x22, 0x13,
+ 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x0d, 0x22, 0x08, 0x2f, 0x76, 0x31, 0x2f, 0x65, 0x63, 0x68, 0x6f,
+ 0x3a, 0x01, 0x2a, 0x42, 0x11, 0x5a, 0x0f, 0x2e, 0x2f, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x73,
+ 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
+}
+
+var (
+ file_targetservice_proto_rawDescOnce sync.Once
+ file_targetservice_proto_rawDescData = file_targetservice_proto_rawDesc
+)
+
+func file_targetservice_proto_rawDescGZIP() []byte {
+ file_targetservice_proto_rawDescOnce.Do(func() {
+ file_targetservice_proto_rawDescData = protoimpl.X.CompressGZIP(file_targetservice_proto_rawDescData)
+ })
+ return file_targetservice_proto_rawDescData
+}
+
+var file_targetservice_proto_msgTypes = make([]protoimpl.MessageInfo, 7)
+var file_targetservice_proto_goTypes = []interface{}{
+ (*HelloRequest)(nil), // 0: targetservice.HelloRequest
+ (*HelloResponse)(nil), // 1: targetservice.HelloResponse
+ (*BallIn)(nil), // 2: targetservice.BallIn
+ (*BallOut)(nil), // 3: targetservice.BallOut
+ (*Limb)(nil), // 4: targetservice.Limb
+ (*Body)(nil), // 5: targetservice.Body
+ (*EchoMsg)(nil), // 6: targetservice.EchoMsg
+ (*timestamp.Timestamp)(nil), // 7: google.protobuf.Timestamp
+}
+var file_targetservice_proto_depIdxs = []int32{
+ 7, // 0: targetservice.BallIn.when:type_name -> google.protobuf.Timestamp
+ 7, // 1: targetservice.BallIn.now:type_name -> google.protobuf.Timestamp
+ 7, // 2: targetservice.BallOut.now:type_name -> google.protobuf.Timestamp
+ 4, // 3: targetservice.Body.hands:type_name -> targetservice.Limb
+ 4, // 4: targetservice.Body.legs:type_name -> targetservice.Limb
+ 4, // 5: targetservice.Body.tail:type_name -> targetservice.Limb
+ 0, // 6: targetservice.Bouncer.SayHello:input_type -> targetservice.HelloRequest
+ 0, // 7: targetservice.Bouncer.UnknownMethod:input_type -> targetservice.HelloRequest
+ 2, // 8: targetservice.Bouncer.BounceIt:input_type -> targetservice.BallIn
+ 5, // 9: targetservice.Bouncer.GrowTail:input_type -> targetservice.Body
+ 6, // 10: targetservice.Bouncer.Echo:input_type -> targetservice.EchoMsg
+ 1, // 11: targetservice.Bouncer.SayHello:output_type -> targetservice.HelloResponse
+ 1, // 12: targetservice.Bouncer.UnknownMethod:output_type -> targetservice.HelloResponse
+ 3, // 13: targetservice.Bouncer.BounceIt:output_type -> targetservice.BallOut
+ 5, // 14: targetservice.Bouncer.GrowTail:output_type -> targetservice.Body
+ 6, // 15: targetservice.Bouncer.Echo:output_type -> targetservice.EchoMsg
+ 11, // [11:16] is the sub-list for method output_type
+ 6, // [6:11] is the sub-list for method input_type
+ 6, // [6:6] is the sub-list for extension type_name
+ 6, // [6:6] is the sub-list for extension extendee
+ 0, // [0:6] is the sub-list for field type_name
+}
+
+func init() { file_targetservice_proto_init() }
+func file_targetservice_proto_init() {
+ if File_targetservice_proto != nil {
+ return
+ }
+ if !protoimpl.UnsafeEnabled {
+ file_targetservice_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*HelloRequest); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_targetservice_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*HelloResponse); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_targetservice_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*BallIn); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_targetservice_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*BallOut); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_targetservice_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*Limb); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_targetservice_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*Body); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_targetservice_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*EchoMsg); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ }
+ type x struct{}
+ out := protoimpl.TypeBuilder{
+ File: protoimpl.DescBuilder{
+ GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
+ RawDescriptor: file_targetservice_proto_rawDesc,
+ NumEnums: 0,
+ NumMessages: 7,
+ NumExtensions: 0,
+ NumServices: 1,
+ },
+ GoTypes: file_targetservice_proto_goTypes,
+ DependencyIndexes: file_targetservice_proto_depIdxs,
+ MessageInfos: file_targetservice_proto_msgTypes,
+ }.Build()
+ File_targetservice_proto = out.File
+ file_targetservice_proto_rawDesc = nil
+ file_targetservice_proto_goTypes = nil
+ file_targetservice_proto_depIdxs = nil
+}
diff --git a/kong-versions/3.9.0.0/kong/spec/fixtures/grpc/target/targetservice/targetservice_grpc.pb.go b/kong-versions/3.9.0.0/kong/spec/fixtures/grpc/target/targetservice/targetservice_grpc.pb.go
new file mode 100644
index 00000000..e59433d7
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/fixtures/grpc/target/targetservice/targetservice_grpc.pb.go
@@ -0,0 +1,251 @@
+// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
+// versions:
+// - protoc-gen-go-grpc v1.2.0
+// - protoc v3.21.7
+// source: targetservice.proto
+
+package targetservice
+
+import (
+ context "context"
+ grpc "google.golang.org/grpc"
+ codes "google.golang.org/grpc/codes"
+ status "google.golang.org/grpc/status"
+)
+
+// This is a compile-time assertion to ensure that this generated file
+// is compatible with the grpc package it is being compiled against.
+// Requires gRPC-Go v1.32.0 or later.
+const _ = grpc.SupportPackageIsVersion7
+
+// BouncerClient is the client API for Bouncer service.
+//
+// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
+type BouncerClient interface {
+ SayHello(ctx context.Context, in *HelloRequest, opts ...grpc.CallOption) (*HelloResponse, error)
+ // define a gRPC method that's not implemented in the target
+ UnknownMethod(ctx context.Context, in *HelloRequest, opts ...grpc.CallOption) (*HelloResponse, error)
+ BounceIt(ctx context.Context, in *BallIn, opts ...grpc.CallOption) (*BallOut, error)
+ GrowTail(ctx context.Context, in *Body, opts ...grpc.CallOption) (*Body, error)
+ Echo(ctx context.Context, in *EchoMsg, opts ...grpc.CallOption) (*EchoMsg, error)
+}
+
+type bouncerClient struct {
+ cc grpc.ClientConnInterface
+}
+
+func NewBouncerClient(cc grpc.ClientConnInterface) BouncerClient {
+ return &bouncerClient{cc}
+}
+
+func (c *bouncerClient) SayHello(ctx context.Context, in *HelloRequest, opts ...grpc.CallOption) (*HelloResponse, error) {
+ out := new(HelloResponse)
+ err := c.cc.Invoke(ctx, "/targetservice.Bouncer/SayHello", in, out, opts...)
+ if err != nil {
+ return nil, err
+ }
+ return out, nil
+}
+
+func (c *bouncerClient) UnknownMethod(ctx context.Context, in *HelloRequest, opts ...grpc.CallOption) (*HelloResponse, error) {
+ out := new(HelloResponse)
+ err := c.cc.Invoke(ctx, "/targetservice.Bouncer/UnknownMethod", in, out, opts...)
+ if err != nil {
+ return nil, err
+ }
+ return out, nil
+}
+
+func (c *bouncerClient) BounceIt(ctx context.Context, in *BallIn, opts ...grpc.CallOption) (*BallOut, error) {
+ out := new(BallOut)
+ err := c.cc.Invoke(ctx, "/targetservice.Bouncer/BounceIt", in, out, opts...)
+ if err != nil {
+ return nil, err
+ }
+ return out, nil
+}
+
+func (c *bouncerClient) GrowTail(ctx context.Context, in *Body, opts ...grpc.CallOption) (*Body, error) {
+ out := new(Body)
+ err := c.cc.Invoke(ctx, "/targetservice.Bouncer/GrowTail", in, out, opts...)
+ if err != nil {
+ return nil, err
+ }
+ return out, nil
+}
+
+func (c *bouncerClient) Echo(ctx context.Context, in *EchoMsg, opts ...grpc.CallOption) (*EchoMsg, error) {
+ out := new(EchoMsg)
+ err := c.cc.Invoke(ctx, "/targetservice.Bouncer/Echo", in, out, opts...)
+ if err != nil {
+ return nil, err
+ }
+ return out, nil
+}
+
+// BouncerServer is the server API for Bouncer service.
+// All implementations must embed UnimplementedBouncerServer
+// for forward compatibility
+type BouncerServer interface {
+ SayHello(context.Context, *HelloRequest) (*HelloResponse, error)
+ // define a gRPC method that's not implemented in the target
+ UnknownMethod(context.Context, *HelloRequest) (*HelloResponse, error)
+ BounceIt(context.Context, *BallIn) (*BallOut, error)
+ GrowTail(context.Context, *Body) (*Body, error)
+ Echo(context.Context, *EchoMsg) (*EchoMsg, error)
+ mustEmbedUnimplementedBouncerServer()
+}
+
+// UnimplementedBouncerServer must be embedded to have forward compatible implementations.
+type UnimplementedBouncerServer struct {
+}
+
+func (UnimplementedBouncerServer) SayHello(context.Context, *HelloRequest) (*HelloResponse, error) {
+ return nil, status.Errorf(codes.Unimplemented, "method SayHello not implemented")
+}
+func (UnimplementedBouncerServer) UnknownMethod(context.Context, *HelloRequest) (*HelloResponse, error) {
+ return nil, status.Errorf(codes.Unimplemented, "method UnknownMethod not implemented")
+}
+func (UnimplementedBouncerServer) BounceIt(context.Context, *BallIn) (*BallOut, error) {
+ return nil, status.Errorf(codes.Unimplemented, "method BounceIt not implemented")
+}
+func (UnimplementedBouncerServer) GrowTail(context.Context, *Body) (*Body, error) {
+ return nil, status.Errorf(codes.Unimplemented, "method GrowTail not implemented")
+}
+func (UnimplementedBouncerServer) Echo(context.Context, *EchoMsg) (*EchoMsg, error) {
+ return nil, status.Errorf(codes.Unimplemented, "method Echo not implemented")
+}
+func (UnimplementedBouncerServer) mustEmbedUnimplementedBouncerServer() {}
+
+// UnsafeBouncerServer may be embedded to opt out of forward compatibility for this service.
+// Use of this interface is not recommended, as added methods to BouncerServer will
+// result in compilation errors.
+type UnsafeBouncerServer interface {
+ mustEmbedUnimplementedBouncerServer()
+}
+
+func RegisterBouncerServer(s grpc.ServiceRegistrar, srv BouncerServer) {
+ s.RegisterService(&Bouncer_ServiceDesc, srv)
+}
+
+func _Bouncer_SayHello_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+ in := new(HelloRequest)
+ if err := dec(in); err != nil {
+ return nil, err
+ }
+ if interceptor == nil {
+ return srv.(BouncerServer).SayHello(ctx, in)
+ }
+ info := &grpc.UnaryServerInfo{
+ Server: srv,
+ FullMethod: "/targetservice.Bouncer/SayHello",
+ }
+ handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ return srv.(BouncerServer).SayHello(ctx, req.(*HelloRequest))
+ }
+ return interceptor(ctx, in, info, handler)
+}
+
+func _Bouncer_UnknownMethod_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+ in := new(HelloRequest)
+ if err := dec(in); err != nil {
+ return nil, err
+ }
+ if interceptor == nil {
+ return srv.(BouncerServer).UnknownMethod(ctx, in)
+ }
+ info := &grpc.UnaryServerInfo{
+ Server: srv,
+ FullMethod: "/targetservice.Bouncer/UnknownMethod",
+ }
+ handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ return srv.(BouncerServer).UnknownMethod(ctx, req.(*HelloRequest))
+ }
+ return interceptor(ctx, in, info, handler)
+}
+
+func _Bouncer_BounceIt_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+ in := new(BallIn)
+ if err := dec(in); err != nil {
+ return nil, err
+ }
+ if interceptor == nil {
+ return srv.(BouncerServer).BounceIt(ctx, in)
+ }
+ info := &grpc.UnaryServerInfo{
+ Server: srv,
+ FullMethod: "/targetservice.Bouncer/BounceIt",
+ }
+ handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ return srv.(BouncerServer).BounceIt(ctx, req.(*BallIn))
+ }
+ return interceptor(ctx, in, info, handler)
+}
+
+func _Bouncer_GrowTail_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+ in := new(Body)
+ if err := dec(in); err != nil {
+ return nil, err
+ }
+ if interceptor == nil {
+ return srv.(BouncerServer).GrowTail(ctx, in)
+ }
+ info := &grpc.UnaryServerInfo{
+ Server: srv,
+ FullMethod: "/targetservice.Bouncer/GrowTail",
+ }
+ handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ return srv.(BouncerServer).GrowTail(ctx, req.(*Body))
+ }
+ return interceptor(ctx, in, info, handler)
+}
+
+func _Bouncer_Echo_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+ in := new(EchoMsg)
+ if err := dec(in); err != nil {
+ return nil, err
+ }
+ if interceptor == nil {
+ return srv.(BouncerServer).Echo(ctx, in)
+ }
+ info := &grpc.UnaryServerInfo{
+ Server: srv,
+ FullMethod: "/targetservice.Bouncer/Echo",
+ }
+ handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ return srv.(BouncerServer).Echo(ctx, req.(*EchoMsg))
+ }
+ return interceptor(ctx, in, info, handler)
+}
+
+// Bouncer_ServiceDesc is the grpc.ServiceDesc for Bouncer service.
+// It's only intended for direct use with grpc.RegisterService,
+// and not to be introspected or modified (even as a copy)
+var Bouncer_ServiceDesc = grpc.ServiceDesc{
+ ServiceName: "targetservice.Bouncer",
+ HandlerType: (*BouncerServer)(nil),
+ Methods: []grpc.MethodDesc{
+ {
+ MethodName: "SayHello",
+ Handler: _Bouncer_SayHello_Handler,
+ },
+ {
+ MethodName: "UnknownMethod",
+ Handler: _Bouncer_UnknownMethod_Handler,
+ },
+ {
+ MethodName: "BounceIt",
+ Handler: _Bouncer_BounceIt_Handler,
+ },
+ {
+ MethodName: "GrowTail",
+ Handler: _Bouncer_GrowTail_Handler,
+ },
+ {
+ MethodName: "Echo",
+ Handler: _Bouncer_Echo_Handler,
+ },
+ },
+ Streams: []grpc.StreamDesc{},
+ Metadata: "targetservice.proto",
+}
diff --git a/kong-versions/3.9.0.0/kong/spec/fixtures/grpc/targetservice.proto b/kong-versions/3.9.0.0/kong/spec/fixtures/grpc/targetservice.proto
new file mode 100644
index 00000000..e2f887fe
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/fixtures/grpc/targetservice.proto
@@ -0,0 +1,95 @@
+syntax = "proto3";
+
+package targetservice;
+
+import "google/api/annotations.proto";
+import "google/protobuf/timestamp.proto";
+
+option go_package = "./targetservice";
+
+service Bouncer {
+ rpc SayHello(HelloRequest) returns (HelloResponse) {
+ option (google.api.http) = {
+ // https://github.com/googleapis/googleapis/blob/master/google/api/http.proto
+ // HTTP | gRPC
+ // -----|-----
+ // `GET /v1/messages/123456` | `HelloRequest(greeting: "123456")`
+ get: "/v1/messages/{greeting}"
+ additional_bindings {
+ get: "/v1/messages/legacy/{greeting=**}"
+ additional_bindings {
+ post: "/v1/messages/"
+ }
+ }
+ body: "*"
+ };
+ };
+
+ // define a gRPC method that's not implemented in the target
+ rpc UnknownMethod(HelloRequest) returns (HelloResponse) {
+ option (google.api.http) = {
+ get: "/v1/unknown/{greeting}"
+ };
+ };
+
+ rpc BounceIt (BallIn) returns (BallOut) {
+ option (google.api.http) = {
+ post: "/bounce"
+ body: "*"
+ };
+ }
+
+ rpc GrowTail(Body) returns (Body) {
+ option (google.api.http) = {
+ get: "/v1/grow/tail"
+ };
+ }
+
+ rpc Echo(EchoMsg) returns (EchoMsg) {
+ option (google.api.http) = {
+ post: "/v1/echo"
+ body: "*"
+ };
+ }
+}
+
+
+message HelloRequest {
+ string greeting = 1;
+ bool boolean_test = 2;
+}
+
+message HelloResponse {
+ string reply = 1;
+ bool boolean_test = 2;
+}
+
+
+message BallIn {
+ string message = 1;
+ google.protobuf.Timestamp when = 2;
+ google.protobuf.Timestamp now = 3;
+}
+
+message BallOut {
+ string reply = 1;
+ string time_message = 2;
+ google.protobuf.Timestamp now = 3;
+}
+
+message Limb {
+ int32 count = 1;
+ string endings = 2;
+}
+
+message Body {
+ string name = 1;
+ Limb hands = 2;
+ Limb legs = 3;
+ Limb tail = 4;
+}
+
+message EchoMsg {
+ repeated string array = 1;
+ string nullable = 2;
+}
diff --git a/kong-versions/3.9.0.0/kong/spec/fixtures/headers.conf b/kong-versions/3.9.0.0/kong/spec/fixtures/headers.conf
new file mode 100644
index 00000000..36df085d
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/fixtures/headers.conf
@@ -0,0 +1,28 @@
+# 1st digit is 9 for our test instances
+admin_listen = 127.0.0.1:9001
+proxy_listen = 0.0.0.0:9000, 0.0.0.0:9443 ssl
+
+ssl_cert = spec/fixtures/kong_spec.crt
+ssl_cert_key = spec/fixtures/kong_spec.key
+
+admin_ssl_cert = spec/fixtures/kong_spec.crt
+admin_ssl_cert_key = spec/fixtures/kong_spec.key
+
+database = postgres
+pg_host = 127.0.0.1
+pg_port = 5432
+pg_timeout = 10000
+pg_database = kong_tests
+anonymous_reports = off
+
+dns_hostsfile = spec/fixtures/hosts
+
+nginx_main_worker_processes = 1
+nginx_main_worker_rlimit_nofile = 4096
+nginx_events_worker_connections = 4096
+nginx_events_multi_accept = off
+
+prefix = servroot
+log_level = debug
+
+headers = server_tokens, X-Kong-Proxy-Latency
diff --git a/kong-versions/3.9.0.0/kong/spec/fixtures/hosts b/kong-versions/3.9.0.0/kong/spec/fixtures/hosts
new file mode 100644
index 00000000..75721cd5
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/fixtures/hosts
@@ -0,0 +1 @@
+127.0.0.1 localhost
diff --git a/kong-versions/3.9.0.0/kong/spec/fixtures/https_server.lua b/kong-versions/3.9.0.0/kong/spec/fixtures/https_server.lua
new file mode 100644
index 00000000..9ad2c61b
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/fixtures/https_server.lua
@@ -0,0 +1,289 @@
+-- This software is copyright Kong Inc. and its licensors.
+-- Use of the software is subject to the agreement between your organization
+-- and Kong Inc. If there is no such agreement, use is governed by and
+-- subject to the terms of the Kong Master Software License Agreement found
+-- at https://konghq.com/enterprisesoftwarelicense/.
+-- [ END OF LICENSE 0867164ffc95e54f04670b5169c09574bdbd9bba ]
+
+local https_server = {}
+https_server.__index = https_server
+
+
+local fmt = string.format
+local mock_srv_tpl_file = require "spec.fixtures.mock_webserver_tpl"
+local ngx = require "ngx"
+local pl_dir = require "pl.dir"
+local pl_file = require "pl.file"
+local pl_template = require "pl.template"
+local pl_path = require "pl.path"
+local uuid = require "resty.jit-uuid"
+local http_client = require "resty.http"
+local cjson = require "cjson"
+local shell = require "resty.shell"
+
+
+local Template = require("pl.stringx").Template
+
+
+-- we need this to get random UUIDs
+math.randomseed(os.time())
+
+
+local HTTPS_SERVER_START_MAX_RETRY = 10
+
+local tmp_root = os.getenv("TMPDIR") or "/tmp"
+local host_regex = [[([a-z0-9\-._~%!$&'()*+,;=]+@)?([a-z0-9\-._~%]+|\[[a-z0-9\-._~%!$&'()*+,;=:]+\])(:?[0-9]+)*]]
+
+
+
+local function create_temp_dir(copy_cert_and_key)
+ local tmp_name = fmt("nginx_%s", uuid())
+ local tmp_path = fmt("%s/%s", tmp_root, tmp_name)
+ local _, err = pl_path.mkdir(tmp_path)
+ if err then
+ return nil, err
+ end
+
+ local _, err = pl_path.mkdir(tmp_path .. "/logs")
+ if err then
+ return nil, err
+ end
+
+ if copy_cert_and_key then
+ local status = pl_dir.copyfile("./spec/fixtures/kong_spec.crt", tmp_path)
+ if not status then
+ return nil, "could not copy cert"
+ end
+
+ status = pl_dir.copyfile("./spec/fixtures/kong_spec.key", tmp_path)
+ if not status then
+ return nil, "could not copy private key"
+ end
+ end
+
+ return tmp_path
+end
+
+
+local function create_conf(params)
+ local tpl, err = pl_template.compile(mock_srv_tpl_file)
+ if err then
+ return nil, err
+ end
+
+ local compiled_tpl = Template(tpl:render(params, { ipairs = ipairs }))
+ local conf_filename = params.base_path .. "/nginx.conf"
+ local conf, err = io.open (conf_filename, "w")
+ if err then
+ return nil, err
+ end
+
+ conf:write(compiled_tpl:substitute(params))
+ conf:close()
+
+ return conf_filename
+end
+
+
+local function count_results(logs_dir)
+ local results = {
+ ["ok"] = 0,
+ ["fail"] = 0,
+ ["total"] = 0,
+ ["status_ok"] = 0,
+ ["status_fail"] = 0,
+ ["status_total"] = 0
+ }
+ local error_log_filename = logs_dir .. "/error.log"
+
+ for line in io.lines(error_log_filename) do
+ local m = ngx.re.match(line, [[^.*\[COUNT\] (.+) (\d\d\d)\,.*\, host: \"(.+)\"$]])
+ if m then
+ local location = m[1]
+ local status = m[2]
+ local host = m[3]
+ if host then
+ local host_no_port = ngx.re.match(m[3], host_regex)
+ if host_no_port then
+ host = host_no_port[2]
+ end
+ else
+ host = "nonamehost"
+ end
+ if results[host] == nil then
+ results[host] = {
+ ["ok"] = 0,
+ ["fail"] = 0,
+ ["status_ok"] = 0,
+ ["status_fail"] = 0,
+ }
+ end
+
+ if location == "slash" then
+ if status == "200" then
+ results.ok = results.ok + 1
+ results[host].ok = results[host].ok + 1
+ else
+ results.fail = results.fail + 1
+ results[host].fail = results[host].fail + 1
+ end
+ results.total = results.ok + results.fail
+ elseif location == "status" then
+ if status == "200" then
+ results.status_ok = results.status_ok + 1
+ results[host].status_ok = results[host].status_ok + 1
+ else
+ results.status_fail = results.status_fail + 1
+ results[host].status_fail = results[host].status_fail + 1
+ end
+ results.status_total = results.status_ok + results.status_fail
+ end
+ end
+ end
+
+ return results
+end
+
+
+function https_server.clear_access_log(self)
+ local client = assert(http_client.new())
+
+ local uri = string.format("%s://%s:%d/clear_log", self.protocol, self.host, self.http_port)
+
+ local res = assert(client:request_uri(uri, {
+ method = "GET"
+ }))
+
+ assert(res.body == "cleared\n")
+end
+
+
+function https_server.get_access_log(self)
+ local client = assert(http_client.new())
+
+ local uri = string.format("%s://%s:%d/log?do_not_log", self.protocol, self.host, self.http_port)
+
+ local res = assert(client:request_uri(uri, {
+ method = "GET"
+ }))
+
+ return assert(cjson.decode(res.body))
+end
+
+
+function https_server.start(self)
+ if not pl_path.exists(tmp_root) or not pl_path.isdir(tmp_root) then
+ error("could not get a temporary path", 2)
+ end
+
+ local err
+ self.base_path, err = create_temp_dir(self.protocol == "https")
+ if err then
+ error(fmt("could not create temp dir: %s", err), 2)
+ end
+
+ local conf_params = {
+ base_path = self.base_path,
+ delay = self.delay,
+ cert_path = "./",
+ check_hostname = self.check_hostname,
+ logs_dir = self.logs_dir,
+ host = self.host,
+ hosts = self.hosts,
+ http_port = self.http_port,
+ protocol = self.protocol,
+ worker_num = self.worker_num,
+ disable_ipv6 = self.disable_ipv6,
+ }
+
+ local file, err = create_conf(conf_params)
+ if err then
+ error(fmt("could not create conf: %s", err), 2)
+ end
+
+ for _ = 1, HTTPS_SERVER_START_MAX_RETRY do
+ if shell.run("nginx -c " .. file .. " -p " .. self.base_path, nil, 0) then
+ return
+ end
+
+ ngx.sleep(1)
+ end
+
+ error("failed starting nginx")
+end
+
+
+function https_server.shutdown(self)
+ local pid_filename = self.base_path .. "/logs/nginx.pid"
+ local pid_file = io.open (pid_filename, "r")
+ if pid_file then
+ local pid, err = pid_file:read()
+ if err then
+ error(fmt("could not read pid file: %s", tostring(err)), 2)
+ end
+
+ local kill_nginx_cmd = fmt("kill -s TERM %s", tostring(pid))
+ local status = shell.run(kill_nginx_cmd, nil, 0)
+ if not status then
+ error(fmt("could not kill nginx test server. %s was not removed", self.base_path), 2)
+ end
+
+ local pidfile_removed
+ local watchdog = 0
+ repeat
+ pidfile_removed = pl_file.access_time(pid_filename) == nil
+ if not pidfile_removed then
+ ngx.sleep(0.01)
+ watchdog = watchdog + 1
+ if(watchdog > 100) then
+ error("could not stop nginx", 2)
+ end
+ end
+ until(pidfile_removed)
+ end
+
+ local count, err = count_results(self.base_path .. "/" .. self.logs_dir)
+ if err then
+ -- not a fatal error
+ print(fmt("could not count results: %s", tostring(err)))
+ end
+
+ local _, err = pl_dir.rmtree(self.base_path)
+ if err then
+ print(fmt("could not remove %s: %s", self.base_path, tostring(err)))
+ end
+
+ return count
+end
+
+-- **DEPRECATED**: please use `spec.helpers.http_mock` instead.
+function https_server.new(port, hostname, protocol, check_hostname, workers, delay, disable_ipv6)
+ local self = setmetatable({}, https_server)
+ local host
+ local hosts
+
+ if type(hostname) == "table" then
+ hosts = hostname
+ host = ""
+ for _, h in ipairs(hostname) do
+ host = fmt("%s %s", host, h)
+ end
+ else
+ hosts = {hostname}
+ host = hostname
+ end
+
+ self.check_hostname = check_hostname or false
+ self.delay = tonumber(delay) or 0
+ self.host = host or "localhost"
+ self.hosts = hosts
+ self.http_port = port
+ self.logs_dir = "logs"
+ self.protocol = protocol or "http"
+ self.worker_num = workers or 2
+ self.disable_ipv6 = disable_ipv6
+
+ return self
+end
+
+return https_server
diff --git a/kong-versions/3.9.0.0/kong/spec/fixtures/invalid-module.lua b/kong-versions/3.9.0.0/kong/spec/fixtures/invalid-module.lua
new file mode 100644
index 00000000..e40e5929
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/fixtures/invalid-module.lua
@@ -0,0 +1,12 @@
+-- This software is copyright Kong Inc. and its licensors.
+-- Use of the software is subject to the agreement between your organization
+-- and Kong Inc. If there is no such agreement, use is governed by and
+-- subject to the terms of the Kong Master Software License Agreement found
+-- at https://konghq.com/enterprisesoftwarelicense/.
+-- [ END OF LICENSE 0867164ffc95e54f04670b5169c09574bdbd9bba ]
+
+-- Invalid module (syntax error) for utils.load_module_if_exists unit tests.
+-- Assert that load_module_if_exists throws an error helps for development, where one could
+-- be confused as to the reason why his or her plugin doesn't load. (not implemented or has an error)
+
+local a = "hello",
diff --git a/kong-versions/3.9.0.0/kong/spec/fixtures/invalid.conf b/kong-versions/3.9.0.0/kong/spec/fixtures/invalid.conf
new file mode 100644
index 00000000..fbbfedcc
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/fixtures/invalid.conf
@@ -0,0 +1,3 @@
+pg_ssl = on
+database = postgres
+untrusted_lua = foobar
diff --git a/kong-versions/3.9.0.0/kong/spec/fixtures/invalid_nginx_directives.conf b/kong-versions/3.9.0.0/kong/spec/fixtures/invalid_nginx_directives.conf
new file mode 100644
index 00000000..46738cc2
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/fixtures/invalid_nginx_directives.conf
@@ -0,0 +1 @@
+nginx_http_random_directive = value
diff --git a/kong-versions/3.9.0.0/kong/spec/fixtures/jwks.lua b/kong-versions/3.9.0.0/kong/spec/fixtures/jwks.lua
new file mode 100644
index 00000000..24712e93
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/fixtures/jwks.lua
@@ -0,0 +1,69 @@
+-- This software is copyright Kong Inc. and its licensors.
+-- Use of the software is subject to the agreement between your organization
+-- and Kong Inc. If there is no such agreement, use is governed by and
+-- subject to the terms of the Kong Master Software License Agreement found
+-- at https://konghq.com/enterprisesoftwarelicense/.
+-- [ END OF LICENSE 0867164ffc95e54f04670b5169c09574bdbd9bba ]
+
+local client_jwk = {
+ p =
+ "2OZf9JxDwXpXLokSpjFq81XZfrG1_cSqzi-ZMzbiqpVKdBYhZ77SfV2xsgK7kAxo_4Jh0Bh3MFt9NvYll8pE6VBDVPRLmAIcv7-UMkSVbUnRdltT5ElROViTy57iJO3BlzOiFHENhA_DnQrDRVtLuPFyMZVYHXuWWTfJveXh2xU",
+ kty = "RSA",
+ q =
+ "sC8S3S-rKb2GFzfmSNDw5thy-2sLWMKPPWloN5jIWqHB2OumYzzUR_2TLkrf4SBQ-69qbfamoce8El_ipRnBbJRzd-qO8kjgRgK9_v_trxmcDiqb__Mivyu2J0a2-13VyS12tFAM9DVfewcR10V_bNsxV15WaMNmqslpHuHyPkk",
+ d =
+ "QRes9v86K0SMfBLLalyDMR5BUdI8uF_e6vmYCU9i7kYkGMGdwEVy9ZJ5Zz8EptbUuUpH3lCnstEyCZJ92CFieGAiw95S9BQNqKYaQJi2vnWopPHExDmNy6p2opSzaskBh0UlgVfQ_9bCHaXC-L-63lg1vqm3Lb2vGhqfKCJ_n1O8Y078l2Bp1zf8t3kAT7yix7qvO7HO_8JcWXecMpnZp2BYvUTUC5x58UGz30JzIuhsZqEGjiYInSJ5NyUuiC5sYrSW87ClsmrsM3QtieEekceqdCPimIcNyL6hetQ_sEeAVNsX7Pr1Ptf68cLmFf5SygLsqPZn4QUzOhmX5IHPQQ",
+ e = "AQAB",
+ use = "sig",
+ kid = "test",
+ qi =
+ "jZMzMywer5cauHZSdSa0bUBh1pm3Xs3-hGYz87He9at8rgwJOrbExn3gnt7j0YOqgbto3hRa5c15dW5zijElhLxlOfYm3Mx8iqjx6wZwCzgh0_gcGg0K2z9NyFo5jr9cx4ADFPQbeBg1nJuSDCSM4dKZDRIoea67ZOlD0nVX31U",
+ dp =
+ "1WUidujfCJWy_IfDn1rzXGDUUP_Ki9dYLO9LjMWtECM9UyUKzKVDNjBeSULDAiATlX7TeQb5DMyWTuKxbbuFPP7In-aSEQXS_xwfU62CTjnYKNgFm44-qWrqTeUNnUOFuZsFFZN8trdDv1f9clk2EMkLjpjeTnNvImvuwjRPl1k",
+ alg = "RS512",
+ dq =
+ "V2pz3KUbMvGjR3_n1bc93_wDSPW6woZ-VcUn_XXj6vwZV0zM2K5E0ZdiYHSsEmJbbBWEJB1eXiThDujeZnaZ_wrFI_mQhWxdQr93j79iKh_1yx2fG2aClgHVNjWi8qODQHc7T4nsc3rL7hn64ynLaLJ1D9lx3DcfiJu4eac372k",
+ n =
+ "lUZEP2Nan3nFork1tElu5V8-pwsvMibfAau3ADpM6OqBF4n08eSeHeWC2uZltQkLKaU_n-dm0INUv72QDJsaZ-ZNCc9LST_HNoQQ5qPH86RDPmMEus_OdKJ7V57gxJzWonwzJ3sDdGW1QjK1Hb8kHnwM46uPoHHF_Iottc6oUXIiXQ18hTFFsKtpeSUl6PsA76j3pvxOLPFhJPtgZ2p9WhwDmiav6oK4XXgyhxolkF7kBVNSIqZrGI4_KAuxVpZiX3t-4pzHV4Rh6_YBmA9OgdVJ3WfKjGiPpz8YA4PmhXPND2nFXm4_GUWm3_QIhD1Cyk6jO8RRUUEZI59Xz1CO_Q"
+}
+
+local client_jwk_public = {
+ kty = "RSA",
+ e = "AQAB",
+ use = "sig",
+ kid = "test",
+ alg = "RS512",
+ n =
+ "lUZEP2Nan3nFork1tElu5V8-pwsvMibfAau3ADpM6OqBF4n08eSeHeWC2uZltQkLKaU_n-dm0INUv72QDJsaZ-ZNCc9LST_HNoQQ5qPH86RDPmMEus_OdKJ7V57gxJzWonwzJ3sDdGW1QjK1Hb8kHnwM46uPoHHF_Iottc6oUXIiXQ18hTFFsKtpeSUl6PsA76j3pvxOLPFhJPtgZ2p9WhwDmiav6oK4XXgyhxolkF7kBVNSIqZrGI4_KAuxVpZiX3t-4pzHV4Rh6_YBmA9OgdVJ3WfKjGiPpz8YA4PmhXPND2nFXm4_GUWm3_QIhD1Cyk6jO8RRUUEZI59Xz1CO_Q"
+}
+
+local client2_jwk = {
+ p = "0uCA8VaL5xxR8G2eFCo1ZfigXEDWS8IjWhB0jrIFsruRSEOo5ZvPq6AK23pI3-QwG05IZTyPegsJL_VXKiPzBXiPxCn1C_nlJY0EjYAdzPhQVub3Jv820cPIXWhgzCVmX1eU_gX1uU7BksHHViIPqQ180huyes4eDP0LVz2sisk",
+ kty = "RSA",
+ q = "ymSY6f7peJTh3i_IfQdoymrhuFT3PB6EOjDCEtaiKUfzC4iy4Sj4zlCAm4hvoo1O9Bl_qeGRVsFFz47JD66Kd1S0fJV-5ZmyroKy0h1vcwNudUWdNZlplQfg22I3GgNeWzte_xFF7kyv49BFkPPZ9VyAfDSdzN4ngv-JLkaFz1c",
+ d = "nR5APnZezsNHk9kbHeq1Who_YQPikMlqNI39bEbTWq_eSsAkpgSIMQv8r_w76_9jL2ilYu26arWxi4ReEa8HvbIc9VxLRO392zw6JdPrNBVfWRw5YFkBf5V3_5B8VDjzmuUNpZHR6H92MhLJ7P3kqd6kIb9fJLFZlqkKQs-XPtfI4eTNfsuSkDLqaxGs6dRSc7za6wqnajJUuX0ThwEGRUjBEdx5fzCJH5_8-Y4DMb7qmgM24nNR9pHqhmSDJFDUSuqRNZEyZD-9wnl-A2rXMakNknll-4WkjlcccqzDSMoHpCyXkn5fduMrHuBSBqsIIWJCIVnwuSaOjCh8nlwBkQ",
+ e = "AQAB",
+ use = "sig",
+ kid = "test2",
+ qi = "RN8D_k4J2bx247FKfLsabNBczUDKE2YlJSru2viQJzy9doEPAd0WCMQ2da5xc3JubHmnnfpUWMcl4bcOOVlMSEIu57NSqy1N3xY52m_OztfceRc4R1Ri1i79mX17w2cFDGiE7HIQtWEmCw8ijN1-7JzJq1StkhtHgTFPGTXI2FE",
+ dp = "C8HkrpAKwNn9X5BdDfbEf2j7V-ltiU_LtMvSE9qtIqf-k67iDdtAGuuTb2VEBuesHvmgY7Sas01GN9xP_dN_S0DLkz5boU1Pj2ZraJBKGRGHOTEreoskPVHTLBITw44aRRqW_grLBofzlwEi4hSIFv7fhL9ylhJD7ql1JmoT4rE",
+ alg = "RS512",
+ dq = "CKTZPw0rDYJWTzX9OxHI8PQ1pbjDQmcPQKj6cPGHxXmUMMbq1OD6F12q0Hm4QtoEKDq6kBfZLDpe7-lqPug2c7hDaRq9a7LvxbJBTuYA74mS-yE5AKQHtVy7xsLgFZVVP1I-0Wf8c5wE2xb3EaTIh0knF6bromdOirK9OiO67Us",
+ n = "prgDZtlv66YmFnnyPkWbJFYi_Ozz2qmyAod4loa_lzsbGP3Db4wziSAs8mmrSbjYfX1U-OvIYKiykPiIim1F7EUQjF4GZX8luCUPmO8MLoqC2PMIXvGyBU84I2pz0a6ipxDs_5IkXDRNjHhEieyVfxVKz_8CSLphMohlJqRelGFtGMp89zu5ZQix1CA3UpMnAlQg_peDMob81VeYYus8S92moL110V8JPsiv7Ao4eQ6aUyS0dJZGW9dMckDaNz5kf9XppeKFP3X_d6mdUeDODRSH-O4bxA8mGR1tPWDXrelXn86r1969JSJtvwpsc3qwSueORH4hgu2A2B85ikixTw"
+}
+
+local client2_jwk_public = {
+ kty = "RSA",
+ e = "AQAB",
+ use = "sig",
+ kid = "test2",
+ alg = "RS512",
+ n = "prgDZtlv66YmFnnyPkWbJFYi_Ozz2qmyAod4loa_lzsbGP3Db4wziSAs8mmrSbjYfX1U-OvIYKiykPiIim1F7EUQjF4GZX8luCUPmO8MLoqC2PMIXvGyBU84I2pz0a6ipxDs_5IkXDRNjHhEieyVfxVKz_8CSLphMohlJqRelGFtGMp89zu5ZQix1CA3UpMnAlQg_peDMob81VeYYus8S92moL110V8JPsiv7Ao4eQ6aUyS0dJZGW9dMckDaNz5kf9XppeKFP3X_d6mdUeDODRSH-O4bxA8mGR1tPWDXrelXn86r1969JSJtvwpsc3qwSueORH4hgu2A2B85ikixTw"
+}
+
+return {
+ client_jwk = client_jwk,
+ client_jwk_public = client_jwk_public,
+ client2_jwk = client2_jwk,
+ client2_jwk_public = client2_jwk_public,
+}
diff --git a/kong-versions/3.9.0.0/kong/spec/fixtures/key-auth-enc/FTI-4592.yaml b/kong-versions/3.9.0.0/kong/spec/fixtures/key-auth-enc/FTI-4592.yaml
new file mode 100644
index 00000000..c6ac85ec
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/fixtures/key-auth-enc/FTI-4592.yaml
@@ -0,0 +1,64 @@
+# workspace default
+_format_version: "3.0"
+_transform: false
+
+workspaces:
+ - name: default
+ id: 213e4358-0611-4a0f-8b6a-e1a0df608a04
+ - name: test
+ id: 84c4e4b7-a307-4478-8875-27a484599159
+
+consumers:
+ - id: 1bd69f90-741c-4e75-834e-94155d6e3f5d
+ username: bob
+ ws_id: 213e4358-0611-4a0f-8b6a-e1a0df608a04
+ - id: 8df2d29b-fb8f-45b2-b90d-4b7fdbaa92e7
+ username: bob
+ ws_id: 84c4e4b7-a307-4478-8875-27a484599159
+
+keyauth_enc_credentials:
+ - key: wcKDwkL3I5nOCDVd8qlMhWKSV69NE7uf
+ id: 05f41be3-0002-4fcf-b361-3f479bf2e437
+ consumer: 1bd69f90-741c-4e75-834e-94155d6e3f5d
+ ws_id: 213e4358-0611-4a0f-8b6a-e1a0df608a04
+ - key: wcKDwkL3I5nOCDVd8qlMhWKSV69NE7uf
+ id: 535cb5a1-d8b5-4698-a75a-6fcda03ed08f
+ consumer: 8df2d29b-fb8f-45b2-b90d-4b7fdbaa92e7
+ ws_id: 84c4e4b7-a307-4478-8875-27a484599159
+
+
+services:
+ - host: localhost
+ name: example-service-1
+ port: 9036
+ protocol: http
+ ws_id: 213e4358-0611-4a0f-8b6a-e1a0df608a04
+ id: 6e40e2ba-3a9a-4201-87ef-fd6029005da7
+ - host: localhost
+ name: example-service-2
+ port: 9036
+ protocol: http
+ ws_id: 84c4e4b7-a307-4478-8875-27a484599159
+ id: 9c70e94e-341a-4bd4-b62a-7d1e42778746
+
+routes:
+ - https_redirect_status_code: 426
+ name: example-route-1
+ ws_id: 213e4358-0611-4a0f-8b6a-e1a0df608a04
+ service: 6e40e2ba-3a9a-4201-87ef-fd6029005da7
+ paths:
+ - /test1
+ - https_redirect_status_code: 426
+ name: example-route-2
+ ws_id: 84c4e4b7-a307-4478-8875-27a484599159
+ service: 9c70e94e-341a-4bd4-b62a-7d1e42778746
+ paths:
+ - /test2
+
+plugins:
+ - name: key-auth-enc
+ ws_id: 213e4358-0611-4a0f-8b6a-e1a0df608a04
+ service: 6e40e2ba-3a9a-4201-87ef-fd6029005da7
+ - name: key-auth-enc
+ ws_id: 84c4e4b7-a307-4478-8875-27a484599159
+ service: 9c70e94e-341a-4bd4-b62a-7d1e42778746
diff --git a/kong-versions/3.9.0.0/kong/spec/fixtures/kong_clustering.crt b/kong-versions/3.9.0.0/kong/spec/fixtures/kong_clustering.crt
new file mode 100644
index 00000000..a92d31ca
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/fixtures/kong_clustering.crt
@@ -0,0 +1,23 @@
+-----BEGIN CERTIFICATE-----
+MIIDzTCCArWgAwIBAgIUMmq4W4is+P02LXKinUdLoPjFuDYwDQYJKoZIhvcNAQEL
+BQAwdjELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExFjAUBgNVBAcM
+DVNhbiBGcmFuY2lzY28xIDAeBgNVBAoMF0tvbmcgQ2x1c3RlcmluZyBUZXN0aW5n
+MRgwFgYDVQQDDA9rb25nX2NsdXN0ZXJpbmcwHhcNMTkxMTEzMDU0NTA1WhcNMjkx
+MTEwMDU0NTA1WjB2MQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEW
+MBQGA1UEBwwNU2FuIEZyYW5jaXNjbzEgMB4GA1UECgwXS29uZyBDbHVzdGVyaW5n
+IFRlc3RpbmcxGDAWBgNVBAMMD2tvbmdfY2x1c3RlcmluZzCCASIwDQYJKoZIhvcN
+AQEBBQADggEPADCCAQoCggEBALr7evXK3nLxW98lXDWUcyNRCKDzUVX5Rlm7ny0a
+qVIh+qRUT7XGHFnDznl7s1gEkcxLtuMnKBV7Ic2jVTzKluZZFJD5H2plP7flpVu/
+byvpBNguERFDC2mbnlX7TSRhhWjlYTgFS2KiFP1OjYjim6vemszobDsCg2gRs0Mh
+A7XwsVvPSFNfnAOPTpyLRGtN3ShEA0LKjBkjg2u67MPAfg1y8/8Tm3h/kqfOciMT
+5ax2J1Ll/9/oCWX9qW6gNmnnUGNlBpcAZk3pzh6n1coRnVaysoCPYPgd9u1KoBkt
+uTQJOn1Qi3OWPZzyiLGRa/X0tGx/5QQDnLr6GyDjwPcC09sCAwEAAaNTMFEwHQYD
+VR0OBBYEFNNvhlhHAsJtBZejHystlPa/CoP2MB8GA1UdIwQYMBaAFNNvhlhHAsJt
+BZejHystlPa/CoP2MA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEB
+AHQpVBYGfFPFTRY/HvtWdXROgW358m9rUC5E4SfTJ8JLWpCB4J+hfjQ+mASTFb1V
+5FS8in8S/u1MgeU65RC1/xt6Rof7Tu/Cx2SusPWo0YGyN0E9mwr2c91JsIgDO03Y
+gtDiavyw3tAPVo5n2U3y5Hf46bfT5TLZ2yFnUJcKRZ0CeX6YAJA5dwG182xOn02r
+kkh9T1bO72pQHi15QxnQ9Gc4Mi5gjuxX4/Xyag5KyEXnniTb7XquW+JKP36RfhnU
+DGoEEUNU5UYwIzh910NM0UZubu5Umya1JVumoDqAi1lf2DHhKwDNAhmozYqE1vJJ
++e1C9/9oqok3CRyLDe+VJ7M=
+-----END CERTIFICATE-----
diff --git a/kong-versions/3.9.0.0/kong/spec/fixtures/kong_clustering.key b/kong-versions/3.9.0.0/kong/spec/fixtures/kong_clustering.key
new file mode 100644
index 00000000..67e3d9f3
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/fixtures/kong_clustering.key
@@ -0,0 +1,28 @@
+-----BEGIN PRIVATE KEY-----
+MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQC6+3r1yt5y8Vvf
+JVw1lHMjUQig81FV+UZZu58tGqlSIfqkVE+1xhxZw855e7NYBJHMS7bjJygVeyHN
+o1U8ypbmWRSQ+R9qZT+35aVbv28r6QTYLhERQwtpm55V+00kYYVo5WE4BUtiohT9
+To2I4pur3prM6Gw7AoNoEbNDIQO18LFbz0hTX5wDj06ci0RrTd0oRANCyowZI4Nr
+uuzDwH4NcvP/E5t4f5KnznIjE+WsdidS5f/f6All/aluoDZp51BjZQaXAGZN6c4e
+p9XKEZ1WsrKAj2D4HfbtSqAZLbk0CTp9UItzlj2c8oixkWv19LRsf+UEA5y6+hsg
+48D3AtPbAgMBAAECggEBALoFVt8RZR2VYYEu+f2UIrgP9jWp3FFcHdFIB6Qn0iwU
+AfdaqbJ91da4JsJVfqciZKqK6Pg0DHzSc17SEArawiWImh1guxBuimW54jjUyxU0
+Tc2EhxZVTRVT7MI9sRFws/kXuxCws7784UTg0Y5NY/IpFHinAoXyiikO8vjl73sg
+trN5mQGNTE/c8lEs7pUAFWX9zuNbmV0m1q25lHDgbkAD76/9X26lLCK1A5e2iCj3
+MME6/2GlSy3hrtSY7mCiR1GktvnK+yidXXJSkGMNCSopQARfcAlMvcCDav5ODxTz
+mB+A47oxGKBTdc9gGF44dR15y5E1kRAvTtaAIzpc14ECgYEA4u9uZkZS0gEiiA5K
+pOm/lnBp6bloGg9RlsOO5waE8DiGZgkwWuDwsncxUB1SvLd28MgxZzNQClncS98J
+viJzdAVzauMpn3Iqrdtk9drGzEeuxibic1FKMf1URGwKnlcsDHaeKAGyRQgO2Q7l
+Oy7EwtRmUKBUA3RCIqLSoiEi6NcCgYEA0u4a2abgYdyR1QMavgevqCGhuqu1Aa2Y
+rbD3TmIfGVubI2YZeFSyhC/7Jx+5HofQj5cpMRgASxzKXqrCXuyb+Q+u23kHogfQ
+cO1yO2GzjlA3FVHTK28t9EDPTOgHWQt3q7iS1s44VHwXDOpEQJ2onKKohvcP5WTf
+LO0T2K9NOJ0CgYEAtX9nHXc6/+iWdJhxjKnCaBBqNNrrboQ37ctj/FOTeQjMPMk2
+mkhzWVjI4NlC9doJz5NdJ7u7VTv/W9L7WMz256EAaUlbXcGSbtAcVCFwg6sFFke9
+Lxuhqo+AmOSMLY1sll88KKUKrfk+3szx+z5xcZ0sY2mHJ+gQiOEOc0rrP6sCgYBi
+Ksi6RU0mnoYMki5PBLq+0DA59ZH/XvCw3ayrgUUiAx1XwzvVYe3XUZFc6wm36NOr
+EFnubFIuow6YMnbVwN7yclcZ8+EWivZ6qDfC5Tyw3ipUtMlH7K2BgOw5yb8ptQmU
+FQnaCQ30W/BKZXkwbW+8voMalT+DroejnA7hiOyyjQKBgFLi6x6w76fTgQ7Ts8x0
+eATLOrvdvfotuLyMSsQLbljXyJznCTNrOGfYTua/Ifgkn4LpnoOkkxvVbj/Eugc7
+WeXBG+gbEi25GZUktrZWP1uc6s8aXH6rjYJP8iXnUpFHmQAPGuGiFnfB5MxlSns9
+9SKBXe7AvKGknGf7zg8WLKJZ
+-----END PRIVATE KEY-----
diff --git a/kong-versions/3.9.0.0/kong/spec/fixtures/kong_clustering_ca.crt b/kong-versions/3.9.0.0/kong/spec/fixtures/kong_clustering_ca.crt
new file mode 100644
index 00000000..c16572e0
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/fixtures/kong_clustering_ca.crt
@@ -0,0 +1,20 @@
+-----BEGIN CERTIFICATE-----
+MIIDLTCCAhWgAwIBAgIUBEI9LAuIcrg6fFLxC+Qo8SaEvfswDQYJKoZIhvcNAQEL
+BQAwHjEcMBoGA1UEAwwTa29uZ19jbHVzdGVyaW5nX3BraTAeFw0yMDAyMTkxODIw
+MzlaFw0zMDAyMTYxODIxMDlaMB4xHDAaBgNVBAMME2tvbmdfY2x1c3RlcmluZ19w
+a2kwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDqJdBsqWhTxA0k83N1
+9KvV6Z9YBee4BnYhQiOe8HgL8+d/SS/Ri35Ue+rZ5YbGu0im2KwzpsIEc5dw2/Tm
+eL5QL7rGnPeEQlRNufP27lI07M5XVsQx3VeZ41lhVFBwr03XQCOdozkeimriZryd
+WElslevdH4htxALDobK+HaSWl8FR8kJWlflaXuoOH0A4SQf2djo3/kmRkok5OXZz
+oeActuO5tE8/EveykABNyC4HOOfHSFCrm4dzVTskEZsJKEgQGqXNG30S5SmP6keS
+4npcgVTYV8DQinwY3lpwGb5f62nCFYbiu7M41e3ly+J9UP+qxmI9Qm1QG3rlVCtF
+wCJbAgMBAAGjYzBhMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0G
+A1UdDgQWBBRdgggWza66a1dWqUDM05ANj+BUJDAfBgNVHSMEGDAWgBRdgggWza66
+a1dWqUDM05ANj+BUJDANBgkqhkiG9w0BAQsFAAOCAQEAt9nD9jNxF0d08ioqY92R
+MR4WXa7Lp0jZUavLevXl+xhSXUo/ovUARHXs9qJ8SA/8u6eADtUQNGs0D03OSpD+
+klY4FmbcfJSBSXjOgwUz4hUVnUk/MESmLOKRMfqAW9oToBqWa/sdh9B8UzXLeM7c
+DPazf0K9AcaITUuwltDIFkQH80DiRZnoOk6nag/eBkK4nI42UZCvrg0ffRq4HY43
+jvb4EpIOf3i6PfkWznxwPq4UJLoj3NGhPwBzxZEpyfu5bvXFB4sSww9RMwu+w/fT
++wjt04CbQf286zWgOcGShJYBzNZ2EKQji6dC5PBpBO/iidddnxxCKnF/04ivSBME
+6g==
+-----END CERTIFICATE-----
diff --git a/kong-versions/3.9.0.0/kong/spec/fixtures/kong_clustering_client.crt b/kong-versions/3.9.0.0/kong/spec/fixtures/kong_clustering_client.crt
new file mode 100644
index 00000000..b5853359
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/fixtures/kong_clustering_client.crt
@@ -0,0 +1,20 @@
+-----BEGIN CERTIFICATE-----
+MIIDSTCCAjGgAwIBAgIUYr7mGItDJ+hOGVdVQSYBgacnKqIwDQYJKoZIhvcNAQEL
+BQAwHjEcMBoGA1UEAwwTa29uZ19jbHVzdGVyaW5nX3BraTAeFw0yMDAyMTkxODI1
+NDhaFw0zMDAyMTIxNDI2MThaMCwxKjAoBgNVBAMMIWNsaWVudC5rb25nX2NsdXN0
+ZXJpbmdfcGtpLmRvbWFpbjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB
+AMv1wKHhIy7RrHr/MFNYzZXyCEcdc0/b+BxFzhgdy8n3KI2rR60WtVulCGItbr35
+Dj3NxfRHTTAF1BvlbCg+A4bEOz3lfuuD1NQHRbLK+j2mH+GuHmUMV9fP9jf7SfbL
+zGR1zdj+d/xQHe3oSsEW3LQ/vjnWpFmVA8LFE6xYKQQtKqPHxJ+/hnohqcW2RiOJ
+EW7oAgjB/HWgwg1kgshEaAhouWWSzI2uEilxHEPtsTcSJCd1bxO0oU61jYa1dkwX
++CWhW/CDoyiCWzxr97lavyW02xRwvcDvTbpXD3sFQScp36quZ1Igr3iWGniKCaQa
+hZ4/OA7TGlhbOf5Bu4RihTECAwEAAaNxMG8wDgYDVR0PAQH/BAQDAgOoMB0GA1Ud
+JQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjAdBgNVHQ4EFgQUaeNNIcyO/C7B4L0F
+BQC/2ZILhiowHwYDVR0jBBgwFoAUXYIIFs2uumtXVqlAzNOQDY/gVCQwDQYJKoZI
+hvcNAQELBQADggEBAKUBSjBESwRwgyhSLmZU6LWbVmezmGmkTdTmaArwN4SZL0Vm
+gBJSatBN+MHuqzgnUxvgLIGmZLCMfL1rW6ERv/sOXWV6QTN+91RoGFf9zGBJ+tmH
+oXs+qps9Ge8zV+W63DoNqRKOkU9TrEWYt9kAQE/y6zTCMtmwRBaSAWurlwO6FZcF
+D9apy74B7RNjM3L0NF4Nj9z5O44drWPIcBpd+26sVQuUkyda2MCyLItla7OSHAWl
+FgDQt1Bmx1ByL1PeogKBQ/2elwsw0hn8jqNLDu0YuNEdUz4h6oGxdPsh1zJeGT7l
+u/Jqwu+kkQgZk8UIiKV7A9cGXD88W3+ABpf5IX8=
+-----END CERTIFICATE-----
diff --git a/kong-versions/3.9.0.0/kong/spec/fixtures/kong_clustering_client.key b/kong-versions/3.9.0.0/kong/spec/fixtures/kong_clustering_client.key
new file mode 100644
index 00000000..f4abb659
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/fixtures/kong_clustering_client.key
@@ -0,0 +1,27 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIEowIBAAKCAQEAy/XAoeEjLtGsev8wU1jNlfIIRx1zT9v4HEXOGB3LyfcojatH
+rRa1W6UIYi1uvfkOPc3F9EdNMAXUG+VsKD4DhsQ7PeV+64PU1AdFssr6PaYf4a4e
+ZQxX18/2N/tJ9svMZHXN2P53/FAd7ehKwRbctD++OdakWZUDwsUTrFgpBC0qo8fE
+n7+GeiGpxbZGI4kRbugCCMH8daDCDWSCyERoCGi5ZZLMja4SKXEcQ+2xNxIkJ3Vv
+E7ShTrWNhrV2TBf4JaFb8IOjKIJbPGv3uVq/JbTbFHC9wO9NulcPewVBJynfqq5n
+UiCveJYaeIoJpBqFnj84DtMaWFs5/kG7hGKFMQIDAQABAoIBAECRRPE6P5QTxoGN
+hbPs+fBNFbfFp/qRDWON6aeSzy/ZsZnfrioqdTFU9ml2Loevb4W7Pb6OT+4y+in2
+oB3BPAaO2p5Gp75RFrAkuTjXrw6TJ6afI3ojxS9J441nXMvnSoZHEOpv7HYQutjU
+381uumHJiCPxQkglt3ISR58YratnPFKKO21p9JRXBVDGefLhR9cFjhvRixsxF+DU
+y9l0X6hBq/VXtozzLMYpsUwLtzc6+FWIz+pLv5Y+JGtONx5IdaTW5z/VFLMNZHdP
+9cwwYKdR9dm5c37a1HKuHOZvBVAWRwjaC+uaF8IoyrGteAA9HMjCvR+jz9VST+nG
+CVGaN1ECgYEA3+OCeOcdWA2dolWlHPcSkR0BEpHmKlxSYjShJVa1JvW9C91rXw/E
+5jeCtTBmMOT/6OT/SEtaSHtMfuWSknig8OfHO0zO1N5t4+xgmp47vWUFR2fHK5PF
+GoqAYYPmYOZdSAsqE+9Rm7gzjDhriCRl6vvr0gV1bbn3BtyrCJo3XR0CgYEA6TaF
+qDhAoNQlC/GuC0JcrcxZzH2WecdSjncEPFv5xsvzc7K6Y1ptRx+9ntC8x0VyLHJJ
+RL2fPOC3HmGIVko/JS9b8kjciymwRzsQBsq3mDHzloqBAnJI3w1nzibAKfc9Azsp
+ZsZsLK+PWTkx5QR/cl+Avw8K7z+Wil4pfxUdUCUCgYEAnyXgRwUybLcxCIYM2qwe
+vJx7eLHRhOcfgMOckSgzmUAxY8+/VVGmS2fGN/nximweJXUyqjc2NDPBSqryJ8Ar
+11NK4jJVDCgYwV3zxbUZDiZTPFDe2XEvORCe9bKG/vaB9IZLIOSLhD/KFLC+b4ZA
+FGuDVEWhFaCNookV4wWMuVkCgYAQ+VjtD3sUuZwgrGyAgUoBlFgM3C8xmeJWYC88
+vW0GnR2RFDcguBowDQ1eG89BqbpPpdnTWQHYCnsJiQvFTA4ghLvqfIcg0d30sUXP
+WL3YI/qYwGf3Z54KLg2aIZPm+gnEzG+M/XAuKHEEi3coNhWYm37haRTgqP4qAASB
+LWY+yQKBgEN/zl6yTDg1iCGt/QlZWTdeQEWvCSrdaGjqvsFXlWoNsnf20zXiS/rU
+NATB1+T74kKIohYiagcgYt4H4P8wXX7rEFhCi+aYtz5ZRmjrD0hrbJkqmR+VPBJP
+SIHDqpgwRx0gXFoCV3JWl9dvHWUFl/FgRD55oCe1C8lxqZNpt2Fu
+-----END RSA PRIVATE KEY-----
diff --git a/kong-versions/3.9.0.0/kong/spec/fixtures/kong_clustering_server.crt b/kong-versions/3.9.0.0/kong/spec/fixtures/kong_clustering_server.crt
new file mode 100644
index 00000000..7abc701e
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/fixtures/kong_clustering_server.crt
@@ -0,0 +1,30 @@
+-----BEGIN CERTIFICATE-----
+MIIFOTCCAyGgAwIBAgIUGIGEUNv1gzJpSkoCZbKcsjmuQxcwDQYJKoZIhvcNAQEL
+BQAwLDEqMCgGA1UEAwwhc2VydmVyLmtvbmdfY2x1c3RlcmluZ19wa2kuZG9tYWlu
+MB4XDTIwMTIwODA5NDU1M1oXDTMwMTIwNjA5NDU1M1owLDEqMCgGA1UEAwwhc2Vy
+dmVyLmtvbmdfY2x1c3RlcmluZ19wa2kuZG9tYWluMIICIjANBgkqhkiG9w0BAQEF
+AAOCAg8AMIICCgKCAgEA3SvUdI94oqmGXkv3YBws8wxITBJ+f/ri+dTBlKSaw0/b
+2MRaP8zkhGywuQd9owVv0q9XfTUJChbmzAKwS4oC/Kk0oJ6/xD5Xv/6KtRHCydtG
+Yn3o/INzE6gJJ8f+pAotvTZfLRs7O4nfJHYpKlnpJsUG31RR66yiVOd09c5dQyQg
+CjcLH35Jv4vIIyQN6QXVZAf3QVYgF193bqoFEaL5OZH4i4Y5PMevaCOLl7f4NXy4
+XEHbvRtBUuN4EISai7Riyx00M60a/ocmWzJr3PtBFYu4t5hIiReNuoQAJxAmqvLb
+RXh5ti3LOgNel1kjlcKXaDWGMeIAj4T5IgRikMPosEhdUU7CIlTcGJFj03e9uUNY
+VW7SfTopDLdbFrblYqrqPO7djQ7XI5iHGyP3EJHkKWpbT6YGCRd5+bWp4qwRHHjZ
+xyxK5lx3tVbhd6ZXqlj/+7fiEn5W6fVGUyRjb+SPavpihgal2G/yeJrY4JYeHTSj
+nWQ0P5dIGHVBgDWzcUpSJmTmuayQ/+lU2+zc2UWfhFqmgyArR4QlzzNMDU0362qb
+amxN+VOsHMJ2XJWETB44IfgW3qv5oVoOuZdl6883TmE4oSzWzyG/HKBvujBMOSIQ
+u5PPDXQrweuoWx7mHhIaSNy4/v4BtpZ7Y3IUxbWXA5W7Voe16E9v+Aos3lx6Si8C
+AwEAAaNTMFEwHQYDVR0OBBYEFA2pU/tVp1+iXxS1pAQJSVY807rfMB8GA1UdIwQY
+MBaAFA2pU/tVp1+iXxS1pAQJSVY807rfMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZI
+hvcNAQELBQADggIBAE9wnFNn/D6qB9CYfT6AU7+Xza6i+a1pKOkPheU9LSRWUKNh
+Qz0+N2qdV3mozBC1kjT3XW5LRxE8NpQjGG6oZ+Caa6VR9RQZkLihYxqGtgociVT1
+N34tWzy6ck1UAsMpy9QwvFUE0udgpR1NSbYjFElMQmOM5Pr5phr4r0+mDljX2ro3
+I5m5NZ/W9jaICrxqS3GnP91a5V2TcLmwSZGiC2TOqJLhi0zc+Jfkscr6hik3P2Bc
+kzSbM4A+6lo5nE7221/CRFg/hQXx8dxfySCl3eHQYjuBSQAsYyVSO5DFmaX+KJE6
+4Wg5sMRcmMDRa/sQhDJiBH1+RQMtJRUPDwds0y6WIK4pfONJjiCeE0/3PLpem5qE
+/h3AJjoYWnJ0hTkjnR26OW7bWrwuo/RVMQq3An78TsQWyr1SDazPpjfFYwxZk722
+sgYkIuCZ3I+rW+cAw9VvrT3gh7QFpEb3Yuh5ehr6srl/jD2p/WeVBYQwHJKpgxGF
+13t3DXbzAVdNDy/M1gJxfHyDTe3kxs03BckMz+fd19EQhlVd4ZI+14xm2kr+ULKg
++pDTdg5TpcgqcfpG55sHWm5G2059fkEk/z/8ABtB4v4fcKA7ZmrUcDlpSQd/ejjt
+obN+e+Dq0Rm5Rb5oI/wHHd6JLW1TqLEH6w6ZyNsOjofiJWSSJTC75eH4HJgl
+-----END CERTIFICATE-----
diff --git a/kong-versions/3.9.0.0/kong/spec/fixtures/kong_clustering_server.key b/kong-versions/3.9.0.0/kong/spec/fixtures/kong_clustering_server.key
new file mode 100644
index 00000000..2add6a0e
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/fixtures/kong_clustering_server.key
@@ -0,0 +1,52 @@
+-----BEGIN PRIVATE KEY-----
+MIIJQwIBADANBgkqhkiG9w0BAQEFAASCCS0wggkpAgEAAoICAQDdK9R0j3iiqYZe
+S/dgHCzzDEhMEn5/+uL51MGUpJrDT9vYxFo/zOSEbLC5B32jBW/Sr1d9NQkKFubM
+ArBLigL8qTSgnr/EPle//oq1EcLJ20Zifej8g3MTqAknx/6kCi29Nl8tGzs7id8k
+dikqWekmxQbfVFHrrKJU53T1zl1DJCAKNwsffkm/i8gjJA3pBdVkB/dBViAXX3du
+qgURovk5kfiLhjk8x69oI4uXt/g1fLhcQdu9G0FS43gQhJqLtGLLHTQzrRr+hyZb
+Mmvc+0EVi7i3mEiJF426hAAnECaq8ttFeHm2Lcs6A16XWSOVwpdoNYYx4gCPhPki
+BGKQw+iwSF1RTsIiVNwYkWPTd725Q1hVbtJ9OikMt1sWtuViquo87t2NDtcjmIcb
+I/cQkeQpaltPpgYJF3n5tanirBEceNnHLErmXHe1VuF3pleqWP/7t+ISflbp9UZT
+JGNv5I9q+mKGBqXYb/J4mtjglh4dNKOdZDQ/l0gYdUGANbNxSlImZOa5rJD/6VTb
+7NzZRZ+EWqaDICtHhCXPM0wNTTfraptqbE35U6wcwnZclYRMHjgh+Bbeq/mhWg65
+l2XrzzdOYTihLNbPIb8coG+6MEw5IhC7k88NdCvB66hbHuYeEhpI3Lj+/gG2lntj
+chTFtZcDlbtWh7XoT2/4CizeXHpKLwIDAQABAoICAQDAYZWl5f47D1avw0hkM13t
+8+sXMKcUT3kLc0MHNr7f0SEcRn9yK5lCjwCRkbB5EwuXqaliYbWBLzaGkngi3OOI
+Pu5mIHASFWBiwtiIc/CJgNCSb48vxm9c07dTASXALpJmmVrkc2Fsgpq0rotUKW0i
+qhM2Q7QWWc3CKKqV/XEmK9Aq0oI8XK9ti/sEhiILZWWeY0dxb6bubb4HZqCOHMLI
+ju4w/wnekptC7FhKGl4uuFPs++RVc9W4ceBIDfAYQUoF/1se8B4g9BIrFYq5Z1vP
+j/+Ww0Gk7fX8HUG8uNHJtQGCRi8ohmDWD4RCBelsJR1qKdSWo011iWbjbgkGf0Jw
+JiiU9yJBMjXhedEnsrQnqRzqL/+GSX8MciHMmzaHlrIYiinEaVRsZ+m2Tq3KiE8v
+VVD39gZCbEkN4swu+FdHEpdL4FQBslz29SOixKmBadK+S3ZNK3Q2SodIVP9DYcod
+Oga1LoZeVkNSFMalcal2PmgT6IfIZHC/i5yAF40xV/SESg5QZNVWUCFnnjR5UxEN
+Gn9LxXBHoJlh1SSI7Mf7OSSBC/n3JY8XOoY364v1OkqsMYvgnz1CbruRNDI76Bc+
+Rl9jRImmqO89jgNMzQpcCOAeb/fNnjYqCb19J/Bke1c/c0cw1pvJvPxGgWJ/MqLu
+/pIQjMY2tqO3wAzBrmAsYQKCAQEA8CSpxsSyIE2xGMkfasAQ9axMohd76xqskpUR
+Uw+XR7yAwh1qrGKGa9rXai3tjTvMVRjIk23z+yJf1NhwTp77ssFyOBDIJAm8+bkJ
+zRBwIWKFQytZKLM8BhxJvrMAn81YbgXmhoz0A5felqzAfILZP0Wghm0NWdIz81E4
+hcspKuwcxMh5HH7xKhBfX9hko3zo6qzgCl+drRZBSBkPRguKZE0/bCZWY5rb1c1w
+PgDWgjknkBFamo8UWFYrkwVf9X1ARtMOGRaYzoEHt9ME0It3p7wisP7BYzLbQBLk
+ca5rQztccmgUrSII2BqeBXkYx0OSLow/pgQcVD59Do5ck7CNJwKCAQEA68Z3qTmf
+NmI3cHkkP5flMT4xkloaMSaUu+wZbqKBpxbahazSTO6cayXUDEDkDGIO1XjJxhtF
+/FNQ7lgQCsUXxmF78caNhtE1vjo4zXdgf9yVkSM3wBmZTOWssFYbG2sgelz3yHjm
+mAztj9cvrnrenJeqZTYx0SNsqBwccy12WGek6cgk+bQLARXWctOwJ+d0RWRaqfab
+tU2/2Dg4H53w8sNG7AXQ6ELq9tIHkykHs5T3mmYFft2NMgO2Wqfy5yPWckhJlO/P
+D+ZLUCETCB153yf9N9KUjlZRDoIhn9G2JoEuDw1UMyj79c2H1KChdNwCLaJ4RfqI
+CEJq87H4mskPuQKCAQB9wqWKq52hHy68jS8/x1/aWKY1SNkjcW+owBo3hnWyIrzH
+a4JezqYYu52ORIkgKo3Cjt0ToERiY0kOfV6rPcUQgxAe3mMBxHvLx6SjWJVwVlj1
+qTDjCKJJjOztym5sQayqybpFAnITo6f0/nk7e4bsBLmhTGDuhg+gwAs6vf9MNCSI
+xXfvfWcsoTBhUEC8AYE0zN3zcMlxSLNdX4pJI2gRSQcKyzT4qrOvzwuV3Ph5cBcQ
+8pWhVYbRECd3shvjwvkzXfoHF3dkxdvV39OopzE9jWAZkwCRw6NgdcRe6HnR1rd+
+TpVtaeJ50c6pjRZ13CQk7luyxHpVf/gb9F/1FEOHAoIBABcajaNBiD52BWS6Gjk5
+EzZuF8F1ntduJmj7y8oxlm7fKG6s7ranMyC0xkClIzOrcDSu72bASW1eZLHWY0wK
+4DeKWfDpOfkaCyAm6GYJ6qTc4rMkNlRWrdUBNJja9zEKoFYdQhKc9ku0CJttxLhe
+Re4mVoYwd1U9GWqnxonqzIwBLAHUoPrvD5z9nNQHtl1SquwZ12CMT9nGUqRHbgh7
+G59OT2bVcxEvbYLeNevPu3d3g4PXt3YlE67w+i+MAZtwwZTVTJCRp0KxmHOzqf/D
+k6uwaXnM4s3H242GZvEYRbckNXU4IyYYQAhoKYVGcEvZO0VphEunLylQCNb0e53/
+UdECggEBALgTFFed9iTiZxvFeT8p/Xq7WIOyf82A/stvPDlm4Hyl+7nQ3oxqp05D
+B+tPtjPE33rjfwhevd0OZVF6DAB792E9x6Ln1khlsbgdSuASJNHkrj12Ib8WVib5
+U+O5Ps9s3+VHe53C0e2nP+SNv8UdCu41liudQtmrZnCfKEYaXs/Yysd/LYsp2hbe
+0NYhG84WeLajumVI0CbENkkPioOOJUbo8ytIPgtWgbEFuy9DZUcSCwrg7UoWqoqL
+qGe7eYuHDetoxuA2men4mgBLLEeo1DqlW9BIO1qz2LOU4EW/0AlLgGMVwBI7Z/fj
+VzlV/SRWxLEaQCujgP/IFVniA+r/yw0=
+-----END PRIVATE KEY-----
diff --git a/kong-versions/3.9.0.0/kong/spec/fixtures/kong_spec.crt b/kong-versions/3.9.0.0/kong/spec/fixtures/kong_spec.crt
new file mode 100644
index 00000000..75cd9602
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/fixtures/kong_spec.crt
@@ -0,0 +1,11 @@
+-----BEGIN CERTIFICATE-----
+MIIBmzCCAUGgAwIBAgIUDTiAG3jByZjjmUwJZJDtuLItbWwwCgYIKoZIzj0EAwIw
+IzENMAsGA1UECgwES29uZzESMBAGA1UEAwwJbG9jYWxob3N0MB4XDTIzMDQyNDA5
+MzcxM1oXDTQzMDQxOTA5MzcxM1owIzENMAsGA1UECgwES29uZzESMBAGA1UEAwwJ
+bG9jYWxob3N0MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEus1/MmWimrKiQngJ
+7Ia+SvsU5FCIpttKfEvcKQZRzImlAVLpWEGnf7IbqxgTUP/03JmVkg9SdExN/gP8
+6Usgq6NTMFEwHQYDVR0OBBYEFIXbvRnB4mXOnZ5Ps6AnXz66FPPgMB8GA1UdIwQY
+MBaAFIXbvRnB4mXOnZ5Ps6AnXz66FPPgMA8GA1UdEwEB/wQFMAMBAf8wCgYIKoZI
+zj0EAwIDSAAwRQIgXiyT9+6AS1oSR6A06eTVaiM1/XO80r1h24OrTXvc/pYCIQDA
+yHqB8IlSpNGJXcsEUuuhvbGT6ZcpLeEWNfNFtVp11w==
+-----END CERTIFICATE-----
diff --git a/kong-versions/3.9.0.0/kong/spec/fixtures/kong_spec.key b/kong-versions/3.9.0.0/kong/spec/fixtures/kong_spec.key
new file mode 100644
index 00000000..1da05db1
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/fixtures/kong_spec.key
@@ -0,0 +1,5 @@
+-----BEGIN EC PRIVATE KEY-----
+MHcCAQEEIEIaZr9tJn4gjvOisL8syGCKs8pC9eYGqpHdp012CPmqoAoGCCqGSM49
+AwEHoUQDQgAEus1/MmWimrKiQngJ7Ia+SvsU5FCIpttKfEvcKQZRzImlAVLpWEGn
+f7IbqxgTUP/03JmVkg9SdExN/gP86Usgqw==
+-----END EC PRIVATE KEY-----
diff --git a/kong-versions/3.9.0.0/kong/spec/fixtures/migrations/kong/db/migrations/core/000_base.lua b/kong-versions/3.9.0.0/kong/spec/fixtures/migrations/kong/db/migrations/core/000_base.lua
new file mode 100644
index 00000000..3a4b4f82
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/fixtures/migrations/kong/db/migrations/core/000_base.lua
@@ -0,0 +1,107 @@
+-- This software is copyright Kong Inc. and its licensors.
+-- Use of the software is subject to the agreement between your organization
+-- and Kong Inc. If there is no such agreement, use is governed by and
+-- subject to the terms of the Kong Master Software License Agreement found
+-- at https://konghq.com/enterprisesoftwarelicense/.
+-- [ END OF LICENSE 0867164ffc95e54f04670b5169c09574bdbd9bba ]
+
+return {
+ postgres = {
+ up = [[
+ CREATE TABLE IF NOT EXISTS "cluster_events" (
+ "id" UUID PRIMARY KEY,
+ "node_id" UUID NOT NULL,
+ "at" TIMESTAMP WITH TIME ZONE NOT NULL,
+ "nbf" TIMESTAMP WITH TIME ZONE,
+ "expire_at" TIMESTAMP WITH TIME ZONE NOT NULL,
+ "channel" TEXT,
+ "data" TEXT
+ );
+
+ CREATE TABLE IF NOT EXISTS "services" (
+ "id" UUID PRIMARY KEY,
+ "ws_id" UUID NULL
+ );
+
+ CREATE TABLE IF NOT EXISTS "routes" (
+ "id" UUID PRIMARY KEY,
+ "ws_id" UUID NULL
+ );
+
+ CREATE TABLE IF NOT EXISTS "certificates" (
+ "id" UUID PRIMARY KEY,
+ "ws_id" UUID NULL
+ );
+
+ CREATE TABLE IF NOT EXISTS "consumers" (
+ "id" UUID PRIMARY KEY,
+ "ws_id" UUID NULL
+ );
+
+ CREATE TABLE IF NOT EXISTS "snis" (
+ "id" UUID PRIMARY KEY,
+ "ws_id" UUID NULL
+ );
+
+ CREATE TABLE IF NOT EXISTS "plugins" (
+ "id" UUID PRIMARY KEY,
+ "ws_id" UUID NULL
+ );
+
+ CREATE TABLE IF NOT EXISTS "upstreams" (
+ "id" UUID PRIMARY KEY,
+ "ws_id" UUID NULL
+ );
+
+ CREATE TABLE IF NOT EXISTS "targets" (
+ "id" UUID PRIMARY KEY,
+ "ws_id" UUID NULL
+ );
+
+ CREATE TABLE IF NOT EXISTS "filter_chains" (
+ "id" UUID PRIMARY KEY,
+ "ws_id" UUID NULL
+ );
+
+ CREATE TABLE IF NOT EXISTS "key_sets" (
+ "id" UUID PRIMARY KEY,
+ "ws_id" UUID NULL
+ );
+
+ CREATE TABLE IF NOT EXISTS "keys" (
+ "id" UUID PRIMARY KEY,
+ "ws_id" UUID NULL
+ );
+
+ CREATE TABLE IF NOT EXISTS "sm_vaults" (
+ "id" UUID PRIMARY KEY,
+ "ws_id" UUID NULL
+ );
+
+ INSERT INTO sm_vaults ("id", "ws_id")
+ VALUES ('23111c66-8c80-4f8a-8f18-7d6c495bc36e', '23111c66-8c80-4f8a-8f18-7d6c495bc36e')
+ ON CONFLICT DO NOTHING; -- Hack, mock data
+
+ CREATE OR REPLACE FUNCTION batch_delete_expired_rows() RETURNS trigger
+ LANGUAGE plpgsql
+ AS $$
+ BEGIN
+ EXECUTE FORMAT('WITH rows AS (SELECT ctid FROM %s WHERE %s < CURRENT_TIMESTAMP AT TIME ZONE ''UTC'' ORDER BY %s LIMIT 2 FOR UPDATE SKIP LOCKED) DELETE FROM %s WHERE ctid IN (TABLE rows)', TG_TABLE_NAME, TG_ARGV[0], TG_ARGV[0], TG_TABLE_NAME);
+ RETURN NULL;
+ END;
+ $$;
+
+ DROP TRIGGER IF EXISTS "cluster_events_ttl_trigger" ON "cluster_events";
+
+ DO $$
+ BEGIN
+ CREATE TRIGGER "cluster_events_ttl_trigger"
+ AFTER INSERT ON "cluster_events"
+ FOR EACH STATEMENT
+ EXECUTE PROCEDURE batch_delete_expired_rows("expire_at");
+ EXCEPTION WHEN UNDEFINED_COLUMN OR UNDEFINED_TABLE THEN
+ -- Do nothing, accept existing state
+ END$$;
+ ]]
+ },
+}
diff --git a/kong-versions/3.9.0.0/kong/spec/fixtures/migrations/kong/db/migrations/core/001_14_to_15.lua b/kong-versions/3.9.0.0/kong/spec/fixtures/migrations/kong/db/migrations/core/001_14_to_15.lua
new file mode 100644
index 00000000..a2f18917
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/fixtures/migrations/kong/db/migrations/core/001_14_to_15.lua
@@ -0,0 +1,13 @@
+-- This software is copyright Kong Inc. and its licensors.
+-- Use of the software is subject to the agreement between your organization
+-- and Kong Inc. If there is no such agreement, use is governed by and
+-- subject to the terms of the Kong Master Software License Agreement found
+-- at https://konghq.com/enterprisesoftwarelicense/.
+-- [ END OF LICENSE 0867164ffc95e54f04670b5169c09574bdbd9bba ]
+
+return {
+ postgres = {
+ up = [[
+ ]],
+ },
+}
diff --git a/kong-versions/3.9.0.0/kong/spec/fixtures/migrations/kong/db/migrations/core/init.lua b/kong-versions/3.9.0.0/kong/spec/fixtures/migrations/kong/db/migrations/core/init.lua
new file mode 100644
index 00000000..5c4163d3
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/fixtures/migrations/kong/db/migrations/core/init.lua
@@ -0,0 +1,10 @@
+-- This software is copyright Kong Inc. and its licensors.
+-- Use of the software is subject to the agreement between your organization
+-- and Kong Inc. If there is no such agreement, use is governed by and
+-- subject to the terms of the Kong Master Software License Agreement found
+-- at https://konghq.com/enterprisesoftwarelicense/.
+-- [ END OF LICENSE 0867164ffc95e54f04670b5169c09574bdbd9bba ]
+
+return {
+ "000_base",
+}
diff --git a/kong-versions/3.9.0.0/kong/spec/fixtures/migrations/kong/enterprise_edition/db/migrations/enterprise/000_base.lua b/kong-versions/3.9.0.0/kong/spec/fixtures/migrations/kong/enterprise_edition/db/migrations/enterprise/000_base.lua
new file mode 100644
index 00000000..a4bbe3b5
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/fixtures/migrations/kong/enterprise_edition/db/migrations/enterprise/000_base.lua
@@ -0,0 +1,97 @@
+-- This software is copyright Kong Inc. and its licensors.
+-- Use of the software is subject to the agreement between your organization
+-- and Kong Inc. If there is no such agreement, use is governed by and
+-- subject to the terms of the Kong Master Software License Agreement found
+-- at https://konghq.com/enterprisesoftwarelicense/.
+-- [ END OF LICENSE 0867164ffc95e54f04670b5169c09574bdbd9bba ]
+
+local utils = require "kong.tools.utils"
+local enums = require "kong.enterprise_edition.dao.enums"
+
+local fmt = string.format
+
+-- This query is designed to ensure that the workspace entity counter does not count non-proxy
+-- consumers. The created consumer may not function as expected.
+-- See also: `seed()` in kong/enterprise_edition/db/migrations/enterprise/000_base.lua
+local mock_admin_consumer = [[
+ DO $$
+ BEGIN
+ -- Mainly taken from enterprise base migration
+ IF not EXISTS (SELECT column_name
+ FROM information_schema.columns
+ WHERE table_schema=current_schema()
+ AND table_name='consumers'
+ AND column_name='type') THEN
+ ALTER TABLE consumers ADD COLUMN type int NOT NULL DEFAULT 0;
+ END IF;
+ END$$;
+]] .. fmt([[
+ INSERT INTO consumers (id, ws_id, type) VALUES ('%s', '%s', %d);
+]], utils.uuid(), utils.uuid(), enums.CONSUMERS.TYPE.ADMIN)
+
+return {
+ postgres = {
+ up = [[
+ CREATE TABLE IF NOT EXISTS "workspaces" (
+ id UUID PRIMARY KEY,
+ name TEXT UNIQUE,
+ comment TEXT,
+ created_at TIMESTAMP WITHOUT TIME ZONE DEFAULT timezone('utc'::text, ('now'::text)::timestamp(0) with time zone),
+ meta JSON DEFAULT '{}'::json,
+ config JSON DEFAULT '{"portal":false}'::json
+ );
+
+ CREATE TABLE IF NOT EXISTS "workspace_entity_counters" (
+ workspace_id uuid,
+ entity_type text,
+ count int,
+ PRIMARY KEY(workspace_id, entity_type)
+ );
+
+ CREATE TABLE IF NOT EXISTS "rbac_users" (
+ "id" UUID PRIMARY KEY,
+ "ws_id" UUID NULL
+ );
+
+ CREATE TABLE IF NOT EXISTS "rbac_roles" (
+ "id" UUID PRIMARY KEY,
+ "ws_id" UUID NULL
+ );
+
+ CREATE TABLE IF NOT EXISTS "consumer_groups" (
+ "id" UUID PRIMARY KEY,
+ "ws_id" UUID NULL
+ );
+
+ CREATE TABLE IF NOT EXISTS "consumer_group_plugins" (
+ "id" UUID PRIMARY KEY,
+ "ws_id" UUID NULL
+ );
+
+ CREATE TABLE IF NOT EXISTS "files" (
+ "id" UUID PRIMARY KEY,
+ "ws_id" UUID NULL
+ );
+
+ CREATE TABLE IF NOT EXISTS "developers" (
+ "id" UUID PRIMARY KEY,
+ "ws_id" UUID NULL
+ );
+
+ CREATE TABLE IF NOT EXISTS "document_objects" (
+ "id" UUID PRIMARY KEY,
+ "ws_id" UUID NULL
+ );
+
+ CREATE TABLE IF NOT EXISTS "applications" (
+ "id" UUID PRIMARY KEY,
+ "ws_id" UUID NULL
+ );
+
+ CREATE TABLE IF NOT EXISTS "application_instances" (
+ "id" UUID PRIMARY KEY,
+ "ws_id" UUID NULL
+ );
+ ]] .. mock_admin_consumer
+ },
+}
diff --git a/kong-versions/3.9.0.0/kong/spec/fixtures/migrations/kong/enterprise_edition/db/migrations/enterprise/006_1301_to_1500.lua b/kong-versions/3.9.0.0/kong/spec/fixtures/migrations/kong/enterprise_edition/db/migrations/enterprise/006_1301_to_1500.lua
new file mode 100644
index 00000000..bf7d7952
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/fixtures/migrations/kong/enterprise_edition/db/migrations/enterprise/006_1301_to_1500.lua
@@ -0,0 +1,12 @@
+-- This software is copyright Kong Inc. and its licensors.
+-- Use of the software is subject to the agreement between your organization
+-- and Kong Inc. If there is no such agreement, use is governed by and
+-- subject to the terms of the Kong Master Software License Agreement found
+-- at https://konghq.com/enterprisesoftwarelicense/.
+-- [ END OF LICENSE 0867164ffc95e54f04670b5169c09574bdbd9bba ]
+
+return {
+ postgres = {
+ up = [[ ]],
+ },
+}
diff --git a/kong-versions/3.9.0.0/kong/spec/fixtures/migrations/kong/enterprise_edition/db/migrations/enterprise/init.lua b/kong-versions/3.9.0.0/kong/spec/fixtures/migrations/kong/enterprise_edition/db/migrations/enterprise/init.lua
new file mode 100644
index 00000000..3edb511d
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/fixtures/migrations/kong/enterprise_edition/db/migrations/enterprise/init.lua
@@ -0,0 +1,11 @@
+-- This software is copyright Kong Inc. and its licensors.
+-- Use of the software is subject to the agreement between your organization
+-- and Kong Inc. If there is no such agreement, use is governed by and
+-- subject to the terms of the Kong Master Software License Agreement found
+-- at https://konghq.com/enterprisesoftwarelicense/.
+-- [ END OF LICENSE 0867164ffc95e54f04670b5169c09574bdbd9bba ]
+
+return {
+ "000_base",
+ "006_1301_to_1500",
+}
diff --git a/kong-versions/3.9.0.0/kong/spec/fixtures/mock_cp.lua b/kong-versions/3.9.0.0/kong/spec/fixtures/mock_cp.lua
new file mode 100644
index 00000000..219317b1
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/fixtures/mock_cp.lua
@@ -0,0 +1,411 @@
+-- This software is copyright Kong Inc. and its licensors.
+-- Use of the software is subject to the agreement between your organization
+-- and Kong Inc. If there is no such agreement, use is governed by and
+-- subject to the terms of the Kong Master Software License Agreement found
+-- at https://konghq.com/enterprisesoftwarelicense/.
+-- [ END OF LICENSE 0867164ffc95e54f04670b5169c09574bdbd9bba ]
+
+local _M = {}
+
+local ws_server = require "resty.websocket.server"
+local pl_file = require "pl.file"
+local cjson = require "cjson.safe"
+local semaphore = require "ngx.semaphore"
+local gzip = require "kong.tools.gzip"
+local buffer = require "string.buffer"
+
+local shm = assert(ngx.shared.kong_test_cp_mock)
+
+local WRITER = "writer"
+local READER = "reader"
+
+---@type resty.websocket.new.opts
+local WS_OPTS = {
+ timeout = 500,
+ max_payload_len = 1024 * 1024 * 20,
+}
+
+
+---@class spec.fixtures.cluster-mock.ctx
+---
+---@field basic_info table
+---@field cancel boolean
+---@field dp table
+---@field need_pong boolean
+---@field writer_sema ngx.semaphore
+---@field ws resty.websocket.server
+---@field sent_version integer
+
+
+local function send(status, json)
+ ngx.status = status
+ ngx.print(cjson.encode(json))
+ return ngx.exit(status)
+end
+
+
+local function bad_request(err)
+ send(ngx.HTTP_BAD_REQUEST, { error = err })
+end
+
+
+---@param ctx spec.fixtures.cluster-mock.ctx
+---@param entry table
+local function emit_log_entry(ctx, entry)
+ entry.dp = ctx.dp
+ assert(shm:rpush("log", buffer.encode(entry)))
+end
+
+
+---@param ctx spec.fixtures.cluster-mock.ctx
+---@param name string
+---@param data table?
+local function log_event(ctx, name, data)
+ local evt = data or {}
+ evt.event = name
+ emit_log_entry(ctx, evt)
+end
+
+
+---@return integer
+local function get_version()
+ return shm:get("payload-version") or 0
+end
+
+
+---@return integer
+local function increment_version()
+ return assert(shm:incr("payload-version", 1, 0))
+end
+
+
+---@param ctx spec.fixtures.cluster-mock.ctx
+local function wake_writer(ctx)
+ ctx.writer_sema:post(1)
+end
+
+
+---@param ctx spec.fixtures.cluster-mock.ctx
+---@return boolean
+local function canceled(ctx)
+ return ctx.cancel or ngx.worker.exiting()
+end
+
+
+---@param ctx spec.fixtures.cluster-mock.ctx
+local function wait_writer(ctx)
+ return canceled(ctx) or ctx.writer_sema:wait(0.1)
+end
+
+
+---@param ctx spec.fixtures.cluster-mock.ctx
+---@return boolean continue
+local function get_basic_info(ctx)
+ local data, typ, err = ctx.ws:recv_frame()
+
+ if err and err:find("timeout") then
+ return true
+
+ elseif not data then
+ log_event(ctx, "client-read-error", { error = err })
+ return false
+ end
+
+ if typ == "binary" then
+ local info = cjson.decode(data)
+
+ if type(info) == "table" and info.type == "basic_info" then
+ log_event(ctx, "client-basic-info-received")
+ wake_writer(ctx)
+ ctx.basic_info = info
+ return true
+
+ else
+ log_event(ctx, "client-error",
+ { error = "client did not send proper basic info frame" })
+
+ return false
+ end
+
+ else
+ log_event(ctx, "client-error", {
+ error = "invalid pre-basic-info frame type: " .. typ,
+ })
+ return false
+ end
+end
+
+
+---@param ctx spec.fixtures.cluster-mock.ctx
+---@return boolean continue
+local function reader_recv(ctx)
+ local data, typ, err = ctx.ws:recv_frame()
+
+ if err then
+ if err:find("timeout") then
+ return true
+ end
+
+ log_event(ctx, "client-read-error", { error = err })
+ return false
+ end
+
+ log_event(ctx, "client-recv", {
+ type = typ,
+ data = data,
+ json = cjson.decode(data),
+ })
+
+ if typ == "ping" then
+ ctx.need_pong = true
+ wake_writer(ctx)
+
+ elseif typ == "close" then
+ log_event(ctx, "close", { initiator = "dp" })
+ return false
+ end
+
+ return true
+end
+
+
+---@param ctx spec.fixtures.cluster-mock.ctx
+local function read_handler(ctx)
+ while not canceled(ctx) and not ctx.basic_info do
+ if not get_basic_info(ctx) then
+ return READER
+ end
+ end
+
+ while not canceled(ctx) do
+ if not reader_recv(ctx) then
+ break
+ end
+ end
+
+ return READER
+end
+
+
+---@param ctx spec.fixtures.cluster-mock.ctx
+---@return boolean continue
+local function handle_ping(ctx)
+ if ctx.need_pong then
+ ctx.need_pong = false
+ ctx.ws:send_pong()
+ end
+
+ return true
+end
+
+
+---@param ctx spec.fixtures.cluster-mock.ctx
+---@return boolean continue
+local function send_config(ctx)
+ local version = get_version()
+
+ if version <= ctx.sent_version then
+ return true
+ end
+
+ local data = assert(shm:get("payload"))
+ local payload = gzip.deflate_gzip(data)
+
+ local ok, err = ctx.ws:send_binary(payload)
+
+ if ok then
+ log_event(ctx, "sent-config", {
+ version = version,
+ size = #data,
+ deflated_size = #payload,
+ })
+ ctx.sent_version = version
+ return true
+
+ else
+ log_event(ctx, "send-error", { error = err })
+ return false
+ end
+end
+
+
+---@param ctx spec.fixtures.cluster-mock.ctx
+local function write_handler(ctx)
+ while not ctx.basic_info and not canceled(ctx) do
+ wait_writer(ctx)
+ end
+
+ -- wait until the test driver has sent us at least one config payload
+ while get_version() < 1 and not canceled(ctx) do
+ wait_writer(ctx)
+ end
+
+ ctx.sent_version = 0
+
+ while not canceled(ctx)
+ and handle_ping(ctx)
+ and send_config(ctx)
+ do
+ wait_writer(ctx)
+ end
+
+ return WRITER
+end
+
+
+function _M.outlet()
+ local dp = {
+ id = ngx.var.arg_node_id,
+ hostname = ngx.var.arg_node_hostname,
+ ip = ngx.var.remote_addr,
+ version = ngx.var.arg_node_version,
+ }
+
+ local ctx = ngx.ctx
+ ctx.dp = dp
+
+ log_event(ctx, "connect")
+
+ local ws, err = ws_server:new(WS_OPTS)
+
+ if ws then
+ log_event(ctx, "handshake", { ok = true, err = nil })
+ else
+ log_event(ctx, "handshake", { ok = false, err = err })
+ log_event(ctx, "close", { initiator = "cp" })
+ return ngx.exit(ngx.HTTP_CLOSE)
+ end
+
+ ws:set_timeout(500)
+
+ ctx.ws = ws
+ ctx.cancel = false
+ ctx.writer_sema = semaphore.new()
+
+ local reader = ngx.thread.spawn(read_handler, ctx)
+ local writer = ngx.thread.spawn(write_handler, ctx)
+
+ local ok, err_or_result = ngx.thread.wait(reader, writer)
+
+ ctx.cancel = true
+ wake_writer(ctx)
+
+ ws:send_close()
+
+ if ok then
+ local res = err_or_result
+ local thread
+ if res == READER then
+ thread = writer
+
+ elseif res == WRITER then
+ thread = reader
+
+ else
+ error("unreachable!")
+ end
+
+ ngx.thread.wait(thread)
+ ngx.thread.kill(thread)
+
+ else
+ ngx.log(ngx.ERR, "abnormal ngx.thread.wait() status: ", err_or_result)
+ ngx.thread.kill(reader)
+ ngx.thread.kill(writer)
+ end
+
+ log_event(ctx, "exit")
+end
+
+
+function _M.set_payload()
+ ngx.req.read_body()
+
+ local body = ngx.req.get_body_data()
+ if not body then
+ local body_file = ngx.req.get_body_file()
+ if body_file then
+ body = pl_file.read(body_file)
+ end
+ end
+
+ if not body then
+ return bad_request("expected request body")
+ end
+
+ local json, err = cjson.decode(body)
+ if err then
+ return bad_request("invalid JSON: " .. tostring(err))
+ end
+
+ assert(shm:set("payload", cjson.encode(json)))
+ local version = increment_version()
+
+ return send(201, {
+ status = "created",
+ message = "updated payload",
+ version = version,
+ })
+end
+
+function _M.get_log()
+ local entries = {}
+
+ repeat
+ local data = shm:lpop("log")
+ if data then
+ table.insert(entries, buffer.decode(data))
+ end
+ until not data
+
+ send(200, { data = entries })
+end
+
+
+function _M.fixture(listen, listen_ssl)
+ return ([[
+lua_shared_dict kong_test_cp_mock 10m;
+
+server {
+ charset UTF-8;
+ server_name kong_cluster_listener;
+ listen %s;
+ listen %s ssl;
+
+ access_log ${{ADMIN_ACCESS_LOG}};
+ error_log ${{ADMIN_ERROR_LOG}} ${{LOG_LEVEL}};
+
+> if cluster_mtls == "shared" then
+ ssl_verify_client optional_no_ca;
+> else
+ ssl_verify_client on;
+ ssl_client_certificate ${{CLUSTER_CA_CERT}};
+ ssl_verify_depth 4;
+> end
+ ssl_certificate ${{CLUSTER_CERT}};
+ ssl_certificate_key ${{CLUSTER_CERT_KEY}};
+ ssl_session_cache shared:ClusterSSL:10m;
+
+ location = /v1/outlet {
+ content_by_lua_block {
+ require("spec.fixtures.mock_cp").outlet()
+ }
+ }
+
+ location = /payload {
+ content_by_lua_block {
+ require("spec.fixtures.mock_cp").set_payload()
+ }
+ }
+
+ location = /log {
+ content_by_lua_block {
+ require("spec.fixtures.mock_cp").get_log()
+ }
+ }
+}
+]]):format(listen, listen_ssl)
+end
+
+
+return _M
diff --git a/kong-versions/3.9.0.0/kong/spec/fixtures/mock_upstream.lua b/kong-versions/3.9.0.0/kong/spec/fixtures/mock_upstream.lua
new file mode 100644
index 00000000..25d25b5b
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/fixtures/mock_upstream.lua
@@ -0,0 +1,426 @@
+-- This software is copyright Kong Inc. and its licensors.
+-- Use of the software is subject to the agreement between your organization
+-- and Kong Inc. If there is no such agreement, use is governed by and
+-- subject to the terms of the Kong Master Software License Agreement found
+-- at https://konghq.com/enterprisesoftwarelicense/.
+-- [ END OF LICENSE 0867164ffc95e54f04670b5169c09574bdbd9bba ]
+
+local cjson_safe = require "cjson.safe"
+local cjson = require "cjson"
+local ws_server = require "resty.websocket.server"
+local pl_file = require "pl.file"
+local strip = require("kong.tools.string").strip
+local split = require("kong.tools.string").split
+
+
+local kong = {
+ table = require("kong.pdk.table").new()
+}
+
+local ocsp_status = "good"
+
+local function parse_multipart_form_params(body, content_type)
+ if not content_type then
+ return nil, 'missing content-type'
+ end
+
+ local m, err = ngx.re.match(content_type, "boundary=(.+)", "oj")
+ if not m or not m[1] or err then
+ return nil, "could not find boundary in content type " .. content_type ..
+ "error: " .. tostring(err)
+ end
+
+ local boundary = m[1]
+ local parts_split = split(body, '--' .. boundary)
+ local params = {}
+ local part, from, to, part_value, part_name, part_headers, first_header
+ for i = 1, #parts_split do
+ part = strip(parts_split[i])
+
+ if part ~= '' and part ~= '--' then
+ from, to, err = ngx.re.find(part, '^\\r$', 'ojm')
+ if err or (not from and not to) then
+ return nil, nil, "could not find part body. Error: " .. tostring(err)
+ end
+
+ part_value = part:sub(to + 2, #part) -- +2: trim leading line jump
+ part_headers = part:sub(1, from - 1)
+ first_header = split(part_headers, '\\n')[1]
+ if first_header:lower():sub(1, 19) == "content-disposition" then
+ local m, err = ngx.re.match(first_header, 'name="(.*?)"', "oj")
+
+ if err or not m or not m[1] then
+ return nil, "could not parse part name. Error: " .. tostring(err)
+ end
+
+ part_name = m[1]
+ else
+ return nil, "could not find part name in: " .. part_headers
+ end
+
+ params[part_name] = part_value
+ end
+ end
+
+ return params
+end
+
+
+local function send_text_response(text, content_type, headers)
+ headers = headers or {}
+ content_type = content_type or "text/plain"
+
+ text = ngx.req.get_method() == "HEAD" and "" or tostring(text)
+
+ ngx.header["X-Powered-By"] = "mock_upstream"
+ ngx.header["Server"] = "mock-upstream/1.0.0"
+ ngx.header["Content-Length"] = #text + 1
+ ngx.header["Content-Type"] = content_type
+
+ for header,value in pairs(headers) do
+ if type(value) == "table" then
+ ngx.header[header] = table.concat(value, ", ")
+ else
+ ngx.header[header] = value
+ end
+ end
+
+ return ngx.say(text)
+end
+
+
+local function filter_access_by_method(method)
+ if ngx.req.get_method() ~= method then
+ ngx.status = ngx.HTTP_NOT_ALLOWED
+ send_text_response("Method not allowed for the requested URL")
+ return ngx.exit(ngx.OK)
+ end
+end
+
+
+local function find_http_credentials(authorization_header)
+ if not authorization_header then
+ return
+ end
+
+ local iterator, iter_err = ngx.re.gmatch(authorization_header,
+ "\\s*[Bb]asic\\s*(.+)")
+ if not iterator then
+ ngx.log(ngx.ERR, iter_err)
+ return
+ end
+
+ local m, err = iterator()
+
+ if err then
+ ngx.log(ngx.ERR, err)
+ return
+ end
+
+ if m and m[1] then
+ local decoded_basic = ngx.decode_base64(m[1])
+
+ if decoded_basic then
+ local user_pass = split(decoded_basic, ":")
+ return user_pass[1], user_pass[2]
+ end
+ end
+end
+
+
+local function filter_access_by_basic_auth(expected_username,
+ expected_password)
+ local headers = ngx.req.get_headers(0)
+
+ local username, password =
+ find_http_credentials(headers["proxy-authorization"])
+
+ if not username then
+ username, password =
+ find_http_credentials(headers["authorization"])
+ end
+
+ if username ~= expected_username or password ~= expected_password then
+ ngx.header["WWW-Authenticate"] = "mock_upstream"
+ ngx.header["X-Powered-By"] = "mock_upstream"
+ return ngx.exit(ngx.HTTP_UNAUTHORIZED)
+ end
+end
+
+
+local function get_ngx_vars()
+ local var = ngx.var
+ return {
+ uri = var.uri,
+ host = var.host,
+ hostname = var.hostname,
+ https = var.https,
+ scheme = var.scheme,
+ is_args = var.is_args,
+ server_addr = var.server_addr,
+ server_port = var.server_port,
+ server_name = var.server_name,
+ server_protocol = var.server_protocol,
+ remote_addr = var.remote_addr,
+ remote_port = var.remote_port,
+ realip_remote_addr = var.realip_remote_addr,
+ realip_remote_port = var.realip_remote_port,
+ binary_remote_addr = var.binary_remote_addr,
+ request = var.request,
+ request_uri = var.request_uri,
+ request_time = var.request_time,
+ request_length = var.request_length,
+ request_method = var.request_method,
+ bytes_received = var.bytes_received,
+ ssl_server_name = var.ssl_server_name or "no SNI",
+ }
+end
+
+
+local function get_body_data()
+ local req = ngx.req
+
+ req.read_body()
+ local data = req.get_body_data()
+ if data then
+ return data
+ end
+
+ local file_path = req.get_body_file()
+ if file_path then
+ local file = io.open(file_path, "r")
+ data = file:read("*all")
+ file:close()
+ return data
+ end
+
+ return ""
+end
+
+local function get_post_data(content_type)
+ local text = get_body_data()
+ local kind = "unknown"
+ local params = cjson_safe.null
+ local err
+
+ if type(content_type) == "string" then
+ if content_type:find("application/x-www-form-urlencoded", nil, true) then
+
+ kind = "form"
+ params, err = ngx.req.get_post_args(0)
+
+ elseif content_type:find("multipart/form-data", nil, true) then
+ kind = "multipart-form"
+ params, err = parse_multipart_form_params(text, content_type)
+
+ elseif content_type:find("application/json", nil, true) then
+ kind = "json"
+ params, err = cjson_safe.decode(text)
+ end
+
+ params = params or cjson_safe.null
+
+ if err then
+ kind = kind .. " (error)"
+ err = tostring(err)
+ end
+ end
+
+ return { text = text, kind = kind, params = params, error = err }
+end
+
+
+local function get_default_json_response()
+ local headers = ngx.req.get_headers(0)
+ local vars = get_ngx_vars()
+
+ return {
+ headers = headers,
+ post_data = get_post_data(headers["Content-Type"]),
+ url = ("%s://%s:%s%s"):format(vars.scheme, vars.host,
+ vars.server_port, vars.request_uri),
+ uri_args = ngx.req.get_uri_args(0),
+ vars = vars,
+ }
+end
+
+
+local function send_default_json_response(extra_fields, response_headers)
+ local tbl = kong.table.merge(get_default_json_response(), extra_fields)
+ return send_text_response(cjson.encode(tbl),
+ "application/json", response_headers)
+end
+
+
+local function serve_web_sockets()
+ local wb, err = ws_server:new({
+ timeout = 5000,
+ max_payload_len = 65535,
+ })
+
+ if not wb then
+ ngx.log(ngx.ERR, "failed to open websocket: ", err)
+ return ngx.exit(444)
+ end
+
+ while true do
+ local data, typ, err = wb:recv_frame()
+ if wb.fatal then
+ ngx.log(ngx.ERR, "failed to receive frame: ", err)
+ return ngx.exit(444)
+ end
+
+ if data then
+ if typ == "close" then
+ break
+ end
+
+ if typ == "ping" then
+ local bytes, err = wb:send_pong(data)
+ if not bytes then
+ ngx.log(ngx.ERR, "failed to send pong: ", err)
+ return ngx.exit(444)
+ end
+
+ elseif typ == "pong" then
+ ngx.log(ngx.INFO, "client ponged")
+
+ elseif typ == "text" then
+ local bytes, err = wb:send_text(data)
+ if not bytes then
+ ngx.log(ngx.ERR, "failed to send text: ", err)
+ return ngx.exit(444)
+ end
+ end
+
+ else
+ local bytes, err = wb:send_ping()
+ if not bytes then
+ ngx.log(ngx.ERR, "failed to send ping: ", err)
+ return ngx.exit(444)
+ end
+ end
+ end
+
+ wb:send_close()
+end
+
+
+local function get_logger()
+ local logger = ngx.shared.kong_mock_upstream_loggers
+ if not logger then
+ error("missing 'kong_mock_upstream_loggers' shm declaration")
+ end
+
+ return logger
+end
+
+
+local function store_log(logname)
+ ngx.req.read_body()
+
+ local raw_entries = ngx.req.get_body_data()
+ local logger = get_logger()
+
+ local entries = cjson.decode(raw_entries)
+ if #entries == 0 then
+ -- backwards-compatibility for `conf.queue_size == 1`
+ entries = { entries }
+ end
+
+ local log_req_params = ngx.req.get_uri_args()
+ local log_req_headers = ngx.req.get_headers(0)
+
+ for i = 1, #entries do
+ local store = {
+ entry = entries[i],
+ log_req_headers = log_req_headers,
+ log_req_params = log_req_params,
+ }
+
+ assert(logger:rpush(logname, cjson.encode(store)))
+ assert(logger:incr(logname .. "|count", 1, 0))
+ end
+
+ ngx.status = 200
+end
+
+
+local function retrieve_log(logname)
+ local logger = get_logger()
+ local len = logger:llen(logname)
+ local entries = {}
+
+ for i = 1, len do
+ local encoded_stored = assert(logger:lpop(logname))
+ local stored = cjson.decode(encoded_stored)
+ entries[i] = stored.entry
+ entries[i].log_req_headers = stored.log_req_headers
+ entries[i].log_req_params = stored.log_req_params
+ assert(logger:rpush(logname, encoded_stored))
+ end
+
+ local count, err = logger:get(logname .. "|count")
+ if err then
+ error(err)
+ end
+
+ ngx.status = 200
+ ngx.say(cjson.encode({
+ entries = entries,
+ count = count,
+ }))
+end
+
+
+local function count_log(logname)
+ local logger = get_logger()
+ local count = assert(logger:get(logname .. "|count"))
+
+ ngx.status = 200
+ ngx.say(count)
+end
+
+
+local function reset_log(logname)
+ local logger = get_logger()
+ logger:delete(logname)
+ logger:delete(logname .. "|count")
+end
+
+
+local function handle_ocsp()
+ if ocsp_status == "good" then
+ ngx.print(pl_file.read(ngx.config.prefix() .. "/../spec/fixtures/ocsp_certs/resp-good.dat"))
+
+ elseif ocsp_status == "revoked" then
+ ngx.print(pl_file.read(ngx.config.prefix() .. "/../spec/fixtures/ocsp_certs/resp-revoked.dat"))
+
+ elseif ocsp_status == "error" then
+ ngx.exit(500)
+
+ else
+ assert("unknown ocsp_status:" ..ocsp_status)
+ end
+end
+
+
+local function set_ocsp(status)
+ ocsp_status = status
+end
+
+
+return {
+ get_default_json_response = get_default_json_response,
+ filter_access_by_method = filter_access_by_method,
+ filter_access_by_basic_auth = filter_access_by_basic_auth,
+ send_text_response = send_text_response,
+ send_default_json_response = send_default_json_response,
+ serve_web_sockets = serve_web_sockets,
+ store_log = store_log,
+ retrieve_log = retrieve_log,
+ count_log = count_log,
+ reset_log = reset_log,
+ handle_ocsp = handle_ocsp,
+ set_ocsp = set_ocsp,
+}
diff --git a/kong-versions/3.9.0.0/kong/spec/fixtures/mock_webserver_tpl.lua b/kong-versions/3.9.0.0/kong/spec/fixtures/mock_webserver_tpl.lua
new file mode 100644
index 00000000..d0f1d207
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/fixtures/mock_webserver_tpl.lua
@@ -0,0 +1,267 @@
+-- This software is copyright Kong Inc. and its licensors.
+-- Use of the software is subject to the agreement between your organization
+-- and Kong Inc. If there is no such agreement, use is governed by and
+-- subject to the terms of the Kong Master Software License Agreement found
+-- at https://konghq.com/enterprisesoftwarelicense/.
+-- [ END OF LICENSE 0867164ffc95e54f04670b5169c09574bdbd9bba ]
+
+return [[daemon on;
+worker_processes ${worker_num};
+error_log ${base_path}/${logs_dir}/error.log info;
+pid ${base_path}/${logs_dir}/nginx.pid;
+worker_rlimit_nofile 8192;
+
+events {
+ worker_connections 1024;
+}
+
+http {
+ lua_shared_dict server_values 512k;
+ lua_shared_dict logs 512k;
+ lua_shared_dict log_locks 512k;
+
+ init_worker_by_lua_block {
+ local resty_lock = require "resty.lock"
+ _G.log_locks = resty_lock:new("log_locks")
+
+ _G.log_record = function(ngx_req)
+ local cjson = require("cjson")
+ local args, err = ngx_req.get_uri_args(0)
+ local key = args['key'] or "default"
+ local log_locks = _G.log_locks
+
+ if err then
+ return ngx.exit(ngx.HTTP_INTERNAL_SERVER_ERROR)
+ end
+
+ log_locks:lock("lock")
+
+ local logs = ngx.shared.logs:get(key) or "[]"
+
+ if not args['do_not_log'] then
+ local log = {
+ time = ngx.now(),
+ -- path = "/log",
+ method = ngx_req.get_method(),
+ headers = ngx_req.get_headers(0),
+ }
+
+ logs = cjson.decode(logs)
+ table.insert(logs, log)
+ logs = cjson.encode(logs)
+ ngx.shared.logs:set(key, logs)
+ end
+
+ log_locks:unlock()
+
+ return logs
+ end
+
+ local server_values = ngx.shared.server_values
+# for _, prefix in ipairs(hosts) do
+ if server_values:get("$(prefix)_healthy") == nil then
+ server_values:set("$(prefix)_healthy", true)
+ ngx.log(ngx.INFO, "Creating entries for $(prefix)_healthy")
+ end
+
+ if server_values:get("$(prefix)_timeout") == nil then
+ server_values:set("$(prefix)_timeout", false)
+ ngx.log(ngx.INFO, "Creating entries for $(prefix)_timeout")
+ end
+# end
+ }
+
+ default_type application/json;
+ access_log ${base_path}/${logs_dir}/access.log;
+ sendfile on;
+ tcp_nopush on;
+ server_names_hash_bucket_size 128;
+
+ server {
+# if protocol ~= 'https' then
+ listen 127.0.0.1:${http_port};
+# if not disable_ipv6 then
+ listen [::1]:${http_port};
+#end
+# else
+ listen 127.0.0.1:${http_port} ssl;
+# if not disable_ipv6 then
+ listen [::1]:${http_port} ssl;
+#end
+ http2 on;
+
+ ssl_certificate ${cert_path}/kong_spec.crt;
+ ssl_certificate_key ${cert_path}/kong_spec.key;
+ ssl_protocols TLSv1.2;
+ ssl_ciphers HIGH:!aNULL:!MD5;
+#end
+# if check_hostname then
+ server_name ${host};
+#end
+
+ location = /clear_log {
+ content_by_lua_block {
+ local log_locks = _G.log_locks
+ log_locks:lock("lock")
+ ngx.shared.logs:flush_all()
+ log_locks:unlock()
+ ngx.say("cleared")
+ }
+ }
+
+ location = /log {
+ content_by_lua_block {
+ ngx.say(_G.log_record(ngx.req))
+ }
+ }
+
+ location = /always_200 {
+ content_by_lua_block {
+ ngx.say("ok")
+ return ngx.exit(ngx.HTTP_OK)
+ }
+ }
+
+ location = /healthy {
+ access_by_lua_block {
+ local host = ngx.req.get_headers(0)["host"] or "localhost"
+ local host_no_port = ngx.re.match(host, [=[([a-z0-9\-._~%!$&'()*+,;=]+@)?([a-z0-9\-._~%]+|\[[a-z0-9\-._~%!$&'()*+,;=:]+\])(:?[0-9]+)*]=])
+ if host_no_port == nil then
+ return ngx.exit(ngx.HTTP_INTERNAL_SERVER_ERROR)
+ else
+ host = host_no_port[2]
+ if host == "[0000:0000:0000:0000:0000:0000:0000:0001]" then
+ host = "[::1]"
+ end
+ end
+ ngx.shared.server_values:set(host .. "_healthy", true)
+ ngx.shared.server_values:set(host .. "_timeout", false)
+ ngx.log(ngx.INFO, "Host ", host, " is now healthy")
+ }
+
+ content_by_lua_block {
+ ngx.say("server ", ngx.var.server_name, " is now healthy")
+ return ngx.exit(ngx.HTTP_OK)
+ }
+ }
+
+ location = /unhealthy {
+ access_by_lua_block {
+ local host = ngx.req.get_headers(0)["host"] or "localhost"
+ local host_no_port = ngx.re.match(host, [=[([a-z0-9\-._~%!$&'()*+,;=]+@)?([a-z0-9\-._~%]+|\[[a-z0-9\-._~%!$&'()*+,;=:]+\])(:?[0-9]+)*]=])
+ if host_no_port == nil then
+ return ngx.exit(ngx.HTTP_INTERNAL_SERVER_ERROR)
+ else
+ host = host_no_port[2]
+ if host == "[0000:0000:0000:0000:0000:0000:0000:0001]" then
+ host = "[::1]"
+ end
+ end
+ ngx.shared.server_values:set(host .. "_healthy", false)
+ ngx.log(ngx.INFO, "Host ", host, " is now unhealthy")
+ }
+
+ content_by_lua_block {
+ ngx.say("server ", ngx.var.server_name, " is now unhealthy")
+ return ngx.exit(ngx.HTTP_OK)
+ }
+ }
+
+ location = /timeout {
+ access_by_lua_block {
+ local host = ngx.req.get_headers()["host"] or "localhost"
+ local host_no_port = ngx.re.match(host, [=[([a-z0-9\-._~%!$&'()*+,;=]+@)?([a-z0-9\-._~%]+|\[[a-z0-9\-._~%!$&'()*+,;=:]+\])(:?[0-9]+)*]=])
+ if host_no_port == nil then
+ return ngx.exit(ngx.HTTP_INTERNAL_SERVER_ERROR)
+ else
+ host = host_no_port[2]
+ if host == "[0000:0000:0000:0000:0000:0000:0000:0001]" then
+ host = "[::1]"
+ end
+ end
+ ngx.shared.server_values:set(host .. "_timeout", true)
+ ngx.log(ngx.INFO, "Host ", host, " is timeouting now")
+ }
+
+ content_by_lua_block {
+ ngx.say("server ", ngx.var.server_name, " is timeouting now")
+ return ngx.exit(ngx.HTTP_OK)
+ }
+ }
+
+ location = /status {
+ access_by_lua_block {
+ _G.log_record(ngx.req)
+ local i = require 'inspect'
+ ngx.log(ngx.ERR, "INSPECT status (headers): ", i(ngx.req.get_headers(0)))
+ local host = ngx.req.get_headers(0)["host"] or "localhost"
+ local host_no_port = ngx.re.match(host, [=[([a-z0-9\-._~%!$&'()*+,;=]+@)?([a-z0-9\-._~%]+|\[[a-z0-9\-._~%!$&'()*+,;=:]+\])(:?[0-9]+)*]=])
+ if host_no_port == nil then
+ return ngx.exit(ngx.HTTP_INTERNAL_SERVER_ERROR)
+ else
+ host = host_no_port[2]
+ if host == "[0000:0000:0000:0000:0000:0000:0000:0001]" then
+ host = "[::1]"
+ end
+ end
+ local server_values = ngx.shared.server_values
+
+ local status = server_values:get(host .. "_healthy") and
+ ngx.HTTP_OK or ngx.HTTP_INTERNAL_SERVER_ERROR
+
+ if server_values:get(host .. "_timeout") == true then
+ ngx.log(ngx.INFO, "Host ", host, " timeouting...")
+ ngx.log(ngx.INFO, "[COUNT] status 599")
+ ngx.sleep(4)
+ else
+ ngx.log(ngx.INFO, "[COUNT] status ", status)
+ end
+
+ ngx.exit(status)
+ }
+ }
+
+ location / {
+ access_by_lua_block {
+ _G.log_record(ngx.req)
+ local cjson = require("cjson")
+ local server_values = ngx.shared.server_values
+ local host = ngx.req.get_headers(0)["host"] or "localhost"
+ local host_no_port = ngx.re.match(host, [=[([a-z0-9\-._~%!$&'()*+,;=]+@)?([a-z0-9\-._~%]+|\[[a-z0-9\-._~%!$&'()*+,;=:]+\])(:?[0-9]+)*]=])
+ if host_no_port == nil then
+ return ngx.exit(ngx.HTTP_INTERNAL_SERVER_ERROR)
+ else
+ host = host_no_port[2]
+ if host == "[0000:0000:0000:0000:0000:0000:0000:0001]" then
+ host = "[::1]"
+ end
+ end
+ local status
+
+ local status = server_values:get(host .. "_healthy") and
+ ngx.HTTP_OK or ngx.HTTP_INTERNAL_SERVER_ERROR
+
+ if server_values:get(host .. "_timeout") == true then
+ -- not this status actually, but it is used to count failures
+ ngx.log(ngx.INFO, "[COUNT] slash 599")
+ ngx.sleep(4)
+ else
+ ngx.log(ngx.INFO, "[COUNT] slash ", status)
+ end
+
+ ngx.sleep(${delay}/1000)
+ ngx.exit(status)
+ }
+ }
+ }
+# if check_hostname then
+ server {
+ listen 127.0.0.1:${http_port} default_server;
+ listen [::1]:${http_port} default_server;
+ server_name _;
+ return 400;
+ }
+# end
+
+}
+]]
diff --git a/kong-versions/3.9.0.0/kong/spec/fixtures/mocker.lua b/kong-versions/3.9.0.0/kong/spec/fixtures/mocker.lua
new file mode 100644
index 00000000..2080c57d
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/fixtures/mocker.lua
@@ -0,0 +1,68 @@
+-- This software is copyright Kong Inc. and its licensors.
+-- Use of the software is subject to the agreement between your organization
+-- and Kong Inc. If there is no such agreement, use is governed by and
+-- subject to the terms of the Kong Master Software License Agreement found
+-- at https://konghq.com/enterprisesoftwarelicense/.
+-- [ END OF LICENSE 0867164ffc95e54f04670b5169c09574bdbd9bba ]
+
+local mocker = {}
+
+-- Setup mocks, which are undone in a finally() block
+-- @param finally The `finally` function, that needs to be passed in because
+-- Busted generates it dynamically.
+-- @param args A table containing three optional fields:
+-- * modules: an array of pairs (module name, module content).
+-- This allows modules to be declared in order.
+-- * kong: a mock of the kong global (which will fallback to the default one
+-- via metatable)
+-- * ngx: a mock of the ngx global (which will fallback to the default one
+-- via metatable)
+function mocker.setup(finally, args)
+
+ local mocked_modules = {}
+ local _ngx = _G.ngx
+ local _kong = _G.kong
+
+ local function mock_module(name, tbl)
+ local old_module = require(name)
+ mocked_modules[name] = true
+ package.loaded[name] = setmetatable(tbl or {}, {
+ __index = old_module,
+ })
+ end
+
+ if args.ngx then
+ _G.ngx = setmetatable(args.ngx, { __index = _ngx })
+ end
+
+ if args.kong then
+ _G.kong = setmetatable(args.kong, { __index = _kong })
+ end
+
+ if args.modules then
+ for _, pair in ipairs(args.modules) do
+ mock_module(pair[1], pair[2])
+ end
+ end
+
+ finally(function()
+ _G.ngx = _ngx
+ _G.kong = _kong
+
+ for k in pairs(mocked_modules) do
+ package.loaded[k] = nil
+ end
+ end)
+end
+
+
+function mocker.table_where_every_key_returns(value)
+ return setmetatable({}, {
+ __index = function()
+ return value
+ end
+ })
+end
+
+
+return mocker
diff --git a/kong-versions/3.9.0.0/kong/spec/fixtures/mocking/T1-1748.json b/kong-versions/3.9.0.0/kong/spec/fixtures/mocking/T1-1748.json
new file mode 100644
index 00000000..fdaff9b7
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/fixtures/mocking/T1-1748.json
@@ -0,0 +1,357 @@
+{
+ "openapi": "3.0.2",
+ "info": {
+ "description": "This is a sample server Petstore server. You can find out more about Swagger at [http://swagger.io](http://swagger.io) or on [irc.freenode.net, #swagger](http://swagger.io/irc/). For this sample, you can use the api key `special-key` to test the authorization filters.",
+ "version": "1.0.0",
+ "title": "Swagger Petstore",
+ "termsOfService": "http://swagger.io/terms/",
+ "contact": {
+ "email": "apiteam@swagger.io"
+ },
+ "license": {
+ "name": "Apache 2.0",
+ "url": "http://www.apache.org/licenses/LICENSE-2.0.html"
+ }
+ },
+ "servers": [{
+ "url": "http://petstore.swagger.io/v2"
+ }],
+ "tags": [{
+ "name": "pet",
+ "description": "Everything about your Pets",
+ "externalDocs": {
+ "description": "Find out more",
+ "url": "http://swagger.io"
+ }
+ }],
+ "paths": {
+ "/pet/findByStatus/MultipleExamples": {
+ "get": {
+ "tags": ["pet"],
+ "summary": "Finds Pets by status",
+ "description": "Multiple status values can be provided with comma separated strings",
+ "operationId": "findPetsByStatus",
+ "produces": ["application/xml", "application/json"],
+ "parameters": [{
+ "name": "status",
+ "in": "query",
+ "description": "Status values that need to be considered for filter",
+ "required": true,
+ "schema": {
+ "type": "array",
+ "items": {
+ "type": "string",
+ "enum": ["available", "pending", "sold"],
+ "default": "available"
+ }
+ },
+ "style": "form",
+ "explode": true,
+ "examples": {
+ "Available": {
+ "summary": "Available",
+ "description": "Showing status of `available`, using `value` property",
+ "value": "available"
+ },
+ "Sold": {
+ "summary": "Sold",
+ "description": "Showing status of `sold`, using `externalValue` property",
+ "externalValue": "http://example.com/examples/dog.json"
+ }
+ }
+ }],
+ "responses": {
+ "200": {
+ "description": "successful operation",
+ "content": {
+ "application/json": {
+ "examples": {
+ "Issue1": {
+ "value": {
+ "issueCode": "example issue code",
+ "reference": "example reference"
+ }
+ },
+ "Issue2": {
+ "value": {
+ "issueCode": "example issue 2",
+ "reference": "example reference 2"
+ }
+ }
+ }
+ }
+ }
+
+
+ },
+ "400": {
+ "description": "Invalid status value"
+ }
+ },
+ "security": [{
+ "petstore_auth": ["write:pets", "read:pets"]
+ }]
+ }
+ },
+ "/pet/findByStatus/singleExample": {
+ "get": {
+ "tags": ["pet"],
+ "summary": "Finds Pets by status",
+ "description": "Multiple status values can be provided with comma separated strings",
+ "operationId": "findPetsByStatus",
+ "produces": ["application/xml", "application/json"],
+ "parameters": [{
+ "name": "status",
+ "in": "query",
+ "description": "Status values that need to be considered for filter",
+ "required": true,
+ "schema": {
+ "type": "array",
+ "items": {
+ "type": "string",
+ "enum": ["available", "pending", "sold"],
+ "default": "available"
+ }
+ },
+ "style": "form",
+ "explode": true,
+ "example": {
+ "summary": "Available",
+ "description": "Showing status of `available`, using `value` property",
+ "value": "available"
+ }
+ }],
+ "responses": {
+ "200": {
+ "description": "successful operation",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "array",
+ "items": {
+ "$ref": "#/components/schemas/Pet"
+ }
+ },
+ "example": {
+ "summary": "Example response showing a regular response",
+ "description": "Two pets are returned in this example.",
+ "value": [{
+ "id": 1,
+ "category": {
+ "id": 1,
+ "name": "cat"
+ },
+ "name": "fluffy",
+ "photoUrls": [
+ "http://example.com/path/to/cat/1.jpg",
+ "http://example.com/path/to/cat/2.jpg"
+ ],
+ "tags": [{
+ "id": 1,
+ "name": "cat"
+ }],
+ "status": "available"
+ }, {
+ "id": 2,
+ "category": {
+ "id": 2,
+ "name": "dog"
+ },
+ "name": "puppy",
+ "photoUrls": [
+ "http://example.com/path/to/dog/1.jpg"
+ ],
+ "tags": [{
+ "id": 2,
+ "name": "dog"
+ }],
+ "status": "available"
+ }]
+ }
+ }
+ }
+ },
+ "400": {
+ "description": "Invalid status value"
+ }
+ },
+ "security": [{
+ "petstore_auth": ["write:pets", "read:pets"]
+ }]
+ }
+ },
+ "/pet": {
+ "post": {
+ "tags": ["pet"],
+ "summary": "Add a new pet to the store",
+ "description": "",
+ "operationId": "addPet",
+ "requestBody": {
+ "description": "Pet object that needs to be added to the store",
+ "required": true,
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Pet"
+ },
+ "examples": {
+ "Cat": {
+ "summary": "An example of cat",
+ "description": "An example of cat, using `value` property",
+ "value": {
+ "id": 1,
+ "category": {
+ "id": 1,
+ "name": "cat"
+ },
+ "name": "fluffy",
+ "photoUrls": [
+ "http://example.com/path/to/cat/1.jpg",
+ "http://example.com/path/to/cat/2.jpg"
+ ],
+ "tags": [{
+ "id": 1,
+ "name": "cat"
+ }],
+ "status": "available"
+ }
+ },
+ "Cat2": {
+ "summary": "An example of cat",
+ "description": "An example of cat, using `value` property, which value is an array",
+ "value": [{
+ "id": 1,
+ "category": {
+ "id": 1,
+ "name": "cat"
+ },
+ "name": "fluffy",
+ "photoUrls": [
+ "http://example.com/path/to/cat/1.jpg",
+ "http://example.com/path/to/cat/2.jpg"
+ ],
+ "tags": [{
+ "id": 1,
+ "name": "cat"
+ }],
+ "status": "available"
+ }]
+ },
+ "Dog": {
+ "summary": "An example of dog",
+ "description": "An example of dog, using `externalValue` property",
+ "externalValue": "http://example.com/examples/dog.json"
+ }
+ }
+ },
+ "application/xml": {
+ "schema": {
+ "$ref": "#/components/schemas/Pet"
+ },
+ "examples": {
+ "Cat": {
+ "summary": "An example of cat",
+ "description": "An example of cat, using `value` property",
+ "value": ""
+ },
+ "Dog": {
+ "summary": "An example of dog",
+ "description": "An example of dog, using `externalValue` property",
+ "externalValue": "http://example.com/examples/dog.xml"
+ }
+ }
+ }
+ }
+ },
+ "responses": {
+ "405": {
+ "description": "Invalid input"
+ }
+ }
+ }
+ }
+ },
+ "components": {
+ "schemas": {
+ "Category": {
+ "type": "object",
+ "properties": {
+ "id": {
+ "type": "integer",
+ "format": "int64"
+ },
+ "name": {
+ "type": "string"
+ }
+ },
+ "xml": {
+ "name": "Category"
+ }
+ },
+ "Tag": {
+ "type": "object",
+ "properties": {
+ "id": {
+ "type": "integer",
+ "format": "int64"
+ },
+ "name": {
+ "type": "string"
+ }
+ },
+ "xml": {
+ "name": "Tag"
+ }
+ },
+ "Pet": {
+ "type": "object",
+ "required": ["name", "photoUrls"],
+ "properties": {
+ "id": {
+ "type": "integer",
+ "format": "int64"
+ },
+ "category": {
+ "$ref": "#/components/schemas/Category"
+ },
+ "name": {
+ "type": "string",
+ "example": "doggie"
+ },
+ "photoUrls": {
+ "type": "array",
+ "xml": {
+ "name": "photoUrl",
+ "wrapped": true
+ },
+ "items": {
+ "type": "string"
+ }
+ },
+ "tags": {
+ "type": "array",
+ "xml": {
+ "name": "tag",
+ "wrapped": true
+ },
+ "items": {
+ "$ref": "#/components/schemas/Tag"
+ }
+ },
+ "status": {
+ "type": "string",
+ "description": "pet status in the store",
+ "enum": ["available", "pending", "sold"]
+ }
+ },
+ "xml": {
+ "name": "Pet"
+ }
+ }
+ }
+ },
+ "externalDocs": {
+ "description": "Find out more about Swagger",
+ "url": "http://swagger.io"
+ }
+}
diff --git a/kong-versions/3.9.0.0/kong/spec/fixtures/mocking/fhir.json b/kong-versions/3.9.0.0/kong/spec/fixtures/mocking/fhir.json
new file mode 100644
index 00000000..9a5ff7e7
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/fixtures/mocking/fhir.json
@@ -0,0 +1,308 @@
+ {
+ "swagger": "2.0",
+ "info": {
+ "title": "FHIR Patient",
+ "description": "Demographics and other administrative information about an individual or animal receiving care or other health-related services. For more information: https://www.hl7.org/fhir/patient.html",
+ "version": "2.1"
+ },
+ "host": "localhost:8000",
+ "basePath": "/v2",
+ "schemes": [
+ "http",
+ "https"
+ ],
+ "consumes": [
+ "application/json"
+ ],
+ "produces": [
+ "application/json"
+ ],
+ "paths": {
+ "/Patient/{id}": {
+ "get": {
+ "description": "",
+ "operationId": "GET /Patient/{id}",
+ "produces": [
+ "application/json+fhir",
+ "application/xml+fhir"
+ ],
+ "tags": [
+ "Patient"
+ ],
+ "parameters": [{
+ "required": true,
+ "in": "path",
+ "name": "id",
+ "type": "string"
+ }],
+ "responses": {
+ "200": {
+ "description": "Status 200",
+ "examples": {
+ "application/json+fhir": {
+ "resourceType": "Patient",
+ "identifier": [{
+ "use": "official",
+ "value": "1015617902"
+ }],
+ "active": true,
+ "name": [{
+ "use": "official",
+ "family": "Sehl",
+ "given": [
+ "Vivien"
+ ]
+ }],
+ "gender": "male",
+ "birthDate": "1946-05-11",
+ "telecom": [{
+ "system": "email",
+ "use": "home",
+ "value": "dynamic.extras2@medibank.com.au"
+ },
+ {
+ "system": "phone",
+ "use": "mobile",
+ "value": "99999"
+ }
+ ],
+ "address": [{
+ "use": "home",
+ "type": "physical",
+ "text": "720 Bourke Street, Medibank, Docklands, Queensland - 4074 ",
+ "line": [
+ "720 Bourke Street",
+ "",
+ "Medibank"
+ ],
+ "city": "Docklands",
+ "state": "Queensland",
+ "postalCode": "4074"
+ }]
+ }
+ }
+ },
+ "404": {
+ "description": "Tried to get an unknown resource\n"
+ },
+ "410": {
+ "description": "Tried to get a deleted resource\n"
+ },
+ "422": {
+ "description": "Unprocessable Entity - the proposed resource violated applicable FHIR profiles or server business rules. This should be accompanied by an OperationOutcome resource providing additional detail.\n"
+ }
+ }
+ },
+ "put": {
+ "description": "Update an existing instance\n",
+ "operationId": "PUT /Patient/{id}",
+ "consumes": [
+ "application/json+fhir",
+ "application/xml+fhir"
+ ],
+ "produces": [
+ "application/json+fhir",
+ "application/xml+fhir"
+ ],
+ "parameters": [{
+ "required": true,
+ "in": "path",
+ "name": "id",
+ "type": "string"
+ }],
+ "tags": [
+ "Patient"
+ ],
+ "responses": {
+ "200": {
+ "description": "Succesfully updated the instance \n"
+ },
+ "201": {
+ "description": "Succesfully created the instance \n"
+ },
+ "400": {
+ "description": "Bad Request - Resource cound not be parsed or failed basic FHIR validation rules\n"
+ },
+ "404": {
+ "description": "Not Found - resource type not support, or not a FHIR validation rules\n"
+ },
+ "405": {
+ "description": "Method Not allowed - the resource did not exist prior to the update, and the server does not allow client defined ids\n"
+ },
+ "409": {
+ "description": "Version conflict management\n"
+ },
+ "412": {
+ "description": "Version conflict management\n"
+ },
+ "422": {
+ "description": "Unprocessable Entity - the proposed resource violated applicable FHIR profiles or server business rules. This should be accompanied by an OperationOutcome resource providing additional detail.\n"
+ }
+ }
+ },
+ "delete": {
+ "description": "Delete resource\n",
+ "operationId": "DELETE /Patient/{id}",
+ "produces": [
+ "application/json+fhir",
+ "application/xml+fhir"
+ ],
+ "parameters": [{
+ "required": true,
+ "in": "path",
+ "name": "id",
+ "type": "string"
+ }],
+ "tags": [
+ "Patient"
+ ],
+ "responses": {
+ "204": {
+ "description": "Succesfully deleted resource\n"
+ },
+ "404": {
+ "description": "Not Found - resource was not found\n"
+ },
+ "405": {
+ "description": "Method Not allowed - delete is not allowed\n"
+ }
+ }
+ }
+ }
+ },
+ "definitions": {
+ "Patient": {
+ "properties": {
+ "resourceType": {
+ "type": "string",
+ "example": "Patient"
+ },
+ "identifier": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {
+ "use": {
+ "type": "string",
+ "example": "official"
+ },
+ "value": {
+ "type": "string",
+ "example": "1015617902"
+ }
+ }
+ }
+ },
+ "active": {
+ "type": "boolean"
+ },
+ "name": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {
+ "use": {
+ "type": "string",
+ "example": "official"
+ },
+ "family": {
+ "type": "string",
+ "example": "Sehl"
+ },
+ "given": {
+ "type": "array",
+ "items": {
+ "type": "string",
+ "example": "Vivien"
+ }
+ }
+ }
+ }
+ },
+ "gender": {
+ "type": "string",
+ "example": "male"
+ },
+ "birthDate": {
+ "type": "string",
+ "format": "date",
+ "example": "1946-05-11"
+ },
+ "telecom": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {
+ "system": {
+ "type": "string",
+ "example": "email"
+ },
+ "use": {
+ "type": "string",
+ "example": "home"
+ },
+ "value": {
+ "type": "string",
+ "example": "dynamic.extras2@medibank.com.au"
+ }
+ }
+ }
+ },
+ "address": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {
+ "use": {
+ "type": "string",
+ "example": "home"
+ },
+ "type": {
+ "type": "string",
+ "example": "physical"
+ },
+ "text": {
+ "type": "string",
+ "example": "720 Bourke Street, Medibank, Docklands, Queensland - 4074"
+ },
+ "line": {
+ "type": "array",
+ "items": {
+ "type": "string",
+ "example": "720 Bourke Street"
+ }
+ },
+ "city": {
+ "type": "string",
+ "example": "Docklands"
+ },
+ "state": {
+ "type": "string",
+ "example": "Queensland"
+ },
+ "postalCode": {
+ "type": "string",
+ "example": "4074"
+ }
+ }
+ }
+ }
+ }
+ },
+ "Error": {
+ "required": [
+ "code",
+ "message"
+ ],
+ "properties": {
+ "code": {
+ "type": "integer",
+ "format": "int32"
+ },
+ "message": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
\ No newline at end of file
diff --git a/kong-versions/3.9.0.0/kong/spec/fixtures/mocking/multipleexamples.json b/kong-versions/3.9.0.0/kong/spec/fixtures/mocking/multipleexamples.json
new file mode 100644
index 00000000..26b3f1ae
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/fixtures/mocking/multipleexamples.json
@@ -0,0 +1,371 @@
+{
+ "openapi": "3.0.2",
+ "info": {
+ "description": "This is a sample server Petstore server. You can find out more about Swagger at [http://swagger.io](http://swagger.io) or on [irc.freenode.net, #swagger](http://swagger.io/irc/). For this sample, you can use the api key `special-key` to test the authorization filters.",
+ "version": "1.0.0",
+ "title": "Swagger Petstore",
+ "termsOfService": "http://swagger.io/terms/",
+ "contact": {
+ "email": "apiteam@swagger.io"
+ },
+ "license": {
+ "name": "Apache 2.0",
+ "url": "http://www.apache.org/licenses/LICENSE-2.0.html"
+ }
+ },
+ "servers": [{
+ "url": "http://petstore.swagger.io/v2"
+ }],
+ "tags": [{
+ "name": "pet",
+ "description": "Everything about your Pets",
+ "externalDocs": {
+ "description": "Find out more",
+ "url": "http://swagger.io"
+ }
+ }],
+ "paths": {
+ "/pet/findByStatus/MultipleExamples": {
+ "get": {
+ "tags": ["pet"],
+ "summary": "Finds Pets by status",
+ "description": "Multiple status values can be provided with comma separated strings",
+ "operationId": "findPetsByStatus",
+ "produces": ["application/xml", "application/json"],
+ "parameters": [{
+ "name": "status",
+ "in": "query",
+ "description": "Status values that need to be considered for filter",
+ "required": true,
+ "schema": {
+ "type": "array",
+ "items": {
+ "type": "string",
+ "enum": ["available", "pending", "sold"],
+ "default": "available"
+ }
+ },
+ "style": "form",
+ "explode": true,
+ "examples": {
+ "Available": {
+ "summary": "Available",
+ "description": "Showing status of `available`, using `value` property",
+ "value": "available"
+ },
+ "Sold": {
+ "summary": "Sold",
+ "description": "Showing status of `sold`, using `externalValue` property",
+ "externalValue": "http://example.com/examples/dog.json"
+ }
+ }
+ }],
+ "responses": {
+ "200": {
+ "description": "successful operation",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "array",
+ "items": {
+ "$ref": "#/components/schemas/Pet"
+ }
+ },
+ "examples": {
+ "No Content": {
+ "summary": "Example response showing no pets are matched",
+ "description": "An example response, using `value` property",
+ "value": []
+ },
+ "Example 1": {
+ "summary": "Example response showing a regular response",
+ "description": "Two pets are returned in this example.",
+ "value": [{
+ "id": 1,
+ "category": {
+ "id": 1,
+ "name": "cat"
+ },
+ "nickname": "fluffy",
+ "photoUrls": [
+ "http://example.com/path/to/cat/1.jpg",
+ "http://example.com/path/to/cat/2.jpg"
+ ],
+ "tags": [{
+ "id": 1,
+ "name": "cat"
+ }],
+ "status": "available"
+ }, {
+ "id": 2,
+ "category": {
+ "id": 2,
+ "name": "dog"
+ },
+ "nickname": "puppy",
+ "photoUrls": [
+ "http://example.com/path/to/dog/1.jpg"
+ ],
+ "tags": [{
+ "id": 2,
+ "name": "dog"
+ }],
+ "status": "available"
+ }]
+ }
+ }
+ }
+ }
+ },
+ "400": {
+ "description": "Invalid status value"
+ }
+ },
+ "security": [{
+ "petstore_auth": ["write:pets", "read:pets"]
+ }]
+ }
+ },
+ "/pet/findByStatus/singleExample": {
+ "get": {
+ "tags": ["pet"],
+ "summary": "Finds Pets by status",
+ "description": "Multiple status values can be provided with comma separated strings",
+ "operationId": "findPetsByStatus",
+ "produces": ["application/xml", "application/json"],
+ "parameters": [{
+ "name": "status",
+ "in": "query",
+ "description": "Status values that need to be considered for filter",
+ "required": true,
+ "schema": {
+ "type": "array",
+ "items": {
+ "type": "string",
+ "enum": ["available", "pending", "sold"],
+ "default": "available"
+ }
+ },
+ "style": "form",
+ "explode": true,
+ "example": {
+ "summary": "Available",
+ "description": "Showing status of `available`, using `value` property",
+ "value": "available"
+ }
+ }],
+ "responses": {
+ "200": {
+ "description": "successful operation",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "array",
+ "items": {
+ "$ref": "#/components/schemas/Pet"
+ }
+ },
+ "example": {
+ "id": 1,
+ "category": {
+ "id": 1,
+ "name": "cat"
+ },
+ "nickname": "fluffy",
+ "photoUrls": [
+ "http://example.com/path/to/cat/1.jpg",
+ "http://example.com/path/to/cat/2.jpg"
+ ],
+ "tags": [{
+ "id": 1,
+ "name": "cat"
+ }],
+ "status": "available"
+ }
+ }
+ }
+ },
+ "400": {
+ "description": "Invalid status value"
+ }
+ },
+ "security": [{
+ "petstore_auth": ["write:pets", "read:pets"]
+ }]
+ }
+ },
+ "/pet": {
+ "post": {
+ "tags": ["pet"],
+ "summary": "Add a new pet to the store",
+ "description": "",
+ "operationId": "addPet",
+ "requestBody": {
+ "description": "Pet object that needs to be added to the store",
+ "required": true,
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Pet"
+ },
+ "examples": {
+ "Cat": {
+ "summary": "An example of cat",
+ "description": "An example of cat, using `value` property",
+ "value": {
+ "id": 1,
+ "category": {
+ "id": 1,
+ "name": "cat"
+ },
+ "name": "fluffy",
+ "photoUrls": [
+ "http://example.com/path/to/cat/1.jpg",
+ "http://example.com/path/to/cat/2.jpg"
+ ],
+ "tags": [{
+ "id": 1,
+ "name": "cat"
+ }],
+ "status": "available"
+ }
+ },
+ "Cat2": {
+ "summary": "An example of cat",
+ "description": "An example of cat, using `value` property, which value is an array",
+ "value": [{
+ "id": 1,
+ "category": {
+ "id": 1,
+ "name": "cat"
+ },
+ "name": "fluffy",
+ "photoUrls": [
+ "http://example.com/path/to/cat/1.jpg",
+ "http://example.com/path/to/cat/2.jpg"
+ ],
+ "tags": [{
+ "id": 1,
+ "name": "cat"
+ }],
+ "status": "available"
+ }]
+ },
+ "Dog": {
+ "summary": "An example of dog",
+ "description": "An example of dog, using `externalValue` property",
+ "externalValue": "http://example.com/examples/dog.json"
+ }
+ }
+ },
+ "application/xml": {
+ "schema": {
+ "$ref": "#/components/schemas/Pet"
+ },
+ "examples": {
+ "Cat": {
+ "summary": "An example of cat",
+ "description": "An example of cat, using `value` property",
+ "value": ""
+ },
+ "Dog": {
+ "summary": "An example of dog",
+ "description": "An example of dog, using `externalValue` property",
+ "externalValue": "http://example.com/examples/dog.xml"
+ }
+ }
+ }
+ }
+ },
+ "responses": {
+ "405": {
+ "description": "Invalid input"
+ }
+ }
+ }
+ }
+ },
+ "components": {
+ "schemas": {
+ "Category": {
+ "type": "object",
+ "properties": {
+ "id": {
+ "type": "integer",
+ "format": "int64"
+ },
+ "name": {
+ "type": "string"
+ }
+ },
+ "xml": {
+ "name": "Category"
+ }
+ },
+ "Tag": {
+ "type": "object",
+ "properties": {
+ "id": {
+ "type": "integer",
+ "format": "int64"
+ },
+ "name": {
+ "type": "string"
+ }
+ },
+ "xml": {
+ "name": "Tag"
+ }
+ },
+ "Pet": {
+ "type": "object",
+ "required": ["name", "photoUrls"],
+ "properties": {
+ "id": {
+ "type": "integer",
+ "format": "int64"
+ },
+ "category": {
+ "$ref": "#/components/schemas/Category"
+ },
+ "name": {
+ "type": "string",
+ "example": "doggie"
+ },
+ "photoUrls": {
+ "type": "array",
+ "xml": {
+ "name": "photoUrl",
+ "wrapped": true
+ },
+ "items": {
+ "type": "string"
+ }
+ },
+ "tags": {
+ "type": "array",
+ "xml": {
+ "name": "tag",
+ "wrapped": true
+ },
+ "items": {
+ "$ref": "#/components/schemas/Tag"
+ }
+ },
+ "status": {
+ "type": "string",
+ "description": "pet status in the store",
+ "enum": ["available", "pending", "sold"]
+ }
+ },
+ "xml": {
+ "name": "Pet"
+ }
+ }
+ }
+ },
+ "externalDocs": {
+ "description": "Find out more about Swagger",
+ "url": "http://swagger.io"
+ }
+}
diff --git a/kong-versions/3.9.0.0/kong/spec/fixtures/mocking/openApi3.yaml b/kong-versions/3.9.0.0/kong/spec/fixtures/mocking/openApi3.yaml
new file mode 100644
index 00000000..f5089c6e
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/fixtures/mocking/openApi3.yaml
@@ -0,0 +1,1045 @@
+openapi: 3.0.0
+# Added by API Auto Mocking Plugin
+servers:
+ - description: SwaggerHub API Auto Mocking
+ url: https://virtserver.swaggerhub.com/rosireddy2020/CUOOrder/1.0.0
+info:
+ description: This is a simple API
+ version: "1.0.0"
+ title: CUO_Order
+ contact:
+ email: you@your-company.com
+ license:
+ name: Apache 2.0
+ url: 'http://www.apache.org/licenses/LICENSE-2.0.html'
+tags:
+
+ - name: login
+ description: order login api
+ - name: user
+ description: login user api
+ - name: location
+ description: Location API for eCUo orders
+ - name: orderEntry
+ description: order entry/editing APi for eCUO orders
+ - name: standingorder
+ description: Standing orders view and Activation for eCUO orders
+ - name: commitedAmounts
+ description: Commited amount Api for eCUO orders
+ - name: pickList
+ description: PickList Api for eCUO orders
+ - name: orderprint
+ description: Orderprint Api for eCUO orders
+ - name: manifest
+ description: Manifest Api for eCUO orders
+paths:
+ /login:
+ post:
+ tags:
+ - login
+ summary: find user is valid or not
+ operationId: login
+ requestBody:
+ description: login input deatails
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/LoginRequest'
+ required: true
+
+ responses:
+ '204':
+ description: login user is valid
+ '400':
+ description: Invalid login user name
+ /adLogin:
+ post:
+ tags:
+ - login
+ summary: find ad user is valid or not
+ operationId: adLogin
+ requestBody:
+ description: Ad login input deatails
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/LoginRequest'
+ required: true
+
+ responses:
+ '204':
+ description: Ad name is valid
+ '400':
+ description: Invalid Ad name
+ /locations:
+ post:
+ tags:
+ - location
+ summary: find all locations by login details
+ operationId: getLocationsForOrders
+ requestBody:
+ description: Input details for locations
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/EcuoLoginBean'
+ required: true
+
+ responses:
+ "200":
+ description: Location deatails featched successfully
+ content:
+ application/json:
+ schema:
+ type: array
+ items:
+ $ref: '#/components/schemas/LocationEnqResponseBean'
+ '412':
+ description: Invalid Input
+ /location:
+ post:
+ tags:
+ - location
+ summary: find New Order confiuration deatils by location
+ operationId: validateLocation
+ requestBody:
+ description: Input Valid location details
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/EcuoLoginBean'
+ required: true
+
+ responses:
+ "200":
+ description: New order details featched successfully
+ content:
+ application/json:
+ schema:
+ type: array
+ items:
+ $ref: '#/components/schemas/CuoorderLocationDetailResponse'
+ '412':
+ description: Invalid location details
+ /cuoorder:
+ post:
+ tags:
+ - orderEntry
+ summary: creating order
+ operationId: createOrder
+ requestBody:
+ description: enter valid order details
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/NewOrderEntryBean'
+ responses:
+ "200":
+ description: Order create successfully.
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/AddOrderResponse'
+ "400":
+ description: Invalid Input
+ "404":
+ description: Page not found
+
+ put:
+ tags:
+ - orderEntry
+ summary: update order
+ operationId: updateOrder
+ requestBody:
+ description: enter valid order details
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/UpdateOrderRequest'
+ responses:
+ "200":
+ description: Order create successfully.
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/AddOrderResponse'
+ "400":
+ description: Invalid Input
+ "404":
+ description: Page not found
+ /cuoorder/delorder:
+ post:
+ tags:
+ - orderEntry
+ summary: Cancel order
+ operationId: cancelOrder
+ requestBody:
+ description: enter valid order info
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/CancelOrderRequest'
+ responses:
+ "200":
+ description: Order Canceled
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/CancelOrderResponse'
+ "400":
+ description: Invalid Input
+ "404":
+ description: Page not found
+ /cuoorder/orderstatus:
+ post:
+ tags:
+ - orderEntry
+ summary: order subtypes
+ operationId: findOrdersWithStatus
+ requestBody:
+ description: enter valid order info
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/FindOrderBean'
+ responses:
+ "200":
+ description: order subtypes featched successfully
+ content:
+ application/json:
+ schema:
+ type: array
+ items:
+ $ref: '#/components/schemas/IBrowseElement'
+ "400":
+ description: Invalid Input
+ "404":
+ description: Page not found
+ /cuoorder/subtypes:
+ post:
+ tags:
+ - orderEntry
+ summary: find order subtypes
+ operationId: findOrderSubtypes
+ requestBody:
+ description: enter valid order info
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/FindOrderBean'
+ responses:
+ "200":
+ description: Order Canceled
+ content:
+ application/json:
+ schema:
+ type: array
+ items:
+ $ref: '#/components/schemas/IBrowseElement'
+ "400":
+ description: Invalid Input
+ "404":
+ description: Page not found
+ /standingOrder/view:
+ post:
+ tags:
+ - standingorder
+ summary: find standing orders
+ operationId: viewStandingOrders
+ requestBody:
+ description: enter valid standing orders by given input
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ViewStdOrderBean'
+ responses:
+ "200":
+ description: Standing orders featched successfully
+ content:
+ application/json:
+ schema:
+ type: array
+ items:
+ $ref: '#/components/schemas/StandingOrderBean'
+ "400":
+ description: Invalid Input
+ "404":
+ description: Page not found
+ /standingOrder/activate:
+ post:
+ tags:
+ - standingorder
+ summary: Activating standing orders
+ operationId: activateStdOrder
+ requestBody:
+ description: Activating standing orders
+ required: true
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/StandingOrderBean'
+ parameters:
+ - name: siteno
+ in: query
+ schema:
+ type: integer
+ - name: systemName
+ in: header
+ schema:
+ type: string
+
+ responses:
+ "200":
+ description: Standing orders featched successfully
+ content:
+ application/json:
+ schema:
+ type: array
+ items:
+ $ref: '#/components/schemas/StandingOrderBean'
+ "400":
+ description: Invalid Input
+ "404":
+ description: Page not found
+ /commitedAmounts/view:
+ post:
+ tags:
+ - commitedAmounts
+ summary: find Commited Amount records
+ operationId: viewReport
+ requestBody:
+ description: Input valid date, ordertypes and debitsiteno
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/CommitedAmountsRequest'
+ required: true
+
+ responses:
+ "200":
+ description: Commited Amount records featched successfully
+ content:
+ application/pdf:
+ schema:
+ type: string
+ format: byte
+ '412':
+ description: Invalid Commited Amount input
+ /picklist/view:
+ post:
+ tags:
+ - pickList
+ summary: view or print Picklist records
+ operationId: viewreport
+ requestBody:
+ description: Input valid date, ordertypes and debitsiteno
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/PickListParamsBean'
+ required: true
+
+ responses:
+ "200":
+ description: PickList records featched successfully
+ content:
+ application/pdf:
+ schema:
+ type: string
+ format: byte
+ '412':
+ description: Invalid Picklist input
+ /manifest/view:
+ post:
+ tags:
+ - manifest
+ summary: view or print Manifest records
+ operationId: viewREport
+ requestBody:
+ description: Input valid date, ordertypes and debitsiteno
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ManifestReportRequest'
+ required: true
+
+ responses:
+ "200":
+ description: Manifest records featched successfully
+ content:
+ application/pdf:
+ schema:
+ type: string
+ format: byte
+ '412':
+ description: Invalid Picklist input
+ /orderprint/view:
+ post:
+ tags:
+ - orderprint
+ summary: view or print OrderPrint records
+ operationId: viewReports
+ requestBody:
+ description: Input valid date, ordertypes and debitsiteno
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/OrderPrintReportRequest'
+ required: true
+
+ responses:
+ "200":
+ description: Manifest records featched successfully
+ content:
+ application/pdf:
+ schema:
+ type: string
+ format: byte
+ '412':
+ description: Invalid Picklist input
+ /user/{userid}:
+ get:
+ tags:
+ - user
+ summary: find login user detail like alternate gloryid
+ operationId: findUser
+ parameters:
+ - in: path
+ name: userid
+ schema:
+ type: integer
+ required: true
+ description: Numeric ID of the user to get
+ responses:
+ "201":
+ description: Envelop records featched successfully
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/UserModel'
+ "400":
+ description: Invalid Input
+ "404":
+ description: Page not found
+
+
+components:
+ schemas:
+ LoginRequest:
+ type: object
+ properties:
+ stationName:
+ type: number
+ format: long
+ adName:
+ type: string
+ userId:
+ type: string
+ password:
+ type: string
+ UserModel:
+ type: object
+ properties:
+ gloryid:
+ type: string
+ name:
+ type: string
+ title:
+ type: string
+ expireDate:
+ type: string
+ lockStatus:
+ type: integer
+ retryCount:
+ type: integer
+ overShort:
+ type: number
+ format: double
+ siteno:
+ type: integer
+ autoSellBuy:
+ type: integer
+ invGroupNo:
+ type: integer
+ rotateFlg:
+ type: integer
+ glId:
+ type: string
+ modifyDate:
+ type: string
+ modifyTime:
+ type: string
+ modifier:
+ type: string
+ deleteFlg:
+ type: string
+ shift:
+ type: string
+ bankId:
+ type: string
+ altUsers:
+ type: array
+ items:
+ $ref: '#/components/schemas/UsersAltIdModel'
+ clientList:
+ type: array
+ items:
+ $ref: '#/components/schemas/ClientSet'
+ groups:
+ type: array
+ items:
+ $ref: '#/components/schemas/GroupsModel'
+ adName:
+ type: string
+ employeeId:
+ type: string
+ reSellGId:
+ type: string
+ buyGId:
+ type: string
+ sellQuality:
+ type: string
+ buysiteno:
+ type: integer
+ eodinv:
+ type: integer
+ creditDateChngCtrl:
+ type: integer
+ fedBuySellCtrl:
+ type: integer
+ invAdjCtrl:
+ type: integer
+ reCountCtrl:
+ type: integer
+ sellManifest:
+ type: integer
+ invverifyReq:
+ type: integer
+ sysAltId:
+ type: integer
+ sysAltSupervisor:
+ type: integer
+ sellMfstLoc:
+ type: string
+ sellMfstAddr:
+ type: string
+ # shift:
+ # type: array
+ # items:
+ # $ref: '#/components/schemas/ShiftModel'
+ menuSecurity:
+ type: array
+ items:
+ $ref: '#/components/schemas/MenuView'
+ clientno:
+ type: integer
+ # name:
+ # type: string
+ MenuView:
+ type: object
+ properties:
+ privilege:
+ type: integer
+ nodeno:
+ type: integer
+ itemno:
+ type: integer
+ name:
+ type: string
+ module:
+ type: string
+ param:
+ type: string
+ nextnode:
+ type: integer
+ dualcustody:
+ type: integer
+ moduletype:
+ type: integer
+ deleteflg:
+ type: string
+ address:
+ type: string
+ ShiftModel:
+ type: object
+ properties:
+ sun:
+ type: integer
+ mon:
+ type: integer
+ tue:
+ type: integer
+ wed:
+ type: integer
+ thu:
+ type: integer
+ fri:
+ type: integer
+ sat:
+ type: integer
+ GroupsModel:
+ type: object
+ properties:
+ groupID:
+ type: string
+ name:
+ type: string
+ glid:
+ type: string
+ privilege:
+ type: integer
+ deleteFLG:
+ type: string
+ overShort:
+ type: number
+ format: double
+ icom:
+ type: integer
+ UsersAltIdModel:
+ type: object
+ properties:
+ gloryId:
+ type: string
+ altGloryId:
+ type: string
+ sysAltId:
+ type: string
+ altGloryIdName:
+ type: string
+ ClientSet:
+ type: object
+ properties:
+ clientno:
+ type: integer
+ name:
+ type: string
+ EcuoLoginBean:
+ type: object
+ properties:
+ siteno:
+ type: integer
+ clientno:
+ type: integer
+ loginUserId:
+ type: integer
+ loginUserName:
+ type: integer
+
+ LocationEnqResponseBean:
+ type: object
+ properties:
+ response:
+ $ref: '#/components/schemas/CommonResponseBean'
+ locList:
+ type: array
+ items:
+ $ref: '#/components/schemas/IBrowseElement'
+ ValidateLocationRequest:
+ type: object
+ properties:
+ siteno:
+ type: integer
+ clientno:
+ type: integer
+ cuoid:
+ type: number
+ format: long
+ locationid:
+ type: string
+ locname:
+ type: string
+ CuoorderLocationDetailResponse:
+ type: object
+ properties:
+ response:
+ $ref: '#/components/schemas/CommonResponseBean'
+ neworderentbean:
+ $ref: '#/components/schemas/NewOrderEntryBean'
+
+ AddOrderResponse:
+ type: object
+ NewOrderEntryBean:
+ type: object
+ properties:
+ siteno:
+ type: integer
+ clientno:
+ type: integer
+ locationid:
+ type: number
+ format: long
+ orderid:
+ type: number
+ format: long
+ previd:
+ type: number
+ format: long
+ orderdate:
+ type: string
+ format: date
+ ordertime:
+ type: string
+ format: date
+ orderby:
+ type: string
+ gtotal:
+ type: number
+ format: long
+ mediacount:
+ type: integer
+ shipdate:
+ type: string
+ deliverydate:
+ type: string
+ routeid:
+ type: integer
+ courierid:
+ type: integer
+ firstshipdate:
+ type: string
+ format: date
+ manifestdate:
+ type: string
+ format: date
+ canceldate:
+ type: string
+ format: date
+ cancelby:
+ type: string
+ entrytype:
+ type: string
+ orOrdersubtypeid:
+ type: integer
+ passthruLong:
+ type: number
+ format: long
+ cashadd:
+ type: integer
+ status:
+ type: string
+ accountno:
+ type: string
+ rtno:
+ type: string
+ acctlocid:
+ type: string
+ memo:
+ type: string
+ minOrderAmount:
+ type: number
+ format: long
+ maxOrderAmount:
+ type: number
+ format: long
+ shpWks:
+ type: array
+ items:
+ type: integer
+ deliWks:
+ type: array
+ items:
+ type: integer
+ shpHolidaysList:
+ type: array
+ items:
+ type: string
+ format: date
+ deliHolidaysList:
+ type: array
+ items:
+ type: string
+ format: date
+ supervisor:
+ type: string
+ UpdateOrderRequest:
+ type: object
+ properties:
+ orderid:
+ type: number
+ format: long
+ subType:
+ type: integer
+ memo:
+ type: string
+ cashAdd:
+ type: integer
+ clientno:
+ type: integer
+ siteno:
+ type: integer
+ cuoid:
+ type: number
+ format: long
+ updatedDate:
+ type: string
+ format: date
+ userId:
+ type: string
+ userName:
+ type: string
+ CancelOrderRequest:
+ type: object
+ properties:
+ siteno:
+ type: integer
+ clientno:
+ type: integer
+ orderid:
+ type: number
+ format: long
+ cuoid:
+ type: number
+ format: long
+ cancelDate:
+ type: string
+ format: date
+ cancelBy:
+ type: string
+ CancelOrderResponse:
+ type: object
+ FindOrderBean:
+ type: object
+ properties:
+ siteno:
+ type: integer
+ clientno:
+ type: integer
+ cuoid:
+ type: number
+ format: long
+ clientLocId:
+ type: string
+ ordeno:
+ type: number
+ format: long
+ GetOrderResponse:
+ type: object
+ IBrowseElement:
+ type: object
+ properties:
+ id:
+ type: number
+ format: long
+ name:
+ type: string
+ key:
+ type: string
+ StandingOrderBean:
+ type: object
+ properties:
+ maxShipdate:
+ type: string
+ clientno:
+ type: integer
+ siteno:
+ type: integer
+ orderamount:
+ type: number
+ format: long
+ mediacount:
+ type: number
+ format: long
+ stdorderno:
+ type: integer
+ locationid:
+ type: string
+ accountno:
+ type: string
+ rtno:
+ type: string
+ cuoid:
+ type: number
+ format: long
+ nextdelidate:
+ type: string
+ format: date
+ deliverydays:
+ type: integer
+ prepardays:
+ type: integer
+ delileaddays:
+ type: integer
+ ordprepdays:
+ type: integer
+ delivleaddays:
+ type: integer
+ workdaysC:
+ type: integer
+ shiproute:
+ type: integer
+ courierid:
+ type: string
+ wklyinterval:
+ type: integer
+ shipdate:
+ type: string
+ format: date
+ deliverydate:
+ type: string
+ format: date
+ orderby:
+ type: string
+ siteZoneId:
+ type: string
+ ViewStdOrderBean:
+ type: object
+ properties:
+ siteno:
+ type: integer
+ clientno:
+ type: integer
+ stdOrdDate:
+ type: string
+ format: date
+ groupid:
+ type: integer
+ siteZoneId:
+ type: string
+ CommonResponseBean:
+ type: object
+ properties:
+ responseMessage:
+ type: string
+ responseCode:
+ type: string
+ responseDetailMessage:
+ type: string
+ processCount:
+ type: string
+ versionNo:
+ type: string
+ timestamp:
+ type: string
+ format: timestamp
+ CommitedAmountsRequest:
+ type: object
+ properties:
+ fromDate:
+ type: string
+ toDate:
+ type: string
+ debitSites:
+ type: array
+ items:
+ type: integer
+ ordertypes:
+ type: array
+ items:
+ type: integer
+ funcType:
+ type: integer
+ clientNo:
+ type: integer
+ siteNo:
+ type: integer
+ clientName:
+ type: string
+ PickListParamsBean:
+ type: object
+ properties:
+ fromDate:
+ type: string
+ toDate:
+ type: string
+ clientNo:
+ type: integer
+ siteNo:
+ type: integer
+ clientName:
+ type: string
+ entryTypes:
+ type: array
+ items:
+ type: integer
+ couriers:
+ type: array
+ items:
+ $ref: '#/components/schemas/IBrowseElement'
+ funcType:
+ type: integer
+ totalsOnly:
+ type: boolean
+ ManifestReportRequest:
+ type: object
+ properties:
+ fromDate:
+ type: string
+ toDate:
+ type: string
+ clientNo:
+ type: integer
+ siteNo:
+ type: integer
+ clientName:
+ type: string
+ couriers:
+ type: array
+ items:
+ $ref: '#/components/schemas/IBrowseElement'
+ deliveryDateSorting:
+ type: boolean
+ isrouteDetail:
+ type: boolean
+ useLocationId:
+ type: boolean
+ pageTotals:
+ type: boolean
+ printShipped:
+ type: boolean
+ rePrintManifested:
+ type: boolean
+ orderMediaType:
+ type: boolean
+ orderStatusType:
+ type: boolean
+ orderUpdateToManifestSts:
+ type: boolean
+ orderCurrUpdateSts:
+ type: boolean
+ orderCoinUpdateSts:
+ type: boolean
+ OrderPrintReportRequest:
+ type: object
+ properties:
+ fromDate:
+ type: string
+ toDate:
+ type: string
+ debitSites:
+ type: array
+ items:
+ type: integer
+ couriers:
+ type: array
+ items:
+ $ref: '#/components/schemas/IBrowseElement'
+ ordertypes:
+ type: array
+ items:
+ type: integer
+ clientNo:
+ type: integer
+ siteNo:
+ type: integer
+ toOrder:
+ type: string
+ fromOrder:
+ type: string
+ iscurrLabel:
+ type: boolean
+ iscoinLabel:
+ type: boolean
+ isshippingLabel:
+ type: boolean
+ isreturnLabel:
+ type: boolean
+ isprintNew:
+ type: boolean
+ isrePrintShipped:
+ type: boolean
+ isorderPickList:
+ type: boolean
+ istotalsOnly:
+ type: boolean
+ isupdateSts:
+ type: boolean
diff --git a/kong-versions/3.9.0.0/kong/spec/fixtures/mocking/openapi.json b/kong-versions/3.9.0.0/kong/spec/fixtures/mocking/openapi.json
new file mode 100644
index 00000000..142821b8
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/fixtures/mocking/openapi.json
@@ -0,0 +1,167 @@
+{
+ "openapi": "3.0.0",
+ "info": {
+ "title": "Simple API overview",
+ "version": "2.0.0"
+ },
+ "paths": {
+ "/": {
+ "get": {
+ "operationId": "listVersionsv2",
+ "summary": "List API versions",
+ "responses": {
+ "200": {
+ "description": "200 response",
+ "content": {
+ "application/json": {
+ "examples": {
+ "foo": {
+ "value": {
+ "versions": [
+ {
+ "status": "CURRENT",
+ "updated": "2011-01-21T11:33:21Z",
+ "id": "v2.0",
+ "links": [
+ {
+ "href": "http://127.0.0.1:8774/v2/",
+ "rel": "self"
+ }
+ ]
+ },
+ {
+ "status": "EXPERIMENTAL",
+ "updated": "2013-07-23T11:33:21Z",
+ "id": "v3.0",
+ "links": [
+ {
+ "href": "http://127.0.0.1:8774/v3/",
+ "rel": "self"
+ }
+ ]
+ }
+ ]
+ }
+ }
+ }
+ }
+ }
+ },
+ "300": {
+ "description": "300 response",
+ "content": {
+ "application/json": {
+ "examples": {
+ "foo": {
+ "value": "{\n \"versions\": [\n {\n \"status\": \"CURRENT\",\n \"updated\": \"2011-01-21T11:33:21Z\",\n \"id\": \"v2.0\",\n \"links\": [\n {\n \"href\": \"http://127.0.0.1:8774/v2/\",\n \"rel\": \"self\"\n }\n ]\n },\n {\n \"status\": \"EXPERIMENTAL\",\n \"updated\": \"2013-07-23T11:33:21Z\",\n \"id\": \"v3.0\",\n \"links\": [\n {\n \"href\": \"http://127.0.0.1:8774/v3/\",\n \"rel\": \"self\"\n }\n ]\n }\n ]\n}\n"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "/v2": {
+ "get": {
+ "operationId": "getVersionDetailsv2",
+ "summary": "Show API version details",
+ "responses": {
+ "200": {
+ "description": "200 response",
+ "content": {
+ "application/json": {
+ "examples": {
+ "foo": {
+ "value": {
+ "version": {
+ "status": "CURRENT",
+ "updated": "2011-01-21T11:33:21Z",
+ "media-types": [
+ {
+ "base": "application/xml",
+ "type": "application/vnd.openstack.compute+xml;version=2"
+ },
+ {
+ "base": "application/json",
+ "type": "application/vnd.openstack.compute+json;version=2"
+ }
+ ],
+ "id": "v2.0",
+ "links": [
+ {
+ "href": "http://127.0.0.1:8774/v2/",
+ "rel": "self"
+ },
+ {
+ "href": "http://docs.openstack.org/api/openstack-compute/2/os-compute-devguide-2.pdf",
+ "type": "application/pdf",
+ "rel": "describedby"
+ },
+ {
+ "href": "http://docs.openstack.org/api/openstack-compute/2/wadl/os-compute-2.wadl",
+ "type": "application/vnd.sun.wadl+xml",
+ "rel": "describedby"
+ },
+ {
+ "href": "http://docs.openstack.org/api/openstack-compute/2/wadl/os-compute-2.wadl",
+ "type": "application/vnd.sun.wadl+xml",
+ "rel": "describedby"
+ }
+ ]
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "203": {
+ "description": "203 response",
+ "content": {
+ "application/json": {
+ "examples": {
+ "foo": {
+ "value": {
+ "version": {
+ "status": "CURRENT",
+ "updated": "2011-01-21T11:33:21Z",
+ "media-types": [
+ {
+ "base": "application/xml",
+ "type": "application/vnd.openstack.compute+xml;version=2"
+ },
+ {
+ "base": "application/json",
+ "type": "application/vnd.openstack.compute+json;version=2"
+ }
+ ],
+ "id": "v2.0",
+ "links": [
+ {
+ "href": "http://23.253.228.211:8774/v2/",
+ "rel": "self"
+ },
+ {
+ "href": "http://docs.openstack.org/api/openstack-compute/2/os-compute-devguide-2.pdf",
+ "type": "application/pdf",
+ "rel": "describedby"
+ },
+ {
+ "href": "http://docs.openstack.org/api/openstack-compute/2/wadl/os-compute-2.wadl",
+ "type": "application/vnd.sun.wadl+xml",
+ "rel": "describedby"
+ }
+ ]
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
\ No newline at end of file
diff --git a/kong-versions/3.9.0.0/kong/spec/fixtures/mocking/openapi_2.json b/kong-versions/3.9.0.0/kong/spec/fixtures/mocking/openapi_2.json
new file mode 100644
index 00000000..8b4f8deb
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/fixtures/mocking/openapi_2.json
@@ -0,0 +1,291 @@
+{
+ "swagger": "2.0",
+ "info": {
+ "title": "Simple Inventory API",
+ "description": "This is a simple API",
+ "version": "1.0.0",
+ "contact": {
+ "email": "example@example.com"
+ }
+ },
+ "host": "api.example.com",
+ "basePath": "/v1",
+ "schemes": [
+ "http",
+ "https"
+ ],
+ "paths": {
+ "/inventory": {
+ "get": {
+ "summary": "searches inventory",
+ "operationId": "searchInventory",
+ "description": "By passing in the appropriate options, you can search for available inventory in the system",
+ "produces": [
+ "application/json",
+ "application/xml",
+ "text/plain",
+ "text/html"
+ ],
+ "parameters": [
+ {
+ "in": "query",
+ "name": "searchString",
+ "description": "pass an optional search string for looking up inventory",
+ "required": false,
+ "type": "string"
+ },
+ {
+ "in": "query",
+ "name": "skip",
+ "description": "number of records to skip for pagination",
+ "type": "integer",
+ "format": "int32",
+ "minimum": 0
+ },
+ {
+ "in": "query",
+ "name": "limit",
+ "description": "maximum number of records to return",
+ "type": "integer",
+ "format": "int32",
+ "minimum": 0,
+ "maximum": 50
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "bad input parameter",
+ "examples": {
+ "text/html": "
+ application/xml:
+ example: AliceBob
+ post:
+ summary: adds an inventory item
+ description: Adds an item to the system
+ operationId: addInventory
+ requestBody:
+ description: Inventory item to add
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/InventoryItem'
+ required: false
+ responses:
+ 201:
+ description: item created
+ content: {}
+ 400:
+ description: invalid input, object invalid
+ content: {}
+ 409:
+ description: an existing item already exists
+ content: {}
+ x-codegen-request-body-name: inventoryItem
+ /inventory.v2:
+ get:
+ summary: searches inventory
+ operationId: searchInventoryV2
+ responses:
+ 200:
+ description: bad input parameter
+ content:
+ application/json:
+ example:
+ id: d290f1ee-6c54-4b01-90e6-d701748f0851
+
+
+ /inventory_empty_responses:
+ get:
+ responses: {}
+
+ /inventory_without_content:
+ get:
+ responses:
+ '200':
+ description: success
+
+ /inventory_empty_content:
+ get:
+ responses:
+ '200':
+ description: success
+ content: {}
+
+ /inventory_empty_content_examples:
+ get:
+ responses:
+ '200':
+ description: success
+ content:
+ application/json:
+ examples: {}
+
+ /ref/inventory_ref_schema:
+ get:
+ responses:
+ '200':
+ description: 'success'
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/GetInventoryItemResponse'
+
+ /ref/inventory_ref_response:
+ get:
+ responses:
+ '400':
+ $ref: '#/components/responses/InvalidRequestResponse'
+
+ /ping-with-one-default-response:
+ get:
+ responses:
+ default:
+ description: default response
+ content:
+ application/json:
+ example:
+ msg: pong
+
+ /ping-with-multiple-response:
+ get:
+ responses:
+ 200:
+ description: OK
+ content:
+ application/json:
+ example:
+ msg: pong
+ 400:
+ description: OK
+ content:
+ application/json:
+ example:
+ msg: invalid request
+ 5XX:
+ description: error
+ content:
+ application/json:
+ example:
+ msg: gateway timeout
+ default:
+ description: default response
+ content:
+ application/json:
+ example:
+ msg: unknow error
+
+components:
+ responses:
+ InvalidRequestResponse:
+ description: '400'
+ content:
+ application/json:
+ example:
+ code: "INVALID_REQUEST"
+ msg: "Invalid Request"
+ schemas:
+ APIResponse:
+ type: object
+ properties:
+ code:
+ type: string
+ msg:
+ type: string
+ GetInventoryItemResponse:
+ allOf:
+ - $ref: '#/components/schemas/APIResponse'
+ - type: object
+ properties:
+ data:
+ $ref: '#/components/schemas/InventoryItem'
+ InventoryItem:
+ required:
+ - id
+ - manufacturer
+ - name
+ - releaseDate
+ type: object
+ properties:
+ id:
+ type: string
+ format: uuid
+ example: d290f1ee-6c54-4b01-90e6-d701748f0851
+ name:
+ type: string
+ example: Doge111
+ releaseDate:
+ type: string
+ format: date-time
+ example: 2016-08-29T09:12:33.001Z
+ manufacturer:
+ $ref: '#/components/schemas/Manufacturer'
+ Manufacturer:
+ required:
+ - name
+ type: object
+ properties:
+ name:
+ type: string
+ example: ACME Corporation
+ homePage:
+ type: string
+ format: url
+ example: https://www.acme-corp.com
+ phone:
+ type: string
+ example: 408-867-5309
diff --git a/kong-versions/3.9.0.0/kong/spec/fixtures/mocking/path-match-oas.yaml b/kong-versions/3.9.0.0/kong/spec/fixtures/mocking/path-match-oas.yaml
new file mode 100644
index 00000000..bbc72a62
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/fixtures/mocking/path-match-oas.yaml
@@ -0,0 +1,63 @@
+openapi: "3.0.0"
+info:
+ title: Sample API
+ description: A Sample OpenAPI Spec
+ version: 1.0.0
+
+servers:
+ - url: "/v1"
+
+paths:
+ /user/{username}:
+ get:
+ summary: Get user by user name
+ description: ''
+ operationId: getUserByName
+ parameters:
+ - name: username
+ in: path
+ description: 'The name that needs to be fetched. Use user1 for testing. '
+ required: true
+ schema:
+ type: string
+ responses:
+ '200':
+ description: successful operation
+ '400':
+ description: Invalid username supplied
+ '404':
+ description: User not found
+ /user/{username}/report.{format}:
+ get:
+ parameters:
+ - name: username
+ in: path
+ description: 'The name that needs to be fetched. Use user1 for testing. '
+ required: true
+ schema:
+ type: string
+ - in: path
+ name: format
+ required: true
+ description: The user to create.
+ schema:
+ type: string
+ enum:
+ - pdf
+ - txt
+ - word
+ responses:
+ 201:
+ description: Created
+ /user/{username}.pdf:
+ get:
+ parameters:
+ - name: username
+ in: path
+ description: 'The name that needs to be fetched. Use user1 for testing. '
+ required: true
+ schema:
+ type: string
+ responses:
+ 201:
+ description: Created
diff --git a/kong-versions/3.9.0.0/kong/spec/fixtures/mocking/reference-oas.yaml b/kong-versions/3.9.0.0/kong/spec/fixtures/mocking/reference-oas.yaml
new file mode 100644
index 00000000..42d04fc9
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/fixtures/mocking/reference-oas.yaml
@@ -0,0 +1,132 @@
+openapi: 3.0.1
+info:
+ title: Sample API
+ description: A Sample OpenAPI Spec
+ version: 1.0.0
+
+paths:
+ /ref-case-1:
+ post:
+ responses:
+ 200:
+ description: OK
+ content:
+ 'application/json':
+ schema:
+ $ref: '#/components/schemas/Simple'
+ /ref-case-2:
+ post:
+ responses:
+ 200:
+ description: OK
+ content:
+ 'application/json':
+ schema:
+ type: array
+ items:
+ $ref: '#/components/schemas/Simple'
+ minItems: 2
+ maxItems: 2
+ /ref-case-3:
+ post:
+ responses:
+ '200':
+ description: OK
+ content:
+ 'application/json':
+ schema:
+ type: object
+ properties:
+ key_integer:
+ type: integer
+ key_boolean:
+ type: boolean
+ simple:
+ $ref: '#/components/schemas/Simple'
+
+ /recursive-ref-case-1:
+ post:
+ responses:
+ '200':
+ description: OK
+ content:
+ 'application/json':
+ schema:
+ $ref: '#/components/schemas/Node'
+ /recursive-ref-case-2:
+ post:
+ responses:
+ '200':
+ description: OK
+ content:
+ 'application/json':
+ schema:
+ $ref: '#/components/schemas/ComparedTcmAgreementsDto'
+
+ /recursive-ref-case-3:
+ post:
+ responses:
+ '200':
+ description: OK
+ content:
+ 'application/json':
+ schema:
+ type: array
+ items:
+ $ref: '#/components/schemas/Customer'
+ minItems: 1
+ maxItems: 1
+
+components:
+ schemas:
+ Simple:
+ type: object
+ properties:
+ key_string:
+ type: string
+ Node:
+ type: object
+ properties:
+ value:
+ type: string
+ node:
+ $ref: '#/components/schemas/Node'
+ ComparedTcmAgreementsDto:
+ type: object
+ properties:
+ differentFields:
+ type: array
+ items:
+ type: string
+ securityEligibilityRules:
+ $ref: '#/components/schemas/ConstraintTree'
+ ConstraintTree:
+ type: object
+ properties:
+ constraint:
+ type: string
+ leaves:
+ type: array
+ items:
+ $ref: '#/components/schemas/ConstraintTree'
+ operation:
+ type: string
+ enum:
+ - IS
+ - AND
+ - OR
+ Customer:
+ type: object
+ properties:
+ title:
+ type: string
+ profile:
+ $ref: '#/components/schemas/Profile'
+ Profile:
+ type: object
+ properties:
+ customer:
+ $ref: '#/components/schemas/Customer'
+ createdDate:
+ type: string
+ format: date-time
diff --git a/kong-versions/3.9.0.0/kong/spec/fixtures/mocking/stock.json b/kong-versions/3.9.0.0/kong/spec/fixtures/mocking/stock.json
new file mode 100644
index 00000000..60391e1d
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/fixtures/mocking/stock.json
@@ -0,0 +1,161 @@
+{"swagger": "2.0",
+ "info" : {
+ "title": "Stock API",
+ "description": "Stock Information Service",
+ "version": "0.1"
+ },
+ "host": "apistore.kong.com:8000",
+ "basePath": "/",
+ "schemes": [
+ "http",
+ "https"
+ ],
+ "consumes": [
+ "application/json"
+ ],
+ "produces": [
+ "application/json"
+ ],
+ "paths": {
+ "/stock/historical": {
+ "get": {
+ "description": "",
+ "operationId": "GET /stock/historical",
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "Production"
+ ],
+ "parameters": [
+ {
+ "required": true,
+ "in": "query",
+ "name": "tickers",
+ "type": "string"
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "Status 200",
+ "examples": {
+ "application/json":
+ {
+ "meta_data" : {
+ "api_name" : "historical_stock_price_v2",
+ "num_total_data_points" : 1,
+ "credit_cost" : 10,
+ "start_date" : "yesterday",
+ "end_date" : "yesterday"
+ },
+ "result_data" : {
+ "AAPL" : [ {
+ "date" : "2000-04-23",
+ "volume" : 33,
+ "high" : 100.75,
+ "low" : 100.87,
+ "adj_close" : 275.03,
+ "close" : 100.03,
+ "open" : 100.87
+ } ]
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "/stock/closing": {
+ "get": {
+ "description": "",
+ "operationId": "GET /stock/closing",
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "Beta"
+ ],
+ "parameters": [
+ {
+ "required": true,
+ "in": "query",
+ "name": "tickers",
+ "type": "string"
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "Status 200",
+ "examples": {
+ "application/json":
+ {
+ "meta_data" : {
+ "api_name" : "closing_stock_price_v1"
+ },
+ "result_data" : {
+ "AAPL" : [ {
+ "date" : "2000-06-23",
+ "volume" : 33,
+ "high" : 100.75,
+ "low" : 100.87,
+ "adj_close" : 275.03,
+ "close" : 100.03,
+ "open" : 100.87
+ } ]
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "/stock-historical.v3": {
+ "get": {
+ "description": "",
+ "operationId": "GET /stock-historical.v3",
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "Production"
+ ],
+ "parameters": [
+ {
+ "required": true,
+ "in": "query",
+ "name": "tickers",
+ "type": "string"
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "Status 200",
+ "examples": {
+ "application/json":
+ {
+ "meta_data" : {
+ "api_name" : "historical_stock_price_v3",
+ "num_total_data_points" : 1,
+ "credit_cost" : 10,
+ "start_date" : "yesterday",
+ "end_date" : "yesterday"
+ },
+ "result_data" : {
+ "AAPL" : [ {
+ "date" : "2000-04-23",
+ "volume" : 33,
+ "high" : 100.75,
+ "low" : 100.87,
+ "adj_close" : 275.03,
+ "close" : 100.03,
+ "open" : 100.87
+ } ]
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/kong-versions/3.9.0.0/kong/spec/fixtures/mocking/stock_500.yaml b/kong-versions/3.9.0.0/kong/spec/fixtures/mocking/stock_500.yaml
new file mode 100644
index 00000000..16346669
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/fixtures/mocking/stock_500.yaml
@@ -0,0 +1,84 @@
+openapi: 3.0.2
+info:
+ title: Stock API
+ description: Stock Information Service
+ version: "1.0"
+paths:
+ /stock/historical:
+ get:
+ description: ""
+ operationId: GET /stock/historical
+ tags:
+ - Production
+ parameters:
+ - required: true
+ in: query
+ name: tickers
+ schema:
+ type: string
+ responses:
+ "200":
+ description: Status 200
+ content:
+ application/json:
+ examples:
+ response:
+ value:
+ meta_data:
+ api_name: historical_stock_price_v2
+ num_total_data_points: 1
+ credit_cost: 10
+ start_date: yesterday
+ end_date: yesterday
+ result_data:
+ AAPL:
+ - date: 2000-04-23
+ volume: 33
+ high: 100.75
+ low: 100.87
+ adj_close: 275.03
+ close: 100.03
+ open: 100.87
+ /stock/closing:
+ get:
+ description: ""
+ operationId: GET /stock/closing
+ tags:
+ - Beta
+ parameters:
+ - required: true
+ in: query
+ name: tickers
+ schema:
+ type: string
+ responses:
+ "200":
+ description: Status 200
+ content:
+ application/json:
+ examples:
+ response:
+ value:
+ meta_data:
+ api_name: closing_stock_price_v1
+ result_data:
+ AAPL:
+ - date: 2000-06-23
+ volume: 33
+ high: 100.75
+ low: 100.87
+ adj_close: 275.03
+ close: 100.03
+ open: 100.87
+ /stock/delete:
+ delete:
+ description: ""
+ operationId: DELETE /stock/historical
+ tags:
+ - Production
+ responses:
+ "204":
+ description: delete success
+servers:
+ - url: http://localhost:8000/
+ - url: https://localhost:8443/
diff --git a/kong-versions/3.9.0.0/kong/spec/fixtures/mocking/users.yaml b/kong-versions/3.9.0.0/kong/spec/fixtures/mocking/users.yaml
new file mode 100644
index 00000000..6c1a2406
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/fixtures/mocking/users.yaml
@@ -0,0 +1,35 @@
+swagger: "2.0"
+info:
+ title: Sample API
+ description: A Sample API
+ version: 1.0.0
+host: api.example.com
+basePath: /v1
+schemes:
+ - https
+paths:
+ /users/{id}:
+ get:
+ summary: Returns an individual user
+ description: Returns an individual user
+ produces:
+ - application/json
+ parameters:
+ - in: path
+ name: id # Note the name is the same as in the path
+ required: true
+ schema:
+ type: integer
+ minimum: 1
+ description: The user ID
+ responses:
+ "200":
+ description: OK
+ examples:
+ "application/json" : {
+ "sub": "jdoe",
+ "name": "Jane Doe",
+ "given_name": "Jane",
+ "family_name": "Doe",
+ "email": "janedoe@example.com"
+ }
diff --git a/kong-versions/3.9.0.0/kong/spec/fixtures/mocks/lua-resty-dns/resty/dns/resolver.lua b/kong-versions/3.9.0.0/kong/spec/fixtures/mocks/lua-resty-dns/resty/dns/resolver.lua
new file mode 100644
index 00000000..b21835fb
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/fixtures/mocks/lua-resty-dns/resty/dns/resolver.lua
@@ -0,0 +1,129 @@
+-- This software is copyright Kong Inc. and its licensors.
+-- Use of the software is subject to the agreement between your organization
+-- and Kong Inc. If there is no such agreement, use is governed by and
+-- subject to the terms of the Kong Master Software License Agreement found
+-- at https://konghq.com/enterprisesoftwarelicense/.
+-- [ END OF LICENSE 0867164ffc95e54f04670b5169c09574bdbd9bba ]
+
+-- Mock for the underlying 'resty.dns.resolver' library
+-- (so NOT the Kong dns client)
+
+-- this file should be in the Kong working directory (prefix)
+local MOCK_RECORD_FILENAME = "dns_mock_records.json"
+
+
+local LOG_PREFIX = "[mock_dns_resolver] "
+local cjson = require "cjson.safe"
+
+-- first thing is to get the original (non-mock) resolver
+local resolver
+do
+ local function get_source_path()
+ -- find script path remember to strip off the starting @
+ -- should be like: 'spec/fixtures/mocks/lua-resty-dns/resty/dns/resolver.lua'
+ return debug.getinfo(2, "S").source:sub(2) --only works in a function, hence the wrapper
+ end
+ local path = get_source_path()
+
+ -- module part is like: 'resty.dns.resolver'
+ local module_part = select(1,...)
+
+ -- create the packagepath part, like: 'spec/fixtures/mocks/lua-resty-dns/?.lua'
+ path = path:gsub(module_part:gsub("%.", "/"), "?") .. ";" -- prefix path, so semi-colon at end
+
+ -- grab current paths
+ local old_paths = package.path
+
+ -- drop the element that picked this mock from the path
+ local s, e = old_paths:find(path, 1, true)
+ package.path = old_paths:sub(1, s-1) .. old_paths:sub(e + 1, -1)
+
+ -- With the mock out of the path, require the module again to get the original.
+ -- Problem is that package.loaded contains a userdata now, because we're in
+ -- the middle of loading that same module name. So swap it.
+ local swap
+ swap, package.loaded[module_part] = package.loaded[module_part], nil
+ resolver = require(module_part)
+ package.loaded[module_part] = swap
+
+ -- restore the package path
+ package.path = old_paths
+end
+
+
+-- load and cache the mock-records
+local get_mock_records
+do
+ local mock_file
+ get_mock_records = function()
+ if mock_file then
+ return mock_file.records, mock_file.mocks_only
+ end
+
+ local is_file = require("pl.path").isfile
+ local prefix = ((kong or {}).configuration or {}).prefix
+ if not prefix then
+ -- we might be invoked before the Kong config was loaded, so exit early
+ -- and do not set _mock_records yet.
+ return {}
+ end
+
+ local filename = prefix .. "/" .. MOCK_RECORD_FILENAME
+
+ mock_file = {}
+ if not is_file(filename) then
+ -- no mock records set up, return empty default
+ ngx.log(ngx.DEBUG, LOG_PREFIX, "bypassing mock, no mock records found")
+ return mock_file
+ end
+
+ -- there is a file with mock records available, go load it
+ local f = assert(io.open(filename))
+ local json_file = assert(f:read("*a"))
+ f:close()
+
+ mock_file = assert(cjson.decode(json_file))
+ return mock_file.records, mock_file.mocks_only
+ end
+end
+
+
+-- patch the actual query method
+local old_query = resolver.query
+resolver.query = function(self, name, options, tries)
+ local mock_records, mocks_only = get_mock_records()
+ local qtype = (options or {}).qtype or resolver.TYPE_A
+
+ local answer = (mock_records[qtype] or {})[name]
+ if answer then
+ -- we actually have a mock answer, return it
+ ngx.log(ngx.DEBUG, LOG_PREFIX, "serving '", name, "' from mocks")
+ return answer, nil, tries
+ end
+
+ if not mocks_only then
+ -- No mock, so invoke original resolver. Note that if the original resolver fails (i.e. because an
+ -- invalid domain name like example.com was used), we return an empty result set instead of passing
+ -- the error up to the caller. This is done so that if the mock contains "A" records (which would
+ -- be the most common case), the initial query for a SRV record does not fail, but appear not to have
+ -- yielded any results. This will make dns/client.lua try finding an A record next.
+ local records, err, tries = old_query(self, name, options, tries)
+ if records then
+ return records, err, tries
+ end
+ end
+
+ return {}, nil, tries
+end
+
+-- do
+-- local semaphore = require "ngx.semaphore"
+-- local old_post = semaphore.post
+-- function semaphore.post(self, n)
+-- old_post(self, n)
+-- ngx.sleep(0)
+-- end
+-- end
+
+
+return resolver
diff --git a/kong-versions/3.9.0.0/kong/spec/fixtures/mocks/lua-resty-websocket/resty/websocket/peer.lua b/kong-versions/3.9.0.0/kong/spec/fixtures/mocks/lua-resty-websocket/resty/websocket/peer.lua
new file mode 100644
index 00000000..ea36c414
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/fixtures/mocks/lua-resty-websocket/resty/websocket/peer.lua
@@ -0,0 +1,150 @@
+-- This software is copyright Kong Inc. and its licensors.
+-- Use of the software is subject to the agreement between your organization
+-- and Kong Inc. If there is no such agreement, use is governed by and
+-- subject to the terms of the Kong Master Software License Agreement found
+-- at https://konghq.com/enterprisesoftwarelicense/.
+-- [ END OF LICENSE 0867164ffc95e54f04670b5169c09574bdbd9bba ]
+
+local semaphore = require "ngx.semaphore"
+local semaphore_new = semaphore.new
+
+local remove = table.remove
+local insert = table.insert
+
+-- buffer
+local recv_buf = {}
+local recv_buf_mt = { __index = recv_buf }
+
+local default_timeout = 5
+
+function recv_buf.new()
+ return setmetatable({ smph = semaphore_new() }, recv_buf_mt)
+end
+
+function recv_buf:push(obj)
+ insert(self, obj)
+ if #self == 1 then
+ self.smph:post()
+ end
+
+ return true
+end
+
+function recv_buf:pop_no_wait()
+ return remove(self)
+end
+
+function recv_buf:pop(timeout)
+ if #self == 0 then
+ local ok, err = self.smph:wait(timeout or default_timeout)
+ if not ok then
+ return nil, err
+ end
+ end
+
+ return remove(self)
+end
+
+-- end buffer
+
+local unpack = unpack
+
+local _M = {}
+local mt = { __index = _M }
+
+local empty = {}
+
+-- we ignore mask problems and most of error handling
+
+function _M:new(opts)
+ opts = opts or empty
+
+ local new_peer = setmetatable({
+ timeout = opts.timeout,
+ buf = recv_buf.new(),
+ }, mt)
+
+ return new_peer
+end
+
+function _M:set_timeout(time)
+ self.timeout = time
+ return true
+end
+
+local types = {
+ [0x0] = "continuation",
+ [0x1] = "text",
+ [0x2] = "binary",
+ [0x8] = "close",
+ [0x9] = "ping",
+ [0xa] = "pong",
+}
+
+function _M:translate_frame(fin, op, payload)
+ payload = payload or ""
+ local payload_len = #payload
+ op = types[op]
+ if op == "close" then
+ -- being a close frame
+ if payload_len > 0 then
+ return payload[2], "close", payload[1]
+ end
+
+ return "", "close", nil
+ end
+
+ return payload, op, not fin and "again" or nil
+end
+
+function _M:recv_frame()
+ local buf = self.buf
+ local obj, err = buf:pop(self.timeout)
+ if not obj then
+ return nil, nil, err
+ end
+
+ return self:translate_frame(unpack(obj)) -- data, typ, err
+end
+
+local function send_frame(self, fin, op, payload)
+ local message = { fin, op, payload }
+
+ return self.peer.buf:push(message)
+end
+
+_M.send_frame = send_frame
+
+function _M:send_text(data)
+ return self:send_frame(true, 0x1, data)
+end
+
+function _M:send_binary(data)
+ return self:send_frame(true, 0x2, data)
+end
+
+function _M:send_close(code, msg)
+ local payload
+ if code then
+ payload = {code, msg}
+ end
+ return self:send_frame(true, 0x8, payload)
+end
+
+function _M:send_ping(data)
+ return self:send_frame(true, 0x9, data)
+end
+
+function _M:send_pong(data)
+ return self:send_frame(true, 0xa, data)
+end
+
+-- for clients
+function _M.connect()
+end
+function _M.set_keepalive()
+end
+function _M.close()
+end
+
+return _M
diff --git a/kong-versions/3.9.0.0/kong/spec/fixtures/mtls_certs/ca.crt b/kong-versions/3.9.0.0/kong/spec/fixtures/mtls_certs/ca.crt
new file mode 100644
index 00000000..6b5555eb
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/fixtures/mtls_certs/ca.crt
@@ -0,0 +1,33 @@
+-----BEGIN CERTIFICATE-----
+MIIFoTCCA4mgAwIBAgIUQDBLwIychoRbVRO44IzBBk9R4oYwDQYJKoZIhvcNAQEL
+BQAwWDELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExFTATBgNVBAoM
+DEtvbmcgVGVzdGluZzEdMBsGA1UEAwwUS29uZyBUZXN0aW5nIFJvb3QgQ0EwHhcN
+MTkwNTAyMTkzNDQyWhcNMzkwNDI3MTkzNDQyWjBYMQswCQYDVQQGEwJVUzETMBEG
+A1UECAwKQ2FsaWZvcm5pYTEVMBMGA1UECgwMS29uZyBUZXN0aW5nMR0wGwYDVQQD
+DBRLb25nIFRlc3RpbmcgUm9vdCBDQTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCC
+AgoCggIBAMp6IggUp3aSNRbLAac8oOkrbUnFuxtlKGYgg8vfA2UU71qTktigdwO6
+Kod0/M+daO3RDqJJXQL2rD14NDO3MaextICanoQSEe+nYyMFUIk+QplXLD3fbshU
+nHoJcMS2w0x4cm1os4ebxR2Evndo6luz39ivcjau+BL+9iBAYL1g6+eGOjcSy7ft
+1nAMvbxcQ7dmbAH2KP6OmF8cok+eQWVqXEjqtVx5GDMDlj1BjX6Kulmh/vhNi3Hr
+NEi+kPrw/YtRgnqnN0sv3NnAyKnantxy7w0TDicFjiBsSIhjB5aUfWYErBR+Nj/m
+uumwc/kRJcHWklqDzxrZKCIyOyWcE5Dyjjr46cnF8HxhYwgZcwkmgTtaXOLpBMlo
+XUTgOQrWpm9HYg2vOJMMA/ZPUJ2tJ34/4RgiA00EJ5xG8r24suZmT775l+XFLFzp
+Ihxvs3BMbrWsXlcZkI5neNk7Q/1jLoBhWeTYjMpUS7bJ/49YVGQZFs3xu2IcLqeD
+5WsB1i+EqBAI0jm4vWEynsyX+kS2BqAiDtCsS6WYT2q00DTeP5eIHh/vHsm75jJ+
+yUEb1xFxGnNevLKNTcHUeXxPUnowdC6wqFnaJm7l09qVGDom7tLX9i6MCojgpAP0
+hMpBxzh8jLxHh+zZQdiORSFdYxNnlnWwbic2GUJruiQVLuhpseenAgMBAAGjYzBh
+MB0GA1UdDgQWBBQHT/IIheEC2kdBxI/TfGqUxWJw9zAfBgNVHSMEGDAWgBQHT/II
+heEC2kdBxI/TfGqUxWJw9zAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIB
+hjANBgkqhkiG9w0BAQsFAAOCAgEAqXZjy4EltJCRtBmN0ohAHPWqH4ZJQCI2HrM3
+wHB6c4oPWcJ+M2PfmYPUJo9VMjvn4S3sZuAysyoHduvRdGDnElW4wglL1xxpoUOx
+FqoZUoYWV8hDFmUTWM5b4CtJxOPdTAd8VgypulM3iUEzBQrjR6tnMOdkiFMOmVag
+0/Nnr+Tcfk/crMCx3xsVnisYjJoQBFBH4UY+gWE/V/MS1Sya4/qTbuuCUq+Qym5P
+r8TkWAJlg7iVVLbZ2j94VUdpiQPWJEGMtJck/NEmOTruhhQlT7c1u/lqXCGj7uci
+LmhLsBVmdtWT9AWS8Rl7Qo5GXbjxKIaP3IM9axhDLm8WHwPRLx7DuIFEc+OBxJhz
+wkr0g0yLS0AMZpaC6UGbWX01ed10U01mQ/qPU5uZiB0GvruwsYWZsyL1QXUeqLz3
+/KKrx3XsXjtBu3ZG4LAnwuxfeZCNw9ofg8CqF9c20ko+7tZAv6DCu9UL+2oZnEyQ
+CboRDwpnAlQ7qJVSp2xMgunO3xxVMlhD5LZpEJz1lRT0nQV3uuLpMYNM4FS9OW/X
+MZSzwHhDdCTDWtc/iRszimOnYYV8Y0ubJcb59uhwcsHmdfnwL9DVO6X5xyzb8wsf
+wWaPbub8SN2jKnT0g6ZWuca4VwEo1fRaBkzSZDqXwhkBDWP8UBqLXMXWHdZaT8NK
+0NEO74c=
+-----END CERTIFICATE-----
diff --git a/kong-versions/3.9.0.0/kong/spec/fixtures/mtls_certs/ca.key b/kong-versions/3.9.0.0/kong/spec/fixtures/mtls_certs/ca.key
new file mode 100644
index 00000000..22f7391c
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/fixtures/mtls_certs/ca.key
@@ -0,0 +1,51 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIJKAIBAAKCAgEAynoiCBSndpI1FssBpzyg6SttScW7G2UoZiCDy98DZRTvWpOS
+2KB3A7oqh3T8z51o7dEOokldAvasPXg0M7cxp7G0gJqehBIR76djIwVQiT5CmVcs
+Pd9uyFSceglwxLbDTHhybWizh5vFHYS+d2jqW7Pf2K9yNq74Ev72IEBgvWDr54Y6
+NxLLt+3WcAy9vFxDt2ZsAfYo/o6YXxyiT55BZWpcSOq1XHkYMwOWPUGNfoq6WaH+
++E2Lces0SL6Q+vD9i1GCeqc3Sy/c2cDIqdqe3HLvDRMOJwWOIGxIiGMHlpR9ZgSs
+FH42P+a66bBz+RElwdaSWoPPGtkoIjI7JZwTkPKOOvjpycXwfGFjCBlzCSaBO1pc
+4ukEyWhdROA5Ctamb0diDa84kwwD9k9Qna0nfj/hGCIDTQQnnEbyvbiy5mZPvvmX
+5cUsXOkiHG+zcExutaxeVxmQjmd42TtD/WMugGFZ5NiMylRLtsn/j1hUZBkWzfG7
+Yhwup4PlawHWL4SoEAjSObi9YTKezJf6RLYGoCIO0KxLpZhParTQNN4/l4geH+8e
+ybvmMn7JQRvXEXEac168so1NwdR5fE9SejB0LrCoWdombuXT2pUYOibu0tf2LowK
+iOCkA/SEykHHOHyMvEeH7NlB2I5FIV1jE2eWdbBuJzYZQmu6JBUu6Gmx56cCAwEA
+AQKCAgBh8MQHbp42r7B4bwhEsgIP5868kaXZMYxiIjY+ZojI22CQSrQMj0oihmnO
+Dhu//Z9k8ewHOj+AkHtuXHe70FB3knECiEhHEEqWxzwgE5EKYhBrBgzDfRGkW7E5
+ItnmfZVopxaKr8uvu/yUM8LCFgDPDOopcWxo4SfkYGoD3cAtuvVBj98XBsN+G9DP
+cIpS07p5u1RheoYH5Ef2Me6dXqq5eMJdDxNdQMIg4wpIZS4hWM+dTcv8pd3e4+vt
+iCivCeVK/8mCtOH9P5Cv0B4Ac1zGu93AUEhXPcurCVXoiyZ/gyJJN9dZLlflfyFI
+qu7eOpot8jHnEL0cepB8Qhn0LlQTuv6rjJqmnl3tJA3S6rcM/mOjihkk1uo7JdDK
+vH498XR5qZPDlXZ8PVu3nI5EgXpmFIcCBuuVFS5QI63NZ32YqoGYXK37K7C9lQsL
+L/iR+YpwuQqDmM+UEETjBCIMKvxghFH0ICR041yg9tkjRhNKCAGc6n70wQDUq57s
+jjZmTQ4ZydxCsWVjLo7fCcoyQ9B7IUGPUUn8WavPUwtz1kG6VK7RDGa0KtgCD0vc
+iEwbWi9uwkZdoZdHcB8qLgCPjMGgRJLOyJ67xQ0RP+r+WkhUAjYcaucFonyyBhtv
+OrqNyEM3SEpgrzgttyyg+dP/cDvPbp4NXoxKAMyd8c7mjPploQKCAQEA+BL/qxLe
+LTKwe3TKpjAeyTB2iOxoWjtCqe3/xKbTS32Tn/VGwqhXyNeh+FTRhQu7fg5iL2C2
+JCOdYXWxRYIBwUh4HfApkgYzznUAU2vOh653MzW6LsOtDdgYF2cijN1ZFcbRTGpw
+eoA6U/cijuglwpTHF7zmRd9rSsv+PZ/fTDgY82MOdeaOUwyKuVyPUpNWfqSwxPd9
+tWEdOYjgq1llPbl1mktR0gYHIdHcSr1By7kmFw3/TQuic5Nm+FDidtfJYO36xFI1
+/CfwGVYeH42iul+KzdlITLAMRm2PAcWFjvxpw78T+xeUNpZlnZSgCIjtpfjywmXb
+uQvJoMMEX5PN1wKCAQEA0PIx4sgXiwqASa/foBB0Tk5jG3QWxucpqnLJURZeRqLQ
+BmF4WRrjs5V2y6iizegIcNmL0ZfwFBU79HwtAgFiTELLQL2xivhpMVjXL7QHeE4r
+A/9+49iO8wu8W/hwKxCDdGqXKyCKtW9b1yfUVB09j29GtApcV9v8KCTmDwYGrHI0
+DcEMtNLUbJvUeWFYFadJNFKxbsBtJPJIrYaiIyv2sL+Y3tZrYES72tTAYhMFwd0r
+9ooL5Ufrpuh4pHOxxA0Sh0EVUhNmyoq/ZJZ5wia+WB5NXBSD9JbciC5M4J8BMl/u
+Bx5RZbJSoAktYiOzev//6NHUmXsDjg3Kh9P48JVasQKCAQBVjt/k1bYQ6pmZirdV
+x+TmSLOpF7gJ3sRoLTB4V30qXR4sHgEQo9Ta7RvstPwqIdjBah6M7pMDNdFSyq+g
+JG2Mhvz+flUoCsGVZB7/pn/tpctwuwgClvQ5gR0V/TkaUkEmVJLdAxzV8yGq0eJ2
+XTSgvoVH95uH3712Z5LBGEGAXRyl3LUhDqpplDrIIVdBCJXdSdm5pQ4TH3Jf5Ihw
+MH3NYwhfdbi7cd7F2EZc9Jcbtzie3PH/VZLqv5zU6bihelz29Dz3ts7tr6yMYHo1
+Mbk9BDSwOE9KO7GQHLskxkYBAadMnrs6b3Brv0U+qwLizq7//jNjvpOgZ6Nbscbx
+W92zAoIBAQCNCK17cavSgggNtNSw6epXYLmssjMdlrKdBlW0kfCYpRTc+bWOD4Ra
+lyxUU0Nw0InCAlVJ59B4/cw2PgrzK5P5/avLyz6nmv0F/f1hiZbxMXH/hNlVWbtD
+ekxtl8e+iarxTXEz/wchaEUJeSzsicAfrPCAXe3ur+IIBr/yrBKdG4jfL8sv0o7n
+sFc+huI522yiEJ8LLn99TLyZxCJ0sxwUOX8qCnj3xe02zBv/Fu/v5yXhh1R4Mo9x
+XcDw39bBikFTYi7N86KSXAzMDHWrAxO/ztRQrthSo/G/SeFCTJE2O2IjE+fFSRRU
+SV2EvKxM/bbyo49o+YtwuwZVoFKLsYRBAoIBADaL9sx49XTHIIFGqEQP7NLEhs7D
+eJgSKP5oQ54J0iaoVpsoxng8DrTBkMVW75hiWzTW75EJnMXrauo/YfAbvsMM//3e
+BfRWvYpS5xKcHmXg2QJxy2VpvElHLg5Y2lligEZhO+5Sm2OG/hixBmiFvEvxPEB8
+8YIvYKcRAGA/HgDY9hGWSNsBP7qDXWP5kRm8qnB6zn33TVZMsXwUv6TP0cwsBKf7
+XDbnPBpOQK9nicehY7oscy9yTB9Q3bUHecYLY822ueCwaJgwJWFUH+Xe4u6xIH5l
+A/IyIfyOqxjUc34Me+37ehNmbTIxZ1BqLddppm9QsSAD7cDMurfb3pRpju4=
+-----END RSA PRIVATE KEY-----
diff --git a/kong-versions/3.9.0.0/kong/spec/fixtures/mtls_certs/example.com.crt b/kong-versions/3.9.0.0/kong/spec/fixtures/mtls_certs/example.com.crt
new file mode 100644
index 00000000..8a3257f9
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/fixtures/mtls_certs/example.com.crt
@@ -0,0 +1,63 @@
+-----BEGIN CERTIFICATE-----
+MIIFTDCCAzSgAwIBAgICIAAwDQYJKoZIhvcNAQELBQAwYDELMAkGA1UEBhMCVVMx
+EzARBgNVBAgMCkNhbGlmb3JuaWExFTATBgNVBAoMDEtvbmcgVGVzdGluZzElMCMG
+A1UEAwwcS29uZyBUZXN0aW5nIEludGVybWlkaWF0ZSBDQTAeFw0xOTA1MDIxOTU1
+MjFaFw0yOTA0MjgxOTU1MjFaME8xCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxp
+Zm9ybmlhMRUwEwYDVQQKDAxLb25nIFRlc3RpbmcxFDASBgNVBAMMC2V4YW1wbGUu
+Y29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqCozbPPts2H7CsUf
+4KlyKwbCOjqUa7ZhBcXfX5KuEHOvAUZfJOlm2TCNbO1wMTI1QHwjn6a9HM1njhBG
+4r9HH8CLckF83b247iJQbqUEjjvbb6DMTxjbC7dBunIikv6gUXeWGlRHupy/UEh8
+K0Y2KM2fm+HEbKI6zvjg/wb7zb0agzNaKV6fyEourKL0Xjz8ePm3kH58HaUmqhfk
+PPf7GnGW1xk/aIm6tsi9wzj2VBI/T3E5hVnMGrJTYnXh5DoFQrbuLvWtOB6MdZcM
+BWN/he8ISvvhKrctjWvUjpWgoZE9bRoMxkzxpHF/agM++WlHJrJ7my3yRHN3LspF
+4ER+/QIDAQABo4IBHzCCARswCQYDVR0TBAIwADARBglghkgBhvhCAQEEBAMCBkAw
+MwYJYIZIAYb4QgENBCYWJE9wZW5TU0wgR2VuZXJhdGVkIFNlcnZlciBDZXJ0aWZp
+Y2F0ZTAdBgNVHQ4EFgQUlpSl7QvKjdvJLx/sI3CXST3SqwowgYEGA1UdIwR6MHiA
+FAsOBA6X+G1iTyTwO8Zv0go7jRERoVykWjBYMQswCQYDVQQGEwJVUzETMBEGA1UE
+CAwKQ2FsaWZvcm5pYTEVMBMGA1UECgwMS29uZyBUZXN0aW5nMR0wGwYDVQQDDBRL
+b25nIFRlc3RpbmcgUm9vdCBDQYICEAAwDgYDVR0PAQH/BAQDAgWgMBMGA1UdJQQM
+MAoGCCsGAQUFBwMBMA0GCSqGSIb3DQEBCwUAA4ICAQA6kfAONRKeg0ygcyY8OwVi
+y9SGPKnKtOGjF2BSk74UF3bj63kx7utIQ0w5LZA3CwjcE2VzdPx+lQEDy/dbv442
+2bWrc7kG0/Dcr92KoUbzuuI0kPRoM/4rcOb8shKG9txFL1j44a60SWlbvkoNUD88
+vKZy2uSJ++OeQ7vuxrt2UDsfO2jRk74p/ztQibTX/cpwjvHrz2JcLTSxUZXK342x
+o7bWl1f7XMn8o7nPtNWHZq418uwFJ6OZO/rLc+FxE+31SnHYJUYC6/TSAg9kGomk
+Ws+K453QVoiPsG08Uz1JRjUQWotlEmqFAwax3kmfnrsiKmKy451CcwVAlyEIvnSb
+s2hEePHUaJltsatvFNPLnjcsOtqA46zJN0mv63BKuoa9fWAYr81D8wilcPgx534j
+KQcSv24cAoWesp/KhERK5G+F5mE0qnlCfMpFJFtfMjh+CDLbR//L4/0KQrSS/eRn
+ooeXinTpO5S2WOxk0W96rZMsBL2rBUI2qhfjBW8aQAiew4cMtddxryyUKskDlJPx
+bZXB2OmPibOOOTrTrBFkQ+tjKCuPKbOQDsIPTasZQKc2jK0boixXE8AXhN/A+3J4
+muvYnypmWGb0jMLEQT2u+RQzCNDjIOEHBP50XnoEX3jkOgEwknje89VDm/JXcClR
+l5HH4/9/AbS7rFCRnphOjQ==
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIIFmjCCA4KgAwIBAgICEAAwDQYJKoZIhvcNAQELBQAwWDELMAkGA1UEBhMCVVMx
+EzARBgNVBAgMCkNhbGlmb3JuaWExFTATBgNVBAoMDEtvbmcgVGVzdGluZzEdMBsG
+A1UEAwwUS29uZyBUZXN0aW5nIFJvb3QgQ0EwHhcNMTkwNTAyMTk0MDQ4WhcNMjkw
+NDI5MTk0MDQ4WjBgMQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEV
+MBMGA1UECgwMS29uZyBUZXN0aW5nMSUwIwYDVQQDDBxLb25nIFRlc3RpbmcgSW50
+ZXJtaWRpYXRlIENBMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA0dnj
+oHlJmNM94vQnK2FIIQJm9OAVvyMtAAkBKL7Cxt8G062GHDhq6gjQ9enuNQE0l3Vv
+mSAh7N9gNlma6YbRB9VeG54BCuRQwCxveOBiwQvC2qrTzYI34kF/AeflrDOdzuLb
+zj5cLADKXGCbGDtrSPKUwdlkuLs3pRr/YAyIQr7zJtlLz+E0GBYp0GWnLs0FiLSP
+qSBWllC9u8gt2MiKyNlXw+kZ8lofOehCJzfFr6qagVklPw+8IpU6OGmRLFQVwVhp
+zdAJmAGmSo/AGNKGqDdjzC4N2l4uYGH6n2KmY2yxsLBGZgwtLDst3fK4a3Wa5Tj7
+cUwCcGLGtfVTaIXZYbqQ0nGsaYUd/mhx3B3Jk1p3ILZ72nVYowhpj22ipPGal5hp
+ABh1MX3s/B+2ybWyDTtSaspcyhsRQsS6axB3DwLOLRy5Xp/kqEdConCtGCsjgm+U
+FzdupubXK+KIAmTKXDx8OM7Af/K7kLDfFTre40sEB6fwrWwH8yFojeqkA/Uqhn5S
+CzB0o4F3ON0xajsw2dRCziiq7pSe6ALLXetKpBr+xnVbUswH6BANUoDvh9thVPPx
+1trkv+OuoJalkruZaT+38+iV9xwdqxnR7PUawqSyvrEAxjqUo7dDPsEuOpx1DJjO
+XwRJCUjd7Ux913Iks24BqpPhEQz/rZzJLBApRVsCAwEAAaNmMGQwHQYDVR0OBBYE
+FAsOBA6X+G1iTyTwO8Zv0go7jRERMB8GA1UdIwQYMBaAFAdP8giF4QLaR0HEj9N8
+apTFYnD3MBIGA1UdEwEB/wQIMAYBAf8CAQAwDgYDVR0PAQH/BAQDAgGGMA0GCSqG
+SIb3DQEBCwUAA4ICAQAWzIvIVM32iurqM451Amz0HNDG9j84cORnnaRR5opFTr3P
+EqI3QkgCyP6YOs9t0QSbA4ur9WUzd3c9Ktj3qRRgTE+98JBOPO0rv+Kjj48aANDV
+5tcbI9TZ9ap6g0jYr4XNT+KOO7E8QYlpY/wtokudCUDJE9vrsp1on4Bal2gjvCdh
+SU0C1lnj6q6kBdQSYHrcjiEIGJH21ayVoNaBVP/fxyCHz472w1xN220dxUI/GqB6
+pjcuy9cHjJHJKJbrkdt2eDRAFP5cILXc3mzUoGUDHY2JA1gtOHV0p4ix9R9AfI9x
+snBEFiD8oIpcQay8MJH/z3NLEPLoBW+JaAAs89P+jcppea5N9vbiAkrPi687BFTP
+PWPdstyttw6KrvtPQR1+FsVFcGeTjo32/UrckJixdiOEZgHk+deXpp7JoRdcsgzD
++okrsG79/LgS4icLmzNEp0IV36QckEq0+ALKDu6BXvWTkb5DB/FUrovZKJgkYeWj
+GKogyrPIXrYi725Ff306124kLbxiA+6iBbKUtCutQnvut78puC6iP+a2SrfsbUJ4
+qpvBFOY29Mlww88oWNGTA8QeW84Y1EJbRkHavzSsMFB73sxidQW0cHNC5t9RCKAQ
+uibeZgK1Yk7YQKXdvbZvXwrgTcAjCdbppw2L6e0Uy+OGgNjnIps8K460SdaIiA==
+-----END CERTIFICATE-----
diff --git a/kong-versions/3.9.0.0/kong/spec/fixtures/mtls_certs/example.com.key b/kong-versions/3.9.0.0/kong/spec/fixtures/mtls_certs/example.com.key
new file mode 100644
index 00000000..c8ad8f2e
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/fixtures/mtls_certs/example.com.key
@@ -0,0 +1,27 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIEpAIBAAKCAQEAqCozbPPts2H7CsUf4KlyKwbCOjqUa7ZhBcXfX5KuEHOvAUZf
+JOlm2TCNbO1wMTI1QHwjn6a9HM1njhBG4r9HH8CLckF83b247iJQbqUEjjvbb6DM
+TxjbC7dBunIikv6gUXeWGlRHupy/UEh8K0Y2KM2fm+HEbKI6zvjg/wb7zb0agzNa
+KV6fyEourKL0Xjz8ePm3kH58HaUmqhfkPPf7GnGW1xk/aIm6tsi9wzj2VBI/T3E5
+hVnMGrJTYnXh5DoFQrbuLvWtOB6MdZcMBWN/he8ISvvhKrctjWvUjpWgoZE9bRoM
+xkzxpHF/agM++WlHJrJ7my3yRHN3LspF4ER+/QIDAQABAoIBACHkx5KpI3qpP+ju
+zDsCzAECDrmfvvRqwOlh9WCU9sJYHqi6H0kYReN2lrqirJ8tyG/j1WZDPBCHEd0f
+SLpA5TvwGesAagNjTteoUN/MILvuMo8wMJ2sm9GjsPq8MF3CNlvVJ4rM+9wP5btv
+sJ8kOpxEvWu0uFtQ41t97BNau/u+UtMk3oNCYBhiUWDg0rWPrUeX8cKzFSM8VAt4
+vvsybRHPbBmSLW01xO1Hq5cZdqbN4SxyQC1Ug9gW/afJQNRK7CubpWjOOQAsla0j
+ExyBxMMwDLLZfYCQpRn92ZB4x+LiaXqnbrtyfA+GLLjtlUPY6ClpdXa7KSN/mEuE
+LIIjiV0CgYEA2YsCt1+Yak+GOX6tSx1YUDz6UpZyOo2OKwqJ+G+SKT7JLT84A5nP
+rn6r6UUpNKhK3glpU1A1VJKiFnZ9qJi/gHJcNiSEIcUFHNFflDSmiZc6MyfcIkCZ
+xLUCrYHpETubTnB5P5jOhmsA3/uApaAc/Pv5hfSRzQv524k08TRgCU8CgYEAxeSQ
+MIRV1SKDYsEdEfXJE+WJLz2rlpR19l/9Wfuc5QVgAgDhFCCvHUX1ULU8yGQUSHqz
+DseR3iQF+Jvo3MK7pgC2fH6UePjakWOCXqXey1CpAzUHM/Qhwd451VqAGAT+Pabj
+tzPJ0cSC7sszxhwmAzotIUrjZDbuAzwQyRXdh/MCgYEApP2KVNt69H5V9bs+4W5j
+MY/d5s9V2VTNE5XNqI+uEfwdhmShLhH08on+BlC+/MH67kXDDT4TBI6lwlWh3kHj
+VB7oEuRFFnuf8ghV7ki0WjxJFs1PZucJ+Ke0XTXfN4O2uZoSS4qwcEAtjLLqEjPK
+aJEO4WrpPdOsb7WzYpDvmX8CgYEAwPunXZkAN0xkAl8+4S/mup+Ci+5BMiRvcSek
+4yaLl5AJU4rV9JH3E74QgHdt4iIu4Yu+qHAYoSBSLmKk0PyakEVrsLakReCxDU2U
+aoapYW60k6sX7iNq9CuqDJUoC8R6x1bEBPndG9LeuM6zG8SBkW4farMkU6t5qu/d
+kqvfEN8CgYAQphK9AoATrEomLbGwmcW+8JkjU9Sxnq+zo8io75wFAY2cUnQJQEId
+zGWwYjwHxXQCNCZ3ZwD7+iYgFHfxbPaiTWELkV2nEpBHQI0cLgzlcEBwo+uoFiYK
+33Yxb6EhNFSy7d2GPVZMjIR+KifCIem+i/3BiIlzneuFSRlnKORekQ==
+-----END RSA PRIVATE KEY-----
diff --git a/kong-versions/3.9.0.0/kong/spec/fixtures/mtls_certs/example2.com.crt b/kong-versions/3.9.0.0/kong/spec/fixtures/mtls_certs/example2.com.crt
new file mode 100644
index 00000000..85756548
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/fixtures/mtls_certs/example2.com.crt
@@ -0,0 +1,25 @@
+-----BEGIN CERTIFICATE-----
+MIIEJzCCAg8CFAQ6oTnLBUHbumx1bxyY9kV0W21BMA0GCSqGSIb3DQEBCwUAMFgx
+CzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRUwEwYDVQQKDAxLb25n
+IFRlc3RpbmcxHTAbBgNVBAMMFEtvbmcgVGVzdGluZyBSb290IENBMB4XDTIwMDQx
+MzIzNDg0MVoXDTMwMDQxMTIzNDg0MVowSDELMAkGA1UEBhMCVVMxCzAJBgNVBAgM
+AkNBMRUwEwYDVQQKDAxLb25nIFRlc3RpbmcxFTATBgNVBAMMDGV4YW1wbGUyLmNv
+bTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAK+kZhxdN8PA3SW9cXiv
+xgtANq57PIWNnSDsg9Yxn0/+JKR45pSU+SKYtZUJJJuOdkv4IIJLm6uG6LbOPUDO
+g9EaV0Zw7RQtbY6EDFDFzeyq0/Mwl9wLJtXf0fPsXGyFIdeelBjzoSVsGGJKPWbP
+rlUtSHCrpFX53NTPnNVUJz9V6CdzZJgbyoiWP7ggKJeRPq6jCW5pt+cd+sR4+EPh
+daBmEVWeifLEKCbBvsQaOGfU1aVG1AlX0RpLBkTxOOFIIk/3dgWOsrek2ofjku4F
+g0MeWmD8oXOHUX2JxO77/BbLDQt0lzD27y/EkDoqy6mMAH85/LTYrU+P0WsEyexg
+CHcCAwEAATANBgkqhkiG9w0BAQsFAAOCAgEAwWAxQjQOoGxU5LQu4ZmsCkps9y0B
+kNj8MUpLcFmK+02VIUh3hM4vuB6Gct2Ph+6zqCge3oqTXltU0Bs2MTwAKs/scsxq
+Mtanz4W00UlmG3QdgHaEs196tYQ8cKIaGZsNBv15VgBBduUG478pKqYE8bJKBbw7
+1Ym390hSPo0dNe7jLFXx6AaJvlEYh09P4FgfkXuY5VVTGXfN7XgJI073pLRY6iGH
+Qd+Egymh86AQtnoNpmqSCMNcjRVAyR8Ti3qnyro8ruZCnNYHieGeh/ZsZvhGDeWX
+v4YXjW2NDQ5+Ok6Gtvhf/l6RSrnXLbZtv8NStqwQJ+ydu05BJglZ/7Sb0uQYVNq2
+H8V+MtApFT6fG6ANM6hadNFG+p8Hwz6k4BLrc9ZxeWYKWIIusqExR9JIlGzEjvFJ
+6NmNjm3eZE9Ue4YgURj1KTr53wAso4LbJpz/zuZS+m9PMz7n8fRL25/Z5b/92L3a
+w0vsxUJyTDeMvYf8oT6OkxNVJ0zBRZNtEg5AJKdP6nU53V998jHP9vUisrU2ALhu
+Jw3QiWiDKnRtx8PiiRx7dWo+Xwn9+xVypytqNz3w/XJlOjMwOg73q399w+vMiFTl
+qdr7eYvaQBGOZVc3OdiP8afyVxlhHBowUoi8G+iPbgOsARHv/j4UeMVyIThzxv73
+a2EQ5BzyOzQ81H4=
+-----END CERTIFICATE-----
diff --git a/kong-versions/3.9.0.0/kong/spec/fixtures/mtls_certs/example2.com.key b/kong-versions/3.9.0.0/kong/spec/fixtures/mtls_certs/example2.com.key
new file mode 100644
index 00000000..05c29251
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/fixtures/mtls_certs/example2.com.key
@@ -0,0 +1,27 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIEpAIBAAKCAQEAr6RmHF03w8DdJb1xeK/GC0A2rns8hY2dIOyD1jGfT/4kpHjm
+lJT5Ipi1lQkkm452S/gggkubq4bots49QM6D0RpXRnDtFC1tjoQMUMXN7KrT8zCX
+3Asm1d/R8+xcbIUh156UGPOhJWwYYko9Zs+uVS1IcKukVfnc1M+c1VQnP1XoJ3Nk
+mBvKiJY/uCAol5E+rqMJbmm35x36xHj4Q+F1oGYRVZ6J8sQoJsG+xBo4Z9TVpUbU
+CVfRGksGRPE44UgiT/d2BY6yt6Tah+OS7gWDQx5aYPyhc4dRfYnE7vv8FssNC3SX
+MPbvL8SQOirLqYwAfzn8tNitT4/RawTJ7GAIdwIDAQABAoIBAHMJzgdN1rRToYSS
+a7uMBL5htG7bMGyYsA1cW4zyu1F9NyqyNPOkDvjl5ChU8LEhwcFIJqKwOqlBlzIE
+KoJDwHo4MmlklSLeDh+FxTsyEwmraV6iuRPaCfmSusR0TqSVHfFHX+Bn0WfdQKs/
+zK+F3rzTB9sj0GKvYD/SKvpeP8Zuu9EBqo4N7PU3VHwDq5t32Ut/+M5XWtulsQcs
+qXr2R3agj/DnODANT6Dn/mJboTrYOSV18S/Yw/+OnWBcLzlT5sj0aLgrtXvIputv
+9caux4HklAQr29+lKB8nBTfjhXnBntMaEgqCVJ3ri83MuEfVDhmjwo6PnX22/J0h
+2XbCyUECgYEA2v8m+CTBTjdAqOuje34+UiWRzT2P9OFONV8nYgzEcQW5JkUoFCun
+KgQQIvjCsX4jY6/8w/IPF1ieTconZYJUWSyMZFtBBDCVif1GZRiiM2C4Zcero1KV
+U0V3wZcnYkzafzIHkqFUYZwamvdKWVI4c6F5MhSEKCgcbgKKI52TEokCgYEAzVHr
+KjQt+dqNkbipYoGH2ywLdcogDwKoyUFbgcvz/q625gu4am025wF25yRKExm7Dyjx
+eCQC+KOsBfJSc78fG5R6KPIDK1JrpUEGSCeqFICiqGv9kUzPf5zeGZVf9cU4tyPT
+5wYUEM7NX8VRoasZ4OUvYyYBw1Cx8vMdvQn/gv8CgYAIhxcFYqkEWrJx4XskO+5B
+VKUw0MziREO/YE0wTD76B7cF/ntpDaocwLvAIN+z+a13HEtDdhGQXysK7GxMT57p
+OgrdfZAykZHBJdOv7B2k0odbr0LHwVd/Pp1DNJecBFId0dzpoM6gXmvKzQZgJAt+
+tTL6+EGNLsKspfyrFl+7wQKBgQDAt2VuJbAJ1xQOdS+4IDCujfbrxp60uCBJVylW
++WK56LAP2WxtqLlhtsQuTKeiqgIkRp/vzo1jZ+0tX7f4oKnIL2NCT3aeESys3g3R
+aDmCKQOD5mkJGvmgpFLr3INHoqiLbfuV2uS2qgWnIQRwJLOTnksOWzxIYdPFYGDH
+cTz9bQKBgQDGv929DUinrKXe/uKJHLAcq+MjmF/+kZU9yn+svq6SSdplqp7xbXX4
+3T5HCWqD4Sy+PVzGaDg5YfXC8yaFPPfY0/35T2FoQEiCAPQO+07Smg6RqJ3yVpIm
+LTsbLleJTc8CX0bI4SukQ7MVQsiHimzyEzx3eyLt1S8aBdJuRFZ2mg==
+-----END RSA PRIVATE KEY-----
diff --git a/kong-versions/3.9.0.0/kong/spec/fixtures/nginx-directives.conf b/kong-versions/3.9.0.0/kong/spec/fixtures/nginx-directives.conf
new file mode 100644
index 00000000..c7a73f59
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/fixtures/nginx-directives.conf
@@ -0,0 +1,8 @@
+nginx_http_variables_hash_bucket_size = 128
+nginx_stream_variables_hash_bucket_size = 128
+nginx_http_lua_shared_dict = custom_cache 5m
+nginx_stream_lua_shared_dict = custom_cache 5m
+nginx_proxy_proxy_bind = 127.0.0.1
+nginx_sproxy_proxy_bind = 127.0.0.1
+nginx_admin_server_tokens = off
+nginx_status_client_body_buffer_size = 8k
diff --git a/kong-versions/3.9.0.0/kong/spec/fixtures/ocsp_certs/ca-chain.crt b/kong-versions/3.9.0.0/kong/spec/fixtures/ocsp_certs/ca-chain.crt
new file mode 100644
index 00000000..9c3449c5
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/fixtures/ocsp_certs/ca-chain.crt
@@ -0,0 +1,65 @@
+-----BEGIN CERTIFICATE-----
+MIIFmTCCA4GgAwIBAgICEAAwDQYJKoZIhvcNAQELBQAwXjELMAkGA1UEBhMCVVMx
+CzAJBgNVBAgMAkNBMQswCQYDVQQHDAJTRjENMAsGA1UECgwES29uZzEUMBIGA1UE
+CwwLRW5naW5lZXJpbmcxEDAOBgNVBAMMB3Jvb3RfY2EwHhcNMjEwMzA0MTEyMjM1
+WhcNNDEwMjI3MTEyMjM1WjBZMQswCQYDVQQGEwJVUzELMAkGA1UECAwCQ0ExDTAL
+BgNVBAoMBEtvbmcxFDASBgNVBAsMC0VuZ2luZWVyaW5nMRgwFgYDVQQDDA9pbnRl
+cm1lZGlhdGVfY2EwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDXcXvt
+kyiEY7Nr8VeEF2KTpGkEwPLNoLW9eNpFH0bFlKcmM/+IocSUErD091SCf0fGCRuo
+8bISb4MVa5esq8XMUSR63cDmz2IbWOtvNir4wLfAoUuA4JBhubaSyaslXLf376QT
+sYDjLH9jQ3rFYskz9hrlX1HFFmm0hlDnuqr1w0GF+6PxPdxRKkdvKexPuQp3qaVZ
+dzKvFcGuCu7nuqemb37CBBkdRAgVUj37pXBIcc5p5h8PVAU24r7pAaYppDmmZMWa
+uTSjz4K/PTh5GzG+snf8iH+EpTLGUqPElR+ABP8YiNrQQzgA91lPjwLqp6D34sMT
+7xvk4Ri1cOpOsNA4hCdFPilzolMQ6Zpz0ELI25vBt8qY57JMlsUjaY2PR1gI+pE+
+jc52e18Bt/axNnbgxoxTQWPcw27mUs7H4+1WiZufhzz59obgWRnoCom0Fb6RN9Rl
+8ezl+h30+Dgk8ftiFm/fI1BttL6dihveSP/xvuMYRFyT0F1ZNZhgME218cOB5hZN
+dKOFynRgI4SfCeMNSy3KnrBoPYE3P/f1ljBbrR5x/xQE0V5iWFJwZwWexO0+Hf7h
+Aaql5dcwsMIjf8MfHKuQOfZauUmPxu0EbM4NiQu5GEK/9rGEIO51Tlo237l6k4tF
+oKCj3EUZ9cM02CROKGDM6vfkyeyGDbuDPGmdLwIDAQABo2YwZDAdBgNVHQ4EFgQU
+xTAm/Gj7/9K32+Wdc0BOHFKRFeEwHwYDVR0jBBgwFoAU9NE7mu7p9CqGxLNWl7km
+VfMeEO0wEgYDVR0TAQH/BAgwBgEB/wIBADAOBgNVHQ8BAf8EBAMCAYYwDQYJKoZI
+hvcNAQELBQADggIBAKFvNX1Wv7lOsYvDGOCmIrJEDdjW2Q60p23v1U/R9Wv7xo7X
+2SRuQvqKd3AB/9dCSgaaXKHwYgTPIS8NwUJ0SMvSwrnnRpZS5qkOB9JgRgAX5Ebd
+eyupB2AumZ1BGaw2gqPYHm8zxu3N2yw2pVV9LJ2nM+IPTqiQrYCV7BxNpAd/v9OA
+EC9XbKhPqdJ4bD6dGg7w5iBPadb6amAKkGutKjjB+AC/lJlM9bMEGd6RP0ywptQx
+jAfY0VTElLsN30Q6pn31Xf4UzZk4xzyW04GaPFcJVoHTWSl969p0k0L/WAMakDHB
+/g4VvkMTFDoH1Mi7ohakHnMC9XQbMVj2t/EE3XLiD4gcNEyCjXczIxDYJRYe2X3f
+51vQNR921P1KUNTooGusltMmHuWBnT046o9rp/2uQvHm2y/qv1kCPHTiP7vhb/TG
+2JCc+3LZ621EjH5jRvL60Pji4RnGGqLDBykLK68dymHVfrSAi+ZCx6PNxSm0Ydm6
+ZM1Vb8lD2EwEm20qKWM484ItWcVHgWEWDvaMjh0iIq45LA0KmN47iUN8X6rmdulZ
+MDSnSYwJfRt1DdyUC0nDWMQaW1JOQxQxoJCoDmiLwv9BIeNB8LNJEU0FTOPc8xhf
+VdlbjNIC1fs2OMWOc3A1hAFlf+vU8UYLRgYhLiAhFT2iwhBksSzGURY7eKqM
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIIFrTCCA5WgAwIBAgIUFQe9z25yjw26iWzS+P7+hz1zx6AwDQYJKoZIhvcNAQEL
+BQAwXjELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMQswCQYDVQQHDAJTRjENMAsG
+A1UECgwES29uZzEUMBIGA1UECwwLRW5naW5lZXJpbmcxEDAOBgNVBAMMB3Jvb3Rf
+Y2EwHhcNMjEwMzA0MTEyMjM0WhcNNDEwMjI3MTEyMjM0WjBeMQswCQYDVQQGEwJV
+UzELMAkGA1UECAwCQ0ExCzAJBgNVBAcMAlNGMQ0wCwYDVQQKDARLb25nMRQwEgYD
+VQQLDAtFbmdpbmVlcmluZzEQMA4GA1UEAwwHcm9vdF9jYTCCAiIwDQYJKoZIhvcN
+AQEBBQADggIPADCCAgoCggIBAKKjido39I5SEmPhme0Z+hG0buOylXg+jmqHpJ/K
+rs+dSq/PsJCjSke81eOP2MFa5duyBxdnXmMJwZYxuQ91bKxdzWVE9ZgCJgNJYsB6
+y5+Fe7ypERwa2ebS/M99FFJ3EzpF017XdsgnSfVh1GEQOZkWQ1+7YrEUEgtwN5lO
+MVUmj1EfoL+jQ/zwxwdxpLu3dh3Ica3szmx3YxqIPRnpyoYYqbktjL63gmFCjLeW
+zEXdVZyoisdaA4iZ9e/wmuLR2/F4cbZ0SjU7QULZ2Zt/SCrs3CaJ3/ZAa6s84kjg
+JBMav+GxbvATSuWQEajiVQrkW9HvXD/NUQBCzzZsOfpzn0044Ls7XvWDCCXs+xtG
+Uhd5cJfmlcbHbZ9PU1xTBqdbwiRX+XlmX7CJRcfgnYnU/B3m5IheA1XKYhoXikgv
+geRwq5uZ8Z2E/WONmFts46MLSmH43Ft+gIXA1u1g3eDHkU2bx9u592lZoluZtL3m
+bmebyk+5bd0GdiHjBGvDSCf/fgaWROgGO9e0PBgdsngHEFmRspipaH39qveM1Cdh
+83q4I96BRmjU5tvFXydFCvp8ABpZz9Gj0h8IRP+bK5ukU46YrEIxQxjBee1c1AAb
+oatRJSJc2J6zSYXRnQfwf5OkhpmVYc+1TAyqPBfixa2TQ7OOhXxDYsJHAb7WySKP
+lfonAgMBAAGjYzBhMB0GA1UdDgQWBBT00Tua7un0KobEs1aXuSZV8x4Q7TAfBgNV
+HSMEGDAWgBT00Tua7un0KobEs1aXuSZV8x4Q7TAPBgNVHRMBAf8EBTADAQH/MA4G
+A1UdDwEB/wQEAwIBhjANBgkqhkiG9w0BAQsFAAOCAgEAgI8CSmjvzQgmnzcNwqX5
+o+KBWEMHJEqQfowaZE7o6xkvEljb1YHRDE0hlwUtD1vbKUthoHD8Mqim3No5z4J0
+dEE+mXQ3zlJWKl5gqHs9KtcLhk51mf4VJ2TW8Z7AoE2OjWSnycLNdlpqUvxzCQOn
+CIhvyDfs4OV1RYywbfiLLmzTCYT7Mt5ye1ZafoRNZ37DCnI/uqoOaMb+a6VaE+0F
+ZXlDonXmy54QUmt6foSG/+kYaqdVLribsE6H+GpePmPTKKOvgE1RutR5+nvMJUB3
++zMQSPVVYLzizwV+Tq9il81qNQB2hZGvM8iSRraBNn8mwpx7M6kcoJ4gvCA3kHCI
+rmuuzlhkNcmZYh0uG378CzhdEOV+JMmuCh4xt2SbQIr5Luqm/+Xoq4tDplKoUVkC
+DScxPoFNoi9bZYW/ppcaeX5KT3Gt0JBaCfD7d0CtbUp/iPS1HtgXTIL9XiYPipsV
+oPLtqvfeORl6aUuqs1xX8HvZrSgcld51+r8X31YIs6feYTFvlbfP0/Jhf2Cs0K/j
+jhC0sGVdWO1C0akDlEBfuE5YMrehjYrrOnEavtTi9+H0vNaB+BGAJHIAj+BGj5C7
+0EkbQdEyhB0pliy9qzbPtN5nt+y0I1lgN9VlFMub6r1u5novNzuVm+5ceBrxG+ga
+T6nsr9aTE1yghO6GTWEPssw=
+-----END CERTIFICATE-----
diff --git a/kong-versions/3.9.0.0/kong/spec/fixtures/ocsp_certs/ca.crt b/kong-versions/3.9.0.0/kong/spec/fixtures/ocsp_certs/ca.crt
new file mode 100644
index 00000000..a33350b0
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/fixtures/ocsp_certs/ca.crt
@@ -0,0 +1,33 @@
+-----BEGIN CERTIFICATE-----
+MIIFrTCCA5WgAwIBAgIUFQe9z25yjw26iWzS+P7+hz1zx6AwDQYJKoZIhvcNAQEL
+BQAwXjELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMQswCQYDVQQHDAJTRjENMAsG
+A1UECgwES29uZzEUMBIGA1UECwwLRW5naW5lZXJpbmcxEDAOBgNVBAMMB3Jvb3Rf
+Y2EwHhcNMjEwMzA0MTEyMjM0WhcNNDEwMjI3MTEyMjM0WjBeMQswCQYDVQQGEwJV
+UzELMAkGA1UECAwCQ0ExCzAJBgNVBAcMAlNGMQ0wCwYDVQQKDARLb25nMRQwEgYD
+VQQLDAtFbmdpbmVlcmluZzEQMA4GA1UEAwwHcm9vdF9jYTCCAiIwDQYJKoZIhvcN
+AQEBBQADggIPADCCAgoCggIBAKKjido39I5SEmPhme0Z+hG0buOylXg+jmqHpJ/K
+rs+dSq/PsJCjSke81eOP2MFa5duyBxdnXmMJwZYxuQ91bKxdzWVE9ZgCJgNJYsB6
+y5+Fe7ypERwa2ebS/M99FFJ3EzpF017XdsgnSfVh1GEQOZkWQ1+7YrEUEgtwN5lO
+MVUmj1EfoL+jQ/zwxwdxpLu3dh3Ica3szmx3YxqIPRnpyoYYqbktjL63gmFCjLeW
+zEXdVZyoisdaA4iZ9e/wmuLR2/F4cbZ0SjU7QULZ2Zt/SCrs3CaJ3/ZAa6s84kjg
+JBMav+GxbvATSuWQEajiVQrkW9HvXD/NUQBCzzZsOfpzn0044Ls7XvWDCCXs+xtG
+Uhd5cJfmlcbHbZ9PU1xTBqdbwiRX+XlmX7CJRcfgnYnU/B3m5IheA1XKYhoXikgv
+geRwq5uZ8Z2E/WONmFts46MLSmH43Ft+gIXA1u1g3eDHkU2bx9u592lZoluZtL3m
+bmebyk+5bd0GdiHjBGvDSCf/fgaWROgGO9e0PBgdsngHEFmRspipaH39qveM1Cdh
+83q4I96BRmjU5tvFXydFCvp8ABpZz9Gj0h8IRP+bK5ukU46YrEIxQxjBee1c1AAb
+oatRJSJc2J6zSYXRnQfwf5OkhpmVYc+1TAyqPBfixa2TQ7OOhXxDYsJHAb7WySKP
+lfonAgMBAAGjYzBhMB0GA1UdDgQWBBT00Tua7un0KobEs1aXuSZV8x4Q7TAfBgNV
+HSMEGDAWgBT00Tua7un0KobEs1aXuSZV8x4Q7TAPBgNVHRMBAf8EBTADAQH/MA4G
+A1UdDwEB/wQEAwIBhjANBgkqhkiG9w0BAQsFAAOCAgEAgI8CSmjvzQgmnzcNwqX5
+o+KBWEMHJEqQfowaZE7o6xkvEljb1YHRDE0hlwUtD1vbKUthoHD8Mqim3No5z4J0
+dEE+mXQ3zlJWKl5gqHs9KtcLhk51mf4VJ2TW8Z7AoE2OjWSnycLNdlpqUvxzCQOn
+CIhvyDfs4OV1RYywbfiLLmzTCYT7Mt5ye1ZafoRNZ37DCnI/uqoOaMb+a6VaE+0F
+ZXlDonXmy54QUmt6foSG/+kYaqdVLribsE6H+GpePmPTKKOvgE1RutR5+nvMJUB3
++zMQSPVVYLzizwV+Tq9il81qNQB2hZGvM8iSRraBNn8mwpx7M6kcoJ4gvCA3kHCI
+rmuuzlhkNcmZYh0uG378CzhdEOV+JMmuCh4xt2SbQIr5Luqm/+Xoq4tDplKoUVkC
+DScxPoFNoi9bZYW/ppcaeX5KT3Gt0JBaCfD7d0CtbUp/iPS1HtgXTIL9XiYPipsV
+oPLtqvfeORl6aUuqs1xX8HvZrSgcld51+r8X31YIs6feYTFvlbfP0/Jhf2Cs0K/j
+jhC0sGVdWO1C0akDlEBfuE5YMrehjYrrOnEavtTi9+H0vNaB+BGAJHIAj+BGj5C7
+0EkbQdEyhB0pliy9qzbPtN5nt+y0I1lgN9VlFMub6r1u5novNzuVm+5ceBrxG+ga
+T6nsr9aTE1yghO6GTWEPssw=
+-----END CERTIFICATE-----
diff --git a/kong-versions/3.9.0.0/kong/spec/fixtures/ocsp_certs/index.txt b/kong-versions/3.9.0.0/kong/spec/fixtures/ocsp_certs/index.txt
new file mode 100644
index 00000000..d9c4e670
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/fixtures/ocsp_certs/index.txt
@@ -0,0 +1,3 @@
+V 310302112235Z 1000 unknown /C=US/ST=CA/L=SF/O=Kong/OU=Engineering/CN=ocsp
+V 310302112337Z 1001 unknown /C=US/ST=CA/L=SF/O=Kong/OU=Engineering/CN=kong_clustering
+V 310302112425Z 1002 unknown /C=US/ST=CA/L=SF/O=Kong/OU=Engineering/CN=kong_data_plane
diff --git a/kong-versions/3.9.0.0/kong/spec/fixtures/ocsp_certs/index.txt.revoked b/kong-versions/3.9.0.0/kong/spec/fixtures/ocsp_certs/index.txt.revoked
new file mode 100644
index 00000000..adc8959a
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/fixtures/ocsp_certs/index.txt.revoked
@@ -0,0 +1,3 @@
+V 310302112235Z 1000 unknown /C=US/ST=CA/L=SF/O=Kong/OU=Engineering/CN=ocsp
+V 310302112337Z 1001 unknown /C=US/ST=CA/L=SF/O=Kong/OU=Engineering/CN=kong_clustering
+R 310302112425Z 210304112822Z 1002 unknown /C=US/ST=CA/L=SF/O=Kong/OU=Engineering/CN=kong_data_plane
diff --git a/kong-versions/3.9.0.0/kong/spec/fixtures/ocsp_certs/kong_clustering.crt b/kong-versions/3.9.0.0/kong/spec/fixtures/ocsp_certs/kong_clustering.crt
new file mode 100644
index 00000000..43ae9de2
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/fixtures/ocsp_certs/kong_clustering.crt
@@ -0,0 +1,63 @@
+-----BEGIN CERTIFICATE-----
+MIIFYzCCA0ugAwIBAgICEAEwDQYJKoZIhvcNAQELBQAwWTELMAkGA1UEBhMCVVMx
+CzAJBgNVBAgMAkNBMQ0wCwYDVQQKDARLb25nMRQwEgYDVQQLDAtFbmdpbmVlcmlu
+ZzEYMBYGA1UEAwwPaW50ZXJtZWRpYXRlX2NhMB4XDTIxMDMwNDExMjMzN1oXDTMx
+MDMwMjExMjMzN1owZjELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMQswCQYDVQQH
+DAJTRjENMAsGA1UECgwES29uZzEUMBIGA1UECwwLRW5naW5lZXJpbmcxGDAWBgNV
+BAMMD2tvbmdfY2x1c3RlcmluZzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
+ggEBANaCyZeJxFogkiIBjNBTZcztOsW/8vfljzK/m6Yi589hbrTw2CgDGBl+3Pnl
+3AA8bkpAG0Tl0TjB3h/hij5Ywopd/dDEeNAhjvlBNiDMy2cN93t3XvGyp7w4hF9u
+yaUiJgyTH7AjuCDO01jvj8GT31cfNDBMBwjQF0AltsGScZhanwy82fHUZzvpHMr6
+OQ+riBwb2rXKHoSCukxbs/Y1HfPxmpNShWDPXFFMbsujPRT6meVcCKQuThIWLdwA
+KvJYSYC3gTHQyadjwTF9nLZgMu6cWxTheWXXZ/sF4tZ1DPQCjd/1Pdi/TwEawAUa
+vOHP7ArfB2vHOX59bJgJbFyGB3ECAwEAAaOCASYwggEiMAkGA1UdEwQCMAAwEQYJ
+YIZIAYb4QgEBBAQDAgZAMDMGCWCGSAGG+EIBDQQmFiRPcGVuU1NMIEdlbmVyYXRl
+ZCBTZXJ2ZXIgQ2VydGlmaWNhdGUwHQYDVR0OBBYEFCOojCEbuBGgdyxoUfYTEyYU
+ioxGMIGIBgNVHSMEgYAwfoAUxTAm/Gj7/9K32+Wdc0BOHFKRFeGhYqRgMF4xCzAJ
+BgNVBAYTAlVTMQswCQYDVQQIDAJDQTELMAkGA1UEBwwCU0YxDTALBgNVBAoMBEtv
+bmcxFDASBgNVBAsMC0VuZ2luZWVyaW5nMRAwDgYDVQQDDAdyb290X2NhggIQADAO
+BgNVHQ8BAf8EBAMCBaAwEwYDVR0lBAwwCgYIKwYBBQUHAwEwDQYJKoZIhvcNAQEL
+BQADggIBAHJmrqebjeI7dz34cJBZH0iKTv/dHqinck4u2Dnol85SUICDAlIk1ZDm
++VHA7ZH3ittPjWbiR8N8CJ+GW+2zfcenM+9BfCm95FJ8K/4vU9Xrx/NZH621NELm
+fneD/rFWahf+KT9J7H9SeR3oIiecsDEDM0RAFrqU3innLAnWoTKDNQukjBGUrTnm
+3YPv6+MAUHl1AaZpX4yEtakevQHxY0Kfpt0U1iZbvL5jeC9HuswTFCplARI5qnxG
+0RhRveApQ6Im0clUKx8eqG2Iez4clSNLGJEsUpvyr3CwbyOU/9UneK98hbf13rww
+DPoYT1U6JMEJuKBuL1qDECH8UUF0X41KEPP9s+dgBcAXE/gaD89hjIzOhbkDXbLO
+L8511Fr466Gcab05FBGupXjnJ63EB3Ct4TAkRS6W8IrOtWRPOtOCbRJtSKqcZnfE
+F8UCklCfIHaM7y8JClVLWSIjaOtg2UVJqCJnEMo+5h4WLnkGfBZr7VAJRKPKC3Vt
+jfKbOUcWcMJxR+UWWu+9A/kMb97cAXuSwZRyeeKAnMzQHWYMx6Bo/m2JHWwhlsf+
+vX6mp4C+FeyoXejP1cZBVkMh1JsRKWHAxbGLQkrYHhTKwYudLvsXURatJ0i+BNjI
+QmBTKAfIh2q6qJDRcsDURDsvBD46f2p/kzg08+f5eQv+cMx2ryAq
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIIFmTCCA4GgAwIBAgICEAAwDQYJKoZIhvcNAQELBQAwXjELMAkGA1UEBhMCVVMx
+CzAJBgNVBAgMAkNBMQswCQYDVQQHDAJTRjENMAsGA1UECgwES29uZzEUMBIGA1UE
+CwwLRW5naW5lZXJpbmcxEDAOBgNVBAMMB3Jvb3RfY2EwHhcNMjEwMzA0MTEyMjM1
+WhcNNDEwMjI3MTEyMjM1WjBZMQswCQYDVQQGEwJVUzELMAkGA1UECAwCQ0ExDTAL
+BgNVBAoMBEtvbmcxFDASBgNVBAsMC0VuZ2luZWVyaW5nMRgwFgYDVQQDDA9pbnRl
+cm1lZGlhdGVfY2EwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDXcXvt
+kyiEY7Nr8VeEF2KTpGkEwPLNoLW9eNpFH0bFlKcmM/+IocSUErD091SCf0fGCRuo
+8bISb4MVa5esq8XMUSR63cDmz2IbWOtvNir4wLfAoUuA4JBhubaSyaslXLf376QT
+sYDjLH9jQ3rFYskz9hrlX1HFFmm0hlDnuqr1w0GF+6PxPdxRKkdvKexPuQp3qaVZ
+dzKvFcGuCu7nuqemb37CBBkdRAgVUj37pXBIcc5p5h8PVAU24r7pAaYppDmmZMWa
+uTSjz4K/PTh5GzG+snf8iH+EpTLGUqPElR+ABP8YiNrQQzgA91lPjwLqp6D34sMT
+7xvk4Ri1cOpOsNA4hCdFPilzolMQ6Zpz0ELI25vBt8qY57JMlsUjaY2PR1gI+pE+
+jc52e18Bt/axNnbgxoxTQWPcw27mUs7H4+1WiZufhzz59obgWRnoCom0Fb6RN9Rl
+8ezl+h30+Dgk8ftiFm/fI1BttL6dihveSP/xvuMYRFyT0F1ZNZhgME218cOB5hZN
+dKOFynRgI4SfCeMNSy3KnrBoPYE3P/f1ljBbrR5x/xQE0V5iWFJwZwWexO0+Hf7h
+Aaql5dcwsMIjf8MfHKuQOfZauUmPxu0EbM4NiQu5GEK/9rGEIO51Tlo237l6k4tF
+oKCj3EUZ9cM02CROKGDM6vfkyeyGDbuDPGmdLwIDAQABo2YwZDAdBgNVHQ4EFgQU
+xTAm/Gj7/9K32+Wdc0BOHFKRFeEwHwYDVR0jBBgwFoAU9NE7mu7p9CqGxLNWl7km
+VfMeEO0wEgYDVR0TAQH/BAgwBgEB/wIBADAOBgNVHQ8BAf8EBAMCAYYwDQYJKoZI
+hvcNAQELBQADggIBAKFvNX1Wv7lOsYvDGOCmIrJEDdjW2Q60p23v1U/R9Wv7xo7X
+2SRuQvqKd3AB/9dCSgaaXKHwYgTPIS8NwUJ0SMvSwrnnRpZS5qkOB9JgRgAX5Ebd
+eyupB2AumZ1BGaw2gqPYHm8zxu3N2yw2pVV9LJ2nM+IPTqiQrYCV7BxNpAd/v9OA
+EC9XbKhPqdJ4bD6dGg7w5iBPadb6amAKkGutKjjB+AC/lJlM9bMEGd6RP0ywptQx
+jAfY0VTElLsN30Q6pn31Xf4UzZk4xzyW04GaPFcJVoHTWSl969p0k0L/WAMakDHB
+/g4VvkMTFDoH1Mi7ohakHnMC9XQbMVj2t/EE3XLiD4gcNEyCjXczIxDYJRYe2X3f
+51vQNR921P1KUNTooGusltMmHuWBnT046o9rp/2uQvHm2y/qv1kCPHTiP7vhb/TG
+2JCc+3LZ621EjH5jRvL60Pji4RnGGqLDBykLK68dymHVfrSAi+ZCx6PNxSm0Ydm6
+ZM1Vb8lD2EwEm20qKWM484ItWcVHgWEWDvaMjh0iIq45LA0KmN47iUN8X6rmdulZ
+MDSnSYwJfRt1DdyUC0nDWMQaW1JOQxQxoJCoDmiLwv9BIeNB8LNJEU0FTOPc8xhf
+VdlbjNIC1fs2OMWOc3A1hAFlf+vU8UYLRgYhLiAhFT2iwhBksSzGURY7eKqM
+-----END CERTIFICATE-----
diff --git a/kong-versions/3.9.0.0/kong/spec/fixtures/ocsp_certs/kong_clustering.key b/kong-versions/3.9.0.0/kong/spec/fixtures/ocsp_certs/kong_clustering.key
new file mode 100644
index 00000000..77e81fde
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/fixtures/ocsp_certs/kong_clustering.key
@@ -0,0 +1,27 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIEpAIBAAKCAQEA1oLJl4nEWiCSIgGM0FNlzO06xb/y9+WPMr+bpiLnz2FutPDY
+KAMYGX7c+eXcADxuSkAbROXROMHeH+GKPljCil390MR40CGO+UE2IMzLZw33e3de
+8bKnvDiEX27JpSImDJMfsCO4IM7TWO+PwZPfVx80MEwHCNAXQCW2wZJxmFqfDLzZ
+8dRnO+kcyvo5D6uIHBvatcoehIK6TFuz9jUd8/Gak1KFYM9cUUxuy6M9FPqZ5VwI
+pC5OEhYt3AAq8lhJgLeBMdDJp2PBMX2ctmAy7pxbFOF5Zddn+wXi1nUM9AKN3/U9
+2L9PARrABRq84c/sCt8Ha8c5fn1smAlsXIYHcQIDAQABAoIBAGXOrN6/A/HCg5ig
+I7S74BTigoJYF3iP+uabCcRPzLUgCOrXY7+ZuFZhX387GK8D/1Q+GLMaX7IQUNvQ
+r0vn1GzXLx9mH/Cn/LNPv+DRUbgXaN2wSd9say9po2mnqww0qNpO+TsfuMPZZXVQ
+PWoiRF2U8a/6ZVxJZr+LJrG4TzF+8gyHoUJrlncob8ma5EQKOR3HzMxfJx9OrjQW
+ISu+g2D+0qpaiPGlEUOMKBnrFhVCd5LUaCKM1F7qTe08hvyywqp7CJ4rw2loa+4W
+cdl2UTl01lTke3uEPsBdtvpwQ0DAvFyXgA09LmnwRjHtPzHjNxnkGE2qz14sctBi
+OXt2KAECgYEA+qGxJ5tYkqob+JTvrAQp1zD9ECs9ElVbJZwZ5Z/lhxMBJ07v11Ku
+++M9rSUjhWcYbd2gfGEkxXzSK9yYc4ryzDvCREuNmGxYs52VnaBlKPY3T/h046/9
+S0NivzApCTVK+CYdntT4XNyn9+WGO7zq7x6FQkSsFuj2lnfHrahq0i0CgYEA2xsI
+KMYMe0NTJFNzhfFQMzkSU1R1+TvhaXjpqfneeizF4plYxrZOtOb3vzriWepB70de
+4atsoxZUfqS34RKkLX1WyuoLm3WtpJHHmhUfj18PlIMu0gXrisUZM8evltTOyRsg
+mn+V/nZeXn34tZARbJ4rAMrmOKIz/z0OCtZ6yNUCgYEArb6ZiNNwO3whl9nnrF/W
+gY88X5EZ7TOu1Au7CCwoedL64b0fFy4CkCuf/f/Y+AnYLZGOR6swSpeVO0LZjH+u
+gVaL/bxClH/HnfyIU5V1i0fkYFPk9FJ0TVCRi+hfCjsflZcWwZzx764n4voCbDcy
+xkFqL95bTiaBix3OFtzB8KECgYEAuyhbDuEllkELCxORsY9Qz4Bnq/CQmWXSBVM4
+XW5H4RrPqeENWSgvEQ3eAGZfJSkaSzcu0BurP5/6avdu7n4K6aSP9+J2KcQaoGG6
+G18Bx2kPGO/5lYNjEPWNspJW5cNAI77dWbu0N1mLALIgOY8nox10ZEfs4eGEAvl3
+PkC5P0UCgYBh1qnXWvj5KT0pt7p2X7ayg2FHunNHO1QLpFBWhhgQlyvLns/toQWc
+XXKogwiMZ8D6g3eex8vZ25K01JNn7uQUDUNVhzyUcSjfVFB1Bc9dLdNfIYvL4adz
+BTZ7TjBYdScSIhjHKbaLwimHcNllYqz3vJ6hAK9YFVt5sI+/EixHmQ==
+-----END RSA PRIVATE KEY-----
diff --git a/kong-versions/3.9.0.0/kong/spec/fixtures/ocsp_certs/kong_data_plane.crt b/kong-versions/3.9.0.0/kong/spec/fixtures/ocsp_certs/kong_data_plane.crt
new file mode 100644
index 00000000..4f30d968
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/fixtures/ocsp_certs/kong_data_plane.crt
@@ -0,0 +1,62 @@
+-----BEGIN CERTIFICATE-----
+MIIFOjCCAyKgAwIBAgICEAIwDQYJKoZIhvcNAQELBQAwWTELMAkGA1UEBhMCVVMx
+CzAJBgNVBAgMAkNBMQ0wCwYDVQQKDARLb25nMRQwEgYDVQQLDAtFbmdpbmVlcmlu
+ZzEYMBYGA1UEAwwPaW50ZXJtZWRpYXRlX2NhMB4XDTIxMDMwNDExMjQyNVoXDTMx
+MDMwMjExMjQyNVowZjELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMQswCQYDVQQH
+DAJTRjENMAsGA1UECgwES29uZzEUMBIGA1UECwwLRW5naW5lZXJpbmcxGDAWBgNV
+BAMMD2tvbmdfZGF0YV9wbGFuZTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
+ggEBAK8wCJuLAIZa+hihNEOx/YBSx+05lXXgoNirVuJjmUhx80oZQsrUnCA3PPe0
+snkUfUTpe0g1P1YPMDQBoXK+MffpanTL2e5EIkD+T1ti9EkTZg+jnjdGaAZ27Y70
+9k6KTb/rFj1Lezswdo86WlXpxcbCFyHlMO590pCPpQ/VpQodqn9bTPPoTKTHlL4q
+8no26rb16t7wBVrbADOu7lzcIZYB2xLslM5B8fk7jzIBPMb3uQxh+AhKn2bw07jv
+unPMHJK64alfUwqRk9krd/1WICSm51eKi400kefrtzXRwtxjr72EmOCnZdHr2A0O
+7ZKlHhZolVXaACghMd4IRI/eUD8CAwEAAaOB/jCB+zAJBgNVHRMEAjAAMBEGCWCG
+SAGG+EIBAQQEAwIFoDAzBglghkgBhvhCAQ0EJhYkT3BlblNTTCBHZW5lcmF0ZWQg
+Q2xpZW50IENlcnRpZmljYXRlMB0GA1UdDgQWBBSpSKxdiN8o9qYMOy158lXYg2MI
+qTAfBgNVHSMEGDAWgBTFMCb8aPv/0rfb5Z1zQE4cUpEV4TAOBgNVHQ8BAf8EBAMC
+BeAwHQYDVR0lBBYwFAYIKwYBBQUHAwIGCCsGAQUFBwMEMDcGCCsGAQUFBwEBBCsw
+KTAnBggrBgEFBQcwAYYbaHR0cDovLzEyNy4wLjAuMToxNTU1NS9vY3NwMA0GCSqG
+SIb3DQEBCwUAA4ICAQCxdljA6Yxg7DLCs0RDZwzjHf4/H7SO888v7Tad+mbQcIzI
+dzxEaAcXf0qvDsDEPcE8n3vKDC9kHm3wKFJqK04Clc6Su+BLvGwVO0TTi9yC5X0j
+OFQQQAeth6ByJh7fqXkY4qkER7aunN77tpdmz4/m19we8U3DO/oQm87Fu89l6hMH
+942rpu4uSz2J0d+PpnXulLOJx0xLWv8ARmJkGD8oWUrVMmeeq9q1Yz41Oyyf37Xn
+iGUMLC1ejDTBw89wuMuqD9smka9stMdC/7mQWJJqz/Ww16MqGwqLvcK2WZzvU6jE
+V42n0Zdq/rnPV63B/NZgwGEpfqWqZj5K0NfjboCoRmS70vWurFlP/oeaYZBoCoUW
+cMiw8lnS53fFtX5Mt8gV4NLzoy5a4Q6qoZMzuudcabmEKMNONBp8phkqosSgkDKY
+wJvhK1mYdWf3VcX2mjyW3j/shTXlKibesNZAR2XiKqEFqTkqFY6Dx+wpvsNIyvHw
+ZWLwa71ZONVhVgt5Hu6w/u+hzrL22v/s9ticVx1jJ6lopppiXf/0Ex4EHjZI5h3w
+Sdj2fCBsv05FWJqFadMY6gt92/pmyA1HL7S5rK5odoDviRGQxsCvBax2Vv4WDrIh
+tcGGGUZ4nLeWPOqb9e8fJKJtILvQ9x4qRMmeYKMAkflsbjDNw6g612D3TV2WXQ==
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIIFmTCCA4GgAwIBAgICEAAwDQYJKoZIhvcNAQELBQAwXjELMAkGA1UEBhMCVVMx
+CzAJBgNVBAgMAkNBMQswCQYDVQQHDAJTRjENMAsGA1UECgwES29uZzEUMBIGA1UE
+CwwLRW5naW5lZXJpbmcxEDAOBgNVBAMMB3Jvb3RfY2EwHhcNMjEwMzA0MTEyMjM1
+WhcNNDEwMjI3MTEyMjM1WjBZMQswCQYDVQQGEwJVUzELMAkGA1UECAwCQ0ExDTAL
+BgNVBAoMBEtvbmcxFDASBgNVBAsMC0VuZ2luZWVyaW5nMRgwFgYDVQQDDA9pbnRl
+cm1lZGlhdGVfY2EwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDXcXvt
+kyiEY7Nr8VeEF2KTpGkEwPLNoLW9eNpFH0bFlKcmM/+IocSUErD091SCf0fGCRuo
+8bISb4MVa5esq8XMUSR63cDmz2IbWOtvNir4wLfAoUuA4JBhubaSyaslXLf376QT
+sYDjLH9jQ3rFYskz9hrlX1HFFmm0hlDnuqr1w0GF+6PxPdxRKkdvKexPuQp3qaVZ
+dzKvFcGuCu7nuqemb37CBBkdRAgVUj37pXBIcc5p5h8PVAU24r7pAaYppDmmZMWa
+uTSjz4K/PTh5GzG+snf8iH+EpTLGUqPElR+ABP8YiNrQQzgA91lPjwLqp6D34sMT
+7xvk4Ri1cOpOsNA4hCdFPilzolMQ6Zpz0ELI25vBt8qY57JMlsUjaY2PR1gI+pE+
+jc52e18Bt/axNnbgxoxTQWPcw27mUs7H4+1WiZufhzz59obgWRnoCom0Fb6RN9Rl
+8ezl+h30+Dgk8ftiFm/fI1BttL6dihveSP/xvuMYRFyT0F1ZNZhgME218cOB5hZN
+dKOFynRgI4SfCeMNSy3KnrBoPYE3P/f1ljBbrR5x/xQE0V5iWFJwZwWexO0+Hf7h
+Aaql5dcwsMIjf8MfHKuQOfZauUmPxu0EbM4NiQu5GEK/9rGEIO51Tlo237l6k4tF
+oKCj3EUZ9cM02CROKGDM6vfkyeyGDbuDPGmdLwIDAQABo2YwZDAdBgNVHQ4EFgQU
+xTAm/Gj7/9K32+Wdc0BOHFKRFeEwHwYDVR0jBBgwFoAU9NE7mu7p9CqGxLNWl7km
+VfMeEO0wEgYDVR0TAQH/BAgwBgEB/wIBADAOBgNVHQ8BAf8EBAMCAYYwDQYJKoZI
+hvcNAQELBQADggIBAKFvNX1Wv7lOsYvDGOCmIrJEDdjW2Q60p23v1U/R9Wv7xo7X
+2SRuQvqKd3AB/9dCSgaaXKHwYgTPIS8NwUJ0SMvSwrnnRpZS5qkOB9JgRgAX5Ebd
+eyupB2AumZ1BGaw2gqPYHm8zxu3N2yw2pVV9LJ2nM+IPTqiQrYCV7BxNpAd/v9OA
+EC9XbKhPqdJ4bD6dGg7w5iBPadb6amAKkGutKjjB+AC/lJlM9bMEGd6RP0ywptQx
+jAfY0VTElLsN30Q6pn31Xf4UzZk4xzyW04GaPFcJVoHTWSl969p0k0L/WAMakDHB
+/g4VvkMTFDoH1Mi7ohakHnMC9XQbMVj2t/EE3XLiD4gcNEyCjXczIxDYJRYe2X3f
+51vQNR921P1KUNTooGusltMmHuWBnT046o9rp/2uQvHm2y/qv1kCPHTiP7vhb/TG
+2JCc+3LZ621EjH5jRvL60Pji4RnGGqLDBykLK68dymHVfrSAi+ZCx6PNxSm0Ydm6
+ZM1Vb8lD2EwEm20qKWM484ItWcVHgWEWDvaMjh0iIq45LA0KmN47iUN8X6rmdulZ
+MDSnSYwJfRt1DdyUC0nDWMQaW1JOQxQxoJCoDmiLwv9BIeNB8LNJEU0FTOPc8xhf
+VdlbjNIC1fs2OMWOc3A1hAFlf+vU8UYLRgYhLiAhFT2iwhBksSzGURY7eKqM
+-----END CERTIFICATE-----
diff --git a/kong-versions/3.9.0.0/kong/spec/fixtures/ocsp_certs/kong_data_plane.key b/kong-versions/3.9.0.0/kong/spec/fixtures/ocsp_certs/kong_data_plane.key
new file mode 100644
index 00000000..79ea99e4
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/fixtures/ocsp_certs/kong_data_plane.key
@@ -0,0 +1,27 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIEowIBAAKCAQEArzAIm4sAhlr6GKE0Q7H9gFLH7TmVdeCg2KtW4mOZSHHzShlC
+ytScIDc897SyeRR9ROl7SDU/Vg8wNAGhcr4x9+lqdMvZ7kQiQP5PW2L0SRNmD6Oe
+N0ZoBnbtjvT2TopNv+sWPUt7OzB2jzpaVenFxsIXIeUw7n3SkI+lD9WlCh2qf1tM
+8+hMpMeUviryejbqtvXq3vAFWtsAM67uXNwhlgHbEuyUzkHx+TuPMgE8xve5DGH4
+CEqfZvDTuO+6c8wckrrhqV9TCpGT2St3/VYgJKbnV4qLjTSR5+u3NdHC3GOvvYSY
+4Kdl0evYDQ7tkqUeFmiVVdoAKCEx3ghEj95QPwIDAQABAoIBACkcGXj+pnHg2X18
+HrqgAv/g7R+C+sq9mqEdm/bmLmssqk3CHcVhHP4GWF08XwFAyKCqNY7dR+6XA9XA
+aDV34lvtv1iHGa3q+SrNQqwMTYz0a2fSGmeYMwMJV3fLjh0iIVqe/QoHM3TRS5ES
+vW4ZvJqGo00F7nSYvBfGTZKorODxb3CIjFXTlJZ1u/+YDVswWv3+XrqXKponoedr
+Zl8SCf7iqLz6cIPGnx6joIR/e7LK9eDBfgV8bxfsyulby51f06V/cBTQk4l8Qjeb
+Z+iFJzZxDuxq219JLWYqKH/JIAchvPoov1PBfEZXK4fKunAR/mw6j4OL/X5H+Dj1
+ziFjbyECgYEA51NHPMiChIRJ4poaTE99CPPcJek3rIAP83+BSRm0e38hibfB7p3C
+FpPhtWlMMM6YRAJsVkYrLWTtdl2nZbw3AuH46MM03nTbEgueQ2ry4hofzUKQfe5Y
+VyQccFQvQx1XF8lFML0TIEZ1ID38G8oNhme/fk5eHsR7Bn8Pi8XlpY8CgYEAwd/S
+qbTph05yCTYGeqqsMh+hUq9oqLvcYJDd7lStJjLlt6b8jEjZspePTHTtcL2vOwx3
+hmA4PQR2Rnc4M4nl8zMHSySk7m7dR9w01uORzk2BzWb2XHy+SdtwFWS+2bKJBWuf
+DAtlQzvfF07ccxZfQQTjMGVkhnsDMinriWCxMlECgYBJTRNSyHrLQRwkiQ5yRfHq
+B1QoUzmIGOB1GV8/abzOMV/QQwFZ+nWJL/0iviYdhSmsy1PHFt8RuFyi2FR2IWkR
+Kcf1Af5by42rrzDMTjR+vyZ6pXAh54fovRGh6ps7Wi3B5M5e/lr0LD9rIxkjOSiG
+AZQlkvGyMDKHwXWMpf36MwKBgGDMslBNpfQK9OEoel+w670zEcdJEYZ+FfCZJFYl
+LTbPXuctlxcsIJYNGl1gXFVYQC/Jb7xGOo4stilEyWjiR1AAgHnCWB88d3uztSY+
+BcTt6gt2hzdyiUgzKmlkHe5wN/3e2FCZN/wz3pWyqFtGJlU+bXjyhximPthDGflD
+r/WhAoGBAKFWK2lmVTiChupq3nihccggW0Dvk1NBLF+OTOGdkPDmNhypMJ7e1OhE
+4KYHCmGKFPvg1M0+CQzqop4lxTzFz8NI/Pt/HkWbkbmRyHE2p2cUY4zGIfF9/nwq
+vS/uKrJbHMqXyu/pa3HzmFtWrMoXd8/yCdSGwaNDK4ZCiP+hVMQ3
+-----END RSA PRIVATE KEY-----
diff --git a/kong-versions/3.9.0.0/kong/spec/fixtures/ocsp_certs/ocsp.crt b/kong-versions/3.9.0.0/kong/spec/fixtures/ocsp_certs/ocsp.crt
new file mode 100644
index 00000000..21930086
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/fixtures/ocsp_certs/ocsp.crt
@@ -0,0 +1,33 @@
+-----BEGIN CERTIFICATE-----
+MIIFpTCCA42gAwIBAgICEAAwDQYJKoZIhvcNAQELBQAwWTELMAkGA1UEBhMCVVMx
+CzAJBgNVBAgMAkNBMQ0wCwYDVQQKDARLb25nMRQwEgYDVQQLDAtFbmdpbmVlcmlu
+ZzEYMBYGA1UEAwwPaW50ZXJtZWRpYXRlX2NhMB4XDTIxMDMwNDExMjIzNVoXDTMx
+MDMwMjExMjIzNVowWzELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMQswCQYDVQQH
+DAJTRjENMAsGA1UECgwES29uZzEUMBIGA1UECwwLRW5naW5lZXJpbmcxDTALBgNV
+BAMMBG9jc3AwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDOlydfksGd
+jK5CI2yNdsqpA9/Zr6eksPE0BOkbb1LdrqNyI2pRw9D8tpEY6AqaaYwQQyVDA54U
+BKE0L/PiqpACm4nKWv1XNsRK+REhEw8V4aqgkt8oyVz2w22mXq+DH8+iCmlpap1N
+ZfLXpKz0ZS47uvhFscs3N8bohWI92EHrMxp3JKbmWdoE/NnyAF9wV1WvYpfdpcDT
+BKwxO7lW7cgIB3kArtvGLLrtkVhR/js/B+Ff9CLugImGrNnSXfiXOMeLhui1U4v2
+aYEM+BN5TC8PTIoLwo96SRoBnZBoZ215liJiF3peVQNnR1NCYmJ6jQjtBXC4/wz9
+ganFdYF9+WSzSrBHiwIe7Nn7ARdRAtJPvOUBvaj3/zNpNCfikqcvGSTgJ1ixw0oO
+8o+UvWThQCGfB34FkG3oAl0y7SEpFKU6+8IWqPoM7Kdm0ZFUKXA2G7RNl5gH/o/B
+qVJyx31OvvZZoc3OyTInRpxNdhrWRaJppYw8xxv4mudedf48CToFGQjsWumVkjlU
+VdPSVP4VbgrOeVwwas7YBONES7oqkKnvjmLHqAYdalMLyopSuvnb3X96Fp6L2Oms
+FuNo6/7AUBVQtm0I08uCRWhP2CPeca1fERgTbO/puECMW3XqNAhyBB5e20uxcB/E
+h3qgu4y2xcn6Za1aQ30+RUB5n7DST0odEQIDAQABo3UwczAJBgNVHRMEAjAAMB0G
+A1UdDgQWBBRnqkgve+lZRPAGhX4AwHIMJl++gzAfBgNVHSMEGDAWgBTFMCb8aPv/
+0rfb5Z1zQE4cUpEV4TAOBgNVHQ8BAf8EBAMCB4AwFgYDVR0lAQH/BAwwCgYIKwYB
+BQUHAwkwDQYJKoZIhvcNAQELBQADggIBACuoaNr7uVBIfDFo6jdLqtiVAOKsUxO9
+EDoBIpGGiLOk3/NZxKUG2+xhsuAwZxPIVxifkg64qlLmMzZMrWFzOvkvRDYnU2se
+s/1sbOC3h+Xm5G5HjRhwmHczXUljyZySz0m8UHWeJ49zkDVIGzEBXrRnzBtji1N2
+9PddIz8zhqMtP33nKTo9m1kkkdoA3cZ/fcM21doZ6+ZimtRcOOz7BgQLOwPupq0L
+9DxBjJYwPrXj5IRaib0rZQ+kdjPNgggCryvJCk/27dKAwFe4rWLmFYQ+fgY2N2DL
+djXtxDxZ8Gw3x+GM5agI/BUhTscx4AvscZZr7brSPPmW5Q8nAE6NJQtanuT0VCuU
+VoRwNuTs0w4uTXyS7TwXDvfSrQqQLI+O7BWDnJT02FYmakT5CFsf7zqJzsbhSqq7
+11qK32MBN6q7QvH9SZi6A1jK2UgGiZSCZxF8OFQGJxaf5VBL6naP2NlPSeCZUZ5X
+eWVqE/lXi4LLUIWTwGdjbfkY72FFWThZoxtS+lM/CGVjVWS9gwABL+jiirZL++qQ
+y9IzzULMyxd6Xl3/eEzwT8kYjgwUQ2KWnjaHSBxHssJiRyHUhl0cUXuLGiW5fsHE
+TG6WevipP7qdOiIttLzFyC60pLR7v+vW5VrRXGR1kzou5N1ESi/ixl7PY9fg+wp0
+cWEwPQGHYdE/
+-----END CERTIFICATE-----
diff --git a/kong-versions/3.9.0.0/kong/spec/fixtures/ocsp_certs/ocsp.key b/kong-versions/3.9.0.0/kong/spec/fixtures/ocsp_certs/ocsp.key
new file mode 100644
index 00000000..5d0bf2cc
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/fixtures/ocsp_certs/ocsp.key
@@ -0,0 +1,51 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIJKAIBAAKCAgEAzpcnX5LBnYyuQiNsjXbKqQPf2a+npLDxNATpG29S3a6jciNq
+UcPQ/LaRGOgKmmmMEEMlQwOeFAShNC/z4qqQApuJylr9VzbESvkRIRMPFeGqoJLf
+KMlc9sNtpl6vgx/PogppaWqdTWXy16Ss9GUuO7r4RbHLNzfG6IViPdhB6zMadySm
+5lnaBPzZ8gBfcFdVr2KX3aXA0wSsMTu5Vu3ICAd5AK7bxiy67ZFYUf47PwfhX/Qi
+7oCJhqzZ0l34lzjHi4botVOL9mmBDPgTeUwvD0yKC8KPekkaAZ2QaGdteZYiYhd6
+XlUDZ0dTQmJieo0I7QVwuP8M/YGpxXWBfflks0qwR4sCHuzZ+wEXUQLST7zlAb2o
+9/8zaTQn4pKnLxkk4CdYscNKDvKPlL1k4UAhnwd+BZBt6AJdMu0hKRSlOvvCFqj6
+DOynZtGRVClwNhu0TZeYB/6PwalScsd9Tr72WaHNzskyJ0acTXYa1kWiaaWMPMcb
++JrnXnX+PAk6BRkI7FrplZI5VFXT0lT+FW4KznlcMGrO2ATjREu6KpCp745ix6gG
+HWpTC8qKUrr5291/ehaei9jprBbjaOv+wFAVULZtCNPLgkVoT9gj3nGtXxEYE2zv
+6bhAjFt16jQIcgQeXttLsXAfxId6oLuMtsXJ+mWtWkN9PkVAeZ+w0k9KHRECAwEA
+AQKCAgBz7ytvXQI+kfYws4R1ltaAJuZ2WTbxG0Mg+CiA9uY/9YNPyEQgAo3DZAjl
+O0LICLdLYQMGKn+JqFd22/o3l5Qdgn+/CXTmfpuFn2RXdUSf+PYyCnolf2smJ+He
+3YANS8rPmpwxRl1kU/QFxCozNJzPdEtjgTUTlb+QOVo6bqP/g7w0ZGMtHftVlTgR
+sNfeSYSSWffzsNMXGKYxMtz9xY7dwqPLGFXJTszQCSLRUKSa6Kc3m+AGjCehZlsO
+zSF2a6y/xkPNjkcbT3XWe1kiVviJ02Ac3WB7NY7cnTmu/WvYMcK13YsUaQzx5nr4
+5BFzyLXbnZP2nVsC4MMPRrQWp+A0Iwu8TJVrb5tUhEoVXGkkj4aUc6awX9g8OTii
+5JhQ2le2BazrCWCXtIfrhbcPyORyGizHqtzXqqVbtLUU6AgRyscWeIFf7v1nxP0K
+PgzFwzTMT8CH4t/CnkV4S9blj+S3JZY+MrmcliSAVz5+45mY3h7+A2vvMrBFnwiw
+5273HZyOCcRdfyufuDGt6vaAC+pgnRuno19i+Q7Mfsp6W3HiutfuNXJwG4YXTLba
+JL47QzOXO5DiJ9AczKo/c0lXMw/K/OkcV7QB5qi+9ynoY42sQFdin1mNW03KwZru
+Yo40wkXfAMAX/0i0dAKmf2ubG8/g1YcHg+NIAr+HQ6SjLuukYQKCAQEA82vIpCt4
+0iW9uOvvF6PpB/PwnUKTwjJYtVlk92TJ/zNhW50MylMMk5Hj4NC2rbH4yBgjHxAn
+jyhYqVi+mrsqidZGXgzmDuS19moqikFV70gFuaf+HbJN4ow3SbvTd5dv4Vv7UKbc
+v/jblLM3Zx5kNBZNP9hoo65o7kywcH38lCxOOr4RheJOCUL0YZmGd+S9BFQgfbur
+dITTHJ1t4g5zYFSevPM+CbkEIUWgOZrdqjhxGsH1SVTGtzR5qwzWiG3tPKe0nwWb
+gejPDrMCzYJm2kd01/WRmkqZU/sAJr7R1iQzrwe9PJmH9BOezyfYremieXqfD4xs
+t7OJD1lxutb//QKCAQEA2UQjaISYnwyVYQPSBiS4FiH5Cn5kTd9jX33Qxy/QUbHJ
+4MaKNq5N6hwb0nCg52kZdOCzLqpX6wVAxHBL3ouKFYFHVk0b1oaoGMb4pxx5EnEZ
+0z18VH+VgfluZH5/ARRwwlB40naqGQq5XlRL+xCm0lcnkqp2/Ie86qwaO+vyYUf0
+L3BcshuWjbVI1aPS81j5lelxpZwBOUAm//tNyPV1KJDRhjV784MxcpH7lNgtrRVf
+4woAZnEu9OnAZcoRHm7IsWnwu3lH7h7rU+WMy163dztKzEzZ6fTZYFemyZV5XQ4N
+q1FwQkav+puSMKZWB6atORY6GormpMK7VZR1XhhLpQKCAQEA0sqThRbgGZr1IB2v
+fhlCwtBLnOL6cUCH8QLonBN7mLM1q8/kM5CXY3MCkrwqdV+YwC2mvE+Q8jdOD9f5
+tqQ9wf78EJW640rLCAgHrpHFiOAllRAUzkKJj5U8i21LQlSxXcX5a24T22n1PF+1
+qmZ2/2QQoSkV9CgkVbezUrbG8skrNVNCeV3vlbWVSq9X8prx073GJRtO7ifXaQAr
+F4bMAq9Ehvtcza6aFPXmOfwR2EXoK/OqJUZ0jlGyypzjamFG/y97CfohH+4q39/E
+nZI+3ubiF+FfpOzUuhSxnNvBel7/IqLhDIknYgVbkKhAytl3CRtWgnBn9OxT1Cbw
+hYuJQQKCAQBVXL0gsoAYdWQ3cr3Q5hphr8VeRxx3sB4mBZPCvtl1T4oGw1rIcyFv
+qs2Pl+rQIO38itA7tHfIgg7ZX1mfvWlqW5nAoZkfZ1aiLYLCfaBgC4nfAhhYRqxi
+HbMuzrhtny9SWTWvUyovnpQIKMyVfwxcNhv5Nvp664XhGe9QvbpEWHXrMZVp8Qbs
+9F4CelRGgh3FtauOKsYcTUVFa+I64529a3C270qc+V2zKwISkAEaMPy0glh3515Q
+oYqTM5oYP+SgOAR6VANb3lANbXIs8TDaKrSPol432piRjr6cExtU4VGjjuKxV36K
+0xbUAHZqmSUT+dSoWwyVjWD3FdYrOxZ1AoIBADwwUIdheYJbVVlcRZclm1pDoVCB
+bzh57GLKQ7KLj+gGp2AoizUKRELLKI844HZ70d2hghEcWei0sfzExRGq61yaNfHa
+lf3SiS6eJ7ivRHWwtrUXTOfO5LcVGzVLp4TMXvl4uZMrHVSB7vGJsDpoRaCK8hKf
+/f3d2lPRWcRQU9Gyc4hQE6daH0pVxrwqnWjmPvf9AIxs9vf6RVGR3y3dyccJeiph
+vC2sZv29dDlfWHSBun0vZzd+Xk73Qn3hSMM083FZrJWhqdzaOA0NfpdYgVxfn5Q+
+B1BYbv02WurCQwdWsCiDiLrXEc4HQT/fY+cV41fBrE2Kb4g565qd93Rh80w=
+-----END RSA PRIVATE KEY-----
diff --git a/kong-versions/3.9.0.0/kong/spec/fixtures/ocsp_certs/resp-good.dat b/kong-versions/3.9.0.0/kong/spec/fixtures/ocsp_certs/resp-good.dat
new file mode 100644
index 00000000..0004e5f8
Binary files /dev/null and b/kong-versions/3.9.0.0/kong/spec/fixtures/ocsp_certs/resp-good.dat differ
diff --git a/kong-versions/3.9.0.0/kong/spec/fixtures/ocsp_certs/resp-revoked.dat b/kong-versions/3.9.0.0/kong/spec/fixtures/ocsp_certs/resp-revoked.dat
new file mode 100644
index 00000000..9744f11d
Binary files /dev/null and b/kong-versions/3.9.0.0/kong/spec/fixtures/ocsp_certs/resp-revoked.dat differ
diff --git a/kong-versions/3.9.0.0/kong/spec/fixtures/opentelemetry/otelcol.yaml b/kong-versions/3.9.0.0/kong/spec/fixtures/opentelemetry/otelcol.yaml
new file mode 100644
index 00000000..a15acde8
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/fixtures/opentelemetry/otelcol.yaml
@@ -0,0 +1,32 @@
+receivers:
+ otlp:
+ protocols:
+ grpc:
+ http:
+
+processors:
+ batch:
+
+exporters:
+ logging:
+ loglevel: debug
+ file:
+ path: /etc/otel/file_exporter.json
+
+extensions:
+ health_check:
+ pprof:
+ zpages:
+ endpoint: "0.0.0.0:55679"
+
+service:
+ extensions: [pprof, zpages, health_check]
+ pipelines:
+ traces:
+ receivers: [otlp]
+ processors: [batch]
+ exporters: [logging, file]
+ logs:
+ receivers: [otlp]
+ processors: [batch]
+ exporters: [logging, file]
diff --git a/kong-versions/3.9.0.0/kong/spec/fixtures/perf/500services-each-4-routes.sql b/kong-versions/3.9.0.0/kong/spec/fixtures/perf/500services-each-4-routes.sql
new file mode 100644
index 00000000..73048645
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/fixtures/perf/500services-each-4-routes.sql
@@ -0,0 +1,2549 @@
+--
+-- PostgreSQL database dump
+--
+
+-- Dumped from database version 11.16 (Debian 11.16-1.pgdg90+1)
+-- Dumped by pg_dump version 11.16 (Debian 11.16-1.pgdg90+1)
+
+SET statement_timeout = 0;
+SET lock_timeout = 0;
+SET idle_in_transaction_session_timeout = 0;
+SET client_encoding = 'UTF8';
+SET standard_conforming_strings = on;
+SELECT pg_catalog.set_config('search_path', '', false);
+SET check_function_bodies = false;
+SET xmloption = content;
+SET client_min_messages = warning;
+SET row_security = off;
+
+
+SET SCHEMA 'public';
+TRUNCATE public.workspaces CASCADE;
+TRUNCATE public.routes CASCADE;
+TRUNCATE public.services CASCADE;
+
+--
+-- Data for Name: workspaces; Type: TABLE DATA; Schema: public; Owner: kong
+--
+
+COPY public.workspaces (id, name, comment, created_at, meta, config) FROM stdin;
+dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 default \N 2022-05-26 09:04:16+00 {} {}
+\.
+
+
+--
+-- Data for Name: services; Type: TABLE DATA; Schema: public; Owner: kong
+--
+
+COPY public.services (id, created_at, updated_at, name, retries, protocol, host, port, path, connect_timeout, write_timeout, read_timeout, tags, client_certificate_id, tls_verify, tls_verify_depth, ca_certificates, ws_id, enabled) FROM stdin;
+a7182665-e3bb-4ad0-91bc-bb013404d465 2022-05-26 09:04:20+00 2022-05-26 09:04:20+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+3c089a41-3c85-4e95-94bc-9dcbcc02d5bf 2022-05-26 09:04:20+00 2022-05-26 09:04:20+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+e4e0c0f8-8f86-4138-b90b-1ab4b42c545a 2022-05-26 09:04:20+00 2022-05-26 09:04:20+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+635667df-d7c8-4c8e-961a-79094fb7edf7 2022-05-26 09:04:20+00 2022-05-26 09:04:20+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+5db07df7-6efa-42f1-b526-aeea5f46aa7f 2022-05-26 09:04:20+00 2022-05-26 09:04:20+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+0cf9ed94-6fe4-4356-906d-34bf7f5e323d 2022-05-26 09:04:20+00 2022-05-26 09:04:20+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+b0d849d4-9d3d-48bd-bddd-59aeed02789c 2022-05-26 09:04:20+00 2022-05-26 09:04:20+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+d609eb1a-3c6c-4867-ae94-ad5757bab196 2022-05-26 09:04:20+00 2022-05-26 09:04:20+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+d92656d5-a8d8-4bab-93cf-5c5630eceffb 2022-05-26 09:04:20+00 2022-05-26 09:04:20+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+1e306cf3-2a3b-40b8-91b4-f50caf61d455 2022-05-26 09:04:20+00 2022-05-26 09:04:20+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+b13775fd-dac8-4322-b7a4-a089d677c22d 2022-05-26 09:04:20+00 2022-05-26 09:04:20+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+0d5ae4f4-5ab1-4320-8057-cd0b21d81496 2022-05-26 09:04:20+00 2022-05-26 09:04:20+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+e6a15913-9bdf-46ed-8e9e-b71a91b1197a 2022-05-26 09:04:20+00 2022-05-26 09:04:20+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+9124182f-7ccf-465a-9553-4802b87f4308 2022-05-26 09:04:20+00 2022-05-26 09:04:20+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+ad9d034f-2de2-4a1a-90ad-7f1cf7039a2a 2022-05-26 09:04:20+00 2022-05-26 09:04:20+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+9d36f4e2-ba97-4da7-9f10-133270adbc2e 2022-05-26 09:04:20+00 2022-05-26 09:04:20+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+71164672-4b79-4b4c-8f23-d7b3d193996f 2022-05-26 09:04:20+00 2022-05-26 09:04:20+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+d2c68623-5766-4b26-a956-aa750b23e6b9 2022-05-26 09:04:20+00 2022-05-26 09:04:20+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+c733f9c1-8fb2-4c99-9229-d9a3fe79420f 2022-05-26 09:04:20+00 2022-05-26 09:04:20+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+879a9948-ed52-4827-b326-232b434d6586 2022-05-26 09:04:20+00 2022-05-26 09:04:20+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+6c2f637e-3365-4475-854d-2da53cf54236 2022-05-26 09:04:20+00 2022-05-26 09:04:20+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+e5322b5b-36ef-4b9d-9238-99de86473537 2022-05-26 09:04:21+00 2022-05-26 09:04:21+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+d71477b1-e512-4b80-b755-d0a074de32c5 2022-05-26 09:04:21+00 2022-05-26 09:04:21+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+548bb3e7-fc07-41c9-9299-84a0708a2a59 2022-05-26 09:04:21+00 2022-05-26 09:04:21+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+4ce0aa65-7a39-4c13-8560-50cbbfbfb393 2022-05-26 09:04:21+00 2022-05-26 09:04:21+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+f4dae3be-eb46-4361-b84c-da2f83277f00 2022-05-26 09:04:21+00 2022-05-26 09:04:21+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+25076386-d45e-40fb-bf23-6078de3ecab7 2022-05-26 09:04:21+00 2022-05-26 09:04:21+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+1525a86d-6ae4-421e-a2dc-d5758ba22312 2022-05-26 09:04:21+00 2022-05-26 09:04:21+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+2c961425-9119-41ad-8df7-7b288060e995 2022-05-26 09:04:21+00 2022-05-26 09:04:21+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+b960c35a-83b5-425b-9fe3-2602de569f5d 2022-05-26 09:04:21+00 2022-05-26 09:04:21+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+a882f2cc-b1ac-40a4-8e5d-09d9595c5140 2022-05-26 09:04:21+00 2022-05-26 09:04:21+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+d730b9c1-e795-4c90-b771-3e3ceb21ab91 2022-05-26 09:04:21+00 2022-05-26 09:04:21+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+406467e3-6d3d-40a2-bc8e-9942b8be51b8 2022-05-26 09:04:21+00 2022-05-26 09:04:21+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+d5ab8d0f-b02b-4bd6-9d46-ab7da78e15ef 2022-05-26 09:04:21+00 2022-05-26 09:04:21+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+62131b85-cb9b-43d1-97d8-f4b2966dbb68 2022-05-26 09:04:21+00 2022-05-26 09:04:21+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+35fefbaf-66df-47b2-abf0-1231af2788b5 2022-05-26 09:04:21+00 2022-05-26 09:04:21+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+63639c14-7690-4f27-8a69-4df1aca28594 2022-05-26 09:04:21+00 2022-05-26 09:04:21+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+872066a1-4cfb-4f69-ab14-2de00fe8a82e 2022-05-26 09:04:21+00 2022-05-26 09:04:21+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+056302e1-150a-416c-9a4f-a9fb03f3f651 2022-05-26 09:04:21+00 2022-05-26 09:04:21+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+73734495-785d-42d2-a755-0ad0b1acf933 2022-05-26 09:04:21+00 2022-05-26 09:04:21+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+8e691f37-eb65-4e3b-a6e2-0525412a98ab 2022-05-26 09:04:21+00 2022-05-26 09:04:21+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+569a3987-9516-4053-92b8-aeebdaeeed5d 2022-05-26 09:04:21+00 2022-05-26 09:04:21+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+5839b3b1-f03a-41f9-b645-a35ff680acbe 2022-05-26 09:04:21+00 2022-05-26 09:04:21+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+649cf33b-3d04-46f8-b849-4bfa449c8a7f 2022-05-26 09:04:21+00 2022-05-26 09:04:21+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+3282f133-b8eb-4e46-80c6-a217df510860 2022-05-26 09:04:21+00 2022-05-26 09:04:21+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+da88cad4-bd4b-4a9d-b81d-d1445bf108a8 2022-05-26 09:04:21+00 2022-05-26 09:04:21+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+365b2abb-1347-4077-8ffc-5b21984fca7f 2022-05-26 09:04:21+00 2022-05-26 09:04:21+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+e3cc7fa5-1919-4753-9afe-6f30f67a2c2e 2022-05-26 09:04:21+00 2022-05-26 09:04:21+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+fb53dd51-d113-4650-b980-e761871f3c54 2022-05-26 09:04:21+00 2022-05-26 09:04:21+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+851cd368-f1ea-4584-8cec-9a430f9b1a3f 2022-05-26 09:04:21+00 2022-05-26 09:04:21+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+4658664d-4ff6-4ab7-a9bf-8c0492c974de 2022-05-26 09:04:22+00 2022-05-26 09:04:22+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+4d48bf3c-a575-4520-8817-34f0b84dd4b6 2022-05-26 09:04:22+00 2022-05-26 09:04:22+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+26968e02-8bda-4c4e-818c-8ed35d44fd9c 2022-05-26 09:04:22+00 2022-05-26 09:04:22+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+27f10e41-7155-4eed-bdfa-783271fc8bae 2022-05-26 09:04:22+00 2022-05-26 09:04:22+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+73bc0430-7355-4c6d-a974-74f5bf707db1 2022-05-26 09:04:22+00 2022-05-26 09:04:22+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+ef27392a-1fb8-4611-8757-c42b55900756 2022-05-26 09:04:22+00 2022-05-26 09:04:22+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+b45da34e-3338-4878-a3e5-d78df8cd22e7 2022-05-26 09:04:22+00 2022-05-26 09:04:22+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+dc5da515-f616-40e9-9b94-d699fded3db7 2022-05-26 09:04:22+00 2022-05-26 09:04:22+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+8168f4cc-39af-49bd-8b6e-a365f038bebd 2022-05-26 09:04:22+00 2022-05-26 09:04:22+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+051898cd-71d2-457b-9ee8-c080908da498 2022-05-26 09:04:22+00 2022-05-26 09:04:22+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+cdb3688d-b5fc-421a-8c06-cb14fc6c5ff9 2022-05-26 09:04:22+00 2022-05-26 09:04:22+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+cae8aca9-818b-450d-97a6-7ea08373e0cc 2022-05-26 09:04:22+00 2022-05-26 09:04:22+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+1b7c0f6a-9eab-428e-b979-5995a4ff6527 2022-05-26 09:04:22+00 2022-05-26 09:04:22+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+3e658a76-cb76-4be7-a15a-84d4883b472b 2022-05-26 09:04:22+00 2022-05-26 09:04:22+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+800121b2-3644-4ea0-8539-25d513acb472 2022-05-26 09:04:22+00 2022-05-26 09:04:22+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+89b2af01-b55f-4425-844e-bc2dea397b93 2022-05-26 09:04:22+00 2022-05-26 09:04:22+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+34f521cb-53b9-4824-89b7-15459e96532f 2022-05-26 09:04:22+00 2022-05-26 09:04:22+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+33a92a68-5e8d-487b-977e-89dd42a458bd 2022-05-26 09:04:22+00 2022-05-26 09:04:22+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+dbbe71cb-7ec1-4c43-804d-ef6a92721d90 2022-05-26 09:04:22+00 2022-05-26 09:04:22+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+69a88ba4-e530-4723-b7c3-f739b92a5a66 2022-05-26 09:04:22+00 2022-05-26 09:04:22+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+0d1eb445-8a10-49bb-952f-5eb35a8599d3 2022-05-26 09:04:22+00 2022-05-26 09:04:22+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+a03dac5a-20dc-492d-b4db-732a79d4a30c 2022-05-26 09:04:22+00 2022-05-26 09:04:22+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+291a0424-2ad1-47a6-a8b2-c63a037bf03c 2022-05-26 09:04:22+00 2022-05-26 09:04:22+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+4eb8a749-0bd2-47af-8fdc-4cf128bf0b66 2022-05-26 09:04:22+00 2022-05-26 09:04:22+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+c398e6e1-2f3e-4897-912f-483c03ec6959 2022-05-26 09:04:22+00 2022-05-26 09:04:22+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+c544969b-0b53-43a7-a6a9-79e400d7b852 2022-05-26 09:04:22+00 2022-05-26 09:04:22+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+1dc10ac4-8720-49d0-9624-e2320ad83910 2022-05-26 09:04:22+00 2022-05-26 09:04:22+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+961eda07-6db4-41a9-b053-55f3d86feab9 2022-05-26 09:04:22+00 2022-05-26 09:04:22+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+a92dc0e0-3cd3-4c00-bfbd-1b9d849c617b 2022-05-26 09:04:22+00 2022-05-26 09:04:22+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+6fc0c8de-dd47-4b2d-be48-acff77604738 2022-05-26 09:04:23+00 2022-05-26 09:04:23+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+c1477ea4-988e-40e5-b7a8-6fa4e688f36d 2022-05-26 09:04:23+00 2022-05-26 09:04:23+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+c0ac16b4-51b2-4388-a75c-99a6e8864567 2022-05-26 09:04:23+00 2022-05-26 09:04:23+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+b3490c56-2668-4cf8-ac26-9d3c38fb9ce6 2022-05-26 09:04:23+00 2022-05-26 09:04:23+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+6f607e1a-2baf-4f12-b0ed-270073df30c6 2022-05-26 09:04:23+00 2022-05-26 09:04:23+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+4284966e-2ef5-45f7-b16c-faba6666c300 2022-05-26 09:04:23+00 2022-05-26 09:04:23+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+0a3d005f-e8ae-46a0-bc92-0a4a8147fe3f 2022-05-26 09:04:23+00 2022-05-26 09:04:23+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+f7039445-e8fa-44c0-ba30-4db609972643 2022-05-26 09:04:23+00 2022-05-26 09:04:23+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+10db8481-4fa8-4531-9e0c-fb20e642dc40 2022-05-26 09:04:23+00 2022-05-26 09:04:23+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+0069a9d9-459a-4efc-b5a2-c0ae786c92bd 2022-05-26 09:04:23+00 2022-05-26 09:04:23+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+fa73881d-a74d-4349-8a9c-b2ae17b414fd 2022-05-26 09:04:23+00 2022-05-26 09:04:23+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+fea825b5-53e7-4d5e-b594-5e6d20822e27 2022-05-26 09:04:23+00 2022-05-26 09:04:23+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+0f9df5d5-3dd4-4a0b-beef-5aed37af31c6 2022-05-26 09:04:23+00 2022-05-26 09:04:23+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+7d839f08-fe27-44a8-bbea-abaea85e8ec4 2022-05-26 09:04:23+00 2022-05-26 09:04:23+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+4e27c8d3-1b57-4837-a62e-7b7129f23b87 2022-05-26 09:04:23+00 2022-05-26 09:04:23+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+187a1bbe-8750-47fd-a693-eb832b67106f 2022-05-26 09:04:23+00 2022-05-26 09:04:23+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+97cac022-7f9a-4eb7-a600-3f99cbdf8484 2022-05-26 09:04:23+00 2022-05-26 09:04:23+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+f731ee23-32fc-428e-858c-2451542ef358 2022-05-26 09:04:23+00 2022-05-26 09:04:23+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+7cdc1f2b-844d-44af-80ee-9ee8ce30ec3a 2022-05-26 09:04:23+00 2022-05-26 09:04:23+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+786c4ca2-f7e2-497f-afe9-04a7d389cffb 2022-05-26 09:04:23+00 2022-05-26 09:04:23+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+327348b0-de35-47ef-a46b-292bf1a2ce91 2022-05-26 09:04:23+00 2022-05-26 09:04:23+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+42231a53-eac6-41d4-906f-96a6007efd5c 2022-05-26 09:04:23+00 2022-05-26 09:04:23+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+2e5dce8d-7e56-4037-a53f-5363e78cfb67 2022-05-26 09:04:23+00 2022-05-26 09:04:23+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+880c0dfc-3b35-4557-9f4f-20e450605453 2022-05-26 09:04:23+00 2022-05-26 09:04:23+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+2d1e40d6-8080-4cee-98b2-c64c3dfbeb70 2022-05-26 09:04:23+00 2022-05-26 09:04:23+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+92e0b48f-e57a-4b37-a150-ca88c81d14a3 2022-05-26 09:04:23+00 2022-05-26 09:04:23+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+837f896d-e596-4681-94af-74e1f8832cec 2022-05-26 09:04:23+00 2022-05-26 09:04:23+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+dfa8a1f7-4dba-4abe-b98d-11146dddf483 2022-05-26 09:04:23+00 2022-05-26 09:04:23+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+87b83cd7-e97b-46e2-b8aa-cfc3f41df930 2022-05-26 09:04:23+00 2022-05-26 09:04:23+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+090f6901-a7d3-42e6-94f4-69ff07632983 2022-05-26 09:04:24+00 2022-05-26 09:04:24+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+f0c01e5e-139d-4458-a3f7-47c6f9eb59de 2022-05-26 09:04:24+00 2022-05-26 09:04:24+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+c1ad53a6-4115-441a-a162-5a27b3e5c01d 2022-05-26 09:04:24+00 2022-05-26 09:04:24+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+6b12e083-97d5-4964-82c5-22bc95802ef0 2022-05-26 09:04:24+00 2022-05-26 09:04:24+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+75d7f4d4-c369-46cd-bf84-fb40784d4fe1 2022-05-26 09:04:24+00 2022-05-26 09:04:24+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+5e861b07-f18f-48b1-aa4d-e44f7ca06eb5 2022-05-26 09:04:24+00 2022-05-26 09:04:24+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+dc67018b-ba17-48f8-962a-e39d4e96eff4 2022-05-26 09:04:24+00 2022-05-26 09:04:24+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+d025ea98-eb37-4e43-bddc-302f5d4ecee1 2022-05-26 09:04:24+00 2022-05-26 09:04:24+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+34f418de-2a74-47b6-ac68-9099b4281763 2022-05-26 09:04:24+00 2022-05-26 09:04:24+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+81c2ba99-2238-48c5-9d7b-ee96f85ed0c5 2022-05-26 09:04:24+00 2022-05-26 09:04:24+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+bebc02c6-4798-4c51-9c65-6ac83e7e2050 2022-05-26 09:04:24+00 2022-05-26 09:04:24+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+84579611-336d-4291-ba77-6907426203d0 2022-05-26 09:04:24+00 2022-05-26 09:04:24+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+03d2fc5d-582c-4f45-bce2-41f8a1e45f45 2022-05-26 09:04:24+00 2022-05-26 09:04:24+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+8bd5e802-0de6-462c-89d8-8a3dc33743fc 2022-05-26 09:04:24+00 2022-05-26 09:04:24+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+75a284e6-a2d0-4fa0-9210-d1dfbfe393cc 2022-05-26 09:04:24+00 2022-05-26 09:04:24+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+9462d6ae-3811-488a-8f43-93afe7e8d6ed 2022-05-26 09:04:24+00 2022-05-26 09:04:24+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+6a8aa9d7-cefe-455e-8671-721e43cd0b96 2022-05-26 09:04:24+00 2022-05-26 09:04:24+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+1a79fb8d-58e0-42d1-a2b2-a9f730a6d635 2022-05-26 09:04:24+00 2022-05-26 09:04:24+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+693ae85e-2dcb-4bac-a88f-832ef036ec35 2022-05-26 09:04:24+00 2022-05-26 09:04:24+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+cf55043c-e758-4007-9d0b-f29ce449b017 2022-05-26 09:04:24+00 2022-05-26 09:04:24+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+b0f369f5-47ca-4790-a7c6-f70ef9670801 2022-05-26 09:04:24+00 2022-05-26 09:04:24+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+f54e8793-3010-4551-8a86-bc026fcdbd71 2022-05-26 09:04:24+00 2022-05-26 09:04:24+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+eda8a272-adab-466a-b5c9-ba27137d2bc3 2022-05-26 09:04:24+00 2022-05-26 09:04:24+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+78c825c8-abdd-4280-9da9-d3bf00e23f82 2022-05-26 09:04:24+00 2022-05-26 09:04:24+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+c3dc6599-036f-46b8-a95e-8e5b6ef3a3f5 2022-05-26 09:04:24+00 2022-05-26 09:04:24+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+4372ca08-22e6-4a0e-8d13-f598ba86cf37 2022-05-26 09:04:24+00 2022-05-26 09:04:24+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+0766430c-c266-489c-bc27-58df3fd10388 2022-05-26 09:04:24+00 2022-05-26 09:04:24+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+c7167c55-60fb-45f7-b257-4acddb1d9119 2022-05-26 09:04:24+00 2022-05-26 09:04:24+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+76b8797a-0ad8-4a9f-9fdf-561c79e481d9 2022-05-26 09:04:25+00 2022-05-26 09:04:25+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+bad7c636-19ad-430e-8c49-6e4efddc4376 2022-05-26 09:04:25+00 2022-05-26 09:04:25+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+fd6fd9ca-1169-45ba-bb87-8b846a8d0d3e 2022-05-26 09:04:25+00 2022-05-26 09:04:25+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+a2ee552e-0961-4036-8d1c-8ebd420f28ed 2022-05-26 09:04:25+00 2022-05-26 09:04:25+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+6fca3f1f-fa31-4c70-8059-aee7dd0d5be3 2022-05-26 09:04:25+00 2022-05-26 09:04:25+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+70d03905-4002-4dc1-b3f9-336d25ee164e 2022-05-26 09:04:25+00 2022-05-26 09:04:25+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+4693dd6c-1d27-46df-b5be-259eda6ad3df 2022-05-26 09:04:25+00 2022-05-26 09:04:25+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+390c61c3-b91b-44d0-9132-d629f3f7f2c2 2022-05-26 09:04:25+00 2022-05-26 09:04:25+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+addbf9ae-c319-4a46-831b-a2c71204cfdc 2022-05-26 09:04:25+00 2022-05-26 09:04:25+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+d59261e7-93ca-464a-b84d-cc9c64e2d649 2022-05-26 09:04:25+00 2022-05-26 09:04:25+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+37262d9e-1dd7-4314-9a5a-d289c7479be0 2022-05-26 09:04:25+00 2022-05-26 09:04:25+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+d3ec5e93-e9e3-4fd4-a27b-6af1e300aa4b 2022-05-26 09:04:25+00 2022-05-26 09:04:25+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+0cdb0d81-1c8a-49b4-b5aa-50b627e298c6 2022-05-26 09:04:25+00 2022-05-26 09:04:25+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+5e987b7a-1d92-49e3-ad2f-362501d07bf9 2022-05-26 09:04:25+00 2022-05-26 09:04:25+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+98193422-6ec1-4767-8568-e34555d37244 2022-05-26 09:04:25+00 2022-05-26 09:04:25+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+23c5d21a-6ff6-4f87-950b-3189611df400 2022-05-26 09:04:25+00 2022-05-26 09:04:25+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+61b20f0c-ad75-46c5-bdb1-c9ee4db679eb 2022-05-26 09:04:25+00 2022-05-26 09:04:25+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+f658e233-91f5-4e42-a97f-43303defe86d 2022-05-26 09:04:25+00 2022-05-26 09:04:25+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+bf2c91f2-cfdd-4f0a-bb05-0433141ad9ce 2022-05-26 09:04:25+00 2022-05-26 09:04:25+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+44e7d282-81cf-4f35-b20d-289a41d57da9 2022-05-26 09:04:25+00 2022-05-26 09:04:25+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+5e9458db-1f76-4728-bf68-8f100dcb5e04 2022-05-26 09:04:25+00 2022-05-26 09:04:25+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+5cf7efb5-6ce3-4bfa-9b9c-69615c0424c3 2022-05-26 09:04:25+00 2022-05-26 09:04:25+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+e601de5f-ad58-4d48-83b7-bc0e20cadd7e 2022-05-26 09:04:25+00 2022-05-26 09:04:25+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+3995380e-ac1c-4133-a6e1-65a2b355a121 2022-05-26 09:04:25+00 2022-05-26 09:04:25+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+109dabd3-4d13-40ea-b6f4-2a94d74c7f6c 2022-05-26 09:04:25+00 2022-05-26 09:04:25+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+502c5b41-66bf-4383-918a-badfea2d25c7 2022-05-26 09:04:25+00 2022-05-26 09:04:25+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+9557d7a1-d82f-4fab-a4c1-59b705f29b2e 2022-05-26 09:04:25+00 2022-05-26 09:04:25+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+cefbb83a-2d32-4aba-83e1-1ad7811849e9 2022-05-26 09:04:25+00 2022-05-26 09:04:25+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+24fbd204-d7a7-4d11-9109-a73e52f718b1 2022-05-26 09:04:25+00 2022-05-26 09:04:25+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+ef9b8d4d-3e83-4353-a80e-426e5fc7cbb9 2022-05-26 09:04:25+00 2022-05-26 09:04:25+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+bd6e4a2a-b1f5-4fdf-bb0d-6e9918275bd6 2022-05-26 09:04:26+00 2022-05-26 09:04:26+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+a39c21f4-1588-473b-b5f0-ca58437f5670 2022-05-26 09:04:26+00 2022-05-26 09:04:26+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+cd7ff4b6-0461-43d7-89d4-00df67b34598 2022-05-26 09:04:26+00 2022-05-26 09:04:26+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+d46890a2-26b2-4d3c-860d-f54cc24b7663 2022-05-26 09:04:26+00 2022-05-26 09:04:26+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+4d17db21-c723-4052-9a5f-d704fd01862f 2022-05-26 09:04:26+00 2022-05-26 09:04:26+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+a9c1b4cf-9457-4010-a9b8-4f5236dcc5ce 2022-05-26 09:04:26+00 2022-05-26 09:04:26+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+e79cb133-66ba-406a-895d-559eddf73902 2022-05-26 09:04:26+00 2022-05-26 09:04:26+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+8b99e7b2-ccdf-4cb9-b185-e3cde9ec9af7 2022-05-26 09:04:26+00 2022-05-26 09:04:26+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+d807dd5e-21de-4d30-823e-41d98b76bf8e 2022-05-26 09:04:26+00 2022-05-26 09:04:26+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+00284c22-d742-4a15-9a67-4bb4dcd90d8f 2022-05-26 09:04:26+00 2022-05-26 09:04:26+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+751853be-1e25-490e-a6ef-9417a6b540ef 2022-05-26 09:04:26+00 2022-05-26 09:04:26+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+f73bf090-0d18-40e8-b186-7fc9e91e62d1 2022-05-26 09:04:26+00 2022-05-26 09:04:26+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+12042bab-a587-44e7-881d-2315a7305c39 2022-05-26 09:04:26+00 2022-05-26 09:04:26+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+9b0c19f6-6ab2-4119-8a6f-37e8f15cdd98 2022-05-26 09:04:26+00 2022-05-26 09:04:26+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+d76ebd2e-5ee7-4810-864b-3a12440faca9 2022-05-26 09:04:26+00 2022-05-26 09:04:26+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+bd3ca0d9-03ac-4021-8de2-08321ccb3277 2022-05-26 09:04:26+00 2022-05-26 09:04:26+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+528428e4-3f06-482d-8b4b-65b51c3bb653 2022-05-26 09:04:26+00 2022-05-26 09:04:26+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+73e663c8-0f96-4908-a02c-5c7eea81e327 2022-05-26 09:04:26+00 2022-05-26 09:04:26+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+2c40d9e2-469a-4c7a-9bcf-61552994e02e 2022-05-26 09:04:26+00 2022-05-26 09:04:26+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+3e2fe25a-fc33-4a1e-a1f1-a60ac070e341 2022-05-26 09:04:26+00 2022-05-26 09:04:26+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+a344e177-1f6e-4753-8404-a3fbd716a992 2022-05-26 09:04:26+00 2022-05-26 09:04:26+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+ababbb85-337f-4aba-9922-41daf23c2865 2022-05-26 09:04:26+00 2022-05-26 09:04:26+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+1b075615-d2ce-4b5c-997d-729c664dc4f4 2022-05-26 09:04:26+00 2022-05-26 09:04:26+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+fe3e3c81-0f6c-4f7b-82d7-06022c1613b6 2022-05-26 09:04:26+00 2022-05-26 09:04:26+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+54d95a23-896b-40b4-b93a-dfe4b4083a23 2022-05-26 09:04:26+00 2022-05-26 09:04:26+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+92af388d-d0f3-41a9-ad5f-ed90b03de869 2022-05-26 09:04:26+00 2022-05-26 09:04:26+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+5a61733d-2684-4d4a-9d35-bf785b7c07c2 2022-05-26 09:04:26+00 2022-05-26 09:04:26+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+ece058ba-4c37-48de-a640-d7b889c4fb6c 2022-05-26 09:04:26+00 2022-05-26 09:04:26+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+c2c49d74-23c3-4ce3-a9e5-f0ede3967097 2022-05-26 09:04:27+00 2022-05-26 09:04:27+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+fbdc551b-4550-4528-a74d-a595aa492b51 2022-05-26 09:04:27+00 2022-05-26 09:04:27+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+92c2bcd2-bb73-4339-aaf1-8b552ceb0106 2022-05-26 09:04:27+00 2022-05-26 09:04:27+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+c60849dc-5675-492f-8bab-5d8cb3626823 2022-05-26 09:04:27+00 2022-05-26 09:04:27+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+1d6aa622-24ef-4888-a080-ba20e5c89316 2022-05-26 09:04:27+00 2022-05-26 09:04:27+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+204833b7-0070-4b55-9583-1df64dc7ab2a 2022-05-26 09:04:27+00 2022-05-26 09:04:27+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+2cebb659-d522-4e02-9ba6-90e09ced208c 2022-05-26 09:04:27+00 2022-05-26 09:04:27+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+8fd65cbb-d37c-45ad-95ba-f5bb0acf87e0 2022-05-26 09:04:27+00 2022-05-26 09:04:27+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+310fe133-a807-45dc-9dd1-6a6b1fe1d07d 2022-05-26 09:04:27+00 2022-05-26 09:04:27+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+f7df66fb-1d8f-46dc-b569-de1b63a0344b 2022-05-26 09:04:27+00 2022-05-26 09:04:27+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+b75d1f70-93f2-4de0-9bb4-7a1fae40e29b 2022-05-26 09:04:27+00 2022-05-26 09:04:27+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+cde580a3-81d5-4cef-9858-f99a1f629422 2022-05-26 09:04:27+00 2022-05-26 09:04:27+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+ebc496df-a1c7-4046-bf99-45778c2de1c6 2022-05-26 09:04:27+00 2022-05-26 09:04:27+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+2a2d78fd-a19a-4a2c-80c1-816deb18c823 2022-05-26 09:04:27+00 2022-05-26 09:04:27+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+88c9d8c2-1bfd-4b33-81c7-7d77866b2d7e 2022-05-26 09:04:27+00 2022-05-26 09:04:27+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+0eb52ec4-f6fc-4c6d-ac31-e07b84f7e17e 2022-05-26 09:04:27+00 2022-05-26 09:04:27+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+1c255589-3ec2-42b8-b722-32c1f9ad2510 2022-05-26 09:04:27+00 2022-05-26 09:04:27+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+b5af350e-6e66-40e4-8333-e0595f756e83 2022-05-26 09:04:27+00 2022-05-26 09:04:27+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+607a67a8-1ab1-4c96-869d-71ffc14a90cb 2022-05-26 09:04:27+00 2022-05-26 09:04:27+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+97657a2e-8286-4638-b42b-d8f1418f68f3 2022-05-26 09:04:27+00 2022-05-26 09:04:27+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+8ebbdaa1-2ede-459c-8f20-9eaf6c4c5e34 2022-05-26 09:04:27+00 2022-05-26 09:04:27+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+dc47a6ab-1456-4e60-95d2-50b7251072be 2022-05-26 09:04:27+00 2022-05-26 09:04:27+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+17157627-0993-4a53-ac67-5dc31565a022 2022-05-26 09:04:27+00 2022-05-26 09:04:27+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+8456d2fa-f8ee-44c4-b062-376c225c6ad9 2022-05-26 09:04:27+00 2022-05-26 09:04:27+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+289e1e86-7c79-4686-910d-91d138398782 2022-05-26 09:04:27+00 2022-05-26 09:04:27+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+ef250969-68ff-4fc9-a9f9-46f776374937 2022-05-26 09:04:27+00 2022-05-26 09:04:27+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+f75fa431-1d5b-4a84-adc9-f2ab778755f2 2022-05-26 09:04:27+00 2022-05-26 09:04:27+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+395b99d4-38f4-4268-9cd0-fa6e0f2cff94 2022-05-26 09:04:27+00 2022-05-26 09:04:27+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+fd296ad3-4272-4acb-8246-1853ba56f38c 2022-05-26 09:04:28+00 2022-05-26 09:04:28+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+2128d33e-4e88-442c-a077-753f5bc3cfb1 2022-05-26 09:04:28+00 2022-05-26 09:04:28+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+0e047d1b-5481-4e2e-949c-8bb2dcf9e5e9 2022-05-26 09:04:28+00 2022-05-26 09:04:28+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+b3a256a3-3d0f-4a67-9518-dda233dab2a4 2022-05-26 09:04:28+00 2022-05-26 09:04:28+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+75b76bb1-fcd9-4b1d-8a07-9c89e323838d 2022-05-26 09:04:28+00 2022-05-26 09:04:28+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+b9fd2d19-6d98-409c-822c-b53d23fc6bf4 2022-05-26 09:04:28+00 2022-05-26 09:04:28+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+999a382f-59db-47a3-95e5-3c7c387e519c 2022-05-26 09:04:28+00 2022-05-26 09:04:28+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+12475fba-736b-41ef-b7c9-91f0ab42706f 2022-05-26 09:04:28+00 2022-05-26 09:04:28+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+991a0eb0-d11a-40c7-9c0c-69134e425825 2022-05-26 09:04:28+00 2022-05-26 09:04:28+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+a8911c95-832e-49cd-bbbf-adf393a69d28 2022-05-26 09:04:28+00 2022-05-26 09:04:28+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+05d5816d-797f-4329-8693-6864ba16fa00 2022-05-26 09:04:28+00 2022-05-26 09:04:28+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+b198788c-dabc-4723-aaeb-258b242f5bf7 2022-05-26 09:04:28+00 2022-05-26 09:04:28+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+f827a7cb-3a5d-49dd-b15b-4a6a05c8f76c 2022-05-26 09:04:28+00 2022-05-26 09:04:28+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+37142dfa-010c-4d0b-ae54-3285c60e177c 2022-05-26 09:04:28+00 2022-05-26 09:04:28+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+82375487-c356-468a-9a2a-3999121b401e 2022-05-26 09:04:28+00 2022-05-26 09:04:28+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+d15f0c0a-bce7-427d-8da1-07928f5d415b 2022-05-26 09:04:28+00 2022-05-26 09:04:28+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+24e96d1e-b429-4a11-8fd1-ec0688531b53 2022-05-26 09:04:28+00 2022-05-26 09:04:28+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+eea2568d-e01a-4936-a539-01988a96bda8 2022-05-26 09:04:28+00 2022-05-26 09:04:28+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+aea5c9f3-3582-4705-be7d-88c291890572 2022-05-26 09:04:28+00 2022-05-26 09:04:28+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+062ddf91-5330-4185-877a-f8cdc29b5580 2022-05-26 09:04:28+00 2022-05-26 09:04:28+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+839c749b-aebf-46d3-b72b-ce58fb730dbe 2022-05-26 09:04:28+00 2022-05-26 09:04:28+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+75fa1631-c22b-4234-b8e0-0e6a79d24963 2022-05-26 09:04:28+00 2022-05-26 09:04:28+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+56e78f0a-a314-4f02-865a-ccfd68eaa009 2022-05-26 09:04:28+00 2022-05-26 09:04:28+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+11b2be65-4a17-48f2-8a23-3c377c31b8bb 2022-05-26 09:04:28+00 2022-05-26 09:04:28+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+8497dff1-9e4d-4a60-b7ba-d4c8ff11af87 2022-05-26 09:04:28+00 2022-05-26 09:04:28+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+712a182e-b50a-4efb-a0f0-ca4fe894e577 2022-05-26 09:04:29+00 2022-05-26 09:04:29+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+ab44cae8-8ac0-41f1-9671-d07d69bb4ad2 2022-05-26 09:04:29+00 2022-05-26 09:04:29+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+86074cab-06f4-425d-b52a-7ba8958f3778 2022-05-26 09:04:29+00 2022-05-26 09:04:29+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+3342939c-cfcb-437b-9ba9-ba20845e2183 2022-05-26 09:04:29+00 2022-05-26 09:04:29+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+be8251f2-6fd1-4823-8bf1-bc8c7fcd04be 2022-05-26 09:04:29+00 2022-05-26 09:04:29+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+3d42dc37-596d-4996-8f00-b3c2fb6de270 2022-05-26 09:04:29+00 2022-05-26 09:04:29+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+704f1d16-e489-41d3-8a88-ee2c5b9b603f 2022-05-26 09:04:29+00 2022-05-26 09:04:29+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+de8247fa-8178-495c-9fdb-111b5ae55037 2022-05-26 09:04:29+00 2022-05-26 09:04:29+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+9a548e20-7aef-4cbc-b959-e1680c595689 2022-05-26 09:04:29+00 2022-05-26 09:04:29+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+6d28de77-2ca4-4bb6-bc60-cd631380e860 2022-05-26 09:04:29+00 2022-05-26 09:04:29+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+9630e957-6d21-4127-b724-dc7be3e201c1 2022-05-26 09:04:29+00 2022-05-26 09:04:29+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+439b1ab5-f5d1-4fce-b52d-b2beca2c2d6b 2022-05-26 09:04:29+00 2022-05-26 09:04:29+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+c385836e-5c56-47a7-b3d8-2388d62b077c 2022-05-26 09:04:29+00 2022-05-26 09:04:29+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+5e375f63-692a-4416-a031-72323da9262b 2022-05-26 09:04:29+00 2022-05-26 09:04:29+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+15ae2d93-8e77-49a2-a00b-1f8c7bf6b5a4 2022-05-26 09:04:29+00 2022-05-26 09:04:29+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+b4045684-2ff9-4810-a1ca-9bd3993f7cd4 2022-05-26 09:04:29+00 2022-05-26 09:04:29+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+75d178df-1223-4f56-80b4-1bea51adfc97 2022-05-26 09:04:29+00 2022-05-26 09:04:29+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+b44e03a1-22f5-4443-ba10-921c56788bfe 2022-05-26 09:04:29+00 2022-05-26 09:04:29+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+8577c35b-106c-418c-8b93-90decb06af58 2022-05-26 09:04:29+00 2022-05-26 09:04:29+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+18b21a7d-7f74-48b1-b9db-9ffa2db7d904 2022-05-26 09:04:29+00 2022-05-26 09:04:29+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+62f8d892-76fb-4ef9-9b66-b0b81564bce5 2022-05-26 09:04:29+00 2022-05-26 09:04:29+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+08da3a9d-5fdf-47a8-be8f-ce287d2f2914 2022-05-26 09:04:29+00 2022-05-26 09:04:29+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+e6ff5e56-255d-440d-81df-a452a2072297 2022-05-26 09:04:29+00 2022-05-26 09:04:29+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+5d13ade8-944a-46a1-89db-e6707760f27a 2022-05-26 09:04:29+00 2022-05-26 09:04:29+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+783e864e-f9f2-410b-ae7e-f083694fd114 2022-05-26 09:04:29+00 2022-05-26 09:04:29+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+dd29a63e-9bd9-4a46-99a2-bb4de34b390d 2022-05-26 09:04:29+00 2022-05-26 09:04:29+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+d308ba72-8ccb-4b74-bc09-c3ea91561b47 2022-05-26 09:04:29+00 2022-05-26 09:04:29+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+bb545b0f-69e5-4dbe-8b3a-8d692e9f0465 2022-05-26 09:04:29+00 2022-05-26 09:04:29+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+09688798-b181-4282-9b47-4ea11cbed88f 2022-05-26 09:04:29+00 2022-05-26 09:04:29+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+f2f31531-6e81-4e47-8ee5-21db84a28cae 2022-05-26 09:04:30+00 2022-05-26 09:04:30+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+5718da07-3088-41a8-a8e9-56d83309d49f 2022-05-26 09:04:30+00 2022-05-26 09:04:30+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+858587ef-4507-470b-bf83-53d9d428607d 2022-05-26 09:04:30+00 2022-05-26 09:04:30+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+e838f443-11b9-47d3-952c-b29d32c47d99 2022-05-26 09:04:30+00 2022-05-26 09:04:30+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+3c00d6b0-b98a-4e77-a9e8-3255963487ca 2022-05-26 09:04:30+00 2022-05-26 09:04:30+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+7968fa6f-3fce-4d76-98b7-ac7e1abd5f3b 2022-05-26 09:04:30+00 2022-05-26 09:04:30+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+0215b396-4130-4073-8c0b-a994e36641fc 2022-05-26 09:04:30+00 2022-05-26 09:04:30+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+053a5358-18e8-401d-8eae-709cae78044b 2022-05-26 09:04:30+00 2022-05-26 09:04:30+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+645d937e-50e6-428b-a66b-b940faa02f28 2022-05-26 09:04:30+00 2022-05-26 09:04:30+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+19fa1c11-2031-49e3-8242-33a1fc7aeb18 2022-05-26 09:04:30+00 2022-05-26 09:04:30+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+9832ee7f-74e0-4e0b-8897-44cfd8c7892a 2022-05-26 09:04:30+00 2022-05-26 09:04:30+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+0a5d0d3b-055c-4338-b19e-1fd4d196234a 2022-05-26 09:04:30+00 2022-05-26 09:04:30+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+70fae9ae-8e2b-4fe7-8c2d-3c50cf88dbac 2022-05-26 09:04:30+00 2022-05-26 09:04:30+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+554fa44c-d64b-4501-84f6-8543e0ac1c42 2022-05-26 09:04:30+00 2022-05-26 09:04:30+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+ff177547-b49b-4e7e-b3d9-f99ba78df0db 2022-05-26 09:04:30+00 2022-05-26 09:04:30+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+76217b97-af15-44da-8565-39546305a786 2022-05-26 09:04:30+00 2022-05-26 09:04:30+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+5f70b4d9-fcd2-4a6b-b5d5-57f603a2d936 2022-05-26 09:04:30+00 2022-05-26 09:04:30+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+cddf8c8a-8e68-45c7-a771-d5d2d8aca8f5 2022-05-26 09:04:30+00 2022-05-26 09:04:30+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+f1e1ff63-b396-4ed6-9305-d4d045a2e9a7 2022-05-26 09:04:30+00 2022-05-26 09:04:30+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+22fa79c7-1a20-4b96-afbb-cac2c2c22706 2022-05-26 09:04:30+00 2022-05-26 09:04:30+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+dc31ed76-081d-4ae2-b4d3-c249a4348842 2022-05-26 09:04:30+00 2022-05-26 09:04:30+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+6331cb28-6a75-45e7-9d9d-7225d0996e0f 2022-05-26 09:04:30+00 2022-05-26 09:04:30+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+d9a841c6-6bf4-4cd6-921c-f38e9f772cb0 2022-05-26 09:04:30+00 2022-05-26 09:04:30+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+49b9e591-2b39-4cca-b0ad-94880347cb6e 2022-05-26 09:04:30+00 2022-05-26 09:04:30+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+50d5126f-ed18-4022-a93a-3fee8b5a2a61 2022-05-26 09:04:30+00 2022-05-26 09:04:30+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+e1e1f82a-936b-49d0-8d28-ebab1f134a1b 2022-05-26 09:04:30+00 2022-05-26 09:04:30+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+b5815188-d327-4734-ad11-6bd6459b38a4 2022-05-26 09:04:30+00 2022-05-26 09:04:30+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+0808e339-4431-4419-8c80-0bd658eb351a 2022-05-26 09:04:30+00 2022-05-26 09:04:30+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+8e7cf859-20b8-46cf-a515-89cff33cbaf3 2022-05-26 09:04:30+00 2022-05-26 09:04:30+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+876e891f-4820-4e1d-96d5-d86cb4ecedc1 2022-05-26 09:04:31+00 2022-05-26 09:04:31+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+84c6bde5-724f-4beb-b1c0-16f07b948029 2022-05-26 09:04:31+00 2022-05-26 09:04:31+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+f612ff85-e276-47b3-a33a-63499962253d 2022-05-26 09:04:31+00 2022-05-26 09:04:31+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+0e58f9e2-049c-413c-9053-520742687a6e 2022-05-26 09:04:31+00 2022-05-26 09:04:31+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+82a6fb35-6254-4f5b-8aa7-c0472632af47 2022-05-26 09:04:31+00 2022-05-26 09:04:31+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+258d783d-9e92-48d2-ace4-861cb00df9b7 2022-05-26 09:04:31+00 2022-05-26 09:04:31+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+bd5dcc38-1fc4-49c0-80e2-f26fa6a49a9f 2022-05-26 09:04:31+00 2022-05-26 09:04:31+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+1e5ab1ef-87e3-4ebc-92e9-ec9c0f7aaa9f 2022-05-26 09:04:31+00 2022-05-26 09:04:31+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+5e35d3e9-49a9-4976-a638-4e6764ccd426 2022-05-26 09:04:31+00 2022-05-26 09:04:31+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+7bab5fa6-6191-49b8-9c7e-8addeb144e8a 2022-05-26 09:04:31+00 2022-05-26 09:04:31+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+9bd52aa4-7158-4d06-81f2-a10f99e33f08 2022-05-26 09:04:31+00 2022-05-26 09:04:31+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+b26027f8-6fc2-46c7-aef7-d9cd67fbffe3 2022-05-26 09:04:31+00 2022-05-26 09:04:31+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+c00f7722-3c3f-498d-9808-cd4a86007958 2022-05-26 09:04:31+00 2022-05-26 09:04:31+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+c512e792-661f-4223-bc9d-6a9c059a4a09 2022-05-26 09:04:31+00 2022-05-26 09:04:31+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+5f154afd-4a66-4d1a-be2a-15354ad499fa 2022-05-26 09:04:31+00 2022-05-26 09:04:31+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+6226f972-df24-4f54-a21d-e90352622724 2022-05-26 09:04:31+00 2022-05-26 09:04:31+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+6337f622-dad3-40f7-9a25-acd776963042 2022-05-26 09:04:31+00 2022-05-26 09:04:31+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+f60b096f-1249-4270-80eb-b451330fc934 2022-05-26 09:04:31+00 2022-05-26 09:04:31+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+6f477457-1329-4c51-b556-9ab27a341116 2022-05-26 09:04:31+00 2022-05-26 09:04:31+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+ba259465-73c0-4035-af03-083de17865cd 2022-05-26 09:04:31+00 2022-05-26 09:04:31+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+ad7ba3c6-8d4c-4f5e-9c8b-58b6b7bc2b42 2022-05-26 09:04:31+00 2022-05-26 09:04:31+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+a3caefa8-c914-44c0-ab20-e5420eef9025 2022-05-26 09:04:31+00 2022-05-26 09:04:31+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+dadc0a91-472d-4792-9b8e-d573a52b9056 2022-05-26 09:04:31+00 2022-05-26 09:04:31+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+8b00c8a1-b680-492a-87eb-350ca72bc616 2022-05-26 09:04:31+00 2022-05-26 09:04:31+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+24fe112c-a8ae-4ee0-9abf-b5d8a8a61f65 2022-05-26 09:04:31+00 2022-05-26 09:04:31+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+33da5233-b9f0-4d03-964e-10a619eaa459 2022-05-26 09:04:31+00 2022-05-26 09:04:31+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+0158712b-2d90-482a-8ca0-5c4dfdf19d42 2022-05-26 09:04:31+00 2022-05-26 09:04:31+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+91dbc846-4c2b-48f0-a5a4-651c884f2b5b 2022-05-26 09:04:31+00 2022-05-26 09:04:31+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+5a2fb39c-5e8a-42ce-bcbe-a84fa6e4d12d 2022-05-26 09:04:31+00 2022-05-26 09:04:31+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+4994d988-d33f-46ae-bec1-f59018f68103 2022-05-26 09:04:32+00 2022-05-26 09:04:32+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+3d398236-c1e0-4051-9845-39c6d0d4b547 2022-05-26 09:04:32+00 2022-05-26 09:04:32+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+e2d0e93c-d371-4a4e-a0c8-f30530c873ab 2022-05-26 09:04:32+00 2022-05-26 09:04:32+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+ecea8625-a170-4648-b363-e132983ebbcf 2022-05-26 09:04:32+00 2022-05-26 09:04:32+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+bfb8643d-7f56-4d95-b2a7-cce9f6a75598 2022-05-26 09:04:32+00 2022-05-26 09:04:32+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+93947ca9-1278-4b68-bf9a-3be07d766959 2022-05-26 09:04:32+00 2022-05-26 09:04:32+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+b81aaca3-eebf-4445-8bd9-f803b8b54551 2022-05-26 09:04:32+00 2022-05-26 09:04:32+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+4f0fe748-796b-413f-a4f5-3cbbe44c27c2 2022-05-26 09:04:32+00 2022-05-26 09:04:32+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+f406cf4a-75c3-4ccf-8f36-9255b36e0f69 2022-05-26 09:04:32+00 2022-05-26 09:04:32+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+e2817bf9-36c2-4acf-8de3-4468b149d571 2022-05-26 09:04:32+00 2022-05-26 09:04:32+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+c3f8cf8e-0683-40bc-aabb-8695dce534a2 2022-05-26 09:04:32+00 2022-05-26 09:04:32+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+da395198-c4a7-4d67-9e0f-8ea9bd6a72db 2022-05-26 09:04:32+00 2022-05-26 09:04:32+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+e5763c8f-13d5-4f01-8ebd-b6db40a89fb0 2022-05-26 09:04:32+00 2022-05-26 09:04:32+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+1d84611e-9887-40c6-ab00-01210d1f82b7 2022-05-26 09:04:32+00 2022-05-26 09:04:32+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+c238d775-2523-46fc-8d1a-540fac1f6896 2022-05-26 09:04:32+00 2022-05-26 09:04:32+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+1d915ba2-c858-4732-a9e9-7b21b9d47b27 2022-05-26 09:04:32+00 2022-05-26 09:04:32+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+2ddd0eb3-bada-4443-bbfe-5fccde527dca 2022-05-26 09:04:32+00 2022-05-26 09:04:32+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+fb6cc1c1-f874-4ad9-9a62-3b406f948218 2022-05-26 09:04:32+00 2022-05-26 09:04:32+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+a7946bd4-5a6b-4f56-bbd5-59cf59fbacc3 2022-05-26 09:04:32+00 2022-05-26 09:04:32+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+c2a397d2-8f91-41d8-9158-97dd24955a80 2022-05-26 09:04:32+00 2022-05-26 09:04:32+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+959074dc-9a50-4bd8-bb49-d0a9333d0477 2022-05-26 09:04:32+00 2022-05-26 09:04:32+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+4fafaa54-d47d-4488-8c56-94be290f38b7 2022-05-26 09:04:32+00 2022-05-26 09:04:32+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+e9556ed2-8e33-4130-a9b9-fc6c799655fc 2022-05-26 09:04:32+00 2022-05-26 09:04:32+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+9a6c8306-cf36-42a6-9117-724b675fd9a2 2022-05-26 09:04:32+00 2022-05-26 09:04:32+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+af36e2ce-968f-4143-926c-34f5827a2319 2022-05-26 09:04:32+00 2022-05-26 09:04:32+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+59a3ea50-4f62-4ce2-ad54-8d72abe1ec68 2022-05-26 09:04:32+00 2022-05-26 09:04:32+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+45cc6295-8cfc-4e44-b124-0d05c04cdd3e 2022-05-26 09:04:32+00 2022-05-26 09:04:32+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+8b3db5a2-f3c4-4d2b-b60e-55c3f0d42960 2022-05-26 09:04:32+00 2022-05-26 09:04:32+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+809b0fa5-91fe-4f0b-bfa4-1b17ca92647f 2022-05-26 09:04:32+00 2022-05-26 09:04:32+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+c75cdbd1-8145-48ae-8097-d6ce0ee3d383 2022-05-26 09:04:32+00 2022-05-26 09:04:32+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+e238e1f2-7acb-4caf-a7b9-4abc165b2f78 2022-05-26 09:04:33+00 2022-05-26 09:04:33+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+579dd648-5a51-4240-9901-d59ea046dbe4 2022-05-26 09:04:33+00 2022-05-26 09:04:33+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+363e3fd7-2510-4b88-8b61-19c6a701a154 2022-05-26 09:04:33+00 2022-05-26 09:04:33+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+6bfe7e94-4211-492f-a9db-a6c81dd6f547 2022-05-26 09:04:33+00 2022-05-26 09:04:33+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+614a1279-a381-4be2-acef-301958e89071 2022-05-26 09:04:33+00 2022-05-26 09:04:33+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+3861f439-875f-453b-8651-03d9359f5788 2022-05-26 09:04:33+00 2022-05-26 09:04:33+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+0663d4a9-d9d4-4d92-ab92-8ecae04c5440 2022-05-26 09:04:33+00 2022-05-26 09:04:33+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+00a04a0e-8a61-497e-a1b7-555d9edebd3c 2022-05-26 09:04:33+00 2022-05-26 09:04:33+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+a90836ba-dcb3-4f3f-bf2c-02bc1d5f7453 2022-05-26 09:04:33+00 2022-05-26 09:04:33+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+001879e3-9e6a-49e1-8893-9bfa1ed0662f 2022-05-26 09:04:33+00 2022-05-26 09:04:33+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+3b864315-4410-47c4-8d1f-41340443be83 2022-05-26 09:04:33+00 2022-05-26 09:04:33+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+da92e9da-c205-44a5-8e55-6cabab24e221 2022-05-26 09:04:33+00 2022-05-26 09:04:33+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+ec7a7ee9-84ef-4e7e-86dc-6c1ea5db4019 2022-05-26 09:04:33+00 2022-05-26 09:04:33+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+de23c01f-138f-4b4f-b077-7966e5301849 2022-05-26 09:04:33+00 2022-05-26 09:04:33+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+2231820c-c6c6-4b43-8030-60d84ec840df 2022-05-26 09:04:33+00 2022-05-26 09:04:33+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+962b06e6-2702-4267-b103-b352f6b842a4 2022-05-26 09:04:33+00 2022-05-26 09:04:33+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+63bfee6a-6d44-4301-9cee-df0105f24f5e 2022-05-26 09:04:33+00 2022-05-26 09:04:33+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+c6a5a31e-2c88-47c4-8e9a-c60bece7ef75 2022-05-26 09:04:33+00 2022-05-26 09:04:33+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+2d096abd-ffb0-4143-96a4-7779218d6d4f 2022-05-26 09:04:33+00 2022-05-26 09:04:33+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+a10741c9-4ed7-422d-9f52-54c17c4bbd8b 2022-05-26 09:04:33+00 2022-05-26 09:04:33+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+234c48dd-9af4-4099-80ff-40ad13f89401 2022-05-26 09:04:33+00 2022-05-26 09:04:33+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+bb5d6545-d507-4b3a-ba24-bb510c914e95 2022-05-26 09:04:33+00 2022-05-26 09:04:33+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+28f712ea-c08c-4e7a-8cf9-4b13e36ff212 2022-05-26 09:04:33+00 2022-05-26 09:04:33+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+152a5d0e-dc5a-44d9-af10-8ec63701dd3b 2022-05-26 09:04:33+00 2022-05-26 09:04:33+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+93857261-5bcb-47aa-9144-22b35b135d4b 2022-05-26 09:04:33+00 2022-05-26 09:04:33+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+111f99da-d06d-4cb3-b864-8f3e1f49aa74 2022-05-26 09:04:33+00 2022-05-26 09:04:33+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+3924e923-d2f1-4275-8747-bd11ac4f74d3 2022-05-26 09:04:33+00 2022-05-26 09:04:33+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+a73038fe-4577-4639-a479-767f244244c3 2022-05-26 09:04:33+00 2022-05-26 09:04:33+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+4a062dd6-f1c2-4b36-ac1d-998925eb0b83 2022-05-26 09:04:34+00 2022-05-26 09:04:34+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+8c475290-e87c-4711-a6ac-d2dc4028fad6 2022-05-26 09:04:34+00 2022-05-26 09:04:34+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+8cec9caf-f09c-4e50-ab29-a23009c77cb7 2022-05-26 09:04:34+00 2022-05-26 09:04:34+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+3a1b190c-0930-4404-bee0-eca6c7621114 2022-05-26 09:04:34+00 2022-05-26 09:04:34+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+ccb26ed5-9dd0-46b3-8cb5-3584782c9d06 2022-05-26 09:04:34+00 2022-05-26 09:04:34+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+6bce2b2a-c6a0-4463-9dfc-bd9366f62b3a 2022-05-26 09:04:34+00 2022-05-26 09:04:34+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+050c4646-3958-40b1-92f3-2a7979732b5b 2022-05-26 09:04:34+00 2022-05-26 09:04:34+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+dfc084df-46cb-4a7e-b89c-b84ae3634ed3 2022-05-26 09:04:34+00 2022-05-26 09:04:34+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+5c96e4e4-bd3c-458a-aecb-70a0e97258d6 2022-05-26 09:04:34+00 2022-05-26 09:04:34+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+643ed9d5-7abd-498c-aa27-e54406f62657 2022-05-26 09:04:34+00 2022-05-26 09:04:34+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+3b43313b-92e3-4a71-89b9-5c94e508ffa4 2022-05-26 09:04:34+00 2022-05-26 09:04:34+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+d1f25d2e-1765-431d-b8ce-c971848c140b 2022-05-26 09:04:34+00 2022-05-26 09:04:34+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+a986ba78-0f21-4714-98af-030c39a99d98 2022-05-26 09:04:34+00 2022-05-26 09:04:34+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+186d8c4f-7240-47be-baec-da9793982cfe 2022-05-26 09:04:34+00 2022-05-26 09:04:34+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+29eb0b4a-38c1-44e3-a342-a738f884bdb8 2022-05-26 09:04:34+00 2022-05-26 09:04:34+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+d6344072-d70a-419e-b400-f792fd7816a6 2022-05-26 09:04:34+00 2022-05-26 09:04:34+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+65dbc1e9-8bf0-4494-b3e7-c6b6445d805f 2022-05-26 09:04:34+00 2022-05-26 09:04:34+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+82e159a7-b83d-4eb9-9228-26eea20c0301 2022-05-26 09:04:34+00 2022-05-26 09:04:34+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+85cab86c-ef60-4b00-ab3a-83649782cbdc 2022-05-26 09:04:34+00 2022-05-26 09:04:34+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+6d8a4447-dba8-40c4-8fa3-9ea447aa4431 2022-05-26 09:04:34+00 2022-05-26 09:04:34+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+297aa958-dd8d-4838-8658-21c7a2f6a45c 2022-05-26 09:04:34+00 2022-05-26 09:04:34+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+516d1b3c-20ec-4abe-9d05-7c10f45cc2b7 2022-05-26 09:04:34+00 2022-05-26 09:04:34+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+c2cfb252-5288-4b94-b4a8-79a8d86e6c7c 2022-05-26 09:04:34+00 2022-05-26 09:04:34+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+d32ddeef-adf4-43e5-b533-d6218f89194e 2022-05-26 09:04:34+00 2022-05-26 09:04:34+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+d735e2a6-44ce-421b-8041-dbeac83b0388 2022-05-26 09:04:34+00 2022-05-26 09:04:34+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+2f34b698-bdc6-4a34-8568-54e2051c301e 2022-05-26 09:04:34+00 2022-05-26 09:04:34+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+1f25c2c5-b997-474a-82c0-2dfe225b38f7 2022-05-26 09:04:34+00 2022-05-26 09:04:34+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+409a0334-ad83-4abe-92bf-9f86cee8e629 2022-05-26 09:04:34+00 2022-05-26 09:04:34+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+21a86be9-f740-47d6-aef6-ea678179d442 2022-05-26 09:04:34+00 2022-05-26 09:04:34+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+dc85040e-5868-4e67-99ae-ae2a83870651 2022-05-26 09:04:35+00 2022-05-26 09:04:35+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+83f56af1-9785-4627-8682-5d9f40d9e567 2022-05-26 09:04:35+00 2022-05-26 09:04:35+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+b8670494-46f7-4ac6-a67b-92662a89eabb 2022-05-26 09:04:35+00 2022-05-26 09:04:35+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+cb4d87c3-1fb7-4b16-8094-eed4a3d00968 2022-05-26 09:04:35+00 2022-05-26 09:04:35+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+106044fb-fc87-41f6-9e71-3faffe47e00b 2022-05-26 09:04:35+00 2022-05-26 09:04:35+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+a88fd1e2-7344-47b5-a7b8-9bd716f94c5d 2022-05-26 09:04:35+00 2022-05-26 09:04:35+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+53f91d1f-e644-4040-bb9c-009b94cdb8e8 2022-05-26 09:04:35+00 2022-05-26 09:04:35+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+dd07fe79-a01b-4e7e-b0d7-2556523cb39e 2022-05-26 09:04:35+00 2022-05-26 09:04:35+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+b2faf9ae-52e2-4dae-a484-7e9978de7057 2022-05-26 09:04:35+00 2022-05-26 09:04:35+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+587584bd-581c-4ec6-90a4-4196ebe3e639 2022-05-26 09:04:35+00 2022-05-26 09:04:35+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+c1e06d08-f053-4e2f-98cb-dfe2b4523fc8 2022-05-26 09:04:35+00 2022-05-26 09:04:35+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+ce17ffbe-39d4-4bba-badd-3fd6a51a909b 2022-05-26 09:04:35+00 2022-05-26 09:04:35+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+df0f28b8-833d-4962-9750-0e2c7dcf1aef 2022-05-26 09:04:35+00 2022-05-26 09:04:35+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+42463594-07f9-463b-8d3d-e640679cf9a0 2022-05-26 09:04:35+00 2022-05-26 09:04:35+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+8dc13325-56ce-4b86-bd36-b090b0f6caab 2022-05-26 09:04:35+00 2022-05-26 09:04:35+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+c629d453-a5a6-431f-8f90-9b27722a415a 2022-05-26 09:04:35+00 2022-05-26 09:04:35+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+c265592f-8adf-4f8c-bb4f-1b4a984dc600 2022-05-26 09:04:35+00 2022-05-26 09:04:35+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+bbfadf44-58fe-4693-9f6b-f1897ad92eb6 2022-05-26 09:04:35+00 2022-05-26 09:04:35+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+515bf1e2-6b17-448a-ad26-6276526a88c2 2022-05-26 09:04:35+00 2022-05-26 09:04:35+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+4f1086b3-8849-4d42-a9fb-5395f1cb573f 2022-05-26 09:04:35+00 2022-05-26 09:04:35+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+d0e54e7a-8475-44f5-af06-0852acc18ada 2022-05-26 09:04:35+00 2022-05-26 09:04:35+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+cedaaa13-f4a0-4aa1-86bd-29f20d10cb17 2022-05-26 09:04:35+00 2022-05-26 09:04:35+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+af2095eb-cb46-45e8-8e62-23c528e8451c 2022-05-26 09:04:35+00 2022-05-26 09:04:35+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+39f8b870-e4a7-4f7c-93ba-7354ffdc3b7a 2022-05-26 09:04:35+00 2022-05-26 09:04:35+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+8b196676-5e99-4ffb-9cf7-e59dd42c9b61 2022-05-26 09:04:35+00 2022-05-26 09:04:35+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+3ed2e405-1166-499d-84ca-abf27c4420d6 2022-05-26 09:04:35+00 2022-05-26 09:04:35+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+6e94f9f7-f322-4be2-a6e3-25220b00d9f6 2022-05-26 09:04:35+00 2022-05-26 09:04:35+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+2ee7b426-001c-4f81-a4b9-f5f6e94dacd9 2022-05-26 09:04:35+00 2022-05-26 09:04:35+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+c235ddd9-4a8b-4ed4-996d-f32d97c2febf 2022-05-26 09:04:35+00 2022-05-26 09:04:35+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+3443f990-ed97-482a-b60d-f9a4fae6dce7 2022-05-26 09:04:35+00 2022-05-26 09:04:35+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+bf3887ae-ebac-4278-aa88-b211be9a6ef4 2022-05-26 09:04:36+00 2022-05-26 09:04:36+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+f5db483a-11d5-4fb7-b977-ddb1b55b6923 2022-05-26 09:04:36+00 2022-05-26 09:04:36+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+7560adfa-0d51-42e6-b727-78821e9404f8 2022-05-26 09:04:36+00 2022-05-26 09:04:36+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+efe7075c-0084-4620-976d-57dcbaf3893b 2022-05-26 09:04:36+00 2022-05-26 09:04:36+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+f062ee0d-1d60-4ac5-bf80-fad59a54306f 2022-05-26 09:04:36+00 2022-05-26 09:04:36+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+838a3bbf-b6e9-4174-9e2f-4c5903f85b51 2022-05-26 09:04:36+00 2022-05-26 09:04:36+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+1813a575-32ba-4c94-99a5-19295b0921de 2022-05-26 09:04:36+00 2022-05-26 09:04:36+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+7aff390f-97f8-4e64-9b95-c85a9002c33c 2022-05-26 09:04:36+00 2022-05-26 09:04:36+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+c6298096-10b7-441c-9688-4695b88a8660 2022-05-26 09:04:36+00 2022-05-26 09:04:36+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+dada2f21-3866-4778-a319-a91f82f8ad76 2022-05-26 09:04:36+00 2022-05-26 09:04:36+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+f5016d6d-f10c-4846-83d5-7bf231c044d3 2022-05-26 09:04:36+00 2022-05-26 09:04:36+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+7463f25e-841f-4e23-9fb3-4dbe0c2554d2 2022-05-26 09:04:36+00 2022-05-26 09:04:36+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+1e87a29f-8009-41bd-8b71-f8800f1dab1e 2022-05-26 09:04:36+00 2022-05-26 09:04:36+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+30e14345-9d6a-42c1-b33f-59cb014e5b68 2022-05-26 09:04:36+00 2022-05-26 09:04:36+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+86c6fa66-322e-487a-8999-ecc03a830fd3 2022-05-26 09:04:36+00 2022-05-26 09:04:36+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+35847d15-de55-4a1b-9493-0d691a83a641 2022-05-26 09:04:36+00 2022-05-26 09:04:36+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+f18b3241-50bd-45b5-8c61-8858473e10fb 2022-05-26 09:04:36+00 2022-05-26 09:04:36+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+3f90d40a-eef1-4a6b-953c-6919087c9b6b 2022-05-26 09:04:36+00 2022-05-26 09:04:36+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+c81f7cfe-c388-4731-88f9-f3eccc0e1aae 2022-05-26 09:04:36+00 2022-05-26 09:04:36+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+54f45fd9-b956-4dd8-a9a2-aa025395fe9b 2022-05-26 09:04:36+00 2022-05-26 09:04:36+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+f0f92b13-e8a2-4208-af35-88c2f57053ed 2022-05-26 09:04:36+00 2022-05-26 09:04:36+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+50b2eea6-fcae-41c7-872a-7f725aad8f68 2022-05-26 09:04:36+00 2022-05-26 09:04:36+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+5d22741a-9f70-4978-a113-4e3370595e14 2022-05-26 09:04:36+00 2022-05-26 09:04:36+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+5e9f240d-6e21-4393-b37c-f9f1e8ca70f3 2022-05-26 09:04:36+00 2022-05-26 09:04:36+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+84d0828f-fe77-41f1-928e-11706edb8821 2022-05-26 09:04:36+00 2022-05-26 09:04:36+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+7c9d3f4c-4e57-450e-b12f-7db6ebcb9aea 2022-05-26 09:04:36+00 2022-05-26 09:04:36+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+b1f4f818-0f47-4372-868c-df50e9603ed0 2022-05-26 09:04:36+00 2022-05-26 09:04:36+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+ea4910d2-9eaa-4e94-8f10-94d0da66aa12 2022-05-26 09:04:36+00 2022-05-26 09:04:36+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+84164c99-8064-4616-9b89-4ad2cd3ee6da 2022-05-26 09:04:36+00 2022-05-26 09:04:36+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+64f3861f-7ec7-45bf-a781-73de35a51bf3 2022-05-26 09:04:37+00 2022-05-26 09:04:37+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+0501b4de-a562-45ac-a4f8-ca0b0a5f2be4 2022-05-26 09:04:37+00 2022-05-26 09:04:37+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+edf40205-69ee-4f3b-ba0c-09d70531b17b 2022-05-26 09:04:37+00 2022-05-26 09:04:37+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+f18530a1-b79f-404c-97b5-c8cb7d4df0d3 2022-05-26 09:04:37+00 2022-05-26 09:04:37+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+6b7f220c-1df2-41b3-9ea3-a6bd5ece4a4f 2022-05-26 09:04:37+00 2022-05-26 09:04:37+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+06b00f42-c69b-4243-8506-582504283fb7 2022-05-26 09:04:37+00 2022-05-26 09:04:37+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+9fa2ce85-2954-470e-9a8f-b80a94d18b5c 2022-05-26 09:04:37+00 2022-05-26 09:04:37+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+690744c2-57e5-458b-aa9c-eec197957ecc 2022-05-26 09:04:37+00 2022-05-26 09:04:37+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+4a74034a-2448-42f4-98d3-dc1fe050f6ce 2022-05-26 09:04:37+00 2022-05-26 09:04:37+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+c4507468-ff51-4d6f-977f-0969cca30830 2022-05-26 09:04:37+00 2022-05-26 09:04:37+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+6c865afc-9439-411c-ade4-6fd8ac429c07 2022-05-26 09:04:37+00 2022-05-26 09:04:37+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+e04db553-36a3-468d-82b4-938514fc8cdb 2022-05-26 09:04:37+00 2022-05-26 09:04:37+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+ecaca662-b04b-474b-a038-c185ac99a3e1 2022-05-26 09:04:37+00 2022-05-26 09:04:37+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+3c19f673-974e-4d27-8aa8-c8b3be9a268a 2022-05-26 09:04:37+00 2022-05-26 09:04:37+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+6c5851b2-0b70-4fd8-9d95-b5f60e89b8d8 2022-05-26 09:04:37+00 2022-05-26 09:04:37+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+ca7691e7-644f-4503-8661-255efc4f2d73 2022-05-26 09:04:37+00 2022-05-26 09:04:37+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+c520c41e-eaac-436b-8943-9d96b749a386 2022-05-26 09:04:37+00 2022-05-26 09:04:37+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+35071e24-8e47-4af5-adfd-b91431777cfb 2022-05-26 09:04:37+00 2022-05-26 09:04:37+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+3206e638-1f43-47b7-8b36-e5a70cf785b2 2022-05-26 09:04:37+00 2022-05-26 09:04:37+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+d665c6e1-e3a9-4f58-bb0b-29a67711080f 2022-05-26 09:04:37+00 2022-05-26 09:04:37+00 \N 5 http 172.17.0.15 18088 /test 60000 60000 60000 \N \N \N \N \N dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t
+\.
+
+
+--
+-- Data for Name: routes; Type: TABLE DATA; Schema: public; Owner: kong
+--
+
+COPY public.routes (id, created_at, updated_at, name, service_id, protocols, methods, hosts, paths, snis, sources, destinations, regex_priority, strip_path, preserve_host, tags, https_redirect_status_code, headers, path_handling, ws_id, request_buffering, response_buffering) FROM stdin;
+ce537a9f-a4b0-4104-aafd-97003b6bd094 2022-05-26 09:04:20+00 2022-05-26 09:04:20+00 \N a7182665-e3bb-4ad0-91bc-bb013404d465 {http,https} \N \N {/s1-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+026dab0d-bb9f-4d78-86c6-573ae01c04d8 2022-05-26 09:04:20+00 2022-05-26 09:04:20+00 \N a7182665-e3bb-4ad0-91bc-bb013404d465 {http,https} \N \N {/s1-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+7d278d10-142a-451d-866c-86ae52e3ba14 2022-05-26 09:04:20+00 2022-05-26 09:04:20+00 \N a7182665-e3bb-4ad0-91bc-bb013404d465 {http,https} \N \N {/s1-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+990d5f16-8024-4568-811f-117504c9990b 2022-05-26 09:04:20+00 2022-05-26 09:04:20+00 \N a7182665-e3bb-4ad0-91bc-bb013404d465 {http,https} \N \N {/s1-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+f3ede165-bfca-4ab9-9db7-f9c2de77039e 2022-05-26 09:04:20+00 2022-05-26 09:04:20+00 \N 3c089a41-3c85-4e95-94bc-9dcbcc02d5bf {http,https} \N \N {/s2-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+951b5a6f-b4d2-4ed4-87ff-dfeb57555c7e 2022-05-26 09:04:20+00 2022-05-26 09:04:20+00 \N 3c089a41-3c85-4e95-94bc-9dcbcc02d5bf {http,https} \N \N {/s2-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+dda0f202-7c28-429d-8ec8-161e9e31514e 2022-05-26 09:04:20+00 2022-05-26 09:04:20+00 \N 3c089a41-3c85-4e95-94bc-9dcbcc02d5bf {http,https} \N \N {/s2-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+87655776-806e-47ed-baa3-3fbf5a758c4a 2022-05-26 09:04:20+00 2022-05-26 09:04:20+00 \N 3c089a41-3c85-4e95-94bc-9dcbcc02d5bf {http,https} \N \N {/s2-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+f8b9a2ce-83aa-4af4-8ce7-436cedf59d26 2022-05-26 09:04:20+00 2022-05-26 09:04:20+00 \N e4e0c0f8-8f86-4138-b90b-1ab4b42c545a {http,https} \N \N {/s3-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+83d60efb-3057-4303-9114-916a98a99889 2022-05-26 09:04:20+00 2022-05-26 09:04:20+00 \N e4e0c0f8-8f86-4138-b90b-1ab4b42c545a {http,https} \N \N {/s3-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+d32ba84f-ebb5-4ebf-a19f-50d4d0ff3c98 2022-05-26 09:04:20+00 2022-05-26 09:04:20+00 \N e4e0c0f8-8f86-4138-b90b-1ab4b42c545a {http,https} \N \N {/s3-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+67f1d309-3609-4eff-ba4d-f05413c56570 2022-05-26 09:04:20+00 2022-05-26 09:04:20+00 \N e4e0c0f8-8f86-4138-b90b-1ab4b42c545a {http,https} \N \N {/s3-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+2938219c-3438-4647-a665-2a2bfa59a166 2022-05-26 09:04:20+00 2022-05-26 09:04:20+00 \N 635667df-d7c8-4c8e-961a-79094fb7edf7 {http,https} \N \N {/s4-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+43acaeda-d0b1-4660-a71a-131268b234b0 2022-05-26 09:04:20+00 2022-05-26 09:04:20+00 \N 635667df-d7c8-4c8e-961a-79094fb7edf7 {http,https} \N \N {/s4-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+db8f7f38-cba3-41b1-b824-c939b1dd4386 2022-05-26 09:04:20+00 2022-05-26 09:04:20+00 \N 635667df-d7c8-4c8e-961a-79094fb7edf7 {http,https} \N \N {/s4-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+b8c7f85d-4ec7-4921-b50b-720c26bac325 2022-05-26 09:04:20+00 2022-05-26 09:04:20+00 \N 635667df-d7c8-4c8e-961a-79094fb7edf7 {http,https} \N \N {/s4-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+abca1b75-1d6d-462c-9787-48122922fb65 2022-05-26 09:04:20+00 2022-05-26 09:04:20+00 \N 5db07df7-6efa-42f1-b526-aeea5f46aa7f {http,https} \N \N {/s5-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+1da0d3cf-1d35-4e93-9855-6bd555445561 2022-05-26 09:04:20+00 2022-05-26 09:04:20+00 \N 5db07df7-6efa-42f1-b526-aeea5f46aa7f {http,https} \N \N {/s5-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+e4073ba4-1f39-4ea5-92b9-ee723f1c7726 2022-05-26 09:04:20+00 2022-05-26 09:04:20+00 \N 5db07df7-6efa-42f1-b526-aeea5f46aa7f {http,https} \N \N {/s5-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+064d691b-e410-414f-9a14-1375cfdfc3c9 2022-05-26 09:04:20+00 2022-05-26 09:04:20+00 \N 5db07df7-6efa-42f1-b526-aeea5f46aa7f {http,https} \N \N {/s5-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+ab58907f-2df9-4170-b0f0-ad00fb5d387f 2022-05-26 09:04:20+00 2022-05-26 09:04:20+00 \N 0cf9ed94-6fe4-4356-906d-34bf7f5e323d {http,https} \N \N {/s6-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+506a4858-240b-4339-9d13-8018fb2a839c 2022-05-26 09:04:20+00 2022-05-26 09:04:20+00 \N 0cf9ed94-6fe4-4356-906d-34bf7f5e323d {http,https} \N \N {/s6-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+720ec3bf-2799-43e6-a16a-4e8e21e64c8a 2022-05-26 09:04:20+00 2022-05-26 09:04:20+00 \N 0cf9ed94-6fe4-4356-906d-34bf7f5e323d {http,https} \N \N {/s6-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+89190960-6e45-480a-8a02-13a48244eacc 2022-05-26 09:04:20+00 2022-05-26 09:04:20+00 \N 0cf9ed94-6fe4-4356-906d-34bf7f5e323d {http,https} \N \N {/s6-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+de05c71c-0e19-4909-9dc8-0f02b07f4d3a 2022-05-26 09:04:20+00 2022-05-26 09:04:20+00 \N b0d849d4-9d3d-48bd-bddd-59aeed02789c {http,https} \N \N {/s7-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+0cc280f0-5fc2-4379-b26c-a29564103995 2022-05-26 09:04:20+00 2022-05-26 09:04:20+00 \N b0d849d4-9d3d-48bd-bddd-59aeed02789c {http,https} \N \N {/s7-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+eded9ada-6e08-41cf-aa4f-217e6c57529e 2022-05-26 09:04:20+00 2022-05-26 09:04:20+00 \N b0d849d4-9d3d-48bd-bddd-59aeed02789c {http,https} \N \N {/s7-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+81d8b01a-fd3e-45d2-bb08-329d107c13cf 2022-05-26 09:04:20+00 2022-05-26 09:04:20+00 \N b0d849d4-9d3d-48bd-bddd-59aeed02789c {http,https} \N \N {/s7-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+9ef63d3e-c320-47ee-a73f-ccf836e589a1 2022-05-26 09:04:20+00 2022-05-26 09:04:20+00 \N d609eb1a-3c6c-4867-ae94-ad5757bab196 {http,https} \N \N {/s8-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+ba1fa05f-e8f5-4f8d-a3fd-3c2df6dedee2 2022-05-26 09:04:20+00 2022-05-26 09:04:20+00 \N d609eb1a-3c6c-4867-ae94-ad5757bab196 {http,https} \N \N {/s8-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+f0eea660-89a0-4742-b94b-b5f3d13e1750 2022-05-26 09:04:20+00 2022-05-26 09:04:20+00 \N d609eb1a-3c6c-4867-ae94-ad5757bab196 {http,https} \N \N {/s8-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+601c7cb8-8e28-4fac-ab85-c7f24b74f0d3 2022-05-26 09:04:20+00 2022-05-26 09:04:20+00 \N d609eb1a-3c6c-4867-ae94-ad5757bab196 {http,https} \N \N {/s8-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+e1cbed49-b206-4dbe-a7dc-4a92e4eecc39 2022-05-26 09:04:20+00 2022-05-26 09:04:20+00 \N d92656d5-a8d8-4bab-93cf-5c5630eceffb {http,https} \N \N {/s9-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+11a07f35-5489-46bf-ac75-9169be6b137e 2022-05-26 09:04:20+00 2022-05-26 09:04:20+00 \N d92656d5-a8d8-4bab-93cf-5c5630eceffb {http,https} \N \N {/s9-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+d12800df-5095-4753-8269-1a75098bb08f 2022-05-26 09:04:20+00 2022-05-26 09:04:20+00 \N d92656d5-a8d8-4bab-93cf-5c5630eceffb {http,https} \N \N {/s9-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+7e2f69a1-3bd6-4676-be97-f89694953713 2022-05-26 09:04:20+00 2022-05-26 09:04:20+00 \N d92656d5-a8d8-4bab-93cf-5c5630eceffb {http,https} \N \N {/s9-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+aa2a94b7-2b36-49bc-bd65-e9eeefe04497 2022-05-26 09:04:20+00 2022-05-26 09:04:20+00 \N 1e306cf3-2a3b-40b8-91b4-f50caf61d455 {http,https} \N \N {/s10-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+39809835-2739-4f66-b3d4-bfea8be6ede4 2022-05-26 09:04:20+00 2022-05-26 09:04:20+00 \N 1e306cf3-2a3b-40b8-91b4-f50caf61d455 {http,https} \N \N {/s10-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+530b83b7-8e49-47a2-86ee-d1fd4f9eaf9f 2022-05-26 09:04:20+00 2022-05-26 09:04:20+00 \N 1e306cf3-2a3b-40b8-91b4-f50caf61d455 {http,https} \N \N {/s10-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+d6817e92-beba-465b-8352-735005f5e981 2022-05-26 09:04:20+00 2022-05-26 09:04:20+00 \N 1e306cf3-2a3b-40b8-91b4-f50caf61d455 {http,https} \N \N {/s10-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+df99cf4e-cd34-4be5-98d6-8470c1c1c211 2022-05-26 09:04:20+00 2022-05-26 09:04:20+00 \N b13775fd-dac8-4322-b7a4-a089d677c22d {http,https} \N \N {/s11-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+ab0e0fb7-5928-48ab-989a-2081b43e7245 2022-05-26 09:04:20+00 2022-05-26 09:04:20+00 \N b13775fd-dac8-4322-b7a4-a089d677c22d {http,https} \N \N {/s11-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+687dd969-c8f6-44f3-b371-e631048cb4cc 2022-05-26 09:04:20+00 2022-05-26 09:04:20+00 \N b13775fd-dac8-4322-b7a4-a089d677c22d {http,https} \N \N {/s11-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+fe454395-7df3-44ed-a95b-9e629e9cd650 2022-05-26 09:04:20+00 2022-05-26 09:04:20+00 \N b13775fd-dac8-4322-b7a4-a089d677c22d {http,https} \N \N {/s11-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+cb222d61-3fe9-4735-9405-e15ff5e8a121 2022-05-26 09:04:20+00 2022-05-26 09:04:20+00 \N 0d5ae4f4-5ab1-4320-8057-cd0b21d81496 {http,https} \N \N {/s12-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+7ddf114b-6438-4bbf-abd3-413def649544 2022-05-26 09:04:20+00 2022-05-26 09:04:20+00 \N 0d5ae4f4-5ab1-4320-8057-cd0b21d81496 {http,https} \N \N {/s12-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+268e6d41-da24-4004-81c0-f8921fc1a899 2022-05-26 09:04:20+00 2022-05-26 09:04:20+00 \N 0d5ae4f4-5ab1-4320-8057-cd0b21d81496 {http,https} \N \N {/s12-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+6c748b5f-ddd3-4689-a68f-fc170bc46870 2022-05-26 09:04:20+00 2022-05-26 09:04:20+00 \N 0d5ae4f4-5ab1-4320-8057-cd0b21d81496 {http,https} \N \N {/s12-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+87de8f22-9a89-470f-bc3d-d2d6bad9afc0 2022-05-26 09:04:20+00 2022-05-26 09:04:20+00 \N e6a15913-9bdf-46ed-8e9e-b71a91b1197a {http,https} \N \N {/s13-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+4d34d19f-f9f1-4d8a-9771-33a5b50ed259 2022-05-26 09:04:20+00 2022-05-26 09:04:20+00 \N e6a15913-9bdf-46ed-8e9e-b71a91b1197a {http,https} \N \N {/s13-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+85a52175-ec74-448b-8119-167cfc2eb741 2022-05-26 09:04:20+00 2022-05-26 09:04:20+00 \N e6a15913-9bdf-46ed-8e9e-b71a91b1197a {http,https} \N \N {/s13-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+518ae3ba-72fa-43eb-9ad4-b74bcbddae72 2022-05-26 09:04:20+00 2022-05-26 09:04:20+00 \N e6a15913-9bdf-46ed-8e9e-b71a91b1197a {http,https} \N \N {/s13-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+d74ab53d-6bf3-4927-8905-8f365b6ec8ad 2022-05-26 09:04:20+00 2022-05-26 09:04:20+00 \N 9124182f-7ccf-465a-9553-4802b87f4308 {http,https} \N \N {/s14-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+9d845b80-bdc8-4142-b388-7318003da3b7 2022-05-26 09:04:20+00 2022-05-26 09:04:20+00 \N 9124182f-7ccf-465a-9553-4802b87f4308 {http,https} \N \N {/s14-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+50cd9f88-ebdf-480f-9ef8-7fb900dc1b2c 2022-05-26 09:04:20+00 2022-05-26 09:04:20+00 \N 9124182f-7ccf-465a-9553-4802b87f4308 {http,https} \N \N {/s14-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+f9362a76-362f-4620-b9e9-8ee86a71fb1f 2022-05-26 09:04:20+00 2022-05-26 09:04:20+00 \N 9124182f-7ccf-465a-9553-4802b87f4308 {http,https} \N \N {/s14-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+b105fd40-f6b8-4d6f-b677-b89354ffbe10 2022-05-26 09:04:20+00 2022-05-26 09:04:20+00 \N ad9d034f-2de2-4a1a-90ad-7f1cf7039a2a {http,https} \N \N {/s15-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+a9020690-1174-4166-8046-8d7fff7e47dd 2022-05-26 09:04:20+00 2022-05-26 09:04:20+00 \N ad9d034f-2de2-4a1a-90ad-7f1cf7039a2a {http,https} \N \N {/s15-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+f30c6ce3-bf1e-4a60-8f7b-bd1381e1ff35 2022-05-26 09:04:20+00 2022-05-26 09:04:20+00 \N ad9d034f-2de2-4a1a-90ad-7f1cf7039a2a {http,https} \N \N {/s15-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+18f0c2ff-0553-484d-bcdd-eca0c08ed669 2022-05-26 09:04:20+00 2022-05-26 09:04:20+00 \N ad9d034f-2de2-4a1a-90ad-7f1cf7039a2a {http,https} \N \N {/s15-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+bb92af61-c9af-42d1-adab-94110ffa746f 2022-05-26 09:04:20+00 2022-05-26 09:04:20+00 \N 9d36f4e2-ba97-4da7-9f10-133270adbc2e {http,https} \N \N {/s16-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+56a88ba6-ca21-4209-86d3-1962008dd901 2022-05-26 09:04:20+00 2022-05-26 09:04:20+00 \N 9d36f4e2-ba97-4da7-9f10-133270adbc2e {http,https} \N \N {/s16-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+886aa74b-b7e2-4b61-8032-5a2b535835fe 2022-05-26 09:04:20+00 2022-05-26 09:04:20+00 \N 9d36f4e2-ba97-4da7-9f10-133270adbc2e {http,https} \N \N {/s16-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+a7a6feb5-505d-434c-ac5f-eb950f1c6182 2022-05-26 09:04:20+00 2022-05-26 09:04:20+00 \N 9d36f4e2-ba97-4da7-9f10-133270adbc2e {http,https} \N \N {/s16-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+6424529b-bb46-426c-aa19-f152165a324b 2022-05-26 09:04:20+00 2022-05-26 09:04:20+00 \N 71164672-4b79-4b4c-8f23-d7b3d193996f {http,https} \N \N {/s17-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+be9aad50-ec49-4814-9039-4ff577f7569b 2022-05-26 09:04:20+00 2022-05-26 09:04:20+00 \N 71164672-4b79-4b4c-8f23-d7b3d193996f {http,https} \N \N {/s17-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+0eefde66-b48e-455d-9bc8-92acd58b560a 2022-05-26 09:04:20+00 2022-05-26 09:04:20+00 \N 71164672-4b79-4b4c-8f23-d7b3d193996f {http,https} \N \N {/s17-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+d635dbe5-5d60-454f-a3da-6ac2533c1e74 2022-05-26 09:04:20+00 2022-05-26 09:04:20+00 \N 71164672-4b79-4b4c-8f23-d7b3d193996f {http,https} \N \N {/s17-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+b3840619-8d47-4100-a917-7691e5497e38 2022-05-26 09:04:20+00 2022-05-26 09:04:20+00 \N d2c68623-5766-4b26-a956-aa750b23e6b9 {http,https} \N \N {/s18-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+d2566c3f-2118-4606-bf81-e95fa302e846 2022-05-26 09:04:20+00 2022-05-26 09:04:20+00 \N d2c68623-5766-4b26-a956-aa750b23e6b9 {http,https} \N \N {/s18-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+e90c02a9-bda8-4bfe-8eb1-d940fcbb7fc2 2022-05-26 09:04:20+00 2022-05-26 09:04:20+00 \N d2c68623-5766-4b26-a956-aa750b23e6b9 {http,https} \N \N {/s18-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+3ed8af14-3b87-4905-b340-59ec4dd04e8a 2022-05-26 09:04:20+00 2022-05-26 09:04:20+00 \N d2c68623-5766-4b26-a956-aa750b23e6b9 {http,https} \N \N {/s18-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+e4e90c18-64d2-4853-b682-73a469787fe0 2022-05-26 09:04:20+00 2022-05-26 09:04:20+00 \N c733f9c1-8fb2-4c99-9229-d9a3fe79420f {http,https} \N \N {/s19-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+fb9f0ded-d0b8-4c03-a073-89c598b19c08 2022-05-26 09:04:20+00 2022-05-26 09:04:20+00 \N c733f9c1-8fb2-4c99-9229-d9a3fe79420f {http,https} \N \N {/s19-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+198ff565-1db6-40d2-8457-2660761f281a 2022-05-26 09:04:20+00 2022-05-26 09:04:20+00 \N c733f9c1-8fb2-4c99-9229-d9a3fe79420f {http,https} \N \N {/s19-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+fdb2ac7c-69cd-4564-a503-9b7bfa2d76a0 2022-05-26 09:04:20+00 2022-05-26 09:04:20+00 \N c733f9c1-8fb2-4c99-9229-d9a3fe79420f {http,https} \N \N {/s19-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+a3b39229-514e-413c-ae7b-ee17bdf507eb 2022-05-26 09:04:20+00 2022-05-26 09:04:20+00 \N 879a9948-ed52-4827-b326-232b434d6586 {http,https} \N \N {/s20-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+26841471-0b61-4845-b128-d428f9919ee7 2022-05-26 09:04:20+00 2022-05-26 09:04:20+00 \N 879a9948-ed52-4827-b326-232b434d6586 {http,https} \N \N {/s20-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+29ff0e49-5e6d-482a-8a50-72b979170e93 2022-05-26 09:04:20+00 2022-05-26 09:04:20+00 \N 879a9948-ed52-4827-b326-232b434d6586 {http,https} \N \N {/s20-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+d94f7d16-b7e1-4eec-adfc-c144e166f9b0 2022-05-26 09:04:20+00 2022-05-26 09:04:20+00 \N 879a9948-ed52-4827-b326-232b434d6586 {http,https} \N \N {/s20-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+c5db351e-2352-43d3-b046-6ec73064c5a0 2022-05-26 09:04:20+00 2022-05-26 09:04:20+00 \N 6c2f637e-3365-4475-854d-2da53cf54236 {http,https} \N \N {/s21-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+cbb4f546-15a9-482d-a808-1d1359ac1d19 2022-05-26 09:04:20+00 2022-05-26 09:04:20+00 \N 6c2f637e-3365-4475-854d-2da53cf54236 {http,https} \N \N {/s21-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+549e80fd-38c1-4cb9-bbf1-561eb56bf039 2022-05-26 09:04:20+00 2022-05-26 09:04:20+00 \N 6c2f637e-3365-4475-854d-2da53cf54236 {http,https} \N \N {/s21-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+dfc428de-00bc-4def-b283-cf4cfef5d33e 2022-05-26 09:04:20+00 2022-05-26 09:04:20+00 \N 6c2f637e-3365-4475-854d-2da53cf54236 {http,https} \N \N {/s21-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+b8a634c1-3431-48e9-949c-dc813a26c0e5 2022-05-26 09:04:21+00 2022-05-26 09:04:21+00 \N e5322b5b-36ef-4b9d-9238-99de86473537 {http,https} \N \N {/s22-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+ffafdf04-2fff-47ca-a8c0-0af508ebff8b 2022-05-26 09:04:21+00 2022-05-26 09:04:21+00 \N e5322b5b-36ef-4b9d-9238-99de86473537 {http,https} \N \N {/s22-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+cc56a218-8f01-43a3-bfbf-8898f9f077c3 2022-05-26 09:04:21+00 2022-05-26 09:04:21+00 \N e5322b5b-36ef-4b9d-9238-99de86473537 {http,https} \N \N {/s22-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+90ad98ec-a31f-4519-9c73-e862c7d4d6d9 2022-05-26 09:04:21+00 2022-05-26 09:04:21+00 \N e5322b5b-36ef-4b9d-9238-99de86473537 {http,https} \N \N {/s22-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+0edca7d2-23cc-47e5-b4a6-7f9e7da0c027 2022-05-26 09:04:21+00 2022-05-26 09:04:21+00 \N d71477b1-e512-4b80-b755-d0a074de32c5 {http,https} \N \N {/s23-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+ddca0b2a-92fe-4a65-9478-6b41ea60c00c 2022-05-26 09:04:21+00 2022-05-26 09:04:21+00 \N d71477b1-e512-4b80-b755-d0a074de32c5 {http,https} \N \N {/s23-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+457feef6-a801-40e9-b4ce-d399837dca7d 2022-05-26 09:04:21+00 2022-05-26 09:04:21+00 \N d71477b1-e512-4b80-b755-d0a074de32c5 {http,https} \N \N {/s23-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+f70623a9-84ca-49ef-aee5-4c52eafa03ab 2022-05-26 09:04:21+00 2022-05-26 09:04:21+00 \N d71477b1-e512-4b80-b755-d0a074de32c5 {http,https} \N \N {/s23-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+4aa16fb3-d011-4567-8176-657a667209cb 2022-05-26 09:04:21+00 2022-05-26 09:04:21+00 \N 548bb3e7-fc07-41c9-9299-84a0708a2a59 {http,https} \N \N {/s24-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+ba2fc179-cfcd-4a3b-ab21-ce4b8e972aaf 2022-05-26 09:04:21+00 2022-05-26 09:04:21+00 \N 548bb3e7-fc07-41c9-9299-84a0708a2a59 {http,https} \N \N {/s24-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+6e85ad75-31f0-4d3d-8e6c-1a9f1bdfe081 2022-05-26 09:04:21+00 2022-05-26 09:04:21+00 \N 548bb3e7-fc07-41c9-9299-84a0708a2a59 {http,https} \N \N {/s24-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+4a07074a-c606-48bd-abb4-2444416c6d12 2022-05-26 09:04:21+00 2022-05-26 09:04:21+00 \N 548bb3e7-fc07-41c9-9299-84a0708a2a59 {http,https} \N \N {/s24-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+0c9fe8c7-ae08-45b1-8d4c-2747e825afd4 2022-05-26 09:04:21+00 2022-05-26 09:04:21+00 \N 4ce0aa65-7a39-4c13-8560-50cbbfbfb393 {http,https} \N \N {/s25-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+64a162fc-842f-4c07-beaf-55a86c16f24a 2022-05-26 09:04:21+00 2022-05-26 09:04:21+00 \N 4ce0aa65-7a39-4c13-8560-50cbbfbfb393 {http,https} \N \N {/s25-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+683651ca-d817-4ab7-8feb-e54d9eddcc53 2022-05-26 09:04:21+00 2022-05-26 09:04:21+00 \N 4ce0aa65-7a39-4c13-8560-50cbbfbfb393 {http,https} \N \N {/s25-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+3ec12d55-4015-4b04-8093-cccc7e7d2661 2022-05-26 09:04:21+00 2022-05-26 09:04:21+00 \N 4ce0aa65-7a39-4c13-8560-50cbbfbfb393 {http,https} \N \N {/s25-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+4e7e4ceb-f130-480c-8241-7a77c918d0f3 2022-05-26 09:04:21+00 2022-05-26 09:04:21+00 \N f4dae3be-eb46-4361-b84c-da2f83277f00 {http,https} \N \N {/s26-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+d601e820-4af1-4cb0-af6a-0f7ad0dae115 2022-05-26 09:04:21+00 2022-05-26 09:04:21+00 \N f4dae3be-eb46-4361-b84c-da2f83277f00 {http,https} \N \N {/s26-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+b763763f-0334-45cc-9475-947acf30317a 2022-05-26 09:04:21+00 2022-05-26 09:04:21+00 \N f4dae3be-eb46-4361-b84c-da2f83277f00 {http,https} \N \N {/s26-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+918dfc23-1bf0-455f-8246-e9fdf3482af3 2022-05-26 09:04:21+00 2022-05-26 09:04:21+00 \N f4dae3be-eb46-4361-b84c-da2f83277f00 {http,https} \N \N {/s26-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+a4069609-ba31-4814-a0c7-b9ee8d929864 2022-05-26 09:04:21+00 2022-05-26 09:04:21+00 \N 25076386-d45e-40fb-bf23-6078de3ecab7 {http,https} \N \N {/s27-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+e996f687-3c69-42d5-86b9-79bc5a996483 2022-05-26 09:04:21+00 2022-05-26 09:04:21+00 \N 25076386-d45e-40fb-bf23-6078de3ecab7 {http,https} \N \N {/s27-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+ab23c967-bcac-4ac5-a1d7-91a32dd62f97 2022-05-26 09:04:21+00 2022-05-26 09:04:21+00 \N 25076386-d45e-40fb-bf23-6078de3ecab7 {http,https} \N \N {/s27-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+9a824c45-c692-48be-a227-344f969f79fb 2022-05-26 09:04:21+00 2022-05-26 09:04:21+00 \N 25076386-d45e-40fb-bf23-6078de3ecab7 {http,https} \N \N {/s27-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+bf57fa62-4d82-421e-8128-b63389a7c31a 2022-05-26 09:04:21+00 2022-05-26 09:04:21+00 \N 1525a86d-6ae4-421e-a2dc-d5758ba22312 {http,https} \N \N {/s28-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+9dac7bc5-4c4c-418b-9687-bd993813d177 2022-05-26 09:04:21+00 2022-05-26 09:04:21+00 \N 1525a86d-6ae4-421e-a2dc-d5758ba22312 {http,https} \N \N {/s28-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+9d8db65b-05e9-4eb2-bec1-6ecc475c502e 2022-05-26 09:04:21+00 2022-05-26 09:04:21+00 \N 1525a86d-6ae4-421e-a2dc-d5758ba22312 {http,https} \N \N {/s28-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+c8a45988-17e9-44a4-b52f-632754ec0e01 2022-05-26 09:04:21+00 2022-05-26 09:04:21+00 \N 1525a86d-6ae4-421e-a2dc-d5758ba22312 {http,https} \N \N {/s28-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+669e731d-8cae-4104-a4ef-d66b111b874a 2022-05-26 09:04:21+00 2022-05-26 09:04:21+00 \N 2c961425-9119-41ad-8df7-7b288060e995 {http,https} \N \N {/s29-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+dbcdd268-877e-4f91-9b60-8b36b84d2c96 2022-05-26 09:04:21+00 2022-05-26 09:04:21+00 \N 2c961425-9119-41ad-8df7-7b288060e995 {http,https} \N \N {/s29-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+c4dfd810-a17e-499d-94b0-7e638aaecba6 2022-05-26 09:04:21+00 2022-05-26 09:04:21+00 \N 2c961425-9119-41ad-8df7-7b288060e995 {http,https} \N \N {/s29-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+1c7bc1c1-bda1-4ef4-8a62-b7d634f6f203 2022-05-26 09:04:21+00 2022-05-26 09:04:21+00 \N 2c961425-9119-41ad-8df7-7b288060e995 {http,https} \N \N {/s29-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+5dc8539b-5cca-4efc-8669-2219dc5d448f 2022-05-26 09:04:21+00 2022-05-26 09:04:21+00 \N b960c35a-83b5-425b-9fe3-2602de569f5d {http,https} \N \N {/s30-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+b58cef55-87f5-4cda-9721-2a4c84b25989 2022-05-26 09:04:21+00 2022-05-26 09:04:21+00 \N b960c35a-83b5-425b-9fe3-2602de569f5d {http,https} \N \N {/s30-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+7dd956b6-1ef4-4a41-87e8-368ef00fe657 2022-05-26 09:04:21+00 2022-05-26 09:04:21+00 \N b960c35a-83b5-425b-9fe3-2602de569f5d {http,https} \N \N {/s30-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+4947d674-d901-41de-bdbb-3dccd8481324 2022-05-26 09:04:21+00 2022-05-26 09:04:21+00 \N b960c35a-83b5-425b-9fe3-2602de569f5d {http,https} \N \N {/s30-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+fefc368e-d9cc-4755-98c3-566e6f09ca09 2022-05-26 09:04:21+00 2022-05-26 09:04:21+00 \N a882f2cc-b1ac-40a4-8e5d-09d9595c5140 {http,https} \N \N {/s31-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+36e460b6-9905-4bb6-861a-86a0ab41a8f8 2022-05-26 09:04:21+00 2022-05-26 09:04:21+00 \N a882f2cc-b1ac-40a4-8e5d-09d9595c5140 {http,https} \N \N {/s31-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+7ca48a70-91b4-4a7e-ada0-3557721356e7 2022-05-26 09:04:21+00 2022-05-26 09:04:21+00 \N a882f2cc-b1ac-40a4-8e5d-09d9595c5140 {http,https} \N \N {/s31-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+5292334d-0aa6-4bae-815b-251dc6aba82a 2022-05-26 09:04:21+00 2022-05-26 09:04:21+00 \N a882f2cc-b1ac-40a4-8e5d-09d9595c5140 {http,https} \N \N {/s31-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+1cd66e88-7b56-4194-a5aa-b085ba8c3fa1 2022-05-26 09:04:21+00 2022-05-26 09:04:21+00 \N d730b9c1-e795-4c90-b771-3e3ceb21ab91 {http,https} \N \N {/s32-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+9692a20a-63c7-4fa4-b66e-48f4ffc9c357 2022-05-26 09:04:21+00 2022-05-26 09:04:21+00 \N d730b9c1-e795-4c90-b771-3e3ceb21ab91 {http,https} \N \N {/s32-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+2fc1c1f1-ab58-456d-a2a7-a7a1df329d94 2022-05-26 09:04:21+00 2022-05-26 09:04:21+00 \N d730b9c1-e795-4c90-b771-3e3ceb21ab91 {http,https} \N \N {/s32-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+81ef3ae6-5a6c-4d71-9336-33a1c2845adc 2022-05-26 09:04:21+00 2022-05-26 09:04:21+00 \N d730b9c1-e795-4c90-b771-3e3ceb21ab91 {http,https} \N \N {/s32-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+4d6fc086-96b3-4f41-aa09-02e5a338c0fe 2022-05-26 09:04:21+00 2022-05-26 09:04:21+00 \N 406467e3-6d3d-40a2-bc8e-9942b8be51b8 {http,https} \N \N {/s33-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+128ea615-7397-4a1d-b74d-0e4e6ee801ce 2022-05-26 09:04:21+00 2022-05-26 09:04:21+00 \N 406467e3-6d3d-40a2-bc8e-9942b8be51b8 {http,https} \N \N {/s33-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+e4f52da1-5142-4f5f-ba1f-2b8127a0a2c5 2022-05-26 09:04:21+00 2022-05-26 09:04:21+00 \N 406467e3-6d3d-40a2-bc8e-9942b8be51b8 {http,https} \N \N {/s33-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+e82380ec-b2d3-4bb6-b8e1-5dcb4f741dc3 2022-05-26 09:04:21+00 2022-05-26 09:04:21+00 \N 406467e3-6d3d-40a2-bc8e-9942b8be51b8 {http,https} \N \N {/s33-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+352279df-6cd4-42ef-90dd-3ae028f5b699 2022-05-26 09:04:21+00 2022-05-26 09:04:21+00 \N d5ab8d0f-b02b-4bd6-9d46-ab7da78e15ef {http,https} \N \N {/s34-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+c7fa960c-c1e6-4623-9ff3-72ce9bd6758d 2022-05-26 09:04:21+00 2022-05-26 09:04:21+00 \N d5ab8d0f-b02b-4bd6-9d46-ab7da78e15ef {http,https} \N \N {/s34-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+246ff19e-15b6-4e33-8f2b-6d5b9e687c1c 2022-05-26 09:04:21+00 2022-05-26 09:04:21+00 \N d5ab8d0f-b02b-4bd6-9d46-ab7da78e15ef {http,https} \N \N {/s34-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+58e550cd-0677-49a3-8bbc-2d1891873baa 2022-05-26 09:04:21+00 2022-05-26 09:04:21+00 \N d5ab8d0f-b02b-4bd6-9d46-ab7da78e15ef {http,https} \N \N {/s34-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+6a4532c1-f9dc-49d1-ad39-151239e516fb 2022-05-26 09:04:21+00 2022-05-26 09:04:21+00 \N 62131b85-cb9b-43d1-97d8-f4b2966dbb68 {http,https} \N \N {/s35-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+2d73aacc-bbaf-445b-bc47-de9e6d80ce16 2022-05-26 09:04:21+00 2022-05-26 09:04:21+00 \N 62131b85-cb9b-43d1-97d8-f4b2966dbb68 {http,https} \N \N {/s35-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+dd47894e-2118-4d74-8de3-4f91c6bf639f 2022-05-26 09:04:21+00 2022-05-26 09:04:21+00 \N 62131b85-cb9b-43d1-97d8-f4b2966dbb68 {http,https} \N \N {/s35-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+3b5b3fcb-ceab-4701-ae85-6f8e22d6423b 2022-05-26 09:04:21+00 2022-05-26 09:04:21+00 \N 62131b85-cb9b-43d1-97d8-f4b2966dbb68 {http,https} \N \N {/s35-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+29c14bb1-8764-4af1-9a63-928ba3dd9dea 2022-05-26 09:04:21+00 2022-05-26 09:04:21+00 \N 35fefbaf-66df-47b2-abf0-1231af2788b5 {http,https} \N \N {/s36-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+d2df53a9-2573-4dfe-be1e-4e7a11c75d77 2022-05-26 09:04:21+00 2022-05-26 09:04:21+00 \N 35fefbaf-66df-47b2-abf0-1231af2788b5 {http,https} \N \N {/s36-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+82d7563b-eee3-4340-8ab4-cbdc8472d146 2022-05-26 09:04:21+00 2022-05-26 09:04:21+00 \N 35fefbaf-66df-47b2-abf0-1231af2788b5 {http,https} \N \N {/s36-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+20c189d9-f3ed-4bda-953a-9c2b4b519ea3 2022-05-26 09:04:21+00 2022-05-26 09:04:21+00 \N 35fefbaf-66df-47b2-abf0-1231af2788b5 {http,https} \N \N {/s36-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+fcc15e73-c6ab-4492-8ac7-7fe0a9708dc2 2022-05-26 09:04:21+00 2022-05-26 09:04:21+00 \N 63639c14-7690-4f27-8a69-4df1aca28594 {http,https} \N \N {/s37-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+a1c1ad43-bf6a-4faf-9156-69b6b9d58050 2022-05-26 09:04:21+00 2022-05-26 09:04:21+00 \N 63639c14-7690-4f27-8a69-4df1aca28594 {http,https} \N \N {/s37-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+0d78b89e-9791-4da5-835c-4c042bf09a63 2022-05-26 09:04:21+00 2022-05-26 09:04:21+00 \N 63639c14-7690-4f27-8a69-4df1aca28594 {http,https} \N \N {/s37-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+454f4856-baee-4b83-9f68-f0802d603a49 2022-05-26 09:04:21+00 2022-05-26 09:04:21+00 \N 63639c14-7690-4f27-8a69-4df1aca28594 {http,https} \N \N {/s37-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+8897263b-fb1a-4bdd-befb-386b52a8798f 2022-05-26 09:04:21+00 2022-05-26 09:04:21+00 \N 872066a1-4cfb-4f69-ab14-2de00fe8a82e {http,https} \N \N {/s38-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+f3a41ff4-4d09-4bae-8352-ac0feed50567 2022-05-26 09:04:21+00 2022-05-26 09:04:21+00 \N 872066a1-4cfb-4f69-ab14-2de00fe8a82e {http,https} \N \N {/s38-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+f15c7ac8-248d-4dd8-b844-26ec3baebad8 2022-05-26 09:04:21+00 2022-05-26 09:04:21+00 \N 872066a1-4cfb-4f69-ab14-2de00fe8a82e {http,https} \N \N {/s38-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+0bb3c7fe-b614-4acd-b3bf-1065f8d4cde5 2022-05-26 09:04:21+00 2022-05-26 09:04:21+00 \N 872066a1-4cfb-4f69-ab14-2de00fe8a82e {http,https} \N \N {/s38-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+3979c902-cefe-431c-8d25-ef04e4d9f5af 2022-05-26 09:04:21+00 2022-05-26 09:04:21+00 \N 056302e1-150a-416c-9a4f-a9fb03f3f651 {http,https} \N \N {/s39-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+f471bd0a-b25e-424a-9695-1405e5d20c41 2022-05-26 09:04:21+00 2022-05-26 09:04:21+00 \N 056302e1-150a-416c-9a4f-a9fb03f3f651 {http,https} \N \N {/s39-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+34a424fa-a31c-485f-bff7-dcee457a0d84 2022-05-26 09:04:21+00 2022-05-26 09:04:21+00 \N 056302e1-150a-416c-9a4f-a9fb03f3f651 {http,https} \N \N {/s39-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+b95badc7-c614-45dd-a4fb-a4c7d1cbd55f 2022-05-26 09:04:21+00 2022-05-26 09:04:21+00 \N 056302e1-150a-416c-9a4f-a9fb03f3f651 {http,https} \N \N {/s39-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+cddf1649-bd6d-4f46-a919-fc1d75fa1803 2022-05-26 09:04:21+00 2022-05-26 09:04:21+00 \N 73734495-785d-42d2-a755-0ad0b1acf933 {http,https} \N \N {/s40-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+6d223be5-215e-471d-a7dd-e676028641e1 2022-05-26 09:04:21+00 2022-05-26 09:04:21+00 \N 73734495-785d-42d2-a755-0ad0b1acf933 {http,https} \N \N {/s40-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+e7cd42c1-60a7-4b64-b4c0-299c5e38ddb2 2022-05-26 09:04:21+00 2022-05-26 09:04:21+00 \N 73734495-785d-42d2-a755-0ad0b1acf933 {http,https} \N \N {/s40-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+15903791-92c7-477e-9dfe-958d1b8d399c 2022-05-26 09:04:21+00 2022-05-26 09:04:21+00 \N 73734495-785d-42d2-a755-0ad0b1acf933 {http,https} \N \N {/s40-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+4a3b7d60-35a8-4506-81c3-d8af5f3affe0 2022-05-26 09:04:21+00 2022-05-26 09:04:21+00 \N 8e691f37-eb65-4e3b-a6e2-0525412a98ab {http,https} \N \N {/s41-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+a190876b-7347-4b29-ab3e-db75a67ea0dd 2022-05-26 09:04:21+00 2022-05-26 09:04:21+00 \N 8e691f37-eb65-4e3b-a6e2-0525412a98ab {http,https} \N \N {/s41-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+b4e7ca47-5c19-4159-a68a-d6b27824aa5c 2022-05-26 09:04:21+00 2022-05-26 09:04:21+00 \N 8e691f37-eb65-4e3b-a6e2-0525412a98ab {http,https} \N \N {/s41-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+511e20f8-840a-4582-ab55-5100cc7d8b24 2022-05-26 09:04:21+00 2022-05-26 09:04:21+00 \N 8e691f37-eb65-4e3b-a6e2-0525412a98ab {http,https} \N \N {/s41-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+6b541eaa-46c7-4b88-af15-530ef074519f 2022-05-26 09:04:21+00 2022-05-26 09:04:21+00 \N 569a3987-9516-4053-92b8-aeebdaeeed5d {http,https} \N \N {/s42-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+b6ea121e-a797-4fb0-a5a6-0b267cde8e7e 2022-05-26 09:04:21+00 2022-05-26 09:04:21+00 \N 569a3987-9516-4053-92b8-aeebdaeeed5d {http,https} \N \N {/s42-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+46835c0e-edcf-4bbf-b2df-5c326648842e 2022-05-26 09:04:21+00 2022-05-26 09:04:21+00 \N 569a3987-9516-4053-92b8-aeebdaeeed5d {http,https} \N \N {/s42-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+c731e6b0-4082-497c-84c7-8addde5129c0 2022-05-26 09:04:21+00 2022-05-26 09:04:21+00 \N 569a3987-9516-4053-92b8-aeebdaeeed5d {http,https} \N \N {/s42-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+5dd725b7-e282-4acb-9357-630cea81d641 2022-05-26 09:04:21+00 2022-05-26 09:04:21+00 \N 5839b3b1-f03a-41f9-b645-a35ff680acbe {http,https} \N \N {/s43-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+6dff752b-6cac-421f-81d7-9187e689e979 2022-05-26 09:04:21+00 2022-05-26 09:04:21+00 \N 5839b3b1-f03a-41f9-b645-a35ff680acbe {http,https} \N \N {/s43-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+cf09ded9-12ff-4ac6-a857-70cfd18139ac 2022-05-26 09:04:21+00 2022-05-26 09:04:21+00 \N 5839b3b1-f03a-41f9-b645-a35ff680acbe {http,https} \N \N {/s43-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+23de1a99-33ae-4e01-af78-d8553c211005 2022-05-26 09:04:21+00 2022-05-26 09:04:21+00 \N 5839b3b1-f03a-41f9-b645-a35ff680acbe {http,https} \N \N {/s43-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+40a92416-c7e0-4500-a12d-090403c50837 2022-05-26 09:04:21+00 2022-05-26 09:04:21+00 \N 649cf33b-3d04-46f8-b849-4bfa449c8a7f {http,https} \N \N {/s44-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+6984d1b3-bd9e-4bed-9307-93aa2794dfe7 2022-05-26 09:04:21+00 2022-05-26 09:04:21+00 \N 649cf33b-3d04-46f8-b849-4bfa449c8a7f {http,https} \N \N {/s44-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+a3935865-cf8a-4758-be41-cb2963bd3dab 2022-05-26 09:04:21+00 2022-05-26 09:04:21+00 \N 649cf33b-3d04-46f8-b849-4bfa449c8a7f {http,https} \N \N {/s44-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+9c4be6b1-c4b5-45c9-bbe9-48ed6875bd7e 2022-05-26 09:04:21+00 2022-05-26 09:04:21+00 \N 649cf33b-3d04-46f8-b849-4bfa449c8a7f {http,https} \N \N {/s44-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+d9d03644-bf13-4438-a41d-35a63f2e8bf7 2022-05-26 09:04:21+00 2022-05-26 09:04:21+00 \N 3282f133-b8eb-4e46-80c6-a217df510860 {http,https} \N \N {/s45-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+1c502e0f-3da4-4a8c-9a7d-d2574f678d00 2022-05-26 09:04:21+00 2022-05-26 09:04:21+00 \N 3282f133-b8eb-4e46-80c6-a217df510860 {http,https} \N \N {/s45-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+bc87abf2-0fae-44af-baac-56ff20817de5 2022-05-26 09:04:21+00 2022-05-26 09:04:21+00 \N 3282f133-b8eb-4e46-80c6-a217df510860 {http,https} \N \N {/s45-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+cf377ce3-5d7f-407f-8c7a-b3d94c22dbfb 2022-05-26 09:04:21+00 2022-05-26 09:04:21+00 \N 3282f133-b8eb-4e46-80c6-a217df510860 {http,https} \N \N {/s45-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+ad56bb2d-fb37-4039-83fc-95bff293db97 2022-05-26 09:04:21+00 2022-05-26 09:04:21+00 \N da88cad4-bd4b-4a9d-b81d-d1445bf108a8 {http,https} \N \N {/s46-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+65c63fb9-3f19-4b14-959e-dc7421392fa9 2022-05-26 09:04:21+00 2022-05-26 09:04:21+00 \N da88cad4-bd4b-4a9d-b81d-d1445bf108a8 {http,https} \N \N {/s46-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+53b43ee6-cce0-4896-a8fa-ca1b771e6ebc 2022-05-26 09:04:21+00 2022-05-26 09:04:21+00 \N da88cad4-bd4b-4a9d-b81d-d1445bf108a8 {http,https} \N \N {/s46-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+9a3a2036-5aad-4b52-b99b-13a907f4e3d0 2022-05-26 09:04:21+00 2022-05-26 09:04:21+00 \N da88cad4-bd4b-4a9d-b81d-d1445bf108a8 {http,https} \N \N {/s46-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+442a6ef8-96b9-4a6e-ad0e-cb2bc887b9ce 2022-05-26 09:04:21+00 2022-05-26 09:04:21+00 \N 365b2abb-1347-4077-8ffc-5b21984fca7f {http,https} \N \N {/s47-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+5b3dfeb3-5e99-444e-9455-c99017106217 2022-05-26 09:04:21+00 2022-05-26 09:04:21+00 \N 365b2abb-1347-4077-8ffc-5b21984fca7f {http,https} \N \N {/s47-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+24191388-c07b-46a5-97f4-462b05d572f1 2022-05-26 09:04:21+00 2022-05-26 09:04:21+00 \N 365b2abb-1347-4077-8ffc-5b21984fca7f {http,https} \N \N {/s47-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+33b863b6-748d-45c7-bc56-eb7ba0280591 2022-05-26 09:04:21+00 2022-05-26 09:04:21+00 \N 365b2abb-1347-4077-8ffc-5b21984fca7f {http,https} \N \N {/s47-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+3184fc79-27b0-4901-ad2e-77bd91729e5a 2022-05-26 09:04:21+00 2022-05-26 09:04:21+00 \N e3cc7fa5-1919-4753-9afe-6f30f67a2c2e {http,https} \N \N {/s48-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+cb659e64-71e6-4014-a0b1-56d8eda12c1d 2022-05-26 09:04:21+00 2022-05-26 09:04:21+00 \N e3cc7fa5-1919-4753-9afe-6f30f67a2c2e {http,https} \N \N {/s48-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+646a364a-116d-4c74-8e29-ff6c5c41f90f 2022-05-26 09:04:21+00 2022-05-26 09:04:21+00 \N e3cc7fa5-1919-4753-9afe-6f30f67a2c2e {http,https} \N \N {/s48-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+d2cd486d-22b6-414c-af0a-4da9a0e89f63 2022-05-26 09:04:21+00 2022-05-26 09:04:21+00 \N e3cc7fa5-1919-4753-9afe-6f30f67a2c2e {http,https} \N \N {/s48-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+0c5fa868-2707-4129-8ca1-fcea55c4624f 2022-05-26 09:04:21+00 2022-05-26 09:04:21+00 \N fb53dd51-d113-4650-b980-e761871f3c54 {http,https} \N \N {/s49-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+f3a14b1a-113f-4ab0-bf91-a04f5a7054ad 2022-05-26 09:04:21+00 2022-05-26 09:04:21+00 \N fb53dd51-d113-4650-b980-e761871f3c54 {http,https} \N \N {/s49-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+eaeae98e-0703-4e17-b196-93c7e54c45bf 2022-05-26 09:04:21+00 2022-05-26 09:04:21+00 \N fb53dd51-d113-4650-b980-e761871f3c54 {http,https} \N \N {/s49-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+51656ed3-fb8d-4b13-a52c-6a747b3b24ef 2022-05-26 09:04:21+00 2022-05-26 09:04:21+00 \N fb53dd51-d113-4650-b980-e761871f3c54 {http,https} \N \N {/s49-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+36dfcf70-1fa3-46b9-ace7-ee6bb5596f7f 2022-05-26 09:04:21+00 2022-05-26 09:04:21+00 \N 851cd368-f1ea-4584-8cec-9a430f9b1a3f {http,https} \N \N {/s50-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+db915c87-9f9c-4e3a-b73c-ae571cac51df 2022-05-26 09:04:21+00 2022-05-26 09:04:21+00 \N 851cd368-f1ea-4584-8cec-9a430f9b1a3f {http,https} \N \N {/s50-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+01b2ab0c-a726-4eb2-a8f3-6f4376c1314d 2022-05-26 09:04:22+00 2022-05-26 09:04:22+00 \N 851cd368-f1ea-4584-8cec-9a430f9b1a3f {http,https} \N \N {/s50-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+edfb8669-a2f3-432a-ac49-5f915354e433 2022-05-26 09:04:22+00 2022-05-26 09:04:22+00 \N 851cd368-f1ea-4584-8cec-9a430f9b1a3f {http,https} \N \N {/s50-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+021e497a-9bf2-4a80-b546-5ccf4b6ff871 2022-05-26 09:04:22+00 2022-05-26 09:04:22+00 \N 4658664d-4ff6-4ab7-a9bf-8c0492c974de {http,https} \N \N {/s51-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+1708116c-89af-4091-a713-3c53b20bb94f 2022-05-26 09:04:22+00 2022-05-26 09:04:22+00 \N 4658664d-4ff6-4ab7-a9bf-8c0492c974de {http,https} \N \N {/s51-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+28e90609-b10b-48e5-b77d-1901c1411da2 2022-05-26 09:04:22+00 2022-05-26 09:04:22+00 \N 4658664d-4ff6-4ab7-a9bf-8c0492c974de {http,https} \N \N {/s51-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+8bcc63d1-46f4-403f-a4d3-4feac7234799 2022-05-26 09:04:22+00 2022-05-26 09:04:22+00 \N 4658664d-4ff6-4ab7-a9bf-8c0492c974de {http,https} \N \N {/s51-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+7b24dde5-5680-4a18-8361-5bc9e1ebbb5e 2022-05-26 09:04:22+00 2022-05-26 09:04:22+00 \N 4d48bf3c-a575-4520-8817-34f0b84dd4b6 {http,https} \N \N {/s52-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+3c39d03a-3219-4021-a234-bdb1f66558ad 2022-05-26 09:04:22+00 2022-05-26 09:04:22+00 \N 4d48bf3c-a575-4520-8817-34f0b84dd4b6 {http,https} \N \N {/s52-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+b62f7012-e2d6-4893-b73b-a37f17b20923 2022-05-26 09:04:22+00 2022-05-26 09:04:22+00 \N 4d48bf3c-a575-4520-8817-34f0b84dd4b6 {http,https} \N \N {/s52-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+985a6882-24fc-4c28-a994-ccd0f4853ccf 2022-05-26 09:04:22+00 2022-05-26 09:04:22+00 \N 4d48bf3c-a575-4520-8817-34f0b84dd4b6 {http,https} \N \N {/s52-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+26f47d54-501c-481e-a057-a655a0f366f4 2022-05-26 09:04:22+00 2022-05-26 09:04:22+00 \N 26968e02-8bda-4c4e-818c-8ed35d44fd9c {http,https} \N \N {/s53-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+0bc4ebbb-8ab9-4768-bbdd-fe078632137c 2022-05-26 09:04:22+00 2022-05-26 09:04:22+00 \N 26968e02-8bda-4c4e-818c-8ed35d44fd9c {http,https} \N \N {/s53-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+5ddadc08-5c3a-4a33-a6cc-5654dd91ab0d 2022-05-26 09:04:22+00 2022-05-26 09:04:22+00 \N 26968e02-8bda-4c4e-818c-8ed35d44fd9c {http,https} \N \N {/s53-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+ba1023c3-197c-4c5c-8644-abf21c3d4523 2022-05-26 09:04:22+00 2022-05-26 09:04:22+00 \N 26968e02-8bda-4c4e-818c-8ed35d44fd9c {http,https} \N \N {/s53-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+0961a24a-4db4-4412-94ae-c662a37bf3d3 2022-05-26 09:04:22+00 2022-05-26 09:04:22+00 \N 27f10e41-7155-4eed-bdfa-783271fc8bae {http,https} \N \N {/s54-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+8043bb3f-229b-4927-a9da-e7c26e3cd2f5 2022-05-26 09:04:22+00 2022-05-26 09:04:22+00 \N 27f10e41-7155-4eed-bdfa-783271fc8bae {http,https} \N \N {/s54-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+63e6a3c0-903b-409d-9a21-0bf86dc8798f 2022-05-26 09:04:22+00 2022-05-26 09:04:22+00 \N 27f10e41-7155-4eed-bdfa-783271fc8bae {http,https} \N \N {/s54-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+c5cdae80-c83c-4e4b-bd99-ee15ac759b87 2022-05-26 09:04:22+00 2022-05-26 09:04:22+00 \N 27f10e41-7155-4eed-bdfa-783271fc8bae {http,https} \N \N {/s54-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+6f73330a-ac60-405e-b592-ce04a111a79b 2022-05-26 09:04:22+00 2022-05-26 09:04:22+00 \N 73bc0430-7355-4c6d-a974-74f5bf707db1 {http,https} \N \N {/s55-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+f88f2b6c-f27e-4872-87ba-55c683e4f1b4 2022-05-26 09:04:22+00 2022-05-26 09:04:22+00 \N 73bc0430-7355-4c6d-a974-74f5bf707db1 {http,https} \N \N {/s55-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+d6ec02df-ecaf-4ef5-b4db-b5462bc57ea3 2022-05-26 09:04:22+00 2022-05-26 09:04:22+00 \N 73bc0430-7355-4c6d-a974-74f5bf707db1 {http,https} \N \N {/s55-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+3c06adfe-4399-4ceb-bc58-b6e7f3412051 2022-05-26 09:04:22+00 2022-05-26 09:04:22+00 \N 73bc0430-7355-4c6d-a974-74f5bf707db1 {http,https} \N \N {/s55-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+5814489d-419d-4f0b-978b-80fc6e715371 2022-05-26 09:04:22+00 2022-05-26 09:04:22+00 \N ef27392a-1fb8-4611-8757-c42b55900756 {http,https} \N \N {/s56-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+bb2c3144-6f34-443b-ae1b-c407bcc86573 2022-05-26 09:04:22+00 2022-05-26 09:04:22+00 \N ef27392a-1fb8-4611-8757-c42b55900756 {http,https} \N \N {/s56-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+0f5869b0-2a4f-4b94-ac24-8860a9aba9d8 2022-05-26 09:04:22+00 2022-05-26 09:04:22+00 \N ef27392a-1fb8-4611-8757-c42b55900756 {http,https} \N \N {/s56-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+c7e117bd-61eb-49a7-b27b-31bd5efa75f8 2022-05-26 09:04:22+00 2022-05-26 09:04:22+00 \N ef27392a-1fb8-4611-8757-c42b55900756 {http,https} \N \N {/s56-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+7941c45b-73eb-4ff1-973c-811cf918b567 2022-05-26 09:04:22+00 2022-05-26 09:04:22+00 \N b45da34e-3338-4878-a3e5-d78df8cd22e7 {http,https} \N \N {/s57-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+b81652aa-9c7a-4ead-901a-de9abbf03ca7 2022-05-26 09:04:22+00 2022-05-26 09:04:22+00 \N b45da34e-3338-4878-a3e5-d78df8cd22e7 {http,https} \N \N {/s57-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+5e402e76-f7d2-42b2-9396-f222fb4e468b 2022-05-26 09:04:22+00 2022-05-26 09:04:22+00 \N b45da34e-3338-4878-a3e5-d78df8cd22e7 {http,https} \N \N {/s57-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+c3aba8bd-a9c8-4b8c-b818-cd460c1dbda1 2022-05-26 09:04:22+00 2022-05-26 09:04:22+00 \N b45da34e-3338-4878-a3e5-d78df8cd22e7 {http,https} \N \N {/s57-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+3403033f-1ec4-4784-894a-1040e85dddeb 2022-05-26 09:04:22+00 2022-05-26 09:04:22+00 \N dc5da515-f616-40e9-9b94-d699fded3db7 {http,https} \N \N {/s58-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+12c929a4-0d97-451e-b9b7-0e86173ecf24 2022-05-26 09:04:22+00 2022-05-26 09:04:22+00 \N dc5da515-f616-40e9-9b94-d699fded3db7 {http,https} \N \N {/s58-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+d1a9cfb9-68bf-4234-9ef7-878d8b0bc3d0 2022-05-26 09:04:22+00 2022-05-26 09:04:22+00 \N dc5da515-f616-40e9-9b94-d699fded3db7 {http,https} \N \N {/s58-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+666c6b7c-ba43-4ae5-a38d-42ebd968f901 2022-05-26 09:04:22+00 2022-05-26 09:04:22+00 \N dc5da515-f616-40e9-9b94-d699fded3db7 {http,https} \N \N {/s58-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+b8bfeae5-5130-4cc9-9a2f-246a16e53328 2022-05-26 09:04:22+00 2022-05-26 09:04:22+00 \N 8168f4cc-39af-49bd-8b6e-a365f038bebd {http,https} \N \N {/s59-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+a793732a-905e-4b4e-96b5-6c849c03423d 2022-05-26 09:04:22+00 2022-05-26 09:04:22+00 \N 8168f4cc-39af-49bd-8b6e-a365f038bebd {http,https} \N \N {/s59-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+b26ed3d4-5587-42ae-a6da-6123669164b4 2022-05-26 09:04:22+00 2022-05-26 09:04:22+00 \N 8168f4cc-39af-49bd-8b6e-a365f038bebd {http,https} \N \N {/s59-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+ec7d7a95-e5b7-42c8-8a0c-a933b5089804 2022-05-26 09:04:22+00 2022-05-26 09:04:22+00 \N 8168f4cc-39af-49bd-8b6e-a365f038bebd {http,https} \N \N {/s59-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+1c4b40eb-d910-4109-838b-d5a145b6005a 2022-05-26 09:04:22+00 2022-05-26 09:04:22+00 \N 051898cd-71d2-457b-9ee8-c080908da498 {http,https} \N \N {/s60-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+01e02128-b620-49cf-bd2b-6ffca9f28c4c 2022-05-26 09:04:22+00 2022-05-26 09:04:22+00 \N 051898cd-71d2-457b-9ee8-c080908da498 {http,https} \N \N {/s60-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+62b48699-f419-4d31-9009-709cd966abcb 2022-05-26 09:04:22+00 2022-05-26 09:04:22+00 \N 051898cd-71d2-457b-9ee8-c080908da498 {http,https} \N \N {/s60-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+ddcffccb-96cd-4cc0-81b1-b1f1cdf09b58 2022-05-26 09:04:22+00 2022-05-26 09:04:22+00 \N 051898cd-71d2-457b-9ee8-c080908da498 {http,https} \N \N {/s60-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+be4c0681-1850-4750-b276-11f6c6ce83de 2022-05-26 09:04:22+00 2022-05-26 09:04:22+00 \N cdb3688d-b5fc-421a-8c06-cb14fc6c5ff9 {http,https} \N \N {/s61-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+760b1b0a-a6d7-4138-bbe7-2da72748aaec 2022-05-26 09:04:22+00 2022-05-26 09:04:22+00 \N cdb3688d-b5fc-421a-8c06-cb14fc6c5ff9 {http,https} \N \N {/s61-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+a19f8cd4-458d-40ff-8919-80b80902fea6 2022-05-26 09:04:22+00 2022-05-26 09:04:22+00 \N cdb3688d-b5fc-421a-8c06-cb14fc6c5ff9 {http,https} \N \N {/s61-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+e8902d3c-6219-4029-adf8-fafb7e91ac2e 2022-05-26 09:04:22+00 2022-05-26 09:04:22+00 \N cdb3688d-b5fc-421a-8c06-cb14fc6c5ff9 {http,https} \N \N {/s61-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+3f71841f-89f3-4fc7-bf7c-70c5c24e64f1 2022-05-26 09:04:22+00 2022-05-26 09:04:22+00 \N cae8aca9-818b-450d-97a6-7ea08373e0cc {http,https} \N \N {/s62-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+26ce1726-fee5-4e7f-ace9-9b506a612843 2022-05-26 09:04:22+00 2022-05-26 09:04:22+00 \N cae8aca9-818b-450d-97a6-7ea08373e0cc {http,https} \N \N {/s62-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+04d8e2e7-7e64-46d2-9fc8-8eb40f50feed 2022-05-26 09:04:22+00 2022-05-26 09:04:22+00 \N cae8aca9-818b-450d-97a6-7ea08373e0cc {http,https} \N \N {/s62-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+5fa7a59b-63dd-427d-a314-eb97ba59889c 2022-05-26 09:04:22+00 2022-05-26 09:04:22+00 \N cae8aca9-818b-450d-97a6-7ea08373e0cc {http,https} \N \N {/s62-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+30f175e5-eb1e-48f2-a455-58d556b1c49d 2022-05-26 09:04:22+00 2022-05-26 09:04:22+00 \N 1b7c0f6a-9eab-428e-b979-5995a4ff6527 {http,https} \N \N {/s63-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+67909e1e-e8d3-494b-88a6-42dddb9cc70c 2022-05-26 09:04:22+00 2022-05-26 09:04:22+00 \N 1b7c0f6a-9eab-428e-b979-5995a4ff6527 {http,https} \N \N {/s63-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+567df721-b470-4340-aaa7-45c6d4d8443a 2022-05-26 09:04:22+00 2022-05-26 09:04:22+00 \N 1b7c0f6a-9eab-428e-b979-5995a4ff6527 {http,https} \N \N {/s63-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+0e7103e2-9878-405a-99c6-896c1fda9308 2022-05-26 09:04:22+00 2022-05-26 09:04:22+00 \N 1b7c0f6a-9eab-428e-b979-5995a4ff6527 {http,https} \N \N {/s63-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+d0b57e6c-7080-4a2c-be92-b343f35b76c1 2022-05-26 09:04:22+00 2022-05-26 09:04:22+00 \N 3e658a76-cb76-4be7-a15a-84d4883b472b {http,https} \N \N {/s64-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+b0dedf00-dc34-4996-87d2-4c3dfc5c46d2 2022-05-26 09:04:22+00 2022-05-26 09:04:22+00 \N 3e658a76-cb76-4be7-a15a-84d4883b472b {http,https} \N \N {/s64-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+e5226a35-9d37-4e3d-a79c-e9f4b3014371 2022-05-26 09:04:22+00 2022-05-26 09:04:22+00 \N 3e658a76-cb76-4be7-a15a-84d4883b472b {http,https} \N \N {/s64-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+f0e9a00d-e797-4a8c-a773-9567ef0487c7 2022-05-26 09:04:22+00 2022-05-26 09:04:22+00 \N 3e658a76-cb76-4be7-a15a-84d4883b472b {http,https} \N \N {/s64-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+6348b289-ccd1-40e7-83ee-9717654a861f 2022-05-26 09:04:22+00 2022-05-26 09:04:22+00 \N 800121b2-3644-4ea0-8539-25d513acb472 {http,https} \N \N {/s65-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+2b3c8d08-5826-40c8-bf4b-c9cd09627efe 2022-05-26 09:04:22+00 2022-05-26 09:04:22+00 \N 800121b2-3644-4ea0-8539-25d513acb472 {http,https} \N \N {/s65-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+92f02e92-a089-490e-b8af-41a788a459a4 2022-05-26 09:04:22+00 2022-05-26 09:04:22+00 \N 800121b2-3644-4ea0-8539-25d513acb472 {http,https} \N \N {/s65-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+0c9f6955-7cbd-4bda-8738-4ee18fce587f 2022-05-26 09:04:22+00 2022-05-26 09:04:22+00 \N 800121b2-3644-4ea0-8539-25d513acb472 {http,https} \N \N {/s65-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+f4e93c81-d3b5-4007-9775-157c8c8c61ae 2022-05-26 09:04:22+00 2022-05-26 09:04:22+00 \N 89b2af01-b55f-4425-844e-bc2dea397b93 {http,https} \N \N {/s66-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+12cfa8af-ef07-4bd0-aec4-6c17e9563fb1 2022-05-26 09:04:22+00 2022-05-26 09:04:22+00 \N 89b2af01-b55f-4425-844e-bc2dea397b93 {http,https} \N \N {/s66-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+103a4113-2570-401a-9bff-456c18a6c41c 2022-05-26 09:04:22+00 2022-05-26 09:04:22+00 \N 89b2af01-b55f-4425-844e-bc2dea397b93 {http,https} \N \N {/s66-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+d85f3777-3b23-45ac-9458-6533790f4813 2022-05-26 09:04:22+00 2022-05-26 09:04:22+00 \N 89b2af01-b55f-4425-844e-bc2dea397b93 {http,https} \N \N {/s66-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+3d6bc425-8bba-4a27-ad92-7f4676b167a5 2022-05-26 09:04:22+00 2022-05-26 09:04:22+00 \N 34f521cb-53b9-4824-89b7-15459e96532f {http,https} \N \N {/s67-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+57b695be-5b45-4e9d-b96c-f82dee5c06ab 2022-05-26 09:04:22+00 2022-05-26 09:04:22+00 \N 34f521cb-53b9-4824-89b7-15459e96532f {http,https} \N \N {/s67-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+bb952eb2-a5e3-465a-837a-06908d777bef 2022-05-26 09:04:22+00 2022-05-26 09:04:22+00 \N 34f521cb-53b9-4824-89b7-15459e96532f {http,https} \N \N {/s67-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+08636446-4863-4615-93a2-d88336303d9a 2022-05-26 09:04:22+00 2022-05-26 09:04:22+00 \N 34f521cb-53b9-4824-89b7-15459e96532f {http,https} \N \N {/s67-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+4ba55de6-96af-4854-8eea-af4f7eae005f 2022-05-26 09:04:22+00 2022-05-26 09:04:22+00 \N 33a92a68-5e8d-487b-977e-89dd42a458bd {http,https} \N \N {/s68-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+638b369e-b27e-4be6-b139-8f747422453e 2022-05-26 09:04:22+00 2022-05-26 09:04:22+00 \N 33a92a68-5e8d-487b-977e-89dd42a458bd {http,https} \N \N {/s68-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+6211773e-191e-43a2-b114-8de79c70d841 2022-05-26 09:04:22+00 2022-05-26 09:04:22+00 \N 33a92a68-5e8d-487b-977e-89dd42a458bd {http,https} \N \N {/s68-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+dee01448-e99a-4990-8f07-f187483c4a3c 2022-05-26 09:04:22+00 2022-05-26 09:04:22+00 \N 33a92a68-5e8d-487b-977e-89dd42a458bd {http,https} \N \N {/s68-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+9e6312a9-762e-4442-82dd-404e5d0b1e24 2022-05-26 09:04:22+00 2022-05-26 09:04:22+00 \N dbbe71cb-7ec1-4c43-804d-ef6a92721d90 {http,https} \N \N {/s69-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+793889bb-ad6d-45c5-ab09-d6170885350e 2022-05-26 09:04:22+00 2022-05-26 09:04:22+00 \N dbbe71cb-7ec1-4c43-804d-ef6a92721d90 {http,https} \N \N {/s69-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+792e6099-3c47-4d19-b97e-b7f1ad14b6b3 2022-05-26 09:04:22+00 2022-05-26 09:04:22+00 \N dbbe71cb-7ec1-4c43-804d-ef6a92721d90 {http,https} \N \N {/s69-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+df9f4f76-306c-4243-843a-ce697957d909 2022-05-26 09:04:22+00 2022-05-26 09:04:22+00 \N dbbe71cb-7ec1-4c43-804d-ef6a92721d90 {http,https} \N \N {/s69-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+c7379f6d-1aea-4c1e-9347-d0b3c4ac1a09 2022-05-26 09:04:22+00 2022-05-26 09:04:22+00 \N 69a88ba4-e530-4723-b7c3-f739b92a5a66 {http,https} \N \N {/s70-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+0473cdf4-8dd1-43cf-bb0e-24dd9133496b 2022-05-26 09:04:22+00 2022-05-26 09:04:22+00 \N 69a88ba4-e530-4723-b7c3-f739b92a5a66 {http,https} \N \N {/s70-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+17e4085d-52ce-4825-98fd-63c6e389ef2a 2022-05-26 09:04:22+00 2022-05-26 09:04:22+00 \N 69a88ba4-e530-4723-b7c3-f739b92a5a66 {http,https} \N \N {/s70-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+50ee2ef5-0eb9-449f-873a-3ffe3ca64478 2022-05-26 09:04:22+00 2022-05-26 09:04:22+00 \N 69a88ba4-e530-4723-b7c3-f739b92a5a66 {http,https} \N \N {/s70-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+339e65d3-f2e4-4d6c-883f-089eb773b0b9 2022-05-26 09:04:22+00 2022-05-26 09:04:22+00 \N 0d1eb445-8a10-49bb-952f-5eb35a8599d3 {http,https} \N \N {/s71-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+b49dea8c-55fa-422f-bca3-aa3c93116e0b 2022-05-26 09:04:22+00 2022-05-26 09:04:22+00 \N 0d1eb445-8a10-49bb-952f-5eb35a8599d3 {http,https} \N \N {/s71-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+0e369db3-ea50-4d1f-b0a2-ed9209ccfc91 2022-05-26 09:04:22+00 2022-05-26 09:04:22+00 \N 0d1eb445-8a10-49bb-952f-5eb35a8599d3 {http,https} \N \N {/s71-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+9f5026b1-a5c7-47d8-b275-a777abdd13da 2022-05-26 09:04:22+00 2022-05-26 09:04:22+00 \N 0d1eb445-8a10-49bb-952f-5eb35a8599d3 {http,https} \N \N {/s71-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+70cac125-433d-4ef7-8d95-d285cf4e0370 2022-05-26 09:04:22+00 2022-05-26 09:04:22+00 \N a03dac5a-20dc-492d-b4db-732a79d4a30c {http,https} \N \N {/s72-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+d84502db-755f-4301-9943-d140abfc00be 2022-05-26 09:04:22+00 2022-05-26 09:04:22+00 \N a03dac5a-20dc-492d-b4db-732a79d4a30c {http,https} \N \N {/s72-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+e08338f6-0985-495a-9f94-c05923658a7a 2022-05-26 09:04:22+00 2022-05-26 09:04:22+00 \N a03dac5a-20dc-492d-b4db-732a79d4a30c {http,https} \N \N {/s72-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+abeb4a51-d15c-4f76-ab81-c66e67871626 2022-05-26 09:04:22+00 2022-05-26 09:04:22+00 \N a03dac5a-20dc-492d-b4db-732a79d4a30c {http,https} \N \N {/s72-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+647e2caf-3b5c-46ab-85e8-a38cdd67a25b 2022-05-26 09:04:22+00 2022-05-26 09:04:22+00 \N 291a0424-2ad1-47a6-a8b2-c63a037bf03c {http,https} \N \N {/s73-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+558e54d5-0c54-4fcf-84ee-da97751c4e48 2022-05-26 09:04:22+00 2022-05-26 09:04:22+00 \N 291a0424-2ad1-47a6-a8b2-c63a037bf03c {http,https} \N \N {/s73-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+3e2c67c4-03d2-49a3-b888-cb185c1fa600 2022-05-26 09:04:22+00 2022-05-26 09:04:22+00 \N 291a0424-2ad1-47a6-a8b2-c63a037bf03c {http,https} \N \N {/s73-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+2ea5cb4d-5e42-4d2f-84cd-abe9854e4697 2022-05-26 09:04:22+00 2022-05-26 09:04:22+00 \N 291a0424-2ad1-47a6-a8b2-c63a037bf03c {http,https} \N \N {/s73-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+4996e322-c97f-4aec-b788-c11ccaf9efd8 2022-05-26 09:04:22+00 2022-05-26 09:04:22+00 \N 4eb8a749-0bd2-47af-8fdc-4cf128bf0b66 {http,https} \N \N {/s74-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+81de2981-e03e-43ee-aed3-a244f12bee7c 2022-05-26 09:04:22+00 2022-05-26 09:04:22+00 \N 4eb8a749-0bd2-47af-8fdc-4cf128bf0b66 {http,https} \N \N {/s74-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+019cf0ee-2cdb-4d65-8263-1a1f9c3c5f6e 2022-05-26 09:04:22+00 2022-05-26 09:04:22+00 \N 4eb8a749-0bd2-47af-8fdc-4cf128bf0b66 {http,https} \N \N {/s74-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+24ac0cea-3fe9-4873-b9a6-e050eff27d82 2022-05-26 09:04:22+00 2022-05-26 09:04:22+00 \N 4eb8a749-0bd2-47af-8fdc-4cf128bf0b66 {http,https} \N \N {/s74-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+4c80aa43-3d2b-46e7-9f26-0f56e776b06c 2022-05-26 09:04:22+00 2022-05-26 09:04:22+00 \N c398e6e1-2f3e-4897-912f-483c03ec6959 {http,https} \N \N {/s75-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+1a8c8d53-ce1e-4b4b-9eeb-acacb1c5d70e 2022-05-26 09:04:22+00 2022-05-26 09:04:22+00 \N c398e6e1-2f3e-4897-912f-483c03ec6959 {http,https} \N \N {/s75-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+29681c3f-0f05-4c3d-8f3f-2230f797811d 2022-05-26 09:04:22+00 2022-05-26 09:04:22+00 \N c398e6e1-2f3e-4897-912f-483c03ec6959 {http,https} \N \N {/s75-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+4245e97f-22dc-40d2-b922-780fd073f3ec 2022-05-26 09:04:22+00 2022-05-26 09:04:22+00 \N c398e6e1-2f3e-4897-912f-483c03ec6959 {http,https} \N \N {/s75-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+757a1bfc-a735-4d45-9a50-7112f969ea15 2022-05-26 09:04:22+00 2022-05-26 09:04:22+00 \N c544969b-0b53-43a7-a6a9-79e400d7b852 {http,https} \N \N {/s76-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+5f7d2f30-ad6f-4eb0-940a-b6d2f0c8877c 2022-05-26 09:04:22+00 2022-05-26 09:04:22+00 \N c544969b-0b53-43a7-a6a9-79e400d7b852 {http,https} \N \N {/s76-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+e0ca802f-c54b-4a69-895b-9d5ddd1bf25c 2022-05-26 09:04:22+00 2022-05-26 09:04:22+00 \N c544969b-0b53-43a7-a6a9-79e400d7b852 {http,https} \N \N {/s76-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+ca7ec55c-2cb6-4689-bac0-c3c3f46abe9e 2022-05-26 09:04:22+00 2022-05-26 09:04:22+00 \N c544969b-0b53-43a7-a6a9-79e400d7b852 {http,https} \N \N {/s76-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+07d18ff5-7c3a-43cf-8e73-0b61cdd9a867 2022-05-26 09:04:22+00 2022-05-26 09:04:22+00 \N 1dc10ac4-8720-49d0-9624-e2320ad83910 {http,https} \N \N {/s77-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+b365a387-d043-4178-81fc-b30f32f082b6 2022-05-26 09:04:22+00 2022-05-26 09:04:22+00 \N 1dc10ac4-8720-49d0-9624-e2320ad83910 {http,https} \N \N {/s77-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+3d56746a-4238-456d-9064-056d21decf91 2022-05-26 09:04:22+00 2022-05-26 09:04:22+00 \N 1dc10ac4-8720-49d0-9624-e2320ad83910 {http,https} \N \N {/s77-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+891dc0c9-4193-4952-87d8-ea6056b2ba88 2022-05-26 09:04:22+00 2022-05-26 09:04:22+00 \N 1dc10ac4-8720-49d0-9624-e2320ad83910 {http,https} \N \N {/s77-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+cbc1d656-4bfa-40bd-b40f-ef2b5af4d4f0 2022-05-26 09:04:22+00 2022-05-26 09:04:22+00 \N 961eda07-6db4-41a9-b053-55f3d86feab9 {http,https} \N \N {/s78-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+bc2f8ad7-55e2-4ccb-9ec2-0dc5d8619482 2022-05-26 09:04:22+00 2022-05-26 09:04:22+00 \N 961eda07-6db4-41a9-b053-55f3d86feab9 {http,https} \N \N {/s78-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+7b040585-87c8-4559-883e-2c316faf3c65 2022-05-26 09:04:22+00 2022-05-26 09:04:22+00 \N 961eda07-6db4-41a9-b053-55f3d86feab9 {http,https} \N \N {/s78-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+2c30a266-bcae-43a2-9541-a291224a7049 2022-05-26 09:04:22+00 2022-05-26 09:04:22+00 \N 961eda07-6db4-41a9-b053-55f3d86feab9 {http,https} \N \N {/s78-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+3b01e0e4-a2d4-49cf-910b-415c20e7f3cf 2022-05-26 09:04:22+00 2022-05-26 09:04:22+00 \N a92dc0e0-3cd3-4c00-bfbd-1b9d849c617b {http,https} \N \N {/s79-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+c5054caa-c60c-436a-a041-0be366e8d272 2022-05-26 09:04:22+00 2022-05-26 09:04:22+00 \N a92dc0e0-3cd3-4c00-bfbd-1b9d849c617b {http,https} \N \N {/s79-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+1419869c-88ee-495a-ba0f-379b5e0e9984 2022-05-26 09:04:22+00 2022-05-26 09:04:22+00 \N a92dc0e0-3cd3-4c00-bfbd-1b9d849c617b {http,https} \N \N {/s79-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+a4909080-0e69-4f7d-8d50-de3bfefae69e 2022-05-26 09:04:22+00 2022-05-26 09:04:22+00 \N a92dc0e0-3cd3-4c00-bfbd-1b9d849c617b {http,https} \N \N {/s79-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+f5db0a03-9630-45ea-9996-e65fcf6d0b8a 2022-05-26 09:04:23+00 2022-05-26 09:04:23+00 \N 6fc0c8de-dd47-4b2d-be48-acff77604738 {http,https} \N \N {/s80-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+4a9d3ff9-c671-48e8-bfaf-28cc9bb82f7b 2022-05-26 09:04:23+00 2022-05-26 09:04:23+00 \N 6fc0c8de-dd47-4b2d-be48-acff77604738 {http,https} \N \N {/s80-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+5b38a474-491d-471f-ba11-1b54ad9f1637 2022-05-26 09:04:23+00 2022-05-26 09:04:23+00 \N 6fc0c8de-dd47-4b2d-be48-acff77604738 {http,https} \N \N {/s80-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+9ff12282-1ec8-49b2-b35f-426406bae7bc 2022-05-26 09:04:23+00 2022-05-26 09:04:23+00 \N 6fc0c8de-dd47-4b2d-be48-acff77604738 {http,https} \N \N {/s80-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+8677f5a4-f5b3-4893-a2c2-5ce9bd4626dd 2022-05-26 09:04:23+00 2022-05-26 09:04:23+00 \N c1477ea4-988e-40e5-b7a8-6fa4e688f36d {http,https} \N \N {/s81-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+9ae59152-7021-4460-b166-ce819c7a078b 2022-05-26 09:04:23+00 2022-05-26 09:04:23+00 \N c1477ea4-988e-40e5-b7a8-6fa4e688f36d {http,https} \N \N {/s81-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+eb751574-5953-4b2b-8ff2-b946d3366caf 2022-05-26 09:04:23+00 2022-05-26 09:04:23+00 \N c1477ea4-988e-40e5-b7a8-6fa4e688f36d {http,https} \N \N {/s81-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+f781fee0-5d8d-485d-a425-49670bf46d9a 2022-05-26 09:04:23+00 2022-05-26 09:04:23+00 \N c1477ea4-988e-40e5-b7a8-6fa4e688f36d {http,https} \N \N {/s81-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+0dce98c9-dffc-4657-bc2a-1ae1033dd2a7 2022-05-26 09:04:23+00 2022-05-26 09:04:23+00 \N c0ac16b4-51b2-4388-a75c-99a6e8864567 {http,https} \N \N {/s82-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+e6684904-4bee-472b-a960-9719d4fb3d09 2022-05-26 09:04:23+00 2022-05-26 09:04:23+00 \N c0ac16b4-51b2-4388-a75c-99a6e8864567 {http,https} \N \N {/s82-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+a21e5c1c-7b7a-40c7-a706-cfe47049969a 2022-05-26 09:04:23+00 2022-05-26 09:04:23+00 \N c0ac16b4-51b2-4388-a75c-99a6e8864567 {http,https} \N \N {/s82-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+36fea073-81cd-4283-956d-128f55a83899 2022-05-26 09:04:23+00 2022-05-26 09:04:23+00 \N c0ac16b4-51b2-4388-a75c-99a6e8864567 {http,https} \N \N {/s82-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+45f33f4c-8fa7-48f0-a831-b368bc51d06a 2022-05-26 09:04:23+00 2022-05-26 09:04:23+00 \N b3490c56-2668-4cf8-ac26-9d3c38fb9ce6 {http,https} \N \N {/s83-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+4b17145e-d390-400b-b142-7b8fe0682b5f 2022-05-26 09:04:23+00 2022-05-26 09:04:23+00 \N b3490c56-2668-4cf8-ac26-9d3c38fb9ce6 {http,https} \N \N {/s83-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+defa59d1-6f2f-436d-a5c8-9cf13c193334 2022-05-26 09:04:23+00 2022-05-26 09:04:23+00 \N b3490c56-2668-4cf8-ac26-9d3c38fb9ce6 {http,https} \N \N {/s83-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+e2f71888-ac65-4716-95cb-6c1999dacbae 2022-05-26 09:04:23+00 2022-05-26 09:04:23+00 \N b3490c56-2668-4cf8-ac26-9d3c38fb9ce6 {http,https} \N \N {/s83-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+e28cbd79-6bf0-466a-8754-e6fc1ca61124 2022-05-26 09:04:23+00 2022-05-26 09:04:23+00 \N 6f607e1a-2baf-4f12-b0ed-270073df30c6 {http,https} \N \N {/s84-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+242ba16c-e255-499c-9908-7cf006340140 2022-05-26 09:04:23+00 2022-05-26 09:04:23+00 \N 6f607e1a-2baf-4f12-b0ed-270073df30c6 {http,https} \N \N {/s84-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+29284033-0e0a-43c6-b82a-5446f0447cb7 2022-05-26 09:04:23+00 2022-05-26 09:04:23+00 \N 6f607e1a-2baf-4f12-b0ed-270073df30c6 {http,https} \N \N {/s84-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+62f01079-9db2-4e4a-ab3d-6235d0900e23 2022-05-26 09:04:23+00 2022-05-26 09:04:23+00 \N 6f607e1a-2baf-4f12-b0ed-270073df30c6 {http,https} \N \N {/s84-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+e87efb35-04cb-44e6-9bb3-30e76b5ec298 2022-05-26 09:04:23+00 2022-05-26 09:04:23+00 \N 4284966e-2ef5-45f7-b16c-faba6666c300 {http,https} \N \N {/s85-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+12a70bf9-d5d8-4402-8d22-b97d3fe6c8a4 2022-05-26 09:04:23+00 2022-05-26 09:04:23+00 \N 4284966e-2ef5-45f7-b16c-faba6666c300 {http,https} \N \N {/s85-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+2594018c-1d96-4af3-af45-7eebc8d06515 2022-05-26 09:04:23+00 2022-05-26 09:04:23+00 \N 4284966e-2ef5-45f7-b16c-faba6666c300 {http,https} \N \N {/s85-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+c7c39170-549b-4182-8ae6-13b8e73be911 2022-05-26 09:04:23+00 2022-05-26 09:04:23+00 \N 4284966e-2ef5-45f7-b16c-faba6666c300 {http,https} \N \N {/s85-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+fc596999-1fc0-4a7b-a61b-14506c15e12d 2022-05-26 09:04:23+00 2022-05-26 09:04:23+00 \N 0a3d005f-e8ae-46a0-bc92-0a4a8147fe3f {http,https} \N \N {/s86-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+b5a95da1-841f-4653-b0de-9a405b6a5b99 2022-05-26 09:04:23+00 2022-05-26 09:04:23+00 \N 0a3d005f-e8ae-46a0-bc92-0a4a8147fe3f {http,https} \N \N {/s86-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+3af242f4-3b4a-4cc8-8e49-fabcdd6d20d7 2022-05-26 09:04:23+00 2022-05-26 09:04:23+00 \N 0a3d005f-e8ae-46a0-bc92-0a4a8147fe3f {http,https} \N \N {/s86-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+8f808cfc-6eb5-4841-82bc-cb9945bab516 2022-05-26 09:04:23+00 2022-05-26 09:04:23+00 \N 0a3d005f-e8ae-46a0-bc92-0a4a8147fe3f {http,https} \N \N {/s86-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+35a595cc-d05e-4e4d-83b4-660e91cf6907 2022-05-26 09:04:23+00 2022-05-26 09:04:23+00 \N f7039445-e8fa-44c0-ba30-4db609972643 {http,https} \N \N {/s87-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+cb93afbe-d5bc-4fae-995c-8b05e05f4a68 2022-05-26 09:04:23+00 2022-05-26 09:04:23+00 \N f7039445-e8fa-44c0-ba30-4db609972643 {http,https} \N \N {/s87-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+d8bbc254-7ec6-40fd-a93a-ad34a5c1b99d 2022-05-26 09:04:23+00 2022-05-26 09:04:23+00 \N f7039445-e8fa-44c0-ba30-4db609972643 {http,https} \N \N {/s87-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+a6c4abac-9a5b-49e8-aa13-ca82f95de345 2022-05-26 09:04:23+00 2022-05-26 09:04:23+00 \N f7039445-e8fa-44c0-ba30-4db609972643 {http,https} \N \N {/s87-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+b3435e36-b1b8-4d10-be89-fc955bb56a12 2022-05-26 09:04:23+00 2022-05-26 09:04:23+00 \N 10db8481-4fa8-4531-9e0c-fb20e642dc40 {http,https} \N \N {/s88-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+49e68f0e-8bb0-42e9-8e7a-a2e05821ff07 2022-05-26 09:04:23+00 2022-05-26 09:04:23+00 \N 10db8481-4fa8-4531-9e0c-fb20e642dc40 {http,https} \N \N {/s88-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+5d706489-1d36-4c5a-b451-1672965ae52d 2022-05-26 09:04:23+00 2022-05-26 09:04:23+00 \N 10db8481-4fa8-4531-9e0c-fb20e642dc40 {http,https} \N \N {/s88-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+986f5e98-8421-4e69-9045-88bdc41a6d09 2022-05-26 09:04:23+00 2022-05-26 09:04:23+00 \N 10db8481-4fa8-4531-9e0c-fb20e642dc40 {http,https} \N \N {/s88-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+f0297b90-367a-4b03-b9ff-6d215458cbf4 2022-05-26 09:04:23+00 2022-05-26 09:04:23+00 \N 0069a9d9-459a-4efc-b5a2-c0ae786c92bd {http,https} \N \N {/s89-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+2af7a506-b909-4ec1-868a-3f8b117483b1 2022-05-26 09:04:23+00 2022-05-26 09:04:23+00 \N 0069a9d9-459a-4efc-b5a2-c0ae786c92bd {http,https} \N \N {/s89-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+63f3ce37-3f36-4b9b-8b81-e1ddb433539b 2022-05-26 09:04:23+00 2022-05-26 09:04:23+00 \N 0069a9d9-459a-4efc-b5a2-c0ae786c92bd {http,https} \N \N {/s89-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+d22ddd42-4591-46d0-bddf-46fad1561fd7 2022-05-26 09:04:23+00 2022-05-26 09:04:23+00 \N 0069a9d9-459a-4efc-b5a2-c0ae786c92bd {http,https} \N \N {/s89-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+35d3cc52-4107-458f-ad8e-aee80dd3483e 2022-05-26 09:04:23+00 2022-05-26 09:04:23+00 \N fa73881d-a74d-4349-8a9c-b2ae17b414fd {http,https} \N \N {/s90-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+678a2a21-fb5c-4b53-b9a3-5acc590e5e93 2022-05-26 09:04:23+00 2022-05-26 09:04:23+00 \N fa73881d-a74d-4349-8a9c-b2ae17b414fd {http,https} \N \N {/s90-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+44162869-6884-47bc-9476-98c8c38ad9bf 2022-05-26 09:04:23+00 2022-05-26 09:04:23+00 \N fa73881d-a74d-4349-8a9c-b2ae17b414fd {http,https} \N \N {/s90-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+716749cf-4ca9-4298-a603-7605970c733e 2022-05-26 09:04:23+00 2022-05-26 09:04:23+00 \N fa73881d-a74d-4349-8a9c-b2ae17b414fd {http,https} \N \N {/s90-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+4d75c19a-37a4-4664-b98d-2b7a81de89c6 2022-05-26 09:04:23+00 2022-05-26 09:04:23+00 \N fea825b5-53e7-4d5e-b594-5e6d20822e27 {http,https} \N \N {/s91-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+c81cf78d-87d0-4977-8496-4824784c28b8 2022-05-26 09:04:23+00 2022-05-26 09:04:23+00 \N fea825b5-53e7-4d5e-b594-5e6d20822e27 {http,https} \N \N {/s91-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+6b1b5631-cf02-4220-b8a7-6aeea37cf89f 2022-05-26 09:04:23+00 2022-05-26 09:04:23+00 \N fea825b5-53e7-4d5e-b594-5e6d20822e27 {http,https} \N \N {/s91-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+cd28b502-199d-4fd7-bd0e-e343844f83cd 2022-05-26 09:04:23+00 2022-05-26 09:04:23+00 \N fea825b5-53e7-4d5e-b594-5e6d20822e27 {http,https} \N \N {/s91-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+9dad893e-6c1b-49f6-bab2-f0f4d23aeeb9 2022-05-26 09:04:23+00 2022-05-26 09:04:23+00 \N 0f9df5d5-3dd4-4a0b-beef-5aed37af31c6 {http,https} \N \N {/s92-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+858e8ea3-ab8d-448f-8336-845f97b77242 2022-05-26 09:04:23+00 2022-05-26 09:04:23+00 \N 0f9df5d5-3dd4-4a0b-beef-5aed37af31c6 {http,https} \N \N {/s92-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+83f1d1a3-11ef-4a49-8467-1ae7769cae4f 2022-05-26 09:04:23+00 2022-05-26 09:04:23+00 \N 0f9df5d5-3dd4-4a0b-beef-5aed37af31c6 {http,https} \N \N {/s92-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+83b72d29-4fc2-4454-af94-b05add1f612a 2022-05-26 09:04:23+00 2022-05-26 09:04:23+00 \N 0f9df5d5-3dd4-4a0b-beef-5aed37af31c6 {http,https} \N \N {/s92-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+5e01aa1d-e5de-4429-a49c-867ba6d43c34 2022-05-26 09:04:23+00 2022-05-26 09:04:23+00 \N 7d839f08-fe27-44a8-bbea-abaea85e8ec4 {http,https} \N \N {/s93-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+eac2c744-d694-4e53-8321-1bf5d2711ef9 2022-05-26 09:04:23+00 2022-05-26 09:04:23+00 \N 7d839f08-fe27-44a8-bbea-abaea85e8ec4 {http,https} \N \N {/s93-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+ff25f866-172d-4eb3-a780-0f7b74779572 2022-05-26 09:04:23+00 2022-05-26 09:04:23+00 \N 7d839f08-fe27-44a8-bbea-abaea85e8ec4 {http,https} \N \N {/s93-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+96f720ad-4305-4dfa-a03d-650aeee8651d 2022-05-26 09:04:23+00 2022-05-26 09:04:23+00 \N 7d839f08-fe27-44a8-bbea-abaea85e8ec4 {http,https} \N \N {/s93-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+c3e8a3ac-10f2-4de2-b9cf-681379e6373e 2022-05-26 09:04:23+00 2022-05-26 09:04:23+00 \N 4e27c8d3-1b57-4837-a62e-7b7129f23b87 {http,https} \N \N {/s94-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+4685cd6e-0dba-4249-ae0e-9deefb9952c5 2022-05-26 09:04:23+00 2022-05-26 09:04:23+00 \N 4e27c8d3-1b57-4837-a62e-7b7129f23b87 {http,https} \N \N {/s94-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+bbbaacf1-310a-4b13-986c-14dbff6320e8 2022-05-26 09:04:23+00 2022-05-26 09:04:23+00 \N 4e27c8d3-1b57-4837-a62e-7b7129f23b87 {http,https} \N \N {/s94-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+8be9c5cd-0b29-4750-8529-109f179754f6 2022-05-26 09:04:23+00 2022-05-26 09:04:23+00 \N 4e27c8d3-1b57-4837-a62e-7b7129f23b87 {http,https} \N \N {/s94-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+28b4f591-df0d-498e-92b8-9b97fae801a3 2022-05-26 09:04:23+00 2022-05-26 09:04:23+00 \N 187a1bbe-8750-47fd-a693-eb832b67106f {http,https} \N \N {/s95-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+f375807e-3ab9-4972-beac-86b454d9f9a1 2022-05-26 09:04:23+00 2022-05-26 09:04:23+00 \N 187a1bbe-8750-47fd-a693-eb832b67106f {http,https} \N \N {/s95-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+293dd5ba-72cb-4f04-8c0a-3757b6fbab6b 2022-05-26 09:04:23+00 2022-05-26 09:04:23+00 \N 187a1bbe-8750-47fd-a693-eb832b67106f {http,https} \N \N {/s95-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+61c03edb-0caa-48b0-a52e-2a462393cee3 2022-05-26 09:04:23+00 2022-05-26 09:04:23+00 \N 187a1bbe-8750-47fd-a693-eb832b67106f {http,https} \N \N {/s95-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+0e70b696-b717-4a41-b399-8ca2ff308a9c 2022-05-26 09:04:23+00 2022-05-26 09:04:23+00 \N 97cac022-7f9a-4eb7-a600-3f99cbdf8484 {http,https} \N \N {/s96-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+d3082908-2a66-42c6-9631-e1c0951f7866 2022-05-26 09:04:23+00 2022-05-26 09:04:23+00 \N 97cac022-7f9a-4eb7-a600-3f99cbdf8484 {http,https} \N \N {/s96-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+61c692c6-67dc-46e9-b910-856cd7bcda12 2022-05-26 09:04:23+00 2022-05-26 09:04:23+00 \N 97cac022-7f9a-4eb7-a600-3f99cbdf8484 {http,https} \N \N {/s96-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+c6c9e4ec-1a34-4fbd-8879-a19cb1d70325 2022-05-26 09:04:23+00 2022-05-26 09:04:23+00 \N 97cac022-7f9a-4eb7-a600-3f99cbdf8484 {http,https} \N \N {/s96-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+00014ccf-4ca8-4755-b0d2-8b92dc71920d 2022-05-26 09:04:23+00 2022-05-26 09:04:23+00 \N f731ee23-32fc-428e-858c-2451542ef358 {http,https} \N \N {/s97-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+eb580aa6-8121-4a18-bb67-7cfdecde4b6f 2022-05-26 09:04:23+00 2022-05-26 09:04:23+00 \N f731ee23-32fc-428e-858c-2451542ef358 {http,https} \N \N {/s97-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+215e806d-f5bb-431a-8497-6d144090476c 2022-05-26 09:04:23+00 2022-05-26 09:04:23+00 \N f731ee23-32fc-428e-858c-2451542ef358 {http,https} \N \N {/s97-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+99afea6a-684b-497d-a342-465f77de19f2 2022-05-26 09:04:23+00 2022-05-26 09:04:23+00 \N f731ee23-32fc-428e-858c-2451542ef358 {http,https} \N \N {/s97-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+f9643224-8206-4dea-bf38-c0774296262a 2022-05-26 09:04:23+00 2022-05-26 09:04:23+00 \N 7cdc1f2b-844d-44af-80ee-9ee8ce30ec3a {http,https} \N \N {/s98-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+2fdd828a-3fef-4df8-b800-040dbaa54e4e 2022-05-26 09:04:23+00 2022-05-26 09:04:23+00 \N 7cdc1f2b-844d-44af-80ee-9ee8ce30ec3a {http,https} \N \N {/s98-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+09ba47c5-29d7-4741-9aaa-66edacca5e2a 2022-05-26 09:04:23+00 2022-05-26 09:04:23+00 \N 7cdc1f2b-844d-44af-80ee-9ee8ce30ec3a {http,https} \N \N {/s98-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+cb992552-77ac-435a-afc0-5bc7e26d0165 2022-05-26 09:04:23+00 2022-05-26 09:04:23+00 \N 7cdc1f2b-844d-44af-80ee-9ee8ce30ec3a {http,https} \N \N {/s98-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+f93a1cf0-2ad4-4df5-a229-5c98139904da 2022-05-26 09:04:23+00 2022-05-26 09:04:23+00 \N 786c4ca2-f7e2-497f-afe9-04a7d389cffb {http,https} \N \N {/s99-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+63f416fb-0ffb-47d2-a206-5cee31b34c1b 2022-05-26 09:04:23+00 2022-05-26 09:04:23+00 \N 786c4ca2-f7e2-497f-afe9-04a7d389cffb {http,https} \N \N {/s99-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+9dfa1071-ab2b-41ba-b753-9cbefef656fb 2022-05-26 09:04:23+00 2022-05-26 09:04:23+00 \N 786c4ca2-f7e2-497f-afe9-04a7d389cffb {http,https} \N \N {/s99-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+6747376a-7cb0-406e-9f40-7797e1125a97 2022-05-26 09:04:23+00 2022-05-26 09:04:23+00 \N 786c4ca2-f7e2-497f-afe9-04a7d389cffb {http,https} \N \N {/s99-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+a4127491-d785-45fa-b64a-784acbf2a89c 2022-05-26 09:04:23+00 2022-05-26 09:04:23+00 \N 327348b0-de35-47ef-a46b-292bf1a2ce91 {http,https} \N \N {/s100-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+d67b5cb2-b0b5-4d77-924b-63bd7584d396 2022-05-26 09:04:23+00 2022-05-26 09:04:23+00 \N 327348b0-de35-47ef-a46b-292bf1a2ce91 {http,https} \N \N {/s100-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+6924c386-e398-46e5-8190-6074c7c7c690 2022-05-26 09:04:23+00 2022-05-26 09:04:23+00 \N 327348b0-de35-47ef-a46b-292bf1a2ce91 {http,https} \N \N {/s100-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+527f67de-81f0-481c-96bf-a1c18272204d 2022-05-26 09:04:23+00 2022-05-26 09:04:23+00 \N 327348b0-de35-47ef-a46b-292bf1a2ce91 {http,https} \N \N {/s100-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+89f8dc6d-5186-4a5e-8a1b-ab664092a901 2022-05-26 09:04:23+00 2022-05-26 09:04:23+00 \N 42231a53-eac6-41d4-906f-96a6007efd5c {http,https} \N \N {/s101-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+5e1cf5ab-5814-4ba0-953d-e65c50359cc2 2022-05-26 09:04:23+00 2022-05-26 09:04:23+00 \N 42231a53-eac6-41d4-906f-96a6007efd5c {http,https} \N \N {/s101-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+56c19a33-1a73-4938-a1cb-744cf850d87f 2022-05-26 09:04:23+00 2022-05-26 09:04:23+00 \N 42231a53-eac6-41d4-906f-96a6007efd5c {http,https} \N \N {/s101-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+28cf63f8-14cc-4a5b-9075-d501074d9c0c 2022-05-26 09:04:23+00 2022-05-26 09:04:23+00 \N 42231a53-eac6-41d4-906f-96a6007efd5c {http,https} \N \N {/s101-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+66247a44-9020-47eb-82ad-6c7a27a3b875 2022-05-26 09:04:23+00 2022-05-26 09:04:23+00 \N 2e5dce8d-7e56-4037-a53f-5363e78cfb67 {http,https} \N \N {/s102-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+d7590ffa-8e4e-47c9-9cd0-b82b0245af60 2022-05-26 09:04:23+00 2022-05-26 09:04:23+00 \N 2e5dce8d-7e56-4037-a53f-5363e78cfb67 {http,https} \N \N {/s102-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+0e9eebed-1078-4198-af13-1e4c61b53d85 2022-05-26 09:04:23+00 2022-05-26 09:04:23+00 \N 2e5dce8d-7e56-4037-a53f-5363e78cfb67 {http,https} \N \N {/s102-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+3ca7c895-8735-4846-af81-977f2e88e0c4 2022-05-26 09:04:23+00 2022-05-26 09:04:23+00 \N 2e5dce8d-7e56-4037-a53f-5363e78cfb67 {http,https} \N \N {/s102-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+9ec2593f-35c3-4b02-a3e8-a76c2d11921f 2022-05-26 09:04:23+00 2022-05-26 09:04:23+00 \N 880c0dfc-3b35-4557-9f4f-20e450605453 {http,https} \N \N {/s103-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+1271dbc2-9ae0-4586-b398-b13056fa66c9 2022-05-26 09:04:23+00 2022-05-26 09:04:23+00 \N 880c0dfc-3b35-4557-9f4f-20e450605453 {http,https} \N \N {/s103-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+e2d31a30-7159-48c9-8f2c-3550d00b4933 2022-05-26 09:04:23+00 2022-05-26 09:04:23+00 \N 880c0dfc-3b35-4557-9f4f-20e450605453 {http,https} \N \N {/s103-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+f7b5e9f4-70d7-40c2-9560-d0b942f078ab 2022-05-26 09:04:23+00 2022-05-26 09:04:23+00 \N 880c0dfc-3b35-4557-9f4f-20e450605453 {http,https} \N \N {/s103-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+99cbb127-80e9-4413-b6d6-a3e2ca030a16 2022-05-26 09:04:23+00 2022-05-26 09:04:23+00 \N 2d1e40d6-8080-4cee-98b2-c64c3dfbeb70 {http,https} \N \N {/s104-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+57fa6077-4a63-4419-9f3d-8835aeee2b51 2022-05-26 09:04:23+00 2022-05-26 09:04:23+00 \N 2d1e40d6-8080-4cee-98b2-c64c3dfbeb70 {http,https} \N \N {/s104-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+843b3b55-37f7-4eaa-b3c2-16f82baf4eba 2022-05-26 09:04:23+00 2022-05-26 09:04:23+00 \N 2d1e40d6-8080-4cee-98b2-c64c3dfbeb70 {http,https} \N \N {/s104-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+b56573dd-73d9-4fcf-b913-4cb34d99501f 2022-05-26 09:04:23+00 2022-05-26 09:04:23+00 \N 2d1e40d6-8080-4cee-98b2-c64c3dfbeb70 {http,https} \N \N {/s104-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+99fa82d0-384b-49cb-a8a9-081ad2b78d96 2022-05-26 09:04:23+00 2022-05-26 09:04:23+00 \N 92e0b48f-e57a-4b37-a150-ca88c81d14a3 {http,https} \N \N {/s105-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+da37c5ed-b9c5-4b50-ada0-f5bb20d979a0 2022-05-26 09:04:23+00 2022-05-26 09:04:23+00 \N 92e0b48f-e57a-4b37-a150-ca88c81d14a3 {http,https} \N \N {/s105-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+bf1f6c36-b4d2-4ee4-a30d-21b7e10fc921 2022-05-26 09:04:23+00 2022-05-26 09:04:23+00 \N 92e0b48f-e57a-4b37-a150-ca88c81d14a3 {http,https} \N \N {/s105-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+71f366dd-fa90-4cca-8bb0-32a8044c1eae 2022-05-26 09:04:23+00 2022-05-26 09:04:23+00 \N 92e0b48f-e57a-4b37-a150-ca88c81d14a3 {http,https} \N \N {/s105-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+96ea5adf-c1a8-4217-9831-ebef9e4bb447 2022-05-26 09:04:23+00 2022-05-26 09:04:23+00 \N 837f896d-e596-4681-94af-74e1f8832cec {http,https} \N \N {/s106-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+d51a47e0-df63-46dc-a58f-2a98da21fe1c 2022-05-26 09:04:23+00 2022-05-26 09:04:23+00 \N 837f896d-e596-4681-94af-74e1f8832cec {http,https} \N \N {/s106-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+2cf8e1a1-c838-45b3-8eba-73159a0e0718 2022-05-26 09:04:23+00 2022-05-26 09:04:23+00 \N 837f896d-e596-4681-94af-74e1f8832cec {http,https} \N \N {/s106-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+092d64bd-9ad3-41c0-8aaf-a2259319ceeb 2022-05-26 09:04:23+00 2022-05-26 09:04:23+00 \N 837f896d-e596-4681-94af-74e1f8832cec {http,https} \N \N {/s106-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+78e6a9d8-d4c6-442a-9a84-1f127076bb68 2022-05-26 09:04:23+00 2022-05-26 09:04:23+00 \N dfa8a1f7-4dba-4abe-b98d-11146dddf483 {http,https} \N \N {/s107-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+43beb0fa-c485-4296-b8cb-c8d135c6847a 2022-05-26 09:04:23+00 2022-05-26 09:04:23+00 \N dfa8a1f7-4dba-4abe-b98d-11146dddf483 {http,https} \N \N {/s107-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+bc74ff68-b16e-4ab5-b6d2-d8584c35d5be 2022-05-26 09:04:23+00 2022-05-26 09:04:23+00 \N dfa8a1f7-4dba-4abe-b98d-11146dddf483 {http,https} \N \N {/s107-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+aa1981d7-2398-45a9-9215-26b5622c203d 2022-05-26 09:04:23+00 2022-05-26 09:04:23+00 \N dfa8a1f7-4dba-4abe-b98d-11146dddf483 {http,https} \N \N {/s107-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+645d75d2-fefb-4d51-a076-f4f56a705b14 2022-05-26 09:04:23+00 2022-05-26 09:04:23+00 \N 87b83cd7-e97b-46e2-b8aa-cfc3f41df930 {http,https} \N \N {/s108-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+52afa8fe-7cd9-4f19-814f-f0a40ddffb48 2022-05-26 09:04:23+00 2022-05-26 09:04:23+00 \N 87b83cd7-e97b-46e2-b8aa-cfc3f41df930 {http,https} \N \N {/s108-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+20613670-0d6c-4b52-bd82-29ab4700eda8 2022-05-26 09:04:23+00 2022-05-26 09:04:23+00 \N 87b83cd7-e97b-46e2-b8aa-cfc3f41df930 {http,https} \N \N {/s108-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+fe336d75-96cc-4e8e-8923-a3f0952f7b5f 2022-05-26 09:04:24+00 2022-05-26 09:04:24+00 \N 87b83cd7-e97b-46e2-b8aa-cfc3f41df930 {http,https} \N \N {/s108-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+a4a47002-7ac0-4c25-b678-40db29d5ac21 2022-05-26 09:04:24+00 2022-05-26 09:04:24+00 \N 090f6901-a7d3-42e6-94f4-69ff07632983 {http,https} \N \N {/s109-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+da5138ea-c2ed-47fb-9f59-b6f814700b6d 2022-05-26 09:04:24+00 2022-05-26 09:04:24+00 \N 090f6901-a7d3-42e6-94f4-69ff07632983 {http,https} \N \N {/s109-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+cf40b75a-8bcd-4858-acbc-e2751a0e7afa 2022-05-26 09:04:24+00 2022-05-26 09:04:24+00 \N 090f6901-a7d3-42e6-94f4-69ff07632983 {http,https} \N \N {/s109-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+4e86288a-0c75-41da-8aa6-c6a59da62285 2022-05-26 09:04:24+00 2022-05-26 09:04:24+00 \N 090f6901-a7d3-42e6-94f4-69ff07632983 {http,https} \N \N {/s109-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+7290602b-fe3e-40b5-82bc-6b4059ed46e7 2022-05-26 09:04:24+00 2022-05-26 09:04:24+00 \N f0c01e5e-139d-4458-a3f7-47c6f9eb59de {http,https} \N \N {/s110-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+3c20d930-7ae4-4e53-89d5-3813eddabb29 2022-05-26 09:04:24+00 2022-05-26 09:04:24+00 \N f0c01e5e-139d-4458-a3f7-47c6f9eb59de {http,https} \N \N {/s110-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+22814e4c-15c5-474d-867e-d8128914d1c2 2022-05-26 09:04:24+00 2022-05-26 09:04:24+00 \N f0c01e5e-139d-4458-a3f7-47c6f9eb59de {http,https} \N \N {/s110-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+ed36a390-d149-4c0a-8847-87d6b227dade 2022-05-26 09:04:24+00 2022-05-26 09:04:24+00 \N f0c01e5e-139d-4458-a3f7-47c6f9eb59de {http,https} \N \N {/s110-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+d5f28231-3ddd-48d8-809c-c06b7c0c16e1 2022-05-26 09:04:24+00 2022-05-26 09:04:24+00 \N c1ad53a6-4115-441a-a162-5a27b3e5c01d {http,https} \N \N {/s111-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+4b9a146a-30d3-4c69-b730-284d0f77caeb 2022-05-26 09:04:24+00 2022-05-26 09:04:24+00 \N c1ad53a6-4115-441a-a162-5a27b3e5c01d {http,https} \N \N {/s111-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+9a27ff94-a4ca-4bc2-b6b7-b00a7cd28518 2022-05-26 09:04:24+00 2022-05-26 09:04:24+00 \N c1ad53a6-4115-441a-a162-5a27b3e5c01d {http,https} \N \N {/s111-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+7f4d261e-7897-498f-86cc-cbac60d7e739 2022-05-26 09:04:24+00 2022-05-26 09:04:24+00 \N c1ad53a6-4115-441a-a162-5a27b3e5c01d {http,https} \N \N {/s111-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+95c42670-8b63-487e-b3fb-86806f894d0b 2022-05-26 09:04:24+00 2022-05-26 09:04:24+00 \N 6b12e083-97d5-4964-82c5-22bc95802ef0 {http,https} \N \N {/s112-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+b72c9536-b5ac-4844-9e11-91371fac14a8 2022-05-26 09:04:24+00 2022-05-26 09:04:24+00 \N 6b12e083-97d5-4964-82c5-22bc95802ef0 {http,https} \N \N {/s112-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+3ec15c7b-a948-4967-9d83-e7fd54b5cb83 2022-05-26 09:04:24+00 2022-05-26 09:04:24+00 \N 6b12e083-97d5-4964-82c5-22bc95802ef0 {http,https} \N \N {/s112-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+8f79e102-51fd-4070-bc31-d88b340e810a 2022-05-26 09:04:24+00 2022-05-26 09:04:24+00 \N 6b12e083-97d5-4964-82c5-22bc95802ef0 {http,https} \N \N {/s112-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+bde2c98c-5c0d-486f-a6b2-924f80e044f0 2022-05-26 09:04:24+00 2022-05-26 09:04:24+00 \N 75d7f4d4-c369-46cd-bf84-fb40784d4fe1 {http,https} \N \N {/s113-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+83413b21-589d-408c-990c-c0b17838847f 2022-05-26 09:04:24+00 2022-05-26 09:04:24+00 \N 75d7f4d4-c369-46cd-bf84-fb40784d4fe1 {http,https} \N \N {/s113-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+18a13c73-d50a-4d12-aad9-16cd0d3c8a40 2022-05-26 09:04:24+00 2022-05-26 09:04:24+00 \N 75d7f4d4-c369-46cd-bf84-fb40784d4fe1 {http,https} \N \N {/s113-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+1f0e0456-c7ee-4af6-8b94-5b077ea64048 2022-05-26 09:04:24+00 2022-05-26 09:04:24+00 \N 75d7f4d4-c369-46cd-bf84-fb40784d4fe1 {http,https} \N \N {/s113-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+10664876-8b48-4c8c-a764-3c40b0be0bfc 2022-05-26 09:04:24+00 2022-05-26 09:04:24+00 \N 5e861b07-f18f-48b1-aa4d-e44f7ca06eb5 {http,https} \N \N {/s114-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+ab17906f-1ee8-4064-817e-5f904bdcf0e1 2022-05-26 09:04:24+00 2022-05-26 09:04:24+00 \N 5e861b07-f18f-48b1-aa4d-e44f7ca06eb5 {http,https} \N \N {/s114-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+520dc7fc-65be-4c4b-b25d-fa3365e23289 2022-05-26 09:04:24+00 2022-05-26 09:04:24+00 \N 5e861b07-f18f-48b1-aa4d-e44f7ca06eb5 {http,https} \N \N {/s114-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+bf18669d-d0a2-4cc6-a560-6b8c8f04889b 2022-05-26 09:04:24+00 2022-05-26 09:04:24+00 \N 5e861b07-f18f-48b1-aa4d-e44f7ca06eb5 {http,https} \N \N {/s114-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+78209c49-5cbb-42c5-b57f-234f15c66764 2022-05-26 09:04:24+00 2022-05-26 09:04:24+00 \N dc67018b-ba17-48f8-962a-e39d4e96eff4 {http,https} \N \N {/s115-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+2a24cacd-bf1a-4757-864e-a07112ddbd8b 2022-05-26 09:04:24+00 2022-05-26 09:04:24+00 \N dc67018b-ba17-48f8-962a-e39d4e96eff4 {http,https} \N \N {/s115-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+aca61615-c28e-4eff-84d8-674a55d753fc 2022-05-26 09:04:24+00 2022-05-26 09:04:24+00 \N dc67018b-ba17-48f8-962a-e39d4e96eff4 {http,https} \N \N {/s115-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+570e8fe5-d94d-43a7-802a-8b899a5261aa 2022-05-26 09:04:24+00 2022-05-26 09:04:24+00 \N dc67018b-ba17-48f8-962a-e39d4e96eff4 {http,https} \N \N {/s115-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+dc879ce6-2110-4e92-a92b-beb92d473387 2022-05-26 09:04:24+00 2022-05-26 09:04:24+00 \N d025ea98-eb37-4e43-bddc-302f5d4ecee1 {http,https} \N \N {/s116-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+1fa533ff-0362-4c74-a56d-cd413a28365a 2022-05-26 09:04:24+00 2022-05-26 09:04:24+00 \N d025ea98-eb37-4e43-bddc-302f5d4ecee1 {http,https} \N \N {/s116-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+e7b0b95e-ab6b-46bb-832b-3c75bae4f5e7 2022-05-26 09:04:24+00 2022-05-26 09:04:24+00 \N d025ea98-eb37-4e43-bddc-302f5d4ecee1 {http,https} \N \N {/s116-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+38b19459-3053-4648-8877-89fbbc1f2c77 2022-05-26 09:04:24+00 2022-05-26 09:04:24+00 \N d025ea98-eb37-4e43-bddc-302f5d4ecee1 {http,https} \N \N {/s116-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+7c7b4f75-d8c9-4a52-9338-f498326f5d50 2022-05-26 09:04:24+00 2022-05-26 09:04:24+00 \N 34f418de-2a74-47b6-ac68-9099b4281763 {http,https} \N \N {/s117-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+badac910-0e73-4e2c-a1d7-73829c48e95d 2022-05-26 09:04:24+00 2022-05-26 09:04:24+00 \N 34f418de-2a74-47b6-ac68-9099b4281763 {http,https} \N \N {/s117-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+18a1b5ec-aa61-4385-9b30-f71c68b07e06 2022-05-26 09:04:24+00 2022-05-26 09:04:24+00 \N 34f418de-2a74-47b6-ac68-9099b4281763 {http,https} \N \N {/s117-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+b6b598c0-2a3a-4d12-ba70-187419437c50 2022-05-26 09:04:24+00 2022-05-26 09:04:24+00 \N 34f418de-2a74-47b6-ac68-9099b4281763 {http,https} \N \N {/s117-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+5bedca3e-46a2-4e94-993d-9e7b21e11042 2022-05-26 09:04:24+00 2022-05-26 09:04:24+00 \N 81c2ba99-2238-48c5-9d7b-ee96f85ed0c5 {http,https} \N \N {/s118-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+2edb719b-ec2b-461d-a93d-2758a5212afb 2022-05-26 09:04:24+00 2022-05-26 09:04:24+00 \N 81c2ba99-2238-48c5-9d7b-ee96f85ed0c5 {http,https} \N \N {/s118-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+ffa536c0-c83d-42c0-84e6-ada512e9dadf 2022-05-26 09:04:24+00 2022-05-26 09:04:24+00 \N 81c2ba99-2238-48c5-9d7b-ee96f85ed0c5 {http,https} \N \N {/s118-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+48e43137-ac5c-4671-9905-2f9da67c9000 2022-05-26 09:04:24+00 2022-05-26 09:04:24+00 \N 81c2ba99-2238-48c5-9d7b-ee96f85ed0c5 {http,https} \N \N {/s118-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+1940e6e7-466d-4546-899d-5e33ed975d22 2022-05-26 09:04:24+00 2022-05-26 09:04:24+00 \N bebc02c6-4798-4c51-9c65-6ac83e7e2050 {http,https} \N \N {/s119-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+c6523340-b914-46e7-a2e3-a69e5bffa403 2022-05-26 09:04:24+00 2022-05-26 09:04:24+00 \N bebc02c6-4798-4c51-9c65-6ac83e7e2050 {http,https} \N \N {/s119-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+d93c99d0-e85a-49cf-89fa-6d87358a5b58 2022-05-26 09:04:24+00 2022-05-26 09:04:24+00 \N bebc02c6-4798-4c51-9c65-6ac83e7e2050 {http,https} \N \N {/s119-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+50f21b8f-9054-4c33-b309-20980545c572 2022-05-26 09:04:24+00 2022-05-26 09:04:24+00 \N bebc02c6-4798-4c51-9c65-6ac83e7e2050 {http,https} \N \N {/s119-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+2f2a3023-b047-4086-abd9-c5d97811124e 2022-05-26 09:04:24+00 2022-05-26 09:04:24+00 \N 84579611-336d-4291-ba77-6907426203d0 {http,https} \N \N {/s120-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+92c01ded-c2bd-4eec-bfa8-b0531bdb0a73 2022-05-26 09:04:24+00 2022-05-26 09:04:24+00 \N 84579611-336d-4291-ba77-6907426203d0 {http,https} \N \N {/s120-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+4e6ada7b-3292-4c2d-b14b-45ec885c1fd0 2022-05-26 09:04:24+00 2022-05-26 09:04:24+00 \N 84579611-336d-4291-ba77-6907426203d0 {http,https} \N \N {/s120-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+ac8b92ca-6a7a-4f7c-9b07-ffc7843880a2 2022-05-26 09:04:24+00 2022-05-26 09:04:24+00 \N 84579611-336d-4291-ba77-6907426203d0 {http,https} \N \N {/s120-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+5a2283a1-2697-4b8c-8acb-6a6f8173f681 2022-05-26 09:04:24+00 2022-05-26 09:04:24+00 \N 03d2fc5d-582c-4f45-bce2-41f8a1e45f45 {http,https} \N \N {/s121-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+5f38f49b-fdc3-464e-90d8-02b15fe2ad31 2022-05-26 09:04:24+00 2022-05-26 09:04:24+00 \N 03d2fc5d-582c-4f45-bce2-41f8a1e45f45 {http,https} \N \N {/s121-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+4e0fe610-4072-4177-9864-4a0db3492c86 2022-05-26 09:04:24+00 2022-05-26 09:04:24+00 \N 03d2fc5d-582c-4f45-bce2-41f8a1e45f45 {http,https} \N \N {/s121-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+8576e3ab-8c50-4928-a817-1807774fdf4f 2022-05-26 09:04:24+00 2022-05-26 09:04:24+00 \N 03d2fc5d-582c-4f45-bce2-41f8a1e45f45 {http,https} \N \N {/s121-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+b72e7a63-e228-46b7-94f1-3c51d14033de 2022-05-26 09:04:24+00 2022-05-26 09:04:24+00 \N 8bd5e802-0de6-462c-89d8-8a3dc33743fc {http,https} \N \N {/s122-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+5d4bcbaa-a58e-4130-b1a7-4724344b734f 2022-05-26 09:04:24+00 2022-05-26 09:04:24+00 \N 8bd5e802-0de6-462c-89d8-8a3dc33743fc {http,https} \N \N {/s122-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+7ed9986a-597c-4b54-879b-c03b8467e3ea 2022-05-26 09:04:24+00 2022-05-26 09:04:24+00 \N 8bd5e802-0de6-462c-89d8-8a3dc33743fc {http,https} \N \N {/s122-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+f4bda711-2f4b-4ef1-b4f6-51a0c9aaf551 2022-05-26 09:04:24+00 2022-05-26 09:04:24+00 \N 8bd5e802-0de6-462c-89d8-8a3dc33743fc {http,https} \N \N {/s122-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+e175c49d-b8c4-460f-a1c0-c8e5132fd117 2022-05-26 09:04:24+00 2022-05-26 09:04:24+00 \N 75a284e6-a2d0-4fa0-9210-d1dfbfe393cc {http,https} \N \N {/s123-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+13ee1365-a19c-46f8-bc06-edc10649ab5d 2022-05-26 09:04:24+00 2022-05-26 09:04:24+00 \N 75a284e6-a2d0-4fa0-9210-d1dfbfe393cc {http,https} \N \N {/s123-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+c299e8f2-c906-41ef-a314-0d76bbbfa642 2022-05-26 09:04:24+00 2022-05-26 09:04:24+00 \N 75a284e6-a2d0-4fa0-9210-d1dfbfe393cc {http,https} \N \N {/s123-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+cc1cda5a-e5bf-4d05-b24f-71c66834cd12 2022-05-26 09:04:24+00 2022-05-26 09:04:24+00 \N 75a284e6-a2d0-4fa0-9210-d1dfbfe393cc {http,https} \N \N {/s123-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+9c9c2674-9b08-4180-b780-af8b124b8713 2022-05-26 09:04:24+00 2022-05-26 09:04:24+00 \N 9462d6ae-3811-488a-8f43-93afe7e8d6ed {http,https} \N \N {/s124-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+77e43a18-b2e5-4ad3-8cd2-fb5a0642051c 2022-05-26 09:04:24+00 2022-05-26 09:04:24+00 \N 9462d6ae-3811-488a-8f43-93afe7e8d6ed {http,https} \N \N {/s124-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+0586adfd-898e-48af-85a6-46d4e32ff94a 2022-05-26 09:04:24+00 2022-05-26 09:04:24+00 \N 9462d6ae-3811-488a-8f43-93afe7e8d6ed {http,https} \N \N {/s124-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+48b5b353-d790-4cb1-928e-a0e5fc50ba43 2022-05-26 09:04:24+00 2022-05-26 09:04:24+00 \N 9462d6ae-3811-488a-8f43-93afe7e8d6ed {http,https} \N \N {/s124-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+62b72daa-088a-46be-a912-a53dacacc40d 2022-05-26 09:04:24+00 2022-05-26 09:04:24+00 \N 6a8aa9d7-cefe-455e-8671-721e43cd0b96 {http,https} \N \N {/s125-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+66d8c4b8-c15a-4fa6-ab67-f93a052240e6 2022-05-26 09:04:24+00 2022-05-26 09:04:24+00 \N 6a8aa9d7-cefe-455e-8671-721e43cd0b96 {http,https} \N \N {/s125-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+e9a334f5-9712-4d35-aa49-ee8f2a3c1c37 2022-05-26 09:04:24+00 2022-05-26 09:04:24+00 \N 6a8aa9d7-cefe-455e-8671-721e43cd0b96 {http,https} \N \N {/s125-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+e42d8021-6e19-4e0a-88d9-0c3d4b4251ca 2022-05-26 09:04:24+00 2022-05-26 09:04:24+00 \N 6a8aa9d7-cefe-455e-8671-721e43cd0b96 {http,https} \N \N {/s125-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+e3c1eada-79a8-44e2-bf0d-83e0beb0d0d6 2022-05-26 09:04:24+00 2022-05-26 09:04:24+00 \N 1a79fb8d-58e0-42d1-a2b2-a9f730a6d635 {http,https} \N \N {/s126-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+31cfa842-fde0-4f62-a531-c4da23b56987 2022-05-26 09:04:24+00 2022-05-26 09:04:24+00 \N 1a79fb8d-58e0-42d1-a2b2-a9f730a6d635 {http,https} \N \N {/s126-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+efc36e6b-b127-48f6-93bd-684d6946f011 2022-05-26 09:04:24+00 2022-05-26 09:04:24+00 \N 1a79fb8d-58e0-42d1-a2b2-a9f730a6d635 {http,https} \N \N {/s126-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+134a7d77-61d9-4cc2-ac68-c467caffe9ef 2022-05-26 09:04:24+00 2022-05-26 09:04:24+00 \N 1a79fb8d-58e0-42d1-a2b2-a9f730a6d635 {http,https} \N \N {/s126-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+22c1c65f-6dde-45bd-b897-2bfccaba56db 2022-05-26 09:04:24+00 2022-05-26 09:04:24+00 \N 693ae85e-2dcb-4bac-a88f-832ef036ec35 {http,https} \N \N {/s127-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+deda4b00-8afd-4da7-93c6-55f93d1a3940 2022-05-26 09:04:24+00 2022-05-26 09:04:24+00 \N 693ae85e-2dcb-4bac-a88f-832ef036ec35 {http,https} \N \N {/s127-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+13ca9075-a2f4-4fa2-88b5-8b2678917cdd 2022-05-26 09:04:24+00 2022-05-26 09:04:24+00 \N 693ae85e-2dcb-4bac-a88f-832ef036ec35 {http,https} \N \N {/s127-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+edc97298-b3f2-4609-b3de-abb7c1f2022b 2022-05-26 09:04:24+00 2022-05-26 09:04:24+00 \N 693ae85e-2dcb-4bac-a88f-832ef036ec35 {http,https} \N \N {/s127-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+349f9c32-5218-4754-93ac-20861d67a844 2022-05-26 09:04:24+00 2022-05-26 09:04:24+00 \N cf55043c-e758-4007-9d0b-f29ce449b017 {http,https} \N \N {/s128-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+72eae599-7eac-4ae5-8552-6128a5a1dcc8 2022-05-26 09:04:24+00 2022-05-26 09:04:24+00 \N cf55043c-e758-4007-9d0b-f29ce449b017 {http,https} \N \N {/s128-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+1e6e5c03-f26e-4952-8038-65542e6c946e 2022-05-26 09:04:24+00 2022-05-26 09:04:24+00 \N cf55043c-e758-4007-9d0b-f29ce449b017 {http,https} \N \N {/s128-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+1be86f83-0192-4b54-9cec-f9afba9d64ce 2022-05-26 09:04:24+00 2022-05-26 09:04:24+00 \N cf55043c-e758-4007-9d0b-f29ce449b017 {http,https} \N \N {/s128-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+10a509e5-1987-4c99-97cc-ba61e91cb463 2022-05-26 09:04:24+00 2022-05-26 09:04:24+00 \N b0f369f5-47ca-4790-a7c6-f70ef9670801 {http,https} \N \N {/s129-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+706ae1e3-3733-472a-8fa1-d2c252d53640 2022-05-26 09:04:24+00 2022-05-26 09:04:24+00 \N b0f369f5-47ca-4790-a7c6-f70ef9670801 {http,https} \N \N {/s129-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+d170ee14-5ddf-47c6-8b38-df0e8fc15ea6 2022-05-26 09:04:24+00 2022-05-26 09:04:24+00 \N b0f369f5-47ca-4790-a7c6-f70ef9670801 {http,https} \N \N {/s129-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+91e08902-d98f-49e6-9b6b-6662d77c9bd5 2022-05-26 09:04:24+00 2022-05-26 09:04:24+00 \N b0f369f5-47ca-4790-a7c6-f70ef9670801 {http,https} \N \N {/s129-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+8eea92e4-0351-485f-a161-7076751c078d 2022-05-26 09:04:24+00 2022-05-26 09:04:24+00 \N f54e8793-3010-4551-8a86-bc026fcdbd71 {http,https} \N \N {/s130-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+cfa091ed-d262-4f27-8bbd-48febb2fd667 2022-05-26 09:04:24+00 2022-05-26 09:04:24+00 \N f54e8793-3010-4551-8a86-bc026fcdbd71 {http,https} \N \N {/s130-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+55259e8b-9b33-4a05-bb76-413012af4a4a 2022-05-26 09:04:24+00 2022-05-26 09:04:24+00 \N f54e8793-3010-4551-8a86-bc026fcdbd71 {http,https} \N \N {/s130-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+6131c283-8f0f-4cde-a92a-0bb689946152 2022-05-26 09:04:24+00 2022-05-26 09:04:24+00 \N f54e8793-3010-4551-8a86-bc026fcdbd71 {http,https} \N \N {/s130-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+bdd51639-d904-477c-ae5c-fecbab88bde7 2022-05-26 09:04:24+00 2022-05-26 09:04:24+00 \N eda8a272-adab-466a-b5c9-ba27137d2bc3 {http,https} \N \N {/s131-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+febbe7d3-b013-4150-a925-0953ad7d6dd8 2022-05-26 09:04:24+00 2022-05-26 09:04:24+00 \N eda8a272-adab-466a-b5c9-ba27137d2bc3 {http,https} \N \N {/s131-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+59154981-6e60-4829-b8e9-35028496621c 2022-05-26 09:04:24+00 2022-05-26 09:04:24+00 \N eda8a272-adab-466a-b5c9-ba27137d2bc3 {http,https} \N \N {/s131-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+84095394-8e55-4d27-9cd4-6bbe0c5b82d9 2022-05-26 09:04:24+00 2022-05-26 09:04:24+00 \N eda8a272-adab-466a-b5c9-ba27137d2bc3 {http,https} \N \N {/s131-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+c9ce4484-1583-4a42-af69-5a8e3b731675 2022-05-26 09:04:24+00 2022-05-26 09:04:24+00 \N 78c825c8-abdd-4280-9da9-d3bf00e23f82 {http,https} \N \N {/s132-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+8e14a515-e926-44e6-9b09-3cdcae5043be 2022-05-26 09:04:24+00 2022-05-26 09:04:24+00 \N 78c825c8-abdd-4280-9da9-d3bf00e23f82 {http,https} \N \N {/s132-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+e642a930-abc7-4fea-8262-142f23cca225 2022-05-26 09:04:24+00 2022-05-26 09:04:24+00 \N 78c825c8-abdd-4280-9da9-d3bf00e23f82 {http,https} \N \N {/s132-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+f07ce3c0-4022-4953-b6e8-93077f0ac5ec 2022-05-26 09:04:24+00 2022-05-26 09:04:24+00 \N 78c825c8-abdd-4280-9da9-d3bf00e23f82 {http,https} \N \N {/s132-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+221463db-8b0c-4b4f-9074-c95726a8aee4 2022-05-26 09:04:24+00 2022-05-26 09:04:24+00 \N c3dc6599-036f-46b8-a95e-8e5b6ef3a3f5 {http,https} \N \N {/s133-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+fa564666-4866-4273-8a2e-9c2fe411e69f 2022-05-26 09:04:24+00 2022-05-26 09:04:24+00 \N c3dc6599-036f-46b8-a95e-8e5b6ef3a3f5 {http,https} \N \N {/s133-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+42113b48-05fa-40a6-ac11-fd452ceaa4c2 2022-05-26 09:04:24+00 2022-05-26 09:04:24+00 \N c3dc6599-036f-46b8-a95e-8e5b6ef3a3f5 {http,https} \N \N {/s133-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+6f48ba6a-3ec1-4019-8537-41672b494b7b 2022-05-26 09:04:24+00 2022-05-26 09:04:24+00 \N c3dc6599-036f-46b8-a95e-8e5b6ef3a3f5 {http,https} \N \N {/s133-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+bc7dbea1-6fd5-4ae3-aa0d-ff0762ca4861 2022-05-26 09:04:24+00 2022-05-26 09:04:24+00 \N 4372ca08-22e6-4a0e-8d13-f598ba86cf37 {http,https} \N \N {/s134-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+2e6aa602-9eff-416c-a3c5-bf2e33818b5c 2022-05-26 09:04:24+00 2022-05-26 09:04:24+00 \N 4372ca08-22e6-4a0e-8d13-f598ba86cf37 {http,https} \N \N {/s134-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+4da38f5e-153c-40d6-bead-d476a3a94fa9 2022-05-26 09:04:24+00 2022-05-26 09:04:24+00 \N 4372ca08-22e6-4a0e-8d13-f598ba86cf37 {http,https} \N \N {/s134-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+d784d600-b813-4709-8100-46bc0d674810 2022-05-26 09:04:24+00 2022-05-26 09:04:24+00 \N 4372ca08-22e6-4a0e-8d13-f598ba86cf37 {http,https} \N \N {/s134-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+332ac737-d32b-4f6c-bced-49a7e73d2aa3 2022-05-26 09:04:24+00 2022-05-26 09:04:24+00 \N 0766430c-c266-489c-bc27-58df3fd10388 {http,https} \N \N {/s135-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+0c29e82e-4079-4cc5-b87a-6555812349cf 2022-05-26 09:04:24+00 2022-05-26 09:04:24+00 \N 0766430c-c266-489c-bc27-58df3fd10388 {http,https} \N \N {/s135-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+253636c0-8013-4d51-871f-01a78270352d 2022-05-26 09:04:24+00 2022-05-26 09:04:24+00 \N 0766430c-c266-489c-bc27-58df3fd10388 {http,https} \N \N {/s135-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+ed9b0cc8-adef-4cd1-be95-303b7d47d553 2022-05-26 09:04:24+00 2022-05-26 09:04:24+00 \N 0766430c-c266-489c-bc27-58df3fd10388 {http,https} \N \N {/s135-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+c77769a9-0bb9-44aa-90c2-f0840c47f629 2022-05-26 09:04:24+00 2022-05-26 09:04:24+00 \N c7167c55-60fb-45f7-b257-4acddb1d9119 {http,https} \N \N {/s136-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+b54080f1-39c7-4446-8f78-ef814583a0e4 2022-05-26 09:04:24+00 2022-05-26 09:04:24+00 \N c7167c55-60fb-45f7-b257-4acddb1d9119 {http,https} \N \N {/s136-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+a68f5932-2632-44d1-a937-0734dba208e3 2022-05-26 09:04:24+00 2022-05-26 09:04:24+00 \N c7167c55-60fb-45f7-b257-4acddb1d9119 {http,https} \N \N {/s136-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+40614334-e48d-433d-947c-64c0c5055aef 2022-05-26 09:04:24+00 2022-05-26 09:04:24+00 \N c7167c55-60fb-45f7-b257-4acddb1d9119 {http,https} \N \N {/s136-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+c308cce9-e114-4e48-925e-94804505abdf 2022-05-26 09:04:25+00 2022-05-26 09:04:25+00 \N 76b8797a-0ad8-4a9f-9fdf-561c79e481d9 {http,https} \N \N {/s137-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+ec57a214-5299-4c0e-9de6-dc8df6fff285 2022-05-26 09:04:25+00 2022-05-26 09:04:25+00 \N 76b8797a-0ad8-4a9f-9fdf-561c79e481d9 {http,https} \N \N {/s137-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+cb583546-40d6-418c-8552-fa944d2412bb 2022-05-26 09:04:25+00 2022-05-26 09:04:25+00 \N 76b8797a-0ad8-4a9f-9fdf-561c79e481d9 {http,https} \N \N {/s137-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+1952393c-d082-4d15-b2bc-29e2d7f82ed3 2022-05-26 09:04:25+00 2022-05-26 09:04:25+00 \N 76b8797a-0ad8-4a9f-9fdf-561c79e481d9 {http,https} \N \N {/s137-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+5c248012-76cb-453c-909b-d40632e801e1 2022-05-26 09:04:25+00 2022-05-26 09:04:25+00 \N bad7c636-19ad-430e-8c49-6e4efddc4376 {http,https} \N \N {/s138-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+fb2c93c5-42ee-4015-b968-df7c7e9c8b82 2022-05-26 09:04:25+00 2022-05-26 09:04:25+00 \N bad7c636-19ad-430e-8c49-6e4efddc4376 {http,https} \N \N {/s138-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+8ab89b41-6cfe-48b6-a3e5-367ecec10896 2022-05-26 09:04:25+00 2022-05-26 09:04:25+00 \N bad7c636-19ad-430e-8c49-6e4efddc4376 {http,https} \N \N {/s138-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+6a2e0400-a685-4c85-abcc-b5ef1fdd7051 2022-05-26 09:04:25+00 2022-05-26 09:04:25+00 \N bad7c636-19ad-430e-8c49-6e4efddc4376 {http,https} \N \N {/s138-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+5f6241fa-ab8a-4cf8-803e-552751cdbbdb 2022-05-26 09:04:25+00 2022-05-26 09:04:25+00 \N fd6fd9ca-1169-45ba-bb87-8b846a8d0d3e {http,https} \N \N {/s139-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+2a8523fc-1001-4503-a12f-db41805792f8 2022-05-26 09:04:25+00 2022-05-26 09:04:25+00 \N fd6fd9ca-1169-45ba-bb87-8b846a8d0d3e {http,https} \N \N {/s139-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+bc54e31d-68da-46cc-b0da-84aea518e92e 2022-05-26 09:04:25+00 2022-05-26 09:04:25+00 \N fd6fd9ca-1169-45ba-bb87-8b846a8d0d3e {http,https} \N \N {/s139-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+08814b9e-e844-4393-a4b8-802458c70eaf 2022-05-26 09:04:25+00 2022-05-26 09:04:25+00 \N fd6fd9ca-1169-45ba-bb87-8b846a8d0d3e {http,https} \N \N {/s139-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+952cad34-82e7-4474-b402-3d9b3467fba0 2022-05-26 09:04:25+00 2022-05-26 09:04:25+00 \N a2ee552e-0961-4036-8d1c-8ebd420f28ed {http,https} \N \N {/s140-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+3f75d9ae-7607-4e84-9382-b80f2d70a99d 2022-05-26 09:04:25+00 2022-05-26 09:04:25+00 \N a2ee552e-0961-4036-8d1c-8ebd420f28ed {http,https} \N \N {/s140-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+0517cf2c-98e8-41de-ae3b-56c2daee2859 2022-05-26 09:04:25+00 2022-05-26 09:04:25+00 \N a2ee552e-0961-4036-8d1c-8ebd420f28ed {http,https} \N \N {/s140-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+fbde95fa-3633-41d1-beca-8df6f9f1b0ae 2022-05-26 09:04:25+00 2022-05-26 09:04:25+00 \N a2ee552e-0961-4036-8d1c-8ebd420f28ed {http,https} \N \N {/s140-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+c04af6ae-707e-4f8e-8e03-d6b59d1ddb57 2022-05-26 09:04:25+00 2022-05-26 09:04:25+00 \N 6fca3f1f-fa31-4c70-8059-aee7dd0d5be3 {http,https} \N \N {/s141-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+79657c82-6938-4449-9349-48ec8678e142 2022-05-26 09:04:25+00 2022-05-26 09:04:25+00 \N 6fca3f1f-fa31-4c70-8059-aee7dd0d5be3 {http,https} \N \N {/s141-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+37381f66-6f01-4b17-824b-27896e93bd95 2022-05-26 09:04:25+00 2022-05-26 09:04:25+00 \N 6fca3f1f-fa31-4c70-8059-aee7dd0d5be3 {http,https} \N \N {/s141-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+0ee50621-2c9a-4945-b938-4a203e6ea199 2022-05-26 09:04:25+00 2022-05-26 09:04:25+00 \N 6fca3f1f-fa31-4c70-8059-aee7dd0d5be3 {http,https} \N \N {/s141-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+80291ade-7bd3-42f8-8ea5-98a1355def09 2022-05-26 09:04:25+00 2022-05-26 09:04:25+00 \N 70d03905-4002-4dc1-b3f9-336d25ee164e {http,https} \N \N {/s142-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+009ea757-f3ad-4302-8296-abe06be681f0 2022-05-26 09:04:25+00 2022-05-26 09:04:25+00 \N 70d03905-4002-4dc1-b3f9-336d25ee164e {http,https} \N \N {/s142-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+4b00370e-83a7-48e5-8e88-43685cde1dca 2022-05-26 09:04:25+00 2022-05-26 09:04:25+00 \N 70d03905-4002-4dc1-b3f9-336d25ee164e {http,https} \N \N {/s142-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+b6887d29-3015-4e8b-b486-02dc03fb70f5 2022-05-26 09:04:25+00 2022-05-26 09:04:25+00 \N 70d03905-4002-4dc1-b3f9-336d25ee164e {http,https} \N \N {/s142-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+54b9278d-ea83-4814-ba00-fa11eb2e0183 2022-05-26 09:04:25+00 2022-05-26 09:04:25+00 \N 4693dd6c-1d27-46df-b5be-259eda6ad3df {http,https} \N \N {/s143-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+3a7fe796-5dd8-40fe-842d-d8a4750493c7 2022-05-26 09:04:25+00 2022-05-26 09:04:25+00 \N 4693dd6c-1d27-46df-b5be-259eda6ad3df {http,https} \N \N {/s143-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+8a73b9f2-4758-4a32-9d2d-6186cbd37d06 2022-05-26 09:04:25+00 2022-05-26 09:04:25+00 \N 4693dd6c-1d27-46df-b5be-259eda6ad3df {http,https} \N \N {/s143-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+c40b1edc-e918-47ca-896d-2fe861a2b16d 2022-05-26 09:04:25+00 2022-05-26 09:04:25+00 \N 4693dd6c-1d27-46df-b5be-259eda6ad3df {http,https} \N \N {/s143-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+a9007af4-7294-4faf-99d1-ea26e4664eea 2022-05-26 09:04:25+00 2022-05-26 09:04:25+00 \N 390c61c3-b91b-44d0-9132-d629f3f7f2c2 {http,https} \N \N {/s144-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+8390994d-f65b-486b-b331-d6233c27975d 2022-05-26 09:04:25+00 2022-05-26 09:04:25+00 \N 390c61c3-b91b-44d0-9132-d629f3f7f2c2 {http,https} \N \N {/s144-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+286457da-3d3d-442a-a47e-eddc90f94fae 2022-05-26 09:04:25+00 2022-05-26 09:04:25+00 \N 390c61c3-b91b-44d0-9132-d629f3f7f2c2 {http,https} \N \N {/s144-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+f2bb38fd-11c0-4302-bc73-9f2b92bfdb7e 2022-05-26 09:04:25+00 2022-05-26 09:04:25+00 \N 390c61c3-b91b-44d0-9132-d629f3f7f2c2 {http,https} \N \N {/s144-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+799f1236-6939-49dc-9559-ce456182edfe 2022-05-26 09:04:25+00 2022-05-26 09:04:25+00 \N addbf9ae-c319-4a46-831b-a2c71204cfdc {http,https} \N \N {/s145-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+afa4a841-ac7e-479d-8cfb-6ee4f3e7576c 2022-05-26 09:04:25+00 2022-05-26 09:04:25+00 \N addbf9ae-c319-4a46-831b-a2c71204cfdc {http,https} \N \N {/s145-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+48d3420a-0715-417a-bd0e-595428ee8552 2022-05-26 09:04:25+00 2022-05-26 09:04:25+00 \N addbf9ae-c319-4a46-831b-a2c71204cfdc {http,https} \N \N {/s145-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+1e3c0494-c573-4202-802e-16c020bd1dcc 2022-05-26 09:04:25+00 2022-05-26 09:04:25+00 \N addbf9ae-c319-4a46-831b-a2c71204cfdc {http,https} \N \N {/s145-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+71d5e006-1d1b-45d3-ab77-767bbc08dacf 2022-05-26 09:04:25+00 2022-05-26 09:04:25+00 \N d59261e7-93ca-464a-b84d-cc9c64e2d649 {http,https} \N \N {/s146-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+40d37028-4253-4d09-a7d4-1d9afb2f80f5 2022-05-26 09:04:25+00 2022-05-26 09:04:25+00 \N d59261e7-93ca-464a-b84d-cc9c64e2d649 {http,https} \N \N {/s146-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+5fa958da-4c0b-4ff0-921e-2d4425c096e2 2022-05-26 09:04:25+00 2022-05-26 09:04:25+00 \N d59261e7-93ca-464a-b84d-cc9c64e2d649 {http,https} \N \N {/s146-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+87f8e3b3-db11-4fb6-897e-3bcf78d1d2f2 2022-05-26 09:04:25+00 2022-05-26 09:04:25+00 \N d59261e7-93ca-464a-b84d-cc9c64e2d649 {http,https} \N \N {/s146-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+d55f55bb-699e-4e16-ac97-197e8f7f4a24 2022-05-26 09:04:25+00 2022-05-26 09:04:25+00 \N 37262d9e-1dd7-4314-9a5a-d289c7479be0 {http,https} \N \N {/s147-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+ec1563f8-689b-4621-b57f-89f5fabb6b8a 2022-05-26 09:04:25+00 2022-05-26 09:04:25+00 \N 37262d9e-1dd7-4314-9a5a-d289c7479be0 {http,https} \N \N {/s147-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+b2ade045-55bf-438b-b0e2-f499953aa888 2022-05-26 09:04:25+00 2022-05-26 09:04:25+00 \N 37262d9e-1dd7-4314-9a5a-d289c7479be0 {http,https} \N \N {/s147-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+8c8b26e7-b443-4738-82f2-3695cd656943 2022-05-26 09:04:25+00 2022-05-26 09:04:25+00 \N 37262d9e-1dd7-4314-9a5a-d289c7479be0 {http,https} \N \N {/s147-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+20a06da8-c6b3-4250-8d30-8bcabb5d97d9 2022-05-26 09:04:25+00 2022-05-26 09:04:25+00 \N d3ec5e93-e9e3-4fd4-a27b-6af1e300aa4b {http,https} \N \N {/s148-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+4ceeb28c-8cac-4f52-8a6d-400716ad0cfb 2022-05-26 09:04:25+00 2022-05-26 09:04:25+00 \N d3ec5e93-e9e3-4fd4-a27b-6af1e300aa4b {http,https} \N \N {/s148-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+10b33ab3-84ff-4c07-961c-8baf666ebf7f 2022-05-26 09:04:25+00 2022-05-26 09:04:25+00 \N d3ec5e93-e9e3-4fd4-a27b-6af1e300aa4b {http,https} \N \N {/s148-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+76636d5b-a12e-4fe9-a09b-c98ecdad1743 2022-05-26 09:04:25+00 2022-05-26 09:04:25+00 \N d3ec5e93-e9e3-4fd4-a27b-6af1e300aa4b {http,https} \N \N {/s148-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+09b43683-f7ac-480f-b8df-4d99f6a5703b 2022-05-26 09:04:25+00 2022-05-26 09:04:25+00 \N 0cdb0d81-1c8a-49b4-b5aa-50b627e298c6 {http,https} \N \N {/s149-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+ea17964f-4682-47be-8580-4e94210d34ec 2022-05-26 09:04:25+00 2022-05-26 09:04:25+00 \N 0cdb0d81-1c8a-49b4-b5aa-50b627e298c6 {http,https} \N \N {/s149-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+e82f3a93-209d-4e7c-aec5-3874747b2b8a 2022-05-26 09:04:25+00 2022-05-26 09:04:25+00 \N 0cdb0d81-1c8a-49b4-b5aa-50b627e298c6 {http,https} \N \N {/s149-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+69784499-8f2a-4fcc-9fe6-e0ab42202ef6 2022-05-26 09:04:25+00 2022-05-26 09:04:25+00 \N 0cdb0d81-1c8a-49b4-b5aa-50b627e298c6 {http,https} \N \N {/s149-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+85dd27b7-3399-4ab0-8ec7-d2e397ea301b 2022-05-26 09:04:25+00 2022-05-26 09:04:25+00 \N 5e987b7a-1d92-49e3-ad2f-362501d07bf9 {http,https} \N \N {/s150-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+c9f001c3-3cdb-4a5f-997d-3a7b00022131 2022-05-26 09:04:25+00 2022-05-26 09:04:25+00 \N 5e987b7a-1d92-49e3-ad2f-362501d07bf9 {http,https} \N \N {/s150-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+39c52891-9c51-4f8d-85bf-9604c3f49c22 2022-05-26 09:04:25+00 2022-05-26 09:04:25+00 \N 5e987b7a-1d92-49e3-ad2f-362501d07bf9 {http,https} \N \N {/s150-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+9b34cd4b-03f7-4911-8326-52e6b1156649 2022-05-26 09:04:25+00 2022-05-26 09:04:25+00 \N 5e987b7a-1d92-49e3-ad2f-362501d07bf9 {http,https} \N \N {/s150-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+af5092d3-7538-4c67-a03a-e13d86f94516 2022-05-26 09:04:25+00 2022-05-26 09:04:25+00 \N 98193422-6ec1-4767-8568-e34555d37244 {http,https} \N \N {/s151-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+f990e621-c712-4904-8d2a-7f0f97c4c3d0 2022-05-26 09:04:25+00 2022-05-26 09:04:25+00 \N 98193422-6ec1-4767-8568-e34555d37244 {http,https} \N \N {/s151-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+735fede1-62ad-4693-a8c9-aa88ed3e3bc0 2022-05-26 09:04:25+00 2022-05-26 09:04:25+00 \N 98193422-6ec1-4767-8568-e34555d37244 {http,https} \N \N {/s151-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+98a8d34c-8127-469a-a53f-930fe4864220 2022-05-26 09:04:25+00 2022-05-26 09:04:25+00 \N 98193422-6ec1-4767-8568-e34555d37244 {http,https} \N \N {/s151-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+d240fa9b-a666-4967-9e28-d757193dd92d 2022-05-26 09:04:25+00 2022-05-26 09:04:25+00 \N 23c5d21a-6ff6-4f87-950b-3189611df400 {http,https} \N \N {/s152-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+cee33038-b02b-401c-b30c-ea12d9e6cb5b 2022-05-26 09:04:25+00 2022-05-26 09:04:25+00 \N 23c5d21a-6ff6-4f87-950b-3189611df400 {http,https} \N \N {/s152-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+e7664be5-15b5-4459-863a-9a57aeabd8db 2022-05-26 09:04:25+00 2022-05-26 09:04:25+00 \N 23c5d21a-6ff6-4f87-950b-3189611df400 {http,https} \N \N {/s152-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+c7300262-fb86-4140-9dd8-541f90ba1602 2022-05-26 09:04:25+00 2022-05-26 09:04:25+00 \N 23c5d21a-6ff6-4f87-950b-3189611df400 {http,https} \N \N {/s152-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+7a83033b-385b-4e01-90ea-acc959fae024 2022-05-26 09:04:25+00 2022-05-26 09:04:25+00 \N 61b20f0c-ad75-46c5-bdb1-c9ee4db679eb {http,https} \N \N {/s153-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+dc96baa4-77a2-456d-85da-1e09359806a2 2022-05-26 09:04:25+00 2022-05-26 09:04:25+00 \N 61b20f0c-ad75-46c5-bdb1-c9ee4db679eb {http,https} \N \N {/s153-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+35faf989-ccc4-4d00-88da-a30a1726bf76 2022-05-26 09:04:25+00 2022-05-26 09:04:25+00 \N 61b20f0c-ad75-46c5-bdb1-c9ee4db679eb {http,https} \N \N {/s153-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+aadd4d64-4895-45e8-850a-5df9123186d3 2022-05-26 09:04:25+00 2022-05-26 09:04:25+00 \N 61b20f0c-ad75-46c5-bdb1-c9ee4db679eb {http,https} \N \N {/s153-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+43b90307-3f64-4595-9c39-7e96c80a03ec 2022-05-26 09:04:25+00 2022-05-26 09:04:25+00 \N f658e233-91f5-4e42-a97f-43303defe86d {http,https} \N \N {/s154-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+f6fe2815-3819-40fa-8901-4baf0fc1c4a5 2022-05-26 09:04:25+00 2022-05-26 09:04:25+00 \N f658e233-91f5-4e42-a97f-43303defe86d {http,https} \N \N {/s154-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+cc0a9449-df5d-44fe-a9d3-7332f4787c05 2022-05-26 09:04:25+00 2022-05-26 09:04:25+00 \N f658e233-91f5-4e42-a97f-43303defe86d {http,https} \N \N {/s154-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+dfae0345-b3d0-4ce1-bafd-39bffa1ad3ea 2022-05-26 09:04:25+00 2022-05-26 09:04:25+00 \N f658e233-91f5-4e42-a97f-43303defe86d {http,https} \N \N {/s154-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+49206548-9d47-43f6-aa41-d8fccc9032a3 2022-05-26 09:04:25+00 2022-05-26 09:04:25+00 \N bf2c91f2-cfdd-4f0a-bb05-0433141ad9ce {http,https} \N \N {/s155-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+2b088891-7e35-4485-ad96-e1b450341308 2022-05-26 09:04:25+00 2022-05-26 09:04:25+00 \N bf2c91f2-cfdd-4f0a-bb05-0433141ad9ce {http,https} \N \N {/s155-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+dfc48b47-1ab1-4253-af03-2be8b4070ab2 2022-05-26 09:04:25+00 2022-05-26 09:04:25+00 \N bf2c91f2-cfdd-4f0a-bb05-0433141ad9ce {http,https} \N \N {/s155-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+f5cfbdc5-4203-4ce9-8d60-2441dfa6f6ea 2022-05-26 09:04:25+00 2022-05-26 09:04:25+00 \N bf2c91f2-cfdd-4f0a-bb05-0433141ad9ce {http,https} \N \N {/s155-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+d529b339-f52e-4cde-a88c-fe21ca1edbb9 2022-05-26 09:04:25+00 2022-05-26 09:04:25+00 \N 44e7d282-81cf-4f35-b20d-289a41d57da9 {http,https} \N \N {/s156-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+b1858bb9-c701-41ab-8faf-ef7abdc3f2af 2022-05-26 09:04:25+00 2022-05-26 09:04:25+00 \N 44e7d282-81cf-4f35-b20d-289a41d57da9 {http,https} \N \N {/s156-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+34d86e9c-51f8-4de3-b44f-6a91904649d2 2022-05-26 09:04:25+00 2022-05-26 09:04:25+00 \N 44e7d282-81cf-4f35-b20d-289a41d57da9 {http,https} \N \N {/s156-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+83dd3ef4-3da3-42d3-98ff-83f6f00e18ae 2022-05-26 09:04:25+00 2022-05-26 09:04:25+00 \N 44e7d282-81cf-4f35-b20d-289a41d57da9 {http,https} \N \N {/s156-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+87989a69-9c8a-4037-9fea-680cc4fd282b 2022-05-26 09:04:25+00 2022-05-26 09:04:25+00 \N 5e9458db-1f76-4728-bf68-8f100dcb5e04 {http,https} \N \N {/s157-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+0f42d0c4-09bf-4799-a550-d7bd5de071cf 2022-05-26 09:04:25+00 2022-05-26 09:04:25+00 \N 5e9458db-1f76-4728-bf68-8f100dcb5e04 {http,https} \N \N {/s157-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+67a0134f-95ac-4aea-a181-e16091b3261b 2022-05-26 09:04:25+00 2022-05-26 09:04:25+00 \N 5e9458db-1f76-4728-bf68-8f100dcb5e04 {http,https} \N \N {/s157-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+be0fe9db-b3a3-4221-a3a0-e3d4e9183d56 2022-05-26 09:04:25+00 2022-05-26 09:04:25+00 \N 5e9458db-1f76-4728-bf68-8f100dcb5e04 {http,https} \N \N {/s157-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+22d86719-08cd-4b0b-9e00-f9957f27dde2 2022-05-26 09:04:25+00 2022-05-26 09:04:25+00 \N 5cf7efb5-6ce3-4bfa-9b9c-69615c0424c3 {http,https} \N \N {/s158-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+2fe55a66-ab3e-4816-8a2d-4f3f992bc8d7 2022-05-26 09:04:25+00 2022-05-26 09:04:25+00 \N 5cf7efb5-6ce3-4bfa-9b9c-69615c0424c3 {http,https} \N \N {/s158-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+eabeed58-c2e9-4516-b141-2e55494094f4 2022-05-26 09:04:25+00 2022-05-26 09:04:25+00 \N 5cf7efb5-6ce3-4bfa-9b9c-69615c0424c3 {http,https} \N \N {/s158-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+c29be95e-602c-461e-9836-2eaf64373ae0 2022-05-26 09:04:25+00 2022-05-26 09:04:25+00 \N 5cf7efb5-6ce3-4bfa-9b9c-69615c0424c3 {http,https} \N \N {/s158-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+e2e495a6-8e59-41bb-91c0-3c9336f2d28e 2022-05-26 09:04:25+00 2022-05-26 09:04:25+00 \N e601de5f-ad58-4d48-83b7-bc0e20cadd7e {http,https} \N \N {/s159-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+b2c400a2-57a3-4756-a5a5-20c57fc6da35 2022-05-26 09:04:25+00 2022-05-26 09:04:25+00 \N e601de5f-ad58-4d48-83b7-bc0e20cadd7e {http,https} \N \N {/s159-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+c70e2d23-3f67-4bad-8c2b-0ae0bf15b8d9 2022-05-26 09:04:25+00 2022-05-26 09:04:25+00 \N e601de5f-ad58-4d48-83b7-bc0e20cadd7e {http,https} \N \N {/s159-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+fd0b32f7-c191-46c2-82df-54ed7eea9ada 2022-05-26 09:04:25+00 2022-05-26 09:04:25+00 \N e601de5f-ad58-4d48-83b7-bc0e20cadd7e {http,https} \N \N {/s159-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+eb4d3228-d924-463b-91ec-d7c92d472bc9 2022-05-26 09:04:25+00 2022-05-26 09:04:25+00 \N 3995380e-ac1c-4133-a6e1-65a2b355a121 {http,https} \N \N {/s160-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+daad247c-b556-4547-b6ff-76c3489e0c7d 2022-05-26 09:04:25+00 2022-05-26 09:04:25+00 \N 3995380e-ac1c-4133-a6e1-65a2b355a121 {http,https} \N \N {/s160-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+5f454e59-d967-46f5-95cd-37a6e8363121 2022-05-26 09:04:25+00 2022-05-26 09:04:25+00 \N 3995380e-ac1c-4133-a6e1-65a2b355a121 {http,https} \N \N {/s160-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+ddd7d394-ee2a-4812-9cce-9397b487698e 2022-05-26 09:04:25+00 2022-05-26 09:04:25+00 \N 3995380e-ac1c-4133-a6e1-65a2b355a121 {http,https} \N \N {/s160-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+4a5efd5a-f47f-4ec8-9c73-59657da79ea1 2022-05-26 09:04:25+00 2022-05-26 09:04:25+00 \N 109dabd3-4d13-40ea-b6f4-2a94d74c7f6c {http,https} \N \N {/s161-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+2b21d645-cd05-4ae9-9072-b5b343826646 2022-05-26 09:04:25+00 2022-05-26 09:04:25+00 \N 109dabd3-4d13-40ea-b6f4-2a94d74c7f6c {http,https} \N \N {/s161-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+d71ea753-3fe6-4582-85af-02c13ec4f25f 2022-05-26 09:04:25+00 2022-05-26 09:04:25+00 \N 109dabd3-4d13-40ea-b6f4-2a94d74c7f6c {http,https} \N \N {/s161-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+dcc781be-61d7-488f-8a54-39b32aca478b 2022-05-26 09:04:25+00 2022-05-26 09:04:25+00 \N 109dabd3-4d13-40ea-b6f4-2a94d74c7f6c {http,https} \N \N {/s161-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+79528e1b-fa40-4dfe-a02d-67c5681b347a 2022-05-26 09:04:25+00 2022-05-26 09:04:25+00 \N 502c5b41-66bf-4383-918a-badfea2d25c7 {http,https} \N \N {/s162-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+f763ec59-ab8e-465a-acb1-9d9c6cb7a607 2022-05-26 09:04:25+00 2022-05-26 09:04:25+00 \N 502c5b41-66bf-4383-918a-badfea2d25c7 {http,https} \N \N {/s162-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+7f1d5485-afa9-4f7c-97a6-709cc21b906a 2022-05-26 09:04:25+00 2022-05-26 09:04:25+00 \N 502c5b41-66bf-4383-918a-badfea2d25c7 {http,https} \N \N {/s162-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+ffe74437-4a70-40f0-be0e-5b389c7ae2f0 2022-05-26 09:04:25+00 2022-05-26 09:04:25+00 \N 502c5b41-66bf-4383-918a-badfea2d25c7 {http,https} \N \N {/s162-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+fd14267c-b276-4cac-bc09-6a95fff7540e 2022-05-26 09:04:25+00 2022-05-26 09:04:25+00 \N 9557d7a1-d82f-4fab-a4c1-59b705f29b2e {http,https} \N \N {/s163-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+04c7a8b9-a0a2-4fc9-b61e-c9722e7d2367 2022-05-26 09:04:25+00 2022-05-26 09:04:25+00 \N 9557d7a1-d82f-4fab-a4c1-59b705f29b2e {http,https} \N \N {/s163-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+4e86a838-8e98-40d7-96ef-62e4248a68b3 2022-05-26 09:04:25+00 2022-05-26 09:04:25+00 \N 9557d7a1-d82f-4fab-a4c1-59b705f29b2e {http,https} \N \N {/s163-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+5074512e-c1e0-4c3c-b79a-368b0a3ce696 2022-05-26 09:04:25+00 2022-05-26 09:04:25+00 \N 9557d7a1-d82f-4fab-a4c1-59b705f29b2e {http,https} \N \N {/s163-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+a92a46d7-e383-4199-80a1-65ab84ed38e7 2022-05-26 09:04:25+00 2022-05-26 09:04:25+00 \N cefbb83a-2d32-4aba-83e1-1ad7811849e9 {http,https} \N \N {/s164-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+f325ec0c-73df-4b78-a4c3-a34006513067 2022-05-26 09:04:25+00 2022-05-26 09:04:25+00 \N cefbb83a-2d32-4aba-83e1-1ad7811849e9 {http,https} \N \N {/s164-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+2f4154d0-78ce-4ff2-bf50-03a4fb272e4f 2022-05-26 09:04:25+00 2022-05-26 09:04:25+00 \N cefbb83a-2d32-4aba-83e1-1ad7811849e9 {http,https} \N \N {/s164-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+72544d66-cec7-476c-af59-f1af6974176e 2022-05-26 09:04:25+00 2022-05-26 09:04:25+00 \N cefbb83a-2d32-4aba-83e1-1ad7811849e9 {http,https} \N \N {/s164-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+be535d03-73d3-471e-aed6-8833ae34a2ae 2022-05-26 09:04:25+00 2022-05-26 09:04:25+00 \N 24fbd204-d7a7-4d11-9109-a73e52f718b1 {http,https} \N \N {/s165-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+bc95d9db-2f13-464d-a318-99d242a2bb52 2022-05-26 09:04:25+00 2022-05-26 09:04:25+00 \N 24fbd204-d7a7-4d11-9109-a73e52f718b1 {http,https} \N \N {/s165-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+18b7158f-dedf-48ea-85b3-147c47351fcd 2022-05-26 09:04:25+00 2022-05-26 09:04:25+00 \N 24fbd204-d7a7-4d11-9109-a73e52f718b1 {http,https} \N \N {/s165-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+b9bd8aa8-6682-47d1-85a6-57723ba8e341 2022-05-26 09:04:25+00 2022-05-26 09:04:25+00 \N 24fbd204-d7a7-4d11-9109-a73e52f718b1 {http,https} \N \N {/s165-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+93e68fcf-c0b5-4f1b-9605-da6389ab6621 2022-05-26 09:04:25+00 2022-05-26 09:04:25+00 \N ef9b8d4d-3e83-4353-a80e-426e5fc7cbb9 {http,https} \N \N {/s166-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+51266dc4-3bdf-415f-b1ae-f3842cbe5dee 2022-05-26 09:04:25+00 2022-05-26 09:04:25+00 \N ef9b8d4d-3e83-4353-a80e-426e5fc7cbb9 {http,https} \N \N {/s166-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+2f306910-0c7b-4bfb-8cc5-4e4280adcfa6 2022-05-26 09:04:25+00 2022-05-26 09:04:25+00 \N ef9b8d4d-3e83-4353-a80e-426e5fc7cbb9 {http,https} \N \N {/s166-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+6eb78f5c-80c0-4492-b352-055da84d6a98 2022-05-26 09:04:25+00 2022-05-26 09:04:25+00 \N ef9b8d4d-3e83-4353-a80e-426e5fc7cbb9 {http,https} \N \N {/s166-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+19a74a8f-9328-4e67-be6e-3d296866251e 2022-05-26 09:04:26+00 2022-05-26 09:04:26+00 \N bd6e4a2a-b1f5-4fdf-bb0d-6e9918275bd6 {http,https} \N \N {/s167-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+28590603-cb60-45a8-835f-bfc5232380c5 2022-05-26 09:04:26+00 2022-05-26 09:04:26+00 \N bd6e4a2a-b1f5-4fdf-bb0d-6e9918275bd6 {http,https} \N \N {/s167-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+3a7417a0-1ba7-47db-913e-ca211871ddba 2022-05-26 09:04:26+00 2022-05-26 09:04:26+00 \N bd6e4a2a-b1f5-4fdf-bb0d-6e9918275bd6 {http,https} \N \N {/s167-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+e51ced59-2ced-4656-966f-584a9a4e488a 2022-05-26 09:04:26+00 2022-05-26 09:04:26+00 \N bd6e4a2a-b1f5-4fdf-bb0d-6e9918275bd6 {http,https} \N \N {/s167-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+e50002ab-e446-4061-93f7-68d7c2cfa4d5 2022-05-26 09:04:26+00 2022-05-26 09:04:26+00 \N a39c21f4-1588-473b-b5f0-ca58437f5670 {http,https} \N \N {/s168-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+471db396-7e15-4da7-8991-73ab2ad29ea4 2022-05-26 09:04:26+00 2022-05-26 09:04:26+00 \N a39c21f4-1588-473b-b5f0-ca58437f5670 {http,https} \N \N {/s168-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+2277f88f-da72-4c75-851d-9b444121c708 2022-05-26 09:04:26+00 2022-05-26 09:04:26+00 \N a39c21f4-1588-473b-b5f0-ca58437f5670 {http,https} \N \N {/s168-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+1e6ab643-c8e7-4bfd-8b7f-fc838a15afb4 2022-05-26 09:04:26+00 2022-05-26 09:04:26+00 \N a39c21f4-1588-473b-b5f0-ca58437f5670 {http,https} \N \N {/s168-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+5f6d11d3-2fa2-4101-86f5-e2c7f169f5ff 2022-05-26 09:04:26+00 2022-05-26 09:04:26+00 \N cd7ff4b6-0461-43d7-89d4-00df67b34598 {http,https} \N \N {/s169-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+87d2868f-44db-445d-a98a-7c3ee3502eee 2022-05-26 09:04:26+00 2022-05-26 09:04:26+00 \N cd7ff4b6-0461-43d7-89d4-00df67b34598 {http,https} \N \N {/s169-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+2171b9be-1957-4eb2-aafb-b201eecc0199 2022-05-26 09:04:26+00 2022-05-26 09:04:26+00 \N cd7ff4b6-0461-43d7-89d4-00df67b34598 {http,https} \N \N {/s169-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+c9b8b29f-1044-490c-8227-546e7c524de9 2022-05-26 09:04:26+00 2022-05-26 09:04:26+00 \N cd7ff4b6-0461-43d7-89d4-00df67b34598 {http,https} \N \N {/s169-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+014a55eb-f1f5-42b5-9fd5-c1e7a06e8bad 2022-05-26 09:04:26+00 2022-05-26 09:04:26+00 \N d46890a2-26b2-4d3c-860d-f54cc24b7663 {http,https} \N \N {/s170-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+04902f25-a16f-47d8-8870-10ceb0fdc8bc 2022-05-26 09:04:26+00 2022-05-26 09:04:26+00 \N d46890a2-26b2-4d3c-860d-f54cc24b7663 {http,https} \N \N {/s170-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+18a21895-85e8-4b21-b594-750a5352ba3e 2022-05-26 09:04:26+00 2022-05-26 09:04:26+00 \N d46890a2-26b2-4d3c-860d-f54cc24b7663 {http,https} \N \N {/s170-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+261c98c5-f53c-400d-8562-8a917211812c 2022-05-26 09:04:26+00 2022-05-26 09:04:26+00 \N d46890a2-26b2-4d3c-860d-f54cc24b7663 {http,https} \N \N {/s170-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+cd4fadc3-d86e-4ed2-b0a0-5eac3256d265 2022-05-26 09:04:26+00 2022-05-26 09:04:26+00 \N 4d17db21-c723-4052-9a5f-d704fd01862f {http,https} \N \N {/s171-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+d5a00454-610d-4098-a872-15d2a01b85a8 2022-05-26 09:04:26+00 2022-05-26 09:04:26+00 \N 4d17db21-c723-4052-9a5f-d704fd01862f {http,https} \N \N {/s171-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+af223b5b-d885-4784-924b-8a4c97bb2b2a 2022-05-26 09:04:26+00 2022-05-26 09:04:26+00 \N 4d17db21-c723-4052-9a5f-d704fd01862f {http,https} \N \N {/s171-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+c0388b6e-65f0-412c-96ad-2b507eaf725e 2022-05-26 09:04:26+00 2022-05-26 09:04:26+00 \N 4d17db21-c723-4052-9a5f-d704fd01862f {http,https} \N \N {/s171-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+ff1879e3-337a-44ca-8f95-851aebf97a03 2022-05-26 09:04:26+00 2022-05-26 09:04:26+00 \N a9c1b4cf-9457-4010-a9b8-4f5236dcc5ce {http,https} \N \N {/s172-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+33dbfde5-d6b8-45c4-a42c-7eb99cfe74e5 2022-05-26 09:04:26+00 2022-05-26 09:04:26+00 \N a9c1b4cf-9457-4010-a9b8-4f5236dcc5ce {http,https} \N \N {/s172-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+30c0bec9-12fe-4055-9a90-29ad4855670d 2022-05-26 09:04:26+00 2022-05-26 09:04:26+00 \N a9c1b4cf-9457-4010-a9b8-4f5236dcc5ce {http,https} \N \N {/s172-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+37cb8256-042c-4890-ac10-3e8a255c9d48 2022-05-26 09:04:26+00 2022-05-26 09:04:26+00 \N a9c1b4cf-9457-4010-a9b8-4f5236dcc5ce {http,https} \N \N {/s172-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+7c07beaa-fa8f-4840-8b08-d11391de882a 2022-05-26 09:04:26+00 2022-05-26 09:04:26+00 \N e79cb133-66ba-406a-895d-559eddf73902 {http,https} \N \N {/s173-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+7c78deff-8eb1-4f60-b5e7-2bbabeca3fdc 2022-05-26 09:04:26+00 2022-05-26 09:04:26+00 \N e79cb133-66ba-406a-895d-559eddf73902 {http,https} \N \N {/s173-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+265650a8-af3a-4fcf-8c43-45d2c91e7fa8 2022-05-26 09:04:26+00 2022-05-26 09:04:26+00 \N e79cb133-66ba-406a-895d-559eddf73902 {http,https} \N \N {/s173-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+dc457997-7b4a-4959-a96d-2a73aa411470 2022-05-26 09:04:26+00 2022-05-26 09:04:26+00 \N e79cb133-66ba-406a-895d-559eddf73902 {http,https} \N \N {/s173-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+e7355947-c821-4cca-a485-e44c90ec50ab 2022-05-26 09:04:26+00 2022-05-26 09:04:26+00 \N 8b99e7b2-ccdf-4cb9-b185-e3cde9ec9af7 {http,https} \N \N {/s174-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+06f8adbc-0a97-429f-a3b8-ee9a9feddbc7 2022-05-26 09:04:26+00 2022-05-26 09:04:26+00 \N 8b99e7b2-ccdf-4cb9-b185-e3cde9ec9af7 {http,https} \N \N {/s174-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+b4d627bb-b68e-4a92-be3e-c3fe220cf533 2022-05-26 09:04:26+00 2022-05-26 09:04:26+00 \N 8b99e7b2-ccdf-4cb9-b185-e3cde9ec9af7 {http,https} \N \N {/s174-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+9cf4e435-0e53-4223-8c95-38ec63479fbd 2022-05-26 09:04:26+00 2022-05-26 09:04:26+00 \N 8b99e7b2-ccdf-4cb9-b185-e3cde9ec9af7 {http,https} \N \N {/s174-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+40948daf-3e7d-4adb-9aa1-83f20e11979c 2022-05-26 09:04:26+00 2022-05-26 09:04:26+00 \N d807dd5e-21de-4d30-823e-41d98b76bf8e {http,https} \N \N {/s175-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+c6cd578b-ad55-4f6e-b2fe-4ea1f40cfb21 2022-05-26 09:04:26+00 2022-05-26 09:04:26+00 \N d807dd5e-21de-4d30-823e-41d98b76bf8e {http,https} \N \N {/s175-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+cc34b095-cf47-4f04-8b42-fff44d04ab50 2022-05-26 09:04:26+00 2022-05-26 09:04:26+00 \N d807dd5e-21de-4d30-823e-41d98b76bf8e {http,https} \N \N {/s175-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+0642f66b-a15c-4c78-8937-1b035448c2e6 2022-05-26 09:04:26+00 2022-05-26 09:04:26+00 \N d807dd5e-21de-4d30-823e-41d98b76bf8e {http,https} \N \N {/s175-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+8c5829a6-6859-4831-bb61-b8ed82e74d1c 2022-05-26 09:04:26+00 2022-05-26 09:04:26+00 \N 00284c22-d742-4a15-9a67-4bb4dcd90d8f {http,https} \N \N {/s176-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+b4ca032f-79e6-4092-aab3-9382b2bf1052 2022-05-26 09:04:26+00 2022-05-26 09:04:26+00 \N 00284c22-d742-4a15-9a67-4bb4dcd90d8f {http,https} \N \N {/s176-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+b52bf36b-7703-47e3-ba86-03adf2ca98bd 2022-05-26 09:04:26+00 2022-05-26 09:04:26+00 \N 00284c22-d742-4a15-9a67-4bb4dcd90d8f {http,https} \N \N {/s176-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+0ea7b271-e1e4-46f7-955a-36f62ab6e960 2022-05-26 09:04:26+00 2022-05-26 09:04:26+00 \N 00284c22-d742-4a15-9a67-4bb4dcd90d8f {http,https} \N \N {/s176-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+1f26d35e-560f-49f9-b5e0-9ee0504e49b3 2022-05-26 09:04:26+00 2022-05-26 09:04:26+00 \N 751853be-1e25-490e-a6ef-9417a6b540ef {http,https} \N \N {/s177-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+657dc03f-22d6-4e30-9a53-a66246406012 2022-05-26 09:04:26+00 2022-05-26 09:04:26+00 \N 751853be-1e25-490e-a6ef-9417a6b540ef {http,https} \N \N {/s177-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+664d362d-e68d-48ac-ab93-79e806f3865c 2022-05-26 09:04:26+00 2022-05-26 09:04:26+00 \N 751853be-1e25-490e-a6ef-9417a6b540ef {http,https} \N \N {/s177-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+180ac050-1a3c-405e-880f-0be43d342e65 2022-05-26 09:04:26+00 2022-05-26 09:04:26+00 \N 751853be-1e25-490e-a6ef-9417a6b540ef {http,https} \N \N {/s177-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+f3bc4438-9c03-4bd3-a817-2faba58a55a3 2022-05-26 09:04:26+00 2022-05-26 09:04:26+00 \N f73bf090-0d18-40e8-b186-7fc9e91e62d1 {http,https} \N \N {/s178-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+abc7b6b5-d944-4ba7-aeb5-7fab62c8bdac 2022-05-26 09:04:26+00 2022-05-26 09:04:26+00 \N f73bf090-0d18-40e8-b186-7fc9e91e62d1 {http,https} \N \N {/s178-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+3ae8e4b9-adab-4512-80c8-4277c7eb37a3 2022-05-26 09:04:26+00 2022-05-26 09:04:26+00 \N f73bf090-0d18-40e8-b186-7fc9e91e62d1 {http,https} \N \N {/s178-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+2c55697c-20fc-48e9-b4db-3c462f62fb5f 2022-05-26 09:04:26+00 2022-05-26 09:04:26+00 \N f73bf090-0d18-40e8-b186-7fc9e91e62d1 {http,https} \N \N {/s178-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+91069e9f-1303-4a9d-aa2a-93db4d7f111f 2022-05-26 09:04:26+00 2022-05-26 09:04:26+00 \N 12042bab-a587-44e7-881d-2315a7305c39 {http,https} \N \N {/s179-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+281664fa-5496-474b-8fde-5f587ce458a8 2022-05-26 09:04:26+00 2022-05-26 09:04:26+00 \N 12042bab-a587-44e7-881d-2315a7305c39 {http,https} \N \N {/s179-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+3a29ce38-4b03-48b5-93b4-d2b06a9b5acc 2022-05-26 09:04:26+00 2022-05-26 09:04:26+00 \N 12042bab-a587-44e7-881d-2315a7305c39 {http,https} \N \N {/s179-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+8481ad3f-469b-4d1d-bf37-5072d3a3c24c 2022-05-26 09:04:26+00 2022-05-26 09:04:26+00 \N 12042bab-a587-44e7-881d-2315a7305c39 {http,https} \N \N {/s179-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+ea144262-7bb7-4796-a5bb-2f5072ec79ec 2022-05-26 09:04:26+00 2022-05-26 09:04:26+00 \N 9b0c19f6-6ab2-4119-8a6f-37e8f15cdd98 {http,https} \N \N {/s180-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+d80c53dc-5d1c-43da-b9bb-acc96d018c65 2022-05-26 09:04:26+00 2022-05-26 09:04:26+00 \N 9b0c19f6-6ab2-4119-8a6f-37e8f15cdd98 {http,https} \N \N {/s180-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+bea9c68b-aa00-4ead-9a62-c39d8b90271f 2022-05-26 09:04:26+00 2022-05-26 09:04:26+00 \N 9b0c19f6-6ab2-4119-8a6f-37e8f15cdd98 {http,https} \N \N {/s180-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+5a0df2fb-4699-4cd5-969d-0496de8dd583 2022-05-26 09:04:26+00 2022-05-26 09:04:26+00 \N 9b0c19f6-6ab2-4119-8a6f-37e8f15cdd98 {http,https} \N \N {/s180-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+cbdd7c1b-7934-4a48-a084-1b4e85f4e816 2022-05-26 09:04:26+00 2022-05-26 09:04:26+00 \N d76ebd2e-5ee7-4810-864b-3a12440faca9 {http,https} \N \N {/s181-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+c9a829cb-f1ea-4112-be04-bcdfc24331a9 2022-05-26 09:04:26+00 2022-05-26 09:04:26+00 \N d76ebd2e-5ee7-4810-864b-3a12440faca9 {http,https} \N \N {/s181-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+a5a86801-54b0-48b3-ba22-a417173689cf 2022-05-26 09:04:26+00 2022-05-26 09:04:26+00 \N d76ebd2e-5ee7-4810-864b-3a12440faca9 {http,https} \N \N {/s181-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+71f19cd6-ad7a-426d-bc0e-d77f624526ac 2022-05-26 09:04:26+00 2022-05-26 09:04:26+00 \N d76ebd2e-5ee7-4810-864b-3a12440faca9 {http,https} \N \N {/s181-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+32317f4f-f3a0-4809-8b51-24efb7379e43 2022-05-26 09:04:26+00 2022-05-26 09:04:26+00 \N bd3ca0d9-03ac-4021-8de2-08321ccb3277 {http,https} \N \N {/s182-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+a846c0e2-87a5-446d-8138-c11efa369837 2022-05-26 09:04:26+00 2022-05-26 09:04:26+00 \N bd3ca0d9-03ac-4021-8de2-08321ccb3277 {http,https} \N \N {/s182-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+a271e44d-c12d-49bb-971f-487597b32292 2022-05-26 09:04:26+00 2022-05-26 09:04:26+00 \N bd3ca0d9-03ac-4021-8de2-08321ccb3277 {http,https} \N \N {/s182-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+07ee9f76-3f50-4a4f-8b6e-871e8918ec9d 2022-05-26 09:04:26+00 2022-05-26 09:04:26+00 \N bd3ca0d9-03ac-4021-8de2-08321ccb3277 {http,https} \N \N {/s182-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+ff672f37-19fc-49ef-9a17-bce8296072f0 2022-05-26 09:04:26+00 2022-05-26 09:04:26+00 \N 528428e4-3f06-482d-8b4b-65b51c3bb653 {http,https} \N \N {/s183-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+b30a35ef-48a7-48da-9ce3-9fe6e79c7dbf 2022-05-26 09:04:26+00 2022-05-26 09:04:26+00 \N 528428e4-3f06-482d-8b4b-65b51c3bb653 {http,https} \N \N {/s183-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+9592dfea-488a-4db5-95f4-bfba492f7eaa 2022-05-26 09:04:26+00 2022-05-26 09:04:26+00 \N 528428e4-3f06-482d-8b4b-65b51c3bb653 {http,https} \N \N {/s183-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+d6da54cb-b86d-46b4-a37d-7d20671a5c68 2022-05-26 09:04:26+00 2022-05-26 09:04:26+00 \N 528428e4-3f06-482d-8b4b-65b51c3bb653 {http,https} \N \N {/s183-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+63879c78-1dfc-40f1-bc58-5c1528acec16 2022-05-26 09:04:26+00 2022-05-26 09:04:26+00 \N 73e663c8-0f96-4908-a02c-5c7eea81e327 {http,https} \N \N {/s184-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+94eb27f6-061d-45ab-949c-e2c4eee3f996 2022-05-26 09:04:26+00 2022-05-26 09:04:26+00 \N 73e663c8-0f96-4908-a02c-5c7eea81e327 {http,https} \N \N {/s184-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+7dcffda6-19ce-4db7-be50-9e5ffdd06661 2022-05-26 09:04:26+00 2022-05-26 09:04:26+00 \N 73e663c8-0f96-4908-a02c-5c7eea81e327 {http,https} \N \N {/s184-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+071657de-ef68-4006-9974-ce8a5744886f 2022-05-26 09:04:26+00 2022-05-26 09:04:26+00 \N 73e663c8-0f96-4908-a02c-5c7eea81e327 {http,https} \N \N {/s184-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+84d47d85-6298-4b1d-ab66-b732ab72c59d 2022-05-26 09:04:26+00 2022-05-26 09:04:26+00 \N 2c40d9e2-469a-4c7a-9bcf-61552994e02e {http,https} \N \N {/s185-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+011ae483-0c29-42b3-915c-b8b422ce71b4 2022-05-26 09:04:26+00 2022-05-26 09:04:26+00 \N 2c40d9e2-469a-4c7a-9bcf-61552994e02e {http,https} \N \N {/s185-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+19c28169-42fa-4251-9828-7ce4d4b90f80 2022-05-26 09:04:26+00 2022-05-26 09:04:26+00 \N 2c40d9e2-469a-4c7a-9bcf-61552994e02e {http,https} \N \N {/s185-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+94fafc99-fd1b-4bfc-899f-2333c776da12 2022-05-26 09:04:26+00 2022-05-26 09:04:26+00 \N 2c40d9e2-469a-4c7a-9bcf-61552994e02e {http,https} \N \N {/s185-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+f4a6e100-d1ff-4c04-b2f7-948703eadc4a 2022-05-26 09:04:26+00 2022-05-26 09:04:26+00 \N 3e2fe25a-fc33-4a1e-a1f1-a60ac070e341 {http,https} \N \N {/s186-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+1ccd126a-5a5d-4597-9c5c-16c5f1699781 2022-05-26 09:04:26+00 2022-05-26 09:04:26+00 \N 3e2fe25a-fc33-4a1e-a1f1-a60ac070e341 {http,https} \N \N {/s186-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+7737eda7-b57b-40f9-8026-001a216ea04e 2022-05-26 09:04:26+00 2022-05-26 09:04:26+00 \N 3e2fe25a-fc33-4a1e-a1f1-a60ac070e341 {http,https} \N \N {/s186-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+85ba2b4b-f82b-4ac1-b91c-38b4ebe28d71 2022-05-26 09:04:26+00 2022-05-26 09:04:26+00 \N 3e2fe25a-fc33-4a1e-a1f1-a60ac070e341 {http,https} \N \N {/s186-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+2c8f7fe9-7eff-40e1-a8a3-3fa14bcf8d53 2022-05-26 09:04:26+00 2022-05-26 09:04:26+00 \N a344e177-1f6e-4753-8404-a3fbd716a992 {http,https} \N \N {/s187-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+7e4a7d82-b633-40dd-92b3-41d66e40fea1 2022-05-26 09:04:26+00 2022-05-26 09:04:26+00 \N a344e177-1f6e-4753-8404-a3fbd716a992 {http,https} \N \N {/s187-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+bca31da5-6c38-485a-a87d-37e374a26c9a 2022-05-26 09:04:26+00 2022-05-26 09:04:26+00 \N a344e177-1f6e-4753-8404-a3fbd716a992 {http,https} \N \N {/s187-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+587a1fad-4cff-4059-8212-56014add501a 2022-05-26 09:04:26+00 2022-05-26 09:04:26+00 \N a344e177-1f6e-4753-8404-a3fbd716a992 {http,https} \N \N {/s187-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+ddcbfca7-d79e-463a-8fe5-2d6c25e0bdc6 2022-05-26 09:04:26+00 2022-05-26 09:04:26+00 \N ababbb85-337f-4aba-9922-41daf23c2865 {http,https} \N \N {/s188-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+c228af42-ba0d-4f22-a07b-e4a8319754fa 2022-05-26 09:04:26+00 2022-05-26 09:04:26+00 \N ababbb85-337f-4aba-9922-41daf23c2865 {http,https} \N \N {/s188-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+ff9eca3c-c9ea-4876-a3b4-44d810c831b3 2022-05-26 09:04:26+00 2022-05-26 09:04:26+00 \N ababbb85-337f-4aba-9922-41daf23c2865 {http,https} \N \N {/s188-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+56438a1c-a5a9-444b-ba64-119dac6590b3 2022-05-26 09:04:26+00 2022-05-26 09:04:26+00 \N ababbb85-337f-4aba-9922-41daf23c2865 {http,https} \N \N {/s188-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+265035f5-2008-491e-9063-14b21b7fd598 2022-05-26 09:04:26+00 2022-05-26 09:04:26+00 \N 1b075615-d2ce-4b5c-997d-729c664dc4f4 {http,https} \N \N {/s189-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+b1f60ac9-cd3b-4008-8cd8-0b301fefaf14 2022-05-26 09:04:26+00 2022-05-26 09:04:26+00 \N 1b075615-d2ce-4b5c-997d-729c664dc4f4 {http,https} \N \N {/s189-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+ed245d94-3876-46e7-998d-347a6325b963 2022-05-26 09:04:26+00 2022-05-26 09:04:26+00 \N 1b075615-d2ce-4b5c-997d-729c664dc4f4 {http,https} \N \N {/s189-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+9e32fcb8-5877-458e-8f61-c375f7195da1 2022-05-26 09:04:26+00 2022-05-26 09:04:26+00 \N 1b075615-d2ce-4b5c-997d-729c664dc4f4 {http,https} \N \N {/s189-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+a9a189b0-ae27-4917-9492-011195b606d0 2022-05-26 09:04:26+00 2022-05-26 09:04:26+00 \N fe3e3c81-0f6c-4f7b-82d7-06022c1613b6 {http,https} \N \N {/s190-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+06f8930d-390b-4688-b733-eec262c2143b 2022-05-26 09:04:26+00 2022-05-26 09:04:26+00 \N fe3e3c81-0f6c-4f7b-82d7-06022c1613b6 {http,https} \N \N {/s190-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+f7559e30-e6a1-4220-97e1-0d3e4d70edb7 2022-05-26 09:04:26+00 2022-05-26 09:04:26+00 \N fe3e3c81-0f6c-4f7b-82d7-06022c1613b6 {http,https} \N \N {/s190-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+af56a77a-2cfd-4b6a-80dc-cbe9761fa839 2022-05-26 09:04:26+00 2022-05-26 09:04:26+00 \N fe3e3c81-0f6c-4f7b-82d7-06022c1613b6 {http,https} \N \N {/s190-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+bf5f5fc9-2078-4b72-9a43-d8878340d3e5 2022-05-26 09:04:26+00 2022-05-26 09:04:26+00 \N 54d95a23-896b-40b4-b93a-dfe4b4083a23 {http,https} \N \N {/s191-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+29cff1a4-2725-40cb-98d1-cc0802bf63eb 2022-05-26 09:04:26+00 2022-05-26 09:04:26+00 \N 54d95a23-896b-40b4-b93a-dfe4b4083a23 {http,https} \N \N {/s191-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+a87bba57-0a9f-41cb-955d-e74ef7f882c5 2022-05-26 09:04:26+00 2022-05-26 09:04:26+00 \N 54d95a23-896b-40b4-b93a-dfe4b4083a23 {http,https} \N \N {/s191-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+3283a9a8-c19d-4950-9f72-9cd852a13f46 2022-05-26 09:04:26+00 2022-05-26 09:04:26+00 \N 54d95a23-896b-40b4-b93a-dfe4b4083a23 {http,https} \N \N {/s191-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+7fbb876e-75ec-4c0d-af98-c70ce26b513e 2022-05-26 09:04:26+00 2022-05-26 09:04:26+00 \N 92af388d-d0f3-41a9-ad5f-ed90b03de869 {http,https} \N \N {/s192-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+759463d0-28af-4458-bea0-b04db67add1a 2022-05-26 09:04:26+00 2022-05-26 09:04:26+00 \N 92af388d-d0f3-41a9-ad5f-ed90b03de869 {http,https} \N \N {/s192-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+bbf3f83e-b4d4-4ad2-822b-88e8f0748df8 2022-05-26 09:04:26+00 2022-05-26 09:04:26+00 \N 92af388d-d0f3-41a9-ad5f-ed90b03de869 {http,https} \N \N {/s192-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+71c67e7c-51b8-45d7-85a9-dbf8e9bc0a45 2022-05-26 09:04:26+00 2022-05-26 09:04:26+00 \N 92af388d-d0f3-41a9-ad5f-ed90b03de869 {http,https} \N \N {/s192-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+53d373d4-2629-4241-a039-d1fdd751ab28 2022-05-26 09:04:26+00 2022-05-26 09:04:26+00 \N 5a61733d-2684-4d4a-9d35-bf785b7c07c2 {http,https} \N \N {/s193-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+a8831701-cbd8-416f-93bc-287126315593 2022-05-26 09:04:26+00 2022-05-26 09:04:26+00 \N 5a61733d-2684-4d4a-9d35-bf785b7c07c2 {http,https} \N \N {/s193-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+44bfe0fd-07eb-4585-949c-e226c244e9d5 2022-05-26 09:04:26+00 2022-05-26 09:04:26+00 \N 5a61733d-2684-4d4a-9d35-bf785b7c07c2 {http,https} \N \N {/s193-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+46a2ea6f-6729-4318-8816-8f65e25a3cd2 2022-05-26 09:04:26+00 2022-05-26 09:04:26+00 \N 5a61733d-2684-4d4a-9d35-bf785b7c07c2 {http,https} \N \N {/s193-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+8842606e-ccfc-4331-bff9-0d59d34ee387 2022-05-26 09:04:26+00 2022-05-26 09:04:26+00 \N ece058ba-4c37-48de-a640-d7b889c4fb6c {http,https} \N \N {/s194-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+e3ac1e1e-1407-4df7-8436-18402735747d 2022-05-26 09:04:26+00 2022-05-26 09:04:26+00 \N ece058ba-4c37-48de-a640-d7b889c4fb6c {http,https} \N \N {/s194-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+94a377f9-7bd0-4634-b305-63b7e88f9ca5 2022-05-26 09:04:26+00 2022-05-26 09:04:26+00 \N ece058ba-4c37-48de-a640-d7b889c4fb6c {http,https} \N \N {/s194-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+bb9b5ed3-d6c3-4cdb-9e5a-f28032574224 2022-05-26 09:04:27+00 2022-05-26 09:04:27+00 \N ece058ba-4c37-48de-a640-d7b889c4fb6c {http,https} \N \N {/s194-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+788fc63b-5d13-41ca-8f13-87282675b88b 2022-05-26 09:04:27+00 2022-05-26 09:04:27+00 \N c2c49d74-23c3-4ce3-a9e5-f0ede3967097 {http,https} \N \N {/s195-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+784e0624-6b13-4699-a26d-96cddfe8851c 2022-05-26 09:04:27+00 2022-05-26 09:04:27+00 \N c2c49d74-23c3-4ce3-a9e5-f0ede3967097 {http,https} \N \N {/s195-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+209e20f0-4ea4-48f0-b275-80d6e3d88483 2022-05-26 09:04:27+00 2022-05-26 09:04:27+00 \N c2c49d74-23c3-4ce3-a9e5-f0ede3967097 {http,https} \N \N {/s195-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+a37f4e35-cac6-49d3-a0a2-c2b58f77278d 2022-05-26 09:04:27+00 2022-05-26 09:04:27+00 \N c2c49d74-23c3-4ce3-a9e5-f0ede3967097 {http,https} \N \N {/s195-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+27c7886f-0847-4165-bbdd-601871847f68 2022-05-26 09:04:27+00 2022-05-26 09:04:27+00 \N fbdc551b-4550-4528-a74d-a595aa492b51 {http,https} \N \N {/s196-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+de454194-9c07-4879-a465-3e194fcf4341 2022-05-26 09:04:27+00 2022-05-26 09:04:27+00 \N fbdc551b-4550-4528-a74d-a595aa492b51 {http,https} \N \N {/s196-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+252a3a99-c46f-4875-904e-dd82aca1777e 2022-05-26 09:04:27+00 2022-05-26 09:04:27+00 \N fbdc551b-4550-4528-a74d-a595aa492b51 {http,https} \N \N {/s196-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+6d96919d-8d0e-405a-b1a2-c3d02b4b56aa 2022-05-26 09:04:27+00 2022-05-26 09:04:27+00 \N fbdc551b-4550-4528-a74d-a595aa492b51 {http,https} \N \N {/s196-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+8fb42864-5606-43c9-b041-0273ea529965 2022-05-26 09:04:27+00 2022-05-26 09:04:27+00 \N 92c2bcd2-bb73-4339-aaf1-8b552ceb0106 {http,https} \N \N {/s197-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+7ff05871-59c1-46a4-8595-84f2bb305465 2022-05-26 09:04:27+00 2022-05-26 09:04:27+00 \N 92c2bcd2-bb73-4339-aaf1-8b552ceb0106 {http,https} \N \N {/s197-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+1884b6a1-611a-42e3-9fbe-eea1b8ca4fe4 2022-05-26 09:04:27+00 2022-05-26 09:04:27+00 \N 92c2bcd2-bb73-4339-aaf1-8b552ceb0106 {http,https} \N \N {/s197-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+9f15af83-4089-4944-bc15-a18687e442d5 2022-05-26 09:04:27+00 2022-05-26 09:04:27+00 \N 92c2bcd2-bb73-4339-aaf1-8b552ceb0106 {http,https} \N \N {/s197-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+e0788586-00b1-490b-8b44-736e8db27981 2022-05-26 09:04:27+00 2022-05-26 09:04:27+00 \N c60849dc-5675-492f-8bab-5d8cb3626823 {http,https} \N \N {/s198-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+8a198fe7-4cd4-4546-83f2-2b4e1e2e6ca2 2022-05-26 09:04:27+00 2022-05-26 09:04:27+00 \N c60849dc-5675-492f-8bab-5d8cb3626823 {http,https} \N \N {/s198-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+29cdcb0e-dd9c-40a5-8b57-e198c5a98f39 2022-05-26 09:04:27+00 2022-05-26 09:04:27+00 \N c60849dc-5675-492f-8bab-5d8cb3626823 {http,https} \N \N {/s198-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+9247fff8-ca66-434f-a300-e4e7db0f47c1 2022-05-26 09:04:27+00 2022-05-26 09:04:27+00 \N c60849dc-5675-492f-8bab-5d8cb3626823 {http,https} \N \N {/s198-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+8941a60b-adeb-418d-87cb-e25d2bde5da1 2022-05-26 09:04:27+00 2022-05-26 09:04:27+00 \N 1d6aa622-24ef-4888-a080-ba20e5c89316 {http,https} \N \N {/s199-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+3e8c7fc4-3828-499e-84c6-585279a856d8 2022-05-26 09:04:27+00 2022-05-26 09:04:27+00 \N 1d6aa622-24ef-4888-a080-ba20e5c89316 {http,https} \N \N {/s199-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+c4b9bb24-57dd-4609-b6e7-3bbf84573a6c 2022-05-26 09:04:27+00 2022-05-26 09:04:27+00 \N 1d6aa622-24ef-4888-a080-ba20e5c89316 {http,https} \N \N {/s199-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+81b2991f-886a-49ef-acb6-2e18ff7b836f 2022-05-26 09:04:27+00 2022-05-26 09:04:27+00 \N 1d6aa622-24ef-4888-a080-ba20e5c89316 {http,https} \N \N {/s199-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+c410bd56-3558-45bb-9421-c80bc680bc18 2022-05-26 09:04:27+00 2022-05-26 09:04:27+00 \N 204833b7-0070-4b55-9583-1df64dc7ab2a {http,https} \N \N {/s200-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+04f736a8-d0cf-4f12-959e-8051346306a6 2022-05-26 09:04:27+00 2022-05-26 09:04:27+00 \N 204833b7-0070-4b55-9583-1df64dc7ab2a {http,https} \N \N {/s200-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+355ab472-684c-4dad-a464-14d223d5cf9a 2022-05-26 09:04:27+00 2022-05-26 09:04:27+00 \N 204833b7-0070-4b55-9583-1df64dc7ab2a {http,https} \N \N {/s200-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+71b18877-0e77-46e1-831f-4145d44cce18 2022-05-26 09:04:27+00 2022-05-26 09:04:27+00 \N 204833b7-0070-4b55-9583-1df64dc7ab2a {http,https} \N \N {/s200-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+508d3ec2-4700-4bc2-8e30-cf5b9989b37d 2022-05-26 09:04:27+00 2022-05-26 09:04:27+00 \N 2cebb659-d522-4e02-9ba6-90e09ced208c {http,https} \N \N {/s201-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+b9db9172-8b7e-481c-91c5-2bba6b5592a5 2022-05-26 09:04:27+00 2022-05-26 09:04:27+00 \N 2cebb659-d522-4e02-9ba6-90e09ced208c {http,https} \N \N {/s201-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+34bbdbd6-2558-4ba5-9cf6-1c43f7347358 2022-05-26 09:04:27+00 2022-05-26 09:04:27+00 \N 2cebb659-d522-4e02-9ba6-90e09ced208c {http,https} \N \N {/s201-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+bf0b9b7b-d3dc-421d-aae1-ea3bc0e4f4b2 2022-05-26 09:04:27+00 2022-05-26 09:04:27+00 \N 2cebb659-d522-4e02-9ba6-90e09ced208c {http,https} \N \N {/s201-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+221c3634-abac-4c45-92e3-9cc676ab4485 2022-05-26 09:04:27+00 2022-05-26 09:04:27+00 \N 8fd65cbb-d37c-45ad-95ba-f5bb0acf87e0 {http,https} \N \N {/s202-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+f18721a4-6297-4f5e-841f-69e90f94bbf1 2022-05-26 09:04:27+00 2022-05-26 09:04:27+00 \N 8fd65cbb-d37c-45ad-95ba-f5bb0acf87e0 {http,https} \N \N {/s202-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+2e66ed55-4275-401e-94b3-f9d0a4e0ed0d 2022-05-26 09:04:27+00 2022-05-26 09:04:27+00 \N 8fd65cbb-d37c-45ad-95ba-f5bb0acf87e0 {http,https} \N \N {/s202-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+df1ac559-4d7d-473e-beac-eb48e6672278 2022-05-26 09:04:27+00 2022-05-26 09:04:27+00 \N 8fd65cbb-d37c-45ad-95ba-f5bb0acf87e0 {http,https} \N \N {/s202-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+2b4fec1a-e43b-4ef7-bbfc-ae8c7bf57f67 2022-05-26 09:04:27+00 2022-05-26 09:04:27+00 \N 310fe133-a807-45dc-9dd1-6a6b1fe1d07d {http,https} \N \N {/s203-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+e434321d-4292-4f93-b34c-0f4a65322831 2022-05-26 09:04:27+00 2022-05-26 09:04:27+00 \N 310fe133-a807-45dc-9dd1-6a6b1fe1d07d {http,https} \N \N {/s203-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+eee19ea7-e3d3-4785-99a7-e59599e9a72a 2022-05-26 09:04:27+00 2022-05-26 09:04:27+00 \N 310fe133-a807-45dc-9dd1-6a6b1fe1d07d {http,https} \N \N {/s203-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+b0b4320f-15f5-4837-bf08-fdb852b5335c 2022-05-26 09:04:27+00 2022-05-26 09:04:27+00 \N 310fe133-a807-45dc-9dd1-6a6b1fe1d07d {http,https} \N \N {/s203-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+198a559c-3922-4174-9f67-0cbcfced40a6 2022-05-26 09:04:27+00 2022-05-26 09:04:27+00 \N f7df66fb-1d8f-46dc-b569-de1b63a0344b {http,https} \N \N {/s204-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+d0b5c8f1-bb54-466c-bf6e-3862cdb19dfb 2022-05-26 09:04:27+00 2022-05-26 09:04:27+00 \N f7df66fb-1d8f-46dc-b569-de1b63a0344b {http,https} \N \N {/s204-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+419939ca-5f75-4831-b957-74321322646a 2022-05-26 09:04:27+00 2022-05-26 09:04:27+00 \N f7df66fb-1d8f-46dc-b569-de1b63a0344b {http,https} \N \N {/s204-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+7611e12a-366a-42d6-9616-4c067bf76546 2022-05-26 09:04:27+00 2022-05-26 09:04:27+00 \N f7df66fb-1d8f-46dc-b569-de1b63a0344b {http,https} \N \N {/s204-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+fa1818d1-d11d-467d-88f0-b2824668b25c 2022-05-26 09:04:27+00 2022-05-26 09:04:27+00 \N b75d1f70-93f2-4de0-9bb4-7a1fae40e29b {http,https} \N \N {/s205-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+0532bb48-00cf-41a9-b651-5e10eb087bfc 2022-05-26 09:04:27+00 2022-05-26 09:04:27+00 \N b75d1f70-93f2-4de0-9bb4-7a1fae40e29b {http,https} \N \N {/s205-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+5120d4f7-8e38-4a65-9ef3-6f9492483e14 2022-05-26 09:04:27+00 2022-05-26 09:04:27+00 \N b75d1f70-93f2-4de0-9bb4-7a1fae40e29b {http,https} \N \N {/s205-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+d328af8a-b84f-4a6e-b35b-63a2e9b8dee5 2022-05-26 09:04:27+00 2022-05-26 09:04:27+00 \N b75d1f70-93f2-4de0-9bb4-7a1fae40e29b {http,https} \N \N {/s205-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+5248f2f3-878b-482a-9626-670f56b6417e 2022-05-26 09:04:27+00 2022-05-26 09:04:27+00 \N cde580a3-81d5-4cef-9858-f99a1f629422 {http,https} \N \N {/s206-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+c237d2b2-8d0a-4f76-a6e0-0bc79d1eb7f6 2022-05-26 09:04:27+00 2022-05-26 09:04:27+00 \N cde580a3-81d5-4cef-9858-f99a1f629422 {http,https} \N \N {/s206-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+9451c770-3558-4e7c-a73a-42fda3b13dbe 2022-05-26 09:04:27+00 2022-05-26 09:04:27+00 \N cde580a3-81d5-4cef-9858-f99a1f629422 {http,https} \N \N {/s206-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+01b6ecaa-932d-4b76-bd6b-d33ee791221e 2022-05-26 09:04:27+00 2022-05-26 09:04:27+00 \N cde580a3-81d5-4cef-9858-f99a1f629422 {http,https} \N \N {/s206-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+227f7690-1b6f-48ed-9ba0-8de2210cf564 2022-05-26 09:04:27+00 2022-05-26 09:04:27+00 \N ebc496df-a1c7-4046-bf99-45778c2de1c6 {http,https} \N \N {/s207-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+5e941f0c-f542-4aea-b2dc-9d793f6a0080 2022-05-26 09:04:27+00 2022-05-26 09:04:27+00 \N ebc496df-a1c7-4046-bf99-45778c2de1c6 {http,https} \N \N {/s207-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+af6e9d14-8189-4b98-88a6-03c57eab6be4 2022-05-26 09:04:27+00 2022-05-26 09:04:27+00 \N ebc496df-a1c7-4046-bf99-45778c2de1c6 {http,https} \N \N {/s207-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+c156047f-6a96-4e2c-ba7f-0fa8b892c5be 2022-05-26 09:04:27+00 2022-05-26 09:04:27+00 \N ebc496df-a1c7-4046-bf99-45778c2de1c6 {http,https} \N \N {/s207-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+03b3939d-8f6e-4df2-93d4-5c6944ffab39 2022-05-26 09:04:27+00 2022-05-26 09:04:27+00 \N 2a2d78fd-a19a-4a2c-80c1-816deb18c823 {http,https} \N \N {/s208-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+1cb4051d-77e3-4292-babb-d994125c4f27 2022-05-26 09:04:27+00 2022-05-26 09:04:27+00 \N 2a2d78fd-a19a-4a2c-80c1-816deb18c823 {http,https} \N \N {/s208-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+8c41b214-4ff1-4a2c-8729-9443b477ea14 2022-05-26 09:04:27+00 2022-05-26 09:04:27+00 \N 2a2d78fd-a19a-4a2c-80c1-816deb18c823 {http,https} \N \N {/s208-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+9baf5a7d-d09e-4f9a-b03c-aba6c414f36e 2022-05-26 09:04:27+00 2022-05-26 09:04:27+00 \N 2a2d78fd-a19a-4a2c-80c1-816deb18c823 {http,https} \N \N {/s208-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+02ef066e-e9c3-4693-9b6c-5b877fee6859 2022-05-26 09:04:27+00 2022-05-26 09:04:27+00 \N 88c9d8c2-1bfd-4b33-81c7-7d77866b2d7e {http,https} \N \N {/s209-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+045c6995-14d4-490c-9532-63b01ada6787 2022-05-26 09:04:27+00 2022-05-26 09:04:27+00 \N 88c9d8c2-1bfd-4b33-81c7-7d77866b2d7e {http,https} \N \N {/s209-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+2f204c88-b044-44f6-bf6b-4e486b5ad64d 2022-05-26 09:04:27+00 2022-05-26 09:04:27+00 \N 88c9d8c2-1bfd-4b33-81c7-7d77866b2d7e {http,https} \N \N {/s209-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+99d40389-5494-417b-95df-71b26c369402 2022-05-26 09:04:27+00 2022-05-26 09:04:27+00 \N 88c9d8c2-1bfd-4b33-81c7-7d77866b2d7e {http,https} \N \N {/s209-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+56477f27-4d1c-4ea8-87b3-d34a1a408239 2022-05-26 09:04:27+00 2022-05-26 09:04:27+00 \N 0eb52ec4-f6fc-4c6d-ac31-e07b84f7e17e {http,https} \N \N {/s210-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+60a83f05-8969-4ddd-959f-ba125750c7d8 2022-05-26 09:04:27+00 2022-05-26 09:04:27+00 \N 0eb52ec4-f6fc-4c6d-ac31-e07b84f7e17e {http,https} \N \N {/s210-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+0c3a00ab-5c5a-4091-b7f8-747d119fdbfa 2022-05-26 09:04:27+00 2022-05-26 09:04:27+00 \N 0eb52ec4-f6fc-4c6d-ac31-e07b84f7e17e {http,https} \N \N {/s210-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+138df44c-a087-49fc-ac27-30dec071a3a5 2022-05-26 09:04:27+00 2022-05-26 09:04:27+00 \N 0eb52ec4-f6fc-4c6d-ac31-e07b84f7e17e {http,https} \N \N {/s210-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+9a9405b4-8b56-4562-a669-efdaa3131af8 2022-05-26 09:04:27+00 2022-05-26 09:04:27+00 \N 1c255589-3ec2-42b8-b722-32c1f9ad2510 {http,https} \N \N {/s211-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+e3dbee91-2b1e-4732-ba78-a6721f1e80d5 2022-05-26 09:04:27+00 2022-05-26 09:04:27+00 \N 1c255589-3ec2-42b8-b722-32c1f9ad2510 {http,https} \N \N {/s211-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+afe847ed-9bf3-4dc9-8afa-7a65c51a26af 2022-05-26 09:04:27+00 2022-05-26 09:04:27+00 \N 1c255589-3ec2-42b8-b722-32c1f9ad2510 {http,https} \N \N {/s211-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+5c10847d-e99a-4683-b950-92c6adb1dee4 2022-05-26 09:04:27+00 2022-05-26 09:04:27+00 \N 1c255589-3ec2-42b8-b722-32c1f9ad2510 {http,https} \N \N {/s211-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+f8d705dc-146b-42aa-9e42-e391a7a7c1b9 2022-05-26 09:04:27+00 2022-05-26 09:04:27+00 \N b5af350e-6e66-40e4-8333-e0595f756e83 {http,https} \N \N {/s212-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+4eacd6c5-8fbc-4a2e-9fe3-bc0bee4517ee 2022-05-26 09:04:27+00 2022-05-26 09:04:27+00 \N b5af350e-6e66-40e4-8333-e0595f756e83 {http,https} \N \N {/s212-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+c99a2b48-2556-4179-8acd-06f427d86e43 2022-05-26 09:04:27+00 2022-05-26 09:04:27+00 \N b5af350e-6e66-40e4-8333-e0595f756e83 {http,https} \N \N {/s212-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+f45c9e1c-abad-4f81-910d-69ccfc347d0e 2022-05-26 09:04:27+00 2022-05-26 09:04:27+00 \N b5af350e-6e66-40e4-8333-e0595f756e83 {http,https} \N \N {/s212-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+04626a0e-3830-4297-a445-7da2ac7bae9c 2022-05-26 09:04:27+00 2022-05-26 09:04:27+00 \N 607a67a8-1ab1-4c96-869d-71ffc14a90cb {http,https} \N \N {/s213-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+a82dbd91-76dd-471b-b6e1-9ba77984d481 2022-05-26 09:04:27+00 2022-05-26 09:04:27+00 \N 607a67a8-1ab1-4c96-869d-71ffc14a90cb {http,https} \N \N {/s213-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+dd52ccb1-ffee-4d4f-8794-ddd1c9b04c0e 2022-05-26 09:04:27+00 2022-05-26 09:04:27+00 \N 607a67a8-1ab1-4c96-869d-71ffc14a90cb {http,https} \N \N {/s213-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+d59bec56-631e-4870-9053-b9aa1a8c3b16 2022-05-26 09:04:27+00 2022-05-26 09:04:27+00 \N 607a67a8-1ab1-4c96-869d-71ffc14a90cb {http,https} \N \N {/s213-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+0f5a7ee7-75c6-4055-a7c8-ea70e80ee487 2022-05-26 09:04:27+00 2022-05-26 09:04:27+00 \N 97657a2e-8286-4638-b42b-d8f1418f68f3 {http,https} \N \N {/s214-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+8ffd06db-9ca7-4071-b267-4c6ca1f217f2 2022-05-26 09:04:27+00 2022-05-26 09:04:27+00 \N 97657a2e-8286-4638-b42b-d8f1418f68f3 {http,https} \N \N {/s214-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+33f9f90b-363e-433e-b018-74a09ff8821b 2022-05-26 09:04:27+00 2022-05-26 09:04:27+00 \N 97657a2e-8286-4638-b42b-d8f1418f68f3 {http,https} \N \N {/s214-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+948637b6-f3ba-4e1e-a3b4-7c9023a99eb2 2022-05-26 09:04:27+00 2022-05-26 09:04:27+00 \N 97657a2e-8286-4638-b42b-d8f1418f68f3 {http,https} \N \N {/s214-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+24d84b7d-c0ac-4043-9ba5-fe93f73fb4b3 2022-05-26 09:04:27+00 2022-05-26 09:04:27+00 \N 8ebbdaa1-2ede-459c-8f20-9eaf6c4c5e34 {http,https} \N \N {/s215-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+fa315997-a402-42bb-8bc8-a015c33a4ebc 2022-05-26 09:04:27+00 2022-05-26 09:04:27+00 \N 8ebbdaa1-2ede-459c-8f20-9eaf6c4c5e34 {http,https} \N \N {/s215-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+a71db8e6-7adc-4672-9fa4-8c663e9ae8d5 2022-05-26 09:04:27+00 2022-05-26 09:04:27+00 \N 8ebbdaa1-2ede-459c-8f20-9eaf6c4c5e34 {http,https} \N \N {/s215-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+07fa01fd-7fda-4e48-a74e-857515e2bb0a 2022-05-26 09:04:27+00 2022-05-26 09:04:27+00 \N 8ebbdaa1-2ede-459c-8f20-9eaf6c4c5e34 {http,https} \N \N {/s215-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+859bbe89-f301-40a6-b751-af71121364c9 2022-05-26 09:04:27+00 2022-05-26 09:04:27+00 \N dc47a6ab-1456-4e60-95d2-50b7251072be {http,https} \N \N {/s216-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+356a976d-9ca3-4dbf-b0b0-e87fb26df24d 2022-05-26 09:04:27+00 2022-05-26 09:04:27+00 \N dc47a6ab-1456-4e60-95d2-50b7251072be {http,https} \N \N {/s216-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+64839bb8-fcd2-4105-aa56-d779f4e37544 2022-05-26 09:04:27+00 2022-05-26 09:04:27+00 \N dc47a6ab-1456-4e60-95d2-50b7251072be {http,https} \N \N {/s216-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+de160398-b693-49e3-8b9b-85112666f1b9 2022-05-26 09:04:27+00 2022-05-26 09:04:27+00 \N dc47a6ab-1456-4e60-95d2-50b7251072be {http,https} \N \N {/s216-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+19ce1881-c412-4267-921a-d2cc78f8e695 2022-05-26 09:04:27+00 2022-05-26 09:04:27+00 \N 17157627-0993-4a53-ac67-5dc31565a022 {http,https} \N \N {/s217-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+cd8596e2-38e3-4c93-95e2-76d31e2a995e 2022-05-26 09:04:27+00 2022-05-26 09:04:27+00 \N 17157627-0993-4a53-ac67-5dc31565a022 {http,https} \N \N {/s217-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+886c5da0-c197-4b27-bc70-74f3b0aa087e 2022-05-26 09:04:27+00 2022-05-26 09:04:27+00 \N 17157627-0993-4a53-ac67-5dc31565a022 {http,https} \N \N {/s217-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+620f3ede-bbc9-4123-ae29-132e9f45708b 2022-05-26 09:04:27+00 2022-05-26 09:04:27+00 \N 17157627-0993-4a53-ac67-5dc31565a022 {http,https} \N \N {/s217-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+c97c962e-854c-480b-8f91-9d8d00240165 2022-05-26 09:04:27+00 2022-05-26 09:04:27+00 \N 8456d2fa-f8ee-44c4-b062-376c225c6ad9 {http,https} \N \N {/s218-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+fba47ef2-1fc3-4519-a0e5-1ac9ada2ccae 2022-05-26 09:04:27+00 2022-05-26 09:04:27+00 \N 8456d2fa-f8ee-44c4-b062-376c225c6ad9 {http,https} \N \N {/s218-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+c9a8fa17-af14-4a3d-968b-eb1280b461f5 2022-05-26 09:04:27+00 2022-05-26 09:04:27+00 \N 8456d2fa-f8ee-44c4-b062-376c225c6ad9 {http,https} \N \N {/s218-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+a49368a3-9a05-4ded-9cc5-7c609d3581e7 2022-05-26 09:04:27+00 2022-05-26 09:04:27+00 \N 8456d2fa-f8ee-44c4-b062-376c225c6ad9 {http,https} \N \N {/s218-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+035bc257-8cb8-4883-9e3f-0e675ddd6f15 2022-05-26 09:04:27+00 2022-05-26 09:04:27+00 \N 289e1e86-7c79-4686-910d-91d138398782 {http,https} \N \N {/s219-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+ee288452-127e-4b81-8235-f459a73ad52d 2022-05-26 09:04:27+00 2022-05-26 09:04:27+00 \N 289e1e86-7c79-4686-910d-91d138398782 {http,https} \N \N {/s219-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+3d1b9b5c-855f-439b-b1e5-39879b7f1109 2022-05-26 09:04:27+00 2022-05-26 09:04:27+00 \N 289e1e86-7c79-4686-910d-91d138398782 {http,https} \N \N {/s219-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+2f2d98f5-9841-46e9-a1e9-9de85a177404 2022-05-26 09:04:27+00 2022-05-26 09:04:27+00 \N 289e1e86-7c79-4686-910d-91d138398782 {http,https} \N \N {/s219-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+45b52dc9-6a5b-419f-9aa4-c9799954814c 2022-05-26 09:04:27+00 2022-05-26 09:04:27+00 \N ef250969-68ff-4fc9-a9f9-46f776374937 {http,https} \N \N {/s220-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+d33e0b54-65db-4f26-9287-df3b8f6b25cb 2022-05-26 09:04:27+00 2022-05-26 09:04:27+00 \N ef250969-68ff-4fc9-a9f9-46f776374937 {http,https} \N \N {/s220-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+22192499-69e4-4fec-b815-19d0a1794f55 2022-05-26 09:04:27+00 2022-05-26 09:04:27+00 \N ef250969-68ff-4fc9-a9f9-46f776374937 {http,https} \N \N {/s220-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+b72fc0df-17ac-4c2d-a6ad-849b01b1aa12 2022-05-26 09:04:27+00 2022-05-26 09:04:27+00 \N ef250969-68ff-4fc9-a9f9-46f776374937 {http,https} \N \N {/s220-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+cb513101-6911-4457-a34a-a11810450c3b 2022-05-26 09:04:27+00 2022-05-26 09:04:27+00 \N f75fa431-1d5b-4a84-adc9-f2ab778755f2 {http,https} \N \N {/s221-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+e76689cf-cd5d-4c76-9a6f-ff0e6ecb40d5 2022-05-26 09:04:27+00 2022-05-26 09:04:27+00 \N f75fa431-1d5b-4a84-adc9-f2ab778755f2 {http,https} \N \N {/s221-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+d2a69105-f34a-4d03-8700-029974e4dd23 2022-05-26 09:04:27+00 2022-05-26 09:04:27+00 \N f75fa431-1d5b-4a84-adc9-f2ab778755f2 {http,https} \N \N {/s221-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+8a44ab04-86a3-434f-acf5-b6742310bff6 2022-05-26 09:04:27+00 2022-05-26 09:04:27+00 \N f75fa431-1d5b-4a84-adc9-f2ab778755f2 {http,https} \N \N {/s221-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+605e87c1-c4b3-46c8-8a26-eaf2466a3cbc 2022-05-26 09:04:27+00 2022-05-26 09:04:27+00 \N 395b99d4-38f4-4268-9cd0-fa6e0f2cff94 {http,https} \N \N {/s222-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+e638a649-e228-448e-a43d-bb01b9595a31 2022-05-26 09:04:27+00 2022-05-26 09:04:27+00 \N 395b99d4-38f4-4268-9cd0-fa6e0f2cff94 {http,https} \N \N {/s222-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+8abbf9d5-609c-42ba-9d3e-e9c465da782b 2022-05-26 09:04:28+00 2022-05-26 09:04:28+00 \N 395b99d4-38f4-4268-9cd0-fa6e0f2cff94 {http,https} \N \N {/s222-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+644a2486-77b8-4909-a320-0b0f64f1e602 2022-05-26 09:04:28+00 2022-05-26 09:04:28+00 \N 395b99d4-38f4-4268-9cd0-fa6e0f2cff94 {http,https} \N \N {/s222-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+3eac023b-f444-4746-b50d-3cd01d728004 2022-05-26 09:04:28+00 2022-05-26 09:04:28+00 \N fd296ad3-4272-4acb-8246-1853ba56f38c {http,https} \N \N {/s223-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+0db4c5f7-9e77-4d76-83e2-21dcbcdbcc96 2022-05-26 09:04:28+00 2022-05-26 09:04:28+00 \N fd296ad3-4272-4acb-8246-1853ba56f38c {http,https} \N \N {/s223-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+a4c419e2-919f-40c1-aba8-0cfa522e276e 2022-05-26 09:04:28+00 2022-05-26 09:04:28+00 \N fd296ad3-4272-4acb-8246-1853ba56f38c {http,https} \N \N {/s223-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+a93825b8-bd1d-413c-92cb-2abcaa4d0926 2022-05-26 09:04:28+00 2022-05-26 09:04:28+00 \N fd296ad3-4272-4acb-8246-1853ba56f38c {http,https} \N \N {/s223-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+db0adc4a-7dfe-43a4-9e74-8cbc772e8230 2022-05-26 09:04:28+00 2022-05-26 09:04:28+00 \N 2128d33e-4e88-442c-a077-753f5bc3cfb1 {http,https} \N \N {/s224-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+5fe30601-1403-452c-9b72-56d974767951 2022-05-26 09:04:28+00 2022-05-26 09:04:28+00 \N 2128d33e-4e88-442c-a077-753f5bc3cfb1 {http,https} \N \N {/s224-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+90c8e8fc-d744-45ec-81b7-f26c60c7623d 2022-05-26 09:04:28+00 2022-05-26 09:04:28+00 \N 2128d33e-4e88-442c-a077-753f5bc3cfb1 {http,https} \N \N {/s224-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+f2528c78-e84e-4da8-a289-955767c7328b 2022-05-26 09:04:28+00 2022-05-26 09:04:28+00 \N 2128d33e-4e88-442c-a077-753f5bc3cfb1 {http,https} \N \N {/s224-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+c8dcbad3-f9e4-49f2-9fae-9c0cec332879 2022-05-26 09:04:28+00 2022-05-26 09:04:28+00 \N 0e047d1b-5481-4e2e-949c-8bb2dcf9e5e9 {http,https} \N \N {/s225-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+957737e1-6569-4650-9fa7-834d2ece5bec 2022-05-26 09:04:28+00 2022-05-26 09:04:28+00 \N 0e047d1b-5481-4e2e-949c-8bb2dcf9e5e9 {http,https} \N \N {/s225-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+86b3c74e-1c47-41e8-9b5a-6ea637769538 2022-05-26 09:04:28+00 2022-05-26 09:04:28+00 \N 0e047d1b-5481-4e2e-949c-8bb2dcf9e5e9 {http,https} \N \N {/s225-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+ddca249b-defc-47f3-acad-0f0a7e4f8617 2022-05-26 09:04:28+00 2022-05-26 09:04:28+00 \N 0e047d1b-5481-4e2e-949c-8bb2dcf9e5e9 {http,https} \N \N {/s225-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+79ae0d64-ab90-4e9a-882e-859056d79538 2022-05-26 09:04:28+00 2022-05-26 09:04:28+00 \N b3a256a3-3d0f-4a67-9518-dda233dab2a4 {http,https} \N \N {/s226-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+f2f9858d-cf8e-4b4a-a5d9-a33908ef5530 2022-05-26 09:04:28+00 2022-05-26 09:04:28+00 \N b3a256a3-3d0f-4a67-9518-dda233dab2a4 {http,https} \N \N {/s226-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+8b26c801-e3d2-4692-b594-4b69485f4ca8 2022-05-26 09:04:28+00 2022-05-26 09:04:28+00 \N b3a256a3-3d0f-4a67-9518-dda233dab2a4 {http,https} \N \N {/s226-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+eab207bd-b43b-416a-a95f-78dd707a4579 2022-05-26 09:04:28+00 2022-05-26 09:04:28+00 \N b3a256a3-3d0f-4a67-9518-dda233dab2a4 {http,https} \N \N {/s226-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+63ab9266-e6de-4b6c-8ec4-9dc035752e64 2022-05-26 09:04:28+00 2022-05-26 09:04:28+00 \N 75b76bb1-fcd9-4b1d-8a07-9c89e323838d {http,https} \N \N {/s227-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+d76b3e9b-33a8-4d3e-800a-f1df30437669 2022-05-26 09:04:28+00 2022-05-26 09:04:28+00 \N 75b76bb1-fcd9-4b1d-8a07-9c89e323838d {http,https} \N \N {/s227-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+07efcc32-c3f6-4860-8753-a8a8646a0f72 2022-05-26 09:04:28+00 2022-05-26 09:04:28+00 \N 75b76bb1-fcd9-4b1d-8a07-9c89e323838d {http,https} \N \N {/s227-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+e9e6a941-3daf-43bf-b592-1501baed5fb2 2022-05-26 09:04:28+00 2022-05-26 09:04:28+00 \N 75b76bb1-fcd9-4b1d-8a07-9c89e323838d {http,https} \N \N {/s227-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+6880c3fa-0d24-44cd-a886-e9f9c4c58cea 2022-05-26 09:04:28+00 2022-05-26 09:04:28+00 \N b9fd2d19-6d98-409c-822c-b53d23fc6bf4 {http,https} \N \N {/s228-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+95efeae4-1f31-4155-ba77-829f06379af1 2022-05-26 09:04:28+00 2022-05-26 09:04:28+00 \N b9fd2d19-6d98-409c-822c-b53d23fc6bf4 {http,https} \N \N {/s228-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+2544fd60-0054-42cc-8d70-dc6ec403f38c 2022-05-26 09:04:28+00 2022-05-26 09:04:28+00 \N b9fd2d19-6d98-409c-822c-b53d23fc6bf4 {http,https} \N \N {/s228-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+3033fd15-db84-4505-b9c8-5aee47497024 2022-05-26 09:04:28+00 2022-05-26 09:04:28+00 \N b9fd2d19-6d98-409c-822c-b53d23fc6bf4 {http,https} \N \N {/s228-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+dbcc9362-249a-4b74-911f-73931014f6d7 2022-05-26 09:04:28+00 2022-05-26 09:04:28+00 \N 999a382f-59db-47a3-95e5-3c7c387e519c {http,https} \N \N {/s229-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+f6c39d90-718a-4aab-817c-f808b0bebb48 2022-05-26 09:04:28+00 2022-05-26 09:04:28+00 \N 999a382f-59db-47a3-95e5-3c7c387e519c {http,https} \N \N {/s229-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+03107345-1338-46fc-a73f-62d1d7c3b36a 2022-05-26 09:04:28+00 2022-05-26 09:04:28+00 \N 999a382f-59db-47a3-95e5-3c7c387e519c {http,https} \N \N {/s229-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+47c87273-2924-47c6-9090-888d86b7dc81 2022-05-26 09:04:28+00 2022-05-26 09:04:28+00 \N 999a382f-59db-47a3-95e5-3c7c387e519c {http,https} \N \N {/s229-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+dee03211-607a-47f4-809a-ca7b1121acc3 2022-05-26 09:04:28+00 2022-05-26 09:04:28+00 \N 12475fba-736b-41ef-b7c9-91f0ab42706f {http,https} \N \N {/s230-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+961a0c1c-f59b-403c-9f09-dfbe43e72f2b 2022-05-26 09:04:28+00 2022-05-26 09:04:28+00 \N 12475fba-736b-41ef-b7c9-91f0ab42706f {http,https} \N \N {/s230-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+452ed169-607d-4df7-b01a-e7d299bf7fae 2022-05-26 09:04:28+00 2022-05-26 09:04:28+00 \N 12475fba-736b-41ef-b7c9-91f0ab42706f {http,https} \N \N {/s230-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+88587098-6e3c-4f1f-8b78-b3ca286d6b86 2022-05-26 09:04:28+00 2022-05-26 09:04:28+00 \N 12475fba-736b-41ef-b7c9-91f0ab42706f {http,https} \N \N {/s230-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+c319290e-5fe8-4104-8ec6-4844c9518e89 2022-05-26 09:04:28+00 2022-05-26 09:04:28+00 \N 991a0eb0-d11a-40c7-9c0c-69134e425825 {http,https} \N \N {/s231-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+9b08a36d-6d73-47c0-8c08-84d9ef630b71 2022-05-26 09:04:28+00 2022-05-26 09:04:28+00 \N 991a0eb0-d11a-40c7-9c0c-69134e425825 {http,https} \N \N {/s231-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+9c3381de-39d6-4656-83b2-e363a0674564 2022-05-26 09:04:28+00 2022-05-26 09:04:28+00 \N 991a0eb0-d11a-40c7-9c0c-69134e425825 {http,https} \N \N {/s231-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+9d3c2d9a-377f-49f3-bd84-825c82b54b2a 2022-05-26 09:04:28+00 2022-05-26 09:04:28+00 \N 991a0eb0-d11a-40c7-9c0c-69134e425825 {http,https} \N \N {/s231-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+fbd49e46-42c2-42fb-8138-5e1f99b76838 2022-05-26 09:04:28+00 2022-05-26 09:04:28+00 \N a8911c95-832e-49cd-bbbf-adf393a69d28 {http,https} \N \N {/s232-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+8d978335-6bb7-49b9-8fa7-fc28c5306d4d 2022-05-26 09:04:28+00 2022-05-26 09:04:28+00 \N a8911c95-832e-49cd-bbbf-adf393a69d28 {http,https} \N \N {/s232-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+93d89a25-7e8f-49fc-ab7c-ba3d9900cdfe 2022-05-26 09:04:28+00 2022-05-26 09:04:28+00 \N a8911c95-832e-49cd-bbbf-adf393a69d28 {http,https} \N \N {/s232-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+7ad486db-d9fc-4e93-b90f-9aad1ffca8c2 2022-05-26 09:04:28+00 2022-05-26 09:04:28+00 \N a8911c95-832e-49cd-bbbf-adf393a69d28 {http,https} \N \N {/s232-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+6232efcc-cf9c-4faa-bdc0-1165995f180e 2022-05-26 09:04:28+00 2022-05-26 09:04:28+00 \N 05d5816d-797f-4329-8693-6864ba16fa00 {http,https} \N \N {/s233-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+db2796a2-5b9f-44e4-b4e6-e1b650eac133 2022-05-26 09:04:28+00 2022-05-26 09:04:28+00 \N 05d5816d-797f-4329-8693-6864ba16fa00 {http,https} \N \N {/s233-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+9aeccec9-69c0-4095-b109-03c37c0f4102 2022-05-26 09:04:28+00 2022-05-26 09:04:28+00 \N 05d5816d-797f-4329-8693-6864ba16fa00 {http,https} \N \N {/s233-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+601e944e-4e5b-49e8-8431-5d5a9ffbd2ef 2022-05-26 09:04:28+00 2022-05-26 09:04:28+00 \N 05d5816d-797f-4329-8693-6864ba16fa00 {http,https} \N \N {/s233-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+f02a8d6a-4494-49b4-8db7-58aa2c068de2 2022-05-26 09:04:28+00 2022-05-26 09:04:28+00 \N b198788c-dabc-4723-aaeb-258b242f5bf7 {http,https} \N \N {/s234-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+aebdeb27-1aa7-4b9c-b324-eb1444df50c8 2022-05-26 09:04:28+00 2022-05-26 09:04:28+00 \N b198788c-dabc-4723-aaeb-258b242f5bf7 {http,https} \N \N {/s234-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+645f09bf-9e69-487d-a15f-d9b5602a100d 2022-05-26 09:04:28+00 2022-05-26 09:04:28+00 \N b198788c-dabc-4723-aaeb-258b242f5bf7 {http,https} \N \N {/s234-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+e8fdd5e7-3d0f-4205-9984-194647b7815e 2022-05-26 09:04:28+00 2022-05-26 09:04:28+00 \N b198788c-dabc-4723-aaeb-258b242f5bf7 {http,https} \N \N {/s234-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+c5748793-1bd0-4bc1-8a0b-a2addb5a8bcc 2022-05-26 09:04:28+00 2022-05-26 09:04:28+00 \N f827a7cb-3a5d-49dd-b15b-4a6a05c8f76c {http,https} \N \N {/s235-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+76ef03e5-c78c-45e2-a406-178b5b77a723 2022-05-26 09:04:28+00 2022-05-26 09:04:28+00 \N f827a7cb-3a5d-49dd-b15b-4a6a05c8f76c {http,https} \N \N {/s235-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+6f95ab1b-95bf-4eac-ba04-d19db0f79ae0 2022-05-26 09:04:28+00 2022-05-26 09:04:28+00 \N f827a7cb-3a5d-49dd-b15b-4a6a05c8f76c {http,https} \N \N {/s235-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+83395d2e-05e3-4ff8-9d10-5597651975cb 2022-05-26 09:04:28+00 2022-05-26 09:04:28+00 \N f827a7cb-3a5d-49dd-b15b-4a6a05c8f76c {http,https} \N \N {/s235-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+990b02bb-1105-4c02-948c-5277b3423853 2022-05-26 09:04:28+00 2022-05-26 09:04:28+00 \N 37142dfa-010c-4d0b-ae54-3285c60e177c {http,https} \N \N {/s236-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+75a4132e-b33a-4b75-bea9-66d59b6b8df1 2022-05-26 09:04:28+00 2022-05-26 09:04:28+00 \N 37142dfa-010c-4d0b-ae54-3285c60e177c {http,https} \N \N {/s236-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+62907511-18be-4e6c-add5-baa3d4830809 2022-05-26 09:04:28+00 2022-05-26 09:04:28+00 \N 37142dfa-010c-4d0b-ae54-3285c60e177c {http,https} \N \N {/s236-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+3c77aa53-ceb7-4e37-828f-39721d97fc9d 2022-05-26 09:04:28+00 2022-05-26 09:04:28+00 \N 37142dfa-010c-4d0b-ae54-3285c60e177c {http,https} \N \N {/s236-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+0bf19a48-2fa5-49b8-96e1-f096f1121522 2022-05-26 09:04:28+00 2022-05-26 09:04:28+00 \N 82375487-c356-468a-9a2a-3999121b401e {http,https} \N \N {/s237-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+fff7df69-dfb4-49f3-a312-4ffc17f98e40 2022-05-26 09:04:28+00 2022-05-26 09:04:28+00 \N 82375487-c356-468a-9a2a-3999121b401e {http,https} \N \N {/s237-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+fa5a1367-d124-42a6-acf6-1efce4ac2338 2022-05-26 09:04:28+00 2022-05-26 09:04:28+00 \N 82375487-c356-468a-9a2a-3999121b401e {http,https} \N \N {/s237-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+f1913020-f42a-4fc2-83b0-d4d837548747 2022-05-26 09:04:28+00 2022-05-26 09:04:28+00 \N 82375487-c356-468a-9a2a-3999121b401e {http,https} \N \N {/s237-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+2638b337-18c2-4e96-be07-b6e989aed671 2022-05-26 09:04:28+00 2022-05-26 09:04:28+00 \N d15f0c0a-bce7-427d-8da1-07928f5d415b {http,https} \N \N {/s238-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+6d6fd3ac-73cc-4a10-bf8c-ab03ac940276 2022-05-26 09:04:28+00 2022-05-26 09:04:28+00 \N d15f0c0a-bce7-427d-8da1-07928f5d415b {http,https} \N \N {/s238-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+a5150d0e-1090-427c-9b20-3d452576fc06 2022-05-26 09:04:28+00 2022-05-26 09:04:28+00 \N d15f0c0a-bce7-427d-8da1-07928f5d415b {http,https} \N \N {/s238-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+56be2967-2351-4c26-8a3e-eee4ef98a8e3 2022-05-26 09:04:28+00 2022-05-26 09:04:28+00 \N d15f0c0a-bce7-427d-8da1-07928f5d415b {http,https} \N \N {/s238-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+7dd824b1-39f8-49a2-9509-3e2bbf05ee7e 2022-05-26 09:04:28+00 2022-05-26 09:04:28+00 \N 24e96d1e-b429-4a11-8fd1-ec0688531b53 {http,https} \N \N {/s239-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+e0de3211-d6ad-4a8c-9087-c5ceb3c42505 2022-05-26 09:04:28+00 2022-05-26 09:04:28+00 \N 24e96d1e-b429-4a11-8fd1-ec0688531b53 {http,https} \N \N {/s239-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+24f8052d-ffbc-4074-b2c6-b08699b78f44 2022-05-26 09:04:28+00 2022-05-26 09:04:28+00 \N 24e96d1e-b429-4a11-8fd1-ec0688531b53 {http,https} \N \N {/s239-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+a1c79a06-a91a-4334-82a3-f8982eaa59b4 2022-05-26 09:04:28+00 2022-05-26 09:04:28+00 \N 24e96d1e-b429-4a11-8fd1-ec0688531b53 {http,https} \N \N {/s239-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+74bd9573-fdd0-44ef-961b-49f4e5720753 2022-05-26 09:04:28+00 2022-05-26 09:04:28+00 \N eea2568d-e01a-4936-a539-01988a96bda8 {http,https} \N \N {/s240-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+b05b9ae2-5cc1-480e-9174-2e9459ec9846 2022-05-26 09:04:28+00 2022-05-26 09:04:28+00 \N eea2568d-e01a-4936-a539-01988a96bda8 {http,https} \N \N {/s240-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+ff61997e-911f-4c69-b5e9-50438b72a263 2022-05-26 09:04:28+00 2022-05-26 09:04:28+00 \N eea2568d-e01a-4936-a539-01988a96bda8 {http,https} \N \N {/s240-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+fb9ec4e2-4a04-4823-b8e7-f8ac42962fcd 2022-05-26 09:04:28+00 2022-05-26 09:04:28+00 \N eea2568d-e01a-4936-a539-01988a96bda8 {http,https} \N \N {/s240-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+7612fda4-4889-4103-869b-77ccd865e086 2022-05-26 09:04:28+00 2022-05-26 09:04:28+00 \N aea5c9f3-3582-4705-be7d-88c291890572 {http,https} \N \N {/s241-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+1789af00-c255-47ef-a66b-9610d239b0da 2022-05-26 09:04:28+00 2022-05-26 09:04:28+00 \N aea5c9f3-3582-4705-be7d-88c291890572 {http,https} \N \N {/s241-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+81100e16-0857-4023-93e8-b81d2a458027 2022-05-26 09:04:28+00 2022-05-26 09:04:28+00 \N aea5c9f3-3582-4705-be7d-88c291890572 {http,https} \N \N {/s241-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+da641f38-12be-45b6-a4ad-fdfcd3557b8d 2022-05-26 09:04:28+00 2022-05-26 09:04:28+00 \N aea5c9f3-3582-4705-be7d-88c291890572 {http,https} \N \N {/s241-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+8ec1ae96-b063-4a14-8d70-620ad207fe3d 2022-05-26 09:04:28+00 2022-05-26 09:04:28+00 \N 062ddf91-5330-4185-877a-f8cdc29b5580 {http,https} \N \N {/s242-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+c4859932-4381-43d5-ba26-356a34bae53e 2022-05-26 09:04:28+00 2022-05-26 09:04:28+00 \N 062ddf91-5330-4185-877a-f8cdc29b5580 {http,https} \N \N {/s242-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+4b70afd1-9913-44d0-9494-378d60c001b1 2022-05-26 09:04:28+00 2022-05-26 09:04:28+00 \N 062ddf91-5330-4185-877a-f8cdc29b5580 {http,https} \N \N {/s242-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+4ffcdbc7-1716-4302-8f04-8b4cef55f3ee 2022-05-26 09:04:28+00 2022-05-26 09:04:28+00 \N 062ddf91-5330-4185-877a-f8cdc29b5580 {http,https} \N \N {/s242-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+4fb8c46c-c343-4b80-8bc9-848d3d4cb24f 2022-05-26 09:04:28+00 2022-05-26 09:04:28+00 \N 839c749b-aebf-46d3-b72b-ce58fb730dbe {http,https} \N \N {/s243-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+60cf7fdb-7492-4b8f-b2c2-70e2b6773095 2022-05-26 09:04:28+00 2022-05-26 09:04:28+00 \N 839c749b-aebf-46d3-b72b-ce58fb730dbe {http,https} \N \N {/s243-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+d5ccbc2b-75c9-401d-961b-0b0f0133f634 2022-05-26 09:04:28+00 2022-05-26 09:04:28+00 \N 839c749b-aebf-46d3-b72b-ce58fb730dbe {http,https} \N \N {/s243-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+5a2b31f4-b9c9-4137-804a-4847c23e0666 2022-05-26 09:04:28+00 2022-05-26 09:04:28+00 \N 839c749b-aebf-46d3-b72b-ce58fb730dbe {http,https} \N \N {/s243-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+74c5ebda-098f-4ecd-9798-ed8ad5e5e9e6 2022-05-26 09:04:28+00 2022-05-26 09:04:28+00 \N 75fa1631-c22b-4234-b8e0-0e6a79d24963 {http,https} \N \N {/s244-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+86b23491-f7ea-43a0-99ee-689d43bcea35 2022-05-26 09:04:28+00 2022-05-26 09:04:28+00 \N 75fa1631-c22b-4234-b8e0-0e6a79d24963 {http,https} \N \N {/s244-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+f70e67ff-9a01-46ad-8c86-4cece7c0c106 2022-05-26 09:04:28+00 2022-05-26 09:04:28+00 \N 75fa1631-c22b-4234-b8e0-0e6a79d24963 {http,https} \N \N {/s244-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+af0bbd28-93b2-4307-932f-085be3944d7e 2022-05-26 09:04:28+00 2022-05-26 09:04:28+00 \N 75fa1631-c22b-4234-b8e0-0e6a79d24963 {http,https} \N \N {/s244-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+c26123d9-0316-4ed7-949f-adb9184ccc2d 2022-05-26 09:04:28+00 2022-05-26 09:04:28+00 \N 56e78f0a-a314-4f02-865a-ccfd68eaa009 {http,https} \N \N {/s245-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+c4da8744-6ba4-438b-91ef-9509f195b114 2022-05-26 09:04:28+00 2022-05-26 09:04:28+00 \N 56e78f0a-a314-4f02-865a-ccfd68eaa009 {http,https} \N \N {/s245-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+141912a4-28bb-4e85-bcd1-6af70ca57811 2022-05-26 09:04:28+00 2022-05-26 09:04:28+00 \N 56e78f0a-a314-4f02-865a-ccfd68eaa009 {http,https} \N \N {/s245-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+35839bab-88c3-40c1-94e2-4e661a5c706c 2022-05-26 09:04:28+00 2022-05-26 09:04:28+00 \N 56e78f0a-a314-4f02-865a-ccfd68eaa009 {http,https} \N \N {/s245-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+9196182e-0c1a-495f-b6b6-b3da1974c5d1 2022-05-26 09:04:28+00 2022-05-26 09:04:28+00 \N 11b2be65-4a17-48f2-8a23-3c377c31b8bb {http,https} \N \N {/s246-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+00d42217-ca42-43d6-a053-82dfc08fb7f0 2022-05-26 09:04:28+00 2022-05-26 09:04:28+00 \N 11b2be65-4a17-48f2-8a23-3c377c31b8bb {http,https} \N \N {/s246-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+e77e0202-6a47-41a1-99f0-eac197f7c818 2022-05-26 09:04:28+00 2022-05-26 09:04:28+00 \N 11b2be65-4a17-48f2-8a23-3c377c31b8bb {http,https} \N \N {/s246-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+0cc09072-39ef-4e3a-a8a7-4862247f40a7 2022-05-26 09:04:28+00 2022-05-26 09:04:28+00 \N 11b2be65-4a17-48f2-8a23-3c377c31b8bb {http,https} \N \N {/s246-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+2a518dd7-8340-4650-9bb4-1597f43e7a13 2022-05-26 09:04:28+00 2022-05-26 09:04:28+00 \N 8497dff1-9e4d-4a60-b7ba-d4c8ff11af87 {http,https} \N \N {/s247-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+3234090b-adb9-4881-bab1-428e85a2d33c 2022-05-26 09:04:28+00 2022-05-26 09:04:28+00 \N 8497dff1-9e4d-4a60-b7ba-d4c8ff11af87 {http,https} \N \N {/s247-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+fbfd5159-8f5a-4289-a63c-0bd42283801f 2022-05-26 09:04:28+00 2022-05-26 09:04:28+00 \N 8497dff1-9e4d-4a60-b7ba-d4c8ff11af87 {http,https} \N \N {/s247-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+0ec7d5b4-4b0b-425e-af57-8ad87f484c63 2022-05-26 09:04:28+00 2022-05-26 09:04:28+00 \N 8497dff1-9e4d-4a60-b7ba-d4c8ff11af87 {http,https} \N \N {/s247-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+ea527d94-9918-41c2-a18f-fd8a891a596e 2022-05-26 09:04:29+00 2022-05-26 09:04:29+00 \N 712a182e-b50a-4efb-a0f0-ca4fe894e577 {http,https} \N \N {/s248-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+348fd434-de19-4323-ab49-a34c9e97d29c 2022-05-26 09:04:29+00 2022-05-26 09:04:29+00 \N 712a182e-b50a-4efb-a0f0-ca4fe894e577 {http,https} \N \N {/s248-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+396a55b0-2278-4c11-82f3-3dbe12c1fa6c 2022-05-26 09:04:29+00 2022-05-26 09:04:29+00 \N 712a182e-b50a-4efb-a0f0-ca4fe894e577 {http,https} \N \N {/s248-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+ff22c081-47e7-41bb-abb4-06608ba68931 2022-05-26 09:04:29+00 2022-05-26 09:04:29+00 \N 712a182e-b50a-4efb-a0f0-ca4fe894e577 {http,https} \N \N {/s248-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+5978de24-382d-4d97-8239-b9ce82c800bc 2022-05-26 09:04:29+00 2022-05-26 09:04:29+00 \N ab44cae8-8ac0-41f1-9671-d07d69bb4ad2 {http,https} \N \N {/s249-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+209680d5-f5ef-444b-a5a4-c41e9103c156 2022-05-26 09:04:29+00 2022-05-26 09:04:29+00 \N ab44cae8-8ac0-41f1-9671-d07d69bb4ad2 {http,https} \N \N {/s249-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+c5502c81-af38-48d9-b723-abded1a99819 2022-05-26 09:04:29+00 2022-05-26 09:04:29+00 \N ab44cae8-8ac0-41f1-9671-d07d69bb4ad2 {http,https} \N \N {/s249-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+eed10aa7-274d-4019-87ce-3faa9f610358 2022-05-26 09:04:29+00 2022-05-26 09:04:29+00 \N ab44cae8-8ac0-41f1-9671-d07d69bb4ad2 {http,https} \N \N {/s249-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+ab583423-fbf6-409b-ba71-9913ef7b7559 2022-05-26 09:04:29+00 2022-05-26 09:04:29+00 \N 86074cab-06f4-425d-b52a-7ba8958f3778 {http,https} \N \N {/s250-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+907c4250-e472-4128-9aec-54d695b1eaeb 2022-05-26 09:04:29+00 2022-05-26 09:04:29+00 \N 86074cab-06f4-425d-b52a-7ba8958f3778 {http,https} \N \N {/s250-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+f419d80c-3261-4ab7-a86c-b5ba9f07144c 2022-05-26 09:04:29+00 2022-05-26 09:04:29+00 \N 86074cab-06f4-425d-b52a-7ba8958f3778 {http,https} \N \N {/s250-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+e0dbcfc1-3bf1-49f2-8646-7257b80d5bc0 2022-05-26 09:04:29+00 2022-05-26 09:04:29+00 \N 86074cab-06f4-425d-b52a-7ba8958f3778 {http,https} \N \N {/s250-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+98feec91-b2f0-46c6-a3af-f846d3e655e6 2022-05-26 09:04:29+00 2022-05-26 09:04:29+00 \N 3342939c-cfcb-437b-9ba9-ba20845e2183 {http,https} \N \N {/s251-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+9400a5c7-b5c5-47d7-ab57-1b94f5ac7a6a 2022-05-26 09:04:29+00 2022-05-26 09:04:29+00 \N 3342939c-cfcb-437b-9ba9-ba20845e2183 {http,https} \N \N {/s251-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+dd14486c-840d-41e6-992f-41957c1d12fe 2022-05-26 09:04:29+00 2022-05-26 09:04:29+00 \N 3342939c-cfcb-437b-9ba9-ba20845e2183 {http,https} \N \N {/s251-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+6fc2a12a-7513-49f8-b4e0-54214e094ac0 2022-05-26 09:04:29+00 2022-05-26 09:04:29+00 \N 3342939c-cfcb-437b-9ba9-ba20845e2183 {http,https} \N \N {/s251-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+8b3e6e32-3f4e-4f64-a4a1-d6bd36322ccb 2022-05-26 09:04:29+00 2022-05-26 09:04:29+00 \N be8251f2-6fd1-4823-8bf1-bc8c7fcd04be {http,https} \N \N {/s252-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+c95c793a-34a4-4f68-9d06-2218e24c482a 2022-05-26 09:04:29+00 2022-05-26 09:04:29+00 \N be8251f2-6fd1-4823-8bf1-bc8c7fcd04be {http,https} \N \N {/s252-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+cf8b1a5a-8cf6-4046-b5d5-7f39cdf7b5f8 2022-05-26 09:04:29+00 2022-05-26 09:04:29+00 \N be8251f2-6fd1-4823-8bf1-bc8c7fcd04be {http,https} \N \N {/s252-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+e7e735ef-8851-4914-8680-27bd81a04bde 2022-05-26 09:04:29+00 2022-05-26 09:04:29+00 \N be8251f2-6fd1-4823-8bf1-bc8c7fcd04be {http,https} \N \N {/s252-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+ba861cca-1947-49d9-be61-489badcf3a55 2022-05-26 09:04:29+00 2022-05-26 09:04:29+00 \N 3d42dc37-596d-4996-8f00-b3c2fb6de270 {http,https} \N \N {/s253-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+b42a4d96-7214-434a-a90f-334d33da57e5 2022-05-26 09:04:29+00 2022-05-26 09:04:29+00 \N 3d42dc37-596d-4996-8f00-b3c2fb6de270 {http,https} \N \N {/s253-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+f16e4e16-e084-4578-aaa5-f94fadd501c1 2022-05-26 09:04:29+00 2022-05-26 09:04:29+00 \N 3d42dc37-596d-4996-8f00-b3c2fb6de270 {http,https} \N \N {/s253-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+f0d4e535-9ad6-488b-8e78-5134a476735c 2022-05-26 09:04:29+00 2022-05-26 09:04:29+00 \N 3d42dc37-596d-4996-8f00-b3c2fb6de270 {http,https} \N \N {/s253-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+37cca1b2-1d03-442c-a8dd-5384f083cb53 2022-05-26 09:04:29+00 2022-05-26 09:04:29+00 \N 704f1d16-e489-41d3-8a88-ee2c5b9b603f {http,https} \N \N {/s254-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+c4f92532-84d6-43ad-ab14-8dbcc7cde10d 2022-05-26 09:04:29+00 2022-05-26 09:04:29+00 \N 704f1d16-e489-41d3-8a88-ee2c5b9b603f {http,https} \N \N {/s254-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+3907184e-5ca9-43b1-aa66-9067eaf30c85 2022-05-26 09:04:29+00 2022-05-26 09:04:29+00 \N 704f1d16-e489-41d3-8a88-ee2c5b9b603f {http,https} \N \N {/s254-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+15b2956d-8a48-439a-8990-e5e3fc06f403 2022-05-26 09:04:29+00 2022-05-26 09:04:29+00 \N 704f1d16-e489-41d3-8a88-ee2c5b9b603f {http,https} \N \N {/s254-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+b598a8c8-b596-469a-bff9-3525463f70eb 2022-05-26 09:04:29+00 2022-05-26 09:04:29+00 \N de8247fa-8178-495c-9fdb-111b5ae55037 {http,https} \N \N {/s255-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+0197fdce-600f-4d72-b8fe-e780bb59dc0c 2022-05-26 09:04:29+00 2022-05-26 09:04:29+00 \N de8247fa-8178-495c-9fdb-111b5ae55037 {http,https} \N \N {/s255-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+f3b4ca02-ad86-40fa-abaf-726711527b72 2022-05-26 09:04:29+00 2022-05-26 09:04:29+00 \N de8247fa-8178-495c-9fdb-111b5ae55037 {http,https} \N \N {/s255-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+4d74bb2f-97ef-439c-a5ee-22d0dcdcebf1 2022-05-26 09:04:29+00 2022-05-26 09:04:29+00 \N de8247fa-8178-495c-9fdb-111b5ae55037 {http,https} \N \N {/s255-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+96b79441-2684-402f-be0e-1b36f14ca501 2022-05-26 09:04:29+00 2022-05-26 09:04:29+00 \N 9a548e20-7aef-4cbc-b959-e1680c595689 {http,https} \N \N {/s256-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+47288119-664e-4a3d-91de-5cf2989e28fa 2022-05-26 09:04:29+00 2022-05-26 09:04:29+00 \N 9a548e20-7aef-4cbc-b959-e1680c595689 {http,https} \N \N {/s256-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+25c97166-1b72-4f15-aea6-d2727a79dabb 2022-05-26 09:04:29+00 2022-05-26 09:04:29+00 \N 9a548e20-7aef-4cbc-b959-e1680c595689 {http,https} \N \N {/s256-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+6e2e11cf-0c8d-4080-b7a9-1f28c90c2dab 2022-05-26 09:04:29+00 2022-05-26 09:04:29+00 \N 9a548e20-7aef-4cbc-b959-e1680c595689 {http,https} \N \N {/s256-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+fbd3a495-78e9-4175-8237-71793cfbb606 2022-05-26 09:04:29+00 2022-05-26 09:04:29+00 \N 6d28de77-2ca4-4bb6-bc60-cd631380e860 {http,https} \N \N {/s257-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+e5ae2c28-dfc5-496d-906d-7e2efc8095d0 2022-05-26 09:04:29+00 2022-05-26 09:04:29+00 \N 6d28de77-2ca4-4bb6-bc60-cd631380e860 {http,https} \N \N {/s257-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+09c5f01c-c719-4109-954e-edaa0eb2e4fd 2022-05-26 09:04:29+00 2022-05-26 09:04:29+00 \N 6d28de77-2ca4-4bb6-bc60-cd631380e860 {http,https} \N \N {/s257-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+5f431b40-da54-4986-aa34-099cccb0d1e4 2022-05-26 09:04:29+00 2022-05-26 09:04:29+00 \N 6d28de77-2ca4-4bb6-bc60-cd631380e860 {http,https} \N \N {/s257-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+6811b6b5-b2e5-4a76-b398-bdcff56d7f22 2022-05-26 09:04:29+00 2022-05-26 09:04:29+00 \N 9630e957-6d21-4127-b724-dc7be3e201c1 {http,https} \N \N {/s258-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+c35cc644-49cd-4594-8de6-9a806674660c 2022-05-26 09:04:29+00 2022-05-26 09:04:29+00 \N 9630e957-6d21-4127-b724-dc7be3e201c1 {http,https} \N \N {/s258-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+530b68b4-7e22-41f0-837d-809dced43422 2022-05-26 09:04:29+00 2022-05-26 09:04:29+00 \N 9630e957-6d21-4127-b724-dc7be3e201c1 {http,https} \N \N {/s258-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+b2534c0d-fdb5-42c1-b908-4520e385cdbf 2022-05-26 09:04:29+00 2022-05-26 09:04:29+00 \N 9630e957-6d21-4127-b724-dc7be3e201c1 {http,https} \N \N {/s258-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+7e3aa4c5-571b-4972-828e-fa399be86501 2022-05-26 09:04:29+00 2022-05-26 09:04:29+00 \N 439b1ab5-f5d1-4fce-b52d-b2beca2c2d6b {http,https} \N \N {/s259-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+c908e9b4-8935-4f19-afd5-090326fde382 2022-05-26 09:04:29+00 2022-05-26 09:04:29+00 \N 439b1ab5-f5d1-4fce-b52d-b2beca2c2d6b {http,https} \N \N {/s259-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+158f7d7d-a0bc-4b85-a502-8b7ad0b56eb7 2022-05-26 09:04:29+00 2022-05-26 09:04:29+00 \N 439b1ab5-f5d1-4fce-b52d-b2beca2c2d6b {http,https} \N \N {/s259-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+e55e8a17-2f7b-469a-ac79-6bd192f221de 2022-05-26 09:04:29+00 2022-05-26 09:04:29+00 \N 439b1ab5-f5d1-4fce-b52d-b2beca2c2d6b {http,https} \N \N {/s259-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+ed05f0e0-9eed-42e8-ad60-06a678b81458 2022-05-26 09:04:29+00 2022-05-26 09:04:29+00 \N c385836e-5c56-47a7-b3d8-2388d62b077c {http,https} \N \N {/s260-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+7b2f74ba-fdc6-4f85-8e8a-983bc873478f 2022-05-26 09:04:29+00 2022-05-26 09:04:29+00 \N c385836e-5c56-47a7-b3d8-2388d62b077c {http,https} \N \N {/s260-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+d22c9fdf-ecd5-4d4f-85b0-3ca66aaf33d9 2022-05-26 09:04:29+00 2022-05-26 09:04:29+00 \N c385836e-5c56-47a7-b3d8-2388d62b077c {http,https} \N \N {/s260-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+462c16fa-1946-47a9-b089-c5cc2d79ad8a 2022-05-26 09:04:29+00 2022-05-26 09:04:29+00 \N c385836e-5c56-47a7-b3d8-2388d62b077c {http,https} \N \N {/s260-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+824cfe79-b762-45b9-bcb1-9ba5ef3b48a5 2022-05-26 09:04:29+00 2022-05-26 09:04:29+00 \N 5e375f63-692a-4416-a031-72323da9262b {http,https} \N \N {/s261-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+a850e086-415a-43d4-be5b-e4e38d8c8943 2022-05-26 09:04:29+00 2022-05-26 09:04:29+00 \N 5e375f63-692a-4416-a031-72323da9262b {http,https} \N \N {/s261-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+3799dd5c-abfd-4e56-95fd-9c86b2991c2a 2022-05-26 09:04:29+00 2022-05-26 09:04:29+00 \N 5e375f63-692a-4416-a031-72323da9262b {http,https} \N \N {/s261-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+847adc5b-670d-49ec-ad2c-d52cfc908eb3 2022-05-26 09:04:29+00 2022-05-26 09:04:29+00 \N 5e375f63-692a-4416-a031-72323da9262b {http,https} \N \N {/s261-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+c0af9b6f-2469-4a72-bd62-d2ba3d4e8dc4 2022-05-26 09:04:29+00 2022-05-26 09:04:29+00 \N 15ae2d93-8e77-49a2-a00b-1f8c7bf6b5a4 {http,https} \N \N {/s262-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+02f33d77-8e08-4483-9290-84c8f9819d92 2022-05-26 09:04:29+00 2022-05-26 09:04:29+00 \N 15ae2d93-8e77-49a2-a00b-1f8c7bf6b5a4 {http,https} \N \N {/s262-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+49c09e7f-5c33-4261-9641-c13a1b7e188c 2022-05-26 09:04:29+00 2022-05-26 09:04:29+00 \N 15ae2d93-8e77-49a2-a00b-1f8c7bf6b5a4 {http,https} \N \N {/s262-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+6fe90468-23d8-439e-9adb-020fc2bca272 2022-05-26 09:04:29+00 2022-05-26 09:04:29+00 \N 15ae2d93-8e77-49a2-a00b-1f8c7bf6b5a4 {http,https} \N \N {/s262-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+0a84aada-558e-4917-a4f7-fa4c6af88c9b 2022-05-26 09:04:29+00 2022-05-26 09:04:29+00 \N b4045684-2ff9-4810-a1ca-9bd3993f7cd4 {http,https} \N \N {/s263-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+744eee8f-0e52-49cb-9561-e32f76762b2b 2022-05-26 09:04:29+00 2022-05-26 09:04:29+00 \N b4045684-2ff9-4810-a1ca-9bd3993f7cd4 {http,https} \N \N {/s263-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+d8422887-12e7-401d-90a4-ba0f7c72d3c1 2022-05-26 09:04:29+00 2022-05-26 09:04:29+00 \N b4045684-2ff9-4810-a1ca-9bd3993f7cd4 {http,https} \N \N {/s263-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+5321323b-2aff-4b1d-a684-6b09daaf580d 2022-05-26 09:04:29+00 2022-05-26 09:04:29+00 \N b4045684-2ff9-4810-a1ca-9bd3993f7cd4 {http,https} \N \N {/s263-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+a55abe57-70a6-454b-b1d9-122fb86ec968 2022-05-26 09:04:29+00 2022-05-26 09:04:29+00 \N 75d178df-1223-4f56-80b4-1bea51adfc97 {http,https} \N \N {/s264-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+3b34a202-fa58-4444-bbb3-5940062b1cb6 2022-05-26 09:04:29+00 2022-05-26 09:04:29+00 \N 75d178df-1223-4f56-80b4-1bea51adfc97 {http,https} \N \N {/s264-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+39e5eb6c-15f1-4381-88ff-52938c020ec4 2022-05-26 09:04:29+00 2022-05-26 09:04:29+00 \N 75d178df-1223-4f56-80b4-1bea51adfc97 {http,https} \N \N {/s264-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+1a80d0b3-e96f-48f6-bb94-f455498bdc7d 2022-05-26 09:04:29+00 2022-05-26 09:04:29+00 \N 75d178df-1223-4f56-80b4-1bea51adfc97 {http,https} \N \N {/s264-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+8b6916bb-cf39-4aba-9b32-5f9142dc4726 2022-05-26 09:04:29+00 2022-05-26 09:04:29+00 \N b44e03a1-22f5-4443-ba10-921c56788bfe {http,https} \N \N {/s265-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+8bc591fa-c2ed-49e1-898e-91fcf8d94cf7 2022-05-26 09:04:29+00 2022-05-26 09:04:29+00 \N b44e03a1-22f5-4443-ba10-921c56788bfe {http,https} \N \N {/s265-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+8cd3fb93-8500-4e7e-9da6-3bbcbc933be7 2022-05-26 09:04:29+00 2022-05-26 09:04:29+00 \N b44e03a1-22f5-4443-ba10-921c56788bfe {http,https} \N \N {/s265-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+3fab8b54-49fe-4951-9497-2fbf94093ac1 2022-05-26 09:04:29+00 2022-05-26 09:04:29+00 \N b44e03a1-22f5-4443-ba10-921c56788bfe {http,https} \N \N {/s265-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+9309d452-40ea-4d41-bba6-81931aa7543c 2022-05-26 09:04:29+00 2022-05-26 09:04:29+00 \N 8577c35b-106c-418c-8b93-90decb06af58 {http,https} \N \N {/s266-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+889ac2e8-ebb9-42e0-b6f1-2ef895622fce 2022-05-26 09:04:29+00 2022-05-26 09:04:29+00 \N 8577c35b-106c-418c-8b93-90decb06af58 {http,https} \N \N {/s266-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+5c1de002-cf5a-4158-a95d-bd945093c7d8 2022-05-26 09:04:29+00 2022-05-26 09:04:29+00 \N 8577c35b-106c-418c-8b93-90decb06af58 {http,https} \N \N {/s266-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+02b5a25d-09ad-4749-b513-4c46f628e7ff 2022-05-26 09:04:29+00 2022-05-26 09:04:29+00 \N 8577c35b-106c-418c-8b93-90decb06af58 {http,https} \N \N {/s266-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+052bf264-63f0-4397-82a6-11e8094fa966 2022-05-26 09:04:29+00 2022-05-26 09:04:29+00 \N 18b21a7d-7f74-48b1-b9db-9ffa2db7d904 {http,https} \N \N {/s267-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+3220acdb-f816-43e7-b1dc-ff4fa95662d5 2022-05-26 09:04:29+00 2022-05-26 09:04:29+00 \N 18b21a7d-7f74-48b1-b9db-9ffa2db7d904 {http,https} \N \N {/s267-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+b3d2e5e1-b160-4da5-bd5f-c6a9a05d05cf 2022-05-26 09:04:29+00 2022-05-26 09:04:29+00 \N 18b21a7d-7f74-48b1-b9db-9ffa2db7d904 {http,https} \N \N {/s267-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+4533df68-786c-487a-9a0b-f5c2d022c6ba 2022-05-26 09:04:29+00 2022-05-26 09:04:29+00 \N 18b21a7d-7f74-48b1-b9db-9ffa2db7d904 {http,https} \N \N {/s267-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+43a993ea-426b-43f7-a5c4-5b97b6717a14 2022-05-26 09:04:29+00 2022-05-26 09:04:29+00 \N 62f8d892-76fb-4ef9-9b66-b0b81564bce5 {http,https} \N \N {/s268-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+0ae6aca5-83ef-4006-9617-f8483bfeedc3 2022-05-26 09:04:29+00 2022-05-26 09:04:29+00 \N 62f8d892-76fb-4ef9-9b66-b0b81564bce5 {http,https} \N \N {/s268-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+09583471-7a23-4a2b-b279-51fbfb8abd61 2022-05-26 09:04:29+00 2022-05-26 09:04:29+00 \N 62f8d892-76fb-4ef9-9b66-b0b81564bce5 {http,https} \N \N {/s268-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+c58d1ab1-a910-402b-aaf3-9b29b1794850 2022-05-26 09:04:29+00 2022-05-26 09:04:29+00 \N 62f8d892-76fb-4ef9-9b66-b0b81564bce5 {http,https} \N \N {/s268-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+5387a4b2-e8c3-4816-97bc-c7c848cd6dc2 2022-05-26 09:04:29+00 2022-05-26 09:04:29+00 \N 08da3a9d-5fdf-47a8-be8f-ce287d2f2914 {http,https} \N \N {/s269-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+b6491fbf-c90a-40cc-97a7-74ca4f088960 2022-05-26 09:04:29+00 2022-05-26 09:04:29+00 \N 08da3a9d-5fdf-47a8-be8f-ce287d2f2914 {http,https} \N \N {/s269-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+76091a4f-6f33-41b6-8087-ca0e7911ad9f 2022-05-26 09:04:29+00 2022-05-26 09:04:29+00 \N 08da3a9d-5fdf-47a8-be8f-ce287d2f2914 {http,https} \N \N {/s269-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+f21744bf-3172-4cbe-9a5b-90b3dc3de89f 2022-05-26 09:04:29+00 2022-05-26 09:04:29+00 \N 08da3a9d-5fdf-47a8-be8f-ce287d2f2914 {http,https} \N \N {/s269-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+43fee4de-6c96-4e33-8aeb-94f9fa66257b 2022-05-26 09:04:29+00 2022-05-26 09:04:29+00 \N e6ff5e56-255d-440d-81df-a452a2072297 {http,https} \N \N {/s270-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+90f51228-c787-46bb-aead-6e6414ae2bc1 2022-05-26 09:04:29+00 2022-05-26 09:04:29+00 \N e6ff5e56-255d-440d-81df-a452a2072297 {http,https} \N \N {/s270-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+61153c6f-6bed-4d51-9f78-3ceab4b5d196 2022-05-26 09:04:29+00 2022-05-26 09:04:29+00 \N e6ff5e56-255d-440d-81df-a452a2072297 {http,https} \N \N {/s270-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+45a72cc0-9e6d-42d9-8d2d-21fb0c847140 2022-05-26 09:04:29+00 2022-05-26 09:04:29+00 \N e6ff5e56-255d-440d-81df-a452a2072297 {http,https} \N \N {/s270-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+24ff427e-0332-49fa-8206-784da4ba5b08 2022-05-26 09:04:29+00 2022-05-26 09:04:29+00 \N 5d13ade8-944a-46a1-89db-e6707760f27a {http,https} \N \N {/s271-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+22ff64e4-97f3-4eec-bba5-53e51f4f883b 2022-05-26 09:04:29+00 2022-05-26 09:04:29+00 \N 5d13ade8-944a-46a1-89db-e6707760f27a {http,https} \N \N {/s271-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+7e421a8c-8875-4594-b600-9ac94d893106 2022-05-26 09:04:29+00 2022-05-26 09:04:29+00 \N 5d13ade8-944a-46a1-89db-e6707760f27a {http,https} \N \N {/s271-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+a1d24aee-f6ba-45fb-959e-57bedffa0b46 2022-05-26 09:04:29+00 2022-05-26 09:04:29+00 \N 5d13ade8-944a-46a1-89db-e6707760f27a {http,https} \N \N {/s271-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+4f824f7d-885e-42ba-9038-b4c65a7be458 2022-05-26 09:04:29+00 2022-05-26 09:04:29+00 \N 783e864e-f9f2-410b-ae7e-f083694fd114 {http,https} \N \N {/s272-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+a6c54709-dbe3-4b18-bd44-d7e8b5182d2b 2022-05-26 09:04:29+00 2022-05-26 09:04:29+00 \N 783e864e-f9f2-410b-ae7e-f083694fd114 {http,https} \N \N {/s272-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+803cf53a-4016-4648-9f0a-2f274b40093c 2022-05-26 09:04:29+00 2022-05-26 09:04:29+00 \N 783e864e-f9f2-410b-ae7e-f083694fd114 {http,https} \N \N {/s272-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+e178bef8-4f8d-47c0-bb07-ef94f4c3348b 2022-05-26 09:04:29+00 2022-05-26 09:04:29+00 \N 783e864e-f9f2-410b-ae7e-f083694fd114 {http,https} \N \N {/s272-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+9148b8d2-133c-4808-8c0c-71545df3008d 2022-05-26 09:04:29+00 2022-05-26 09:04:29+00 \N dd29a63e-9bd9-4a46-99a2-bb4de34b390d {http,https} \N \N {/s273-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+8f0df146-c486-4a7c-832c-a0c5cdf656bc 2022-05-26 09:04:29+00 2022-05-26 09:04:29+00 \N dd29a63e-9bd9-4a46-99a2-bb4de34b390d {http,https} \N \N {/s273-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+5ab69c7c-3c0f-4f0d-9100-726bf887f09f 2022-05-26 09:04:29+00 2022-05-26 09:04:29+00 \N dd29a63e-9bd9-4a46-99a2-bb4de34b390d {http,https} \N \N {/s273-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+01b9bbe7-7748-40ae-b2ea-9e4f641a52bb 2022-05-26 09:04:29+00 2022-05-26 09:04:29+00 \N dd29a63e-9bd9-4a46-99a2-bb4de34b390d {http,https} \N \N {/s273-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+2c068758-6596-4aa6-8d5c-2c1461ea6b63 2022-05-26 09:04:29+00 2022-05-26 09:04:29+00 \N d308ba72-8ccb-4b74-bc09-c3ea91561b47 {http,https} \N \N {/s274-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+be96003d-565e-4bb8-bad7-a497fe5e2e51 2022-05-26 09:04:29+00 2022-05-26 09:04:29+00 \N d308ba72-8ccb-4b74-bc09-c3ea91561b47 {http,https} \N \N {/s274-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+99c4664d-2e5c-4c46-9dda-4f05ef8b6e5b 2022-05-26 09:04:29+00 2022-05-26 09:04:29+00 \N d308ba72-8ccb-4b74-bc09-c3ea91561b47 {http,https} \N \N {/s274-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+7a4b03bc-df94-4d3e-8d22-a078a6539271 2022-05-26 09:04:29+00 2022-05-26 09:04:29+00 \N d308ba72-8ccb-4b74-bc09-c3ea91561b47 {http,https} \N \N {/s274-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+7dfafca3-ad07-479a-a5ff-0ea8d931a5e8 2022-05-26 09:04:29+00 2022-05-26 09:04:29+00 \N bb545b0f-69e5-4dbe-8b3a-8d692e9f0465 {http,https} \N \N {/s275-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+fdb5b185-b8f4-4a36-b8d1-1ee1b7ea4852 2022-05-26 09:04:29+00 2022-05-26 09:04:29+00 \N bb545b0f-69e5-4dbe-8b3a-8d692e9f0465 {http,https} \N \N {/s275-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+9150a4ac-5b0d-40ad-aa34-5e282fa8b6f0 2022-05-26 09:04:29+00 2022-05-26 09:04:29+00 \N bb545b0f-69e5-4dbe-8b3a-8d692e9f0465 {http,https} \N \N {/s275-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+78a2798c-1ccc-4af8-aca8-f64dcbcf83f1 2022-05-26 09:04:29+00 2022-05-26 09:04:29+00 \N bb545b0f-69e5-4dbe-8b3a-8d692e9f0465 {http,https} \N \N {/s275-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+9c5116d1-6f48-4666-890c-6652ade62b3b 2022-05-26 09:04:29+00 2022-05-26 09:04:29+00 \N 09688798-b181-4282-9b47-4ea11cbed88f {http,https} \N \N {/s276-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+7f4f9605-4c50-45f6-b4aa-f0376e44e6e2 2022-05-26 09:04:29+00 2022-05-26 09:04:29+00 \N 09688798-b181-4282-9b47-4ea11cbed88f {http,https} \N \N {/s276-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+a04d56c4-b5a9-4c33-8da6-d144a43d32e5 2022-05-26 09:04:29+00 2022-05-26 09:04:29+00 \N 09688798-b181-4282-9b47-4ea11cbed88f {http,https} \N \N {/s276-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+9a71d07e-24ce-4435-9354-8da15daf1a6d 2022-05-26 09:04:29+00 2022-05-26 09:04:29+00 \N 09688798-b181-4282-9b47-4ea11cbed88f {http,https} \N \N {/s276-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+c8587ba4-265a-477a-bad9-3bc338c6a86e 2022-05-26 09:04:30+00 2022-05-26 09:04:30+00 \N f2f31531-6e81-4e47-8ee5-21db84a28cae {http,https} \N \N {/s277-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+24855e5d-ff47-4287-adc3-6f63a3549733 2022-05-26 09:04:30+00 2022-05-26 09:04:30+00 \N f2f31531-6e81-4e47-8ee5-21db84a28cae {http,https} \N \N {/s277-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+6e3daae6-384f-4ed9-9a52-9c18db969354 2022-05-26 09:04:30+00 2022-05-26 09:04:30+00 \N f2f31531-6e81-4e47-8ee5-21db84a28cae {http,https} \N \N {/s277-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+32435b98-a760-4f16-97e6-7561d91cb280 2022-05-26 09:04:30+00 2022-05-26 09:04:30+00 \N f2f31531-6e81-4e47-8ee5-21db84a28cae {http,https} \N \N {/s277-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+7002e942-31fc-4778-b412-47e49c6e3d70 2022-05-26 09:04:30+00 2022-05-26 09:04:30+00 \N 5718da07-3088-41a8-a8e9-56d83309d49f {http,https} \N \N {/s278-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+09e78d3a-45c5-474a-9ff6-b3b95211b3a4 2022-05-26 09:04:30+00 2022-05-26 09:04:30+00 \N 5718da07-3088-41a8-a8e9-56d83309d49f {http,https} \N \N {/s278-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+70adbf34-eda8-445a-9448-10b5100b9890 2022-05-26 09:04:30+00 2022-05-26 09:04:30+00 \N 5718da07-3088-41a8-a8e9-56d83309d49f {http,https} \N \N {/s278-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+dd3ce252-9cd4-4435-abd7-43de11e0b22a 2022-05-26 09:04:30+00 2022-05-26 09:04:30+00 \N 5718da07-3088-41a8-a8e9-56d83309d49f {http,https} \N \N {/s278-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+24427c56-ec45-4ead-b0a0-b4e05cc8d653 2022-05-26 09:04:30+00 2022-05-26 09:04:30+00 \N 858587ef-4507-470b-bf83-53d9d428607d {http,https} \N \N {/s279-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+19214a79-a957-467d-981d-31cd3685febb 2022-05-26 09:04:30+00 2022-05-26 09:04:30+00 \N 858587ef-4507-470b-bf83-53d9d428607d {http,https} \N \N {/s279-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+256168e2-8de7-4530-88d7-8f54e2d548d6 2022-05-26 09:04:30+00 2022-05-26 09:04:30+00 \N 858587ef-4507-470b-bf83-53d9d428607d {http,https} \N \N {/s279-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+f7c42535-085e-4731-9f29-13c9c033a3c6 2022-05-26 09:04:30+00 2022-05-26 09:04:30+00 \N 858587ef-4507-470b-bf83-53d9d428607d {http,https} \N \N {/s279-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+cc809221-dad1-4357-9525-b99a233008d9 2022-05-26 09:04:30+00 2022-05-26 09:04:30+00 \N e838f443-11b9-47d3-952c-b29d32c47d99 {http,https} \N \N {/s280-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+90af6eaa-2435-4719-8f0c-a6072fda1ee8 2022-05-26 09:04:30+00 2022-05-26 09:04:30+00 \N e838f443-11b9-47d3-952c-b29d32c47d99 {http,https} \N \N {/s280-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+5bd96850-5f1b-47c5-9d47-970da35bb2af 2022-05-26 09:04:30+00 2022-05-26 09:04:30+00 \N e838f443-11b9-47d3-952c-b29d32c47d99 {http,https} \N \N {/s280-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+19fb4a2a-cf09-44dc-8430-85afaba6be53 2022-05-26 09:04:30+00 2022-05-26 09:04:30+00 \N e838f443-11b9-47d3-952c-b29d32c47d99 {http,https} \N \N {/s280-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+0ad8ebfd-5c52-458d-870a-f7e38ef47b22 2022-05-26 09:04:30+00 2022-05-26 09:04:30+00 \N 3c00d6b0-b98a-4e77-a9e8-3255963487ca {http,https} \N \N {/s281-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+5c8e93f6-0b19-4a01-a418-5db63980174f 2022-05-26 09:04:30+00 2022-05-26 09:04:30+00 \N 3c00d6b0-b98a-4e77-a9e8-3255963487ca {http,https} \N \N {/s281-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+5801a3ce-c020-4a20-a858-d9fb576ec08e 2022-05-26 09:04:30+00 2022-05-26 09:04:30+00 \N 3c00d6b0-b98a-4e77-a9e8-3255963487ca {http,https} \N \N {/s281-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+d089c304-1bad-4a90-ab0a-f7cd9ce7e317 2022-05-26 09:04:30+00 2022-05-26 09:04:30+00 \N 3c00d6b0-b98a-4e77-a9e8-3255963487ca {http,https} \N \N {/s281-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+cc4ae031-e11a-44fe-b1c2-7ec6107639a4 2022-05-26 09:04:30+00 2022-05-26 09:04:30+00 \N 7968fa6f-3fce-4d76-98b7-ac7e1abd5f3b {http,https} \N \N {/s282-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+4567a08d-a922-42bb-a9ea-a6c143e09108 2022-05-26 09:04:30+00 2022-05-26 09:04:30+00 \N 7968fa6f-3fce-4d76-98b7-ac7e1abd5f3b {http,https} \N \N {/s282-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+b08a9de6-f0a7-482d-9ca7-f7942a3d5289 2022-05-26 09:04:30+00 2022-05-26 09:04:30+00 \N 7968fa6f-3fce-4d76-98b7-ac7e1abd5f3b {http,https} \N \N {/s282-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+e16a4ba7-c2b9-4bcc-a47b-373bd9e00aa9 2022-05-26 09:04:30+00 2022-05-26 09:04:30+00 \N 7968fa6f-3fce-4d76-98b7-ac7e1abd5f3b {http,https} \N \N {/s282-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+29dc0430-7190-492b-ac0e-f54fd1a2571e 2022-05-26 09:04:30+00 2022-05-26 09:04:30+00 \N 0215b396-4130-4073-8c0b-a994e36641fc {http,https} \N \N {/s283-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+55693b37-b38e-421a-8491-89233a1a6d31 2022-05-26 09:04:30+00 2022-05-26 09:04:30+00 \N 0215b396-4130-4073-8c0b-a994e36641fc {http,https} \N \N {/s283-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+deb4cd60-2671-4143-a1c9-fef0b689b14f 2022-05-26 09:04:30+00 2022-05-26 09:04:30+00 \N 0215b396-4130-4073-8c0b-a994e36641fc {http,https} \N \N {/s283-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+c3069bf3-a702-4577-b07e-3fcefaa8bb22 2022-05-26 09:04:30+00 2022-05-26 09:04:30+00 \N 0215b396-4130-4073-8c0b-a994e36641fc {http,https} \N \N {/s283-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+80197ab5-5266-421d-8472-f2ccfa566226 2022-05-26 09:04:30+00 2022-05-26 09:04:30+00 \N 053a5358-18e8-401d-8eae-709cae78044b {http,https} \N \N {/s284-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+0b74243e-23ff-41af-acbe-fbed49ceafdf 2022-05-26 09:04:30+00 2022-05-26 09:04:30+00 \N 053a5358-18e8-401d-8eae-709cae78044b {http,https} \N \N {/s284-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+8df7a1a5-1896-4c92-9090-37deb9413e0c 2022-05-26 09:04:30+00 2022-05-26 09:04:30+00 \N 053a5358-18e8-401d-8eae-709cae78044b {http,https} \N \N {/s284-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+c4ff1b4c-3f5c-49cc-bfec-000f1c21f00a 2022-05-26 09:04:30+00 2022-05-26 09:04:30+00 \N 053a5358-18e8-401d-8eae-709cae78044b {http,https} \N \N {/s284-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+8f4a829e-3f63-471c-b46e-a58623a1291a 2022-05-26 09:04:30+00 2022-05-26 09:04:30+00 \N 645d937e-50e6-428b-a66b-b940faa02f28 {http,https} \N \N {/s285-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+b6132914-ca25-4d59-ba21-2730b87f2aae 2022-05-26 09:04:30+00 2022-05-26 09:04:30+00 \N 645d937e-50e6-428b-a66b-b940faa02f28 {http,https} \N \N {/s285-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+906b22be-2177-4fc4-a490-b61a79320e75 2022-05-26 09:04:30+00 2022-05-26 09:04:30+00 \N 645d937e-50e6-428b-a66b-b940faa02f28 {http,https} \N \N {/s285-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+f47b12f0-1a61-4bb2-a50a-d3ac3b34160f 2022-05-26 09:04:30+00 2022-05-26 09:04:30+00 \N 645d937e-50e6-428b-a66b-b940faa02f28 {http,https} \N \N {/s285-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+ffc3c83f-3318-4311-99c5-8901687e1c72 2022-05-26 09:04:30+00 2022-05-26 09:04:30+00 \N 19fa1c11-2031-49e3-8242-33a1fc7aeb18 {http,https} \N \N {/s286-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+39a060df-8013-4e5b-9309-36d901a5c48c 2022-05-26 09:04:30+00 2022-05-26 09:04:30+00 \N 19fa1c11-2031-49e3-8242-33a1fc7aeb18 {http,https} \N \N {/s286-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+550cc2f4-a1fd-4462-96dd-2dc76b84961a 2022-05-26 09:04:30+00 2022-05-26 09:04:30+00 \N 19fa1c11-2031-49e3-8242-33a1fc7aeb18 {http,https} \N \N {/s286-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+54b1193f-3c7d-4a44-a181-d6261c68416d 2022-05-26 09:04:30+00 2022-05-26 09:04:30+00 \N 19fa1c11-2031-49e3-8242-33a1fc7aeb18 {http,https} \N \N {/s286-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+f6165dfc-6c2a-4563-85b4-3b2cff47f855 2022-05-26 09:04:30+00 2022-05-26 09:04:30+00 \N 9832ee7f-74e0-4e0b-8897-44cfd8c7892a {http,https} \N \N {/s287-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+80bce374-42f7-4fe6-9a94-719816681ff1 2022-05-26 09:04:30+00 2022-05-26 09:04:30+00 \N 9832ee7f-74e0-4e0b-8897-44cfd8c7892a {http,https} \N \N {/s287-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+82d780da-9228-4204-9682-36a12419dc16 2022-05-26 09:04:30+00 2022-05-26 09:04:30+00 \N 9832ee7f-74e0-4e0b-8897-44cfd8c7892a {http,https} \N \N {/s287-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+f4fac863-5143-4f04-9919-6426d950b22d 2022-05-26 09:04:30+00 2022-05-26 09:04:30+00 \N 9832ee7f-74e0-4e0b-8897-44cfd8c7892a {http,https} \N \N {/s287-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+c762421f-dc86-472e-ace2-5491e03e5d02 2022-05-26 09:04:30+00 2022-05-26 09:04:30+00 \N 0a5d0d3b-055c-4338-b19e-1fd4d196234a {http,https} \N \N {/s288-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+33e9ec41-f5ea-46df-9ec6-eb16e3f19eba 2022-05-26 09:04:30+00 2022-05-26 09:04:30+00 \N 0a5d0d3b-055c-4338-b19e-1fd4d196234a {http,https} \N \N {/s288-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+d78a3acd-0653-4f05-a338-e2e38275b01f 2022-05-26 09:04:30+00 2022-05-26 09:04:30+00 \N 0a5d0d3b-055c-4338-b19e-1fd4d196234a {http,https} \N \N {/s288-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+0e9ad80a-cac1-43a0-b76d-92bd926edb89 2022-05-26 09:04:30+00 2022-05-26 09:04:30+00 \N 0a5d0d3b-055c-4338-b19e-1fd4d196234a {http,https} \N \N {/s288-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+0702cf7d-f724-451a-8c99-a227f4a6f5e6 2022-05-26 09:04:30+00 2022-05-26 09:04:30+00 \N 70fae9ae-8e2b-4fe7-8c2d-3c50cf88dbac {http,https} \N \N {/s289-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+ee2d5b43-ec16-40e1-a0ec-b6d7e5ce8b78 2022-05-26 09:04:30+00 2022-05-26 09:04:30+00 \N 70fae9ae-8e2b-4fe7-8c2d-3c50cf88dbac {http,https} \N \N {/s289-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+5fc724a6-8c41-4d84-acbc-ab8ac58761d5 2022-05-26 09:04:30+00 2022-05-26 09:04:30+00 \N 70fae9ae-8e2b-4fe7-8c2d-3c50cf88dbac {http,https} \N \N {/s289-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+849c6b50-03cc-4dcb-b809-e5f8873594e9 2022-05-26 09:04:30+00 2022-05-26 09:04:30+00 \N 70fae9ae-8e2b-4fe7-8c2d-3c50cf88dbac {http,https} \N \N {/s289-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+c3896e85-8096-4b89-ae83-b1eb037fc659 2022-05-26 09:04:30+00 2022-05-26 09:04:30+00 \N 554fa44c-d64b-4501-84f6-8543e0ac1c42 {http,https} \N \N {/s290-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+64efc957-dc79-4892-bf93-08ac8dd7bbd3 2022-05-26 09:04:30+00 2022-05-26 09:04:30+00 \N 554fa44c-d64b-4501-84f6-8543e0ac1c42 {http,https} \N \N {/s290-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+c8b4f33c-c286-4080-bd26-d78dbb6b9604 2022-05-26 09:04:30+00 2022-05-26 09:04:30+00 \N 554fa44c-d64b-4501-84f6-8543e0ac1c42 {http,https} \N \N {/s290-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+cf84d710-4034-4f8f-9332-c27a23728e25 2022-05-26 09:04:30+00 2022-05-26 09:04:30+00 \N 554fa44c-d64b-4501-84f6-8543e0ac1c42 {http,https} \N \N {/s290-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+8e3ba10b-291c-4adf-a209-1511e4ca9a8f 2022-05-26 09:04:30+00 2022-05-26 09:04:30+00 \N ff177547-b49b-4e7e-b3d9-f99ba78df0db {http,https} \N \N {/s291-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+59e68c8c-1693-441d-90fd-c9163e2acd9a 2022-05-26 09:04:30+00 2022-05-26 09:04:30+00 \N ff177547-b49b-4e7e-b3d9-f99ba78df0db {http,https} \N \N {/s291-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+800b1149-8225-41cb-82e1-1cc4746dfac8 2022-05-26 09:04:30+00 2022-05-26 09:04:30+00 \N ff177547-b49b-4e7e-b3d9-f99ba78df0db {http,https} \N \N {/s291-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+543cb191-333c-4f0c-a5dc-0491916a81a9 2022-05-26 09:04:30+00 2022-05-26 09:04:30+00 \N ff177547-b49b-4e7e-b3d9-f99ba78df0db {http,https} \N \N {/s291-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+108314e6-e3d1-4bdb-9f32-3163cebbf5f4 2022-05-26 09:04:30+00 2022-05-26 09:04:30+00 \N 76217b97-af15-44da-8565-39546305a786 {http,https} \N \N {/s292-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+661143eb-9b31-4c34-88c9-8200c5dfbd1f 2022-05-26 09:04:30+00 2022-05-26 09:04:30+00 \N 76217b97-af15-44da-8565-39546305a786 {http,https} \N \N {/s292-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+1703ab0a-7da4-4665-ae26-cda38a06ddb6 2022-05-26 09:04:30+00 2022-05-26 09:04:30+00 \N 76217b97-af15-44da-8565-39546305a786 {http,https} \N \N {/s292-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+a22d25cc-1114-4f3a-a285-3caa4f7c1c4b 2022-05-26 09:04:30+00 2022-05-26 09:04:30+00 \N 76217b97-af15-44da-8565-39546305a786 {http,https} \N \N {/s292-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+52760e3c-9b52-4bfe-9c33-2648bc1890d1 2022-05-26 09:04:30+00 2022-05-26 09:04:30+00 \N 5f70b4d9-fcd2-4a6b-b5d5-57f603a2d936 {http,https} \N \N {/s293-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+4a293abf-5d48-46b2-86f0-4c95be79be65 2022-05-26 09:04:30+00 2022-05-26 09:04:30+00 \N 5f70b4d9-fcd2-4a6b-b5d5-57f603a2d936 {http,https} \N \N {/s293-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+7de8476d-620c-4d0c-835b-20673d10340b 2022-05-26 09:04:30+00 2022-05-26 09:04:30+00 \N 5f70b4d9-fcd2-4a6b-b5d5-57f603a2d936 {http,https} \N \N {/s293-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+340bcd96-9ae3-4e84-b2c0-f145b9d30f7e 2022-05-26 09:04:30+00 2022-05-26 09:04:30+00 \N 5f70b4d9-fcd2-4a6b-b5d5-57f603a2d936 {http,https} \N \N {/s293-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+8133ed27-39bb-4eee-8bbc-910e77fcc5e2 2022-05-26 09:04:30+00 2022-05-26 09:04:30+00 \N cddf8c8a-8e68-45c7-a771-d5d2d8aca8f5 {http,https} \N \N {/s294-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+c6baa05c-e9e7-4f9e-9a80-19ff337bc72b 2022-05-26 09:04:30+00 2022-05-26 09:04:30+00 \N cddf8c8a-8e68-45c7-a771-d5d2d8aca8f5 {http,https} \N \N {/s294-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+fffea5bd-246a-4cae-bbbf-496f68c32872 2022-05-26 09:04:30+00 2022-05-26 09:04:30+00 \N cddf8c8a-8e68-45c7-a771-d5d2d8aca8f5 {http,https} \N \N {/s294-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+bb097e25-2ac2-4309-8f1d-3660da95aa2c 2022-05-26 09:04:30+00 2022-05-26 09:04:30+00 \N cddf8c8a-8e68-45c7-a771-d5d2d8aca8f5 {http,https} \N \N {/s294-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+b5bdc259-237e-4a60-bbda-fe70889b5d6c 2022-05-26 09:04:30+00 2022-05-26 09:04:30+00 \N f1e1ff63-b396-4ed6-9305-d4d045a2e9a7 {http,https} \N \N {/s295-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+298774f4-ddcb-4667-a502-d7f5969eff3e 2022-05-26 09:04:30+00 2022-05-26 09:04:30+00 \N f1e1ff63-b396-4ed6-9305-d4d045a2e9a7 {http,https} \N \N {/s295-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+92d7bb01-afe4-41cb-acc3-b0e553669f84 2022-05-26 09:04:30+00 2022-05-26 09:04:30+00 \N f1e1ff63-b396-4ed6-9305-d4d045a2e9a7 {http,https} \N \N {/s295-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+decd2289-e746-4792-9d58-ab34081fb1fe 2022-05-26 09:04:30+00 2022-05-26 09:04:30+00 \N f1e1ff63-b396-4ed6-9305-d4d045a2e9a7 {http,https} \N \N {/s295-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+6c887363-c580-49ec-bbb8-89328640a7f7 2022-05-26 09:04:30+00 2022-05-26 09:04:30+00 \N 22fa79c7-1a20-4b96-afbb-cac2c2c22706 {http,https} \N \N {/s296-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+da6360e8-ff98-4d8b-b008-0fc3e7676466 2022-05-26 09:04:30+00 2022-05-26 09:04:30+00 \N 22fa79c7-1a20-4b96-afbb-cac2c2c22706 {http,https} \N \N {/s296-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+fcbd76a8-cf2c-42a6-9b97-4b1f9f9d461a 2022-05-26 09:04:30+00 2022-05-26 09:04:30+00 \N 22fa79c7-1a20-4b96-afbb-cac2c2c22706 {http,https} \N \N {/s296-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+8db17f64-a079-4e82-9fbe-2908b771d6dd 2022-05-26 09:04:30+00 2022-05-26 09:04:30+00 \N 22fa79c7-1a20-4b96-afbb-cac2c2c22706 {http,https} \N \N {/s296-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+cb7fc10f-a7f8-408e-8aa5-6fe29c2f7f83 2022-05-26 09:04:30+00 2022-05-26 09:04:30+00 \N dc31ed76-081d-4ae2-b4d3-c249a4348842 {http,https} \N \N {/s297-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+830d11fc-f539-4581-95ff-b5bc36d0771c 2022-05-26 09:04:30+00 2022-05-26 09:04:30+00 \N dc31ed76-081d-4ae2-b4d3-c249a4348842 {http,https} \N \N {/s297-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+4e351acf-98e3-45e3-9786-c6fb719ca7c2 2022-05-26 09:04:30+00 2022-05-26 09:04:30+00 \N dc31ed76-081d-4ae2-b4d3-c249a4348842 {http,https} \N \N {/s297-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+27b055be-d510-4d88-b119-e576273fb9e5 2022-05-26 09:04:30+00 2022-05-26 09:04:30+00 \N dc31ed76-081d-4ae2-b4d3-c249a4348842 {http,https} \N \N {/s297-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+6f4af7fd-dc45-4a09-aeb1-af0e3c20ea91 2022-05-26 09:04:30+00 2022-05-26 09:04:30+00 \N 6331cb28-6a75-45e7-9d9d-7225d0996e0f {http,https} \N \N {/s298-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+eea50a61-12a9-41e2-92b0-a294e830df8b 2022-05-26 09:04:30+00 2022-05-26 09:04:30+00 \N 6331cb28-6a75-45e7-9d9d-7225d0996e0f {http,https} \N \N {/s298-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+cecb910c-ced0-4ed2-b726-e09de4370d33 2022-05-26 09:04:30+00 2022-05-26 09:04:30+00 \N 6331cb28-6a75-45e7-9d9d-7225d0996e0f {http,https} \N \N {/s298-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+0770314d-25f6-4226-b66b-64e2b9088793 2022-05-26 09:04:30+00 2022-05-26 09:04:30+00 \N 6331cb28-6a75-45e7-9d9d-7225d0996e0f {http,https} \N \N {/s298-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+96d99bd3-b8b8-4e6b-9e3c-65bba71819f9 2022-05-26 09:04:30+00 2022-05-26 09:04:30+00 \N d9a841c6-6bf4-4cd6-921c-f38e9f772cb0 {http,https} \N \N {/s299-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+c47c5c78-11dd-45c5-825b-afc89d4d19b1 2022-05-26 09:04:30+00 2022-05-26 09:04:30+00 \N d9a841c6-6bf4-4cd6-921c-f38e9f772cb0 {http,https} \N \N {/s299-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+8e5d4e58-0ee9-4ab1-9768-641774ba20bd 2022-05-26 09:04:30+00 2022-05-26 09:04:30+00 \N d9a841c6-6bf4-4cd6-921c-f38e9f772cb0 {http,https} \N \N {/s299-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+b6f97875-7d88-4499-9965-a700fb1821ce 2022-05-26 09:04:30+00 2022-05-26 09:04:30+00 \N d9a841c6-6bf4-4cd6-921c-f38e9f772cb0 {http,https} \N \N {/s299-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+3031ee2c-3cbf-4eb5-982d-54ef84e30031 2022-05-26 09:04:30+00 2022-05-26 09:04:30+00 \N 49b9e591-2b39-4cca-b0ad-94880347cb6e {http,https} \N \N {/s300-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+31e86c57-baa0-4709-83ed-a486ce4ecf6f 2022-05-26 09:04:30+00 2022-05-26 09:04:30+00 \N 49b9e591-2b39-4cca-b0ad-94880347cb6e {http,https} \N \N {/s300-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+56f299a5-8df3-4c31-ab8e-5c9a0512f325 2022-05-26 09:04:30+00 2022-05-26 09:04:30+00 \N 49b9e591-2b39-4cca-b0ad-94880347cb6e {http,https} \N \N {/s300-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+e72a3c50-d2b3-4d63-a4de-b8d280e3fffa 2022-05-26 09:04:30+00 2022-05-26 09:04:30+00 \N 49b9e591-2b39-4cca-b0ad-94880347cb6e {http,https} \N \N {/s300-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+539ab917-81ee-46ca-9f90-3cb110bcebd7 2022-05-26 09:04:30+00 2022-05-26 09:04:30+00 \N 50d5126f-ed18-4022-a93a-3fee8b5a2a61 {http,https} \N \N {/s301-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+f2d08cf1-a499-48b4-af7f-56c1ab22d28b 2022-05-26 09:04:30+00 2022-05-26 09:04:30+00 \N 50d5126f-ed18-4022-a93a-3fee8b5a2a61 {http,https} \N \N {/s301-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+be46c66d-667c-4832-8b7e-2d2145ffe5e3 2022-05-26 09:04:30+00 2022-05-26 09:04:30+00 \N 50d5126f-ed18-4022-a93a-3fee8b5a2a61 {http,https} \N \N {/s301-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+57033331-e8db-4919-bd23-2c289503ed70 2022-05-26 09:04:30+00 2022-05-26 09:04:30+00 \N 50d5126f-ed18-4022-a93a-3fee8b5a2a61 {http,https} \N \N {/s301-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+cbdd3bf7-2a83-4358-bb6b-31848887868d 2022-05-26 09:04:30+00 2022-05-26 09:04:30+00 \N e1e1f82a-936b-49d0-8d28-ebab1f134a1b {http,https} \N \N {/s302-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+25c8e254-9fdc-4d75-b57e-f0120d3b144e 2022-05-26 09:04:30+00 2022-05-26 09:04:30+00 \N e1e1f82a-936b-49d0-8d28-ebab1f134a1b {http,https} \N \N {/s302-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+55c08559-fd0b-414f-8b9c-a8ac6047b405 2022-05-26 09:04:30+00 2022-05-26 09:04:30+00 \N e1e1f82a-936b-49d0-8d28-ebab1f134a1b {http,https} \N \N {/s302-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+479f54bd-2893-41d2-910d-c8bda2e94242 2022-05-26 09:04:30+00 2022-05-26 09:04:30+00 \N e1e1f82a-936b-49d0-8d28-ebab1f134a1b {http,https} \N \N {/s302-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+e45c75a8-657a-47dc-adb3-55926af9c3b2 2022-05-26 09:04:30+00 2022-05-26 09:04:30+00 \N b5815188-d327-4734-ad11-6bd6459b38a4 {http,https} \N \N {/s303-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+a0da43c6-ce4d-4513-897e-61fa95f64d8d 2022-05-26 09:04:30+00 2022-05-26 09:04:30+00 \N b5815188-d327-4734-ad11-6bd6459b38a4 {http,https} \N \N {/s303-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+72924912-c284-4596-83c5-c303451001a4 2022-05-26 09:04:30+00 2022-05-26 09:04:30+00 \N b5815188-d327-4734-ad11-6bd6459b38a4 {http,https} \N \N {/s303-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+aff8a5c9-cb02-4c1b-a86c-07ebd6e0bdfd 2022-05-26 09:04:30+00 2022-05-26 09:04:30+00 \N b5815188-d327-4734-ad11-6bd6459b38a4 {http,https} \N \N {/s303-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+14813123-4ed3-4b6e-91db-f1b5ac038a73 2022-05-26 09:04:30+00 2022-05-26 09:04:30+00 \N 0808e339-4431-4419-8c80-0bd658eb351a {http,https} \N \N {/s304-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+741feecc-e331-42aa-a661-8e5ed487ee62 2022-05-26 09:04:30+00 2022-05-26 09:04:30+00 \N 0808e339-4431-4419-8c80-0bd658eb351a {http,https} \N \N {/s304-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+248aa6cc-0725-44da-9dbb-4b7c5850d634 2022-05-26 09:04:30+00 2022-05-26 09:04:30+00 \N 0808e339-4431-4419-8c80-0bd658eb351a {http,https} \N \N {/s304-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+12946059-37ad-4979-8272-354cf58d5617 2022-05-26 09:04:30+00 2022-05-26 09:04:30+00 \N 0808e339-4431-4419-8c80-0bd658eb351a {http,https} \N \N {/s304-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+c31e50a3-ec4f-4a24-a968-525dbb636fa3 2022-05-26 09:04:31+00 2022-05-26 09:04:31+00 \N 8e7cf859-20b8-46cf-a515-89cff33cbaf3 {http,https} \N \N {/s305-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+f24e9f9b-3d61-4cb2-9d02-d158ec53d880 2022-05-26 09:04:31+00 2022-05-26 09:04:31+00 \N 8e7cf859-20b8-46cf-a515-89cff33cbaf3 {http,https} \N \N {/s305-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+07a39fd9-7a46-4b38-936a-2fd9762aa789 2022-05-26 09:04:31+00 2022-05-26 09:04:31+00 \N 8e7cf859-20b8-46cf-a515-89cff33cbaf3 {http,https} \N \N {/s305-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+3c8b3744-685d-484e-af02-c1ad1eb3556a 2022-05-26 09:04:31+00 2022-05-26 09:04:31+00 \N 8e7cf859-20b8-46cf-a515-89cff33cbaf3 {http,https} \N \N {/s305-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+3414b762-ca82-403e-aaa3-8249c2ecf248 2022-05-26 09:04:31+00 2022-05-26 09:04:31+00 \N 876e891f-4820-4e1d-96d5-d86cb4ecedc1 {http,https} \N \N {/s306-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+79d62324-4aa7-42d7-a4ae-03379f54844c 2022-05-26 09:04:31+00 2022-05-26 09:04:31+00 \N 876e891f-4820-4e1d-96d5-d86cb4ecedc1 {http,https} \N \N {/s306-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+4c306453-1d74-4983-a358-50f6ab589901 2022-05-26 09:04:31+00 2022-05-26 09:04:31+00 \N 876e891f-4820-4e1d-96d5-d86cb4ecedc1 {http,https} \N \N {/s306-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+1545b9ce-91da-4760-82c0-21daf92b82fd 2022-05-26 09:04:31+00 2022-05-26 09:04:31+00 \N 876e891f-4820-4e1d-96d5-d86cb4ecedc1 {http,https} \N \N {/s306-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+e9a04683-e583-4767-b401-be4b21716993 2022-05-26 09:04:31+00 2022-05-26 09:04:31+00 \N 84c6bde5-724f-4beb-b1c0-16f07b948029 {http,https} \N \N {/s307-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+29486f34-fe2d-42ea-ae8e-997eec09d113 2022-05-26 09:04:31+00 2022-05-26 09:04:31+00 \N 84c6bde5-724f-4beb-b1c0-16f07b948029 {http,https} \N \N {/s307-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+f0dd87c7-c38f-4f5d-bf09-840a303d8c5a 2022-05-26 09:04:31+00 2022-05-26 09:04:31+00 \N 84c6bde5-724f-4beb-b1c0-16f07b948029 {http,https} \N \N {/s307-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+2edb7b00-f7dd-47d4-941e-f2ad940eafda 2022-05-26 09:04:31+00 2022-05-26 09:04:31+00 \N 84c6bde5-724f-4beb-b1c0-16f07b948029 {http,https} \N \N {/s307-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+097b64d5-e821-402f-841b-6193a92adbc2 2022-05-26 09:04:31+00 2022-05-26 09:04:31+00 \N f612ff85-e276-47b3-a33a-63499962253d {http,https} \N \N {/s308-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+58cc4cf6-04fb-40f0-9e5a-2dbf033e935b 2022-05-26 09:04:31+00 2022-05-26 09:04:31+00 \N f612ff85-e276-47b3-a33a-63499962253d {http,https} \N \N {/s308-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+00d5dc17-89b3-4060-b289-517b17d16a12 2022-05-26 09:04:31+00 2022-05-26 09:04:31+00 \N f612ff85-e276-47b3-a33a-63499962253d {http,https} \N \N {/s308-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+11a89492-7e21-469d-990d-6f6e5a0da418 2022-05-26 09:04:31+00 2022-05-26 09:04:31+00 \N f612ff85-e276-47b3-a33a-63499962253d {http,https} \N \N {/s308-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+868da3e1-521e-4a2d-b4ba-74aa35e5e67a 2022-05-26 09:04:31+00 2022-05-26 09:04:31+00 \N 0e58f9e2-049c-413c-9053-520742687a6e {http,https} \N \N {/s309-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+4f233cfb-63f9-41f6-a15d-c26c0000d759 2022-05-26 09:04:31+00 2022-05-26 09:04:31+00 \N 0e58f9e2-049c-413c-9053-520742687a6e {http,https} \N \N {/s309-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+32f2826c-4afd-40f1-b5a2-858053a33cc7 2022-05-26 09:04:31+00 2022-05-26 09:04:31+00 \N 0e58f9e2-049c-413c-9053-520742687a6e {http,https} \N \N {/s309-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+a85d4c37-8534-4331-a60b-986ea8b76ef2 2022-05-26 09:04:31+00 2022-05-26 09:04:31+00 \N 0e58f9e2-049c-413c-9053-520742687a6e {http,https} \N \N {/s309-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+99efc0da-21fb-4849-81c5-306cd0387caf 2022-05-26 09:04:31+00 2022-05-26 09:04:31+00 \N 82a6fb35-6254-4f5b-8aa7-c0472632af47 {http,https} \N \N {/s310-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+dfcc93dd-3dcd-4f2e-81f3-087bde70a6b5 2022-05-26 09:04:31+00 2022-05-26 09:04:31+00 \N 82a6fb35-6254-4f5b-8aa7-c0472632af47 {http,https} \N \N {/s310-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+b77ed2e4-f97b-45b4-b228-9aacf868f9bb 2022-05-26 09:04:31+00 2022-05-26 09:04:31+00 \N 82a6fb35-6254-4f5b-8aa7-c0472632af47 {http,https} \N \N {/s310-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+29fdf619-528e-4511-a46c-2109bab3a761 2022-05-26 09:04:31+00 2022-05-26 09:04:31+00 \N 82a6fb35-6254-4f5b-8aa7-c0472632af47 {http,https} \N \N {/s310-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+5303abb3-dbf4-4a19-a26c-ef9e7182b975 2022-05-26 09:04:31+00 2022-05-26 09:04:31+00 \N 258d783d-9e92-48d2-ace4-861cb00df9b7 {http,https} \N \N {/s311-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+2b021031-bb05-4c39-8405-fabc1b056cfe 2022-05-26 09:04:31+00 2022-05-26 09:04:31+00 \N 258d783d-9e92-48d2-ace4-861cb00df9b7 {http,https} \N \N {/s311-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+420b4aac-5fe1-42af-8293-b3e9994ec2d8 2022-05-26 09:04:31+00 2022-05-26 09:04:31+00 \N 258d783d-9e92-48d2-ace4-861cb00df9b7 {http,https} \N \N {/s311-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+2355e36d-d82c-4a31-824e-186affeef2c8 2022-05-26 09:04:31+00 2022-05-26 09:04:31+00 \N 258d783d-9e92-48d2-ace4-861cb00df9b7 {http,https} \N \N {/s311-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+048c4888-dc42-424b-803b-251a79f0827a 2022-05-26 09:04:31+00 2022-05-26 09:04:31+00 \N bd5dcc38-1fc4-49c0-80e2-f26fa6a49a9f {http,https} \N \N {/s312-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+676716b3-b615-4e49-9571-fc2ccd13937a 2022-05-26 09:04:31+00 2022-05-26 09:04:31+00 \N bd5dcc38-1fc4-49c0-80e2-f26fa6a49a9f {http,https} \N \N {/s312-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+3ab6f70c-6e28-4e24-934b-4bc0c4f30be1 2022-05-26 09:04:31+00 2022-05-26 09:04:31+00 \N bd5dcc38-1fc4-49c0-80e2-f26fa6a49a9f {http,https} \N \N {/s312-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+c01b7bce-2012-4680-a2c6-cb979ac95931 2022-05-26 09:04:31+00 2022-05-26 09:04:31+00 \N bd5dcc38-1fc4-49c0-80e2-f26fa6a49a9f {http,https} \N \N {/s312-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+e32e7206-4b81-433f-818f-3d47b31edd31 2022-05-26 09:04:31+00 2022-05-26 09:04:31+00 \N 1e5ab1ef-87e3-4ebc-92e9-ec9c0f7aaa9f {http,https} \N \N {/s313-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+c9f23478-4aec-495c-8d12-c69f7d7987f6 2022-05-26 09:04:31+00 2022-05-26 09:04:31+00 \N 1e5ab1ef-87e3-4ebc-92e9-ec9c0f7aaa9f {http,https} \N \N {/s313-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+6b0a7fcb-9f01-4179-b691-0b1479481014 2022-05-26 09:04:31+00 2022-05-26 09:04:31+00 \N 1e5ab1ef-87e3-4ebc-92e9-ec9c0f7aaa9f {http,https} \N \N {/s313-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+e5642783-b3f2-4220-b24b-711595a92acf 2022-05-26 09:04:31+00 2022-05-26 09:04:31+00 \N 1e5ab1ef-87e3-4ebc-92e9-ec9c0f7aaa9f {http,https} \N \N {/s313-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+18d225b8-c01d-4f2f-8edd-fb3c26e305da 2022-05-26 09:04:31+00 2022-05-26 09:04:31+00 \N 5e35d3e9-49a9-4976-a638-4e6764ccd426 {http,https} \N \N {/s314-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+2cd01762-1180-4c1c-871b-651aeb203c3c 2022-05-26 09:04:31+00 2022-05-26 09:04:31+00 \N 5e35d3e9-49a9-4976-a638-4e6764ccd426 {http,https} \N \N {/s314-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+73d9575e-ac4d-4c46-8b12-d1f2958f2cdf 2022-05-26 09:04:31+00 2022-05-26 09:04:31+00 \N 5e35d3e9-49a9-4976-a638-4e6764ccd426 {http,https} \N \N {/s314-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+bb5174a5-5337-4a6a-9e57-70a14ce2682f 2022-05-26 09:04:31+00 2022-05-26 09:04:31+00 \N 5e35d3e9-49a9-4976-a638-4e6764ccd426 {http,https} \N \N {/s314-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+03b928eb-3a70-4949-8811-07129921837a 2022-05-26 09:04:31+00 2022-05-26 09:04:31+00 \N 7bab5fa6-6191-49b8-9c7e-8addeb144e8a {http,https} \N \N {/s315-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+36140aad-79a9-4198-8007-c5c94f31ecdd 2022-05-26 09:04:31+00 2022-05-26 09:04:31+00 \N 7bab5fa6-6191-49b8-9c7e-8addeb144e8a {http,https} \N \N {/s315-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+31e9dc47-a7ac-451e-bfdd-fd4e3491fdda 2022-05-26 09:04:31+00 2022-05-26 09:04:31+00 \N 7bab5fa6-6191-49b8-9c7e-8addeb144e8a {http,https} \N \N {/s315-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+d9c548e4-288c-4ecf-b9cd-73652e6e689b 2022-05-26 09:04:31+00 2022-05-26 09:04:31+00 \N 7bab5fa6-6191-49b8-9c7e-8addeb144e8a {http,https} \N \N {/s315-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+4424a33d-98da-4246-9ccb-200ff9f62ce3 2022-05-26 09:04:31+00 2022-05-26 09:04:31+00 \N 9bd52aa4-7158-4d06-81f2-a10f99e33f08 {http,https} \N \N {/s316-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+5661013c-e421-43c6-ab2e-ae64587f46e2 2022-05-26 09:04:31+00 2022-05-26 09:04:31+00 \N 9bd52aa4-7158-4d06-81f2-a10f99e33f08 {http,https} \N \N {/s316-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+39e23428-ae1f-4cf7-bb56-ce6f4f08defc 2022-05-26 09:04:31+00 2022-05-26 09:04:31+00 \N 9bd52aa4-7158-4d06-81f2-a10f99e33f08 {http,https} \N \N {/s316-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+82da3fbd-0483-41f8-af41-fd3f4c87d071 2022-05-26 09:04:31+00 2022-05-26 09:04:31+00 \N 9bd52aa4-7158-4d06-81f2-a10f99e33f08 {http,https} \N \N {/s316-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+f1543a8c-08aa-4c3a-bde9-c1cd187e0779 2022-05-26 09:04:31+00 2022-05-26 09:04:31+00 \N b26027f8-6fc2-46c7-aef7-d9cd67fbffe3 {http,https} \N \N {/s317-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+793df1e0-6ab6-4fe9-907c-d18863bbeccf 2022-05-26 09:04:31+00 2022-05-26 09:04:31+00 \N b26027f8-6fc2-46c7-aef7-d9cd67fbffe3 {http,https} \N \N {/s317-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+437f872b-bd08-43f5-b957-169c2148f932 2022-05-26 09:04:31+00 2022-05-26 09:04:31+00 \N b26027f8-6fc2-46c7-aef7-d9cd67fbffe3 {http,https} \N \N {/s317-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+9a228df4-32da-4fd7-9093-984ddf1a3c70 2022-05-26 09:04:31+00 2022-05-26 09:04:31+00 \N b26027f8-6fc2-46c7-aef7-d9cd67fbffe3 {http,https} \N \N {/s317-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+a2121b71-4355-49f9-9102-95339015122d 2022-05-26 09:04:31+00 2022-05-26 09:04:31+00 \N c00f7722-3c3f-498d-9808-cd4a86007958 {http,https} \N \N {/s318-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+8c9b468b-2bdb-4700-b0e1-f798138e79e7 2022-05-26 09:04:31+00 2022-05-26 09:04:31+00 \N c00f7722-3c3f-498d-9808-cd4a86007958 {http,https} \N \N {/s318-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+f3fe8c5d-8307-4885-8654-abcbf4817871 2022-05-26 09:04:31+00 2022-05-26 09:04:31+00 \N c00f7722-3c3f-498d-9808-cd4a86007958 {http,https} \N \N {/s318-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+ba06f51b-4793-408d-8695-3382f4fe7ee1 2022-05-26 09:04:31+00 2022-05-26 09:04:31+00 \N c00f7722-3c3f-498d-9808-cd4a86007958 {http,https} \N \N {/s318-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+cde5fa67-134f-46b8-93dc-aba56caee17e 2022-05-26 09:04:31+00 2022-05-26 09:04:31+00 \N c512e792-661f-4223-bc9d-6a9c059a4a09 {http,https} \N \N {/s319-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+1150a88b-b145-42d6-8d45-06d7f0afbcfe 2022-05-26 09:04:31+00 2022-05-26 09:04:31+00 \N c512e792-661f-4223-bc9d-6a9c059a4a09 {http,https} \N \N {/s319-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+a7ab5648-327f-4203-a4df-5d3c99d5ad19 2022-05-26 09:04:31+00 2022-05-26 09:04:31+00 \N c512e792-661f-4223-bc9d-6a9c059a4a09 {http,https} \N \N {/s319-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+dc17decd-87f7-47ce-b199-6639f4995f01 2022-05-26 09:04:31+00 2022-05-26 09:04:31+00 \N c512e792-661f-4223-bc9d-6a9c059a4a09 {http,https} \N \N {/s319-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+b3ee9bb9-f6ec-4e45-a09d-19e3dd69a786 2022-05-26 09:04:31+00 2022-05-26 09:04:31+00 \N 5f154afd-4a66-4d1a-be2a-15354ad499fa {http,https} \N \N {/s320-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+79f14f9b-ffeb-48ef-8827-6e5c1822e974 2022-05-26 09:04:31+00 2022-05-26 09:04:31+00 \N 5f154afd-4a66-4d1a-be2a-15354ad499fa {http,https} \N \N {/s320-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+63c8682f-c030-4621-ae98-85a669e33b8c 2022-05-26 09:04:31+00 2022-05-26 09:04:31+00 \N 5f154afd-4a66-4d1a-be2a-15354ad499fa {http,https} \N \N {/s320-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+ce713b63-fae7-4384-a7c8-305a3bfea60a 2022-05-26 09:04:31+00 2022-05-26 09:04:31+00 \N 5f154afd-4a66-4d1a-be2a-15354ad499fa {http,https} \N \N {/s320-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+d8d2ebe1-78c7-40d3-8077-90adbc27feb3 2022-05-26 09:04:31+00 2022-05-26 09:04:31+00 \N 6226f972-df24-4f54-a21d-e90352622724 {http,https} \N \N {/s321-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+f0317094-0e83-474b-843f-9870f893c2fb 2022-05-26 09:04:31+00 2022-05-26 09:04:31+00 \N 6226f972-df24-4f54-a21d-e90352622724 {http,https} \N \N {/s321-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+1c79b425-d3be-482b-9bfa-33f6952d3dd1 2022-05-26 09:04:31+00 2022-05-26 09:04:31+00 \N 6226f972-df24-4f54-a21d-e90352622724 {http,https} \N \N {/s321-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+c72a5c27-f8ab-4b26-82b4-2229aa4e9fdd 2022-05-26 09:04:31+00 2022-05-26 09:04:31+00 \N 6226f972-df24-4f54-a21d-e90352622724 {http,https} \N \N {/s321-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+66f98d94-be19-48bb-9922-c987e915554a 2022-05-26 09:04:31+00 2022-05-26 09:04:31+00 \N 6337f622-dad3-40f7-9a25-acd776963042 {http,https} \N \N {/s322-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+bc871827-aa4c-4ad2-89c1-3b6109cf4899 2022-05-26 09:04:31+00 2022-05-26 09:04:31+00 \N 6337f622-dad3-40f7-9a25-acd776963042 {http,https} \N \N {/s322-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+97d92c9e-7903-4d72-8896-466e0e4072ae 2022-05-26 09:04:31+00 2022-05-26 09:04:31+00 \N 6337f622-dad3-40f7-9a25-acd776963042 {http,https} \N \N {/s322-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+e1b25673-e1a1-45a3-95f5-5b65085e0a54 2022-05-26 09:04:31+00 2022-05-26 09:04:31+00 \N 6337f622-dad3-40f7-9a25-acd776963042 {http,https} \N \N {/s322-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+04de7c11-54f1-4c5d-9383-d9e8f6b44fb1 2022-05-26 09:04:31+00 2022-05-26 09:04:31+00 \N f60b096f-1249-4270-80eb-b451330fc934 {http,https} \N \N {/s323-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+6d318c2c-335b-4327-a803-bd2d3990809c 2022-05-26 09:04:31+00 2022-05-26 09:04:31+00 \N f60b096f-1249-4270-80eb-b451330fc934 {http,https} \N \N {/s323-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+f2d7326f-8b77-4aaa-ade9-c32fa392c14b 2022-05-26 09:04:31+00 2022-05-26 09:04:31+00 \N f60b096f-1249-4270-80eb-b451330fc934 {http,https} \N \N {/s323-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+3639b575-8aae-4dbe-8b59-d28cfa657bf6 2022-05-26 09:04:31+00 2022-05-26 09:04:31+00 \N f60b096f-1249-4270-80eb-b451330fc934 {http,https} \N \N {/s323-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+198d8756-5382-46bc-bbd0-47e5ad06bc52 2022-05-26 09:04:31+00 2022-05-26 09:04:31+00 \N 6f477457-1329-4c51-b556-9ab27a341116 {http,https} \N \N {/s324-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+1ddd25d8-8b51-47ed-9d18-4aa3464b354e 2022-05-26 09:04:31+00 2022-05-26 09:04:31+00 \N 6f477457-1329-4c51-b556-9ab27a341116 {http,https} \N \N {/s324-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+7f513acc-043e-4c75-a0b2-69fe81b8b812 2022-05-26 09:04:31+00 2022-05-26 09:04:31+00 \N 6f477457-1329-4c51-b556-9ab27a341116 {http,https} \N \N {/s324-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+18508143-177a-40da-a5c8-09ecef14a2a5 2022-05-26 09:04:31+00 2022-05-26 09:04:31+00 \N 6f477457-1329-4c51-b556-9ab27a341116 {http,https} \N \N {/s324-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+9a6d3ff8-ae12-4a16-85ce-6100a247d772 2022-05-26 09:04:31+00 2022-05-26 09:04:31+00 \N ba259465-73c0-4035-af03-083de17865cd {http,https} \N \N {/s325-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+40227b2c-3f97-4011-b988-221639bf3d48 2022-05-26 09:04:31+00 2022-05-26 09:04:31+00 \N ba259465-73c0-4035-af03-083de17865cd {http,https} \N \N {/s325-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+3af767f5-9621-4b5f-ac21-0c73acfe9745 2022-05-26 09:04:31+00 2022-05-26 09:04:31+00 \N ba259465-73c0-4035-af03-083de17865cd {http,https} \N \N {/s325-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+adda8361-8dca-47de-89e6-e91a4656b4cc 2022-05-26 09:04:31+00 2022-05-26 09:04:31+00 \N ba259465-73c0-4035-af03-083de17865cd {http,https} \N \N {/s325-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+f67126dc-9d64-4783-9ce4-8362e27ed727 2022-05-26 09:04:31+00 2022-05-26 09:04:31+00 \N ad7ba3c6-8d4c-4f5e-9c8b-58b6b7bc2b42 {http,https} \N \N {/s326-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+c5a88724-319f-4343-8f85-7309da59a872 2022-05-26 09:04:31+00 2022-05-26 09:04:31+00 \N ad7ba3c6-8d4c-4f5e-9c8b-58b6b7bc2b42 {http,https} \N \N {/s326-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+1649bdcd-4ac7-4f3f-92b9-f0f66eb2f86f 2022-05-26 09:04:31+00 2022-05-26 09:04:31+00 \N ad7ba3c6-8d4c-4f5e-9c8b-58b6b7bc2b42 {http,https} \N \N {/s326-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+a92886db-a118-44a4-9f2d-7ba57b0b2738 2022-05-26 09:04:31+00 2022-05-26 09:04:31+00 \N ad7ba3c6-8d4c-4f5e-9c8b-58b6b7bc2b42 {http,https} \N \N {/s326-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+750bdcc4-274b-457d-9168-39a6bc928198 2022-05-26 09:04:31+00 2022-05-26 09:04:31+00 \N a3caefa8-c914-44c0-ab20-e5420eef9025 {http,https} \N \N {/s327-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+de3129b4-0c83-4f00-aa2d-7f8287abce50 2022-05-26 09:04:31+00 2022-05-26 09:04:31+00 \N a3caefa8-c914-44c0-ab20-e5420eef9025 {http,https} \N \N {/s327-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+10ef3ef9-6413-44e5-9aef-9291d3e840fe 2022-05-26 09:04:31+00 2022-05-26 09:04:31+00 \N a3caefa8-c914-44c0-ab20-e5420eef9025 {http,https} \N \N {/s327-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+503c8713-668f-4a2d-9f94-9a46e3b5967c 2022-05-26 09:04:31+00 2022-05-26 09:04:31+00 \N a3caefa8-c914-44c0-ab20-e5420eef9025 {http,https} \N \N {/s327-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+d6cba0ec-6b78-4d44-9559-01cef7091a1d 2022-05-26 09:04:31+00 2022-05-26 09:04:31+00 \N dadc0a91-472d-4792-9b8e-d573a52b9056 {http,https} \N \N {/s328-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+fc7c8f9b-b54b-441e-9887-dcb2b9a695d7 2022-05-26 09:04:31+00 2022-05-26 09:04:31+00 \N dadc0a91-472d-4792-9b8e-d573a52b9056 {http,https} \N \N {/s328-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+58c681ca-8422-4499-89ae-24420f7b29ca 2022-05-26 09:04:31+00 2022-05-26 09:04:31+00 \N dadc0a91-472d-4792-9b8e-d573a52b9056 {http,https} \N \N {/s328-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+7f7bdd6c-b21d-4c17-88d5-9ace430f23aa 2022-05-26 09:04:31+00 2022-05-26 09:04:31+00 \N dadc0a91-472d-4792-9b8e-d573a52b9056 {http,https} \N \N {/s328-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+dd4fea37-feb9-48f9-9f2c-93f35cffac45 2022-05-26 09:04:31+00 2022-05-26 09:04:31+00 \N 8b00c8a1-b680-492a-87eb-350ca72bc616 {http,https} \N \N {/s329-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+754ea9fd-6de2-4197-b05f-71ceb322da23 2022-05-26 09:04:31+00 2022-05-26 09:04:31+00 \N 8b00c8a1-b680-492a-87eb-350ca72bc616 {http,https} \N \N {/s329-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+2ec5d03e-977a-413c-8383-337a5d5f246d 2022-05-26 09:04:31+00 2022-05-26 09:04:31+00 \N 8b00c8a1-b680-492a-87eb-350ca72bc616 {http,https} \N \N {/s329-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+f77dddbc-7ae4-46f2-8aa9-c97d2ab68ac6 2022-05-26 09:04:31+00 2022-05-26 09:04:31+00 \N 8b00c8a1-b680-492a-87eb-350ca72bc616 {http,https} \N \N {/s329-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+14e35303-2a3a-4356-9396-088d64a291de 2022-05-26 09:04:31+00 2022-05-26 09:04:31+00 \N 24fe112c-a8ae-4ee0-9abf-b5d8a8a61f65 {http,https} \N \N {/s330-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+507f239e-efd7-431f-a9cb-6536507e50bb 2022-05-26 09:04:31+00 2022-05-26 09:04:31+00 \N 24fe112c-a8ae-4ee0-9abf-b5d8a8a61f65 {http,https} \N \N {/s330-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+febd9dd3-9ed7-4033-b773-f55a43662a35 2022-05-26 09:04:31+00 2022-05-26 09:04:31+00 \N 24fe112c-a8ae-4ee0-9abf-b5d8a8a61f65 {http,https} \N \N {/s330-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+eac29fc8-3b05-4e07-93ac-d4949d5f3530 2022-05-26 09:04:31+00 2022-05-26 09:04:31+00 \N 24fe112c-a8ae-4ee0-9abf-b5d8a8a61f65 {http,https} \N \N {/s330-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+f5a74f0f-cd5e-4bfe-ba82-f5b9e13ecef3 2022-05-26 09:04:31+00 2022-05-26 09:04:31+00 \N 33da5233-b9f0-4d03-964e-10a619eaa459 {http,https} \N \N {/s331-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+6f9c9cff-5f6f-4cd6-b5f2-1ec0e618500d 2022-05-26 09:04:31+00 2022-05-26 09:04:31+00 \N 33da5233-b9f0-4d03-964e-10a619eaa459 {http,https} \N \N {/s331-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+ccadb9e5-aea4-494a-88f4-e8ecce7d784d 2022-05-26 09:04:31+00 2022-05-26 09:04:31+00 \N 33da5233-b9f0-4d03-964e-10a619eaa459 {http,https} \N \N {/s331-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+dec88f5c-fcd5-4f43-aae3-4bfa0c7594ce 2022-05-26 09:04:31+00 2022-05-26 09:04:31+00 \N 33da5233-b9f0-4d03-964e-10a619eaa459 {http,https} \N \N {/s331-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+6324fd00-fa16-49f1-ba13-00debc458046 2022-05-26 09:04:31+00 2022-05-26 09:04:31+00 \N 0158712b-2d90-482a-8ca0-5c4dfdf19d42 {http,https} \N \N {/s332-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+cb240526-52a4-494d-a42d-6a6a69940187 2022-05-26 09:04:31+00 2022-05-26 09:04:31+00 \N 0158712b-2d90-482a-8ca0-5c4dfdf19d42 {http,https} \N \N {/s332-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+3e813626-59d3-4451-8742-932fad93398b 2022-05-26 09:04:31+00 2022-05-26 09:04:31+00 \N 0158712b-2d90-482a-8ca0-5c4dfdf19d42 {http,https} \N \N {/s332-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+e10f9d2b-3688-4733-b20f-9148e630e180 2022-05-26 09:04:31+00 2022-05-26 09:04:31+00 \N 0158712b-2d90-482a-8ca0-5c4dfdf19d42 {http,https} \N \N {/s332-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+82e71568-41d7-423e-9ca3-922f02f84408 2022-05-26 09:04:31+00 2022-05-26 09:04:31+00 \N 91dbc846-4c2b-48f0-a5a4-651c884f2b5b {http,https} \N \N {/s333-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+1d78522a-1f35-4d87-adba-dbc350f2274b 2022-05-26 09:04:31+00 2022-05-26 09:04:31+00 \N 91dbc846-4c2b-48f0-a5a4-651c884f2b5b {http,https} \N \N {/s333-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+127c5217-b863-491a-b278-0c2291ccc7f5 2022-05-26 09:04:31+00 2022-05-26 09:04:31+00 \N 91dbc846-4c2b-48f0-a5a4-651c884f2b5b {http,https} \N \N {/s333-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+35eafcb0-8512-46d4-aa8f-e173107a1604 2022-05-26 09:04:31+00 2022-05-26 09:04:31+00 \N 91dbc846-4c2b-48f0-a5a4-651c884f2b5b {http,https} \N \N {/s333-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+a7b427b2-ab87-45d4-bf66-c3c4857dc331 2022-05-26 09:04:31+00 2022-05-26 09:04:31+00 \N 5a2fb39c-5e8a-42ce-bcbe-a84fa6e4d12d {http,https} \N \N {/s334-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+e5759747-a131-4a73-b7f9-a03fa2ae1542 2022-05-26 09:04:31+00 2022-05-26 09:04:31+00 \N 5a2fb39c-5e8a-42ce-bcbe-a84fa6e4d12d {http,https} \N \N {/s334-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+96eaa515-48ba-42cb-b9c9-6448b0dddde2 2022-05-26 09:04:32+00 2022-05-26 09:04:32+00 \N 5a2fb39c-5e8a-42ce-bcbe-a84fa6e4d12d {http,https} \N \N {/s334-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+19096cc7-43da-43c6-9817-8cf391e805c4 2022-05-26 09:04:32+00 2022-05-26 09:04:32+00 \N 5a2fb39c-5e8a-42ce-bcbe-a84fa6e4d12d {http,https} \N \N {/s334-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+94a6ef7b-5d4e-4417-902b-e65c02e552fd 2022-05-26 09:04:32+00 2022-05-26 09:04:32+00 \N 4994d988-d33f-46ae-bec1-f59018f68103 {http,https} \N \N {/s335-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+6d9382dc-6cca-457a-ab74-3547df4bc9bf 2022-05-26 09:04:32+00 2022-05-26 09:04:32+00 \N 4994d988-d33f-46ae-bec1-f59018f68103 {http,https} \N \N {/s335-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+64c65c94-5e4f-496b-906c-7612184fb954 2022-05-26 09:04:32+00 2022-05-26 09:04:32+00 \N 4994d988-d33f-46ae-bec1-f59018f68103 {http,https} \N \N {/s335-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+0f5c296c-5db7-493a-beef-c1b94d484c30 2022-05-26 09:04:32+00 2022-05-26 09:04:32+00 \N 4994d988-d33f-46ae-bec1-f59018f68103 {http,https} \N \N {/s335-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+19e0422c-4dc7-4174-b935-fd2774cf6c48 2022-05-26 09:04:32+00 2022-05-26 09:04:32+00 \N 3d398236-c1e0-4051-9845-39c6d0d4b547 {http,https} \N \N {/s336-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+a725261e-63d1-4f30-a0a9-3dfe9297690f 2022-05-26 09:04:32+00 2022-05-26 09:04:32+00 \N 3d398236-c1e0-4051-9845-39c6d0d4b547 {http,https} \N \N {/s336-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+c4434fce-c6da-45d0-9f69-5cb90f2a009b 2022-05-26 09:04:32+00 2022-05-26 09:04:32+00 \N 3d398236-c1e0-4051-9845-39c6d0d4b547 {http,https} \N \N {/s336-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+6ba3547d-789e-4f0e-92fe-cbe4c76514b9 2022-05-26 09:04:32+00 2022-05-26 09:04:32+00 \N 3d398236-c1e0-4051-9845-39c6d0d4b547 {http,https} \N \N {/s336-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+d721787a-9a7e-4237-b879-4aa533d4ff28 2022-05-26 09:04:32+00 2022-05-26 09:04:32+00 \N e2d0e93c-d371-4a4e-a0c8-f30530c873ab {http,https} \N \N {/s337-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+9a544f08-0d44-41a9-8116-64eb634a3ceb 2022-05-26 09:04:32+00 2022-05-26 09:04:32+00 \N e2d0e93c-d371-4a4e-a0c8-f30530c873ab {http,https} \N \N {/s337-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+9445a380-80c9-494a-86b9-c0e7b34a159e 2022-05-26 09:04:32+00 2022-05-26 09:04:32+00 \N e2d0e93c-d371-4a4e-a0c8-f30530c873ab {http,https} \N \N {/s337-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+b0024ab6-3a6f-4385-8112-b563885e71c5 2022-05-26 09:04:32+00 2022-05-26 09:04:32+00 \N e2d0e93c-d371-4a4e-a0c8-f30530c873ab {http,https} \N \N {/s337-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+2ca93712-d2aa-4861-a69c-8cd7e9decc83 2022-05-26 09:04:32+00 2022-05-26 09:04:32+00 \N ecea8625-a170-4648-b363-e132983ebbcf {http,https} \N \N {/s338-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+0f5014ca-782c-4f5a-91c6-5c08dbdc4a5c 2022-05-26 09:04:32+00 2022-05-26 09:04:32+00 \N ecea8625-a170-4648-b363-e132983ebbcf {http,https} \N \N {/s338-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+dfa56ed7-daee-4551-a413-905d5cd62469 2022-05-26 09:04:32+00 2022-05-26 09:04:32+00 \N ecea8625-a170-4648-b363-e132983ebbcf {http,https} \N \N {/s338-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+483946bc-6626-4d44-a006-87f6ef0741f3 2022-05-26 09:04:32+00 2022-05-26 09:04:32+00 \N ecea8625-a170-4648-b363-e132983ebbcf {http,https} \N \N {/s338-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+606d55cd-f09c-40a9-8308-37046318b700 2022-05-26 09:04:32+00 2022-05-26 09:04:32+00 \N bfb8643d-7f56-4d95-b2a7-cce9f6a75598 {http,https} \N \N {/s339-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+58ee5bf2-860d-4c46-9c99-228b0038ccba 2022-05-26 09:04:32+00 2022-05-26 09:04:32+00 \N bfb8643d-7f56-4d95-b2a7-cce9f6a75598 {http,https} \N \N {/s339-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+517c94e8-f100-448e-ad63-cdfb3ac4b5dd 2022-05-26 09:04:32+00 2022-05-26 09:04:32+00 \N bfb8643d-7f56-4d95-b2a7-cce9f6a75598 {http,https} \N \N {/s339-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+cbadd587-dbca-4c78-86e1-6d9da547d827 2022-05-26 09:04:32+00 2022-05-26 09:04:32+00 \N bfb8643d-7f56-4d95-b2a7-cce9f6a75598 {http,https} \N \N {/s339-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+e605c81b-cdce-4efa-b181-dc5933eccbda 2022-05-26 09:04:32+00 2022-05-26 09:04:32+00 \N 93947ca9-1278-4b68-bf9a-3be07d766959 {http,https} \N \N {/s340-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+52f3205e-aaaf-4c1f-93e2-b9ed8e195cba 2022-05-26 09:04:32+00 2022-05-26 09:04:32+00 \N 93947ca9-1278-4b68-bf9a-3be07d766959 {http,https} \N \N {/s340-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+9083933c-c9c8-44de-bc93-3ade3cf235b8 2022-05-26 09:04:32+00 2022-05-26 09:04:32+00 \N 93947ca9-1278-4b68-bf9a-3be07d766959 {http,https} \N \N {/s340-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+12fcf5fb-fc25-4b3c-a9cd-156c75b713a9 2022-05-26 09:04:32+00 2022-05-26 09:04:32+00 \N 93947ca9-1278-4b68-bf9a-3be07d766959 {http,https} \N \N {/s340-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+b25cab50-de05-4726-bde6-ac6e23f78ecd 2022-05-26 09:04:32+00 2022-05-26 09:04:32+00 \N b81aaca3-eebf-4445-8bd9-f803b8b54551 {http,https} \N \N {/s341-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+8d9ca2e3-c577-4134-86b7-e823e6b73e59 2022-05-26 09:04:32+00 2022-05-26 09:04:32+00 \N b81aaca3-eebf-4445-8bd9-f803b8b54551 {http,https} \N \N {/s341-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+2322db41-34c9-412e-a702-002bc316e023 2022-05-26 09:04:32+00 2022-05-26 09:04:32+00 \N b81aaca3-eebf-4445-8bd9-f803b8b54551 {http,https} \N \N {/s341-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+5c97e6f9-414c-4377-832d-989bee35377a 2022-05-26 09:04:32+00 2022-05-26 09:04:32+00 \N b81aaca3-eebf-4445-8bd9-f803b8b54551 {http,https} \N \N {/s341-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+4e518090-3431-424d-94e9-0ce4fed3dc1b 2022-05-26 09:04:32+00 2022-05-26 09:04:32+00 \N 4f0fe748-796b-413f-a4f5-3cbbe44c27c2 {http,https} \N \N {/s342-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+b253cdee-c36a-4b4e-9f82-861acb678fb5 2022-05-26 09:04:32+00 2022-05-26 09:04:32+00 \N 4f0fe748-796b-413f-a4f5-3cbbe44c27c2 {http,https} \N \N {/s342-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+2bfb2f5e-fbff-43ec-9478-9c8d437d8a93 2022-05-26 09:04:32+00 2022-05-26 09:04:32+00 \N 4f0fe748-796b-413f-a4f5-3cbbe44c27c2 {http,https} \N \N {/s342-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+ed1b8cde-e815-4aff-8480-434c60b6a024 2022-05-26 09:04:32+00 2022-05-26 09:04:32+00 \N 4f0fe748-796b-413f-a4f5-3cbbe44c27c2 {http,https} \N \N {/s342-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+5ea36b55-e87b-4a9a-8553-ade0b92cc448 2022-05-26 09:04:32+00 2022-05-26 09:04:32+00 \N f406cf4a-75c3-4ccf-8f36-9255b36e0f69 {http,https} \N \N {/s343-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+d519436e-ecbd-4214-9c45-571516db2062 2022-05-26 09:04:32+00 2022-05-26 09:04:32+00 \N f406cf4a-75c3-4ccf-8f36-9255b36e0f69 {http,https} \N \N {/s343-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+03abb2da-a99d-41ee-b03e-5cab0c96a0db 2022-05-26 09:04:32+00 2022-05-26 09:04:32+00 \N f406cf4a-75c3-4ccf-8f36-9255b36e0f69 {http,https} \N \N {/s343-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+3fb5c8e7-69b6-48ca-8d9e-fe9a5de788a8 2022-05-26 09:04:32+00 2022-05-26 09:04:32+00 \N f406cf4a-75c3-4ccf-8f36-9255b36e0f69 {http,https} \N \N {/s343-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+abaf7bb1-202c-4a1a-939b-57841b2a355d 2022-05-26 09:04:32+00 2022-05-26 09:04:32+00 \N e2817bf9-36c2-4acf-8de3-4468b149d571 {http,https} \N \N {/s344-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+e20351c6-e156-4704-9db5-5cc4b91eb840 2022-05-26 09:04:32+00 2022-05-26 09:04:32+00 \N e2817bf9-36c2-4acf-8de3-4468b149d571 {http,https} \N \N {/s344-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+28ef2b55-4bbb-49fc-a509-95b888799a46 2022-05-26 09:04:32+00 2022-05-26 09:04:32+00 \N e2817bf9-36c2-4acf-8de3-4468b149d571 {http,https} \N \N {/s344-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+7dbe296a-4373-4864-b743-759ea36dccf7 2022-05-26 09:04:32+00 2022-05-26 09:04:32+00 \N e2817bf9-36c2-4acf-8de3-4468b149d571 {http,https} \N \N {/s344-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+af502028-50bd-4bda-b6d1-3aedd395c5ed 2022-05-26 09:04:32+00 2022-05-26 09:04:32+00 \N c3f8cf8e-0683-40bc-aabb-8695dce534a2 {http,https} \N \N {/s345-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+2a57c331-b134-41be-86d6-fe41a168f35b 2022-05-26 09:04:32+00 2022-05-26 09:04:32+00 \N c3f8cf8e-0683-40bc-aabb-8695dce534a2 {http,https} \N \N {/s345-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+7cfca594-2827-4f2f-aef5-1db708a6cdbc 2022-05-26 09:04:32+00 2022-05-26 09:04:32+00 \N c3f8cf8e-0683-40bc-aabb-8695dce534a2 {http,https} \N \N {/s345-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+a6df4d33-4ddc-4211-8aba-ffc049d0633e 2022-05-26 09:04:32+00 2022-05-26 09:04:32+00 \N c3f8cf8e-0683-40bc-aabb-8695dce534a2 {http,https} \N \N {/s345-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+8b5aa23c-fb9c-4d26-a705-5d50a71d2d4f 2022-05-26 09:04:32+00 2022-05-26 09:04:32+00 \N da395198-c4a7-4d67-9e0f-8ea9bd6a72db {http,https} \N \N {/s346-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+41f98379-f615-4b60-a8d3-633a903175d5 2022-05-26 09:04:32+00 2022-05-26 09:04:32+00 \N da395198-c4a7-4d67-9e0f-8ea9bd6a72db {http,https} \N \N {/s346-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+6a8504c5-a46f-4b1e-9b28-7a9a25fedac7 2022-05-26 09:04:32+00 2022-05-26 09:04:32+00 \N da395198-c4a7-4d67-9e0f-8ea9bd6a72db {http,https} \N \N {/s346-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+86e8e358-7926-4a5a-b9fb-2a7f2ba5d984 2022-05-26 09:04:32+00 2022-05-26 09:04:32+00 \N da395198-c4a7-4d67-9e0f-8ea9bd6a72db {http,https} \N \N {/s346-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+478ff66f-b6ee-4ad2-b7ce-c59a1cea3423 2022-05-26 09:04:32+00 2022-05-26 09:04:32+00 \N e5763c8f-13d5-4f01-8ebd-b6db40a89fb0 {http,https} \N \N {/s347-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+70b4c8ac-7ace-4e03-9bbe-d33da69e9b46 2022-05-26 09:04:32+00 2022-05-26 09:04:32+00 \N e5763c8f-13d5-4f01-8ebd-b6db40a89fb0 {http,https} \N \N {/s347-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+64329e6f-182a-47dd-ba42-d64150e522a6 2022-05-26 09:04:32+00 2022-05-26 09:04:32+00 \N e5763c8f-13d5-4f01-8ebd-b6db40a89fb0 {http,https} \N \N {/s347-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+86de25d5-8059-4b44-96c8-0c283f56e722 2022-05-26 09:04:32+00 2022-05-26 09:04:32+00 \N e5763c8f-13d5-4f01-8ebd-b6db40a89fb0 {http,https} \N \N {/s347-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+5a45a249-1273-40c6-a277-db604f0ece4e 2022-05-26 09:04:32+00 2022-05-26 09:04:32+00 \N 1d84611e-9887-40c6-ab00-01210d1f82b7 {http,https} \N \N {/s348-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+75e39c9b-250a-4877-8535-1334322a8e7f 2022-05-26 09:04:32+00 2022-05-26 09:04:32+00 \N 1d84611e-9887-40c6-ab00-01210d1f82b7 {http,https} \N \N {/s348-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+a83e5ce3-6f48-4b55-814b-0786efa3f57a 2022-05-26 09:04:32+00 2022-05-26 09:04:32+00 \N 1d84611e-9887-40c6-ab00-01210d1f82b7 {http,https} \N \N {/s348-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+9e090bb4-5252-4dac-8440-46393a08b5e3 2022-05-26 09:04:32+00 2022-05-26 09:04:32+00 \N 1d84611e-9887-40c6-ab00-01210d1f82b7 {http,https} \N \N {/s348-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+0e57a6e5-a00e-4d30-b2f0-4dfe33eb6cce 2022-05-26 09:04:32+00 2022-05-26 09:04:32+00 \N c238d775-2523-46fc-8d1a-540fac1f6896 {http,https} \N \N {/s349-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+9f7adf82-c336-436b-ad3c-f6ef3717aad0 2022-05-26 09:04:32+00 2022-05-26 09:04:32+00 \N c238d775-2523-46fc-8d1a-540fac1f6896 {http,https} \N \N {/s349-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+9a24d389-8b40-4d59-ac92-75125bf6d4e9 2022-05-26 09:04:32+00 2022-05-26 09:04:32+00 \N c238d775-2523-46fc-8d1a-540fac1f6896 {http,https} \N \N {/s349-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+69d769b5-0041-4d8e-8b98-d89d3d5a1a4d 2022-05-26 09:04:32+00 2022-05-26 09:04:32+00 \N c238d775-2523-46fc-8d1a-540fac1f6896 {http,https} \N \N {/s349-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+e1877bca-7a44-4921-8069-99447c8a6f3f 2022-05-26 09:04:32+00 2022-05-26 09:04:32+00 \N 1d915ba2-c858-4732-a9e9-7b21b9d47b27 {http,https} \N \N {/s350-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+89624eec-f60d-4976-8ff8-445e5ac8bc10 2022-05-26 09:04:32+00 2022-05-26 09:04:32+00 \N 1d915ba2-c858-4732-a9e9-7b21b9d47b27 {http,https} \N \N {/s350-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+1e18ca64-3817-46bf-aa9d-901f064b43ed 2022-05-26 09:04:32+00 2022-05-26 09:04:32+00 \N 1d915ba2-c858-4732-a9e9-7b21b9d47b27 {http,https} \N \N {/s350-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+6a0827b4-55b7-4de3-a68c-d1d32352c61b 2022-05-26 09:04:32+00 2022-05-26 09:04:32+00 \N 1d915ba2-c858-4732-a9e9-7b21b9d47b27 {http,https} \N \N {/s350-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+24428a28-8db0-46c3-a9ba-f613604bfc9b 2022-05-26 09:04:32+00 2022-05-26 09:04:32+00 \N 2ddd0eb3-bada-4443-bbfe-5fccde527dca {http,https} \N \N {/s351-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+ec8fdc94-187d-42fd-9269-398ee1277e41 2022-05-26 09:04:32+00 2022-05-26 09:04:32+00 \N 2ddd0eb3-bada-4443-bbfe-5fccde527dca {http,https} \N \N {/s351-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+f7eec7d2-08cb-4080-8257-662e57a049de 2022-05-26 09:04:32+00 2022-05-26 09:04:32+00 \N 2ddd0eb3-bada-4443-bbfe-5fccde527dca {http,https} \N \N {/s351-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+3ebd16e5-1a83-42c9-aaeb-1c6d6a352d6f 2022-05-26 09:04:32+00 2022-05-26 09:04:32+00 \N 2ddd0eb3-bada-4443-bbfe-5fccde527dca {http,https} \N \N {/s351-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+0305af07-edec-4338-9a35-a70610fdc841 2022-05-26 09:04:32+00 2022-05-26 09:04:32+00 \N fb6cc1c1-f874-4ad9-9a62-3b406f948218 {http,https} \N \N {/s352-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+ca14ccb8-b0bc-4584-bd0a-8e5bf15e8f71 2022-05-26 09:04:32+00 2022-05-26 09:04:32+00 \N fb6cc1c1-f874-4ad9-9a62-3b406f948218 {http,https} \N \N {/s352-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+d35d85fd-46e6-4659-af15-43f4d3223fbe 2022-05-26 09:04:32+00 2022-05-26 09:04:32+00 \N fb6cc1c1-f874-4ad9-9a62-3b406f948218 {http,https} \N \N {/s352-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+25528edd-75fb-48e4-bab0-19c7b9888670 2022-05-26 09:04:32+00 2022-05-26 09:04:32+00 \N fb6cc1c1-f874-4ad9-9a62-3b406f948218 {http,https} \N \N {/s352-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+93cfa9fd-30e8-49ac-a3fa-367e6ab88a20 2022-05-26 09:04:32+00 2022-05-26 09:04:32+00 \N a7946bd4-5a6b-4f56-bbd5-59cf59fbacc3 {http,https} \N \N {/s353-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+c6524368-ce3b-42d9-9626-71a1ac6cc0c5 2022-05-26 09:04:32+00 2022-05-26 09:04:32+00 \N a7946bd4-5a6b-4f56-bbd5-59cf59fbacc3 {http,https} \N \N {/s353-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+af27ed48-426a-4b69-9f81-8aca7ab95b87 2022-05-26 09:04:32+00 2022-05-26 09:04:32+00 \N a7946bd4-5a6b-4f56-bbd5-59cf59fbacc3 {http,https} \N \N {/s353-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+878cfaaa-1c75-4a7a-9ff7-324df7c8cec1 2022-05-26 09:04:32+00 2022-05-26 09:04:32+00 \N a7946bd4-5a6b-4f56-bbd5-59cf59fbacc3 {http,https} \N \N {/s353-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+2f8220ab-b3e0-4149-a5a0-9bed6fd0f766 2022-05-26 09:04:32+00 2022-05-26 09:04:32+00 \N c2a397d2-8f91-41d8-9158-97dd24955a80 {http,https} \N \N {/s354-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+8460ddfe-8f07-4d0d-83ae-c376236ef347 2022-05-26 09:04:32+00 2022-05-26 09:04:32+00 \N c2a397d2-8f91-41d8-9158-97dd24955a80 {http,https} \N \N {/s354-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+991e01eb-9fca-4ca8-9ea0-34f3ea2d3d63 2022-05-26 09:04:32+00 2022-05-26 09:04:32+00 \N c2a397d2-8f91-41d8-9158-97dd24955a80 {http,https} \N \N {/s354-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+29b09368-8b00-4dd5-8ffe-ee5cfe06c0f3 2022-05-26 09:04:32+00 2022-05-26 09:04:32+00 \N c2a397d2-8f91-41d8-9158-97dd24955a80 {http,https} \N \N {/s354-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+794e1b54-9252-4c31-81b8-e97f7de7954f 2022-05-26 09:04:32+00 2022-05-26 09:04:32+00 \N 959074dc-9a50-4bd8-bb49-d0a9333d0477 {http,https} \N \N {/s355-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+b399d469-fe06-45d3-83a9-8399da0459c3 2022-05-26 09:04:32+00 2022-05-26 09:04:32+00 \N 959074dc-9a50-4bd8-bb49-d0a9333d0477 {http,https} \N \N {/s355-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+5edab9de-fd7c-4745-8802-822070cb1b76 2022-05-26 09:04:32+00 2022-05-26 09:04:32+00 \N 959074dc-9a50-4bd8-bb49-d0a9333d0477 {http,https} \N \N {/s355-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+3c3471b7-1ac2-474d-baf8-c0155b3cc954 2022-05-26 09:04:32+00 2022-05-26 09:04:32+00 \N 959074dc-9a50-4bd8-bb49-d0a9333d0477 {http,https} \N \N {/s355-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+6700d7a1-8329-4a82-a7b0-7c0482f49839 2022-05-26 09:04:32+00 2022-05-26 09:04:32+00 \N 4fafaa54-d47d-4488-8c56-94be290f38b7 {http,https} \N \N {/s356-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+0320b0e9-a314-4daf-be4b-eb1c4554c0ad 2022-05-26 09:04:32+00 2022-05-26 09:04:32+00 \N 4fafaa54-d47d-4488-8c56-94be290f38b7 {http,https} \N \N {/s356-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+fb7c1e9e-e202-4a6d-b295-ab5768d91390 2022-05-26 09:04:32+00 2022-05-26 09:04:32+00 \N 4fafaa54-d47d-4488-8c56-94be290f38b7 {http,https} \N \N {/s356-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+1584e198-4952-4a7c-a7cc-07de52851883 2022-05-26 09:04:32+00 2022-05-26 09:04:32+00 \N 4fafaa54-d47d-4488-8c56-94be290f38b7 {http,https} \N \N {/s356-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+bc766404-5881-4a64-ad32-45dad707ae63 2022-05-26 09:04:32+00 2022-05-26 09:04:32+00 \N e9556ed2-8e33-4130-a9b9-fc6c799655fc {http,https} \N \N {/s357-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+7460da23-fec2-4276-838d-bc6ccfdcb35e 2022-05-26 09:04:32+00 2022-05-26 09:04:32+00 \N e9556ed2-8e33-4130-a9b9-fc6c799655fc {http,https} \N \N {/s357-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+5fafe87e-a43e-4de6-881c-7f25cc109d10 2022-05-26 09:04:32+00 2022-05-26 09:04:32+00 \N e9556ed2-8e33-4130-a9b9-fc6c799655fc {http,https} \N \N {/s357-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+582e3091-8abd-40f7-b3ab-2787b9976b2a 2022-05-26 09:04:32+00 2022-05-26 09:04:32+00 \N e9556ed2-8e33-4130-a9b9-fc6c799655fc {http,https} \N \N {/s357-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+1b6fd211-1332-4c07-b7b2-f0c2dfcde27d 2022-05-26 09:04:32+00 2022-05-26 09:04:32+00 \N 9a6c8306-cf36-42a6-9117-724b675fd9a2 {http,https} \N \N {/s358-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+bfa87303-9222-471e-9d39-7a1d898bd097 2022-05-26 09:04:32+00 2022-05-26 09:04:32+00 \N 9a6c8306-cf36-42a6-9117-724b675fd9a2 {http,https} \N \N {/s358-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+5ab771a8-5eef-4328-8609-99ae74d8d7c2 2022-05-26 09:04:32+00 2022-05-26 09:04:32+00 \N 9a6c8306-cf36-42a6-9117-724b675fd9a2 {http,https} \N \N {/s358-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+b7a6f7a6-aa81-4cef-96d2-dec529a94680 2022-05-26 09:04:32+00 2022-05-26 09:04:32+00 \N 9a6c8306-cf36-42a6-9117-724b675fd9a2 {http,https} \N \N {/s358-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+0080ed1d-ccc1-4f02-b014-dd3a92ac964e 2022-05-26 09:04:32+00 2022-05-26 09:04:32+00 \N af36e2ce-968f-4143-926c-34f5827a2319 {http,https} \N \N {/s359-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+ad1e84ac-bc9b-4ab1-a954-afebdc7d5907 2022-05-26 09:04:32+00 2022-05-26 09:04:32+00 \N af36e2ce-968f-4143-926c-34f5827a2319 {http,https} \N \N {/s359-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+a10dd6fb-af73-467b-bcc4-869186049cc6 2022-05-26 09:04:32+00 2022-05-26 09:04:32+00 \N af36e2ce-968f-4143-926c-34f5827a2319 {http,https} \N \N {/s359-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+dc92bade-6f80-4cd0-95f4-1eaf4bfc93a6 2022-05-26 09:04:32+00 2022-05-26 09:04:32+00 \N af36e2ce-968f-4143-926c-34f5827a2319 {http,https} \N \N {/s359-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+07335b05-d85c-45be-a16c-5760a077318b 2022-05-26 09:04:32+00 2022-05-26 09:04:32+00 \N 59a3ea50-4f62-4ce2-ad54-8d72abe1ec68 {http,https} \N \N {/s360-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+4c892d67-7d8c-4879-93fd-c2bcd7a69271 2022-05-26 09:04:32+00 2022-05-26 09:04:32+00 \N 59a3ea50-4f62-4ce2-ad54-8d72abe1ec68 {http,https} \N \N {/s360-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+6f415709-c4bd-42fb-b916-224f1bb4ee56 2022-05-26 09:04:32+00 2022-05-26 09:04:32+00 \N 59a3ea50-4f62-4ce2-ad54-8d72abe1ec68 {http,https} \N \N {/s360-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+000ad825-d106-4ba3-93c8-424338479452 2022-05-26 09:04:32+00 2022-05-26 09:04:32+00 \N 59a3ea50-4f62-4ce2-ad54-8d72abe1ec68 {http,https} \N \N {/s360-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+5479f8b8-d617-47cd-93c5-ea9c7581a07e 2022-05-26 09:04:32+00 2022-05-26 09:04:32+00 \N 45cc6295-8cfc-4e44-b124-0d05c04cdd3e {http,https} \N \N {/s361-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+9498812b-b58b-4250-94f1-694faebd104c 2022-05-26 09:04:32+00 2022-05-26 09:04:32+00 \N 45cc6295-8cfc-4e44-b124-0d05c04cdd3e {http,https} \N \N {/s361-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+0e8c019f-1d59-43a1-8e02-b9be646649f1 2022-05-26 09:04:32+00 2022-05-26 09:04:32+00 \N 45cc6295-8cfc-4e44-b124-0d05c04cdd3e {http,https} \N \N {/s361-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+72d8cdb5-6f7b-48c9-8a82-eedf0fa5479d 2022-05-26 09:04:32+00 2022-05-26 09:04:32+00 \N 45cc6295-8cfc-4e44-b124-0d05c04cdd3e {http,https} \N \N {/s361-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+c67e2369-5ff1-40a4-92ba-a63a49d57130 2022-05-26 09:04:32+00 2022-05-26 09:04:32+00 \N 8b3db5a2-f3c4-4d2b-b60e-55c3f0d42960 {http,https} \N \N {/s362-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+b1566411-b1ff-4055-b8d4-9f274ca268eb 2022-05-26 09:04:32+00 2022-05-26 09:04:32+00 \N 8b3db5a2-f3c4-4d2b-b60e-55c3f0d42960 {http,https} \N \N {/s362-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+54f335c0-bc32-4fa9-8929-1c6dccb13d36 2022-05-26 09:04:32+00 2022-05-26 09:04:32+00 \N 8b3db5a2-f3c4-4d2b-b60e-55c3f0d42960 {http,https} \N \N {/s362-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+7fa94e74-d93b-42b8-ace1-95d5526737df 2022-05-26 09:04:32+00 2022-05-26 09:04:32+00 \N 8b3db5a2-f3c4-4d2b-b60e-55c3f0d42960 {http,https} \N \N {/s362-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+cc2cfc87-6cd6-4a9c-82af-110aecc7001e 2022-05-26 09:04:32+00 2022-05-26 09:04:32+00 \N 809b0fa5-91fe-4f0b-bfa4-1b17ca92647f {http,https} \N \N {/s363-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+c4709f82-2569-4d4c-a4c9-b3ceeccf6689 2022-05-26 09:04:32+00 2022-05-26 09:04:32+00 \N 809b0fa5-91fe-4f0b-bfa4-1b17ca92647f {http,https} \N \N {/s363-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+edcd51f1-9374-49a8-ac8e-ab96a9f249cb 2022-05-26 09:04:32+00 2022-05-26 09:04:32+00 \N 809b0fa5-91fe-4f0b-bfa4-1b17ca92647f {http,https} \N \N {/s363-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+4f5a5ff5-8ea4-4e02-8ba9-5742fd50e171 2022-05-26 09:04:32+00 2022-05-26 09:04:32+00 \N 809b0fa5-91fe-4f0b-bfa4-1b17ca92647f {http,https} \N \N {/s363-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+ae992988-c221-4d56-b3ee-928d7cda0762 2022-05-26 09:04:33+00 2022-05-26 09:04:33+00 \N c75cdbd1-8145-48ae-8097-d6ce0ee3d383 {http,https} \N \N {/s364-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+ea622405-967e-4c78-bdd1-4547c57aa585 2022-05-26 09:04:33+00 2022-05-26 09:04:33+00 \N c75cdbd1-8145-48ae-8097-d6ce0ee3d383 {http,https} \N \N {/s364-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+c7fc5f78-b09c-4c74-bd4e-ff12f57bebc8 2022-05-26 09:04:33+00 2022-05-26 09:04:33+00 \N c75cdbd1-8145-48ae-8097-d6ce0ee3d383 {http,https} \N \N {/s364-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+6e1f0b6c-5c92-4d9e-a468-510ea095dc98 2022-05-26 09:04:33+00 2022-05-26 09:04:33+00 \N c75cdbd1-8145-48ae-8097-d6ce0ee3d383 {http,https} \N \N {/s364-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+a9ef3f1e-7b53-482d-b4ff-2fdd4c06652c 2022-05-26 09:04:33+00 2022-05-26 09:04:33+00 \N e238e1f2-7acb-4caf-a7b9-4abc165b2f78 {http,https} \N \N {/s365-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+8af2c3ca-8d5b-4ddb-9ae9-627fe6003eb7 2022-05-26 09:04:33+00 2022-05-26 09:04:33+00 \N e238e1f2-7acb-4caf-a7b9-4abc165b2f78 {http,https} \N \N {/s365-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+3297507a-c132-4dc6-afc0-522dac9f4800 2022-05-26 09:04:33+00 2022-05-26 09:04:33+00 \N e238e1f2-7acb-4caf-a7b9-4abc165b2f78 {http,https} \N \N {/s365-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+1ddc042c-07c8-4789-9845-85c75efa01dd 2022-05-26 09:04:33+00 2022-05-26 09:04:33+00 \N e238e1f2-7acb-4caf-a7b9-4abc165b2f78 {http,https} \N \N {/s365-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+3cc542c4-4412-4796-bddb-83f17634ba53 2022-05-26 09:04:33+00 2022-05-26 09:04:33+00 \N 579dd648-5a51-4240-9901-d59ea046dbe4 {http,https} \N \N {/s366-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+329b4835-c874-4fc3-ac09-ab231af047dc 2022-05-26 09:04:33+00 2022-05-26 09:04:33+00 \N 579dd648-5a51-4240-9901-d59ea046dbe4 {http,https} \N \N {/s366-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+9a0fccd8-69ba-433e-ba8d-523307a4cc74 2022-05-26 09:04:33+00 2022-05-26 09:04:33+00 \N 579dd648-5a51-4240-9901-d59ea046dbe4 {http,https} \N \N {/s366-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+e04ee641-8b42-4049-8251-d5c5232028b7 2022-05-26 09:04:33+00 2022-05-26 09:04:33+00 \N 579dd648-5a51-4240-9901-d59ea046dbe4 {http,https} \N \N {/s366-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+97d3baf7-99fe-46ad-a9ad-594b44ccd95c 2022-05-26 09:04:33+00 2022-05-26 09:04:33+00 \N 363e3fd7-2510-4b88-8b61-19c6a701a154 {http,https} \N \N {/s367-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+c2c78b0c-5593-467d-803f-d81a08e52009 2022-05-26 09:04:33+00 2022-05-26 09:04:33+00 \N 363e3fd7-2510-4b88-8b61-19c6a701a154 {http,https} \N \N {/s367-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+51d4c327-304b-4082-acda-ec921b2f0452 2022-05-26 09:04:33+00 2022-05-26 09:04:33+00 \N 363e3fd7-2510-4b88-8b61-19c6a701a154 {http,https} \N \N {/s367-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+af0cc7e6-6754-45df-9398-858ec4b6374b 2022-05-26 09:04:33+00 2022-05-26 09:04:33+00 \N 363e3fd7-2510-4b88-8b61-19c6a701a154 {http,https} \N \N {/s367-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+51656063-1fd6-4352-851c-3d3fdce5f89b 2022-05-26 09:04:33+00 2022-05-26 09:04:33+00 \N 6bfe7e94-4211-492f-a9db-a6c81dd6f547 {http,https} \N \N {/s368-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+5467cdd0-7125-4043-be60-f219600c161b 2022-05-26 09:04:33+00 2022-05-26 09:04:33+00 \N 6bfe7e94-4211-492f-a9db-a6c81dd6f547 {http,https} \N \N {/s368-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+8f0a47c4-bbde-4c79-9277-eeb8d6572ef9 2022-05-26 09:04:33+00 2022-05-26 09:04:33+00 \N 6bfe7e94-4211-492f-a9db-a6c81dd6f547 {http,https} \N \N {/s368-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+dc6edc7c-3bcb-456e-a059-e6df5a1dd33a 2022-05-26 09:04:33+00 2022-05-26 09:04:33+00 \N 6bfe7e94-4211-492f-a9db-a6c81dd6f547 {http,https} \N \N {/s368-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+c454e2c3-b89f-447b-9ba5-373d57a15b13 2022-05-26 09:04:33+00 2022-05-26 09:04:33+00 \N 614a1279-a381-4be2-acef-301958e89071 {http,https} \N \N {/s369-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+cda42f89-9974-4193-8a36-05532d921f5c 2022-05-26 09:04:33+00 2022-05-26 09:04:33+00 \N 614a1279-a381-4be2-acef-301958e89071 {http,https} \N \N {/s369-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+315e9356-356c-4fb1-9c90-24f7036d918a 2022-05-26 09:04:33+00 2022-05-26 09:04:33+00 \N 614a1279-a381-4be2-acef-301958e89071 {http,https} \N \N {/s369-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+d5d61b12-65fb-40f9-8f6d-1a0f2a2d5d3b 2022-05-26 09:04:33+00 2022-05-26 09:04:33+00 \N 614a1279-a381-4be2-acef-301958e89071 {http,https} \N \N {/s369-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+221875af-ce48-49bd-9221-3041ed8b2c84 2022-05-26 09:04:33+00 2022-05-26 09:04:33+00 \N 3861f439-875f-453b-8651-03d9359f5788 {http,https} \N \N {/s370-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+8d6f924b-ac52-4b3f-9125-a82d6ced70ff 2022-05-26 09:04:33+00 2022-05-26 09:04:33+00 \N 3861f439-875f-453b-8651-03d9359f5788 {http,https} \N \N {/s370-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+77aec436-9027-467b-9173-542650d94bba 2022-05-26 09:04:33+00 2022-05-26 09:04:33+00 \N 3861f439-875f-453b-8651-03d9359f5788 {http,https} \N \N {/s370-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+61e5fbf8-5f7e-4d2c-ab9d-e3c04e78d006 2022-05-26 09:04:33+00 2022-05-26 09:04:33+00 \N 3861f439-875f-453b-8651-03d9359f5788 {http,https} \N \N {/s370-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+7f76d3d9-7ad2-4b50-b9db-79d2dbf488c7 2022-05-26 09:04:33+00 2022-05-26 09:04:33+00 \N 0663d4a9-d9d4-4d92-ab92-8ecae04c5440 {http,https} \N \N {/s371-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+939a8636-faeb-438f-9db7-3602974a6863 2022-05-26 09:04:33+00 2022-05-26 09:04:33+00 \N 0663d4a9-d9d4-4d92-ab92-8ecae04c5440 {http,https} \N \N {/s371-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+7f12304e-0c34-4598-94d5-efe0798f705a 2022-05-26 09:04:33+00 2022-05-26 09:04:33+00 \N 0663d4a9-d9d4-4d92-ab92-8ecae04c5440 {http,https} \N \N {/s371-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+f8a345b6-9917-411d-ad6d-e3e30387b9dc 2022-05-26 09:04:33+00 2022-05-26 09:04:33+00 \N 0663d4a9-d9d4-4d92-ab92-8ecae04c5440 {http,https} \N \N {/s371-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+413e7132-1858-41d9-ad19-d3c6fcf9cc8a 2022-05-26 09:04:33+00 2022-05-26 09:04:33+00 \N 00a04a0e-8a61-497e-a1b7-555d9edebd3c {http,https} \N \N {/s372-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+236a1762-301b-4970-aad7-42db64186ce2 2022-05-26 09:04:33+00 2022-05-26 09:04:33+00 \N 00a04a0e-8a61-497e-a1b7-555d9edebd3c {http,https} \N \N {/s372-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+1766c248-137a-4c64-917b-947cc9beed45 2022-05-26 09:04:33+00 2022-05-26 09:04:33+00 \N 00a04a0e-8a61-497e-a1b7-555d9edebd3c {http,https} \N \N {/s372-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+da45a0a2-a908-4513-a48b-e802b87306fa 2022-05-26 09:04:33+00 2022-05-26 09:04:33+00 \N 00a04a0e-8a61-497e-a1b7-555d9edebd3c {http,https} \N \N {/s372-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+61773a20-69d3-4493-be5a-28c141aa0d1e 2022-05-26 09:04:33+00 2022-05-26 09:04:33+00 \N a90836ba-dcb3-4f3f-bf2c-02bc1d5f7453 {http,https} \N \N {/s373-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+6862d7e7-6c8a-4a59-bc83-c12c67c58957 2022-05-26 09:04:33+00 2022-05-26 09:04:33+00 \N a90836ba-dcb3-4f3f-bf2c-02bc1d5f7453 {http,https} \N \N {/s373-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+2c68df09-0ba1-4d91-9503-b013453e457a 2022-05-26 09:04:33+00 2022-05-26 09:04:33+00 \N a90836ba-dcb3-4f3f-bf2c-02bc1d5f7453 {http,https} \N \N {/s373-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+bc03b311-d66f-4cf5-b822-d8455ba367e3 2022-05-26 09:04:33+00 2022-05-26 09:04:33+00 \N a90836ba-dcb3-4f3f-bf2c-02bc1d5f7453 {http,https} \N \N {/s373-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+de5dbba9-6119-483e-987c-fca0597b20cf 2022-05-26 09:04:33+00 2022-05-26 09:04:33+00 \N 001879e3-9e6a-49e1-8893-9bfa1ed0662f {http,https} \N \N {/s374-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+79ab012b-7a07-481e-af00-3e06f1f1f01c 2022-05-26 09:04:33+00 2022-05-26 09:04:33+00 \N 001879e3-9e6a-49e1-8893-9bfa1ed0662f {http,https} \N \N {/s374-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+6785d5f2-2915-4610-9ea4-d82c01cd5f56 2022-05-26 09:04:33+00 2022-05-26 09:04:33+00 \N 001879e3-9e6a-49e1-8893-9bfa1ed0662f {http,https} \N \N {/s374-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+648cd88c-5683-4638-bfb4-0e486bed189b 2022-05-26 09:04:33+00 2022-05-26 09:04:33+00 \N 001879e3-9e6a-49e1-8893-9bfa1ed0662f {http,https} \N \N {/s374-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+84052b2e-d59b-43b2-aaec-7fbd9f994cca 2022-05-26 09:04:33+00 2022-05-26 09:04:33+00 \N 3b864315-4410-47c4-8d1f-41340443be83 {http,https} \N \N {/s375-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+dfd5a62a-1225-4492-a107-5bcdb41b0156 2022-05-26 09:04:33+00 2022-05-26 09:04:33+00 \N 3b864315-4410-47c4-8d1f-41340443be83 {http,https} \N \N {/s375-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+11603845-42ab-429c-b7c2-1a9f41626e4b 2022-05-26 09:04:33+00 2022-05-26 09:04:33+00 \N 3b864315-4410-47c4-8d1f-41340443be83 {http,https} \N \N {/s375-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+dc441c3f-d83d-4b49-bc91-db810eb363df 2022-05-26 09:04:33+00 2022-05-26 09:04:33+00 \N 3b864315-4410-47c4-8d1f-41340443be83 {http,https} \N \N {/s375-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+6ad602ad-561f-4f7d-bfe5-fa790ce6a140 2022-05-26 09:04:33+00 2022-05-26 09:04:33+00 \N da92e9da-c205-44a5-8e55-6cabab24e221 {http,https} \N \N {/s376-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+bfcc5bbd-046f-4dfb-8ea1-7fbbd0424ca8 2022-05-26 09:04:33+00 2022-05-26 09:04:33+00 \N da92e9da-c205-44a5-8e55-6cabab24e221 {http,https} \N \N {/s376-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+8f98604e-a592-4420-b50d-7e3441327f39 2022-05-26 09:04:33+00 2022-05-26 09:04:33+00 \N da92e9da-c205-44a5-8e55-6cabab24e221 {http,https} \N \N {/s376-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+086aedad-4995-404b-bf04-79afc201db86 2022-05-26 09:04:33+00 2022-05-26 09:04:33+00 \N da92e9da-c205-44a5-8e55-6cabab24e221 {http,https} \N \N {/s376-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+6b566f60-9397-4951-9408-44f3b041d709 2022-05-26 09:04:33+00 2022-05-26 09:04:33+00 \N ec7a7ee9-84ef-4e7e-86dc-6c1ea5db4019 {http,https} \N \N {/s377-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+b9f69b21-4680-4dd6-b8d7-d29fcdd3d066 2022-05-26 09:04:33+00 2022-05-26 09:04:33+00 \N ec7a7ee9-84ef-4e7e-86dc-6c1ea5db4019 {http,https} \N \N {/s377-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+4ccd11ff-72de-4ceb-8011-83e4d93575b8 2022-05-26 09:04:33+00 2022-05-26 09:04:33+00 \N ec7a7ee9-84ef-4e7e-86dc-6c1ea5db4019 {http,https} \N \N {/s377-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+8990d95f-7246-45c8-ab26-d82f8e0b770c 2022-05-26 09:04:33+00 2022-05-26 09:04:33+00 \N ec7a7ee9-84ef-4e7e-86dc-6c1ea5db4019 {http,https} \N \N {/s377-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+f54a0c19-68fd-4523-9223-eb355b652ba2 2022-05-26 09:04:33+00 2022-05-26 09:04:33+00 \N de23c01f-138f-4b4f-b077-7966e5301849 {http,https} \N \N {/s378-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+22d2cc42-2fd1-44b9-bda6-4f18d81c4c69 2022-05-26 09:04:33+00 2022-05-26 09:04:33+00 \N de23c01f-138f-4b4f-b077-7966e5301849 {http,https} \N \N {/s378-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+8987a4e8-880e-45e9-a3f3-eb169357c337 2022-05-26 09:04:33+00 2022-05-26 09:04:33+00 \N de23c01f-138f-4b4f-b077-7966e5301849 {http,https} \N \N {/s378-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+80a62322-1d0c-48bf-b529-858c3dfce1a9 2022-05-26 09:04:33+00 2022-05-26 09:04:33+00 \N de23c01f-138f-4b4f-b077-7966e5301849 {http,https} \N \N {/s378-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+4af060f3-0c41-420e-8848-e19c64c4f68f 2022-05-26 09:04:33+00 2022-05-26 09:04:33+00 \N 2231820c-c6c6-4b43-8030-60d84ec840df {http,https} \N \N {/s379-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+7160fc2f-ede7-4559-89d4-6fe1a346cdd7 2022-05-26 09:04:33+00 2022-05-26 09:04:33+00 \N 2231820c-c6c6-4b43-8030-60d84ec840df {http,https} \N \N {/s379-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+7444991e-be0a-49e5-966e-af21ed179cd9 2022-05-26 09:04:33+00 2022-05-26 09:04:33+00 \N 2231820c-c6c6-4b43-8030-60d84ec840df {http,https} \N \N {/s379-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+2f37b85d-318b-42a0-a2e2-18f3a9487bf0 2022-05-26 09:04:33+00 2022-05-26 09:04:33+00 \N 2231820c-c6c6-4b43-8030-60d84ec840df {http,https} \N \N {/s379-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+952b4c5c-a71d-49ad-becd-3033f7703e18 2022-05-26 09:04:33+00 2022-05-26 09:04:33+00 \N 962b06e6-2702-4267-b103-b352f6b842a4 {http,https} \N \N {/s380-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+f2bed3e4-72ae-49a1-9263-a729dfb5b028 2022-05-26 09:04:33+00 2022-05-26 09:04:33+00 \N 962b06e6-2702-4267-b103-b352f6b842a4 {http,https} \N \N {/s380-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+85f3b168-600e-405a-b66b-ac2cfb321a81 2022-05-26 09:04:33+00 2022-05-26 09:04:33+00 \N 962b06e6-2702-4267-b103-b352f6b842a4 {http,https} \N \N {/s380-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+75cdeb50-abb0-4af0-872c-bafbf0c5a51a 2022-05-26 09:04:33+00 2022-05-26 09:04:33+00 \N 962b06e6-2702-4267-b103-b352f6b842a4 {http,https} \N \N {/s380-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+5213a1c8-19c7-444e-913c-42dfc02a09d0 2022-05-26 09:04:33+00 2022-05-26 09:04:33+00 \N 63bfee6a-6d44-4301-9cee-df0105f24f5e {http,https} \N \N {/s381-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+91e485c1-8fda-4a50-b1be-eda59a22fdc9 2022-05-26 09:04:33+00 2022-05-26 09:04:33+00 \N 63bfee6a-6d44-4301-9cee-df0105f24f5e {http,https} \N \N {/s381-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+c1a188ed-50c2-41ce-92de-d3831e736f71 2022-05-26 09:04:33+00 2022-05-26 09:04:33+00 \N 63bfee6a-6d44-4301-9cee-df0105f24f5e {http,https} \N \N {/s381-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+1dcfafc0-0ced-4655-aa29-1efd22877b90 2022-05-26 09:04:33+00 2022-05-26 09:04:33+00 \N 63bfee6a-6d44-4301-9cee-df0105f24f5e {http,https} \N \N {/s381-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+55d057c2-be1d-477b-a075-cb1bed856b8d 2022-05-26 09:04:33+00 2022-05-26 09:04:33+00 \N c6a5a31e-2c88-47c4-8e9a-c60bece7ef75 {http,https} \N \N {/s382-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+bd0377bd-ef7d-41eb-a086-2984063615a3 2022-05-26 09:04:33+00 2022-05-26 09:04:33+00 \N c6a5a31e-2c88-47c4-8e9a-c60bece7ef75 {http,https} \N \N {/s382-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+58903e6e-39b8-494c-b871-ea65c3aa5fb9 2022-05-26 09:04:33+00 2022-05-26 09:04:33+00 \N c6a5a31e-2c88-47c4-8e9a-c60bece7ef75 {http,https} \N \N {/s382-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+59f9b2e4-6dc6-476d-98b4-435519bb3953 2022-05-26 09:04:33+00 2022-05-26 09:04:33+00 \N c6a5a31e-2c88-47c4-8e9a-c60bece7ef75 {http,https} \N \N {/s382-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+8e388a1c-cc25-4156-ab6d-d94900121cb1 2022-05-26 09:04:33+00 2022-05-26 09:04:33+00 \N 2d096abd-ffb0-4143-96a4-7779218d6d4f {http,https} \N \N {/s383-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+e465856b-aa77-4837-9ef3-4f3789960415 2022-05-26 09:04:33+00 2022-05-26 09:04:33+00 \N 2d096abd-ffb0-4143-96a4-7779218d6d4f {http,https} \N \N {/s383-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+8870b0c2-6b31-4f3d-a09a-e8afb622a1bf 2022-05-26 09:04:33+00 2022-05-26 09:04:33+00 \N 2d096abd-ffb0-4143-96a4-7779218d6d4f {http,https} \N \N {/s383-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+985749b3-89f2-40bd-ac5a-fdbba81ebfd3 2022-05-26 09:04:33+00 2022-05-26 09:04:33+00 \N 2d096abd-ffb0-4143-96a4-7779218d6d4f {http,https} \N \N {/s383-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+1c1992eb-be64-4f77-aadb-9f2464687003 2022-05-26 09:04:33+00 2022-05-26 09:04:33+00 \N a10741c9-4ed7-422d-9f52-54c17c4bbd8b {http,https} \N \N {/s384-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+28bc0bf3-b497-4694-adf4-221e8c32fa50 2022-05-26 09:04:33+00 2022-05-26 09:04:33+00 \N a10741c9-4ed7-422d-9f52-54c17c4bbd8b {http,https} \N \N {/s384-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+0f6e5eb8-f2f9-4596-8dc6-d5798fbfcf17 2022-05-26 09:04:33+00 2022-05-26 09:04:33+00 \N a10741c9-4ed7-422d-9f52-54c17c4bbd8b {http,https} \N \N {/s384-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+c97b2ca4-3ed8-4bc5-b9e8-a0c964c62140 2022-05-26 09:04:33+00 2022-05-26 09:04:33+00 \N a10741c9-4ed7-422d-9f52-54c17c4bbd8b {http,https} \N \N {/s384-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+47fcf675-d1d9-49cd-91e6-5319a9868edb 2022-05-26 09:04:33+00 2022-05-26 09:04:33+00 \N 234c48dd-9af4-4099-80ff-40ad13f89401 {http,https} \N \N {/s385-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+558293de-13ea-42cc-b124-dc89484f8916 2022-05-26 09:04:33+00 2022-05-26 09:04:33+00 \N 234c48dd-9af4-4099-80ff-40ad13f89401 {http,https} \N \N {/s385-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+807fc65e-8053-4b45-9a2c-11358a86b215 2022-05-26 09:04:33+00 2022-05-26 09:04:33+00 \N 234c48dd-9af4-4099-80ff-40ad13f89401 {http,https} \N \N {/s385-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+de177505-cc95-424a-9848-e72f78b7e110 2022-05-26 09:04:33+00 2022-05-26 09:04:33+00 \N 234c48dd-9af4-4099-80ff-40ad13f89401 {http,https} \N \N {/s385-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+a821d074-d659-40af-8c2d-9366c9c6ff31 2022-05-26 09:04:33+00 2022-05-26 09:04:33+00 \N bb5d6545-d507-4b3a-ba24-bb510c914e95 {http,https} \N \N {/s386-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+ba20cb2d-25b7-4176-a6cf-da9395baec5b 2022-05-26 09:04:33+00 2022-05-26 09:04:33+00 \N bb5d6545-d507-4b3a-ba24-bb510c914e95 {http,https} \N \N {/s386-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+41460742-9989-43a7-a5f4-4bd454a02955 2022-05-26 09:04:33+00 2022-05-26 09:04:33+00 \N bb5d6545-d507-4b3a-ba24-bb510c914e95 {http,https} \N \N {/s386-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+c822b82c-79c3-42f9-ae1b-f83a03fc1049 2022-05-26 09:04:33+00 2022-05-26 09:04:33+00 \N bb5d6545-d507-4b3a-ba24-bb510c914e95 {http,https} \N \N {/s386-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+26d19423-642f-46c6-9160-62801b6619da 2022-05-26 09:04:33+00 2022-05-26 09:04:33+00 \N 28f712ea-c08c-4e7a-8cf9-4b13e36ff212 {http,https} \N \N {/s387-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+c4430fb6-cb22-4f3a-845d-b5f5f003f289 2022-05-26 09:04:33+00 2022-05-26 09:04:33+00 \N 28f712ea-c08c-4e7a-8cf9-4b13e36ff212 {http,https} \N \N {/s387-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+164f2566-d220-4140-84bc-3c66ff8e7cbd 2022-05-26 09:04:33+00 2022-05-26 09:04:33+00 \N 28f712ea-c08c-4e7a-8cf9-4b13e36ff212 {http,https} \N \N {/s387-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+6a524151-86f9-42e5-933d-405065d4afd3 2022-05-26 09:04:33+00 2022-05-26 09:04:33+00 \N 28f712ea-c08c-4e7a-8cf9-4b13e36ff212 {http,https} \N \N {/s387-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+e1ad3f70-d9cb-4bd7-9270-b7920adc4b7a 2022-05-26 09:04:33+00 2022-05-26 09:04:33+00 \N 152a5d0e-dc5a-44d9-af10-8ec63701dd3b {http,https} \N \N {/s388-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+33b555ad-42cb-4c55-8f0f-8da3a1ce5f9f 2022-05-26 09:04:33+00 2022-05-26 09:04:33+00 \N 152a5d0e-dc5a-44d9-af10-8ec63701dd3b {http,https} \N \N {/s388-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+c9ddcbe4-12d3-4a16-8c74-6aa16052471c 2022-05-26 09:04:33+00 2022-05-26 09:04:33+00 \N 152a5d0e-dc5a-44d9-af10-8ec63701dd3b {http,https} \N \N {/s388-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+4abc74ac-517c-47b3-9d56-f674a30936de 2022-05-26 09:04:33+00 2022-05-26 09:04:33+00 \N 152a5d0e-dc5a-44d9-af10-8ec63701dd3b {http,https} \N \N {/s388-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+b42fa17b-9260-464b-a19b-98299f7a0ea4 2022-05-26 09:04:33+00 2022-05-26 09:04:33+00 \N 93857261-5bcb-47aa-9144-22b35b135d4b {http,https} \N \N {/s389-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+b71c5ee8-da34-4fd1-ba89-60a80f125c9c 2022-05-26 09:04:33+00 2022-05-26 09:04:33+00 \N 93857261-5bcb-47aa-9144-22b35b135d4b {http,https} \N \N {/s389-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+ff3c9019-b6f6-4085-997b-a2fcefed7e6d 2022-05-26 09:04:33+00 2022-05-26 09:04:33+00 \N 93857261-5bcb-47aa-9144-22b35b135d4b {http,https} \N \N {/s389-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+9c082c36-8d43-4286-82c8-1f4bb9ec059c 2022-05-26 09:04:33+00 2022-05-26 09:04:33+00 \N 93857261-5bcb-47aa-9144-22b35b135d4b {http,https} \N \N {/s389-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+f5b00f8b-9254-41d8-82bb-25137f5c6da9 2022-05-26 09:04:33+00 2022-05-26 09:04:33+00 \N 111f99da-d06d-4cb3-b864-8f3e1f49aa74 {http,https} \N \N {/s390-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+9c740728-2ed9-436c-9862-685c2a4e8a25 2022-05-26 09:04:33+00 2022-05-26 09:04:33+00 \N 111f99da-d06d-4cb3-b864-8f3e1f49aa74 {http,https} \N \N {/s390-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+0cd81876-c603-43bd-85cb-02a03a3ad133 2022-05-26 09:04:33+00 2022-05-26 09:04:33+00 \N 111f99da-d06d-4cb3-b864-8f3e1f49aa74 {http,https} \N \N {/s390-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+be46714f-b556-4bb2-921d-f1d9987003ca 2022-05-26 09:04:33+00 2022-05-26 09:04:33+00 \N 111f99da-d06d-4cb3-b864-8f3e1f49aa74 {http,https} \N \N {/s390-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+f58d8f45-788f-4b3a-9f03-a3083fba70fa 2022-05-26 09:04:33+00 2022-05-26 09:04:33+00 \N 3924e923-d2f1-4275-8747-bd11ac4f74d3 {http,https} \N \N {/s391-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+3ec9e067-61d3-4020-b7c1-9be001df4d9c 2022-05-26 09:04:33+00 2022-05-26 09:04:33+00 \N 3924e923-d2f1-4275-8747-bd11ac4f74d3 {http,https} \N \N {/s391-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+d0c7488b-2fe5-4084-ac74-de4688c18b44 2022-05-26 09:04:33+00 2022-05-26 09:04:33+00 \N 3924e923-d2f1-4275-8747-bd11ac4f74d3 {http,https} \N \N {/s391-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+200bf282-ca7a-47a1-9345-ec0e38175963 2022-05-26 09:04:33+00 2022-05-26 09:04:33+00 \N 3924e923-d2f1-4275-8747-bd11ac4f74d3 {http,https} \N \N {/s391-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+3adb743f-2d77-46ec-84dc-2d0003b50d5f 2022-05-26 09:04:33+00 2022-05-26 09:04:33+00 \N a73038fe-4577-4639-a479-767f244244c3 {http,https} \N \N {/s392-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+22a08988-6063-4eee-bf9e-1b3e8aeeeb37 2022-05-26 09:04:33+00 2022-05-26 09:04:33+00 \N a73038fe-4577-4639-a479-767f244244c3 {http,https} \N \N {/s392-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+b8598f0b-f3b5-4806-b6fd-7c3e590d8775 2022-05-26 09:04:34+00 2022-05-26 09:04:34+00 \N a73038fe-4577-4639-a479-767f244244c3 {http,https} \N \N {/s392-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+2bb6a9b6-6da4-4b97-8cd0-b55ea0a031fc 2022-05-26 09:04:34+00 2022-05-26 09:04:34+00 \N a73038fe-4577-4639-a479-767f244244c3 {http,https} \N \N {/s392-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+436b0418-1a0c-4314-9b1e-b92b5268ac2d 2022-05-26 09:04:34+00 2022-05-26 09:04:34+00 \N 4a062dd6-f1c2-4b36-ac1d-998925eb0b83 {http,https} \N \N {/s393-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+a87ff715-320b-4f9a-a1c3-6e4f73e050d3 2022-05-26 09:04:34+00 2022-05-26 09:04:34+00 \N 4a062dd6-f1c2-4b36-ac1d-998925eb0b83 {http,https} \N \N {/s393-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+ca7d52dc-bfb7-42f3-95e7-837e002d7a8c 2022-05-26 09:04:34+00 2022-05-26 09:04:34+00 \N 4a062dd6-f1c2-4b36-ac1d-998925eb0b83 {http,https} \N \N {/s393-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+9416e2cc-af41-4618-b366-844246114c14 2022-05-26 09:04:34+00 2022-05-26 09:04:34+00 \N 4a062dd6-f1c2-4b36-ac1d-998925eb0b83 {http,https} \N \N {/s393-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+88efc63a-aaef-4ba5-a7e4-ad7e8d0c3b26 2022-05-26 09:04:34+00 2022-05-26 09:04:34+00 \N 8c475290-e87c-4711-a6ac-d2dc4028fad6 {http,https} \N \N {/s394-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+7a788b39-3ef4-4627-ba39-823ce3b3135e 2022-05-26 09:04:34+00 2022-05-26 09:04:34+00 \N 8c475290-e87c-4711-a6ac-d2dc4028fad6 {http,https} \N \N {/s394-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+d9a329b4-59e1-4d94-8c50-331df0da25e2 2022-05-26 09:04:34+00 2022-05-26 09:04:34+00 \N 8c475290-e87c-4711-a6ac-d2dc4028fad6 {http,https} \N \N {/s394-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+2f331ace-1d1b-4068-b543-a67043408803 2022-05-26 09:04:34+00 2022-05-26 09:04:34+00 \N 8c475290-e87c-4711-a6ac-d2dc4028fad6 {http,https} \N \N {/s394-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+eefd9468-e6b6-4f30-be8a-77e2da8d3c9f 2022-05-26 09:04:34+00 2022-05-26 09:04:34+00 \N 8cec9caf-f09c-4e50-ab29-a23009c77cb7 {http,https} \N \N {/s395-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+5adb33b8-3ec9-4c38-b64a-e7db42204bdf 2022-05-26 09:04:34+00 2022-05-26 09:04:34+00 \N 8cec9caf-f09c-4e50-ab29-a23009c77cb7 {http,https} \N \N {/s395-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+b0ee32c5-5e4f-43b5-aee6-77eb539e4961 2022-05-26 09:04:34+00 2022-05-26 09:04:34+00 \N 8cec9caf-f09c-4e50-ab29-a23009c77cb7 {http,https} \N \N {/s395-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+95c9a80f-5ab6-4364-8ca7-ec3080743b49 2022-05-26 09:04:34+00 2022-05-26 09:04:34+00 \N 8cec9caf-f09c-4e50-ab29-a23009c77cb7 {http,https} \N \N {/s395-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+deea16af-e5df-47aa-a869-414656ee2d30 2022-05-26 09:04:34+00 2022-05-26 09:04:34+00 \N 3a1b190c-0930-4404-bee0-eca6c7621114 {http,https} \N \N {/s396-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+ef7b4a9f-4ba5-408c-81b7-47ae27350a82 2022-05-26 09:04:34+00 2022-05-26 09:04:34+00 \N 3a1b190c-0930-4404-bee0-eca6c7621114 {http,https} \N \N {/s396-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+a8f75c71-0778-4453-8514-27df41e14a3b 2022-05-26 09:04:34+00 2022-05-26 09:04:34+00 \N 3a1b190c-0930-4404-bee0-eca6c7621114 {http,https} \N \N {/s396-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+08b777bf-d125-429b-8d28-48e909bf7f4b 2022-05-26 09:04:34+00 2022-05-26 09:04:34+00 \N 3a1b190c-0930-4404-bee0-eca6c7621114 {http,https} \N \N {/s396-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+28ab6b88-5d8e-4859-b882-9e82a00f460c 2022-05-26 09:04:34+00 2022-05-26 09:04:34+00 \N ccb26ed5-9dd0-46b3-8cb5-3584782c9d06 {http,https} \N \N {/s397-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+be3158c6-d0e2-45b9-928f-f0d96aa0867e 2022-05-26 09:04:34+00 2022-05-26 09:04:34+00 \N ccb26ed5-9dd0-46b3-8cb5-3584782c9d06 {http,https} \N \N {/s397-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+4bec0e71-22e6-4959-accb-e4e2019f392f 2022-05-26 09:04:34+00 2022-05-26 09:04:34+00 \N ccb26ed5-9dd0-46b3-8cb5-3584782c9d06 {http,https} \N \N {/s397-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+a539a7c1-ce69-4d1e-b467-33fd3d68b514 2022-05-26 09:04:34+00 2022-05-26 09:04:34+00 \N ccb26ed5-9dd0-46b3-8cb5-3584782c9d06 {http,https} \N \N {/s397-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+8bbbf888-17b3-4862-a1fd-9aa2063f6383 2022-05-26 09:04:34+00 2022-05-26 09:04:34+00 \N 6bce2b2a-c6a0-4463-9dfc-bd9366f62b3a {http,https} \N \N {/s398-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+62a54ead-af8e-4e0d-b316-e2ecf13627b9 2022-05-26 09:04:34+00 2022-05-26 09:04:34+00 \N 6bce2b2a-c6a0-4463-9dfc-bd9366f62b3a {http,https} \N \N {/s398-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+925c217c-669b-4111-8985-008e61aff1d4 2022-05-26 09:04:34+00 2022-05-26 09:04:34+00 \N 6bce2b2a-c6a0-4463-9dfc-bd9366f62b3a {http,https} \N \N {/s398-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+27ee97d0-2dc6-4cab-a807-6d96645e467e 2022-05-26 09:04:34+00 2022-05-26 09:04:34+00 \N 6bce2b2a-c6a0-4463-9dfc-bd9366f62b3a {http,https} \N \N {/s398-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+6d2e96e0-1a59-4290-92c6-cb1c8798aef1 2022-05-26 09:04:34+00 2022-05-26 09:04:34+00 \N 050c4646-3958-40b1-92f3-2a7979732b5b {http,https} \N \N {/s399-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+a696295f-4a96-4414-b113-a81d63435f8d 2022-05-26 09:04:34+00 2022-05-26 09:04:34+00 \N 050c4646-3958-40b1-92f3-2a7979732b5b {http,https} \N \N {/s399-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+36121b59-fcfb-4a14-8d31-ac9931afbdd5 2022-05-26 09:04:34+00 2022-05-26 09:04:34+00 \N 050c4646-3958-40b1-92f3-2a7979732b5b {http,https} \N \N {/s399-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+e8472a7d-4b68-40c7-9b60-41bccc7a189a 2022-05-26 09:04:34+00 2022-05-26 09:04:34+00 \N 050c4646-3958-40b1-92f3-2a7979732b5b {http,https} \N \N {/s399-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+0ad4944e-0971-4fbd-85ac-4ea55a56e14f 2022-05-26 09:04:34+00 2022-05-26 09:04:34+00 \N dfc084df-46cb-4a7e-b89c-b84ae3634ed3 {http,https} \N \N {/s400-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+658db0dc-6b0d-4559-9f6c-57d70b7792b2 2022-05-26 09:04:34+00 2022-05-26 09:04:34+00 \N dfc084df-46cb-4a7e-b89c-b84ae3634ed3 {http,https} \N \N {/s400-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+04a523c4-1983-47be-a1ab-b9ad0cb558e9 2022-05-26 09:04:34+00 2022-05-26 09:04:34+00 \N dfc084df-46cb-4a7e-b89c-b84ae3634ed3 {http,https} \N \N {/s400-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+d7a17d3f-b2d2-4d98-836d-8a07bbfdf567 2022-05-26 09:04:34+00 2022-05-26 09:04:34+00 \N dfc084df-46cb-4a7e-b89c-b84ae3634ed3 {http,https} \N \N {/s400-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+01f3f0ed-6b5c-46e2-9ecc-c63b5614179d 2022-05-26 09:04:34+00 2022-05-26 09:04:34+00 \N 5c96e4e4-bd3c-458a-aecb-70a0e97258d6 {http,https} \N \N {/s401-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+383e7800-07aa-4b13-9017-c7ecf8f75732 2022-05-26 09:04:34+00 2022-05-26 09:04:34+00 \N 5c96e4e4-bd3c-458a-aecb-70a0e97258d6 {http,https} \N \N {/s401-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+b50a2a4a-5e12-47a5-a60e-ea0da37a2f3d 2022-05-26 09:04:34+00 2022-05-26 09:04:34+00 \N 5c96e4e4-bd3c-458a-aecb-70a0e97258d6 {http,https} \N \N {/s401-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+8378a247-4321-4fa1-8d57-106eb3639f8f 2022-05-26 09:04:34+00 2022-05-26 09:04:34+00 \N 5c96e4e4-bd3c-458a-aecb-70a0e97258d6 {http,https} \N \N {/s401-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+5cd832f9-aa54-47b8-a52e-73e69a0e1718 2022-05-26 09:04:34+00 2022-05-26 09:04:34+00 \N 643ed9d5-7abd-498c-aa27-e54406f62657 {http,https} \N \N {/s402-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+2ba96167-2daa-413c-9b07-f9833307fa67 2022-05-26 09:04:34+00 2022-05-26 09:04:34+00 \N 643ed9d5-7abd-498c-aa27-e54406f62657 {http,https} \N \N {/s402-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+75c4eb2d-3511-4e86-9892-096bbde16d13 2022-05-26 09:04:34+00 2022-05-26 09:04:34+00 \N 643ed9d5-7abd-498c-aa27-e54406f62657 {http,https} \N \N {/s402-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+58874cf9-0216-4378-af62-dc7de48a36b8 2022-05-26 09:04:34+00 2022-05-26 09:04:34+00 \N 643ed9d5-7abd-498c-aa27-e54406f62657 {http,https} \N \N {/s402-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+cce66afe-de5b-4247-a04f-e464f62ed3d7 2022-05-26 09:04:34+00 2022-05-26 09:04:34+00 \N 3b43313b-92e3-4a71-89b9-5c94e508ffa4 {http,https} \N \N {/s403-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+6859a3a2-9ea5-423c-bf5c-6d9ac7355791 2022-05-26 09:04:34+00 2022-05-26 09:04:34+00 \N 3b43313b-92e3-4a71-89b9-5c94e508ffa4 {http,https} \N \N {/s403-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+52b0f641-c655-47d1-84e0-5ba8e8751e93 2022-05-26 09:04:34+00 2022-05-26 09:04:34+00 \N 3b43313b-92e3-4a71-89b9-5c94e508ffa4 {http,https} \N \N {/s403-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+ceacde02-edfb-4ae8-b4d5-10bc70de61d0 2022-05-26 09:04:34+00 2022-05-26 09:04:34+00 \N 3b43313b-92e3-4a71-89b9-5c94e508ffa4 {http,https} \N \N {/s403-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+7156e88a-d9d1-4315-9e1d-5c87a062eccf 2022-05-26 09:04:34+00 2022-05-26 09:04:34+00 \N d1f25d2e-1765-431d-b8ce-c971848c140b {http,https} \N \N {/s404-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+4dad8fd6-92f0-4661-bb90-98389477dd7d 2022-05-26 09:04:34+00 2022-05-26 09:04:34+00 \N d1f25d2e-1765-431d-b8ce-c971848c140b {http,https} \N \N {/s404-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+810fc05e-9ca1-4950-ba8d-a09b39187270 2022-05-26 09:04:34+00 2022-05-26 09:04:34+00 \N d1f25d2e-1765-431d-b8ce-c971848c140b {http,https} \N \N {/s404-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+aad96b96-b873-48f5-a8a3-1e6124df6216 2022-05-26 09:04:34+00 2022-05-26 09:04:34+00 \N d1f25d2e-1765-431d-b8ce-c971848c140b {http,https} \N \N {/s404-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+aa1f89cc-75a8-4a7b-8591-f3ba7c13529e 2022-05-26 09:04:34+00 2022-05-26 09:04:34+00 \N a986ba78-0f21-4714-98af-030c39a99d98 {http,https} \N \N {/s405-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+5f4b35db-1ab1-4866-8712-086f8e6a2fec 2022-05-26 09:04:34+00 2022-05-26 09:04:34+00 \N a986ba78-0f21-4714-98af-030c39a99d98 {http,https} \N \N {/s405-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+ccbcb619-83b4-4951-a41a-9e20ae65e251 2022-05-26 09:04:34+00 2022-05-26 09:04:34+00 \N a986ba78-0f21-4714-98af-030c39a99d98 {http,https} \N \N {/s405-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+08654641-6d0c-44b2-9c3c-5682b4bb1340 2022-05-26 09:04:34+00 2022-05-26 09:04:34+00 \N a986ba78-0f21-4714-98af-030c39a99d98 {http,https} \N \N {/s405-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+79a35cda-0cc2-418b-94ad-95dc57e1b093 2022-05-26 09:04:34+00 2022-05-26 09:04:34+00 \N 186d8c4f-7240-47be-baec-da9793982cfe {http,https} \N \N {/s406-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+9351be75-b763-44e2-9dde-c912c4e179f0 2022-05-26 09:04:34+00 2022-05-26 09:04:34+00 \N 186d8c4f-7240-47be-baec-da9793982cfe {http,https} \N \N {/s406-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+b1473c31-579d-4868-b517-22b046e8503d 2022-05-26 09:04:34+00 2022-05-26 09:04:34+00 \N 186d8c4f-7240-47be-baec-da9793982cfe {http,https} \N \N {/s406-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+b75a16d6-56a1-46b0-b96a-b765f4350017 2022-05-26 09:04:34+00 2022-05-26 09:04:34+00 \N 186d8c4f-7240-47be-baec-da9793982cfe {http,https} \N \N {/s406-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+97fb40c7-904c-4193-9be7-1abe23532019 2022-05-26 09:04:34+00 2022-05-26 09:04:34+00 \N 29eb0b4a-38c1-44e3-a342-a738f884bdb8 {http,https} \N \N {/s407-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+31220fad-7d79-49a6-bb67-2e941dfd3cd0 2022-05-26 09:04:34+00 2022-05-26 09:04:34+00 \N 29eb0b4a-38c1-44e3-a342-a738f884bdb8 {http,https} \N \N {/s407-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+53eb5882-367d-45ef-a7e5-440116bb92f8 2022-05-26 09:04:34+00 2022-05-26 09:04:34+00 \N 29eb0b4a-38c1-44e3-a342-a738f884bdb8 {http,https} \N \N {/s407-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+9bb107a2-7a71-488c-a15c-9177eb47cd45 2022-05-26 09:04:34+00 2022-05-26 09:04:34+00 \N 29eb0b4a-38c1-44e3-a342-a738f884bdb8 {http,https} \N \N {/s407-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+cce5650f-ebcf-4398-a62e-16ed830104a8 2022-05-26 09:04:34+00 2022-05-26 09:04:34+00 \N d6344072-d70a-419e-b400-f792fd7816a6 {http,https} \N \N {/s408-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+59d3a177-9f2d-4565-9a77-bfefcf96c164 2022-05-26 09:04:34+00 2022-05-26 09:04:34+00 \N d6344072-d70a-419e-b400-f792fd7816a6 {http,https} \N \N {/s408-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+a50c6467-7fb9-463a-a78e-5b02dde0a523 2022-05-26 09:04:34+00 2022-05-26 09:04:34+00 \N d6344072-d70a-419e-b400-f792fd7816a6 {http,https} \N \N {/s408-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+dcb58a4a-dc96-4a4b-9ff5-eb56fb81664e 2022-05-26 09:04:34+00 2022-05-26 09:04:34+00 \N d6344072-d70a-419e-b400-f792fd7816a6 {http,https} \N \N {/s408-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+67cd080f-6a50-41c7-bb3e-5774a3929944 2022-05-26 09:04:34+00 2022-05-26 09:04:34+00 \N 65dbc1e9-8bf0-4494-b3e7-c6b6445d805f {http,https} \N \N {/s409-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+a69e23c8-6161-41e4-8cd3-cc06b1ff2607 2022-05-26 09:04:34+00 2022-05-26 09:04:34+00 \N 65dbc1e9-8bf0-4494-b3e7-c6b6445d805f {http,https} \N \N {/s409-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+3ac795e6-ed24-498e-b72c-574e0ca1df09 2022-05-26 09:04:34+00 2022-05-26 09:04:34+00 \N 65dbc1e9-8bf0-4494-b3e7-c6b6445d805f {http,https} \N \N {/s409-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+8a88aef7-b902-4783-ad97-513428000f05 2022-05-26 09:04:34+00 2022-05-26 09:04:34+00 \N 65dbc1e9-8bf0-4494-b3e7-c6b6445d805f {http,https} \N \N {/s409-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+ca7ccc60-1ce1-42ea-9743-32e2cac6d156 2022-05-26 09:04:34+00 2022-05-26 09:04:34+00 \N 82e159a7-b83d-4eb9-9228-26eea20c0301 {http,https} \N \N {/s410-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+85f63859-375e-409c-a720-da75a13aaa26 2022-05-26 09:04:34+00 2022-05-26 09:04:34+00 \N 82e159a7-b83d-4eb9-9228-26eea20c0301 {http,https} \N \N {/s410-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+1eb10b28-b23b-4140-8e6b-065df19fc5e6 2022-05-26 09:04:34+00 2022-05-26 09:04:34+00 \N 82e159a7-b83d-4eb9-9228-26eea20c0301 {http,https} \N \N {/s410-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+f2fcc0d8-73f4-441f-ad80-3cf1b67420e4 2022-05-26 09:04:34+00 2022-05-26 09:04:34+00 \N 82e159a7-b83d-4eb9-9228-26eea20c0301 {http,https} \N \N {/s410-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+25020e19-af27-4047-9818-3b9ccf3f8d94 2022-05-26 09:04:34+00 2022-05-26 09:04:34+00 \N 85cab86c-ef60-4b00-ab3a-83649782cbdc {http,https} \N \N {/s411-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+ace35e0e-e5b0-42e8-a2d4-44cd4f6be88b 2022-05-26 09:04:34+00 2022-05-26 09:04:34+00 \N 85cab86c-ef60-4b00-ab3a-83649782cbdc {http,https} \N \N {/s411-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+2d9665e4-118d-4b7d-b402-92bf81971dbe 2022-05-26 09:04:34+00 2022-05-26 09:04:34+00 \N 85cab86c-ef60-4b00-ab3a-83649782cbdc {http,https} \N \N {/s411-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+b6d6b10f-87e1-4e17-b945-74f98c071448 2022-05-26 09:04:34+00 2022-05-26 09:04:34+00 \N 85cab86c-ef60-4b00-ab3a-83649782cbdc {http,https} \N \N {/s411-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+5840fd00-3446-43ab-bad9-e5f306bfd1fd 2022-05-26 09:04:34+00 2022-05-26 09:04:34+00 \N 6d8a4447-dba8-40c4-8fa3-9ea447aa4431 {http,https} \N \N {/s412-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+f2d6812b-9cee-4238-a979-97cb70f88e5a 2022-05-26 09:04:34+00 2022-05-26 09:04:34+00 \N 6d8a4447-dba8-40c4-8fa3-9ea447aa4431 {http,https} \N \N {/s412-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+81327c65-dbe9-499b-9c87-a4bf8d7e1af3 2022-05-26 09:04:34+00 2022-05-26 09:04:34+00 \N 6d8a4447-dba8-40c4-8fa3-9ea447aa4431 {http,https} \N \N {/s412-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+cd75f2c7-e8f4-4ace-9d06-816214d24dd2 2022-05-26 09:04:34+00 2022-05-26 09:04:34+00 \N 6d8a4447-dba8-40c4-8fa3-9ea447aa4431 {http,https} \N \N {/s412-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+56da08be-da5f-43b0-a57d-39c1c307bb99 2022-05-26 09:04:34+00 2022-05-26 09:04:34+00 \N 297aa958-dd8d-4838-8658-21c7a2f6a45c {http,https} \N \N {/s413-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+2b204232-7211-441c-9092-095417c7f065 2022-05-26 09:04:34+00 2022-05-26 09:04:34+00 \N 297aa958-dd8d-4838-8658-21c7a2f6a45c {http,https} \N \N {/s413-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+6eeadf66-273b-4782-a45d-549367043e38 2022-05-26 09:04:34+00 2022-05-26 09:04:34+00 \N 297aa958-dd8d-4838-8658-21c7a2f6a45c {http,https} \N \N {/s413-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+ac9d5b89-eae8-4f56-a14e-e4aa3cf0131d 2022-05-26 09:04:34+00 2022-05-26 09:04:34+00 \N 297aa958-dd8d-4838-8658-21c7a2f6a45c {http,https} \N \N {/s413-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+1b844bea-9033-4cb1-a2c6-634820fc8567 2022-05-26 09:04:34+00 2022-05-26 09:04:34+00 \N 516d1b3c-20ec-4abe-9d05-7c10f45cc2b7 {http,https} \N \N {/s414-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+461dfe4a-61f0-495b-86a7-8abb9e916648 2022-05-26 09:04:34+00 2022-05-26 09:04:34+00 \N 516d1b3c-20ec-4abe-9d05-7c10f45cc2b7 {http,https} \N \N {/s414-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+589265b9-2632-4803-9468-1c493ac14ca1 2022-05-26 09:04:34+00 2022-05-26 09:04:34+00 \N 516d1b3c-20ec-4abe-9d05-7c10f45cc2b7 {http,https} \N \N {/s414-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+88caa8a6-bffe-435b-8ee8-b13c57ec33d3 2022-05-26 09:04:34+00 2022-05-26 09:04:34+00 \N 516d1b3c-20ec-4abe-9d05-7c10f45cc2b7 {http,https} \N \N {/s414-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+bffd14fc-2aff-47ad-8329-0b031c57a7b6 2022-05-26 09:04:34+00 2022-05-26 09:04:34+00 \N c2cfb252-5288-4b94-b4a8-79a8d86e6c7c {http,https} \N \N {/s415-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+6cf6f30f-a166-46ca-b420-b4e42ead43ef 2022-05-26 09:04:34+00 2022-05-26 09:04:34+00 \N c2cfb252-5288-4b94-b4a8-79a8d86e6c7c {http,https} \N \N {/s415-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+4826ce43-fd72-4290-8f46-cf9079a64a9f 2022-05-26 09:04:34+00 2022-05-26 09:04:34+00 \N c2cfb252-5288-4b94-b4a8-79a8d86e6c7c {http,https} \N \N {/s415-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+0b5c2a84-bbf9-45ed-8c3d-1e6c35b5b9b5 2022-05-26 09:04:34+00 2022-05-26 09:04:34+00 \N c2cfb252-5288-4b94-b4a8-79a8d86e6c7c {http,https} \N \N {/s415-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+3be50a21-5eac-4560-84bf-35f16456257e 2022-05-26 09:04:34+00 2022-05-26 09:04:34+00 \N d32ddeef-adf4-43e5-b533-d6218f89194e {http,https} \N \N {/s416-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+2d1f7635-e80d-4a5c-ad59-754df502b60e 2022-05-26 09:04:34+00 2022-05-26 09:04:34+00 \N d32ddeef-adf4-43e5-b533-d6218f89194e {http,https} \N \N {/s416-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+83b4f771-9ac8-432f-be0b-cf7c5a233ad2 2022-05-26 09:04:34+00 2022-05-26 09:04:34+00 \N d32ddeef-adf4-43e5-b533-d6218f89194e {http,https} \N \N {/s416-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+fe612456-09ef-4714-a074-3c36de689640 2022-05-26 09:04:34+00 2022-05-26 09:04:34+00 \N d32ddeef-adf4-43e5-b533-d6218f89194e {http,https} \N \N {/s416-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+aad96364-6f16-4578-8419-c52d08be4016 2022-05-26 09:04:34+00 2022-05-26 09:04:34+00 \N d735e2a6-44ce-421b-8041-dbeac83b0388 {http,https} \N \N {/s417-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+37affbe9-c9f0-42da-801f-9af9480b5a36 2022-05-26 09:04:34+00 2022-05-26 09:04:34+00 \N d735e2a6-44ce-421b-8041-dbeac83b0388 {http,https} \N \N {/s417-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+a88dc384-982b-4a2c-9700-5bea758a85c9 2022-05-26 09:04:34+00 2022-05-26 09:04:34+00 \N d735e2a6-44ce-421b-8041-dbeac83b0388 {http,https} \N \N {/s417-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+a201d66f-a0fe-4f24-8f8e-55fccb90eb25 2022-05-26 09:04:34+00 2022-05-26 09:04:34+00 \N d735e2a6-44ce-421b-8041-dbeac83b0388 {http,https} \N \N {/s417-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+6a011f41-d99a-4836-8251-a0cec458068a 2022-05-26 09:04:34+00 2022-05-26 09:04:34+00 \N 2f34b698-bdc6-4a34-8568-54e2051c301e {http,https} \N \N {/s418-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+e4dad1df-04b0-4424-8fbe-53cf792ca530 2022-05-26 09:04:34+00 2022-05-26 09:04:34+00 \N 2f34b698-bdc6-4a34-8568-54e2051c301e {http,https} \N \N {/s418-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+27e08bdf-b6f2-4ff0-9dfd-988504c11433 2022-05-26 09:04:34+00 2022-05-26 09:04:34+00 \N 2f34b698-bdc6-4a34-8568-54e2051c301e {http,https} \N \N {/s418-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+b036ee57-36c2-49f1-a891-8220081f59b2 2022-05-26 09:04:34+00 2022-05-26 09:04:34+00 \N 2f34b698-bdc6-4a34-8568-54e2051c301e {http,https} \N \N {/s418-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+dba746b6-4d8b-4409-a15f-ae105f8026d7 2022-05-26 09:04:34+00 2022-05-26 09:04:34+00 \N 1f25c2c5-b997-474a-82c0-2dfe225b38f7 {http,https} \N \N {/s419-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+1bf6a5c3-ee00-4360-b6eb-001a12606257 2022-05-26 09:04:34+00 2022-05-26 09:04:34+00 \N 1f25c2c5-b997-474a-82c0-2dfe225b38f7 {http,https} \N \N {/s419-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+c0da6fdb-0e2f-47dc-8bb4-783b40b8bf72 2022-05-26 09:04:34+00 2022-05-26 09:04:34+00 \N 1f25c2c5-b997-474a-82c0-2dfe225b38f7 {http,https} \N \N {/s419-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+c0c748a3-e6bc-4f94-bcbd-26bd0b618c12 2022-05-26 09:04:34+00 2022-05-26 09:04:34+00 \N 1f25c2c5-b997-474a-82c0-2dfe225b38f7 {http,https} \N \N {/s419-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+25094cba-976c-462d-8390-050eecf804b2 2022-05-26 09:04:34+00 2022-05-26 09:04:34+00 \N 409a0334-ad83-4abe-92bf-9f86cee8e629 {http,https} \N \N {/s420-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+7d875813-49ed-48dd-bb45-95d895ca75dc 2022-05-26 09:04:34+00 2022-05-26 09:04:34+00 \N 409a0334-ad83-4abe-92bf-9f86cee8e629 {http,https} \N \N {/s420-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+8a9c3865-8bf4-42d0-8aec-705dfd492387 2022-05-26 09:04:34+00 2022-05-26 09:04:34+00 \N 409a0334-ad83-4abe-92bf-9f86cee8e629 {http,https} \N \N {/s420-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+6d3efc16-1557-486c-a580-f1405863b379 2022-05-26 09:04:34+00 2022-05-26 09:04:34+00 \N 409a0334-ad83-4abe-92bf-9f86cee8e629 {http,https} \N \N {/s420-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+685ef39a-44c3-4ff3-a80f-8aede0d29716 2022-05-26 09:04:34+00 2022-05-26 09:04:34+00 \N 21a86be9-f740-47d6-aef6-ea678179d442 {http,https} \N \N {/s421-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+42b9812d-1e90-4173-91fe-b5644dc092e1 2022-05-26 09:04:34+00 2022-05-26 09:04:34+00 \N 21a86be9-f740-47d6-aef6-ea678179d442 {http,https} \N \N {/s421-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+862e1cc2-612c-4983-9398-e31d24a74769 2022-05-26 09:04:35+00 2022-05-26 09:04:35+00 \N 21a86be9-f740-47d6-aef6-ea678179d442 {http,https} \N \N {/s421-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+31eb93b2-8cbf-4b74-9b40-2042c7ff1d4a 2022-05-26 09:04:35+00 2022-05-26 09:04:35+00 \N 21a86be9-f740-47d6-aef6-ea678179d442 {http,https} \N \N {/s421-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+e246e51f-3229-4a29-9591-35c9aedc356d 2022-05-26 09:04:35+00 2022-05-26 09:04:35+00 \N dc85040e-5868-4e67-99ae-ae2a83870651 {http,https} \N \N {/s422-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+9e975049-6e6c-46b3-8bd9-a8fbdf47b77e 2022-05-26 09:04:35+00 2022-05-26 09:04:35+00 \N dc85040e-5868-4e67-99ae-ae2a83870651 {http,https} \N \N {/s422-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+6003dc95-e8af-43c6-a916-108476ee2294 2022-05-26 09:04:35+00 2022-05-26 09:04:35+00 \N dc85040e-5868-4e67-99ae-ae2a83870651 {http,https} \N \N {/s422-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+a3af20e5-798e-40ce-a257-e2a3bc9601f0 2022-05-26 09:04:35+00 2022-05-26 09:04:35+00 \N dc85040e-5868-4e67-99ae-ae2a83870651 {http,https} \N \N {/s422-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+796f20e9-9fee-4a38-9ed3-3f878dac9b09 2022-05-26 09:04:35+00 2022-05-26 09:04:35+00 \N 83f56af1-9785-4627-8682-5d9f40d9e567 {http,https} \N \N {/s423-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+ce65c939-d17b-4abf-ac74-c04354726e3c 2022-05-26 09:04:35+00 2022-05-26 09:04:35+00 \N 83f56af1-9785-4627-8682-5d9f40d9e567 {http,https} \N \N {/s423-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+3df3e212-70a4-4f03-a487-572fd89c5b9d 2022-05-26 09:04:35+00 2022-05-26 09:04:35+00 \N 83f56af1-9785-4627-8682-5d9f40d9e567 {http,https} \N \N {/s423-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+9281a796-531f-4f56-8e2b-e82ad80f6ab4 2022-05-26 09:04:35+00 2022-05-26 09:04:35+00 \N 83f56af1-9785-4627-8682-5d9f40d9e567 {http,https} \N \N {/s423-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+f4178e3d-327c-4d18-9705-98327d29fb4d 2022-05-26 09:04:35+00 2022-05-26 09:04:35+00 \N b8670494-46f7-4ac6-a67b-92662a89eabb {http,https} \N \N {/s424-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+9b193f7e-3e1f-47ce-81cb-baa11abad8ea 2022-05-26 09:04:35+00 2022-05-26 09:04:35+00 \N b8670494-46f7-4ac6-a67b-92662a89eabb {http,https} \N \N {/s424-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+5040e3e7-b96c-4ff0-8aaa-2dae06704791 2022-05-26 09:04:35+00 2022-05-26 09:04:35+00 \N b8670494-46f7-4ac6-a67b-92662a89eabb {http,https} \N \N {/s424-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+68ba6e34-a781-4a8b-882e-03fac53367f0 2022-05-26 09:04:35+00 2022-05-26 09:04:35+00 \N b8670494-46f7-4ac6-a67b-92662a89eabb {http,https} \N \N {/s424-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+332a858f-f03c-4230-83e8-ef08961739f2 2022-05-26 09:04:35+00 2022-05-26 09:04:35+00 \N cb4d87c3-1fb7-4b16-8094-eed4a3d00968 {http,https} \N \N {/s425-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+63e6bf30-2271-4d34-aac3-ad36fb6a4a24 2022-05-26 09:04:35+00 2022-05-26 09:04:35+00 \N cb4d87c3-1fb7-4b16-8094-eed4a3d00968 {http,https} \N \N {/s425-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+ce5b9cdc-4973-41bc-9b31-34cabf0a6669 2022-05-26 09:04:35+00 2022-05-26 09:04:35+00 \N cb4d87c3-1fb7-4b16-8094-eed4a3d00968 {http,https} \N \N {/s425-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+b68588d8-d53c-4392-8611-94ab67eacc14 2022-05-26 09:04:35+00 2022-05-26 09:04:35+00 \N cb4d87c3-1fb7-4b16-8094-eed4a3d00968 {http,https} \N \N {/s425-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+8f2108d5-5006-483f-98c0-ea742be4e801 2022-05-26 09:04:35+00 2022-05-26 09:04:35+00 \N 106044fb-fc87-41f6-9e71-3faffe47e00b {http,https} \N \N {/s426-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+ed520698-3eb3-49b7-807d-d398e8c386f5 2022-05-26 09:04:35+00 2022-05-26 09:04:35+00 \N 106044fb-fc87-41f6-9e71-3faffe47e00b {http,https} \N \N {/s426-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+bfcb594c-3473-41ae-92aa-949571895fdf 2022-05-26 09:04:35+00 2022-05-26 09:04:35+00 \N 106044fb-fc87-41f6-9e71-3faffe47e00b {http,https} \N \N {/s426-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+602701ea-004a-440f-8b32-0de658928841 2022-05-26 09:04:35+00 2022-05-26 09:04:35+00 \N 106044fb-fc87-41f6-9e71-3faffe47e00b {http,https} \N \N {/s426-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+44779b09-653d-43fb-977a-ab86d3bedb55 2022-05-26 09:04:35+00 2022-05-26 09:04:35+00 \N a88fd1e2-7344-47b5-a7b8-9bd716f94c5d {http,https} \N \N {/s427-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+9cbabfe0-14c9-44bf-8380-9d21ce4e8c78 2022-05-26 09:04:35+00 2022-05-26 09:04:35+00 \N a88fd1e2-7344-47b5-a7b8-9bd716f94c5d {http,https} \N \N {/s427-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+a898c036-f030-4347-b629-5d26221d2807 2022-05-26 09:04:35+00 2022-05-26 09:04:35+00 \N a88fd1e2-7344-47b5-a7b8-9bd716f94c5d {http,https} \N \N {/s427-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+ddb74d4c-be57-4411-83d6-a6f9b593bf5d 2022-05-26 09:04:35+00 2022-05-26 09:04:35+00 \N a88fd1e2-7344-47b5-a7b8-9bd716f94c5d {http,https} \N \N {/s427-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+3dd511df-0974-4fa4-812b-d617d0aa4e7b 2022-05-26 09:04:35+00 2022-05-26 09:04:35+00 \N 53f91d1f-e644-4040-bb9c-009b94cdb8e8 {http,https} \N \N {/s428-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+73058d2b-ceef-486a-8e20-53287ebe6b97 2022-05-26 09:04:35+00 2022-05-26 09:04:35+00 \N 53f91d1f-e644-4040-bb9c-009b94cdb8e8 {http,https} \N \N {/s428-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+16a20100-ef5a-4412-b1e6-7bdb520fd215 2022-05-26 09:04:35+00 2022-05-26 09:04:35+00 \N 53f91d1f-e644-4040-bb9c-009b94cdb8e8 {http,https} \N \N {/s428-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+d22c3097-4d54-4e65-a3ff-e422785ea684 2022-05-26 09:04:35+00 2022-05-26 09:04:35+00 \N 53f91d1f-e644-4040-bb9c-009b94cdb8e8 {http,https} \N \N {/s428-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+baec13c8-483c-47eb-9412-5003efcf5560 2022-05-26 09:04:35+00 2022-05-26 09:04:35+00 \N dd07fe79-a01b-4e7e-b0d7-2556523cb39e {http,https} \N \N {/s429-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+f0d48392-1ee3-442d-956b-4e1be1bfb2ea 2022-05-26 09:04:35+00 2022-05-26 09:04:35+00 \N dd07fe79-a01b-4e7e-b0d7-2556523cb39e {http,https} \N \N {/s429-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+928a6194-6852-444c-8321-6679bc4d116f 2022-05-26 09:04:35+00 2022-05-26 09:04:35+00 \N dd07fe79-a01b-4e7e-b0d7-2556523cb39e {http,https} \N \N {/s429-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+aa93e1d0-2e0e-4f62-9bb7-979e28c18105 2022-05-26 09:04:35+00 2022-05-26 09:04:35+00 \N dd07fe79-a01b-4e7e-b0d7-2556523cb39e {http,https} \N \N {/s429-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+64bde6f9-51c5-4e41-817f-d1c55f5f65cb 2022-05-26 09:04:35+00 2022-05-26 09:04:35+00 \N b2faf9ae-52e2-4dae-a484-7e9978de7057 {http,https} \N \N {/s430-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+de4e4f36-bc95-4fd1-954f-4a239a006a0f 2022-05-26 09:04:35+00 2022-05-26 09:04:35+00 \N b2faf9ae-52e2-4dae-a484-7e9978de7057 {http,https} \N \N {/s430-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+035f23a4-99bc-48b6-934e-273cbeb4c4c3 2022-05-26 09:04:35+00 2022-05-26 09:04:35+00 \N b2faf9ae-52e2-4dae-a484-7e9978de7057 {http,https} \N \N {/s430-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+d96f636c-6524-48d1-94c3-cb08066fddb7 2022-05-26 09:04:35+00 2022-05-26 09:04:35+00 \N b2faf9ae-52e2-4dae-a484-7e9978de7057 {http,https} \N \N {/s430-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+22f8a8a0-fc47-4b1d-9c43-cda860699f25 2022-05-26 09:04:35+00 2022-05-26 09:04:35+00 \N 587584bd-581c-4ec6-90a4-4196ebe3e639 {http,https} \N \N {/s431-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+6f35e1eb-6957-48c2-8b9d-e67189a74e29 2022-05-26 09:04:35+00 2022-05-26 09:04:35+00 \N 587584bd-581c-4ec6-90a4-4196ebe3e639 {http,https} \N \N {/s431-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+699001c3-4b00-43c7-a34e-4c1efa3f910b 2022-05-26 09:04:35+00 2022-05-26 09:04:35+00 \N 587584bd-581c-4ec6-90a4-4196ebe3e639 {http,https} \N \N {/s431-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+c9bd1d4c-bd11-409b-9991-de547fa66154 2022-05-26 09:04:35+00 2022-05-26 09:04:35+00 \N 587584bd-581c-4ec6-90a4-4196ebe3e639 {http,https} \N \N {/s431-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+629efa23-6418-428c-9232-056dae0f8a8f 2022-05-26 09:04:35+00 2022-05-26 09:04:35+00 \N c1e06d08-f053-4e2f-98cb-dfe2b4523fc8 {http,https} \N \N {/s432-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+9c8aeeb6-88fd-4512-97a2-b1344be5c973 2022-05-26 09:04:35+00 2022-05-26 09:04:35+00 \N c1e06d08-f053-4e2f-98cb-dfe2b4523fc8 {http,https} \N \N {/s432-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+d08ec189-3c74-48b0-93ef-a6f37a1bf514 2022-05-26 09:04:35+00 2022-05-26 09:04:35+00 \N c1e06d08-f053-4e2f-98cb-dfe2b4523fc8 {http,https} \N \N {/s432-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+8a5e88bd-38cd-46dc-b77c-995a49f1c0fc 2022-05-26 09:04:35+00 2022-05-26 09:04:35+00 \N c1e06d08-f053-4e2f-98cb-dfe2b4523fc8 {http,https} \N \N {/s432-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+b4522141-769c-463e-b461-34a464626121 2022-05-26 09:04:35+00 2022-05-26 09:04:35+00 \N ce17ffbe-39d4-4bba-badd-3fd6a51a909b {http,https} \N \N {/s433-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+a42961ef-d801-4810-9521-c0e5b00d39fd 2022-05-26 09:04:35+00 2022-05-26 09:04:35+00 \N ce17ffbe-39d4-4bba-badd-3fd6a51a909b {http,https} \N \N {/s433-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+8a83f503-9745-474b-a1e8-a323ab9111ff 2022-05-26 09:04:35+00 2022-05-26 09:04:35+00 \N ce17ffbe-39d4-4bba-badd-3fd6a51a909b {http,https} \N \N {/s433-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+2fa6dc93-4a07-426d-abe9-57ab379ac1be 2022-05-26 09:04:35+00 2022-05-26 09:04:35+00 \N ce17ffbe-39d4-4bba-badd-3fd6a51a909b {http,https} \N \N {/s433-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+fe5e88e8-cda5-41ad-af58-514648c3fb53 2022-05-26 09:04:35+00 2022-05-26 09:04:35+00 \N df0f28b8-833d-4962-9750-0e2c7dcf1aef {http,https} \N \N {/s434-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+0ccffa33-9e36-46be-a1e1-95703d57c087 2022-05-26 09:04:35+00 2022-05-26 09:04:35+00 \N df0f28b8-833d-4962-9750-0e2c7dcf1aef {http,https} \N \N {/s434-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+3897b977-24b3-4d61-aeb7-5da41eea369f 2022-05-26 09:04:35+00 2022-05-26 09:04:35+00 \N df0f28b8-833d-4962-9750-0e2c7dcf1aef {http,https} \N \N {/s434-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+d3964655-3562-449c-a996-188d928e4416 2022-05-26 09:04:35+00 2022-05-26 09:04:35+00 \N df0f28b8-833d-4962-9750-0e2c7dcf1aef {http,https} \N \N {/s434-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+95226f06-eaa4-4eb5-b0e2-97446f6eaf10 2022-05-26 09:04:35+00 2022-05-26 09:04:35+00 \N 42463594-07f9-463b-8d3d-e640679cf9a0 {http,https} \N \N {/s435-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+4b35e94a-4a4f-42ff-b535-87a2c952f8f9 2022-05-26 09:04:35+00 2022-05-26 09:04:35+00 \N 42463594-07f9-463b-8d3d-e640679cf9a0 {http,https} \N \N {/s435-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+de996ae3-1009-4904-b43f-a8c0719eb142 2022-05-26 09:04:35+00 2022-05-26 09:04:35+00 \N 42463594-07f9-463b-8d3d-e640679cf9a0 {http,https} \N \N {/s435-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+c29cd9ce-c6df-4966-b9d9-3113cba54214 2022-05-26 09:04:35+00 2022-05-26 09:04:35+00 \N 42463594-07f9-463b-8d3d-e640679cf9a0 {http,https} \N \N {/s435-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+ac266bff-33ea-4308-98ee-3feffbf0c68d 2022-05-26 09:04:35+00 2022-05-26 09:04:35+00 \N 8dc13325-56ce-4b86-bd36-b090b0f6caab {http,https} \N \N {/s436-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+d96be58d-b781-4fe9-aa94-cce5025d99d1 2022-05-26 09:04:35+00 2022-05-26 09:04:35+00 \N 8dc13325-56ce-4b86-bd36-b090b0f6caab {http,https} \N \N {/s436-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+f82a40d3-42fd-45ad-bb65-5d2518933867 2022-05-26 09:04:35+00 2022-05-26 09:04:35+00 \N 8dc13325-56ce-4b86-bd36-b090b0f6caab {http,https} \N \N {/s436-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+c60a482b-ce4e-45f2-a927-f92bf18fbb0e 2022-05-26 09:04:35+00 2022-05-26 09:04:35+00 \N 8dc13325-56ce-4b86-bd36-b090b0f6caab {http,https} \N \N {/s436-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+f4b22302-a261-4a49-ba01-82de71cb8f1f 2022-05-26 09:04:35+00 2022-05-26 09:04:35+00 \N c629d453-a5a6-431f-8f90-9b27722a415a {http,https} \N \N {/s437-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+2e9e6753-7e85-41fd-8d1f-9adb3928d74f 2022-05-26 09:04:35+00 2022-05-26 09:04:35+00 \N c629d453-a5a6-431f-8f90-9b27722a415a {http,https} \N \N {/s437-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+1dc1dbe7-a85c-4a9f-90bd-8d65c484021f 2022-05-26 09:04:35+00 2022-05-26 09:04:35+00 \N c629d453-a5a6-431f-8f90-9b27722a415a {http,https} \N \N {/s437-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+fc73c2b0-4025-4f15-83fb-6dc460aa2f7e 2022-05-26 09:04:35+00 2022-05-26 09:04:35+00 \N c629d453-a5a6-431f-8f90-9b27722a415a {http,https} \N \N {/s437-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+9e369f00-4fc8-4576-a55f-ae12f08a9dfa 2022-05-26 09:04:35+00 2022-05-26 09:04:35+00 \N c265592f-8adf-4f8c-bb4f-1b4a984dc600 {http,https} \N \N {/s438-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+b2dff9b6-1050-4831-aff0-a556b5f3dfc9 2022-05-26 09:04:35+00 2022-05-26 09:04:35+00 \N c265592f-8adf-4f8c-bb4f-1b4a984dc600 {http,https} \N \N {/s438-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+b874a1d4-7d08-4c7b-bf16-d7388c0000dc 2022-05-26 09:04:35+00 2022-05-26 09:04:35+00 \N c265592f-8adf-4f8c-bb4f-1b4a984dc600 {http,https} \N \N {/s438-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+037fdcd7-d5af-4e8e-a79b-0282ff6720fb 2022-05-26 09:04:35+00 2022-05-26 09:04:35+00 \N c265592f-8adf-4f8c-bb4f-1b4a984dc600 {http,https} \N \N {/s438-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+ef456973-296b-4562-8e2e-5cf6fd081f6d 2022-05-26 09:04:35+00 2022-05-26 09:04:35+00 \N bbfadf44-58fe-4693-9f6b-f1897ad92eb6 {http,https} \N \N {/s439-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+441cf7fb-a81c-44de-b667-2cd0b0e4ec83 2022-05-26 09:04:35+00 2022-05-26 09:04:35+00 \N bbfadf44-58fe-4693-9f6b-f1897ad92eb6 {http,https} \N \N {/s439-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+1b04ac64-689f-43f1-9466-3157ac0f0a95 2022-05-26 09:04:35+00 2022-05-26 09:04:35+00 \N bbfadf44-58fe-4693-9f6b-f1897ad92eb6 {http,https} \N \N {/s439-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+f8d12639-4bc3-4d83-a10d-501c0ea50549 2022-05-26 09:04:35+00 2022-05-26 09:04:35+00 \N bbfadf44-58fe-4693-9f6b-f1897ad92eb6 {http,https} \N \N {/s439-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+30a2db7d-800f-4719-8562-168dc1286507 2022-05-26 09:04:35+00 2022-05-26 09:04:35+00 \N 515bf1e2-6b17-448a-ad26-6276526a88c2 {http,https} \N \N {/s440-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+845b106b-35b7-48f5-875c-e384c6f6b67e 2022-05-26 09:04:35+00 2022-05-26 09:04:35+00 \N 515bf1e2-6b17-448a-ad26-6276526a88c2 {http,https} \N \N {/s440-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+27955626-cbbc-42bd-815b-02e0234af5a8 2022-05-26 09:04:35+00 2022-05-26 09:04:35+00 \N 515bf1e2-6b17-448a-ad26-6276526a88c2 {http,https} \N \N {/s440-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+bda33765-6241-4fed-b4d7-b633ce66428f 2022-05-26 09:04:35+00 2022-05-26 09:04:35+00 \N 515bf1e2-6b17-448a-ad26-6276526a88c2 {http,https} \N \N {/s440-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+eb478595-1abe-4bc9-885f-042cf6130695 2022-05-26 09:04:35+00 2022-05-26 09:04:35+00 \N 4f1086b3-8849-4d42-a9fb-5395f1cb573f {http,https} \N \N {/s441-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+aabb4603-89c3-4e74-b1ba-35c3db96b301 2022-05-26 09:04:35+00 2022-05-26 09:04:35+00 \N 4f1086b3-8849-4d42-a9fb-5395f1cb573f {http,https} \N \N {/s441-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+e28134da-413b-450c-a399-87a783ce54ae 2022-05-26 09:04:35+00 2022-05-26 09:04:35+00 \N 4f1086b3-8849-4d42-a9fb-5395f1cb573f {http,https} \N \N {/s441-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+7302f741-b7c4-428c-85f2-3b1c47203038 2022-05-26 09:04:35+00 2022-05-26 09:04:35+00 \N 4f1086b3-8849-4d42-a9fb-5395f1cb573f {http,https} \N \N {/s441-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+a02b0fe6-a210-4190-8ec7-e056824aa9d0 2022-05-26 09:04:35+00 2022-05-26 09:04:35+00 \N d0e54e7a-8475-44f5-af06-0852acc18ada {http,https} \N \N {/s442-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+8e100cd5-ee9e-4f65-b059-5ae366597489 2022-05-26 09:04:35+00 2022-05-26 09:04:35+00 \N d0e54e7a-8475-44f5-af06-0852acc18ada {http,https} \N \N {/s442-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+8df16482-225a-4078-81fa-dad84e01abc4 2022-05-26 09:04:35+00 2022-05-26 09:04:35+00 \N d0e54e7a-8475-44f5-af06-0852acc18ada {http,https} \N \N {/s442-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+35cd220d-170f-42ed-a7ff-c69afcc9bf50 2022-05-26 09:04:35+00 2022-05-26 09:04:35+00 \N d0e54e7a-8475-44f5-af06-0852acc18ada {http,https} \N \N {/s442-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+2005f03c-633c-47b1-a600-d074ac298f1d 2022-05-26 09:04:35+00 2022-05-26 09:04:35+00 \N cedaaa13-f4a0-4aa1-86bd-29f20d10cb17 {http,https} \N \N {/s443-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+63e91ee0-15fe-4538-8b7d-f10744a01e85 2022-05-26 09:04:35+00 2022-05-26 09:04:35+00 \N cedaaa13-f4a0-4aa1-86bd-29f20d10cb17 {http,https} \N \N {/s443-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+8a42d4d9-6676-4b9b-9500-6f9eb4a9450e 2022-05-26 09:04:35+00 2022-05-26 09:04:35+00 \N cedaaa13-f4a0-4aa1-86bd-29f20d10cb17 {http,https} \N \N {/s443-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+0c772d39-7359-4978-aac2-efa3e9266682 2022-05-26 09:04:35+00 2022-05-26 09:04:35+00 \N cedaaa13-f4a0-4aa1-86bd-29f20d10cb17 {http,https} \N \N {/s443-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+0a2a695a-b01b-4105-89a8-46dc8936cc92 2022-05-26 09:04:35+00 2022-05-26 09:04:35+00 \N af2095eb-cb46-45e8-8e62-23c528e8451c {http,https} \N \N {/s444-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+5dca14c8-a7b0-4944-b7f7-08ffaaf9ca84 2022-05-26 09:04:35+00 2022-05-26 09:04:35+00 \N af2095eb-cb46-45e8-8e62-23c528e8451c {http,https} \N \N {/s444-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+39518705-d1ee-4023-b9c5-1bf33d9cfd6a 2022-05-26 09:04:35+00 2022-05-26 09:04:35+00 \N af2095eb-cb46-45e8-8e62-23c528e8451c {http,https} \N \N {/s444-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+acf1ec7f-8f26-4733-9d8b-599a71f0748b 2022-05-26 09:04:35+00 2022-05-26 09:04:35+00 \N af2095eb-cb46-45e8-8e62-23c528e8451c {http,https} \N \N {/s444-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+cbc05dd0-bea4-4a26-a13e-34c90f60c3db 2022-05-26 09:04:35+00 2022-05-26 09:04:35+00 \N 39f8b870-e4a7-4f7c-93ba-7354ffdc3b7a {http,https} \N \N {/s445-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+e97f6a04-5013-4d19-85af-d9bb2304e9b7 2022-05-26 09:04:35+00 2022-05-26 09:04:35+00 \N 39f8b870-e4a7-4f7c-93ba-7354ffdc3b7a {http,https} \N \N {/s445-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+d63846ed-e5c6-4141-acf1-2fb001179132 2022-05-26 09:04:35+00 2022-05-26 09:04:35+00 \N 39f8b870-e4a7-4f7c-93ba-7354ffdc3b7a {http,https} \N \N {/s445-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+3bf553f4-1aea-44f6-b75a-0ddcd8e4994e 2022-05-26 09:04:35+00 2022-05-26 09:04:35+00 \N 39f8b870-e4a7-4f7c-93ba-7354ffdc3b7a {http,https} \N \N {/s445-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+693f2f3a-0157-4896-948c-d964c4fe7d63 2022-05-26 09:04:35+00 2022-05-26 09:04:35+00 \N 8b196676-5e99-4ffb-9cf7-e59dd42c9b61 {http,https} \N \N {/s446-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+6a6f8a21-e961-4362-9394-d0ed942b768f 2022-05-26 09:04:35+00 2022-05-26 09:04:35+00 \N 8b196676-5e99-4ffb-9cf7-e59dd42c9b61 {http,https} \N \N {/s446-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+18859324-0c22-40f3-8c10-d3d9c8b6aeb9 2022-05-26 09:04:35+00 2022-05-26 09:04:35+00 \N 8b196676-5e99-4ffb-9cf7-e59dd42c9b61 {http,https} \N \N {/s446-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+4bf7f1a5-5102-48bc-a4de-89fe1fb6d450 2022-05-26 09:04:35+00 2022-05-26 09:04:35+00 \N 8b196676-5e99-4ffb-9cf7-e59dd42c9b61 {http,https} \N \N {/s446-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+716db20a-f3e6-4c4e-a3ec-39b98c272af5 2022-05-26 09:04:35+00 2022-05-26 09:04:35+00 \N 3ed2e405-1166-499d-84ca-abf27c4420d6 {http,https} \N \N {/s447-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+92ee91d3-befa-4eea-8f02-a6659f9bbe50 2022-05-26 09:04:35+00 2022-05-26 09:04:35+00 \N 3ed2e405-1166-499d-84ca-abf27c4420d6 {http,https} \N \N {/s447-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+c79bbbe1-a759-45fe-9c43-c05981da2b52 2022-05-26 09:04:35+00 2022-05-26 09:04:35+00 \N 3ed2e405-1166-499d-84ca-abf27c4420d6 {http,https} \N \N {/s447-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+a23b9326-baac-4524-bafd-cf431f8acf92 2022-05-26 09:04:35+00 2022-05-26 09:04:35+00 \N 3ed2e405-1166-499d-84ca-abf27c4420d6 {http,https} \N \N {/s447-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+ea7be992-3302-4778-b897-82fab2848357 2022-05-26 09:04:35+00 2022-05-26 09:04:35+00 \N 6e94f9f7-f322-4be2-a6e3-25220b00d9f6 {http,https} \N \N {/s448-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+7d0f8aee-48aa-416b-b844-1324475985b2 2022-05-26 09:04:35+00 2022-05-26 09:04:35+00 \N 6e94f9f7-f322-4be2-a6e3-25220b00d9f6 {http,https} \N \N {/s448-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+a3ab15b6-a233-4720-b0ce-18f5d52f616d 2022-05-26 09:04:35+00 2022-05-26 09:04:35+00 \N 6e94f9f7-f322-4be2-a6e3-25220b00d9f6 {http,https} \N \N {/s448-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+982884e2-8b41-442f-9520-7b5c7bfbc734 2022-05-26 09:04:35+00 2022-05-26 09:04:35+00 \N 6e94f9f7-f322-4be2-a6e3-25220b00d9f6 {http,https} \N \N {/s448-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+1299cf5e-49fe-4346-815e-f355b5c47a2f 2022-05-26 09:04:35+00 2022-05-26 09:04:35+00 \N 2ee7b426-001c-4f81-a4b9-f5f6e94dacd9 {http,https} \N \N {/s449-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+f3743842-c6ff-464e-9876-5f4f09826103 2022-05-26 09:04:35+00 2022-05-26 09:04:35+00 \N 2ee7b426-001c-4f81-a4b9-f5f6e94dacd9 {http,https} \N \N {/s449-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+4d3e31d6-54c9-4457-a9fa-42d1d798d474 2022-05-26 09:04:35+00 2022-05-26 09:04:35+00 \N 2ee7b426-001c-4f81-a4b9-f5f6e94dacd9 {http,https} \N \N {/s449-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+5cc5a134-3225-4ffe-9e54-cb108db54ff9 2022-05-26 09:04:35+00 2022-05-26 09:04:35+00 \N 2ee7b426-001c-4f81-a4b9-f5f6e94dacd9 {http,https} \N \N {/s449-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+74a99ab8-12cf-42ef-98ae-bab2200d712d 2022-05-26 09:04:35+00 2022-05-26 09:04:35+00 \N c235ddd9-4a8b-4ed4-996d-f32d97c2febf {http,https} \N \N {/s450-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+7b6edd61-322c-4014-b0eb-ba31540657d3 2022-05-26 09:04:35+00 2022-05-26 09:04:35+00 \N c235ddd9-4a8b-4ed4-996d-f32d97c2febf {http,https} \N \N {/s450-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+5f5c4836-3803-4015-9df3-d4701d9da5f5 2022-05-26 09:04:35+00 2022-05-26 09:04:35+00 \N c235ddd9-4a8b-4ed4-996d-f32d97c2febf {http,https} \N \N {/s450-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+8e9069f5-1f20-4b38-9a10-61bf35aa17b2 2022-05-26 09:04:35+00 2022-05-26 09:04:35+00 \N c235ddd9-4a8b-4ed4-996d-f32d97c2febf {http,https} \N \N {/s450-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+d5391c92-a824-48d8-acb5-afb842d854d4 2022-05-26 09:04:35+00 2022-05-26 09:04:35+00 \N 3443f990-ed97-482a-b60d-f9a4fae6dce7 {http,https} \N \N {/s451-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+e674c13d-c97b-40ad-912b-0b3ddbafbc1b 2022-05-26 09:04:36+00 2022-05-26 09:04:36+00 \N 3443f990-ed97-482a-b60d-f9a4fae6dce7 {http,https} \N \N {/s451-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+b168028b-8819-4141-8ed7-840efb851df0 2022-05-26 09:04:36+00 2022-05-26 09:04:36+00 \N 3443f990-ed97-482a-b60d-f9a4fae6dce7 {http,https} \N \N {/s451-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+459abb4f-1140-44e4-8155-03a2031b3f0c 2022-05-26 09:04:36+00 2022-05-26 09:04:36+00 \N 3443f990-ed97-482a-b60d-f9a4fae6dce7 {http,https} \N \N {/s451-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+a15175ec-ed00-4bc7-a9f1-feda48fa738e 2022-05-26 09:04:36+00 2022-05-26 09:04:36+00 \N bf3887ae-ebac-4278-aa88-b211be9a6ef4 {http,https} \N \N {/s452-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+2b703033-8e5c-40f9-aca8-f3482b927a07 2022-05-26 09:04:36+00 2022-05-26 09:04:36+00 \N bf3887ae-ebac-4278-aa88-b211be9a6ef4 {http,https} \N \N {/s452-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+362732aa-8820-46f1-ad5a-11088daf1d95 2022-05-26 09:04:36+00 2022-05-26 09:04:36+00 \N bf3887ae-ebac-4278-aa88-b211be9a6ef4 {http,https} \N \N {/s452-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+a4067a1b-a7de-4444-bb97-d3f20f9d922e 2022-05-26 09:04:36+00 2022-05-26 09:04:36+00 \N bf3887ae-ebac-4278-aa88-b211be9a6ef4 {http,https} \N \N {/s452-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+1828cabb-c68f-493f-b289-e03040fb5bca 2022-05-26 09:04:36+00 2022-05-26 09:04:36+00 \N f5db483a-11d5-4fb7-b977-ddb1b55b6923 {http,https} \N \N {/s453-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+e2121668-7f21-4951-81a0-315e7104858c 2022-05-26 09:04:36+00 2022-05-26 09:04:36+00 \N f5db483a-11d5-4fb7-b977-ddb1b55b6923 {http,https} \N \N {/s453-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+5f900b38-e6e0-419f-87cb-dc18ef0fc407 2022-05-26 09:04:36+00 2022-05-26 09:04:36+00 \N f5db483a-11d5-4fb7-b977-ddb1b55b6923 {http,https} \N \N {/s453-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+e0e09eaa-0951-4d65-b0bb-43076d4d659e 2022-05-26 09:04:36+00 2022-05-26 09:04:36+00 \N f5db483a-11d5-4fb7-b977-ddb1b55b6923 {http,https} \N \N {/s453-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+cfc3836f-6a6e-4b12-8b40-872258301b4a 2022-05-26 09:04:36+00 2022-05-26 09:04:36+00 \N 7560adfa-0d51-42e6-b727-78821e9404f8 {http,https} \N \N {/s454-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+c75d182b-0b2e-450e-ae09-213438cd85aa 2022-05-26 09:04:36+00 2022-05-26 09:04:36+00 \N 7560adfa-0d51-42e6-b727-78821e9404f8 {http,https} \N \N {/s454-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+24d8a298-f52e-4f92-8a0d-b8804c489376 2022-05-26 09:04:36+00 2022-05-26 09:04:36+00 \N 7560adfa-0d51-42e6-b727-78821e9404f8 {http,https} \N \N {/s454-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+83ca008b-c45f-40fc-a7e3-76e161eebb31 2022-05-26 09:04:36+00 2022-05-26 09:04:36+00 \N 7560adfa-0d51-42e6-b727-78821e9404f8 {http,https} \N \N {/s454-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+7b5bb779-02ea-446d-97d7-31d60246df94 2022-05-26 09:04:36+00 2022-05-26 09:04:36+00 \N efe7075c-0084-4620-976d-57dcbaf3893b {http,https} \N \N {/s455-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+a3a831ec-aab7-4f9c-910b-2baf43fffceb 2022-05-26 09:04:36+00 2022-05-26 09:04:36+00 \N efe7075c-0084-4620-976d-57dcbaf3893b {http,https} \N \N {/s455-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+d80258d8-4588-41ad-8d2e-b092e995f875 2022-05-26 09:04:36+00 2022-05-26 09:04:36+00 \N efe7075c-0084-4620-976d-57dcbaf3893b {http,https} \N \N {/s455-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+fb82fc75-0533-4801-8826-d9ef4c07b9fa 2022-05-26 09:04:36+00 2022-05-26 09:04:36+00 \N efe7075c-0084-4620-976d-57dcbaf3893b {http,https} \N \N {/s455-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+b5f48d1e-4613-42d3-adc0-3917b542dc8c 2022-05-26 09:04:36+00 2022-05-26 09:04:36+00 \N f062ee0d-1d60-4ac5-bf80-fad59a54306f {http,https} \N \N {/s456-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+fc84f22c-9877-4151-866e-4611f73aba61 2022-05-26 09:04:36+00 2022-05-26 09:04:36+00 \N f062ee0d-1d60-4ac5-bf80-fad59a54306f {http,https} \N \N {/s456-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+9eb2fb93-7229-4f2d-b719-0ea3ae35732e 2022-05-26 09:04:36+00 2022-05-26 09:04:36+00 \N f062ee0d-1d60-4ac5-bf80-fad59a54306f {http,https} \N \N {/s456-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+b9205cd6-7d62-498e-a7e4-934491693c89 2022-05-26 09:04:36+00 2022-05-26 09:04:36+00 \N f062ee0d-1d60-4ac5-bf80-fad59a54306f {http,https} \N \N {/s456-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+f5e72d25-7288-4835-bb58-b9b46844e186 2022-05-26 09:04:36+00 2022-05-26 09:04:36+00 \N 838a3bbf-b6e9-4174-9e2f-4c5903f85b51 {http,https} \N \N {/s457-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+c058491d-f008-4be7-b154-c2080f177cdf 2022-05-26 09:04:36+00 2022-05-26 09:04:36+00 \N 838a3bbf-b6e9-4174-9e2f-4c5903f85b51 {http,https} \N \N {/s457-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+75dc36cc-8f3b-4130-a3f9-d7c75704107f 2022-05-26 09:04:36+00 2022-05-26 09:04:36+00 \N 838a3bbf-b6e9-4174-9e2f-4c5903f85b51 {http,https} \N \N {/s457-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+1e37f25f-37e4-493a-9401-0f11e083923d 2022-05-26 09:04:36+00 2022-05-26 09:04:36+00 \N 838a3bbf-b6e9-4174-9e2f-4c5903f85b51 {http,https} \N \N {/s457-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+9ef8a655-ac65-46e8-ab96-98a5ca2d687b 2022-05-26 09:04:36+00 2022-05-26 09:04:36+00 \N 1813a575-32ba-4c94-99a5-19295b0921de {http,https} \N \N {/s458-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+21a0ed20-8689-42d8-b1bc-3d949638ffc7 2022-05-26 09:04:36+00 2022-05-26 09:04:36+00 \N 1813a575-32ba-4c94-99a5-19295b0921de {http,https} \N \N {/s458-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+880c58b3-ea22-4f40-9e81-98b5ba83f64d 2022-05-26 09:04:36+00 2022-05-26 09:04:36+00 \N 1813a575-32ba-4c94-99a5-19295b0921de {http,https} \N \N {/s458-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+22d3e5b0-d209-4248-ad44-5e8308287366 2022-05-26 09:04:36+00 2022-05-26 09:04:36+00 \N 1813a575-32ba-4c94-99a5-19295b0921de {http,https} \N \N {/s458-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+0bac6e77-a2ed-48f8-a22e-47289c607c67 2022-05-26 09:04:36+00 2022-05-26 09:04:36+00 \N 7aff390f-97f8-4e64-9b95-c85a9002c33c {http,https} \N \N {/s459-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+31e10549-c69a-4a12-8fee-ec0980eff22d 2022-05-26 09:04:36+00 2022-05-26 09:04:36+00 \N 7aff390f-97f8-4e64-9b95-c85a9002c33c {http,https} \N \N {/s459-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+1157895c-0bc6-4e8e-aca8-3cacfb38a2e3 2022-05-26 09:04:36+00 2022-05-26 09:04:36+00 \N 7aff390f-97f8-4e64-9b95-c85a9002c33c {http,https} \N \N {/s459-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+ed80a6be-75c3-40a7-9260-e37b02953e21 2022-05-26 09:04:36+00 2022-05-26 09:04:36+00 \N 7aff390f-97f8-4e64-9b95-c85a9002c33c {http,https} \N \N {/s459-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+11fa8193-b685-4daa-818f-050e1ee78a94 2022-05-26 09:04:36+00 2022-05-26 09:04:36+00 \N c6298096-10b7-441c-9688-4695b88a8660 {http,https} \N \N {/s460-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+3487f8a1-8c7d-43a1-8841-0bcdba3367cf 2022-05-26 09:04:36+00 2022-05-26 09:04:36+00 \N c6298096-10b7-441c-9688-4695b88a8660 {http,https} \N \N {/s460-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+8d19797e-fdaf-4506-ac6e-9e0f4ee38b2e 2022-05-26 09:04:36+00 2022-05-26 09:04:36+00 \N c6298096-10b7-441c-9688-4695b88a8660 {http,https} \N \N {/s460-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+31cc408d-655a-459b-a9ab-3199d73bcf8a 2022-05-26 09:04:36+00 2022-05-26 09:04:36+00 \N c6298096-10b7-441c-9688-4695b88a8660 {http,https} \N \N {/s460-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+a428bb72-a27d-4ec7-8bf1-bed2c543b6f7 2022-05-26 09:04:36+00 2022-05-26 09:04:36+00 \N dada2f21-3866-4778-a319-a91f82f8ad76 {http,https} \N \N {/s461-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+c97ce96e-a8c1-4637-9dfd-1c416ae616a5 2022-05-26 09:04:36+00 2022-05-26 09:04:36+00 \N dada2f21-3866-4778-a319-a91f82f8ad76 {http,https} \N \N {/s461-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+9384c3e2-f1e1-4854-83df-d11f9b30344e 2022-05-26 09:04:36+00 2022-05-26 09:04:36+00 \N dada2f21-3866-4778-a319-a91f82f8ad76 {http,https} \N \N {/s461-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+070b854f-a709-428c-808b-c2f116c28254 2022-05-26 09:04:36+00 2022-05-26 09:04:36+00 \N dada2f21-3866-4778-a319-a91f82f8ad76 {http,https} \N \N {/s461-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+8a09c21e-38a6-4b36-9127-314d6e6c3b72 2022-05-26 09:04:36+00 2022-05-26 09:04:36+00 \N f5016d6d-f10c-4846-83d5-7bf231c044d3 {http,https} \N \N {/s462-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+5d98f7d4-5de2-4f9c-84fe-fdb3236bd303 2022-05-26 09:04:36+00 2022-05-26 09:04:36+00 \N f5016d6d-f10c-4846-83d5-7bf231c044d3 {http,https} \N \N {/s462-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+f0176518-e3ae-4658-ac29-dc59f29c2485 2022-05-26 09:04:36+00 2022-05-26 09:04:36+00 \N f5016d6d-f10c-4846-83d5-7bf231c044d3 {http,https} \N \N {/s462-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+93e08cc0-3fb4-4bd4-9592-adce2a1684e4 2022-05-26 09:04:36+00 2022-05-26 09:04:36+00 \N f5016d6d-f10c-4846-83d5-7bf231c044d3 {http,https} \N \N {/s462-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+6ad81b72-200f-454c-ae5f-6a817a257a55 2022-05-26 09:04:36+00 2022-05-26 09:04:36+00 \N 7463f25e-841f-4e23-9fb3-4dbe0c2554d2 {http,https} \N \N {/s463-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+dc92a638-89e7-4677-afa7-2a8cb7ee9ab4 2022-05-26 09:04:36+00 2022-05-26 09:04:36+00 \N 7463f25e-841f-4e23-9fb3-4dbe0c2554d2 {http,https} \N \N {/s463-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+22f79c49-0d58-4997-a244-a38f94acce12 2022-05-26 09:04:36+00 2022-05-26 09:04:36+00 \N 7463f25e-841f-4e23-9fb3-4dbe0c2554d2 {http,https} \N \N {/s463-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+409dbe83-1650-4149-9b40-8d03aaf9b607 2022-05-26 09:04:36+00 2022-05-26 09:04:36+00 \N 7463f25e-841f-4e23-9fb3-4dbe0c2554d2 {http,https} \N \N {/s463-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+4ddaca3a-02d7-4ea8-a73c-762cfa3462b6 2022-05-26 09:04:36+00 2022-05-26 09:04:36+00 \N 1e87a29f-8009-41bd-8b71-f8800f1dab1e {http,https} \N \N {/s464-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+ddb714fc-1535-49cb-8590-96b4553fa6f4 2022-05-26 09:04:36+00 2022-05-26 09:04:36+00 \N 1e87a29f-8009-41bd-8b71-f8800f1dab1e {http,https} \N \N {/s464-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+19fb2a92-672b-49f1-a1e5-7c95e865ee76 2022-05-26 09:04:36+00 2022-05-26 09:04:36+00 \N 1e87a29f-8009-41bd-8b71-f8800f1dab1e {http,https} \N \N {/s464-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+57e61c94-cd64-4669-a33b-4a6105a034cf 2022-05-26 09:04:36+00 2022-05-26 09:04:36+00 \N 1e87a29f-8009-41bd-8b71-f8800f1dab1e {http,https} \N \N {/s464-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+3bc338fe-1d42-499e-817f-98c71292d864 2022-05-26 09:04:36+00 2022-05-26 09:04:36+00 \N 30e14345-9d6a-42c1-b33f-59cb014e5b68 {http,https} \N \N {/s465-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+2ea78bee-9b42-4346-9900-57400da07b37 2022-05-26 09:04:36+00 2022-05-26 09:04:36+00 \N 30e14345-9d6a-42c1-b33f-59cb014e5b68 {http,https} \N \N {/s465-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+caeb38de-87f3-47fc-8222-508d38f7c660 2022-05-26 09:04:36+00 2022-05-26 09:04:36+00 \N 30e14345-9d6a-42c1-b33f-59cb014e5b68 {http,https} \N \N {/s465-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+13bfbc09-4bc2-4b21-9c51-c75df526211c 2022-05-26 09:04:36+00 2022-05-26 09:04:36+00 \N 30e14345-9d6a-42c1-b33f-59cb014e5b68 {http,https} \N \N {/s465-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+92cc82f5-3599-4cc9-b5fc-43fca3c9dceb 2022-05-26 09:04:36+00 2022-05-26 09:04:36+00 \N 86c6fa66-322e-487a-8999-ecc03a830fd3 {http,https} \N \N {/s466-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+92e36d2d-f87c-45f1-a324-70453d608e51 2022-05-26 09:04:36+00 2022-05-26 09:04:36+00 \N 86c6fa66-322e-487a-8999-ecc03a830fd3 {http,https} \N \N {/s466-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+1b1c60ca-05d2-4415-b2ff-3cbddde1e5a4 2022-05-26 09:04:36+00 2022-05-26 09:04:36+00 \N 86c6fa66-322e-487a-8999-ecc03a830fd3 {http,https} \N \N {/s466-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+c3677645-9805-4e82-af47-e9a963d16091 2022-05-26 09:04:36+00 2022-05-26 09:04:36+00 \N 86c6fa66-322e-487a-8999-ecc03a830fd3 {http,https} \N \N {/s466-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+3c7e10fe-1939-4813-ab29-e4795edbc5ff 2022-05-26 09:04:36+00 2022-05-26 09:04:36+00 \N 35847d15-de55-4a1b-9493-0d691a83a641 {http,https} \N \N {/s467-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+693b8d67-5d36-40fe-89ec-3a53b4272463 2022-05-26 09:04:36+00 2022-05-26 09:04:36+00 \N 35847d15-de55-4a1b-9493-0d691a83a641 {http,https} \N \N {/s467-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+e49b36e7-fef7-4ba3-890d-c5471138f2ed 2022-05-26 09:04:36+00 2022-05-26 09:04:36+00 \N 35847d15-de55-4a1b-9493-0d691a83a641 {http,https} \N \N {/s467-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+4cf67451-f2aa-4974-b700-30a8951866a8 2022-05-26 09:04:36+00 2022-05-26 09:04:36+00 \N 35847d15-de55-4a1b-9493-0d691a83a641 {http,https} \N \N {/s467-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+ca6253c1-3a62-413e-b97a-43399244e3ff 2022-05-26 09:04:36+00 2022-05-26 09:04:36+00 \N f18b3241-50bd-45b5-8c61-8858473e10fb {http,https} \N \N {/s468-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+5e8377b3-4bcb-4fb9-b7b1-2013d0645ec7 2022-05-26 09:04:36+00 2022-05-26 09:04:36+00 \N f18b3241-50bd-45b5-8c61-8858473e10fb {http,https} \N \N {/s468-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+1df52a05-4f48-4af3-8cdf-0da33141a4e9 2022-05-26 09:04:36+00 2022-05-26 09:04:36+00 \N f18b3241-50bd-45b5-8c61-8858473e10fb {http,https} \N \N {/s468-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+283da355-d78e-415c-851a-165af8070103 2022-05-26 09:04:36+00 2022-05-26 09:04:36+00 \N f18b3241-50bd-45b5-8c61-8858473e10fb {http,https} \N \N {/s468-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+d46e10e2-5c30-4fad-af2b-3e31ce034d6d 2022-05-26 09:04:36+00 2022-05-26 09:04:36+00 \N 3f90d40a-eef1-4a6b-953c-6919087c9b6b {http,https} \N \N {/s469-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+5ef1787b-24ec-4a50-93d7-e6c2175201a0 2022-05-26 09:04:36+00 2022-05-26 09:04:36+00 \N 3f90d40a-eef1-4a6b-953c-6919087c9b6b {http,https} \N \N {/s469-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+902f1a1e-26f0-49d6-bdb0-ac94d57085b4 2022-05-26 09:04:36+00 2022-05-26 09:04:36+00 \N 3f90d40a-eef1-4a6b-953c-6919087c9b6b {http,https} \N \N {/s469-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+0d4245e3-e09f-47f6-8e85-095dca32ab4e 2022-05-26 09:04:36+00 2022-05-26 09:04:36+00 \N 3f90d40a-eef1-4a6b-953c-6919087c9b6b {http,https} \N \N {/s469-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+3e4ca35e-f94b-458d-a588-668c78320040 2022-05-26 09:04:36+00 2022-05-26 09:04:36+00 \N c81f7cfe-c388-4731-88f9-f3eccc0e1aae {http,https} \N \N {/s470-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+afb9c5ec-ad49-458f-87da-8f9e74ebce0d 2022-05-26 09:04:36+00 2022-05-26 09:04:36+00 \N c81f7cfe-c388-4731-88f9-f3eccc0e1aae {http,https} \N \N {/s470-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+abd31258-aa72-4fe1-bdff-397abfb64934 2022-05-26 09:04:36+00 2022-05-26 09:04:36+00 \N c81f7cfe-c388-4731-88f9-f3eccc0e1aae {http,https} \N \N {/s470-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+6c86a7a6-e243-41da-bbd8-c34bba6381f0 2022-05-26 09:04:36+00 2022-05-26 09:04:36+00 \N c81f7cfe-c388-4731-88f9-f3eccc0e1aae {http,https} \N \N {/s470-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+30b83f00-8969-44f5-87c2-f88e886a7bc8 2022-05-26 09:04:36+00 2022-05-26 09:04:36+00 \N 54f45fd9-b956-4dd8-a9a2-aa025395fe9b {http,https} \N \N {/s471-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+4f579d4b-bfab-42f0-bf5e-92ba2891066b 2022-05-26 09:04:36+00 2022-05-26 09:04:36+00 \N 54f45fd9-b956-4dd8-a9a2-aa025395fe9b {http,https} \N \N {/s471-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+ef8bf65e-0847-410b-97b8-78a140284248 2022-05-26 09:04:36+00 2022-05-26 09:04:36+00 \N 54f45fd9-b956-4dd8-a9a2-aa025395fe9b {http,https} \N \N {/s471-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+9e71f4aa-f7fc-4a66-9e87-840479699e8d 2022-05-26 09:04:36+00 2022-05-26 09:04:36+00 \N 54f45fd9-b956-4dd8-a9a2-aa025395fe9b {http,https} \N \N {/s471-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+91131f39-d683-4f10-abdb-c8ee69fe26a2 2022-05-26 09:04:36+00 2022-05-26 09:04:36+00 \N f0f92b13-e8a2-4208-af35-88c2f57053ed {http,https} \N \N {/s472-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+534e8382-13c5-4bf2-b7b5-b665cf70a8f8 2022-05-26 09:04:36+00 2022-05-26 09:04:36+00 \N f0f92b13-e8a2-4208-af35-88c2f57053ed {http,https} \N \N {/s472-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+8802df97-7210-454c-918e-a6b5138bdcaa 2022-05-26 09:04:36+00 2022-05-26 09:04:36+00 \N f0f92b13-e8a2-4208-af35-88c2f57053ed {http,https} \N \N {/s472-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+19f9eb11-c202-4b14-ab7c-cd0971a424db 2022-05-26 09:04:36+00 2022-05-26 09:04:36+00 \N f0f92b13-e8a2-4208-af35-88c2f57053ed {http,https} \N \N {/s472-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+97772726-85c5-4469-a489-e862aa6bddb8 2022-05-26 09:04:36+00 2022-05-26 09:04:36+00 \N 50b2eea6-fcae-41c7-872a-7f725aad8f68 {http,https} \N \N {/s473-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+a5fc7fe6-cb38-4c40-888d-b829e1d2eb0c 2022-05-26 09:04:36+00 2022-05-26 09:04:36+00 \N 50b2eea6-fcae-41c7-872a-7f725aad8f68 {http,https} \N \N {/s473-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+6e96309a-1c5e-416f-94b9-ae94f9451a6d 2022-05-26 09:04:36+00 2022-05-26 09:04:36+00 \N 50b2eea6-fcae-41c7-872a-7f725aad8f68 {http,https} \N \N {/s473-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+61ca5840-595c-4661-934a-327e4a15640b 2022-05-26 09:04:36+00 2022-05-26 09:04:36+00 \N 50b2eea6-fcae-41c7-872a-7f725aad8f68 {http,https} \N \N {/s473-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+00c6602a-885b-441c-ad13-39eb3c1fda8c 2022-05-26 09:04:36+00 2022-05-26 09:04:36+00 \N 5d22741a-9f70-4978-a113-4e3370595e14 {http,https} \N \N {/s474-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+8538e410-547d-4af1-a5e4-a3e7491b64ce 2022-05-26 09:04:36+00 2022-05-26 09:04:36+00 \N 5d22741a-9f70-4978-a113-4e3370595e14 {http,https} \N \N {/s474-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+516eeb29-4c13-4502-84bd-cbaff4b5e540 2022-05-26 09:04:36+00 2022-05-26 09:04:36+00 \N 5d22741a-9f70-4978-a113-4e3370595e14 {http,https} \N \N {/s474-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+e77d4b44-4733-493a-975b-9762f987d109 2022-05-26 09:04:36+00 2022-05-26 09:04:36+00 \N 5d22741a-9f70-4978-a113-4e3370595e14 {http,https} \N \N {/s474-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+4e7b3320-325c-4c94-8967-6a3de95dea3e 2022-05-26 09:04:36+00 2022-05-26 09:04:36+00 \N 5e9f240d-6e21-4393-b37c-f9f1e8ca70f3 {http,https} \N \N {/s475-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+ea66dc1a-9b79-402e-8585-01afeab94962 2022-05-26 09:04:36+00 2022-05-26 09:04:36+00 \N 5e9f240d-6e21-4393-b37c-f9f1e8ca70f3 {http,https} \N \N {/s475-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+e2d661f8-add0-4cd3-a766-aa3152afbf2e 2022-05-26 09:04:36+00 2022-05-26 09:04:36+00 \N 5e9f240d-6e21-4393-b37c-f9f1e8ca70f3 {http,https} \N \N {/s475-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+f9dd2af8-4d40-4368-93a4-e80590f59d0e 2022-05-26 09:04:36+00 2022-05-26 09:04:36+00 \N 5e9f240d-6e21-4393-b37c-f9f1e8ca70f3 {http,https} \N \N {/s475-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+90010a98-3ee3-46d2-9767-f80944e8c593 2022-05-26 09:04:36+00 2022-05-26 09:04:36+00 \N 84d0828f-fe77-41f1-928e-11706edb8821 {http,https} \N \N {/s476-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+80be433d-83b1-4635-a8f9-825da2430b41 2022-05-26 09:04:36+00 2022-05-26 09:04:36+00 \N 84d0828f-fe77-41f1-928e-11706edb8821 {http,https} \N \N {/s476-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+5418854d-e234-45fd-8312-d518a6ef7b41 2022-05-26 09:04:36+00 2022-05-26 09:04:36+00 \N 84d0828f-fe77-41f1-928e-11706edb8821 {http,https} \N \N {/s476-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+f6d6a613-de42-499f-b225-77580c97ec89 2022-05-26 09:04:36+00 2022-05-26 09:04:36+00 \N 84d0828f-fe77-41f1-928e-11706edb8821 {http,https} \N \N {/s476-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+9762fb31-d4b9-4430-9b19-3e28edee92cd 2022-05-26 09:04:36+00 2022-05-26 09:04:36+00 \N 7c9d3f4c-4e57-450e-b12f-7db6ebcb9aea {http,https} \N \N {/s477-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+5f7ad1f4-1385-423c-a952-bbb9bd2be874 2022-05-26 09:04:36+00 2022-05-26 09:04:36+00 \N 7c9d3f4c-4e57-450e-b12f-7db6ebcb9aea {http,https} \N \N {/s477-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+d974ac69-db43-4e85-9a87-f9342fe8d912 2022-05-26 09:04:36+00 2022-05-26 09:04:36+00 \N 7c9d3f4c-4e57-450e-b12f-7db6ebcb9aea {http,https} \N \N {/s477-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+d44df5f8-a07c-4ff5-9625-35526371b822 2022-05-26 09:04:36+00 2022-05-26 09:04:36+00 \N 7c9d3f4c-4e57-450e-b12f-7db6ebcb9aea {http,https} \N \N {/s477-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+1830c64f-60d2-44fd-b9e4-0729764c033e 2022-05-26 09:04:36+00 2022-05-26 09:04:36+00 \N b1f4f818-0f47-4372-868c-df50e9603ed0 {http,https} \N \N {/s478-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+83588352-b2c2-4572-acdc-65b246a782cd 2022-05-26 09:04:36+00 2022-05-26 09:04:36+00 \N b1f4f818-0f47-4372-868c-df50e9603ed0 {http,https} \N \N {/s478-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+78aa5f81-0230-4005-8b32-b98a4d9e79e5 2022-05-26 09:04:36+00 2022-05-26 09:04:36+00 \N b1f4f818-0f47-4372-868c-df50e9603ed0 {http,https} \N \N {/s478-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+b32d93cc-f2db-4337-98c8-ad29cf07af27 2022-05-26 09:04:36+00 2022-05-26 09:04:36+00 \N b1f4f818-0f47-4372-868c-df50e9603ed0 {http,https} \N \N {/s478-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+227095bd-7f4a-4260-bc8e-3f0e483a60a7 2022-05-26 09:04:36+00 2022-05-26 09:04:36+00 \N ea4910d2-9eaa-4e94-8f10-94d0da66aa12 {http,https} \N \N {/s479-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+f2d72654-4dbe-418e-81f1-b7f57f6010a2 2022-05-26 09:04:36+00 2022-05-26 09:04:36+00 \N ea4910d2-9eaa-4e94-8f10-94d0da66aa12 {http,https} \N \N {/s479-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+bc7e358a-b8eb-4243-9ffe-d23ac5f84d0e 2022-05-26 09:04:36+00 2022-05-26 09:04:36+00 \N ea4910d2-9eaa-4e94-8f10-94d0da66aa12 {http,https} \N \N {/s479-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+9d861fc6-747d-4703-9167-c5f0ba831697 2022-05-26 09:04:36+00 2022-05-26 09:04:36+00 \N ea4910d2-9eaa-4e94-8f10-94d0da66aa12 {http,https} \N \N {/s479-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+d885bdcd-efe2-4188-aaf3-ba94d761876a 2022-05-26 09:04:36+00 2022-05-26 09:04:36+00 \N 84164c99-8064-4616-9b89-4ad2cd3ee6da {http,https} \N \N {/s480-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+e04162d2-1d25-42e8-9974-be98ae62fa91 2022-05-26 09:04:36+00 2022-05-26 09:04:36+00 \N 84164c99-8064-4616-9b89-4ad2cd3ee6da {http,https} \N \N {/s480-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+72075bd9-b063-4a57-af12-3a4a88828b3e 2022-05-26 09:04:36+00 2022-05-26 09:04:36+00 \N 84164c99-8064-4616-9b89-4ad2cd3ee6da {http,https} \N \N {/s480-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+0af1158f-9fc4-4ece-a444-d11bd29b730c 2022-05-26 09:04:37+00 2022-05-26 09:04:37+00 \N 84164c99-8064-4616-9b89-4ad2cd3ee6da {http,https} \N \N {/s480-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+5d61baba-08f7-41b2-906d-af28e90761d7 2022-05-26 09:04:37+00 2022-05-26 09:04:37+00 \N 64f3861f-7ec7-45bf-a781-73de35a51bf3 {http,https} \N \N {/s481-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+b58a7295-19fe-4862-8636-af354002176e 2022-05-26 09:04:37+00 2022-05-26 09:04:37+00 \N 64f3861f-7ec7-45bf-a781-73de35a51bf3 {http,https} \N \N {/s481-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+c27c93de-efe2-4751-8c68-704590169272 2022-05-26 09:04:37+00 2022-05-26 09:04:37+00 \N 64f3861f-7ec7-45bf-a781-73de35a51bf3 {http,https} \N \N {/s481-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+e49dc496-bbf0-4744-913e-b4c93011ef7c 2022-05-26 09:04:37+00 2022-05-26 09:04:37+00 \N 64f3861f-7ec7-45bf-a781-73de35a51bf3 {http,https} \N \N {/s481-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+31b5fbc7-e064-424b-8913-0237f253d47d 2022-05-26 09:04:37+00 2022-05-26 09:04:37+00 \N 0501b4de-a562-45ac-a4f8-ca0b0a5f2be4 {http,https} \N \N {/s482-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+f5a41a52-afcc-4559-8d58-a02dd7eb4c19 2022-05-26 09:04:37+00 2022-05-26 09:04:37+00 \N 0501b4de-a562-45ac-a4f8-ca0b0a5f2be4 {http,https} \N \N {/s482-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+a4cd39a9-79c6-40ae-86c6-d43961fe2f88 2022-05-26 09:04:37+00 2022-05-26 09:04:37+00 \N 0501b4de-a562-45ac-a4f8-ca0b0a5f2be4 {http,https} \N \N {/s482-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+b7de46b0-d84d-4ec9-a5fe-58e76bd17f38 2022-05-26 09:04:37+00 2022-05-26 09:04:37+00 \N 0501b4de-a562-45ac-a4f8-ca0b0a5f2be4 {http,https} \N \N {/s482-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+a9aa0edb-7c39-4e31-aedd-67c612e0d649 2022-05-26 09:04:37+00 2022-05-26 09:04:37+00 \N edf40205-69ee-4f3b-ba0c-09d70531b17b {http,https} \N \N {/s483-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+57980eec-3861-4b4a-b1a2-a0e3bbbbffd9 2022-05-26 09:04:37+00 2022-05-26 09:04:37+00 \N edf40205-69ee-4f3b-ba0c-09d70531b17b {http,https} \N \N {/s483-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+405ceb75-7c44-49c3-aaa7-806c7518a0a8 2022-05-26 09:04:37+00 2022-05-26 09:04:37+00 \N edf40205-69ee-4f3b-ba0c-09d70531b17b {http,https} \N \N {/s483-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+89a3c416-e757-4363-9c83-bb2dbe801c02 2022-05-26 09:04:37+00 2022-05-26 09:04:37+00 \N edf40205-69ee-4f3b-ba0c-09d70531b17b {http,https} \N \N {/s483-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+a625b1a2-07c7-4f1f-aafa-47dec58a5e65 2022-05-26 09:04:37+00 2022-05-26 09:04:37+00 \N f18530a1-b79f-404c-97b5-c8cb7d4df0d3 {http,https} \N \N {/s484-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+d6f362a2-87fa-4e66-a1ed-9fe48088b2ca 2022-05-26 09:04:37+00 2022-05-26 09:04:37+00 \N f18530a1-b79f-404c-97b5-c8cb7d4df0d3 {http,https} \N \N {/s484-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+294c3258-e1fd-4e94-8054-d680c05c0279 2022-05-26 09:04:37+00 2022-05-26 09:04:37+00 \N f18530a1-b79f-404c-97b5-c8cb7d4df0d3 {http,https} \N \N {/s484-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+97e87056-b434-49f0-bab5-7bad670c1c4c 2022-05-26 09:04:37+00 2022-05-26 09:04:37+00 \N f18530a1-b79f-404c-97b5-c8cb7d4df0d3 {http,https} \N \N {/s484-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+bcedcdfe-d236-4679-84a0-841a71f3e905 2022-05-26 09:04:37+00 2022-05-26 09:04:37+00 \N 6b7f220c-1df2-41b3-9ea3-a6bd5ece4a4f {http,https} \N \N {/s485-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+20ca2aa9-96af-43c7-a0f9-d404bc537b6c 2022-05-26 09:04:37+00 2022-05-26 09:04:37+00 \N 6b7f220c-1df2-41b3-9ea3-a6bd5ece4a4f {http,https} \N \N {/s485-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+bdc1037c-1e47-43ed-b82a-a54cea48ffdb 2022-05-26 09:04:37+00 2022-05-26 09:04:37+00 \N 6b7f220c-1df2-41b3-9ea3-a6bd5ece4a4f {http,https} \N \N {/s485-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+436a2d1b-66be-49cd-9748-0fcd0d982db4 2022-05-26 09:04:37+00 2022-05-26 09:04:37+00 \N 6b7f220c-1df2-41b3-9ea3-a6bd5ece4a4f {http,https} \N \N {/s485-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+6922cc8a-c642-4165-8479-31327ac0abfc 2022-05-26 09:04:37+00 2022-05-26 09:04:37+00 \N 06b00f42-c69b-4243-8506-582504283fb7 {http,https} \N \N {/s486-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+f3c32d74-ceee-4cd8-bbc8-d1f908e80eaa 2022-05-26 09:04:37+00 2022-05-26 09:04:37+00 \N 06b00f42-c69b-4243-8506-582504283fb7 {http,https} \N \N {/s486-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+e3cf12f4-da14-4f3e-905c-479914468396 2022-05-26 09:04:37+00 2022-05-26 09:04:37+00 \N 06b00f42-c69b-4243-8506-582504283fb7 {http,https} \N \N {/s486-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+9dff2046-de1f-4009-90b9-7be7bf99b487 2022-05-26 09:04:37+00 2022-05-26 09:04:37+00 \N 06b00f42-c69b-4243-8506-582504283fb7 {http,https} \N \N {/s486-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+958190df-2bcd-4965-a530-93c3fd16554c 2022-05-26 09:04:37+00 2022-05-26 09:04:37+00 \N 9fa2ce85-2954-470e-9a8f-b80a94d18b5c {http,https} \N \N {/s487-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+6d2a94aa-d74d-4849-8c26-251b29b8e701 2022-05-26 09:04:37+00 2022-05-26 09:04:37+00 \N 9fa2ce85-2954-470e-9a8f-b80a94d18b5c {http,https} \N \N {/s487-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+02886cc1-42d3-4b55-bc1e-ad78a366d1b1 2022-05-26 09:04:37+00 2022-05-26 09:04:37+00 \N 9fa2ce85-2954-470e-9a8f-b80a94d18b5c {http,https} \N \N {/s487-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+9d74ce27-9141-43bb-a072-0c7df671c5bd 2022-05-26 09:04:37+00 2022-05-26 09:04:37+00 \N 9fa2ce85-2954-470e-9a8f-b80a94d18b5c {http,https} \N \N {/s487-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+8ba7ede1-e414-4d2b-9840-2655b34c92ea 2022-05-26 09:04:37+00 2022-05-26 09:04:37+00 \N 690744c2-57e5-458b-aa9c-eec197957ecc {http,https} \N \N {/s488-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+d2918e6e-c2d0-48e9-b36c-336710f3d078 2022-05-26 09:04:37+00 2022-05-26 09:04:37+00 \N 690744c2-57e5-458b-aa9c-eec197957ecc {http,https} \N \N {/s488-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+169bf08d-00cf-4209-baff-ff9ecc883977 2022-05-26 09:04:37+00 2022-05-26 09:04:37+00 \N 690744c2-57e5-458b-aa9c-eec197957ecc {http,https} \N \N {/s488-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+b2e1d473-5314-4dbe-b583-04ec6d4730a7 2022-05-26 09:04:37+00 2022-05-26 09:04:37+00 \N 690744c2-57e5-458b-aa9c-eec197957ecc {http,https} \N \N {/s488-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+bbf9c50c-f4b3-415a-bf15-9089f84cf322 2022-05-26 09:04:37+00 2022-05-26 09:04:37+00 \N 4a74034a-2448-42f4-98d3-dc1fe050f6ce {http,https} \N \N {/s489-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+b1ef0d2b-2454-42d4-bd8b-b0fa58a927b0 2022-05-26 09:04:37+00 2022-05-26 09:04:37+00 \N 4a74034a-2448-42f4-98d3-dc1fe050f6ce {http,https} \N \N {/s489-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+4358263d-ff4c-4a06-a0bb-d4db3dee6760 2022-05-26 09:04:37+00 2022-05-26 09:04:37+00 \N 4a74034a-2448-42f4-98d3-dc1fe050f6ce {http,https} \N \N {/s489-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+3c9becf1-889c-42cc-b80b-9e875f07f91a 2022-05-26 09:04:37+00 2022-05-26 09:04:37+00 \N 4a74034a-2448-42f4-98d3-dc1fe050f6ce {http,https} \N \N {/s489-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+6f810c20-bfe2-49e7-9eac-52b581e91df7 2022-05-26 09:04:37+00 2022-05-26 09:04:37+00 \N c4507468-ff51-4d6f-977f-0969cca30830 {http,https} \N \N {/s490-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+3e5b3cf6-9cbb-4258-93b0-6b4058aab21b 2022-05-26 09:04:37+00 2022-05-26 09:04:37+00 \N c4507468-ff51-4d6f-977f-0969cca30830 {http,https} \N \N {/s490-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+9254b00b-e706-456f-a0a2-b0982568526b 2022-05-26 09:04:37+00 2022-05-26 09:04:37+00 \N c4507468-ff51-4d6f-977f-0969cca30830 {http,https} \N \N {/s490-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+b196ce2a-423d-4a40-b89b-0cada79c24b1 2022-05-26 09:04:37+00 2022-05-26 09:04:37+00 \N c4507468-ff51-4d6f-977f-0969cca30830 {http,https} \N \N {/s490-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+0469b9be-1eb9-4769-a3a3-4a6b2ac11f3d 2022-05-26 09:04:37+00 2022-05-26 09:04:37+00 \N 6c865afc-9439-411c-ade4-6fd8ac429c07 {http,https} \N \N {/s491-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+6a70ee41-c184-43ef-ab43-28ae6362fcfc 2022-05-26 09:04:37+00 2022-05-26 09:04:37+00 \N 6c865afc-9439-411c-ade4-6fd8ac429c07 {http,https} \N \N {/s491-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+d9e3ace8-afd2-4d21-936a-18a8a36eee98 2022-05-26 09:04:37+00 2022-05-26 09:04:37+00 \N 6c865afc-9439-411c-ade4-6fd8ac429c07 {http,https} \N \N {/s491-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+c3051e9f-9b15-4200-8c55-32e5f5de4db2 2022-05-26 09:04:37+00 2022-05-26 09:04:37+00 \N 6c865afc-9439-411c-ade4-6fd8ac429c07 {http,https} \N \N {/s491-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+57d989e7-a5bb-415c-a662-5d395092e40e 2022-05-26 09:04:37+00 2022-05-26 09:04:37+00 \N e04db553-36a3-468d-82b4-938514fc8cdb {http,https} \N \N {/s492-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+be81249d-b3ff-437a-b97f-2d90ed894210 2022-05-26 09:04:37+00 2022-05-26 09:04:37+00 \N e04db553-36a3-468d-82b4-938514fc8cdb {http,https} \N \N {/s492-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+b5760cbe-8c1a-4d3c-ba0b-5f1f525ffc19 2022-05-26 09:04:37+00 2022-05-26 09:04:37+00 \N e04db553-36a3-468d-82b4-938514fc8cdb {http,https} \N \N {/s492-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+28b3c04b-9586-4612-90de-e274a0ddc863 2022-05-26 09:04:37+00 2022-05-26 09:04:37+00 \N e04db553-36a3-468d-82b4-938514fc8cdb {http,https} \N \N {/s492-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+2349d849-97c4-4779-8899-e92411c04986 2022-05-26 09:04:37+00 2022-05-26 09:04:37+00 \N ecaca662-b04b-474b-a038-c185ac99a3e1 {http,https} \N \N {/s493-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+48795b76-6f8d-45d5-8950-74c60e0d7df1 2022-05-26 09:04:37+00 2022-05-26 09:04:37+00 \N ecaca662-b04b-474b-a038-c185ac99a3e1 {http,https} \N \N {/s493-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+36a4c536-7342-430e-8346-c4fc17ff487a 2022-05-26 09:04:37+00 2022-05-26 09:04:37+00 \N ecaca662-b04b-474b-a038-c185ac99a3e1 {http,https} \N \N {/s493-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+907f153a-b5e2-4c95-bb66-f6ad726270c0 2022-05-26 09:04:37+00 2022-05-26 09:04:37+00 \N ecaca662-b04b-474b-a038-c185ac99a3e1 {http,https} \N \N {/s493-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+d4faaf1a-9e86-4a49-b1e7-4565b776d84b 2022-05-26 09:04:37+00 2022-05-26 09:04:37+00 \N 3c19f673-974e-4d27-8aa8-c8b3be9a268a {http,https} \N \N {/s494-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+05e5e286-865b-4f6c-bb73-235808c32eb9 2022-05-26 09:04:37+00 2022-05-26 09:04:37+00 \N 3c19f673-974e-4d27-8aa8-c8b3be9a268a {http,https} \N \N {/s494-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+ce3ff41e-8aa4-46cd-872e-8e9f55f72c0a 2022-05-26 09:04:37+00 2022-05-26 09:04:37+00 \N 3c19f673-974e-4d27-8aa8-c8b3be9a268a {http,https} \N \N {/s494-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+b3524c08-b846-4546-882f-cc6207e90183 2022-05-26 09:04:37+00 2022-05-26 09:04:37+00 \N 3c19f673-974e-4d27-8aa8-c8b3be9a268a {http,https} \N \N {/s494-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+a06facca-91a6-4a98-b3a9-e51484166998 2022-05-26 09:04:37+00 2022-05-26 09:04:37+00 \N 6c5851b2-0b70-4fd8-9d95-b5f60e89b8d8 {http,https} \N \N {/s495-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+8e5dc74b-4585-4417-9444-6e0d185466dc 2022-05-26 09:04:37+00 2022-05-26 09:04:37+00 \N 6c5851b2-0b70-4fd8-9d95-b5f60e89b8d8 {http,https} \N \N {/s495-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+9b9e6e65-8544-4f89-a19b-16ddc70b1f52 2022-05-26 09:04:37+00 2022-05-26 09:04:37+00 \N 6c5851b2-0b70-4fd8-9d95-b5f60e89b8d8 {http,https} \N \N {/s495-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+9f35ed1f-4138-4640-b127-43dd0a528965 2022-05-26 09:04:37+00 2022-05-26 09:04:37+00 \N 6c5851b2-0b70-4fd8-9d95-b5f60e89b8d8 {http,https} \N \N {/s495-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+415b2561-a1e7-4e05-9e86-3c44a0edb91a 2022-05-26 09:04:37+00 2022-05-26 09:04:37+00 \N ca7691e7-644f-4503-8661-255efc4f2d73 {http,https} \N \N {/s496-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+f581e64d-fc6f-4f91-8bbe-600232ec7d3e 2022-05-26 09:04:37+00 2022-05-26 09:04:37+00 \N ca7691e7-644f-4503-8661-255efc4f2d73 {http,https} \N \N {/s496-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+6da5537f-8a92-4b9b-848e-d1864069f23c 2022-05-26 09:04:37+00 2022-05-26 09:04:37+00 \N ca7691e7-644f-4503-8661-255efc4f2d73 {http,https} \N \N {/s496-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+5031154c-ed28-400a-b134-c9af8a782571 2022-05-26 09:04:37+00 2022-05-26 09:04:37+00 \N ca7691e7-644f-4503-8661-255efc4f2d73 {http,https} \N \N {/s496-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+8f366d8c-728c-4eac-921a-d62ec110631a 2022-05-26 09:04:37+00 2022-05-26 09:04:37+00 \N c520c41e-eaac-436b-8943-9d96b749a386 {http,https} \N \N {/s497-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+ba697728-5e97-46ff-8bb8-b5b90a96a8f0 2022-05-26 09:04:37+00 2022-05-26 09:04:37+00 \N c520c41e-eaac-436b-8943-9d96b749a386 {http,https} \N \N {/s497-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+481ffcdf-5d20-42de-a6c2-df0a613f7d7f 2022-05-26 09:04:37+00 2022-05-26 09:04:37+00 \N c520c41e-eaac-436b-8943-9d96b749a386 {http,https} \N \N {/s497-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+a0d9909b-5c47-4ed6-bdee-d0b1ff643370 2022-05-26 09:04:37+00 2022-05-26 09:04:37+00 \N c520c41e-eaac-436b-8943-9d96b749a386 {http,https} \N \N {/s497-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+2c2f7c68-48a6-4629-85b7-17f62ed9f218 2022-05-26 09:04:37+00 2022-05-26 09:04:37+00 \N 35071e24-8e47-4af5-adfd-b91431777cfb {http,https} \N \N {/s498-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+bef6af9d-3386-434d-b1d7-65d1c330c453 2022-05-26 09:04:37+00 2022-05-26 09:04:37+00 \N 35071e24-8e47-4af5-adfd-b91431777cfb {http,https} \N \N {/s498-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+a39ba195-5d74-485b-8997-166fb79f6fb4 2022-05-26 09:04:37+00 2022-05-26 09:04:37+00 \N 35071e24-8e47-4af5-adfd-b91431777cfb {http,https} \N \N {/s498-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+cd0d5bf9-4493-43ef-9a0e-b3035651ddb9 2022-05-26 09:04:37+00 2022-05-26 09:04:37+00 \N 35071e24-8e47-4af5-adfd-b91431777cfb {http,https} \N \N {/s498-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+1b476ff0-69c7-4274-92b1-cc56e2ec5b95 2022-05-26 09:04:37+00 2022-05-26 09:04:37+00 \N 3206e638-1f43-47b7-8b36-e5a70cf785b2 {http,https} \N \N {/s499-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+84196bb5-7d3d-42ee-b404-af4409e35c66 2022-05-26 09:04:37+00 2022-05-26 09:04:37+00 \N 3206e638-1f43-47b7-8b36-e5a70cf785b2 {http,https} \N \N {/s499-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+c51be90b-9f47-47f5-a8bf-09865ab9bf97 2022-05-26 09:04:37+00 2022-05-26 09:04:37+00 \N 3206e638-1f43-47b7-8b36-e5a70cf785b2 {http,https} \N \N {/s499-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+7d91e732-5d39-4cf0-840d-1bb9d54fe465 2022-05-26 09:04:37+00 2022-05-26 09:04:37+00 \N 3206e638-1f43-47b7-8b36-e5a70cf785b2 {http,https} \N \N {/s499-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+9564ba87-46a0-47f9-8f9d-037c8619963a 2022-05-26 09:04:37+00 2022-05-26 09:04:37+00 \N d665c6e1-e3a9-4f58-bb0b-29a67711080f {http,https} \N \N {/s500-r1} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+dc7b472b-29a5-48dc-9a97-dd6996a2d219 2022-05-26 09:04:37+00 2022-05-26 09:04:37+00 \N d665c6e1-e3a9-4f58-bb0b-29a67711080f {http,https} \N \N {/s500-r2} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+0c28aff6-defb-4390-9af5-a587cf80cc89 2022-05-26 09:04:37+00 2022-05-26 09:04:37+00 \N d665c6e1-e3a9-4f58-bb0b-29a67711080f {http,https} \N \N {/s500-r3} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+f5230700-c5b2-411f-8bfb-5307e70ef52f 2022-05-26 09:04:37+00 2022-05-26 09:04:37+00 \N d665c6e1-e3a9-4f58-bb0b-29a67711080f {http,https} \N \N {/s500-r4} \N \N \N 0 t f \N 426 \N v0 dde1a96f-1d2f-41dc-bcc3-2c393ec42c65 t t
+\.
+
+
diff --git a/kong-versions/3.9.0.0/kong/spec/fixtures/perf/charts/test_data1.json b/kong-versions/3.9.0.0/kong/spec/fixtures/perf/charts/test_data1.json
new file mode 100644
index 00000000..c8239d9f
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/fixtures/perf/charts/test_data1.json
@@ -0,0 +1,547 @@
+{
+ "options": {
+ "suite_sequential": true,
+ "xaxis_title": "Upstreams count"
+ },
+ "data": [{
+ "latencies_p90": [1030, 1040],
+ "latencies_p99": [1040, 1200, 1600],
+ "latency_avg": 6.66,
+ "rpss": [498.4, 500],
+ "rps": 498.4,
+ "latency_max": 1040,
+ "version": "2.8.1.1",
+ "suite": "7501"
+ }, {
+ "latency_avg": 1.84,
+ "latency_max": 133.76,
+ "rpss": [498.4],
+ "rps": 498.4,
+ "latencies_p99": [133.89],
+ "latencies_p90": [129.85],
+ "version": "2.8.1.2~internal-preview",
+ "suite": "7501"
+ }, {
+ "latencies_p90": [1240],
+ "latencies_p99": [1250],
+ "latency_avg": 9.22,
+ "rpss": [500.07],
+ "rps": 500.07,
+ "latency_max": 1250,
+ "version": "2.8.1.1",
+ "suite": "9501"
+ }, {
+ "latency_avg": 2.07,
+ "latency_max": 178.05,
+ "rpss": [500.07],
+ "rps": 500.07,
+ "latencies_p99": [178.18],
+ "latencies_p90": [172.41],
+ "version": "2.8.1.2~internal-preview",
+ "suite": "9501"
+ }, {
+ "latencies_p90": [1570],
+ "latencies_p99": [1570],
+ "latency_avg": 15.31,
+ "rpss": [498.4],
+ "rps": 498.4,
+ "latency_max": 1570,
+ "version": "2.8.1.1",
+ "suite": "10001"
+ }, {
+ "latency_avg": 2,
+ "latency_max": 169.86,
+ "rpss": [498.41],
+ "rps": 498.41,
+ "latencies_p99": [169.98],
+ "latencies_p90": [159.62],
+ "version": "2.8.1.2~internal-preview",
+ "suite": "10001"
+ }, {
+ "latencies_p90": [5000],
+ "latencies_p99": [5010],
+ "latency_avg": 165.13,
+ "rpss": [500.07],
+ "rps": 500.07,
+ "latency_max": 5010,
+ "version": "2.8.1.1",
+ "suite": "7001"
+ }, {
+ "latency_avg": 3.32,
+ "latency_max": 216.83,
+ "rpss": [500.07],
+ "rps": 500.07,
+ "latencies_p99": [216.96],
+ "latencies_p90": [178.18],
+ "version": "2.8.1.2~internal-preview",
+ "suite": "7001"
+ }, {
+ "latencies_p90": [964.09],
+ "latencies_p99": [969.22],
+ "latency_avg": 7.28,
+ "rpss": [500.07],
+ "rps": 500.07,
+ "latency_max": 968.7,
+ "version": "2.8.1.1",
+ "suite": "8001"
+ }, {
+ "latency_avg": 1.91,
+ "latency_max": 102.34,
+ "rpss": [498.4],
+ "rps": 498.4,
+ "latencies_p99": [102.4],
+ "latencies_p90": [101.5],
+ "version": "2.8.1.2~internal-preview",
+ "suite": "8001"
+ }, {
+ "latencies_p90": [1210],
+ "latencies_p99": [1230],
+ "latency_avg": 11.7,
+ "rpss": [500.07],
+ "rps": 500.07,
+ "latency_max": 1230,
+ "version": "2.8.1.1",
+ "suite": "8501"
+ }, {
+ "latency_avg": 2.14,
+ "latency_max": 269.82,
+ "rpss": [498.4],
+ "rps": 498.4,
+ "latencies_p99": [270.08],
+ "latencies_p90": [266.75],
+ "version": "2.8.1.2~internal-preview",
+ "suite": "8501"
+ }, {
+ "latencies_p90": [2110],
+ "latencies_p99": [2110],
+ "latency_avg": 49.73,
+ "rpss": [498.4],
+ "rps": 498.4,
+ "latency_max": 2110,
+ "version": "2.8.1.1",
+ "suite": "9001"
+ }, {
+ "latency_avg": 1.93,
+ "latency_max": 138.75,
+ "rpss": [498.41],
+ "rps": 498.41,
+ "latencies_p99": [138.88],
+ "latencies_p90": [138.49],
+ "version": "2.8.1.2~internal-preview",
+ "suite": "9001"
+ }, {
+ "latency_avg": 5.73,
+ "latency_max": 953.86,
+ "rpss": [498.41],
+ "rps": 498.41,
+ "latencies_p99": [954.37],
+ "latencies_p90": [945.66],
+ "version": "2.8.1.1",
+ "suite": "6501"
+ }, {
+ "latency_avg": 1.75,
+ "latency_max": 104.13,
+ "rpss": [500.07],
+ "rps": 500.07,
+ "latencies_p99": [104.19],
+ "latencies_p90": [85.12],
+ "version": "2.8.1.2~internal-preview",
+ "suite": "6501"
+ }, {
+ "latency_avg": 74.1,
+ "latency_max": 2620,
+ "rpss": [498.4],
+ "rps": 498.4,
+ "latencies_p99": [2620],
+ "latencies_p90": [2610],
+ "version": "2.8.1.1",
+ "suite": "12001"
+ }, {
+ "latency_avg": 2.94,
+ "latency_max": 447.23,
+ "rpss": [498.4],
+ "rps": 498.4,
+ "latencies_p99": [447.49],
+ "latencies_p90": [444.42],
+ "version": "2.8.1.2~internal-preview",
+ "suite": "12001"
+ }, {
+ "latency_avg": 1.98,
+ "latency_max": 349.95,
+ "rpss": [498.4],
+ "rps": 498.4,
+ "latencies_p99": [350.21],
+ "latencies_p90": [340.99],
+ "version": "2.8.1.1",
+ "suite": "2501"
+ }, {
+ "latency_avg": 1.42,
+ "latency_max": 86.08,
+ "rpss": [500.07],
+ "rps": 500.07,
+ "latencies_p99": [86.14],
+ "latencies_p90": [66.94],
+ "version": "2.8.1.2~internal-preview",
+ "suite": "2501"
+ }, {
+ "latency_avg": 14.97,
+ "latency_max": 1580,
+ "rpss": [498.41],
+ "rps": 498.41,
+ "latencies_p99": [1580],
+ "latencies_p90": [1570],
+ "version": "2.8.1.1",
+ "suite": "11001"
+ }, {
+ "latency_avg": 2.36,
+ "latency_max": 219.14,
+ "rpss": [498.4],
+ "rps": 498.4,
+ "latencies_p99": [219.26],
+ "latencies_p90": [215.42],
+ "version": "2.8.1.2~internal-preview",
+ "suite": "11001"
+ }, {
+ "latency_avg": 6.16,
+ "latency_max": 1280,
+ "rpss": [500.07],
+ "rps": 500.07,
+ "latencies_p99": [1280],
+ "latencies_p90": [1180],
+ "version": "2.8.1.1",
+ "suite": "6001"
+ }, {
+ "latency_avg": 1.84,
+ "latency_max": 199.81,
+ "rpss": [500.07],
+ "rps": 500.07,
+ "latencies_p99": [199.93],
+ "latencies_p90": [198.53],
+ "version": "2.8.1.2~internal-preview",
+ "suite": "6001"
+ }, {
+ "latency_avg": 14.46,
+ "latency_max": 1930,
+ "rpss": [498.4],
+ "rps": 498.4,
+ "latencies_p99": [1930],
+ "latencies_p90": [1930],
+ "version": "2.8.1.1",
+ "suite": "13001"
+ }, {
+ "latency_avg": 2.36,
+ "latency_max": 391.17,
+ "rpss": [498.42],
+ "rps": 498.42,
+ "latencies_p99": [391.42],
+ "latencies_p90": [358.4],
+ "version": "2.8.1.2~internal-preview",
+ "suite": "13001"
+ }, {
+ "latency_avg": 3.78,
+ "latency_max": 848.38,
+ "rpss": [500.07],
+ "rps": 500.07,
+ "latencies_p99": [848.9],
+ "latencies_p90": [843.26],
+ "version": "2.8.1.1",
+ "suite": "5001"
+ }, {
+ "latency_avg": 1.53,
+ "latency_max": 84.54,
+ "rpss": [498.4],
+ "rps": 498.4,
+ "latencies_p99": [84.61],
+ "latencies_p90": [83.14],
+ "version": "2.8.1.2~internal-preview",
+ "suite": "5001"
+ }, {
+ "latency_avg": 3.86,
+ "latency_max": 774.66,
+ "rpss": [500.07],
+ "rps": 500.07,
+ "latencies_p99": [775.17],
+ "latencies_p90": [771.07],
+ "version": "2.8.1.1",
+ "suite": "3501"
+ }, {
+ "latency_avg": 1.53,
+ "latency_max": 69.25,
+ "rpss": [498.4],
+ "rps": 498.4,
+ "latencies_p99": [69.31],
+ "latencies_p90": [67.84],
+ "version": "2.8.1.2~internal-preview",
+ "suite": "3501"
+ }, {
+ "latency_avg": 3.23,
+ "latency_max": 563.2,
+ "rpss": [500.03],
+ "rps": 500.03,
+ "latencies_p99": [563.71],
+ "latencies_p90": [561.66],
+ "version": "2.8.1.1",
+ "suite": "4001"
+ }, {
+ "latency_avg": 1.61,
+ "latency_max": 215.3,
+ "rpss": [498.4],
+ "rps": 498.4,
+ "latencies_p99": [215.42],
+ "latencies_p90": [203.9],
+ "version": "2.8.1.2~internal-preview",
+ "suite": "4001"
+ }, {
+ "latency_avg": 70.08,
+ "latency_max": 2390,
+ "rpss": [500.06],
+ "rps": 500.06,
+ "latencies_p99": [2390],
+ "latencies_p90": [2390],
+ "version": "2.8.1.1",
+ "suite": "14001"
+ }, {
+ "latency_avg": 84.42,
+ "latency_max": 2270,
+ "rpss": [498.4],
+ "rps": 498.4,
+ "latencies_p99": [2280],
+ "latencies_p90": [2270],
+ "version": "2.8.1.2~internal-preview",
+ "suite": "14001"
+ }, {
+ "latency_avg": 2.34,
+ "latency_max": 512.77,
+ "rpss": [498.4],
+ "rps": 498.4,
+ "latencies_p99": [513.02],
+ "latencies_p90": [511.23],
+ "version": "2.8.1.1",
+ "suite": "2001"
+ }, {
+ "latency_avg": 1.41,
+ "latency_max": 34.56,
+ "rpss": [498.4],
+ "rps": 498.4,
+ "latencies_p99": [34.59],
+ "latencies_p90": [33.82],
+ "version": "2.8.1.2~internal-preview",
+ "suite": "2001"
+ }, {
+ "latency_avg": 1.35,
+ "latency_max": 63.1,
+ "rpss": [500.07],
+ "rps": 500.07,
+ "latencies_p99": [63.13],
+ "latencies_p90": [60.16],
+ "version": "2.8.1.1",
+ "suite": "1001"
+ }, {
+ "latency_avg": 1.34,
+ "latency_max": 39.14,
+ "rpss": [500.07],
+ "rps": 500.07,
+ "latencies_p99": [39.17],
+ "latencies_p90": [35.68],
+ "version": "2.8.1.2~internal-preview",
+ "suite": "1001"
+ }, {
+ "latency_avg": 2.08,
+ "latency_max": 434.18,
+ "rpss": [500.07],
+ "rps": 500.07,
+ "latencies_p99": [434.43],
+ "latencies_p90": [429.57],
+ "version": "2.8.1.1",
+ "suite": "3001"
+ }, {
+ "latency_avg": 1.43,
+ "latency_max": 49.6,
+ "rpss": [498.4],
+ "rps": 498.4,
+ "latencies_p99": [49.63],
+ "latencies_p90": [40.26],
+ "version": "2.8.1.2~internal-preview",
+ "suite": "3001"
+ }, {
+ "latency_avg": 1.67,
+ "latency_max": 298.24,
+ "rpss": [500.07],
+ "rps": 500.07,
+ "latencies_p99": [298.49],
+ "latencies_p90": [296.96],
+ "version": "2.8.1.1",
+ "suite": "1501"
+ }, {
+ "latency_avg": 1.32,
+ "latency_max": 28.4,
+ "rpss": [498.41],
+ "rps": 498.41,
+ "latencies_p99": [28.42],
+ "latencies_p90": [27.66],
+ "version": "2.8.1.2~internal-preview",
+ "suite": "1501"
+ }, {
+ "latency_avg": 1.34,
+ "latency_max": 67.07,
+ "rpss": [500.07],
+ "rps": 500.07,
+ "latencies_p99": [67.14],
+ "latencies_p90": [60.1],
+ "version": "2.8.1.1",
+ "suite": "501"
+ }, {
+ "latency_avg": 1.36,
+ "latency_max": 26.19,
+ "rpss": [498.4],
+ "rps": 498.4,
+ "latencies_p99": [26.21],
+ "latencies_p90": [21.95],
+ "version": "2.8.1.2~internal-preview",
+ "suite": "501"
+ }, {
+ "latency_avg": 16.9,
+ "latency_max": 2140,
+ "rpss": [500.07],
+ "rps": 500.07,
+ "latencies_p99": [2150],
+ "latencies_p90": [2140],
+ "version": "2.8.1.1",
+ "suite": "12501"
+ }, {
+ "latency_avg": 2.28,
+ "latency_max": 323.33,
+ "rpss": [500.07],
+ "rps": 500.07,
+ "latencies_p99": [323.58],
+ "latencies_p90": [320.26],
+ "version": "2.8.1.2~internal-preview",
+ "suite": "12501"
+ }, {
+ "latency_avg": 13.71,
+ "latency_max": 1760,
+ "rpss": [500.07],
+ "rps": 500.07,
+ "latencies_p99": [1770],
+ "latencies_p90": [1760],
+ "version": "2.8.1.1",
+ "suite": "10501"
+ }, {
+ "latency_avg": 2.3,
+ "latency_max": 198.4,
+ "rpss": [498.4],
+ "rps": 498.4,
+ "latencies_p99": [198.53],
+ "latencies_p90": [198.14],
+ "version": "2.8.1.2~internal-preview",
+ "suite": "10501"
+ }, {
+ "latency_avg": 9.52,
+ "latency_max": 769.02,
+ "rpss": [500.07],
+ "rps": 500.07,
+ "latencies_p99": [769.53],
+ "latencies_p90": [763.39],
+ "version": "2.8.1.1",
+ "suite": "4501"
+ }, {
+ "latency_avg": 4.56,
+ "latency_max": 238.59,
+ "rpss": [498.4],
+ "rps": 498.4,
+ "latencies_p99": [238.72],
+ "latencies_p90": [236.93],
+ "version": "2.8.1.2~internal-preview",
+ "suite": "4501"
+ }, {
+ "latency_avg": 24.86,
+ "latency_max": 2410,
+ "rpss": [500.07],
+ "rps": 500.07,
+ "latencies_p99": [2420],
+ "latencies_p90": [2420],
+ "version": "2.8.1.1",
+ "suite": "13501"
+ }, {
+ "latency_avg": 5.96,
+ "latency_max": 342.78,
+ "rpss": [498.46],
+ "rps": 498.46,
+ "latencies_p99": [343.04],
+ "latencies_p90": [342.78],
+ "version": "2.8.1.2~internal-preview",
+ "suite": "13501"
+ }, {
+ "latency_avg": 4.1,
+ "latency_max": 1110,
+ "rpss": [498.4],
+ "rps": 498.4,
+ "latencies_p99": [1110],
+ "latencies_p90": [1100],
+ "version": "2.8.1.1",
+ "suite": "5501"
+ }, {
+ "latency_avg": 1.62,
+ "latency_max": 126.85,
+ "rpss": [500.07],
+ "rps": 500.07,
+ "latencies_p99": [126.91],
+ "latencies_p90": [126.46],
+ "version": "2.8.1.2~internal-preview",
+ "suite": "5501"
+ }, {
+ "latency_avg": 13.74,
+ "latency_max": 1670,
+ "rpss": [498.42],
+ "rps": 498.42,
+ "latencies_p99": [1670],
+ "latencies_p90": [1600],
+ "version": "2.8.1.1",
+ "suite": "11501"
+ }, {
+ "latency_avg": 2.8,
+ "latency_max": 350.98,
+ "rpss": [498.42],
+ "rps": 498.42,
+ "latencies_p99": [351.23],
+ "latencies_p90": [344.06],
+ "version": "2.8.1.2~internal-preview",
+ "suite": "11501"
+ }, {
+ "latency_avg": 1.33,
+ "latency_max": 3.84,
+ "rpss": [498.4],
+ "rps": 498.4,
+ "latencies_p99": [3.84],
+ "latencies_p90": [3.65],
+ "version": "2.8.1.1",
+ "suite": "1"
+ }, {
+ "latency_avg": 1.31,
+ "latency_max": 4.77,
+ "rpss": [500.07],
+ "rps": 500.07,
+ "latencies_p99": [4.77],
+ "latencies_p90": [4.02],
+ "version": "2.8.1.2~internal-preview",
+ "suite": "1"
+ }, {
+ "latency_avg": 28.93,
+ "latency_max": 2530,
+ "rpss": [498.4],
+ "rps": 498.4,
+ "latencies_p99": [2530],
+ "latencies_p90": [2520],
+ "version": "2.8.1.1",
+ "suite": "14501"
+ }, {
+ "latency_avg": 2.63,
+ "latency_max": 352,
+ "rpss": [500.07],
+ "rps": 500.07,
+ "latencies_p99": [352.26],
+ "latencies_p90": [334.33],
+ "version": "2.8.1.2~internal-preview",
+ "suite": "14501"
+ }]
+}
diff --git a/kong-versions/3.9.0.0/kong/spec/fixtures/perf/charts/test_data2.json b/kong-versions/3.9.0.0/kong/spec/fixtures/perf/charts/test_data2.json
new file mode 100644
index 00000000..b47d1b9d
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/fixtures/perf/charts/test_data2.json
@@ -0,0 +1,60 @@
+{
+ "options": {
+ "suite_sequential": false
+ },
+ "data": [{
+ "rpss": [146063.92, 146845.9, 145638.07],
+ "rps": 146182.63,
+ "latencies_p90": [3.14, 3.27, 3.2],
+ "latencies_p99": [9, 9.18, 9.16],
+ "latency_max": 35.16,
+ "latency_avg": 1.1800240836152,
+ "suite": " #simple #no_plugins #single_route",
+ "version": "git:6098495"
+ }, {
+ "rpss": [144977.6, 143785.14, 145332.58],
+ "rps": 144698.44,
+ "latencies_p90": [3.12, 3.15, 3.28],
+ "latencies_p99": [9.01, 9.04, 9.57],
+ "latency_max": 42.51,
+ "latency_avg": 1.1900081272116,
+ "suite": " #simple #no_plugins #single_route",
+ "version": "git:master"
+ }, {
+ "rpss": [110197.34, 109968.96, 110591.39],
+ "rps": 110252.56333333,
+ "latencies_p90": [2.4, 2.28, 2.22],
+ "latencies_p99": [8.48, 8.14, 7.88],
+ "latency_max": 40.12,
+ "latency_avg": 1.2133197804852,
+ "suite": " #simple #key-auth 10 services each has 10 routes with key-auth, 100 consumers",
+ "version": "git:6098495"
+ }, {
+ "rpss": [109102.58, 109136.34, 108647.47],
+ "rps": 108962.13,
+ "latencies_p90": [2.48, 2.27, 2.14],
+ "latencies_p99": [7.87, 8.15, 7.91],
+ "latency_max": 35.43,
+ "latency_avg": 1.2066902201559,
+ "suite": " #simple #key-auth 10 services each has 10 routes with key-auth, 100 consumers",
+ "version": "git:master"
+ }, {
+ "rpss": [133682.24, 133910.3, 134863],
+ "rps": 134151.84666667,
+ "latencies_p90": [2.72, 2.78, 2.72],
+ "latencies_p99": [8.65, 8.87, 8.49],
+ "latency_max": 35.7,
+ "latency_avg": 1.1699763325704,
+ "suite": " #simple #no_plugins 10 services each has 10 routes",
+ "version": "git:6098495"
+ }, {
+ "rpss": [133410.76, 134137.81, 134780.55],
+ "rps": 134109.70666667,
+ "latencies_p90": [2.83, 2.73, 2.88],
+ "latencies_p99": [9.09, 8.87, 8.98],
+ "latency_max": 43.7,
+ "latency_avg": 1.1932978944078,
+ "suite": " #simple #no_plugins 10 services each has 10 routes",
+ "version": "git:master"
+ }]
+}
diff --git a/kong-versions/3.9.0.0/kong/spec/fixtures/perf/terraform/aws-ec2/.gitignore b/kong-versions/3.9.0.0/kong/spec/fixtures/perf/terraform/aws-ec2/.gitignore
new file mode 100644
index 00000000..cbd4daf5
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/fixtures/perf/terraform/aws-ec2/.gitignore
@@ -0,0 +1,8 @@
+.terraform*
+!.terraform-version
+terraform.tfstate*
+*.deb
+output
+id_rsa
+license.json
+cm-*
diff --git a/kong-versions/3.9.0.0/kong/spec/fixtures/perf/terraform/aws-ec2/ec2.tf b/kong-versions/3.9.0.0/kong/spec/fixtures/perf/terraform/aws-ec2/ec2.tf
new file mode 100644
index 00000000..8d7a96f1
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/fixtures/perf/terraform/aws-ec2/ec2.tf
@@ -0,0 +1,111 @@
+resource "aws_key_pair" "perf" {
+ key_name = "key-perf-test-${random_string.ident.result}"
+ public_key = tls_private_key.key.public_key_openssh
+}
+
+data "aws_ami" "perf" {
+ most_recent = true
+
+ filter {
+ name = "name"
+ values = [var.ec2_os]
+ }
+
+ filter {
+ name = "virtualization-type"
+ values = ["hvm"]
+ }
+
+ owners = ["099720109477"] # Canonical
+}
+
+resource "aws_security_group" "openall" {
+ ingress {
+ from_port = 0
+ to_port = 0
+ protocol = "-1"
+ cidr_blocks = ["0.0.0.0/0"]
+ ipv6_cidr_blocks = ["::/0"]
+ }
+
+ egress {
+ from_port = 0
+ to_port = 0
+ protocol = "-1"
+ cidr_blocks = ["0.0.0.0/0"]
+ ipv6_cidr_blocks = ["::/0"]
+ }
+}
+
+resource "aws_instance" "kong" {
+ ami = data.aws_ami.perf.id
+ instance_type = var.ec2_instance_type
+ key_name = aws_key_pair.perf.key_name
+ monitoring = true
+ security_groups = [aws_security_group.openall.name]
+ associate_public_ip_address = true
+
+ root_block_device {
+ tags = {
+ PerfTest = "perf-${random_string.ident.result}"
+ Name = "kong-${random_string.ident.result}"
+ }
+ volume_size = 100
+ }
+
+ tags = {
+ PerfTest = "perf-${random_string.ident.result}"
+ Name = "kong-${random_string.ident.result}"
+ }
+}
+
+resource "aws_instance" "db" {
+ count = var.seperate_db_node ? 1: 0
+ ami = data.aws_ami.perf.id
+ instance_type = var.ec2_instance_db_type
+ key_name = aws_key_pair.perf.key_name
+ monitoring = true
+ security_groups = [aws_security_group.openall.name]
+ associate_public_ip_address = true
+
+ root_block_device {
+ tags = {
+ PerfTest = "perf-${random_string.ident.result}"
+ Name = "kong-${random_string.ident.result}"
+ }
+ volume_size = 100
+ }
+
+ tags = {
+ PerfTest = "perf-${random_string.ident.result}"
+ Name = "db-${random_string.ident.result}"
+ }
+}
+
+resource "aws_instance" "worker" {
+ ami = data.aws_ami.perf.id
+ instance_type = var.ec2_instance_worker_type
+ key_name = aws_key_pair.perf.key_name
+ monitoring = true
+ security_groups = [aws_security_group.openall.name]
+ associate_public_ip_address = true
+
+ root_block_device {
+ tags = {
+ PerfTest = "perf-${random_string.ident.result}"
+ Name = "kong-${random_string.ident.result}"
+ }
+ volume_size = 100
+ }
+
+ tags = {
+ PerfTest = "perf-${random_string.ident.result}"
+ Name = "worker-${random_string.ident.result}"
+ }
+}
+
+
+resource "random_string" "ident" {
+ length = 4
+ special = false
+}
diff --git a/kong-versions/3.9.0.0/kong/spec/fixtures/perf/terraform/aws-ec2/main.tf b/kong-versions/3.9.0.0/kong/spec/fixtures/perf/terraform/aws-ec2/main.tf
new file mode 100644
index 00000000..a6fd2d5e
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/fixtures/perf/terraform/aws-ec2/main.tf
@@ -0,0 +1,26 @@
+terraform {
+ required_version = "~> 1.2"
+
+ required_providers {
+ local = {
+ version = "~> 2.2"
+ }
+ null = {
+ version = "~> 3.1"
+ }
+ aws = {
+ source = "hashicorp/aws"
+ version = "~> 3.0"
+ }
+ tls = {
+ version = "~> 3.4"
+ }
+ random = {
+ version = "~> 3.3"
+ }
+ }
+}
+
+provider "aws" {
+ region = var.aws_region
+}
diff --git a/kong-versions/3.9.0.0/kong/spec/fixtures/perf/terraform/aws-ec2/output.tf b/kong-versions/3.9.0.0/kong/spec/fixtures/perf/terraform/aws-ec2/output.tf
new file mode 100644
index 00000000..79156979
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/fixtures/perf/terraform/aws-ec2/output.tf
@@ -0,0 +1,23 @@
+output "kong-ip" {
+ value = aws_instance.kong.public_ip
+}
+
+output "kong-internal-ip" {
+ value = aws_instance.kong.private_ip
+}
+
+output "db-ip" {
+ value = var.seperate_db_node ? aws_instance.db.0.public_ip: ""
+}
+
+output "db-internal-ip" {
+ value = var.seperate_db_node ? aws_instance.db.0.private_ip: ""
+}
+
+output "worker-ip" {
+ value = aws_instance.worker.public_ip
+}
+
+output "worker-internal-ip" {
+ value = aws_instance.worker.private_ip
+}
diff --git a/kong-versions/3.9.0.0/kong/spec/fixtures/perf/terraform/aws-ec2/ssh.tf b/kong-versions/3.9.0.0/kong/spec/fixtures/perf/terraform/aws-ec2/ssh.tf
new file mode 100644
index 00000000..30629007
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/fixtures/perf/terraform/aws-ec2/ssh.tf
@@ -0,0 +1,10 @@
+resource "tls_private_key" "key" {
+ algorithm = "RSA"
+}
+
+
+resource "local_sensitive_file" "key_priv" {
+ content = tls_private_key.key.private_key_pem
+ filename = "./id_rsa"
+ file_permission = "0600"
+}
diff --git a/kong-versions/3.9.0.0/kong/spec/fixtures/perf/terraform/aws-ec2/variables.tf b/kong-versions/3.9.0.0/kong/spec/fixtures/perf/terraform/aws-ec2/variables.tf
new file mode 100644
index 00000000..f357e884
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/fixtures/perf/terraform/aws-ec2/variables.tf
@@ -0,0 +1,36 @@
+variable "aws_region" {
+ type = string
+ description = "The EC2 region in which to create the EC2 instances"
+ default = "us-east-2"
+}
+
+variable "ec2_instance_type" {
+ type = string
+ description = "The EC2 size on which to run the kong"
+ default = "c5a.2xlarge"
+}
+
+variable "ec2_instance_worker_type" {
+ type = string
+ description = "The EC2 size on which to run the worker"
+ default = "c5a.large"
+}
+
+variable "ec2_instance_db_type" {
+ type = string
+ description = "The EC2 size on which to run the db"
+ default = "c5a.large"
+}
+
+variable "ec2_os" {
+ type = string
+ description = "The OS to install on the EC2"
+ default = "ubuntu/images/hvm-ssd/ubuntu-focal-20.04-amd64-server-*"
+}
+
+variable "seperate_db_node" {
+ type = bool
+ description = "Whether to create a separate db instance"
+ default = false
+}
+
diff --git a/kong-versions/3.9.0.0/kong/spec/fixtures/perf/terraform/bring-your-own/main.tf b/kong-versions/3.9.0.0/kong/spec/fixtures/perf/terraform/bring-your-own/main.tf
new file mode 100644
index 00000000..2d446342
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/fixtures/perf/terraform/bring-your-own/main.tf
@@ -0,0 +1,10 @@
+terraform {
+ required_version = "~> 1.2"
+
+ required_providers {
+ local = {
+ version = "~> 2.2"
+ }
+ }
+}
+
diff --git a/kong-versions/3.9.0.0/kong/spec/fixtures/perf/terraform/bring-your-own/output.tf b/kong-versions/3.9.0.0/kong/spec/fixtures/perf/terraform/bring-your-own/output.tf
new file mode 100644
index 00000000..a01f3ea9
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/fixtures/perf/terraform/bring-your-own/output.tf
@@ -0,0 +1,23 @@
+output "kong-ip" {
+ value = var.kong_ip
+}
+
+output "kong-internal-ip" {
+ value = local.kong_internal_ip_fallback
+}
+
+output "db-ip" {
+ value = var.db_ip
+}
+
+output "db-internal-ip" {
+ value = var.db_internal_ip
+}
+
+output "worker-ip" {
+ value = var.worker_ip
+}
+
+output "worker-internal-ip" {
+ value = local.worker_internal_ip_fallback
+}
diff --git a/kong-versions/3.9.0.0/kong/spec/fixtures/perf/terraform/bring-your-own/ssh.tf b/kong-versions/3.9.0.0/kong/spec/fixtures/perf/terraform/bring-your-own/ssh.tf
new file mode 100644
index 00000000..1659b857
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/fixtures/perf/terraform/bring-your-own/ssh.tf
@@ -0,0 +1,6 @@
+# copy the file to current directory to be loaded by framework
+resource "local_sensitive_file" "key_priv" {
+ source = var.ssh_key_path
+ filename = "./id_rsa"
+ file_permission = "0600"
+}
\ No newline at end of file
diff --git a/kong-versions/3.9.0.0/kong/spec/fixtures/perf/terraform/bring-your-own/variables.tf b/kong-versions/3.9.0.0/kong/spec/fixtures/perf/terraform/bring-your-own/variables.tf
new file mode 100644
index 00000000..f34c1fab
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/fixtures/perf/terraform/bring-your-own/variables.tf
@@ -0,0 +1,43 @@
+variable "kong_ip" {
+ type = string
+}
+
+variable "kong_internal_ip" {
+ type = string
+ default = ""
+}
+
+variable "worker_ip" {
+ type = string
+}
+
+variable "worker_internal_ip" {
+ type = string
+ default = ""
+}
+
+locals {
+ kong_internal_ip_fallback = var.kong_internal_ip != "" ? var.kong_internal_ip : var.kong_ip
+ worker_internal_ip_fallback = var.worker_internal_ip != "" ? var.worker_internal_ip : var.worker_ip
+}
+
+# db IP fallback is done in the lua part
+variable "db_ip" {
+ type = string
+ default = ""
+}
+
+variable "db_internal_ip" {
+ type = string
+ default = ""
+}
+
+variable "ssh_key_path" {
+ type = string
+}
+
+variable "seperate_db_node" {
+ type = bool
+ description = "Whether to create a separate db instance"
+ default = false
+}
diff --git a/kong-versions/3.9.0.0/kong/spec/fixtures/perf/terraform/digitalocean/.gitignore b/kong-versions/3.9.0.0/kong/spec/fixtures/perf/terraform/digitalocean/.gitignore
new file mode 100644
index 00000000..cbd4daf5
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/fixtures/perf/terraform/digitalocean/.gitignore
@@ -0,0 +1,8 @@
+.terraform*
+!.terraform-version
+terraform.tfstate*
+*.deb
+output
+id_rsa
+license.json
+cm-*
diff --git a/kong-versions/3.9.0.0/kong/spec/fixtures/perf/terraform/digitalocean/droplets.tf b/kong-versions/3.9.0.0/kong/spec/fixtures/perf/terraform/digitalocean/droplets.tf
new file mode 100644
index 00000000..bfdd2e01
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/fixtures/perf/terraform/digitalocean/droplets.tf
@@ -0,0 +1,34 @@
+resource "digitalocean_ssh_key" "key" {
+ name = "key1"
+ public_key = tls_private_key.key.public_key_openssh
+}
+
+resource "digitalocean_droplet" "kong" {
+ name = "kong-${random_string.ident.result}"
+ size = var.do_size
+ region = var.do_region
+ image = var.do_os
+ ssh_keys = [digitalocean_ssh_key.key.fingerprint]
+}
+
+resource "digitalocean_droplet" "db" {
+ count = var.seperate_db_node ? 1: 0
+ name = "db-${random_string.ident.result}"
+ size = var.do_db_size
+ region = var.do_region
+ image = var.do_os
+ ssh_keys = [digitalocean_ssh_key.key.fingerprint]
+}
+
+resource "digitalocean_droplet" "worker" {
+ name = "worker-${random_string.ident.result}"
+ size = var.do_worker_size
+ region = var.do_region
+ image = var.do_os
+ ssh_keys = [digitalocean_ssh_key.key.fingerprint]
+}
+
+resource "random_string" "ident" {
+ length = 4
+ special = false
+}
diff --git a/kong-versions/3.9.0.0/kong/spec/fixtures/perf/terraform/digitalocean/main.tf b/kong-versions/3.9.0.0/kong/spec/fixtures/perf/terraform/digitalocean/main.tf
new file mode 100644
index 00000000..e6f29bbd
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/fixtures/perf/terraform/digitalocean/main.tf
@@ -0,0 +1,26 @@
+terraform {
+ required_version = "~> 1.2"
+
+ required_providers {
+ local = {
+ version = "~> 2.2"
+ }
+ null = {
+ version = "~> 3.1"
+ }
+ digitalocean = {
+ source = "digitalocean/digitalocean"
+ version = "~> 2.0"
+ }
+ tls = {
+ version = "~> 3.4"
+ }
+ random = {
+ version = "~> 3.3"
+ }
+ }
+}
+
+provider "digitalocean" {
+ token = var.do_token
+}
diff --git a/kong-versions/3.9.0.0/kong/spec/fixtures/perf/terraform/digitalocean/output.tf b/kong-versions/3.9.0.0/kong/spec/fixtures/perf/terraform/digitalocean/output.tf
new file mode 100644
index 00000000..f5c06c89
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/fixtures/perf/terraform/digitalocean/output.tf
@@ -0,0 +1,23 @@
+output "kong-ip" {
+ value = digitalocean_droplet.kong.ipv4_address
+}
+
+output "kong-internal-ip" {
+ value = digitalocean_droplet.kong.ipv4_address_private
+}
+
+output "db-ip" {
+ value = var.seperate_db_node ? digitalocean_droplet.db.0.ipv4_address: ""
+}
+
+output "db-internal-ip" {
+ value = var.seperate_db_node ? digitalocean_droplet.db.0.ipv4_address_private: ""
+}
+
+output "worker-ip" {
+ value = digitalocean_droplet.worker.ipv4_address
+}
+
+output "worker-internal-ip" {
+ value = digitalocean_droplet.worker.ipv4_address_private
+}
diff --git a/kong-versions/3.9.0.0/kong/spec/fixtures/perf/terraform/digitalocean/project.tf b/kong-versions/3.9.0.0/kong/spec/fixtures/perf/terraform/digitalocean/project.tf
new file mode 100644
index 00000000..eadd28e1
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/fixtures/perf/terraform/digitalocean/project.tf
@@ -0,0 +1,12 @@
+data "digitalocean_project" "benchmark" {
+ name = var.do_project_name
+}
+
+resource "digitalocean_project_resources" "benchmark" {
+ project = data.digitalocean_project.benchmark.id
+ resources = [
+ digitalocean_droplet.kong.urn,
+ digitalocean_droplet.db.urn,
+ digitalocean_droplet.worker.urn
+ ]
+}
\ No newline at end of file
diff --git a/kong-versions/3.9.0.0/kong/spec/fixtures/perf/terraform/digitalocean/ssh.tf b/kong-versions/3.9.0.0/kong/spec/fixtures/perf/terraform/digitalocean/ssh.tf
new file mode 100644
index 00000000..30629007
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/fixtures/perf/terraform/digitalocean/ssh.tf
@@ -0,0 +1,10 @@
+resource "tls_private_key" "key" {
+ algorithm = "RSA"
+}
+
+
+resource "local_sensitive_file" "key_priv" {
+ content = tls_private_key.key.private_key_pem
+ filename = "./id_rsa"
+ file_permission = "0600"
+}
diff --git a/kong-versions/3.9.0.0/kong/spec/fixtures/perf/terraform/digitalocean/variables.tf b/kong-versions/3.9.0.0/kong/spec/fixtures/perf/terraform/digitalocean/variables.tf
new file mode 100644
index 00000000..9bdaee70
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/fixtures/perf/terraform/digitalocean/variables.tf
@@ -0,0 +1,49 @@
+variable "do_token" {
+ type = string
+ description = "The digitalocean auth token"
+}
+
+variable "do_project_name" {
+ type = string
+ description = "The digitalocean project ID under which to create the droplets"
+ default = "Benchmark"
+}
+
+variable "do_size" {
+ type = string
+ description = "The droplet size on which to create the kong droplet"
+ default = "c2-8vpcu-16gb"
+}
+
+variable "do_worker_size" {
+ type = string
+ description = "The droplet size on which to create the worker droplet"
+ default = "s-1vcpu-1gb"
+}
+
+variable "do_db_size" {
+ type = string
+ description = "The droplet size on which to create the db droplet"
+ default = "s-1vcpu-1gb"
+}
+
+
+variable "do_region" {
+ type = string
+ description = "The digitalocean region in which to create the droplets"
+ default = "sfo3"
+}
+
+variable "do_os" {
+ type = string
+ description = "The OS to install on the Metal droplets"
+ default = "ubuntu-20-04-x64"
+}
+
+variable "seperate_db_node" {
+ type = bool
+ description = "Whether to create a separate db instance"
+ default = false
+}
+
+
diff --git a/kong-versions/3.9.0.0/kong/spec/fixtures/perf/terraform/equinix-metal/.gitignore b/kong-versions/3.9.0.0/kong/spec/fixtures/perf/terraform/equinix-metal/.gitignore
new file mode 100644
index 00000000..cbd4daf5
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/fixtures/perf/terraform/equinix-metal/.gitignore
@@ -0,0 +1,8 @@
+.terraform*
+!.terraform-version
+terraform.tfstate*
+*.deb
+output
+id_rsa
+license.json
+cm-*
diff --git a/kong-versions/3.9.0.0/kong/spec/fixtures/perf/terraform/equinix-metal/README.md b/kong-versions/3.9.0.0/kong/spec/fixtures/perf/terraform/equinix-metal/README.md
new file mode 100644
index 00000000..33266d29
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/fixtures/perf/terraform/equinix-metal/README.md
@@ -0,0 +1,5 @@
+Perf test terraform driver expects:
+- `id_rsa` as the private key present
+- `kong-ip`, `kong-internal-ip`, `worker-ip` and `worker-internal-ip`
+to present in terraform output. If instance has no private IP,
+use `-ip` as `-internal-ip` is also accepted.
diff --git a/kong-versions/3.9.0.0/kong/spec/fixtures/perf/terraform/equinix-metal/main.tf b/kong-versions/3.9.0.0/kong/spec/fixtures/perf/terraform/equinix-metal/main.tf
new file mode 100644
index 00000000..57e7eeb7
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/fixtures/perf/terraform/equinix-metal/main.tf
@@ -0,0 +1,26 @@
+terraform {
+ required_version = "~> 1.2"
+
+ required_providers {
+ local = {
+ version = "~> 2.2"
+ }
+ null = {
+ version = "~> 3.1"
+ }
+ equinix = {
+ source = "equinix/equinix"
+ version = "~> 1.6"
+ }
+ tls = {
+ version = "~> 3.4"
+ }
+ random = {
+ version = "~> 3.3"
+ }
+ }
+}
+
+provider "equinix" {
+ auth_token = var.metal_auth_token
+}
diff --git a/kong-versions/3.9.0.0/kong/spec/fixtures/perf/terraform/equinix-metal/metal.tf b/kong-versions/3.9.0.0/kong/spec/fixtures/perf/terraform/equinix-metal/metal.tf
new file mode 100644
index 00000000..af8a39f9
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/fixtures/perf/terraform/equinix-metal/metal.tf
@@ -0,0 +1,49 @@
+resource "equinix_metal_ssh_key" "key" {
+ name = "key1"
+ public_key = tls_private_key.key.public_key_openssh
+}
+
+resource "equinix_metal_device" "kong" {
+ hostname = "kong-${random_string.ident.result}"
+ plan = var.metal_plan
+ facilities = var.metal_region
+ operating_system = var.metal_os
+ billing_cycle = "hourly"
+ project_id = var.metal_project_id
+ tags = []
+ depends_on = [
+ equinix_metal_ssh_key.key,
+ ]
+}
+
+resource "equinix_metal_device" "db" {
+ count = var.seperate_db_node ? 1: 0
+ hostname = "db-${random_string.ident.result}"
+ plan = var.metal_db_plan
+ facilities = var.metal_region
+ operating_system = var.metal_os
+ billing_cycle = "hourly"
+ project_id = var.metal_project_id
+ tags = []
+ depends_on = [
+ equinix_metal_ssh_key.key,
+ ]
+}
+
+resource "equinix_metal_device" "worker" {
+ hostname = "worker-${random_string.ident.result}"
+ plan = var.metal_worker_plan
+ facilities = var.metal_region
+ operating_system = var.metal_os
+ billing_cycle = "hourly"
+ project_id = var.metal_project_id
+ tags = []
+ depends_on = [
+ equinix_metal_ssh_key.key,
+ ]
+}
+
+resource "random_string" "ident" {
+ length = 4
+ special = false
+}
diff --git a/kong-versions/3.9.0.0/kong/spec/fixtures/perf/terraform/equinix-metal/output.tf b/kong-versions/3.9.0.0/kong/spec/fixtures/perf/terraform/equinix-metal/output.tf
new file mode 100644
index 00000000..18a40e86
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/fixtures/perf/terraform/equinix-metal/output.tf
@@ -0,0 +1,23 @@
+output "kong-ip" {
+ value = equinix_metal_device.kong.access_public_ipv4
+}
+
+output "kong-internal-ip" {
+ value = equinix_metal_device.kong.access_private_ipv4
+}
+
+output "db-ip" {
+ value = var.seperate_db_node ? equinix_metal_device.db.0.access_public_ipv4: ""
+}
+
+output "db-internal-ip" {
+ value = var.seperate_db_node ? equinix_metal_device.db.0.access_private_ipv4: ""
+}
+
+output "worker-ip" {
+ value = equinix_metal_device.worker.access_public_ipv4
+}
+
+output "worker-internal-ip" {
+ value = equinix_metal_device.worker.access_private_ipv4
+}
diff --git a/kong-versions/3.9.0.0/kong/spec/fixtures/perf/terraform/equinix-metal/scripts/wrk.lua b/kong-versions/3.9.0.0/kong/spec/fixtures/perf/terraform/equinix-metal/scripts/wrk.lua
new file mode 100644
index 00000000..d8cd38b6
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/fixtures/perf/terraform/equinix-metal/scripts/wrk.lua
@@ -0,0 +1,54 @@
+-- This software is copyright Kong Inc. and its licensors.
+-- Use of the software is subject to the agreement between your organization
+-- and Kong Inc. If there is no such agreement, use is governed by and
+-- subject to the terms of the Kong Master Software License Agreement found
+-- at https://konghq.com/enterprisesoftwarelicense/.
+-- [ END OF LICENSE 0867164ffc95e54f04670b5169c09574bdbd9bba ]
+
+-- luacheck: ignore
+--This script is executed in conjuction with the wrk benchmarking tool via demo.sh
+math.randomseed(os.time()) -- Generate PRNG seed
+local rand = math.random -- Cache random method
+
+-- Get env vars for consumer and api count or assign defaults
+local consumer_count = os.getenv("KONG_DEMO_CONSUMER_COUNT") or 5
+local service_count = os.getenv("KONG_DEMO_SERVICE_COUNT") or 5
+local workspace_count = os.getenv("KONG_DEMO_WORKSPACE_COUNT") or 1
+local route_per_service = os.getenv("KONG_DEMO_ROUTE_PER_SERVICE") or 5
+
+function request()
+ -- generate random URLs, some of which may yield non-200 response codes
+ local random_consumer = rand(consumer_count)
+ local random_service = rand(service_count)
+ local random_route = rand(route_per_service)
+ -- Concat the url parts
+ if workspace_count == 1 then
+ url_path = string.format("/s%s-r%s?apikey=consumer-%s", random_service, random_route, random_consumer)
+ else
+ random_workspace = rand(workspace_count)
+ url_path = string.format("/w%s-s%s-r%s?apikey=consumer-%s", random_workspace, random_service, random_route, random_consumer)
+ end
+ -- Return the request object with the current URL path
+ return wrk.format(nil, url_path, headers)
+end
+
+--[[function done(summary, latency, requests)
+ local file = io.open("output.csv", "a")
+ file:write(string.format(
+ "%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d\n",
+ os.time(),
+ latency.min,
+ latency.max,
+ latency.mean,
+ latency:percentile(50),
+ latency:percentile(90),
+ latency:percentile(99),
+ summary.duration,
+ summary.requests,
+ summary.errors.connect,
+ summary.errors.read,
+ summary.errors.write,
+ summary.errors.status,
+ summary.errors.timeout
+ ))
+end]]
diff --git a/kong-versions/3.9.0.0/kong/spec/fixtures/perf/terraform/equinix-metal/ssh.tf b/kong-versions/3.9.0.0/kong/spec/fixtures/perf/terraform/equinix-metal/ssh.tf
new file mode 100644
index 00000000..9ca74532
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/fixtures/perf/terraform/equinix-metal/ssh.tf
@@ -0,0 +1,5 @@
+resource "local_sensitive_file" "key_priv" {
+ content = tls_private_key.key.private_key_pem
+ filename = "./id_rsa"
+ file_permission = "0600"
+}
diff --git a/kong-versions/3.9.0.0/kong/spec/fixtures/perf/terraform/equinix-metal/tls.tf b/kong-versions/3.9.0.0/kong/spec/fixtures/perf/terraform/equinix-metal/tls.tf
new file mode 100644
index 00000000..1ee3f01a
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/fixtures/perf/terraform/equinix-metal/tls.tf
@@ -0,0 +1,4 @@
+resource "tls_private_key" "key" {
+ algorithm = "RSA"
+}
+
diff --git a/kong-versions/3.9.0.0/kong/spec/fixtures/perf/terraform/equinix-metal/variables.tf b/kong-versions/3.9.0.0/kong/spec/fixtures/perf/terraform/equinix-metal/variables.tf
new file mode 100644
index 00000000..69792e03
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/fixtures/perf/terraform/equinix-metal/variables.tf
@@ -0,0 +1,48 @@
+variable "metal_auth_token" {
+ type = string
+ description = "The pre-existing Metal auth token"
+}
+
+variable "metal_project_id" {
+ type = string
+ description = "The pre-existing Metal project ID under which to create the devices"
+}
+
+variable "metal_plan" {
+ type = string
+ description = "The Metal device plan on which to create the kong devices"
+ default = "c3.small.x86"
+}
+
+variable "metal_worker_plan" {
+ type = string
+ description = "The Metal device plan on which to create the worker devices"
+ default = "c3.small.x86"
+}
+
+variable "metal_db_plan" {
+ type = string
+ description = "The Metal device plan on which to create the db devices"
+ default = "c3.small.x86"
+}
+
+variable "metal_region" {
+ type = list(string)
+ description = "The Metal region in which to create the devices"
+ # All AMER facilities
+ default = ["dc13", "da11", "sv15", "sv16", "sp4", "ch3", "ny5", "ny7", "la4", "tr2", "se4"]
+}
+
+variable "metal_os" {
+ type = string
+ description = "The OS to install on the Metal devices"
+ default = "ubuntu_20_04"
+}
+
+variable "seperate_db_node" {
+ type = bool
+ description = "Whether to create a separate db instance"
+ default = false
+}
+
+
diff --git a/kong-versions/3.9.0.0/kong/spec/fixtures/prometheus/metrics.conf b/kong-versions/3.9.0.0/kong/spec/fixtures/prometheus/metrics.conf
new file mode 100644
index 00000000..8436a97a
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/fixtures/prometheus/metrics.conf
@@ -0,0 +1,13 @@
+server {
+ server_name kong_prometheus_exporter;
+ listen 0.0.0.0:9542;
+
+ location / {
+ default_type text/plain;
+ content_by_lua_block {
+ local serve = require "kong.plugins.prometheus.serve"
+ serve.prometheus_server()
+ }
+ }
+
+}
diff --git a/kong-versions/3.9.0.0/kong/spec/fixtures/proxy_wasm_filters/Cargo.lock b/kong-versions/3.9.0.0/kong/spec/fixtures/proxy_wasm_filters/Cargo.lock
new file mode 100644
index 00000000..5c0d98b6
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/fixtures/proxy_wasm_filters/Cargo.lock
@@ -0,0 +1,753 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+version = 3
+
+[[package]]
+name = "addr2line"
+version = "0.19.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a76fd60b23679b7d19bd066031410fb7e458ccc5e958eb5c325888ce4baedc97"
+dependencies = [
+ "gimli",
+]
+
+[[package]]
+name = "adler"
+version = "1.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
+
+[[package]]
+name = "ahash"
+version = "0.8.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2c99f64d1e06488f620f932677e24bc6e2897582980441ae90a671415bd7ec2f"
+dependencies = [
+ "cfg-if",
+ "once_cell",
+ "version_check",
+]
+
+[[package]]
+name = "aho-corasick"
+version = "0.7.20"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cc936419f96fa211c1b9166887b38e5e40b19958e5b895be7c1f93adec7071ac"
+dependencies = [
+ "memchr",
+]
+
+[[package]]
+name = "android_system_properties"
+version = "0.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311"
+dependencies = [
+ "libc",
+]
+
+[[package]]
+name = "autocfg"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
+
+[[package]]
+name = "backtrace"
+version = "0.3.67"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "233d376d6d185f2a3093e58f283f60f880315b6c60075b01f36b3b85154564ca"
+dependencies = [
+ "addr2line",
+ "cc",
+ "cfg-if",
+ "libc",
+ "miniz_oxide",
+ "object",
+ "rustc-demangle",
+]
+
+[[package]]
+name = "bumpalo"
+version = "3.12.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0d261e256854913907f67ed06efbc3338dfe6179796deefc1ff763fc1aee5535"
+
+[[package]]
+name = "bytes"
+version = "1.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be"
+
+[[package]]
+name = "cc"
+version = "1.0.79"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f"
+
+[[package]]
+name = "cfg-if"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
+
+[[package]]
+name = "chrono"
+version = "0.4.24"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4e3c5919066adf22df73762e50cffcde3a758f2a848b113b586d1f86728b673b"
+dependencies = [
+ "iana-time-zone",
+ "js-sys",
+ "num-integer",
+ "num-traits",
+ "time",
+ "wasm-bindgen",
+ "winapi",
+]
+
+[[package]]
+name = "codespan-reporting"
+version = "0.11.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3538270d33cc669650c4b093848450d380def10c331d38c768e34cac80576e6e"
+dependencies = [
+ "termcolor",
+ "unicode-width",
+]
+
+[[package]]
+name = "core-foundation-sys"
+version = "0.8.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc"
+
+[[package]]
+name = "cxx"
+version = "1.0.92"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9a140f260e6f3f79013b8bfc65e7ce630c9ab4388c6a89c71e07226f49487b72"
+dependencies = [
+ "cc",
+ "cxxbridge-flags",
+ "cxxbridge-macro",
+ "link-cplusplus",
+]
+
+[[package]]
+name = "cxx-build"
+version = "1.0.92"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "da6383f459341ea689374bf0a42979739dc421874f112ff26f829b8040b8e613"
+dependencies = [
+ "cc",
+ "codespan-reporting",
+ "once_cell",
+ "proc-macro2",
+ "quote",
+ "scratch",
+ "syn",
+]
+
+[[package]]
+name = "cxxbridge-flags"
+version = "1.0.92"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "90201c1a650e95ccff1c8c0bb5a343213bdd317c6e600a93075bca2eff54ec97"
+
+[[package]]
+name = "cxxbridge-macro"
+version = "1.0.92"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0b75aed41bb2e6367cae39e6326ef817a851db13c13e4f3263714ca3cfb8de56"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "enum-utils"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ed327f716d0d351d86c9fd3398d20ee39ad8f681873cc081da2ca1c10fed398a"
+dependencies = [
+ "enum-utils-from-str",
+ "failure",
+ "proc-macro2",
+ "quote",
+ "serde_derive_internals",
+ "syn",
+]
+
+[[package]]
+name = "enum-utils-from-str"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d49be08bad6e4ca87b2b8e74146987d4e5cb3b7512efa50ef505b51a22227ee1"
+dependencies = [
+ "proc-macro2",
+ "quote",
+]
+
+[[package]]
+name = "failure"
+version = "0.1.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d32e9bd16cc02eae7db7ef620b392808b89f6a5e16bb3497d159c6b92a0f4f86"
+dependencies = [
+ "backtrace",
+]
+
+[[package]]
+name = "fnv"
+version = "1.0.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
+
+[[package]]
+name = "form_urlencoded"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a9c384f161156f5260c24a097c56119f9be8c798586aecc13afbcbe7b7e26bf8"
+dependencies = [
+ "percent-encoding",
+]
+
+[[package]]
+name = "gimli"
+version = "0.27.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ad0a93d233ebf96623465aad4046a8d3aa4da22d4f4beba5388838c8a434bbb4"
+
+[[package]]
+name = "hashbrown"
+version = "0.13.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "43a3c133739dddd0d2990f9a4bdf8eb4b21ef50e4851ca85ab661199821d510e"
+dependencies = [
+ "ahash",
+]
+
+[[package]]
+name = "http"
+version = "0.2.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bd6effc99afb63425aff9b05836f029929e345a6148a14b7ecd5ab67af944482"
+dependencies = [
+ "bytes",
+ "fnv",
+ "itoa",
+]
+
+[[package]]
+name = "iana-time-zone"
+version = "0.1.53"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "64c122667b287044802d6ce17ee2ddf13207ed924c712de9a66a5814d5b64765"
+dependencies = [
+ "android_system_properties",
+ "core-foundation-sys",
+ "iana-time-zone-haiku",
+ "js-sys",
+ "wasm-bindgen",
+ "winapi",
+]
+
+[[package]]
+name = "iana-time-zone-haiku"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0703ae284fc167426161c2e3f1da3ea71d94b21bedbcc9494e92b28e334e3dca"
+dependencies = [
+ "cxx",
+ "cxx-build",
+]
+
+[[package]]
+name = "idna"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e14ddfc70884202db2244c223200c204c2bda1bc6e0998d11b5e024d657209e6"
+dependencies = [
+ "unicode-bidi",
+ "unicode-normalization",
+]
+
+[[package]]
+name = "itoa"
+version = "1.0.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6"
+
+[[package]]
+name = "js-sys"
+version = "0.3.61"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "445dde2150c55e483f3d8416706b97ec8e8237c307e5b7b4b8dd15e6af2a0730"
+dependencies = [
+ "wasm-bindgen",
+]
+
+[[package]]
+name = "lazy_static"
+version = "1.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
+
+[[package]]
+name = "libc"
+version = "0.2.140"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "99227334921fae1a979cf0bfdfcc6b3e5ce376ef57e16fb6fb3ea2ed6095f80c"
+
+[[package]]
+name = "link-cplusplus"
+version = "1.0.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ecd207c9c713c34f95a097a5b029ac2ce6010530c7b49d7fea24d977dede04f5"
+dependencies = [
+ "cc",
+]
+
+[[package]]
+name = "log"
+version = "0.4.17"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e"
+dependencies = [
+ "cfg-if",
+]
+
+[[package]]
+name = "memchr"
+version = "2.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
+
+[[package]]
+name = "miniz_oxide"
+version = "0.6.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b275950c28b37e794e8c55d88aeb5e139d0ce23fdbbeda68f8d7174abdf9e8fa"
+dependencies = [
+ "adler",
+]
+
+[[package]]
+name = "num"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b8536030f9fea7127f841b45bb6243b27255787fb4eb83958aa1ef9d2fdc0c36"
+dependencies = [
+ "num-bigint",
+ "num-complex",
+ "num-integer",
+ "num-iter",
+ "num-rational",
+ "num-traits",
+]
+
+[[package]]
+name = "num-bigint"
+version = "0.2.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "090c7f9998ee0ff65aa5b723e4009f7b217707f1fb5ea551329cc4d6231fb304"
+dependencies = [
+ "autocfg",
+ "num-integer",
+ "num-traits",
+]
+
+[[package]]
+name = "num-complex"
+version = "0.2.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b6b19411a9719e753aff12e5187b74d60d3dc449ec3f4dc21e3989c3f554bc95"
+dependencies = [
+ "autocfg",
+ "num-traits",
+]
+
+[[package]]
+name = "num-integer"
+version = "0.1.45"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9"
+dependencies = [
+ "autocfg",
+ "num-traits",
+]
+
+[[package]]
+name = "num-iter"
+version = "0.1.43"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7d03e6c028c5dc5cac6e2dec0efda81fc887605bb3d884578bb6d6bf7514e252"
+dependencies = [
+ "autocfg",
+ "num-integer",
+ "num-traits",
+]
+
+[[package]]
+name = "num-rational"
+version = "0.2.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5c000134b5dbf44adc5cb772486d335293351644b801551abe8f75c84cfa4aef"
+dependencies = [
+ "autocfg",
+ "num-bigint",
+ "num-integer",
+ "num-traits",
+]
+
+[[package]]
+name = "num-traits"
+version = "0.2.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd"
+dependencies = [
+ "autocfg",
+]
+
+[[package]]
+name = "object"
+version = "0.30.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ea86265d3d3dcb6a27fc51bd29a4bf387fae9d2986b823079d4986af253eb439"
+dependencies = [
+ "memchr",
+]
+
+[[package]]
+name = "once_cell"
+version = "1.17.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3"
+
+[[package]]
+name = "parse_duration"
+version = "2.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7037e5e93e0172a5a96874380bf73bc6ecef022e26fa25f2be26864d6b3ba95d"
+dependencies = [
+ "lazy_static",
+ "num",
+ "regex",
+]
+
+[[package]]
+name = "percent-encoding"
+version = "2.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e"
+
+[[package]]
+name = "proc-macro2"
+version = "1.0.52"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1d0e1ae9e836cc3beddd63db0df682593d7e2d3d891ae8c9083d2113e1744224"
+dependencies = [
+ "unicode-ident",
+]
+
+[[package]]
+name = "proxy-wasm"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "823b744520cd4a54ba7ebacbffe4562e839d6dcd8f89209f96a1ace4f5229cd4"
+dependencies = [
+ "hashbrown",
+ "log",
+]
+
+[[package]]
+name = "quote"
+version = "1.0.26"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4424af4bf778aae2051a77b60283332f386554255d722233d09fbfc7e30da2fc"
+dependencies = [
+ "proc-macro2",
+]
+
+[[package]]
+name = "regex"
+version = "1.7.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "48aaa5748ba571fb95cd2c85c09f629215d3a6ece942baa100950af03a34f733"
+dependencies = [
+ "aho-corasick",
+ "memchr",
+ "regex-syntax",
+]
+
+[[package]]
+name = "regex-syntax"
+version = "0.6.28"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848"
+
+[[package]]
+name = "response_transformer"
+version = "0.0.1"
+dependencies = [
+ "log",
+ "proxy-wasm",
+ "serde",
+ "serde_json",
+]
+
+[[package]]
+name = "rustc-demangle"
+version = "0.1.21"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7ef03e0a2b150c7a90d01faf6254c9c48a41e95fb2a8c2ac1c6f0d2b9aefc342"
+
+[[package]]
+name = "ryu"
+version = "1.0.13"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f91339c0467de62360649f8d3e185ca8de4224ff281f66000de5eb2a77a79041"
+
+[[package]]
+name = "scratch"
+version = "1.0.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1792db035ce95be60c3f8853017b3999209281c24e2ba5bc8e59bf97a0c590c1"
+
+[[package]]
+name = "serde"
+version = "1.0.156"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "314b5b092c0ade17c00142951e50ced110ec27cea304b1037c6969246c2469a4"
+dependencies = [
+ "serde_derive",
+]
+
+[[package]]
+name = "serde_derive"
+version = "1.0.156"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d7e29c4601e36bcec74a223228dce795f4cd3616341a4af93520ca1a837c087d"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "serde_derive_internals"
+version = "0.25.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1dbab34ca63057a1f15280bdf3c39f2b1eb1b54c17e98360e511637aef7418c6"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "serde_json"
+version = "1.0.94"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1c533a59c9d8a93a09c6ab31f0fd5e5f4dd1b8fc9434804029839884765d04ea"
+dependencies = [
+ "itoa",
+ "ryu",
+ "serde",
+]
+
+[[package]]
+name = "syn"
+version = "1.0.109"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "unicode-ident",
+]
+
+[[package]]
+name = "termcolor"
+version = "1.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "be55cf8942feac5c765c2c993422806843c9a9a45d4d5c407ad6dd2ea95eb9b6"
+dependencies = [
+ "winapi-util",
+]
+
+[[package]]
+name = "tests"
+version = "0.0.1"
+dependencies = [
+ "chrono",
+ "enum-utils",
+ "http",
+ "log",
+ "parse_duration",
+ "proxy-wasm",
+ "url",
+]
+
+[[package]]
+name = "time"
+version = "0.1.45"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1b797afad3f312d1c66a56d11d0316f916356d11bd158fbc6ca6389ff6bf805a"
+dependencies = [
+ "libc",
+ "wasi",
+ "winapi",
+]
+
+[[package]]
+name = "tinyvec"
+version = "1.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50"
+dependencies = [
+ "tinyvec_macros",
+]
+
+[[package]]
+name = "tinyvec_macros"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
+
+[[package]]
+name = "unicode-bidi"
+version = "0.3.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7d502c968c6a838ead8e69b2ee18ec708802f99db92a0d156705ec9ef801993b"
+
+[[package]]
+name = "unicode-ident"
+version = "1.0.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e5464a87b239f13a63a501f2701565754bae92d243d4bb7eb12f6d57d2269bf4"
+
+[[package]]
+name = "unicode-normalization"
+version = "0.1.22"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921"
+dependencies = [
+ "tinyvec",
+]
+
+[[package]]
+name = "unicode-width"
+version = "0.1.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b"
+
+[[package]]
+name = "url"
+version = "2.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0d68c799ae75762b8c3fe375feb6600ef5602c883c5d21eb51c09f22b83c4643"
+dependencies = [
+ "form_urlencoded",
+ "idna",
+ "percent-encoding",
+]
+
+[[package]]
+name = "version_check"
+version = "0.9.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
+
+[[package]]
+name = "wasi"
+version = "0.10.0+wasi-snapshot-preview1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f"
+
+[[package]]
+name = "wasm-bindgen"
+version = "0.2.84"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "31f8dcbc21f30d9b8f2ea926ecb58f6b91192c17e9d33594b3df58b2007ca53b"
+dependencies = [
+ "cfg-if",
+ "wasm-bindgen-macro",
+]
+
+[[package]]
+name = "wasm-bindgen-backend"
+version = "0.2.84"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "95ce90fd5bcc06af55a641a86428ee4229e44e07033963a2290a8e241607ccb9"
+dependencies = [
+ "bumpalo",
+ "log",
+ "once_cell",
+ "proc-macro2",
+ "quote",
+ "syn",
+ "wasm-bindgen-shared",
+]
+
+[[package]]
+name = "wasm-bindgen-macro"
+version = "0.2.84"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4c21f77c0bedc37fd5dc21f897894a5ca01e7bb159884559461862ae90c0b4c5"
+dependencies = [
+ "quote",
+ "wasm-bindgen-macro-support",
+]
+
+[[package]]
+name = "wasm-bindgen-macro-support"
+version = "0.2.84"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2aff81306fcac3c7515ad4e177f521b5c9a15f2b08f4e32d823066102f35a5f6"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+ "wasm-bindgen-backend",
+ "wasm-bindgen-shared",
+]
+
+[[package]]
+name = "wasm-bindgen-shared"
+version = "0.2.84"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0046fef7e28c3804e5e38bfa31ea2a0f73905319b677e57ebe37e49358989b5d"
+
+[[package]]
+name = "winapi"
+version = "0.3.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
+dependencies = [
+ "winapi-i686-pc-windows-gnu",
+ "winapi-x86_64-pc-windows-gnu",
+]
+
+[[package]]
+name = "winapi-i686-pc-windows-gnu"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
+
+[[package]]
+name = "winapi-util"
+version = "0.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178"
+dependencies = [
+ "winapi",
+]
+
+[[package]]
+name = "winapi-x86_64-pc-windows-gnu"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
diff --git a/kong-versions/3.9.0.0/kong/spec/fixtures/proxy_wasm_filters/Cargo.toml b/kong-versions/3.9.0.0/kong/spec/fixtures/proxy_wasm_filters/Cargo.toml
new file mode 100644
index 00000000..d8e358e7
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/fixtures/proxy_wasm_filters/Cargo.toml
@@ -0,0 +1,5 @@
+[workspace]
+members = [
+ "tests",
+ "response_transformer",
+]
diff --git a/kong-versions/3.9.0.0/kong/spec/fixtures/proxy_wasm_filters/response_transformer/Cargo.toml b/kong-versions/3.9.0.0/kong/spec/fixtures/proxy_wasm_filters/response_transformer/Cargo.toml
new file mode 100644
index 00000000..65b3e049
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/fixtures/proxy_wasm_filters/response_transformer/Cargo.toml
@@ -0,0 +1,15 @@
+[package]
+name = "response_transformer"
+version = "0.0.1"
+authors = ["Michael Martin "]
+edition = "2018"
+
+[lib]
+path = "src/filter.rs"
+crate-type = ["cdylib"]
+
+[dependencies]
+proxy-wasm = "0.2"
+serde = { version = "1.0", features = ["derive"] }
+serde_json = "1.0"
+log = "0.4"
diff --git a/kong-versions/3.9.0.0/kong/spec/fixtures/proxy_wasm_filters/response_transformer/src/filter.rs b/kong-versions/3.9.0.0/kong/spec/fixtures/proxy_wasm_filters/response_transformer/src/filter.rs
new file mode 100644
index 00000000..fb23189b
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/fixtures/proxy_wasm_filters/response_transformer/src/filter.rs
@@ -0,0 +1,92 @@
+mod types;
+
+use proxy_wasm::traits::{Context, RootContext, HttpContext};
+use proxy_wasm::types::{Action, LogLevel, ContextType};
+use crate::types::*;
+use serde_json;
+use log::*;
+
+proxy_wasm::main! {{
+ proxy_wasm::set_log_level(LogLevel::Info);
+ proxy_wasm::set_root_context(|_| -> Box {
+ Box::new(ResponseTransformerContext { config: Config::default() } )
+ });
+}}
+
+
+struct ResponseTransformerContext {
+ config: Config,
+}
+
+impl ResponseTransformerContext {
+}
+
+impl RootContext for ResponseTransformerContext {
+ fn on_configure(&mut self, _: usize) -> bool {
+ let bytes = self.get_plugin_configuration().unwrap();
+ match serde_json::from_slice::(bytes.as_slice()) {
+ Ok(config) => {
+ self.config = config;
+ true
+ },
+ Err(e) => {
+ error!("failed parsing filter config: {}", e);
+ false
+ }
+ }
+ }
+
+ fn create_http_context(&self, _: u32) -> Option> {
+ Some(Box::new(ResponseTransformerContext{
+ config: self.config.clone(),
+ }))
+ }
+
+ fn get_type(&self) -> Option {
+ Some(ContextType::HttpContext)
+ }
+}
+
+impl Context for ResponseTransformerContext {
+ fn on_done(&mut self) -> bool {
+ true
+ }
+}
+
+impl HttpContext for ResponseTransformerContext {
+ fn on_http_response_headers(&mut self, _num_headers: usize, _end_of_stream: bool) -> Action {
+ self.config.remove.headers.iter().for_each(|name| {
+ info!("[response-transformer] removing header: {}", name);
+ self.set_http_response_header(&name, None);
+ });
+
+ self.config.rename.headers.iter().for_each(|KeyValuePair(from, to)| {
+ info!("[response-transformer] renaming header {} => {}", from, to);
+ let value = self.get_http_response_header(&from);
+ self.set_http_response_header(&from, None);
+ self.set_http_response_header(&to, value.as_deref());
+ });
+
+ self.config.replace.headers.iter().for_each(|KeyValuePair(name, value)| {
+ if self.get_http_response_header(&name).is_some() {
+ info!("[response-transformer] updating header {} value to {}", name, value);
+ self.set_http_response_header(&name, Some(&value));
+ }
+ });
+
+ self.config.add.headers.iter().for_each(|KeyValuePair(name, value)| {
+ if self.get_http_response_header(&name).is_none() {
+ info!("[response-transformer] adding header {} => {}", name, value);
+ self.set_http_response_header(&name, Some(&value));
+ }
+ });
+
+ self.config.append.headers.iter().for_each(|KeyValuePair(name, value)| {
+ info!("[response-transformer] appending header {} => {}", name, value);
+ self.add_http_response_header(&name, &value);
+ });
+
+
+ Action::Continue
+ }
+}
diff --git a/kong-versions/3.9.0.0/kong/spec/fixtures/proxy_wasm_filters/response_transformer/src/types.rs b/kong-versions/3.9.0.0/kong/spec/fixtures/proxy_wasm_filters/response_transformer/src/types.rs
new file mode 100644
index 00000000..1e9d4342
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/fixtures/proxy_wasm_filters/response_transformer/src/types.rs
@@ -0,0 +1,99 @@
+use std::convert::TryFrom;
+use std::fmt;
+
+use serde::Deserialize;
+
+#[derive(Debug, Clone, PartialEq)]
+pub(crate) struct InvalidHeader(String);
+
+impl fmt::Display for InvalidHeader {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ write!(f, "Invalid : => {}", self.0)
+ }
+}
+
+#[derive(Debug, Clone, PartialEq, Eq, Deserialize)]
+#[serde(try_from = "String")]
+pub(crate) struct KeyValuePair(pub(crate) String, pub(crate) String);
+
+impl TryFrom for KeyValuePair {
+ type Error = InvalidHeader;
+
+ fn try_from(input: String) -> std::result::Result {
+ input
+ .split_once(':')
+ .filter(|(name, value)| {
+ name.len() > 0 && value.len() > 0
+ })
+ .ok_or_else(|| InvalidHeader(input.clone()))
+ .and_then(|(name, value)| {
+ Ok(KeyValuePair(name.to_string(), value.to_string()))
+ })
+ }
+}
+
+impl TryFrom<&str> for KeyValuePair {
+ type Error = InvalidHeader;
+
+ fn try_from(value: &str) -> std::result::Result {
+ KeyValuePair::try_from(value.to_string())
+ }
+}
+
+#[derive(Deserialize, Debug, PartialEq, Eq, Clone)]
+pub(crate) struct Transformations {
+ pub(crate) headers: Vec,
+}
+
+impl Default for Transformations {
+ fn default() -> Self {
+ Transformations { headers: vec![] }
+ }
+}
+
+#[derive(Deserialize, Default, PartialEq, Eq, Debug, Clone)]
+#[serde(default)]
+pub(crate) struct Config {
+ pub(crate) remove: Transformations,
+ pub(crate) rename: Transformations,
+ pub(crate) replace: Transformations,
+ pub(crate) add: Transformations,
+ pub(crate) append: Transformations,
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+
+ use serde_json;
+
+ impl KeyValuePair {
+ #[warn(unused)]
+ pub(crate) fn new(name: T, value: T) -> Self {
+ KeyValuePair(name.to_string(), value.to_string())
+ }
+ }
+
+
+ #[test]
+ fn test_header_try_from_valid() {
+ assert_eq!(Ok(KeyValuePair::new("a", "b")), KeyValuePair::try_from("a:b"));
+ }
+
+ #[test]
+ fn test_header_try_from_invalid() {
+ assert_eq!(Err(InvalidHeader("a".to_string())), KeyValuePair::try_from("a"));
+ assert_eq!(Err(InvalidHeader("a:".to_string())), KeyValuePair::try_from("a:"));
+ assert_eq!(Err(InvalidHeader(":b".to_string())), KeyValuePair::try_from(":b"));
+ }
+
+ #[test]
+ fn test_json_deserialize_transformations() {
+ assert_eq!(
+ Transformations {
+ headers: vec![KeyValuePair::new("a", "b"), KeyValuePair::new("c", "d")]
+ },
+ serde_json::from_str(r#"{ "headers": ["a:b", "c:d"] }"#).unwrap()
+ );
+ }
+}
diff --git a/kong-versions/3.9.0.0/kong/spec/fixtures/proxy_wasm_filters/tests/Cargo.toml b/kong-versions/3.9.0.0/kong/spec/fixtures/proxy_wasm_filters/tests/Cargo.toml
new file mode 100644
index 00000000..07a64787
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/fixtures/proxy_wasm_filters/tests/Cargo.toml
@@ -0,0 +1,18 @@
+[package]
+name = "tests"
+version = "0.0.1"
+authors = ["Thibault Charbonnier "]
+edition = "2018"
+
+[lib]
+path = "src/filter.rs"
+crate-type = ["cdylib"]
+
+[dependencies]
+proxy-wasm = "0.2"
+url = "2.2"
+log = "0.4"
+http = "0.2"
+chrono = "0.4"
+enum-utils = "0.1.2"
+parse_duration = "2.1.1"
diff --git a/kong-versions/3.9.0.0/kong/spec/fixtures/proxy_wasm_filters/tests/src/filter.rs b/kong-versions/3.9.0.0/kong/spec/fixtures/proxy_wasm_filters/tests/src/filter.rs
new file mode 100644
index 00000000..60dbb3f8
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/fixtures/proxy_wasm_filters/tests/src/filter.rs
@@ -0,0 +1,151 @@
+mod routines;
+mod test_http;
+mod types;
+mod metrics;
+
+use crate::routines::*;
+use crate::test_http::*;
+use crate::types::*;
+use http::StatusCode;
+use log::*;
+use proxy_wasm::traits::*;
+use proxy_wasm::types::*;
+use std::str::FromStr;
+use std::time::Duration;
+
+proxy_wasm::main! {{
+ proxy_wasm::set_log_level(LogLevel::Info);
+ proxy_wasm::set_root_context(|_| -> Box {
+ Box::new(TestRoot { config: None })
+ });
+}}
+
+struct TestRoot {
+ config: Option,
+}
+
+impl Context for TestRoot {}
+
+impl RootContext for TestRoot {
+ fn on_vm_start(&mut self, conf_size: usize) -> bool {
+ info!("[proxy-wasm root] on_vm_start (conf_size: {})", conf_size);
+ true
+ }
+
+ fn on_configure(&mut self, conf_size: usize) -> bool {
+ info!("[proxy-wasm root] on_configure (conf_size: {})", conf_size);
+
+ if let Some(bytes) = self.get_plugin_configuration() {
+ let config: &str = std::str::from_utf8(&bytes).unwrap();
+ self.config = TestConfig::from_str(config).ok();
+
+ if let Some(every) = self.config.as_ref().unwrap().map.get("tick_every") {
+ let ms = every.parse().expect("bad tick_every");
+ info!("starting on_tick every {}ms", ms);
+
+ self.set_tick_period(Duration::from_millis(ms));
+ }
+ }
+
+ true
+ }
+
+ fn get_type(&self) -> Option {
+ Some(ContextType::HttpContext)
+ }
+
+ fn create_http_context(&self, context_id: u32) -> Option> {
+ info!(
+ "[proxy-wasm root] create_http_context (id: #{})",
+ context_id
+ );
+
+ let config = if let Some(config) = &self.config {
+ Some(TestConfig{ map: config.map.clone()})
+ } else {
+ None
+ };
+
+ Some(Box::new(TestHttp { config: config }))
+ }
+
+ fn on_tick(&mut self) {
+ info!("[proxy-wasm root] on_tick");
+ }
+}
+
+impl Context for TestHttp {
+ fn on_http_call_response(
+ &mut self,
+ token_id: u32,
+ nheaders: usize,
+ body_size: usize,
+ _ntrailers: usize,
+ ) {
+ const HEADER_NAME: &str = "X-PW-Dispatch-Echo";
+
+ info!(
+ "[proxy-wasm http] on_http_call_response (token_id: {}, headers: {}, body_bytes: {})",
+ token_id, nheaders, body_size
+ );
+
+ if let Some(bytes) = self.get_http_call_response_body(0, usize::MAX) {
+ let body = String::from_utf8(bytes).unwrap();
+ info!("[proxy-wasm] http_call_response body: {:?}", body);
+
+ if let Some(v) = self.get_http_request_header(HEADER_NAME) {
+ match v.as_str() {
+ "on" | "true" | "T" | "1" => {
+ self.send_plain_response(StatusCode::OK, Some(body.trim()))
+ }
+ _ => {}
+ }
+ }
+ }
+
+ self.resume_http_request()
+ }
+}
+
+impl HttpContext for TestHttp {
+ fn on_http_request_headers(&mut self, nheaders: usize, eof: bool) -> Action {
+ info!(
+ "[proxy-wasm http] on_request_headers ({} headers, eof: {})",
+ nheaders, eof
+ );
+
+ self.run_tests(TestPhase::RequestHeaders)
+ }
+
+ fn on_http_request_body(&mut self, size: usize, eof: bool) -> Action {
+ info!(
+ "[proxy-wasm http] on_request_body ({} bytes, eof: {})",
+ size, eof
+ );
+
+ self.run_tests(TestPhase::RequestBody)
+ }
+
+ fn on_http_response_headers(&mut self, nheaders: usize, eof: bool) -> Action {
+ info!(
+ "[proxy-wasm http] on_response_headers ({} headers, eof: {})",
+ nheaders, eof
+ );
+
+ self.run_tests(TestPhase::ResponseHeaders)
+ }
+
+ fn on_http_response_body(&mut self, size: usize, eof: bool) -> Action {
+ info!(
+ "[proxy-wasm http] on_response_body ({} bytes, eof {})",
+ size, eof
+ );
+
+ self.run_tests(TestPhase::ResponseBody)
+ }
+
+ fn on_log(&mut self) {
+ info!("[proxy-wasm http] on_log");
+ self.run_tests(TestPhase::Log);
+ }
+}
diff --git a/kong-versions/3.9.0.0/kong/spec/fixtures/proxy_wasm_filters/tests/src/metrics.rs b/kong-versions/3.9.0.0/kong/spec/fixtures/proxy_wasm_filters/tests/src/metrics.rs
new file mode 100644
index 00000000..dc96d6f2
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/fixtures/proxy_wasm_filters/tests/src/metrics.rs
@@ -0,0 +1,54 @@
+use std::collections::HashMap;
+use std::cell::RefCell;
+use proxy_wasm::hostcalls::{define_metric, increment_metric, record_metric};
+use proxy_wasm::types::{MetricType, Status};
+
+thread_local! {
+ static METRICS: Metrics = Metrics::new();
+}
+
+struct Metrics {
+ metrics: RefCell>,
+}
+
+impl Metrics {
+ fn new() -> Metrics {
+ Metrics {
+ metrics: RefCell::new(HashMap::new()),
+ }
+ }
+
+ fn get_metric_id(&self, metric_type: MetricType, name: &str) -> Result {
+ let mut map = self.metrics.borrow_mut();
+
+ match map.get(name) {
+ Some(m_id) => Ok(*m_id),
+ None => {
+ match define_metric(metric_type, name) {
+ Ok(m_id) => {
+ map.insert(name.to_string(), m_id);
+
+ Ok(m_id)
+ },
+ Err(msg) => Err(msg)
+ }
+ }
+ }
+ }
+}
+
+pub fn define(m_type: MetricType, name: &str) -> Result {
+ METRICS.with(|metrics| metrics.get_metric_id(m_type, name))
+}
+
+pub fn increment_counter(name: &str) -> Result<(), Status> {
+ increment_metric(define(MetricType::Counter, name).unwrap(), 1)
+}
+
+pub fn record_gauge(name: &str, value: u64) -> Result<(), Status> {
+ record_metric(define(MetricType::Gauge, name).unwrap(), value)
+}
+
+pub fn record_histogram(name: &str, value: u64) -> Result<(), Status> {
+ record_metric(define(MetricType::Histogram, name).unwrap(), value)
+}
diff --git a/kong-versions/3.9.0.0/kong/spec/fixtures/proxy_wasm_filters/tests/src/routines.rs b/kong-versions/3.9.0.0/kong/spec/fixtures/proxy_wasm_filters/tests/src/routines.rs
new file mode 100644
index 00000000..dc8fff04
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/fixtures/proxy_wasm_filters/tests/src/routines.rs
@@ -0,0 +1,30 @@
+use crate::*;
+
+pub(crate) fn add_request_header(ctx: &mut TestHttp) {
+ const HEADER_NAME: &str = "X-PW-Add-Header";
+
+ if let Some(header) = ctx.get_http_request_header(HEADER_NAME) {
+ let (name, value) = header.split_once('=').unwrap();
+
+ ctx.add_http_request_header(name, value);
+ ctx.set_http_request_header(HEADER_NAME, None)
+ }
+}
+
+pub(crate) fn add_response_header(ctx: &mut TestHttp) {
+ const HEADER_NAME: &str = "X-PW-Add-Resp-Header";
+
+ if let Some(header) = ctx.get_http_request_header(HEADER_NAME) {
+ let (name, value) = header.split_once('=').unwrap();
+
+ ctx.add_http_response_header(name, value);
+ }
+
+ const CONFIG_HEADER_NAME: &str = "X-PW-Resp-Header-From-Config";
+ if let Some(config) = &ctx.config {
+ info!("[proxy-wasm] setting {:?} header from config", CONFIG_HEADER_NAME);
+ if let Some(value) = config.map.get("add_resp_header") {
+ ctx.add_http_response_header(CONFIG_HEADER_NAME, value);
+ }
+ }
+}
diff --git a/kong-versions/3.9.0.0/kong/spec/fixtures/proxy_wasm_filters/tests/src/test_cases.rs b/kong-versions/3.9.0.0/kong/spec/fixtures/proxy_wasm_filters/tests/src/test_cases.rs
new file mode 100644
index 00000000..4e548ea0
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/fixtures/proxy_wasm_filters/tests/src/test_cases.rs
@@ -0,0 +1,23 @@
+use crate::*;
+
+pub(crate) fn add_request_header(ctx: &mut TestHttpHostcalls) {
+ const HEADER_NAME: &str = "X-PW-Add-Header";
+
+ if let Some(header) = ctx.get_http_request_header(HEADER_NAME) {
+ let (name, value) = header.split_once('=').unwrap();
+
+ ctx.add_http_request_header(name, value);
+ ctx.set_http_request_header(HEADER_NAME, None);
+ }
+}
+
+pub(crate) fn add_response_header(ctx: &mut TestHttpHostcalls) {
+ const HEADER_NAME: &str = "X-PW-Add-Resp-Header";
+
+ if let Some(header) = ctx.get_http_request_header(HEADER_NAME) {
+ let (name, value) = header.split_once('=').unwrap();
+
+ ctx.add_http_response_header(name, value);
+ ctx.set_http_request_header(HEADER_NAME, None);
+ }
+}
diff --git a/kong-versions/3.9.0.0/kong/spec/fixtures/proxy_wasm_filters/tests/src/test_http.rs b/kong-versions/3.9.0.0/kong/spec/fixtures/proxy_wasm_filters/tests/src/test_http.rs
new file mode 100644
index 00000000..9465eaf9
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/fixtures/proxy_wasm_filters/tests/src/test_http.rs
@@ -0,0 +1,170 @@
+use crate::*;
+
+pub struct TestHttp {
+ pub config: Option,
+}
+
+impl TestHttp {
+ pub fn send_plain_response(&mut self, status: StatusCode, body: Option<&str>) {
+ self.send_http_response(status.as_u16() as u32, vec![], body.map(|b| b.as_bytes()))
+ }
+
+ fn get_prop(&self, ns: &str, prop: &str) -> String {
+ if let Some(addr) = self.get_property(vec![ns, prop]) {
+ match std::str::from_utf8(&addr) {
+ Ok(value) => value.to_string(),
+ Err(_) => "".to_string(),
+ }
+ } else {
+ "".to_string()
+ }
+ }
+
+ fn set_prop(&self, ns: &str, prop: &str, value: Option<&str>) {
+ let value: Option<&[u8]> = value.map(|v| v.as_bytes());
+ self.set_property(vec![ns, prop], value);
+ }
+
+ fn update_metrics(&self) {
+ let base: u64 = 2;
+
+ let s_name = self.get_prop("kong", "service_name");
+ let r_name = self.get_prop("kong", "route_name");
+
+ let labeled_c = format!("a_labeled_counter_s_id={}_r_id={}", s_name, r_name);
+ let labeled_g = format!("a_labeled_gauge_s_id={}_r_id={}", s_name, r_name);
+ let labeled_h = format!("a_labeled_histogram_s_id={}_r_id={}", s_name, r_name);
+
+ metrics::increment_counter("a_counter").unwrap();
+ metrics::increment_counter(&labeled_c).unwrap();
+
+ metrics::record_gauge("a_gauge", 1).unwrap();
+ metrics::record_gauge(&labeled_g, 1).unwrap();
+
+ for i in 0..18 {
+ metrics::record_histogram("a_histogram", base.pow(i)).unwrap();
+ metrics::record_histogram(&labeled_h, base.pow(i)).unwrap();
+ }
+ }
+
+ fn send_http_dispatch(&mut self, config: TestConfig) -> Action {
+ let mut timeout = Duration::from_secs(0);
+ let mut headers = Vec::new();
+
+ headers.push((
+ ":method",
+ config
+ .map
+ .get("method")
+ .map(|v| v.as_str())
+ .unwrap_or("GET"),
+ ));
+
+ headers.push((
+ ":path",
+ config.map.get("path").map(|v| v.as_str()).unwrap_or("/"),
+ ));
+
+ headers.push((
+ ":authority",
+ config
+ .map
+ .get("host")
+ .map(|v| v.as_str())
+ .unwrap_or("127.0.0.1:15555"),
+ ));
+
+ if let Some(vals) = config.map.get("headers") {
+ for (k, v) in vals.split('|').filter_map(|s| s.split_once(':')) {
+ headers.push((k, v));
+ }
+ }
+
+ if let Some(val) = config.map.get("timeout") {
+ if let Ok(t) = parse_duration::parse(val) {
+ timeout = t;
+ }
+ }
+
+ self.dispatch_http_call(
+ config
+ .map
+ .get("host")
+ .map(|v| v.as_str())
+ .unwrap_or("127.0.0.1:15555"),
+ headers,
+ config.map.get("body").map(|v| v.as_bytes()),
+ vec![],
+ timeout,
+ )
+ .expect("dispatch error");
+
+ Action::Pause
+ }
+
+ pub fn run_tests(&mut self, cur_phase: TestPhase) -> Action {
+ const PHASE_HEADER_NAME: &str = "X-PW-Phase";
+ const TEST_HEADER_NAME: &str = "X-PW-Test";
+ const INPUT_HEADER_NAME: &str = "X-PW-Input";
+
+ let opt_input = self.get_http_request_header(INPUT_HEADER_NAME);
+ let opt_test = self.get_http_request_header(TEST_HEADER_NAME);
+ let on_phase = self.get_http_request_header(PHASE_HEADER_NAME).map_or(
+ TestPhase::RequestHeaders,
+ |s| {
+ s.parse()
+ .unwrap_or_else(|_| panic!("unknown phase: {:?}", s))
+ },
+ );
+
+ if cur_phase == on_phase {
+ info!("[proxy-wasm] testing in \"{:?}\"", on_phase);
+
+ if cur_phase == TestPhase::RequestHeaders || cur_phase == TestPhase::RequestBody {
+ self.set_http_request_header(INPUT_HEADER_NAME, None);
+ self.set_http_request_header(TEST_HEADER_NAME, None);
+ self.set_http_request_header(PHASE_HEADER_NAME, None);
+
+ add_request_header(self);
+ }
+
+ add_response_header(self);
+
+ if let Some(test) = opt_test {
+ match test.as_str() {
+ "trap" => panic!("trap msg"),
+ "local_response" => {
+ self.send_plain_response(StatusCode::OK, opt_input.as_deref())
+ }
+ "get_kong_property" => {
+ let name = &opt_input.unwrap_or("".to_string());
+ let value = self.get_prop("kong", name);
+ info!("[proxy-wasm] kong.{}: \"{:?}\"", name, value);
+ self.send_plain_response(StatusCode::OK, Some(&value))
+ }
+ "set_kong_property" => {
+ if let Some(input) = opt_input {
+ let (key, value) = match input.split_once('=') {
+ Some((key, value)) => (key, Some(value)),
+ None => (input.as_ref(), None),
+ };
+
+ self.set_prop("kong", key, value);
+ info!("[proxy-wasm] kong.{} = \"{:?}\"", key, value);
+ }
+ }
+ "echo_http_dispatch" => {
+ let config = TestConfig::from_str(&opt_input.unwrap_or("".to_string()))
+ .expect("invalid configuration");
+
+ return self.send_http_dispatch(config);
+ }
+ "update_metrics" => self.update_metrics(),
+ _ => (),
+ }
+ }
+ }
+
+ Action::Continue
+ }
+}
diff --git a/kong-versions/3.9.0.0/kong/spec/fixtures/proxy_wasm_filters/tests/src/types.rs b/kong-versions/3.9.0.0/kong/spec/fixtures/proxy_wasm_filters/tests/src/types.rs
new file mode 100644
index 00000000..29f4d86a
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/fixtures/proxy_wasm_filters/tests/src/types.rs
@@ -0,0 +1,30 @@
+use crate::*;
+use std::collections::HashMap;
+
+pub struct TestConfig {
+ pub map: HashMap,
+}
+
+impl FromStr for TestConfig {
+ type Err = std::str::Utf8Error;
+
+ fn from_str(s: &str) -> Result {
+ Ok(TestConfig {
+ map: s
+ .split_whitespace()
+ .filter_map(|s| s.split_once('='))
+ .map(|(k, v)| (k.to_string(), v.to_string()))
+ .collect(),
+ })
+ }
+}
+
+#[derive(Debug, Eq, PartialEq, enum_utils::FromStr)]
+#[enumeration(rename_all = "snake_case")]
+pub enum TestPhase {
+ RequestHeaders,
+ RequestBody,
+ ResponseHeaders,
+ ResponseBody,
+ Log,
+}
diff --git a/kong-versions/3.9.0.0/kong/spec/fixtures/redis/ca.crt b/kong-versions/3.9.0.0/kong/spec/fixtures/redis/ca.crt
new file mode 100644
index 00000000..54b617b7
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/fixtures/redis/ca.crt
@@ -0,0 +1,121 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number:
+ 04:1e:bb:94:6a:44:ac:b3:2d:3b:fb:25:68:c5:0f:c7:8e:15:54:a7
+ Signature Algorithm: sha512WithRSAEncryption
+ Issuer: C = US, ST = California, O = Kong, CN = Kong Testing Root CA
+ Validity
+ Not Before: Jan 4 06:45:00 2023 GMT
+ Not After : Dec 30 06:45:00 2042 GMT
+ Subject: C = US, ST = California, O = Kong, CN = Kong Testing Root CA
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ Public-Key: (4096 bit)
+ Modulus:
+ 00:d5:57:b6:92:01:54:fa:d9:7c:7f:05:10:93:cd:
+ 22:a5:a1:ca:f0:ef:58:12:da:08:33:f1:39:55:41:
+ 39:03:4a:98:54:1b:a7:d5:30:53:05:69:2d:69:f9:
+ d7:b7:b7:8a:5d:b0:cf:3c:bd:9e:51:e7:35:bc:b4:
+ 5c:db:f4:f0:44:77:9c:2e:51:e0:9f:93:49:42:6b:
+ 5d:f7:de:35:72:68:ee:c2:d7:08:47:ff:09:fa:75:
+ f1:2e:fc:34:e1:d1:b6:75:11:c6:72:18:7a:80:ff:
+ b4:df:82:e5:25:9d:06:70:fc:64:5f:0b:a0:ec:3b:
+ 82:65:6e:13:23:18:db:22:d2:66:79:cd:d9:9e:24:
+ af:76:b2:30:3a:cf:c2:50:6e:8e:61:f1:f1:c4:ad:
+ 3e:28:53:c8:6e:ee:98:f6:d2:ed:ad:7f:fe:46:98:
+ 8e:1d:4b:c4:21:ab:e3:43:76:7f:71:2c:d7:0f:d2:
+ 30:a3:42:b9:23:fc:99:ed:18:d8:a0:64:d2:9c:93:
+ 02:98:33:e5:9e:c0:48:35:8a:de:a1:46:a3:e8:02:
+ 06:cb:17:ff:2f:2b:b2:2a:28:80:48:7c:a6:01:d9:
+ 26:b1:1a:71:7a:f2:46:fc:b8:f7:d4:90:89:5f:73:
+ 10:56:4e:db:b4:de:39:c5:ee:61:4e:58:1d:10:f6:
+ cb:18:35:8a:d9:b6:c8:67:c4:fd:59:3b:d2:30:f2:
+ 33:f6:9b:c7:71:27:a8:c4:54:d7:26:86:78:2d:ef:
+ 51:e6:46:d2:56:8e:e3:4d:26:70:15:ef:a2:ac:c1:
+ 90:d9:24:60:cb:f8:54:47:91:78:e9:4a:b3:47:82:
+ e8:75:c3:2d:40:df:95:cf:8a:ca:6b:47:cb:f1:3f:
+ 01:3c:91:99:cb:6d:64:6f:35:69:6d:51:68:eb:bb:
+ f8:27:5d:4f:5e:df:fe:a5:3e:29:ee:ed:d2:65:c4:
+ 75:15:06:f2:10:51:0e:80:8e:23:d6:1c:00:be:a7:
+ f4:53:ca:c4:5e:b1:ff:8f:d2:d9:b8:6a:26:ee:ba:
+ bb:77:02:54:5c:f9:a8:f1:fb:84:aa:61:6f:03:d0:
+ 0e:67:7e:9f:a8:3d:57:f2:f0:35:ff:3d:c1:63:56:
+ 12:75:66:e0:1d:3a:b9:d0:b6:a3:12:9f:a9:30:01:
+ 0b:1f:87:74:d2:30:88:ea:e3:f5:ea:f5:d1:6c:34:
+ 33:7f:aa:a3:d5:59:ee:08:8c:a0:37:5f:57:c9:43:
+ e4:b6:ad:ae:be:43:dc:46:b7:ba:dd:e0:21:51:bb:
+ 83:b0:16:95:ab:b0:13:a6:d3:22:f4:c6:c8:e0:2a:
+ 5b:82:f0:dd:e5:55:d8:d1:1b:73:ab:47:3a:c6:77:
+ ed:dc:bb
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Key Usage: critical
+ Certificate Sign, CRL Sign
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ X509v3 Subject Key Identifier:
+ 13:6D:39:C0:7E:81:64:DE:4D:9F:5A:64:60:95:F7:44:37:5F:13:8E
+ Signature Algorithm: sha512WithRSAEncryption
+ Signature Value:
+ b2:7d:b7:01:d2:28:4d:eb:ff:b5:db:ca:02:5e:72:11:c8:34:
+ 49:ca:ea:86:00:28:f4:4f:7d:9e:3d:ed:d7:ef:ac:f8:59:20:
+ 78:3b:51:96:a4:e8:f8:99:77:f4:69:d7:c0:bf:26:30:43:de:
+ f6:71:b0:c1:59:23:85:29:ea:80:b8:52:2c:1a:8a:d0:c0:03:
+ 82:9c:83:eb:04:5d:08:e9:fd:dc:ce:a7:22:e4:d7:0d:cf:62:
+ 7b:dd:52:29:70:cb:04:1d:ad:cc:be:b4:04:fc:2b:8e:46:83:
+ 1f:87:5f:90:5b:d7:6b:b3:e1:30:55:b7:1b:9c:7d:a4:85:7b:
+ 12:d0:4d:a4:2b:2c:79:de:3e:1c:cb:be:04:6c:08:48:cd:b1:
+ d5:72:96:cb:17:18:88:35:20:ca:c5:cf:4f:73:7e:73:2f:04:
+ cf:3d:90:7c:0f:c5:1a:2c:6e:89:87:19:ed:28:99:50:b9:b5:
+ 3b:c1:68:fa:51:de:35:ad:ae:a6:17:c5:74:47:fb:fa:31:b0:
+ 59:21:6d:2a:50:a5:28:2e:12:5a:c8:a3:4f:7c:78:d8:62:fc:
+ e6:c7:d8:53:6b:9d:56:db:5b:71:4d:2c:32:01:e7:2e:ca:a4:
+ 93:92:7e:29:8c:13:ed:6e:f2:b0:59:53:03:69:20:93:69:5c:
+ 21:3e:0b:a7:9c:db:39:fc:18:6e:96:9a:7c:86:0f:fb:99:92:
+ 3b:c2:09:5d:ce:b0:cc:0d:ab:28:58:10:6c:5c:11:09:26:d2:
+ d6:1d:ac:cf:8e:0e:08:14:ed:5e:78:9b:4e:e9:c4:39:95:dc:
+ b6:c4:a1:1f:ae:5f:6c:47:47:a6:3a:8c:0c:df:82:7a:7f:a2:
+ d0:ed:e4:f9:d9:e4:1f:7e:a5:71:65:8d:f0:44:78:1a:ee:7d:
+ b1:af:ea:a1:8f:4a:50:cd:2c:76:1f:06:1b:48:1f:42:2f:72:
+ e5:35:0b:71:68:ef:a9:8e:42:00:67:9b:e4:30:36:29:37:12:
+ eb:3c:a2:74:7b:94:fc:3b:84:b9:7d:f5:b9:fc:d5:08:74:b6:
+ ea:9c:89:78:94:2e:51:6a:37:60:9b:24:95:da:63:bd:d7:ca:
+ 40:2c:57:8c:dd:5c:fd:78:d8:51:0c:bc:23:06:9e:fb:b0:8a:
+ 50:ea:aa:c1:f0:a3:a1:85:d8:81:a1:84:19:c2:71:0d:ce:dd:
+ b7:e8:c7:b9:4f:2f:7d:5b:83:34:d9:2c:1c:3d:68:92:2f:4c:
+ 63:67:d3:cb:9a:c5:e8:d6:98:76:d4:32:03:92:19:02:73:09:
+ 1a:29:74:58:e9:a1:29:f8:30:54:f4:fb:9e:c8:13:7f:96:59:
+ 2c:54:19:40:99:3e:0e:ee
+-----BEGIN CERTIFICATE-----
+MIIFcDCCA1igAwIBAgIUBB67lGpErLMtO/slaMUPx44VVKcwDQYJKoZIhvcNAQEN
+BQAwUDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExDTALBgNVBAoT
+BEtvbmcxHTAbBgNVBAMTFEtvbmcgVGVzdGluZyBSb290IENBMB4XDTIzMDEwNDA2
+NDUwMFoXDTQyMTIzMDA2NDUwMFowUDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCkNh
+bGlmb3JuaWExDTALBgNVBAoTBEtvbmcxHTAbBgNVBAMTFEtvbmcgVGVzdGluZyBS
+b290IENBMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA1Ve2kgFU+tl8
+fwUQk80ipaHK8O9YEtoIM/E5VUE5A0qYVBun1TBTBWktafnXt7eKXbDPPL2eUec1
+vLRc2/TwRHecLlHgn5NJQmtd9941cmjuwtcIR/8J+nXxLvw04dG2dRHGchh6gP+0
+34LlJZ0GcPxkXwug7DuCZW4TIxjbItJmec3ZniSvdrIwOs/CUG6OYfHxxK0+KFPI
+bu6Y9tLtrX/+RpiOHUvEIavjQ3Z/cSzXD9Iwo0K5I/yZ7RjYoGTSnJMCmDPlnsBI
+NYreoUaj6AIGyxf/LyuyKiiASHymAdkmsRpxevJG/Lj31JCJX3MQVk7btN45xe5h
+TlgdEPbLGDWK2bbIZ8T9WTvSMPIz9pvHcSeoxFTXJoZ4Le9R5kbSVo7jTSZwFe+i
+rMGQ2SRgy/hUR5F46UqzR4LodcMtQN+Vz4rKa0fL8T8BPJGZy21kbzVpbVFo67v4
+J11PXt/+pT4p7u3SZcR1FQbyEFEOgI4j1hwAvqf0U8rEXrH/j9LZuGom7rq7dwJU
+XPmo8fuEqmFvA9AOZ36fqD1X8vA1/z3BY1YSdWbgHTq50LajEp+pMAELH4d00jCI
+6uP16vXRbDQzf6qj1VnuCIygN19XyUPktq2uvkPcRre63eAhUbuDsBaVq7ATptMi
+9MbI4CpbgvDd5VXY0Rtzq0c6xnft3LsCAwEAAaNCMEAwDgYDVR0PAQH/BAQDAgEG
+MA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFBNtOcB+gWTeTZ9aZGCV90Q3XxOO
+MA0GCSqGSIb3DQEBDQUAA4ICAQCyfbcB0ihN6/+128oCXnIRyDRJyuqGACj0T32e
+Pe3X76z4WSB4O1GWpOj4mXf0adfAvyYwQ972cbDBWSOFKeqAuFIsGorQwAOCnIPr
+BF0I6f3czqci5NcNz2J73VIpcMsEHa3MvrQE/CuORoMfh1+QW9drs+EwVbcbnH2k
+hXsS0E2kKyx53j4cy74EbAhIzbHVcpbLFxiINSDKxc9Pc35zLwTPPZB8D8UaLG6J
+hxntKJlQubU7wWj6Ud41ra6mF8V0R/v6MbBZIW0qUKUoLhJayKNPfHjYYvzmx9hT
+a51W21txTSwyAecuyqSTkn4pjBPtbvKwWVMDaSCTaVwhPgunnNs5/Bhulpp8hg/7
+mZI7wgldzrDMDasoWBBsXBEJJtLWHazPjg4IFO1eeJtO6cQ5ldy2xKEfrl9sR0em
+OowM34J6f6LQ7eT52eQffqVxZY3wRHga7n2xr+qhj0pQzSx2HwYbSB9CL3LlNQtx
+aO+pjkIAZ5vkMDYpNxLrPKJ0e5T8O4S5ffW5/NUIdLbqnIl4lC5RajdgmySV2mO9
+18pALFeM3Vz9eNhRDLwjBp77sIpQ6qrB8KOhhdiBoYQZwnENzt236Me5Ty99W4M0
+2SwcPWiSL0xjZ9PLmsXo1ph21DIDkhkCcwkaKXRY6aEp+DBU9PueyBN/llksVBlA
+mT4O7g==
+-----END CERTIFICATE-----
diff --git a/kong-versions/3.9.0.0/kong/spec/fixtures/redis/ca.key b/kong-versions/3.9.0.0/kong/spec/fixtures/redis/ca.key
new file mode 100644
index 00000000..871f6b34
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/fixtures/redis/ca.key
@@ -0,0 +1,51 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIJJwIBAAKCAgEA1Ve2kgFU+tl8fwUQk80ipaHK8O9YEtoIM/E5VUE5A0qYVBun
+1TBTBWktafnXt7eKXbDPPL2eUec1vLRc2/TwRHecLlHgn5NJQmtd9941cmjuwtcI
+R/8J+nXxLvw04dG2dRHGchh6gP+034LlJZ0GcPxkXwug7DuCZW4TIxjbItJmec3Z
+niSvdrIwOs/CUG6OYfHxxK0+KFPIbu6Y9tLtrX/+RpiOHUvEIavjQ3Z/cSzXD9Iw
+o0K5I/yZ7RjYoGTSnJMCmDPlnsBINYreoUaj6AIGyxf/LyuyKiiASHymAdkmsRpx
+evJG/Lj31JCJX3MQVk7btN45xe5hTlgdEPbLGDWK2bbIZ8T9WTvSMPIz9pvHcSeo
+xFTXJoZ4Le9R5kbSVo7jTSZwFe+irMGQ2SRgy/hUR5F46UqzR4LodcMtQN+Vz4rK
+a0fL8T8BPJGZy21kbzVpbVFo67v4J11PXt/+pT4p7u3SZcR1FQbyEFEOgI4j1hwA
+vqf0U8rEXrH/j9LZuGom7rq7dwJUXPmo8fuEqmFvA9AOZ36fqD1X8vA1/z3BY1YS
+dWbgHTq50LajEp+pMAELH4d00jCI6uP16vXRbDQzf6qj1VnuCIygN19XyUPktq2u
+vkPcRre63eAhUbuDsBaVq7ATptMi9MbI4CpbgvDd5VXY0Rtzq0c6xnft3LsCAwEA
+AQKCAgBwQKWkbyT6lEKoRs7xJcdsJRQ174mE6cnVIsCK9jV8YNyDrMWDK9kTCMNH
+dpklZmJcZ7KzAAZ0i9Y/gxs09M0TCWhZCuXIsOOkGgAocnfmygWO6TvHPg9PBI2x
+rixZAVIiiQbEc9LJW0IdNK9DOjrwaiyZwfGbOriii+dv2R08Vj5rKn+tcRoNtzYf
+S7+vOGycZoRSeuEwsNzOWaaMgHFkj+sH1C86hOoe2WVL0ua9ct15ypui23G02K1Z
+DnC0/DfBAK0lznCsNfoIihgX/aYyZhaS9/5iIHivK/5LpaJnaI2uM/6vtRja0qw7
+4Q0W9uEKuJVrtl3pokL6yOwKSACVtt7UH8cdzxTCG+6PZSDi4Taumv4AI3/YlXEK
+G6RyeYTsHrFJIt3nwTxnG06G/YiRCXCPd6UEgFQBS+E1/iMPJYe0lFliQJ6ugnGd
+wn5alJ/nIPWtAGEOa6TOltVQN/1y2G+BkJpvIVVUU+a6vTp+M3QCX3Q25Sl3/bOv
+3uDtE08cWSQAzA+njfX6ySckMq4O3cbq633CPluIzWTT/YjG+s39mUsIXLfZEqqk
+e+U0rfOmRa1lcqQdWLNzHHp5HT150mEDSUVOgykEA8JYAzRdy8G2A2mcLwob8/iA
+yagwACE3UYB5s2jN1b24OfEZCgKLnbvMEsppJOYqiId5x2efGQKCAQEA2lxVbS/7
+W6P/0on9B+QvMS1xIATiGhgHjbk4UBuW4Y0cIbJoAeSJnOOteFYRMxvxkWCkTb6q
+V9IxNm+PZWHjpkbxSAVvX00X08Dqvp6OtWmxHU5dvCEUTa9HudBSZPBtWG7iXRJK
+SuERLFOeD7KnAhkdqROVtCz8YBdzEljnZ4j/YzjWpAMQBPurwRmOVQVz36Ukuveh
+qGLXm8s6YPP9CiCMxt4DHjef51AkqNqewpN6TK5KPSZjruTWbzhT8934WWqXSYuU
+BYJ6LgEpVWF0dA8MXbWdbzRsocAhwm6ABa5BRZyUmZyl9lH9DUxlJ5omzZ+2t4/i
+D4QbzBUM+dBtRwKCAQEA+h3yUDVW0FRu5gG/QfbPcOKukbxnbwTJZMgyvPxIoAzg
+LxJiSYBPo4osW+dPtg8P+Sta7JEYB6PovSJjuX6e5i7oRJTIhQPc+0R5vAaUlrOl
+Li+cU2/sxuFf5b+R5OqEjtSrS8oUZOn28ShZS9rCTZUn+bf6yZA7fI4CoFIXj7ar
+xBq/5jGs45LvXaaUPc9XzBTkhWacpd9Hinx5d9v6O0C9UsMGoYk+Y6LfW1QV2l19
+gp/oWOXOWde454hirae0n0peeEwv9Ep7LEbf+CCJU/RyWYm6O/zIK9jU2fZsmACw
+W2TggftuEJY2/I1CPxfDOXti9c9FRgLSiVHSDzK+7QKCAQByYuoRP5Bh6iBKDyTw
+rFUYYuCe0FANMUdLs5pPRJSeZQg2krmvPCPmftJRdmyeJGZALKsFWvrq9F35USmC
+B2x0nzcn7kjwWHdB4w5VesPxPoOcgX/S3FVBeK+PJBT1cYkmSTflX35xiUMwwEDN
+ol2gWL3T40GJ2AMA52fNVasq7nYyaQTvd/c9VQUdK6EG4stXfbAnDS+vANBHeYeE
+YGvOkUyNpKFng+YNC0uY9KUz8oOfhbG4JNMVPCUksBIybrX5SUAlM6v/0uDkFpGr
+e1jAr11f/ZKSPZkmhnpo2u/PigABUkv5yDicN0jjXYCj5Tmsf5z8va/DRwY0u1ZH
+yypjAoIBAHFoqrqbtOV5o18/Y41xb9XrsuP53ZyFOxwrenYenn+T1wMA/vf86h9p
+Q3vYglg2tDNy6SNjFtZACAPaWAV/2GTe2ApgvBs0CTsVbW1IPo+mnTs381YR5fa3
+slfmaSy2+awZ2iHfWyf2vjXS6cpvQrMS8rFULq6+a3qqmZ5AGtbbKT8eMe0akR4P
+PeHk6kqsfU7YGlYylMzRVQsCLcGfSPMdA7tHGvab2GItM8GhetcslQBpqVzFtq8e
+FYVGXhgHdurTOcqqIQRP0VHeQSes+RfMOx1GSd9xWwImqzy5c7vodA68yt+lNd7n
+fb89/c/F4otp2xFCDlMUbIo/Q1QI2nECggEAedXZSGOw3BLY8yDRoRczibN9AlwF
+AgQeBS1g0DS6Mz+9C9j1FP9I8oFqwrFVtuYITqaI9LL4Zdebbebd1r4AmoxVrv4u
+WtHH80hHpr5tkONhHxN4IG4BLoYQQiIAD0Hg94TEUUDAosHM5zKgdLkqEX75rj9p
+Sz2jWQyDoh809CJpUSyDqnEeb8/MZ0vwWUrYINIImFNjd3w1jasAxTdul7hmLQ2P
+e9dPRzQ/gIgmiUvbBJZ1ujSFVnhIqfoAGkqkoUQ9EIFhpuzAnNHPPwZzGDxDedE4
+KVgGvJrXP6eJfgqOMjaXHPEF2eZu3gBcFKE30Vg+QW8YvhYOCVxiBFua/g==
+-----END RSA PRIVATE KEY-----
diff --git a/kong-versions/3.9.0.0/kong/spec/fixtures/redis/docker-entrypoint.sh b/kong-versions/3.9.0.0/kong/spec/fixtures/redis/docker-entrypoint.sh
new file mode 100755
index 00000000..a448be06
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/fixtures/redis/docker-entrypoint.sh
@@ -0,0 +1,19 @@
+#!/bin/sh
+set -e
+
+echo "Kong CI redis container..."
+
+if [ -d /workspace ] ; then
+ echo "Starting test server..."
+
+ redis-server \
+ --port 6379 \
+ --tls-port 6380 \
+ --tls-cert-file /workspace/spec/fixtures/redis/server.crt \
+ --tls-key-file /workspace/spec/fixtures/redis/server.key \
+ --tls-cluster no \
+ --tls-replication no \
+ --tls-auth-clients no
+fi
+
+tail -f /dev/null
diff --git a/kong-versions/3.9.0.0/kong/spec/fixtures/redis/server.crt b/kong-versions/3.9.0.0/kong/spec/fixtures/redis/server.crt
new file mode 100644
index 00000000..ce7dd4f6
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/fixtures/redis/server.crt
@@ -0,0 +1,128 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number:
+ 09:a1:b0:61:a9:f6:73:c8:f5:b4:1b:e3:e9:bc:ad:57:88:f5:cf:44
+ Signature Algorithm: sha512WithRSAEncryption
+ Issuer: C = US, ST = California, O = Kong, CN = Kong Testing Root CA
+ Validity
+ Not Before: Jan 4 06:45:00 2023 GMT
+ Not After : Dec 30 05:45:00 2042 GMT
+ Subject: C = US, ST = California, O = Kong, CN = test-redis.example.com
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ Public-Key: (4096 bit)
+ Modulus:
+ 00:cc:c1:d2:98:49:98:4b:6a:8c:4a:40:1b:93:35:
+ 29:29:55:78:b9:b9:e2:3a:ac:25:07:4f:7c:0c:da:
+ bf:f0:18:5d:57:9f:03:90:9f:30:d6:ff:7d:31:e9:
+ 3a:0e:c5:f2:e6:d8:1f:af:d4:7f:8a:bd:72:1e:4d:
+ ba:75:9f:2b:f3:77:72:03:30:7b:ca:67:fc:76:7a:
+ 42:57:81:02:aa:bc:b6:2f:63:e8:72:ec:e6:85:73:
+ f5:1d:a9:4d:47:7f:d2:3c:e2:e9:40:cd:0d:5c:f8:
+ e1:e8:88:89:1a:0d:8f:68:8a:63:9f:62:6c:03:30:
+ 19:ad:db:34:5a:f5:65:85:c5:7c:32:13:24:e8:5f:
+ 30:93:27:ce:01:72:1e:b7:72:48:fc:a6:72:b4:8e:
+ 08:ec:b8:c3:f7:95:60:92:e2:b0:d1:9d:9c:76:41:
+ f4:96:1e:96:a6:ab:73:16:78:7e:6a:8b:27:43:0d:
+ 69:19:6d:b7:6d:c0:21:56:2e:32:6b:ef:dc:31:7b:
+ f0:bc:16:d2:50:3b:bf:fb:7f:65:96:e3:a5:2c:d2:
+ 35:a8:f4:06:82:85:5c:89:02:a0:2f:96:5f:75:f3:
+ 63:22:7c:f3:06:12:66:85:d4:9a:a9:54:d6:12:96:
+ 96:54:0e:da:f5:6f:ae:8c:5a:72:9a:85:d5:9c:63:
+ d1:14:5a:7a:62:44:a5:6f:8d:ed:67:86:e4:34:6f:
+ 26:03:e2:17:57:b8:ee:e9:e7:c0:7d:f1:4e:33:f6:
+ 7f:0a:5c:25:92:04:fb:b1:90:14:e4:dd:cf:16:20:
+ 15:12:87:29:b7:b0:e9:d2:96:4d:1a:16:36:f3:de:
+ dd:0f:e6:55:da:09:df:a1:1a:e7:d0:d8:d2:b6:90:
+ 01:25:24:eb:1a:73:c5:54:d7:75:1e:86:a2:1c:56:
+ 58:66:05:99:5b:bd:e2:8e:12:a6:16:cb:56:f2:16:
+ b2:23:80:1b:d3:5f:ca:17:ec:ad:aa:45:de:76:4b:
+ be:d1:57:94:45:a9:3e:2d:33:1d:ae:e1:ce:27:6b:
+ e5:cf:13:4b:8e:d9:bc:cd:52:a5:7c:bf:0b:eb:8b:
+ 0c:b3:fb:12:b2:44:21:43:d3:56:1f:16:35:09:5f:
+ f7:45:ac:c9:1a:4d:2d:eb:8a:12:9b:35:48:b0:d6:
+ e6:c9:2e:0d:cd:b1:c6:f3:7b:96:6c:cd:f8:82:c9:
+ 29:b3:28:d4:82:82:80:9a:de:b1:3e:67:00:99:1e:
+ 02:b1:15:13:0f:6b:7c:2f:e6:31:ef:13:34:20:89:
+ bf:56:fe:05:41:2d:53:63:a7:ab:d7:d4:fa:ec:81:
+ 23:c6:1f:42:e5:a6:de:0c:08:d0:b0:8c:1b:41:ec:
+ 56:b6:25
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Key Usage: critical
+ Digital Signature, Key Encipherment
+ X509v3 Extended Key Usage:
+ TLS Web Server Authentication
+ X509v3 Basic Constraints: critical
+ CA:FALSE
+ X509v3 Subject Key Identifier:
+ D9:74:21:02:5A:95:A3:CF:F3:BD:1F:99:66:75:D7:69:B5:E1:3E:02
+ X509v3 Authority Key Identifier:
+ 13:6D:39:C0:7E:81:64:DE:4D:9F:5A:64:60:95:F7:44:37:5F:13:8E
+ X509v3 Subject Alternative Name:
+ DNS:test-redis.example.com
+ Signature Algorithm: sha512WithRSAEncryption
+ Signature Value:
+ 5e:3f:cd:02:be:1d:3e:e9:0a:25:98:a8:ae:a7:d0:23:2c:f8:
+ 46:e1:0c:25:d2:a3:73:19:01:08:f7:fb:18:da:65:f6:b3:4d:
+ 28:bb:37:b3:cc:cc:01:ef:c4:ed:18:92:06:78:9d:81:a4:5a:
+ bf:04:f4:c0:3d:0e:97:65:28:d1:8d:cb:1b:92:46:a1:3c:55:
+ 09:e8:b5:eb:4c:36:9f:5b:79:70:4d:bf:c0:6a:27:83:d2:b5:
+ c9:a2:af:f6:92:1c:f5:e9:1d:28:72:b3:7c:84:81:44:bf:e9:
+ cf:3c:73:3d:07:f4:c2:e5:fa:62:d7:5a:a7:87:e9:16:d4:f2:
+ 92:b0:22:b0:8a:1c:75:b0:f5:e9:91:28:55:1b:57:99:e0:d1:
+ 34:18:c2:11:d9:9a:9e:8b:32:c8:d0:5c:5b:20:eb:ac:7a:7b:
+ ee:05:8c:0c:5a:56:25:a2:c9:71:15:e5:07:c4:e7:99:a0:f7:
+ 38:dd:45:97:43:66:44:f9:d4:08:22:33:b6:ec:5b:09:25:d0:
+ 35:2f:00:3b:ef:05:93:36:d1:39:bf:66:77:ce:12:86:9f:22:
+ 12:53:a9:d2:8a:e3:6b:c2:d9:3a:ee:c6:9f:13:e1:34:15:d0:
+ a4:11:09:93:17:38:f7:e9:f7:d7:64:6a:9f:64:6a:28:50:b1:
+ 61:c6:ac:63:51:01:8c:e4:9c:c8:98:73:38:2c:ea:31:4b:b9:
+ 35:dc:26:08:58:f6:f8:fd:db:70:fb:b4:6c:be:ee:0c:da:87:
+ 90:01:66:c6:5c:08:f3:68:f4:8b:ea:55:54:9e:26:a0:4e:4d:
+ 37:7a:ff:85:22:9d:d8:ec:4e:e7:a9:5f:54:b8:16:73:af:7c:
+ fd:17:af:1f:87:92:b7:8b:c9:12:be:13:bd:0e:d0:6b:c9:df:
+ 6a:a4:e1:8d:87:de:b4:30:94:0a:26:98:23:88:8f:b0:eb:01:
+ 00:60:f0:63:bb:3b:c1:e6:92:0a:77:7b:c5:fa:3e:11:cc:04:
+ 21:48:bd:86:63:7f:ce:b7:be:b3:68:bb:b5:a0:50:ea:df:e9:
+ e8:9e:70:10:f8:10:ec:6c:8a:5e:7e:69:3e:eb:f3:9e:5b:a9:
+ d6:8b:39:40:37:79:47:74:15:aa:04:88:bd:76:a7:07:9b:2e:
+ b4:ee:cc:f0:db:55:94:33:93:fb:52:3c:75:8b:78:ec:eb:fe:
+ 83:f3:76:b5:87:c7:2c:45:65:11:67:9a:4b:ac:0d:46:89:13:
+ 96:56:44:0e:bb:dd:f9:b6:fc:99:d8:37:8d:33:aa:5b:c2:61:
+ c7:20:e1:e7:67:67:b9:79:da:95:8f:60:10:05:84:bb:f0:ab:
+ b4:0e:a7:d9:2e:ac:3a:38
+-----BEGIN CERTIFICATE-----
+MIIFyjCCA7KgAwIBAgIUCaGwYan2c8j1tBvj6bytV4j1z0QwDQYJKoZIhvcNAQEN
+BQAwUDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExDTALBgNVBAoT
+BEtvbmcxHTAbBgNVBAMTFEtvbmcgVGVzdGluZyBSb290IENBMB4XDTIzMDEwNDA2
+NDUwMFoXDTQyMTIzMDA1NDUwMFowUjELMAkGA1UEBhMCVVMxEzARBgNVBAgTCkNh
+bGlmb3JuaWExDTALBgNVBAoTBEtvbmcxHzAdBgNVBAMTFnRlc3QtcmVkaXMuZXhh
+bXBsZS5jb20wggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDMwdKYSZhL
+aoxKQBuTNSkpVXi5ueI6rCUHT3wM2r/wGF1XnwOQnzDW/30x6ToOxfLm2B+v1H+K
+vXIeTbp1nyvzd3IDMHvKZ/x2ekJXgQKqvLYvY+hy7OaFc/UdqU1Hf9I84ulAzQ1c
++OHoiIkaDY9oimOfYmwDMBmt2zRa9WWFxXwyEyToXzCTJ84Bch63ckj8pnK0jgjs
+uMP3lWCS4rDRnZx2QfSWHpamq3MWeH5qiydDDWkZbbdtwCFWLjJr79wxe/C8FtJQ
+O7/7f2WW46Us0jWo9AaChVyJAqAvll9182MifPMGEmaF1JqpVNYSlpZUDtr1b66M
+WnKahdWcY9EUWnpiRKVvje1nhuQ0byYD4hdXuO7p58B98U4z9n8KXCWSBPuxkBTk
+3c8WIBUShym3sOnSlk0aFjbz3t0P5lXaCd+hGufQ2NK2kAElJOsac8VU13UehqIc
+VlhmBZlbveKOEqYWy1byFrIjgBvTX8oX7K2qRd52S77RV5RFqT4tMx2u4c4na+XP
+E0uO2bzNUqV8vwvriwyz+xKyRCFD01YfFjUJX/dFrMkaTS3rihKbNUiw1ubJLg3N
+scbze5ZszfiCySmzKNSCgoCa3rE+ZwCZHgKxFRMPa3wv5jHvEzQgib9W/gVBLVNj
+p6vX1PrsgSPGH0Llpt4MCNCwjBtB7Fa2JQIDAQABo4GZMIGWMA4GA1UdDwEB/wQE
+AwIFoDATBgNVHSUEDDAKBggrBgEFBQcDATAMBgNVHRMBAf8EAjAAMB0GA1UdDgQW
+BBTZdCECWpWjz/O9H5lmdddpteE+AjAfBgNVHSMEGDAWgBQTbTnAfoFk3k2fWmRg
+lfdEN18TjjAhBgNVHREEGjAYghZ0ZXN0LXJlZGlzLmV4YW1wbGUuY29tMA0GCSqG
+SIb3DQEBDQUAA4ICAQBeP80Cvh0+6QolmKiup9AjLPhG4Qwl0qNzGQEI9/sY2mX2
+s00ouzezzMwB78TtGJIGeJ2BpFq/BPTAPQ6XZSjRjcsbkkahPFUJ6LXrTDafW3lw
+Tb/AaieD0rXJoq/2khz16R0ocrN8hIFEv+nPPHM9B/TC5fpi11qnh+kW1PKSsCKw
+ihx1sPXpkShVG1eZ4NE0GMIR2ZqeizLI0FxbIOusenvuBYwMWlYloslxFeUHxOeZ
+oPc43UWXQ2ZE+dQIIjO27FsJJdA1LwA77wWTNtE5v2Z3zhKGnyISU6nSiuNrwtk6
+7safE+E0FdCkEQmTFzj36ffXZGqfZGooULFhxqxjUQGM5JzImHM4LOoxS7k13CYI
+WPb4/dtw+7Rsvu4M2oeQAWbGXAjzaPSL6lVUniagTk03ev+FIp3Y7E7nqV9UuBZz
+r3z9F68fh5K3i8kSvhO9DtBryd9qpOGNh960MJQKJpgjiI+w6wEAYPBjuzvB5pIK
+d3vF+j4RzAQhSL2GY3/Ot76zaLu1oFDq3+nonnAQ+BDsbIpefmk+6/OeW6nWizlA
+N3lHdBWqBIi9dqcHmy607szw21WUM5P7Ujx1i3js6/6D83a1h8csRWURZ5pLrA1G
+iROWVkQOu935tvyZ2DeNM6pbwmHHIOHnZ2e5edqVj2AQBYS78Ku0DqfZLqw6OA==
+-----END CERTIFICATE-----
diff --git a/kong-versions/3.9.0.0/kong/spec/fixtures/redis/server.key b/kong-versions/3.9.0.0/kong/spec/fixtures/redis/server.key
new file mode 100644
index 00000000..e0fb26f7
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/fixtures/redis/server.key
@@ -0,0 +1,51 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIJKgIBAAKCAgEAzMHSmEmYS2qMSkAbkzUpKVV4ubniOqwlB098DNq/8BhdV58D
+kJ8w1v99Mek6DsXy5tgfr9R/ir1yHk26dZ8r83dyAzB7ymf8dnpCV4ECqry2L2Po
+cuzmhXP1HalNR3/SPOLpQM0NXPjh6IiJGg2PaIpjn2JsAzAZrds0WvVlhcV8MhMk
+6F8wkyfOAXIet3JI/KZytI4I7LjD95VgkuKw0Z2cdkH0lh6WpqtzFnh+aosnQw1p
+GW23bcAhVi4ya+/cMXvwvBbSUDu/+39lluOlLNI1qPQGgoVciQKgL5ZfdfNjInzz
+BhJmhdSaqVTWEpaWVA7a9W+ujFpymoXVnGPRFFp6YkSlb43tZ4bkNG8mA+IXV7ju
+6efAffFOM/Z/ClwlkgT7sZAU5N3PFiAVEocpt7Dp0pZNGhY2897dD+ZV2gnfoRrn
+0NjStpABJSTrGnPFVNd1HoaiHFZYZgWZW73ijhKmFstW8hayI4Ab01/KF+ytqkXe
+dku+0VeURak+LTMdruHOJ2vlzxNLjtm8zVKlfL8L64sMs/sSskQhQ9NWHxY1CV/3
+RazJGk0t64oSmzVIsNbmyS4NzbHG83uWbM34gskpsyjUgoKAmt6xPmcAmR4CsRUT
+D2t8L+Yx7xM0IIm/Vv4FQS1TY6er19T67IEjxh9C5abeDAjQsIwbQexWtiUCAwEA
+AQKCAgEAjJGDwojDxQKgzVi1lZopZ/cFqnuylBUaVqp6v1ht7KbNbhn8mIyxOuir
+SliTQxEicNhu6Ic6CEWG0scJ+zYLNloKK6ZdVdeNusi0Qt6OtihX6rDsI/n/SB8T
+aAmSxEM8UhB1kcc0JV+3t6wEc55blalsOz+WZ5neBz019DwENpIdcUMzU1QGRQBO
+rS9rZwVOliSvGsVn2xv9bTtf0XdPbJiHkag2Adl+E24g1IxkPUDK832BabOo+e+s
+8z1D4FYLFO3Bl18Tg4GBi2cqlywxeVPXAuaEkZZ8sJLc5c6WOqOcq1Cchs6bE8Wh
+aB6V2K0JBywrpdPGQRTXGL5Ip9Te85+bDvyggQMT9FpT4Ebxau94YGXwFK/OWM04
+sPUbDntPJyMuTzSOxRykegChQIGWaOMSeaTnn0Ff6kHZ6rkF2VLV5KwcOzl92XS2
+OZEa/LrFPzNNylliFY0FICSgzP4zbvtH4of8tCvN+XccB+yM5+6BDik/d0KsCp50
+XSVRaerf/+epo1c5k1ED44UldF4zxxagojJabNt85afg7L3ASqUxFCkNtOQB8r+8
+VBDkz4P64Wnonl4CMdx4dzGX5wZdtiq3PzLRFMP219SVy1c08mnpQFqTv6fXRuHO
+bqZFZ4Hp4PaVI5pTZ7gkwzVW0Nx4T+INhMCTWenAE8x1vzbL1QECggEBANzutYKr
+3jN+hKFL51wNctuSNQcgPYJleKKKT6WDrd4s7TjoGs1fUKcQySqnMC26QZdlcVZs
+xBirJYz3mMS0RamKTTHZ5Ik08nT8i3nOK1gLd/kJO+AtljrrKG2wzawrg/YyRq+l
+ndhgKieJQxH3GCBN/l99wfRibkA/kuUgV/DFACFGsO0/wBZb0/UgiqjSpLaikpRh
+fZY2Wc5/Jb0PPeofSfHGb9MMCDyONrF16ydlJSAlvCuG2rwoPryxe14ZdjVhM2BO
+svhuJRwqe9PC9gwo9QkIAm4wvXHq9pcoubcxhzWPKlfEg1IV9rcIJ0uCHL6aLGvg
+79hMBjofWRbE1jMCggEBAO1B2ccqvfESzeBzMCdjTGChFcbVn3gXmnQsahB1VRTt
+KLLT8IIVYyuVBbzUkaxVACanLNxF6T1HGMd+hTnAytvge5d6lMpgHcOIKRptVU/J
+63o0jB93K4dttkE8ByftCpLasuK0/hKcDJ4A6GFet7jXIgJXDS69LSL9U5NrT6LK
+a1cNaKbnunGynhLOjO4OWlc080G0I4Pwu0zPhPfLv3TwpFWZio1RhAkSqpMZaHKz
+Q8Qrs2PvXvBH7PM/HPaUyBGFntx1YXH4z6QKxCPO4SoXZnL7+J82bKrHbFmElh7t
+YrdnAokjE0AHhZDfb1dyEb1Z2HeqS+j/CO3JlwKpekcCggEBAJzM6pP4SPbBF36m
+sWhavybpCKurDRyryceKZGazI0YpGqAl00fpGwPHXQ7ho8cAhybdP2g4P6DGbxsy
+awFIdJyUZJ855wIeSuoOhysG0Spm0Vo1XIKJuDLOzV20evRz2e901Ug6QeHctm5i
+8/AfL8dVs3Cwf2RkK517wVTO9LsUBjiXxGBNu5XizHcQBnk1LuPUVDXtT0W6A1kU
+UoNw+t9cH43x6VGfG4Vm5ZhjeWb3WTcMsRUvW7To10XyrP0nEwdlmiIDGPBKtBne
+aQ3tM9WDiA1F2vu7qejc+vBjXhOPmke/+Sxbc1xh7D0RE1p62M3J/DcAaRlZM54y
+u3b2cpMCggEBALcwgyBfBi2fYUsOZX3kE9MATboqs2icgOt2Z6axkbIIs8XwEuG9
+9cZu1/FHB/tR3j36Eo85g6+Gt8FBFUjUbU18dLEvOrdPo2uYNHRtOtPSinjfHdol
+v3xf37tayAOx6Noe9sRJD2v7BVryRHr6EU0s/ttjr5AJDVLY2rEWyHRfaqXaepV0
+kua7DYZj6Tjd6C8xeSmgF1QGiffyuy5BKWD3dUuKtAoNiK8gtIfDtHvrokVToL1m
+050fS/s9HfXeRuQQkeqSz1yaymhUz8D+OaiwTLA3kW4NLbZnKGeuEeNrUy9c3/5X
+EMP9ismjW2rfbocPWi57VQVf9dr0Lh8mEH0CggEARX6i78zZxQHLwePavxpOj0oX
+5xc0alYgTF5qALnX6OolV0aqVPgjDDbIK0SU4CVscgrKW40FZpwTuNYCvWcuj9HA
+bSlJ92MrUEjgwzuCwIkpldc6jIQEfvUIrlMWqdT0ewO6pA7PSDLjtCzTybGmfxUQ
+BDv3nEZsf30marG9jc8LO67a1XqZsQ1f4670zby/YcX6K7ipXVM7Ta4sMpYHiVTY
+PwEZl9+s8cxRzCvN2pGDqZs9BMp10moJz+ZrIWqK/RX2XB7HffVyVNeRMNJCG61h
+bVGx6LLdHYkhqM3HyPzV6/1+NzKco1TgiNx8bq9xU8+VkN5kHr9GaiF/ociuWg==
+-----END RSA PRIVATE KEY-----
diff --git a/kong-versions/3.9.0.0/kong/spec/fixtures/redis_cluster/redis-cluster-compose.yaml b/kong-versions/3.9.0.0/kong/spec/fixtures/redis_cluster/redis-cluster-compose.yaml
new file mode 100644
index 00000000..0b4e62a3
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/fixtures/redis_cluster/redis-cluster-compose.yaml
@@ -0,0 +1,67 @@
+version: '3.5'
+name: redis-cluster
+services:
+ rc-node-1:
+ image: redis:7.0.2
+ volumes:
+ - rc-node-1-data:/data
+ ports:
+ - "7000:7000"
+ command: redis-server --port 7000 --cluster-enabled yes --cluster-port 17000 --cluster-config-file rc-node-1.conf --cluster-node-timeout 5000 --appendonly yes --cluster-announce-port 7000 --cluster-announce-bus-port 17000 --cluster-preferred-endpoint-type hostname --cluster-announce-hostname localhost --daemonize no --loglevel debug
+ rc-node-2:
+ image: redis:7.0.2
+ volumes:
+ - rc-node-2-data:/data
+ ports:
+ - "7001:7001"
+ command: redis-server --port 7001 --cluster-enabled yes --cluster-port 17001 --cluster-config-file rc-node-2.conf --cluster-node-timeout 5000 --appendonly yes --cluster-announce-port 7001 --cluster-announce-bus-port 17001 --cluster-preferred-endpoint-type hostname --cluster-announce-hostname localhost --daemonize no --loglevel debug
+ rc-node-3:
+ image: redis:7.0.2
+ volumes:
+ - rc-node-3-data:/data
+ ports:
+ - "7002:7002"
+ command: redis-server --port 7002 --cluster-enabled yes --cluster-port 17002 --cluster-config-file rc-node-3.conf --cluster-node-timeout 5000 --appendonly yes --cluster-announce-port 7002 --cluster-announce-bus-port 17002 --cluster-preferred-endpoint-type hostname --cluster-announce-hostname localhost --daemonize no --loglevel debug
+ rc-node-4:
+ image: redis:7.0.2
+ volumes:
+ - rc-node-4-data:/data
+ ports:
+ - "7003:7003"
+ command: redis-server --port 7003 --cluster-enabled yes --cluster-port 17003 --cluster-config-file rc-node-4.conf --cluster-node-timeout 5000 --appendonly yes --cluster-announce-port 7003 --cluster-announce-bus-port 17003 --cluster-preferred-endpoint-type hostname --cluster-announce-hostname localhost --daemonize no --loglevel debug
+ rc-node-5:
+ image: redis:7.0.2
+ volumes:
+ - rc-node-5-data:/data
+ ports:
+ - "7004:7004"
+ command: redis-server --port 7004 --cluster-enabled yes --cluster-port 17004 --cluster-config-file rc-node-5.conf --cluster-node-timeout 5000 --appendonly yes --cluster-announce-port 7004 --cluster-announce-bus-port 17004 --cluster-preferred-endpoint-type hostname --cluster-announce-hostname localhost --daemonize no --loglevel debug
+ rc-node-6:
+ image: redis:7.0.2
+ volumes:
+ - rc-node-6-data:/data
+ ports:
+ - "7005:7005"
+ command: redis-server --port 7005 --cluster-enabled yes --cluster-port 17005 --cluster-config-file rc-node-6.conf --cluster-node-timeout 5000 --appendonly yes --cluster-announce-port 7005 --cluster-announce-bus-port 17005 --cluster-preferred-endpoint-type hostname --cluster-announce-hostname localhost --daemonize no --loglevel debug
+ create-cluster:
+ image: redis:7.0.2
+ command: redis-cli --cluster create rc-node-1:7000 rc-node-2:7001 rc-node-3:7002 rc-node-4:7003 rc-node-5:7004 rc-node-6:7005 --cluster-replicas 1 --cluster-yes
+ depends_on:
+ - rc-node-1
+ - rc-node-2
+ - rc-node-3
+ - rc-node-4
+ - rc-node-5
+ - rc-node-6
+
+volumes:
+ rc-node-1-data:
+ rc-node-2-data:
+ rc-node-3-data:
+ rc-node-4-data:
+ rc-node-5-data:
+ rc-node-6-data:
+
+networks:
+ default:
+ name: redis-cluster
diff --git a/kong-versions/3.9.0.0/kong/spec/fixtures/redis_sentinel/redis-sentinel-compose.yaml b/kong-versions/3.9.0.0/kong/spec/fixtures/redis_sentinel/redis-sentinel-compose.yaml
new file mode 100644
index 00000000..0f77e854
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/fixtures/redis_sentinel/redis-sentinel-compose.yaml
@@ -0,0 +1,63 @@
+services:
+ redis-master:
+ image: redis:7.4
+ command: redis-server
+ healthcheck:
+ test: ["CMD-SHELL", "redis-cli ping | grep PONG"]
+ interval: 1s
+ timeout: 3s
+ retries: 5
+ network_mode: host
+
+ redis-replica-1:
+ image: redis:7.4
+ network_mode: host
+ command: redis-server --replicaof 127.0.0.1 6379 --port 6380
+ depends_on:
+ - redis-master
+
+ redis-replica-2:
+ image: redis:7.4
+ network_mode: host
+ command: redis-server --replicaof 127.0.0.1 6379 --port 6381
+ depends_on:
+ - redis-master
+
+ sentinel-1:
+ build:
+ context: ./sentinel
+ args:
+ MASTER_IP: 127.0.0.1
+ MASTER_PORT: 6379
+ SENTINEL_PORT: 27000
+ network_mode: host
+ depends_on:
+ - redis-master
+ - redis-replica-1
+ - redis-replica-2
+
+ sentinel-2:
+ build:
+ context: ./sentinel
+ args:
+ MASTER_IP: 127.0.0.1
+ MASTER_PORT: 6379
+ SENTINEL_PORT: 27001
+ network_mode: host
+ depends_on:
+ - redis-master
+ - redis-replica-1
+ - redis-replica-2
+
+ sentinel-3:
+ build:
+ context: ./sentinel
+ args:
+ MASTER_IP: 127.0.0.1
+ MASTER_PORT: 6379
+ SENTINEL_PORT: 27002
+ network_mode: host
+ depends_on:
+ - redis-master
+ - redis-replica-1
+ - redis-replica-2
diff --git a/kong-versions/3.9.0.0/kong/spec/fixtures/redis_sentinel/sentinel/Dockerfile b/kong-versions/3.9.0.0/kong/spec/fixtures/redis_sentinel/sentinel/Dockerfile
new file mode 100644
index 00000000..08ed4df6
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/fixtures/redis_sentinel/sentinel/Dockerfile
@@ -0,0 +1,13 @@
+FROM redis:7.4
+
+ARG MASTER_IP
+ARG MASTER_PORT
+ARG SENTINEL_PORT
+
+COPY --chown=redis:redis sentinel_template.conf /etc/redis/sentinel.conf
+
+RUN sed -i "s/\$SENTINEL_PORT/${SENTINEL_PORT}/g" /etc/redis/sentinel.conf
+RUN sed -i "s/\$MASTER_IP/${MASTER_IP}/g" /etc/redis/sentinel.conf
+RUN sed -i "s/\$MASTER_PORT/${MASTER_PORT}/g" /etc/redis/sentinel.conf
+
+CMD redis-server "/etc/redis/sentinel.conf" --sentinel
diff --git a/kong-versions/3.9.0.0/kong/spec/fixtures/redis_sentinel/sentinel/sentinel_template.conf b/kong-versions/3.9.0.0/kong/spec/fixtures/redis_sentinel/sentinel/sentinel_template.conf
new file mode 100644
index 00000000..7a1fefc7
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/fixtures/redis_sentinel/sentinel/sentinel_template.conf
@@ -0,0 +1,6 @@
+port $SENTINEL_PORT
+
+sentinel resolve-hostnames yes
+sentinel monitor mymaster $MASTER_IP $MASTER_PORT 2
+sentinel down-after-milliseconds mymaster 5000
+sentinel failover-timeout mymaster 60000
diff --git a/kong-versions/3.9.0.0/kong/spec/fixtures/reload.conf b/kong-versions/3.9.0.0/kong/spec/fixtures/reload.conf
new file mode 100644
index 00000000..4f48721e
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/fixtures/reload.conf
@@ -0,0 +1,3 @@
+prefix = servroot
+nginx_main_worker_processes = 1
+proxy_listen = 0.0.0.0:9000
diff --git a/kong-versions/3.9.0.0/kong/spec/fixtures/router_path_handling_tests.lua b/kong-versions/3.9.0.0/kong/spec/fixtures/router_path_handling_tests.lua
new file mode 100644
index 00000000..d03c20da
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/fixtures/router_path_handling_tests.lua
@@ -0,0 +1,212 @@
+-- This software is copyright Kong Inc. and its licensors.
+-- Use of the software is subject to the agreement between your organization
+-- and Kong Inc. If there is no such agreement, use is governed by and
+-- subject to the terms of the Kong Master Software License Agreement found
+-- at https://konghq.com/enterprisesoftwarelicense/.
+-- [ END OF LICENSE 0867164ffc95e54f04670b5169c09574bdbd9bba ]
+
+local cycle_aware_deep_copy = require("kong.tools.table").cycle_aware_deep_copy
+
+-- The following tests are used by unit and integration tests
+-- to test the router path handling. Putting them here avoids
+-- copy-pasting them in several places.
+--
+-- The tests can obtain this table by requiring
+-- "spec.fixtures.router_path_handling_tests"
+--
+-- The rows are sorted by service_path, route_path, strip_path, path_handling and request_path.
+--
+-- Notes:
+-- * The tests are parsed into a hash form at the end
+-- of this file before they are returned.
+-- * Before a test can be executed, it needs to be "expanded".
+-- For example, a test with {"v0", "v1"} must be converted
+-- into two tests, one with "v0" and one with "v1". Each line
+-- can be expanded using the `line:expand()` method.
+
+local tests = {
+ -- service_path route_path strip_path path_handling request_path expected_path
+ { "/", "/", {false, true}, {"v0", "v1"}, "/", "/", },
+ { "/", "/", {false, true}, {"v0", "v1"}, "/route", "/route", },
+ { "/", "/", {false, true}, {"v0", "v1"}, "/route/", "/route/", },
+ { "/", "/", {false, true}, {"v0", "v1"}, "/routereq", "/routereq", },
+ { "/", "/", {false, true}, {"v0", "v1"}, "/route/req", "/route/req", }, -- 5
+ -- service_path route_path strip_path path_handling request_path expected_path
+ { "/", "/route", false, {"v0", "v1"}, "/route", "/route", },
+ { "/", "/route", false, {"v0", "v1"}, "/route/", "/route/", },
+ { "/", "/route", false, {"v0", "v1"}, "/routereq", "/routereq", },
+ { "/", "/route", true, {"v0", "v1"}, "/route", "/", },
+ { "/", "/route", true, {"v0", "v1"}, "/route/", "/", },
+ { "/", "/route", true, {"v0", "v1"}, "/routereq", "/req", }, -- 11
+ -- service_path route_path strip_path path_handling request_path expected_path
+ { "/", "/route/", false, {"v0", "v1"}, "/route/", "/route/", },
+ { "/", "/route/", false, {"v0", "v1"}, "/route/req", "/route/req", },
+ { "/", "/route/", true, {"v0", "v1"}, "/route/", "/", },
+ { "/", "/route/", true, {"v0", "v1"}, "/route/req", "/req", }, -- 15
+ -- service_path route_path strip_path path_handling request_path expected_path
+ { "/srv", "/rou", false, "v0", "/roureq", "/srv/roureq", },
+ { "/srv", "/rou", false, "v1", "/roureq", "/srvroureq", },
+ { "/srv", "/rou", true, "v0", "/roureq", "/srv/req", },
+ { "/srv", "/rou", true, "v1", "/roureq", "/srvreq", }, -- 19
+ -- service_path route_path strip_path path_handling request_path expected_path
+ { "/srv/", "/rou", false, {"v0", "v1"}, "/rou", "/srv/rou", },
+ { "/srv/", "/rou", true, "v0", "/rou", "/srv", },
+ { "/srv/", "/rou", true, "v1", "/rou", "/srv/", }, -- 22
+ -- service_path route_path strip_path path_handling request_path expected_path
+ { "/service", "/", {false, true}, {"v0", "v1"}, "/", "/service", },
+ { "/service", "/", {false, true}, "v0", "/route", "/service/route", },
+ { "/service", "/", {false, true}, "v1", "/route", "/serviceroute", },
+ { "/service", "/", {false, true}, "v0", "/route/", "/service/route/", },
+ { "/service", "/", {false, true}, "v1", "/route/", "/serviceroute/", }, -- 27
+ -- service_path route_path strip_path path_handling request_path expected_path
+ { "/service", "/", {false, true}, "v0", "/routereq", "/service/routereq", },
+ { "/service", "/", {false, true}, "v1", "/routereq", "/serviceroutereq", },
+ { "/service", "/", {false, true}, "v0", "/route/req", "/service/route/req", },
+ { "/service", "/", {false, true}, "v1", "/route/req", "/serviceroute/req", }, -- 31
+ -- service_path route_path strip_path path_handling request_path expected_path
+ { "/service", "/route", false, "v0", "/route", "/service/route", },
+ { "/service", "/route", false, "v1", "/route", "/serviceroute", },
+ { "/service", "/route", false, "v0", "/route/", "/service/route/", },
+ { "/service", "/route", false, "v1", "/route/", "/serviceroute/", },
+ { "/service", "/route", false, "v0", "/routereq", "/service/routereq", },
+ { "/service", "/route", false, "v1", "/routereq", "/serviceroutereq", },
+ { "/service", "/route", true, {"v0", "v1"}, "/route", "/service", },
+ { "/service", "/route", true, {"v0", "v1"}, "/route/", "/service/", },
+ { "/service", "/route", true, "v0", "/routereq", "/service/req", },
+ { "/service", "/route", true, "v1", "/routereq", "/servicereq", }, -- 41
+ -- service_path route_path strip_path path_handling request_path expected_path
+ { "/service", "/route/", false, "v0", "/route/", "/service/route/", },
+ { "/service", "/route/", false, "v1", "/route/", "/serviceroute/", },
+ { "/service", "/route/", false, "v0", "/route/req", "/service/route/req", },
+ { "/service", "/route/", false, "v1", "/route/req", "/serviceroute/req", },
+ { "/service", "/route/", true, "v0", "/route/", "/service/", },
+ { "/service", "/route/", true, "v1", "/route/", "/service", },
+ { "/service", "/route/", true, "v0", "/route/req", "/service/req", },
+ { "/service", "/route/", true, "v1", "/route/req", "/servicereq", }, -- 49
+ -- service_path route_path strip_path path_handling request_path expected_path
+ { "/service/", "/", {false, true}, "v0", "/route/", "/service/route/", },
+ { "/service/", "/", {false, true}, "v1", "/route/", "/service/route/", },
+ { "/service/", "/", {false, true}, {"v0", "v1"}, "/", "/service/", },
+ { "/service/", "/", {false, true}, {"v0", "v1"}, "/route", "/service/route", },
+ { "/service/", "/", {false, true}, {"v0", "v1"}, "/routereq", "/service/routereq", },
+ { "/service/", "/", {false, true}, {"v0", "v1"}, "/route/req", "/service/route/req", }, -- 55
+ -- service_path route_path strip_path path_handling request_path expected_path
+ { "/service/", "/route", false, {"v0", "v1"}, "/route", "/service/route", },
+ { "/service/", "/route", false, {"v0", "v1"}, "/route/", "/service/route/", },
+ { "/service/", "/route", false, {"v0", "v1"}, "/routereq", "/service/routereq", },
+ { "/service/", "/route", true, "v0", "/route", "/service", },
+ { "/service/", "/route", true, "v1", "/route", "/service/", },
+ { "/service/", "/route", true, {"v0", "v1"}, "/route/", "/service/", },
+ { "/service/", "/route", true, {"v0", "v1"}, "/routereq", "/service/req", }, -- 62
+ -- service_path route_path strip_path path_handling request_path expected_path
+ { "/service/", "/route/", false, {"v0", "v1"}, "/route/", "/service/route/", },
+ { "/service/", "/route/", false, {"v0", "v1"}, "/route/req", "/service/route/req", },
+ { "/service/", "/route/", true, {"v0", "v1"}, "/route/", "/service/", },
+ { "/service/", "/route/", true, {"v0", "v1"}, "/route/req", "/service/req", }, -- 66
+ -- service_path route_path strip_path path_handling request_path expected_path
+ -- The following cases match on host (not paths)
+ { "/", nil, {false, true}, {"v0", "v1"}, "/", "/", },
+ { "/", nil, {false, true}, {"v0", "v1"}, "/route", "/route", },
+ { "/", nil, {false, true}, {"v0", "v1"}, "/route/", "/route/", }, -- 69
+ -- service_path route_path strip_path path_handling request_path expected_path
+ { "/service", nil, {false, true}, {"v0", "v1"}, "/", "/service", },
+ { "/service", nil, {false, true}, "v0", "/route", "/service/route", },
+ { "/service", nil, {false, true}, "v1", "/route", "/serviceroute", },
+ { "/service", nil, {false, true}, "v0", "/route/", "/service/route/", },
+ { "/service", nil, {false, true}, "v1", "/route/", "/serviceroute/", }, -- 74
+ -- service_path route_path strip_path path_handling request_path expected_path
+ { "/service/", nil, {false, true}, {"v0", "v1"}, "/", "/service/", },
+ { "/service/", nil, {false, true}, {"v0", "v1"}, "/route", "/service/route", },
+ { "/service/", nil, {false, true}, {"v0", "v1"}, "/route/", "/service/route/", }, -- 77
+ -- service_path route_path strip_path path_handling request_path expected_path
+ { "/service", "/route", true, "v0", "/route./req", "/service/req", },
+ { "/service", "/route", true, "v1", "/route./req", "/servicereq", },
+ { "/service/", "/route", true, {"v0", "v1"}, "/route./req", "/service/req", }, -- 80
+ -- service_path route_path strip_path path_handling request_path expected_path
+ { "/service", "/route", true, "v0", "/route%2E/req", "/service/req", },
+ { "/service", "/route", true, "v1", "/route%2E/req", "/servicereq", },
+ { "/service/", "/route", true, {"v0", "v1"}, "/route%2E/req", "/service/req", },
+ { "/service", "/route", true, "v0", "/route%2e/req", "/service/req", },
+ { "/service", "/route", true, "v1", "/route%2e/req", "/servicereq", },
+ { "/service/", "/route", true, {"v0", "v1"}, "/route%2e/req", "/service/req", }, -- 86
+ -- service_path route_path strip_path path_handling request_path expected_path
+ { "/service", "/route", true, "v0", "/route../req", "/service/req", },
+ { "/service", "/route", true, "v1", "/route../req", "/servicereq", },
+ { "/service/", "/route", true, {"v0", "v1"}, "/route../req", "/service/req", }, -- 89
+ -- service_path route_path strip_path path_handling request_path expected_path
+ { "/service", "/route", true, "v0", "/route%2E%2E/req", "/service/req", },
+ { "/service", "/route", true, "v1", "/route%2E%2E/req", "/servicereq", },
+ { "/service/", "/route", true, {"v0", "v1"}, "/route%2E%2E/req", "/service/req", },
+ { "/service", "/route", true, "v0", "/route%2e%2E/req", "/service/req", },
+ { "/service", "/route", true, "v1", "/route%2e%2E/req", "/servicereq", },
+ { "/service/", "/route", true, {"v0", "v1"}, "/route%2e%2E/req", "/service/req", }, -- 95
+ -- service_path route_path strip_path path_handling request_path expected_path
+ { "/service", "/route", false, "v0", "/route./req", "/service/route./req", },
+ { "/service", "/route", false, "v1", "/route./req", "/serviceroute./req", },
+ { "/service/", "/route", false, {"v0", "v1"}, "/route./req", "/service/route./req", }, -- 98
+ -- service_path route_path strip_path path_handling request_path expected_path
+ { "/service", "/route", false, "v0", "/route%2E/req", "/service/route./req", },
+ { "/service", "/route", false, "v1", "/route%2E/req", "/serviceroute./req", },
+ { "/service/", "/route", false, {"v0", "v1"}, "/route%2E/req", "/service/route./req", },
+ { "/service", "/route", false, "v0", "/route%2e/req", "/service/route./req", },
+ { "/service", "/route", false, "v1", "/route%2e/req", "/serviceroute./req", },
+ { "/service/", "/route", false, {"v0", "v1"}, "/route%2e/req", "/service/route./req", }, -- 104
+ -- service_path route_path strip_path path_handling request_path expected_path
+ { "/service", "/route", false, "v0", "/route../req", "/service/route../req", },
+ { "/service", "/route", false, "v1", "/route../req", "/serviceroute../req", },
+ { "/service/", "/route", false, {"v0", "v1"}, "/route../req", "/service/route../req", }, -- 107
+ -- service_path route_path strip_path path_handling request_path expected_path
+ { "/service", "/route", false, "v0", "/route%2E%2E/req", "/service/route../req", },
+ { "/service", "/route", false, "v1", "/route%2E%2E/req", "/serviceroute../req", },
+ { "/service/", "/route", false, {"v0", "v1"}, "/route%2E%2E/req", "/service/route../req", },
+ { "/service", "/route", false, "v0", "/route%2e%2E/req", "/service/route../req", },
+ { "/service", "/route", false, "v1", "/route%2e%2E/req", "/serviceroute../req", },
+ { "/service/", "/route", false, {"v0", "v1"}, "/route%2e%2E/req", "/service/route../req", }, -- 113
+}
+
+
+local function expand(root_test)
+ local expanded_tests = { root_test }
+
+ for _, field_name in ipairs({ "strip_path", "path_handling" }) do
+ local new_tests = {}
+ for _, test in ipairs(expanded_tests) do
+ if type(test[field_name]) == "table" then
+ for _, field_value in ipairs(test[field_name]) do
+ local et = cycle_aware_deep_copy(test)
+ et[field_name] = field_value
+ new_tests[#new_tests + 1] = et
+ end
+
+ else
+ new_tests[#new_tests + 1] = test
+ end
+ end
+ expanded_tests = new_tests
+ end
+
+ return expanded_tests
+end
+
+
+local tests_mt = {
+ __index = {
+ expand = expand
+ }
+}
+
+
+local parsed_tests = {}
+for i = 1, #tests do
+ local test = tests[i]
+ parsed_tests[i] = setmetatable({
+ service_path = test[1],
+ route_path = test[2],
+ strip_path = test[3],
+ path_handling = test[4],
+ request_path = test[5],
+ expected_path = test[6],
+ }, tests_mt)
+end
+
+return parsed_tests
diff --git a/kong-versions/3.9.0.0/kong/spec/fixtures/sam-app/.gitignore b/kong-versions/3.9.0.0/kong/spec/fixtures/sam-app/.gitignore
new file mode 100644
index 00000000..4808264d
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/fixtures/sam-app/.gitignore
@@ -0,0 +1,244 @@
+
+# Created by https://www.gitignore.io/api/osx,linux,python,windows,pycharm,visualstudiocode
+
+### Linux ###
+*~
+
+# temporary files which can be created if a process still has a handle open of a deleted file
+.fuse_hidden*
+
+# KDE directory preferences
+.directory
+
+# Linux trash folder which might appear on any partition or disk
+.Trash-*
+
+# .nfs files are created when an open file is removed but is still being accessed
+.nfs*
+
+### OSX ###
+*.DS_Store
+.AppleDouble
+.LSOverride
+
+# Icon must end with two \r
+Icon
+
+# Thumbnails
+._*
+
+# Files that might appear in the root of a volume
+.DocumentRevisions-V100
+.fseventsd
+.Spotlight-V100
+.TemporaryItems
+.Trashes
+.VolumeIcon.icns
+.com.apple.timemachine.donotpresent
+
+# Directories potentially created on remote AFP share
+.AppleDB
+.AppleDesktop
+Network Trash Folder
+Temporary Items
+.apdisk
+
+### PyCharm ###
+# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and Webstorm
+# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
+
+# User-specific stuff:
+.idea/**/workspace.xml
+.idea/**/tasks.xml
+.idea/dictionaries
+
+# Sensitive or high-churn files:
+.idea/**/dataSources/
+.idea/**/dataSources.ids
+.idea/**/dataSources.xml
+.idea/**/dataSources.local.xml
+.idea/**/sqlDataSources.xml
+.idea/**/dynamic.xml
+.idea/**/uiDesigner.xml
+
+# Gradle:
+.idea/**/gradle.xml
+.idea/**/libraries
+
+# CMake
+cmake-build-debug/
+
+# Mongo Explorer plugin:
+.idea/**/mongoSettings.xml
+
+## File-based project format:
+*.iws
+
+## Plugin-specific files:
+
+# IntelliJ
+/out/
+
+# mpeltonen/sbt-idea plugin
+.idea_modules/
+
+# JIRA plugin
+atlassian-ide-plugin.xml
+
+# Cursive Clojure plugin
+.idea/replstate.xml
+
+# Ruby plugin and RubyMine
+/.rakeTasks
+
+# Crashlytics plugin (for Android Studio and IntelliJ)
+com_crashlytics_export_strings.xml
+crashlytics.properties
+crashlytics-build.properties
+fabric.properties
+
+### PyCharm Patch ###
+# Comment Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-215987721
+
+# *.iml
+# modules.xml
+# .idea/misc.xml
+# *.ipr
+
+# Sonarlint plugin
+.idea/sonarlint
+
+### Python ###
+# Byte-compiled / optimized / DLL files
+__pycache__/
+*.py[cod]
+*$py.class
+
+# C extensions
+*.so
+
+# Distribution / packaging
+.Python
+build/
+develop-eggs/
+dist/
+downloads/
+eggs/
+.eggs/
+lib/
+lib64/
+parts/
+sdist/
+var/
+wheels/
+*.egg-info/
+.installed.cfg
+*.egg
+
+# PyInstaller
+# Usually these files are written by a python script from a template
+# before PyInstaller builds the exe, so as to inject date/other infos into it.
+*.manifest
+*.spec
+
+# Installer logs
+pip-log.txt
+pip-delete-this-directory.txt
+
+# Unit test / coverage reports
+htmlcov/
+.tox/
+.coverage
+.coverage.*
+.cache
+.pytest_cache/
+nosetests.xml
+coverage.xml
+*.cover
+.hypothesis/
+
+# Translations
+*.mo
+*.pot
+
+# Flask stuff:
+instance/
+.webassets-cache
+
+# Scrapy stuff:
+.scrapy
+
+# Sphinx documentation
+docs/_build/
+
+# PyBuilder
+target/
+
+# Jupyter Notebook
+.ipynb_checkpoints
+
+# pyenv
+.python-version
+
+# celery beat schedule file
+celerybeat-schedule.*
+
+# SageMath parsed files
+*.sage.py
+
+# Environments
+.env
+.venv
+env/
+venv/
+ENV/
+env.bak/
+venv.bak/
+
+# Spyder project settings
+.spyderproject
+.spyproject
+
+# Rope project settings
+.ropeproject
+
+# mkdocs documentation
+/site
+
+# mypy
+.mypy_cache/
+
+### VisualStudioCode ###
+.vscode/*
+!.vscode/settings.json
+!.vscode/tasks.json
+!.vscode/launch.json
+!.vscode/extensions.json
+.history
+
+### Windows ###
+# Windows thumbnail cache files
+Thumbs.db
+ehthumbs.db
+ehthumbs_vista.db
+
+# Folder config file
+Desktop.ini
+
+# Recycle Bin used on file shares
+$RECYCLE.BIN/
+
+# Windows Installer files
+*.cab
+*.msi
+*.msm
+*.msp
+
+# Windows shortcuts
+*.lnk
+
+# Build folder
+
+*/build/*
+
+# End of https://www.gitignore.io/api/osx,linux,python,windows,pycharm,visualstudiocode
\ No newline at end of file
diff --git a/kong-versions/3.9.0.0/kong/spec/fixtures/sam-app/README.md b/kong-versions/3.9.0.0/kong/spec/fixtures/sam-app/README.md
new file mode 100644
index 00000000..03499479
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/fixtures/sam-app/README.md
@@ -0,0 +1,130 @@
+# sam-app
+
+This project contains source code and supporting files for a serverless application that you can deploy with the SAM CLI. It includes the following files and folders.
+
+- hello_world - Code for the application's Lambda function.
+- events - Invocation events that you can use to invoke the function.
+- tests - Unit tests for the application code.
+- template.yaml - A template that defines the application's AWS resources.
+
+The application uses several AWS resources, including Lambda functions and an API Gateway API. These resources are defined in the `template.yaml` file in this project. You can update the template to add AWS resources through the same deployment process that updates your application code.
+
+If you prefer to use an integrated development environment (IDE) to build and test your application, you can use the AWS Toolkit.
+The AWS Toolkit is an open source plug-in for popular IDEs that uses the SAM CLI to build and deploy serverless applications on AWS. The AWS Toolkit also adds a simplified step-through debugging experience for Lambda function code. See the following links to get started.
+
+* [CLion](https://docs.aws.amazon.com/toolkit-for-jetbrains/latest/userguide/welcome.html)
+* [GoLand](https://docs.aws.amazon.com/toolkit-for-jetbrains/latest/userguide/welcome.html)
+* [IntelliJ](https://docs.aws.amazon.com/toolkit-for-jetbrains/latest/userguide/welcome.html)
+* [WebStorm](https://docs.aws.amazon.com/toolkit-for-jetbrains/latest/userguide/welcome.html)
+* [Rider](https://docs.aws.amazon.com/toolkit-for-jetbrains/latest/userguide/welcome.html)
+* [PhpStorm](https://docs.aws.amazon.com/toolkit-for-jetbrains/latest/userguide/welcome.html)
+* [PyCharm](https://docs.aws.amazon.com/toolkit-for-jetbrains/latest/userguide/welcome.html)
+* [RubyMine](https://docs.aws.amazon.com/toolkit-for-jetbrains/latest/userguide/welcome.html)
+* [DataGrip](https://docs.aws.amazon.com/toolkit-for-jetbrains/latest/userguide/welcome.html)
+* [VS Code](https://docs.aws.amazon.com/toolkit-for-vscode/latest/userguide/welcome.html)
+* [Visual Studio](https://docs.aws.amazon.com/toolkit-for-visual-studio/latest/user-guide/welcome.html)
+
+## Deploy the sample application
+
+The Serverless Application Model Command Line Interface (SAM CLI) is an extension of the AWS CLI that adds functionality for building and testing Lambda applications. It uses Docker to run your functions in an Amazon Linux environment that matches Lambda. It can also emulate your application's build environment and API.
+
+To use the SAM CLI, you need the following tools.
+
+* SAM CLI - [Install the SAM CLI](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-sam-cli-install.html)
+* [Python 3 installed](https://www.python.org/downloads/)
+* Docker - [Install Docker community edition](https://hub.docker.com/search/?type=edition&offering=community)
+
+To build and deploy your application for the first time, run the following in your shell:
+
+```bash
+sam build --use-container
+sam deploy --guided
+```
+
+The first command will build the source of your application. The second command will package and deploy your application to AWS, with a series of prompts:
+
+* **Stack Name**: The name of the stack to deploy to CloudFormation. This should be unique to your account and region, and a good starting point would be something matching your project name.
+* **AWS Region**: The AWS region you want to deploy your app to.
+* **Confirm changes before deploy**: If set to yes, any change sets will be shown to you before execution for manual review. If set to no, the AWS SAM CLI will automatically deploy application changes.
+* **Allow SAM CLI IAM role creation**: Many AWS SAM templates, including this example, create AWS IAM roles required for the AWS Lambda function(s) included to access AWS services. By default, these are scoped down to minimum required permissions. To deploy an AWS CloudFormation stack which creates or modifies IAM roles, the `CAPABILITY_IAM` value for `capabilities` must be provided. If permission isn't provided through this prompt, to deploy this example you must explicitly pass `--capabilities CAPABILITY_IAM` to the `sam deploy` command.
+* **Save arguments to samconfig.toml**: If set to yes, your choices will be saved to a configuration file inside the project, so that in the future you can just re-run `sam deploy` without parameters to deploy changes to your application.
+
+You can find your API Gateway Endpoint URL in the output values displayed after deployment.
+
+## Use the SAM CLI to build and test locally
+
+Build your application with the `sam build --use-container` command.
+
+```bash
+sam-app$ sam build --use-container
+```
+
+The SAM CLI installs dependencies defined in `hello_world/requirements.txt`, creates a deployment package, and saves it in the `.aws-sam/build` folder.
+
+Test a single function by invoking it directly with a test event. An event is a JSON document that represents the input that the function receives from the event source. Test events are included in the `events` folder in this project.
+
+Run functions locally and invoke them with the `sam local invoke` command.
+
+```bash
+sam-app$ sam local invoke HelloWorldFunction --event events/event.json
+```
+
+The SAM CLI can also emulate your application's API. Use the `sam local start-api` to run the API locally on port 3000.
+
+```bash
+sam-app$ sam local start-api
+sam-app$ curl http://localhost:3000/
+```
+
+The SAM CLI reads the application template to determine the API's routes and the functions that they invoke. The `Events` property on each function's definition includes the route and method for each path.
+
+```yaml
+ Events:
+ HelloWorld:
+ Type: Api
+ Properties:
+ Path: /hello
+ Method: get
+```
+
+## Add a resource to your application
+The application template uses AWS Serverless Application Model (AWS SAM) to define application resources. AWS SAM is an extension of AWS CloudFormation with a simpler syntax for configuring common serverless application resources such as functions, triggers, and APIs. For resources not included in [the SAM specification](https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md), you can use standard [AWS CloudFormation](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-template-resource-type-ref.html) resource types.
+
+## Fetch, tail, and filter Lambda function logs
+
+To simplify troubleshooting, SAM CLI has a command called `sam logs`. `sam logs` lets you fetch logs generated by your deployed Lambda function from the command line. In addition to printing the logs on the terminal, this command has several nifty features to help you quickly find the bug.
+
+`NOTE`: This command works for all AWS Lambda functions; not just the ones you deploy using SAM.
+
+```bash
+sam-app$ sam logs -n HelloWorldFunction --stack-name sam-app --tail
+```
+
+You can find more information and examples about filtering Lambda function logs in the [SAM CLI Documentation](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-sam-cli-logging.html).
+
+## Tests
+
+Tests are defined in the `tests` folder in this project. Use PIP to install the test dependencies and run tests.
+
+```bash
+sam-app$ pip install -r tests/requirements.txt --user
+# unit test
+sam-app$ python -m pytest tests/unit -v
+# integration test, requiring deploying the stack first.
+# Create the env variable AWS_SAM_STACK_NAME with the name of the stack we are testing
+sam-app$ AWS_SAM_STACK_NAME= python -m pytest tests/integration -v
+```
+
+## Cleanup
+
+To delete the sample application that you created, use the AWS CLI. Assuming you used your project name for the stack name, you can run the following:
+
+```bash
+aws cloudformation delete-stack --stack-name sam-app
+```
+
+## Resources
+
+See the [AWS SAM developer guide](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/what-is-sam.html) for an introduction to SAM specification, the SAM CLI, and serverless application concepts.
+
+Next, you can use AWS Serverless Application Repository to deploy ready to use Apps that go beyond hello world samples and learn how authors developed their applications: [AWS Serverless Application Repository main page](https://aws.amazon.com/serverless/serverlessrepo/)
diff --git a/kong-versions/3.9.0.0/kong/spec/fixtures/sam-app/__init__.py b/kong-versions/3.9.0.0/kong/spec/fixtures/sam-app/__init__.py
new file mode 100644
index 00000000..e69de29b
diff --git a/kong-versions/3.9.0.0/kong/spec/fixtures/sam-app/events/event.json b/kong-versions/3.9.0.0/kong/spec/fixtures/sam-app/events/event.json
new file mode 100644
index 00000000..a6197dea
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/fixtures/sam-app/events/event.json
@@ -0,0 +1,62 @@
+{
+ "body": "{\"message\": \"hello world\"}",
+ "resource": "/hello",
+ "path": "/hello",
+ "httpMethod": "GET",
+ "isBase64Encoded": false,
+ "queryStringParameters": {
+ "foo": "bar"
+ },
+ "pathParameters": {
+ "proxy": "/path/to/resource"
+ },
+ "stageVariables": {
+ "baz": "qux"
+ },
+ "headers": {
+ "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8",
+ "Accept-Encoding": "gzip, deflate, sdch",
+ "Accept-Language": "en-US,en;q=0.8",
+ "Cache-Control": "max-age=0",
+ "CloudFront-Forwarded-Proto": "https",
+ "CloudFront-Is-Desktop-Viewer": "true",
+ "CloudFront-Is-Mobile-Viewer": "false",
+ "CloudFront-Is-SmartTV-Viewer": "false",
+ "CloudFront-Is-Tablet-Viewer": "false",
+ "CloudFront-Viewer-Country": "US",
+ "Host": "1234567890.execute-api.us-east-1.amazonaws.com",
+ "Upgrade-Insecure-Requests": "1",
+ "User-Agent": "Custom User Agent String",
+ "Via": "1.1 08f323deadbeefa7af34d5feb414ce27.cloudfront.net (CloudFront)",
+ "X-Amz-Cf-Id": "cDehVQoZnx43VYQb9j2-nvCh-9z396Uhbp027Y2JvkCPNLmGJHqlaA==",
+ "X-Forwarded-For": "127.0.0.1, 127.0.0.2",
+ "X-Forwarded-Port": "443",
+ "X-Forwarded-Proto": "https"
+ },
+ "requestContext": {
+ "accountId": "123456789012",
+ "resourceId": "123456",
+ "stage": "prod",
+ "requestId": "c6af9ac6-7b61-11e6-9a41-93e8deadbeef",
+ "requestTime": "09/Apr/2015:12:34:56 +0000",
+ "requestTimeEpoch": 1428582896000,
+ "identity": {
+ "cognitoIdentityPoolId": null,
+ "accountId": null,
+ "cognitoIdentityId": null,
+ "caller": null,
+ "accessKey": null,
+ "sourceIp": "127.0.0.1",
+ "cognitoAuthenticationType": null,
+ "cognitoAuthenticationProvider": null,
+ "userArn": null,
+ "userAgent": "Custom User Agent String",
+ "user": null
+ },
+ "path": "/prod/hello",
+ "resourcePath": "/hello",
+ "httpMethod": "POST",
+ "apiId": "1234567890",
+ "protocol": "HTTP/1.1"
+ }
+}
diff --git a/kong-versions/3.9.0.0/kong/spec/fixtures/sam-app/hello_world/__init__.py b/kong-versions/3.9.0.0/kong/spec/fixtures/sam-app/hello_world/__init__.py
new file mode 100644
index 00000000..e69de29b
diff --git a/kong-versions/3.9.0.0/kong/spec/fixtures/sam-app/hello_world/app.py b/kong-versions/3.9.0.0/kong/spec/fixtures/sam-app/hello_world/app.py
new file mode 100644
index 00000000..f416e2d9
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/fixtures/sam-app/hello_world/app.py
@@ -0,0 +1,42 @@
+import json
+
+# import requests
+
+
+def lambda_handler(event, context):
+ """Sample pure Lambda function
+
+ Parameters
+ ----------
+ event: dict, required
+ API Gateway Lambda Proxy Input Format
+
+ Event doc: https://docs.aws.amazon.com/apigateway/latest/developerguide/set-up-lambda-proxy-integrations.html#api-gateway-simple-proxy-for-lambda-input-format
+
+ context: object, required
+ Lambda Context runtime methods and attributes
+
+ Context doc: https://docs.aws.amazon.com/lambda/latest/dg/python-context-object.html
+
+ Returns
+ ------
+ API Gateway Lambda Proxy Output Format: dict
+
+ Return doc: https://docs.aws.amazon.com/apigateway/latest/developerguide/set-up-lambda-proxy-integrations.html
+ """
+
+ # try:
+ # ip = requests.get("http://checkip.amazonaws.com/")
+ # except requests.RequestException as e:
+ # # Send some context about this error to Lambda Logs
+ # print(e)
+
+ # raise e
+
+ return {
+ "statusCode": 201,
+ "body": json.dumps({
+ "message": "hello world",
+ # "location": ip.text.replace("\n", "")
+ }),
+ }
diff --git a/kong-versions/3.9.0.0/kong/spec/fixtures/sam-app/hello_world/requirements.txt b/kong-versions/3.9.0.0/kong/spec/fixtures/sam-app/hello_world/requirements.txt
new file mode 100644
index 00000000..663bd1f6
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/fixtures/sam-app/hello_world/requirements.txt
@@ -0,0 +1 @@
+requests
\ No newline at end of file
diff --git a/kong-versions/3.9.0.0/kong/spec/fixtures/sam-app/template.yaml b/kong-versions/3.9.0.0/kong/spec/fixtures/sam-app/template.yaml
new file mode 100644
index 00000000..5c2605ec
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/fixtures/sam-app/template.yaml
@@ -0,0 +1,41 @@
+AWSTemplateFormatVersion: '2010-09-09'
+Transform: AWS::Serverless-2016-10-31
+Description: >
+ sam-app
+
+ Sample SAM Template for sam-app
+
+# More info about Globals: https://github.com/awslabs/serverless-application-model/blob/master/docs/globals.rst
+Globals:
+ Function:
+ Timeout: 3
+
+Resources:
+ HelloWorldFunction:
+ Type: AWS::Serverless::Function # More info about Function Resource: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlessfunction
+ Properties:
+ CodeUri: hello_world/
+ Handler: app.lambda_handler
+ Runtime: python3.9
+ Architectures:
+ - x86_64
+ Events:
+ HelloWorld:
+ Type: Api # More info about API Event Source: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#api
+ Properties:
+ Path: /hello
+ Method: get
+
+Outputs:
+ # ServerlessRestApi is an implicit API created out of Events key under Serverless::Function
+ # Find out more about other implicit resources you can reference within SAM
+ # https://github.com/awslabs/serverless-application-model/blob/master/docs/internals/generated_resources.rst#api
+ HelloWorldApi:
+ Description: "API Gateway endpoint URL for Prod stage for Hello World function"
+ Value: !Sub "https://${ServerlessRestApi}.execute-api.${AWS::Region}.amazonaws.com/Prod/hello/"
+ HelloWorldFunction:
+ Description: "Hello World Lambda Function ARN"
+ Value: !GetAtt HelloWorldFunction.Arn
+ HelloWorldFunctionIamRole:
+ Description: "Implicit IAM Role created for Hello World function"
+ Value: !GetAtt HelloWorldFunctionRole.Arn
diff --git a/kong-versions/3.9.0.0/kong/spec/fixtures/sam-app/tests/__init__.py b/kong-versions/3.9.0.0/kong/spec/fixtures/sam-app/tests/__init__.py
new file mode 100644
index 00000000..e69de29b
diff --git a/kong-versions/3.9.0.0/kong/spec/fixtures/sam-app/tests/integration/__init__.py b/kong-versions/3.9.0.0/kong/spec/fixtures/sam-app/tests/integration/__init__.py
new file mode 100644
index 00000000..e69de29b
diff --git a/kong-versions/3.9.0.0/kong/spec/fixtures/sam-app/tests/integration/test_api_gateway.py b/kong-versions/3.9.0.0/kong/spec/fixtures/sam-app/tests/integration/test_api_gateway.py
new file mode 100644
index 00000000..b96e8033
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/fixtures/sam-app/tests/integration/test_api_gateway.py
@@ -0,0 +1,45 @@
+import os
+
+import boto3
+import pytest
+import requests
+
+"""
+Make sure env variable AWS_SAM_STACK_NAME exists with the name of the stack we are going to test.
+"""
+
+
+class TestApiGateway:
+
+ @pytest.fixture()
+ def api_gateway_url(self):
+ """ Get the API Gateway URL from Cloudformation Stack outputs """
+ stack_name = os.environ.get("AWS_SAM_STACK_NAME")
+
+ if stack_name is None:
+ raise ValueError('Please set the AWS_SAM_STACK_NAME environment variable to the name of your stack')
+
+ client = boto3.client("cloudformation")
+
+ try:
+ response = client.describe_stacks(StackName=stack_name)
+ except Exception as e:
+ raise Exception(
+ f"Cannot find stack {stack_name} \n" f'Please make sure a stack with the name "{stack_name}" exists'
+ ) from e
+
+ stacks = response["Stacks"]
+ stack_outputs = stacks[0]["Outputs"]
+ api_outputs = [output for output in stack_outputs if output["OutputKey"] == "HelloWorldApi"]
+
+ if not api_outputs:
+ raise KeyError(f"HelloWorldAPI not found in stack {stack_name}")
+
+ return api_outputs[0]["OutputValue"] # Extract url from stack outputs
+
+ def test_api_gateway(self, api_gateway_url):
+ """ Call the API Gateway endpoint and check the response """
+ response = requests.get(api_gateway_url)
+
+ assert response.status_code == 200
+ assert response.json() == {"message": "hello world"}
diff --git a/kong-versions/3.9.0.0/kong/spec/fixtures/sam-app/tests/requirements.txt b/kong-versions/3.9.0.0/kong/spec/fixtures/sam-app/tests/requirements.txt
new file mode 100644
index 00000000..b9cf27ab
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/fixtures/sam-app/tests/requirements.txt
@@ -0,0 +1,3 @@
+pytest
+boto3
+requests
diff --git a/kong-versions/3.9.0.0/kong/spec/fixtures/sam-app/tests/unit/__init__.py b/kong-versions/3.9.0.0/kong/spec/fixtures/sam-app/tests/unit/__init__.py
new file mode 100644
index 00000000..e69de29b
diff --git a/kong-versions/3.9.0.0/kong/spec/fixtures/sam-app/tests/unit/test_handler.py b/kong-versions/3.9.0.0/kong/spec/fixtures/sam-app/tests/unit/test_handler.py
new file mode 100644
index 00000000..d98ce574
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/fixtures/sam-app/tests/unit/test_handler.py
@@ -0,0 +1,72 @@
+import json
+
+import pytest
+
+from hello_world import app
+
+
+@pytest.fixture()
+def apigw_event():
+ """ Generates API GW Event"""
+
+ return {
+ "body": '{ "test": "body"}',
+ "resource": "/{proxy+}",
+ "requestContext": {
+ "resourceId": "123456",
+ "apiId": "1234567890",
+ "resourcePath": "/{proxy+}",
+ "httpMethod": "POST",
+ "requestId": "c6af9ac6-7b61-11e6-9a41-93e8deadbeef",
+ "accountId": "123456789012",
+ "identity": {
+ "apiKey": "",
+ "userArn": "",
+ "cognitoAuthenticationType": "",
+ "caller": "",
+ "userAgent": "Custom User Agent String",
+ "user": "",
+ "cognitoIdentityPoolId": "",
+ "cognitoIdentityId": "",
+ "cognitoAuthenticationProvider": "",
+ "sourceIp": "127.0.0.1",
+ "accountId": "",
+ },
+ "stage": "prod",
+ },
+ "queryStringParameters": {"foo": "bar"},
+ "headers": {
+ "Via": "1.1 08f323deadbeefa7af34d5feb414ce27.cloudfront.net (CloudFront)",
+ "Accept-Language": "en-US,en;q=0.8",
+ "CloudFront-Is-Desktop-Viewer": "true",
+ "CloudFront-Is-SmartTV-Viewer": "false",
+ "CloudFront-Is-Mobile-Viewer": "false",
+ "X-Forwarded-For": "127.0.0.1, 127.0.0.2",
+ "CloudFront-Viewer-Country": "US",
+ "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8",
+ "Upgrade-Insecure-Requests": "1",
+ "X-Forwarded-Port": "443",
+ "Host": "1234567890.execute-api.us-east-1.amazonaws.com",
+ "X-Forwarded-Proto": "https",
+ "X-Amz-Cf-Id": "aaaaaaaaaae3VYQb9jd-nvCd-de396Uhbp027Y2JvkCPNLmGJHqlaA==",
+ "CloudFront-Is-Tablet-Viewer": "false",
+ "Cache-Control": "max-age=0",
+ "User-Agent": "Custom User Agent String",
+ "CloudFront-Forwarded-Proto": "https",
+ "Accept-Encoding": "gzip, deflate, sdch",
+ },
+ "pathParameters": {"proxy": "/examplepath"},
+ "httpMethod": "POST",
+ "stageVariables": {"baz": "qux"},
+ "path": "/examplepath",
+ }
+
+
+def test_lambda_handler(apigw_event):
+
+ ret = app.lambda_handler(apigw_event, "")
+ data = json.loads(ret["body"])
+
+ assert ret["statusCode"] == 200
+ assert "message" in ret["body"]
+ assert data["message"] == "hello world"
diff --git a/kong-versions/3.9.0.0/kong/spec/fixtures/shared_dict.lua b/kong-versions/3.9.0.0/kong/spec/fixtures/shared_dict.lua
new file mode 100644
index 00000000..366122ed
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/fixtures/shared_dict.lua
@@ -0,0 +1,72 @@
+-- This software is copyright Kong Inc. and its licensors.
+-- Use of the software is subject to the agreement between your organization
+-- and Kong Inc. If there is no such agreement, use is governed by and
+-- subject to the terms of the Kong Master Software License Agreement found
+-- at https://konghq.com/enterprisesoftwarelicense/.
+-- [ END OF LICENSE 0867164ffc95e54f04670b5169c09574bdbd9bba ]
+
+--- generate resty `--shdict` options executed by bin/busted
+
+local dicts = {
+ -- http shared dicts
+ "kong 5m",
+ "kong_locks 8m",
+ "kong_healthchecks 5m",
+ "kong_cluster_events 5m",
+ "kong_rate_limiting_counters 12m",
+ "kong_core_db_cache 16m",
+ "kong_core_db_cache_miss 16m",
+ "kong_db_cache 16m",
+ "kong_db_cache_2 16m",
+ "kong_db_cache_miss 12m",
+ "kong_db_cache_miss_2 12m",
+ "kong_dns_cache 5m",
+ "kong_mock_upstream_loggers 10m",
+ "kong_secrets 5m",
+ "test_vault 5m",
+ "prometheus_metrics 5m",
+ "lmdb_mlcache 5m",
+ "kong_test_cp_mock 1m",
+
+ --- XXX EE http shared dicts
+ "kong_counters 1m",
+ "kong_vitals 1m",
+ "kong_vitals_lists 1m",
+ "kong_vitals_counters 50m",
+ "kong_reports_consumers 10m",
+ "kong_reports_routes 1m",
+ "kong_reports_services 1m",
+ "kong_reports_workspaces 1m",
+ "kong_keyring 5m",
+ "kong_test_rla_schema_abcd 1m",
+ "kong_test_sp_schema_abcd 1m",
+ "kong_debug_session 1m",
+
+ -- stream shared dicts
+ "stream_kong 5m",
+ "stream_kong_locks 8m",
+ "stream_kong_healthchecks 5m",
+ "stream_kong_cluster_events 5m",
+ "stream_kong_rate_limiting_counters 12m",
+ "stream_kong_core_db_cache 16m",
+ "stream_kong_core_db_cache_miss 16m",
+ "stream_kong_db_cache 16m",
+ "stream_kong_db_cache_2 16m",
+ "stream_kong_db_cache_miss 12m",
+ "stream_kong_db_cache_miss_2 12m",
+ "stream_kong_secrets 5m",
+ "stream_prometheus_metrics 5m",
+
+ --- XXX EE stream shared dicts
+ "stream_kong_counters 50m",
+ "stream_kong_vitals 1m",
+ "stream_kong_vitals_lists 1m",
+ "stream_kong_vitals_counters 50m",
+ "stream_kong_keyring 5m",
+}
+
+for i, v in ipairs(dicts) do
+ dicts[i] = " --shdict '" .. v .. "' "
+end
+
+return table.concat(dicts, " ")
diff --git a/kong-versions/3.9.0.0/kong/spec/fixtures/shm-stub.lua b/kong-versions/3.9.0.0/kong/spec/fixtures/shm-stub.lua
new file mode 100644
index 00000000..7295a44c
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/fixtures/shm-stub.lua
@@ -0,0 +1,118 @@
+-- This software is copyright Kong Inc. and its licensors.
+-- Use of the software is subject to the agreement between your organization
+-- and Kong Inc. If there is no such agreement, use is governed by and
+-- subject to the terms of the Kong Master Software License Agreement found
+-- at https://konghq.com/enterprisesoftwarelicense/.
+-- [ END OF LICENSE 0867164ffc95e54f04670b5169c09574bdbd9bba ]
+
+
+-- DICT Proxy
+-- https://github.com/bsm/fakengx/blob/master/fakengx.lua
+
+local SharedDict = {}
+
+local function set(data, key, value)
+ data[key] = {
+ value = value,
+ info = {expired = false}
+ }
+end
+
+function SharedDict:new()
+ return setmetatable({data = {}}, {__index = self})
+end
+
+function SharedDict:get(key)
+ return self.data[key] and self.data[key].value, nil
+end
+
+function SharedDict:set(key, value)
+ set(self.data, key, value)
+ return true, nil, false
+end
+
+SharedDict.safe_set = SharedDict.set
+
+function SharedDict:add(key, value)
+ if self.data[key] ~= nil then
+ return false, "exists", false
+ end
+
+ set(self.data, key, value)
+ return true, nil, false
+end
+
+function SharedDict:replace(key, value)
+ if self.data[key] == nil then
+ return false, "not found", false
+ end
+
+ set(self.data, key, value)
+ return true, nil, false
+end
+
+function SharedDict:delete(key)
+ if self.data[key] ~= nil then
+ self.data[key] = nil
+ end
+end
+
+function SharedDict:incr(key, value, init)
+ if not self.data[key] then
+ if not init then
+ return nil, "not found"
+ else
+ set(self.data, key, init)
+ end
+ elseif type(self.data[key]) ~= "table" then
+ return nil, "not a table"
+ end
+
+ self.data[key].value = self.data[key].value + value
+ return self.data[key].value, nil
+end
+
+function SharedDict:flush_all()
+ for _, item in pairs(self.data) do
+ item.info.expired = true
+ end
+end
+
+function SharedDict:flush_expired(n)
+ local data = self.data
+ local flushed = 0
+
+ for key, item in pairs(self.data) do
+ if item.info.expired then
+ data[key] = nil
+ flushed = flushed + 1
+ if n and flushed == n then
+ break
+ end
+ end
+ end
+
+ self.data = data
+
+ return flushed
+end
+
+function SharedDict:get_keys()
+ local keys = {}
+ for k, _ in pairs(self.data) do
+ table.insert(keys, k)
+ end
+
+ return keys
+end
+
+local shared_mt = {
+ __index = function(self, key)
+ if rawget(self, key) == nil then
+ self[key] = SharedDict:new()
+ end
+ return self[key]
+ end
+}
+
+return setmetatable({}, shared_mt)
diff --git a/kong-versions/3.9.0.0/kong/spec/fixtures/ssl.lua b/kong-versions/3.9.0.0/kong/spec/fixtures/ssl.lua
new file mode 100644
index 00000000..beaaec61
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/fixtures/ssl.lua
@@ -0,0 +1,747 @@
+-- This software is copyright Kong Inc. and its licensors.
+-- Use of the software is subject to the agreement between your organization
+-- and Kong Inc. If there is no such agreement, use is governed by and
+-- subject to the terms of the Kong Master Software License Agreement found
+-- at https://konghq.com/enterprisesoftwarelicense/.
+-- [ END OF LICENSE 0867164ffc95e54f04670b5169c09574bdbd9bba ]
+
+return {
+ --[[
+ Version: 1 (0x0)
+ Issuer: C = US, ST = California, L = San Francisco, O = Kong, OU = Core, CN = ssl-example.com
+ Validity
+ Not Before: Apr 24 14:36:29 2020 GMT
+ Not After : Feb 7 14:36:29 2294 GMT
+
+ Note: Version 1 was accomplished by using a openssl.cnf file
+ with the x509_extensions line commented out.
+ See https://stackoverflow.com/questions/26788244/how-to-create-a-legacy-v1-or-v2-x-509-cert-for-testing
+ and this line's commit message for more info
+ --]]
+ cert = [[-----BEGIN CERTIFICATE-----
+MIIFbTCCA1UCFGjFyapVZYpvpKuYDJbLA1YJip++MA0GCSqGSIb3DQEBCwUAMHIx
+CzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRYwFAYDVQQHEw1TYW4g
+RnJhbmNpc2NvMQ0wCwYDVQQKEwRLb25nMQ0wCwYDVQQLEwRDb3JlMRgwFgYDVQQD
+Ew9zc2wtZXhhbXBsZS5jb20wIBcNMjAwNDI0MTQzNjI5WhgPMjI5NDAyMDcxNDM2
+MjlaMHIxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRYwFAYDVQQH
+Ew1TYW4gRnJhbmNpc2NvMQ0wCwYDVQQKEwRLb25nMQ0wCwYDVQQLEwRDb3JlMRgw
+FgYDVQQDEw9zc2wtZXhhbXBsZS5jb20wggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAw
+ggIKAoICAQDDd3IZRGgdL34RY1MiAE2ItnJNbZGPQD9XE32D/I1cDCAXjI/MQrvn
+iSJhnnc/8F2y7/tzJ2GZIk0C8Fz7MRWDXHCBt9byOHU0Jhppj/cRyWqlI7GrvyZy
+QAiyOh/97ZN52xwXqiFDRXCd43PIgPhie6rcJkdYbppg8ETwMbjZcslcX6EUJzLU
+q/I0BscqbqfiAa8viJ0a1bSWINABKWYr5KqpiRfLWsTJmMthWgh5kaLtMZS3m/AM
+IrrKJJY2klvyO6TeXkHuZwm1day4NxhInxZl5H8NNbLgHz+W/8g6vgo2Oafy0crA
+hS7iK0oJZMgK25p7VDbi8BXf9kqZeq17Vcj9uB8JxC4oTjy6XT9HGTAJ3yJ0TtLP
+p8dayJt6fbNgcuHKkiZJAJfg6ecl2jXxYW7aO9oqcIA3btsl1TJbnzpMK8zeQK1H
+Aw7ryQ8qdhKboZUe09iwcyjxyzxieymS387/O6Stnu3UXoPnig9exx8zOgkcZfFa
+yhrtEbS74lwcyWwnSmjq/tUw1+QbzoTEJDeMyFnZjOJT5GbauFadF7o/GSbCurWb
+yh2G/s5S6v+xa7zw7xdO8ECEUKXws4IiGSui3raZWt+B57uBFQqUefDV6H6MevPk
+8aMTC3f9fhp28lbbjfZBI3JiwtaVSV11kJfwmzOcj198nmZlRHotMQIDAQABMA0G
+CSqGSIb3DQEBCwUAA4ICAQC51hH6cZrn+n8LiHlDaT/JFys3kKOQ4OpdpCUyUYzI
+VYFnG/espH8LKzAiui4/LQjwygTkmNdp12GzIUsZItvpia2J4hsi7xNm/uKOhHwG
+B1FViDF8FKOEihyMsZVAHIBj54RjuQ+WLbuQCjajX4PrK2La6lhWMn4cyvFWXCYB
+A28Vrz/jXgXCXEct4+b2gZApOJ2H8qAyJv8JtFOptbB5mUZz3u3PW8/bTwG901/L
+P9rWLq4AXT+UyPwBNs/lG4XXGc5uBfQjHkvamNKQP3usZuxAygdOEz6vJh9i0nyX
+2b/+F/GLi8ZZwllapmp8c3WdsJkycBJ22VLS/LFNNvkz4sbT1dw5w1A7XJhiVDDZ
+Dt9HMqK5qb4GAbaWwS+HPC63vrP6Ltw4QiAhC5x3bRujJ9CscRTVHXxMNw9b1TkQ
+8AGgEFZKtbhirmv2/MQv+T57LQgnFPWNJWwv3YjJOIzDLEOeOxHMFV3Po5R5B2eP
+qhLqmwYS6tQ/ih5BnlbZPBrArdVvsVCWLjQRy9qgetBlh+c65cL4HUAe/BxpXQSK
+OoNpTQYMpSXlERwqm2/LN8rJl3XFlGtSH2xHucX8V3eN1bPURegkfplgPI+HDZDp
+LAhXzHSQgW+cvcEL9Jafm5e5kRqDei4VSJteBfo+X/eTp0WnGJOYv0uJqwUJheNe
+IQ==
+-----END CERTIFICATE-----]],
+ key = [[-----BEGIN RSA PRIVATE KEY-----
+MIIJKAIBAAKCAgEAw3dyGURoHS9+EWNTIgBNiLZyTW2Rj0A/VxN9g/yNXAwgF4yP
+zEK754kiYZ53P/Bdsu/7cydhmSJNAvBc+zEVg1xwgbfW8jh1NCYaaY/3EclqpSOx
+q78mckAIsjof/e2TedscF6ohQ0VwneNzyID4Ynuq3CZHWG6aYPBE8DG42XLJXF+h
+FCcy1KvyNAbHKm6n4gGvL4idGtW0liDQASlmK+SqqYkXy1rEyZjLYVoIeZGi7TGU
+t5vwDCK6yiSWNpJb8juk3l5B7mcJtXWsuDcYSJ8WZeR/DTWy4B8/lv/IOr4KNjmn
+8tHKwIUu4itKCWTICtuae1Q24vAV3/ZKmXqte1XI/bgfCcQuKE48ul0/RxkwCd8i
+dE7Sz6fHWsiben2zYHLhypImSQCX4OnnJdo18WFu2jvaKnCAN27bJdUyW586TCvM
+3kCtRwMO68kPKnYSm6GVHtPYsHMo8cs8Ynspkt/O/zukrZ7t1F6D54oPXscfMzoJ
+HGXxWsoa7RG0u+JcHMlsJ0po6v7VMNfkG86ExCQ3jMhZ2YziU+Rm2rhWnRe6Pxkm
+wrq1m8odhv7OUur/sWu88O8XTvBAhFCl8LOCIhkrot62mVrfgee7gRUKlHnw1eh+
+jHrz5PGjEwt3/X4advJW2432QSNyYsLWlUlddZCX8JsznI9ffJ5mZUR6LTECAwEA
+AQKCAgEAlp18ctHOM+b7imRxk3qOQ/DpxJXQGoTUCcG/7qr1Nd81/09VInytk6yM
+rJHRq5gIazAWHlZTEw9mLgSOcRQSUqUxIBNLcltknGlb4smHBNKh9Vu6tO9WraR/
+zu2Q5zZgc/4M+IMknFRugYrZFb+jJSfLsVVhllerZ1TcmgSGPi//zsj1MrU9qrhP
+qh0q7JxVioXnuoXXIO1Y+HGSNcLzspDBnF9B0XVAu2KcHIimjR5WX9Tbllt3LbK5
+Ibftc2F1rgKdeKdCwHPu/D8PduclNBg5xwu5hrFBAwexFSZE4Fa9QalNq4JSa+R0
+Ctx2cSSSLCOpNqzemiGLiYabVwY7k7tsYjgO/+t9wRYEIZ3SNm2sydK1+6Hebu2Q
+Ibagh78ysEW+3kM2Tto8njUgoYB4i8VJENfTyVVLLYOIbdRifZGCxXkkBjyF9H0L
+S3mfytKHH8Bjd0jpf0U6QiaY/5XXBljQ2yQFAk2Nk03eP3mncJoaiNhHeq9WiNir
+NL+uJo/F9FAxG3q4W1j0EwWszZdAhHZYRELuV7EX1tXgLM6tOPKa28i9MFVxK172
+hyiSQqWLhtvoU3exf5WZ4gWHPk6b7QKhyaeRjUkcClXIkbYSOL2FnrZRVDC4UHYD
+rEqpBzIGFF6tfchQ5r2/IbSvRldMW+btaehHK1K46onYFhmu61ECggEBAOzBBbxu
+92OQQO7G4KcRflJZ4gRve2BOHsqsDS90jfY42tESJEp04LfN5iBxr2PRIz/l0pbX
+14vHSxuaqZqAKcxn/cDIXbhMCPTvzCmF1y6pbG2hh+ki5531rZqUN3RKamRMPS4+
+9xbRo6wynIWMC0EX66Odw0cZKxW89U1avLR6Izy19aCO+/nMZ+qZztle5xprj1rG
+4eYyYfY4/R/ZdvHdcfR3Rp7MiCBxeQZo1nyLXgqoGvsppntKAD8p49VNrqqA92hO
+uCJ4+sUAU9VPzxk8SOACi56lSm3BkvnErIbG0b9WM5Kj5O01HoX3N4n6s7fefZ6X
+uCc3/3ZW43ZfUHUCggEBANNbNc1l3axheTnZbPPrhp8bQ67MjQZqSQ1pqNf/CoA8
+vmrZEDml2UnuqijI6DWWEtPP2+VoWt4CA8xLX11x+w27Ov9ho/CUnuvg+ufn6w4t
+czyiYmQK2nIBJfZAYuCYN0VOwZoOseu1mfIBvLHLwGgWe6lWMuC3wFgHDPz1AgYH
+jH7uUGKNCRXBkzUqSTS6VSX/056fY6xEGU0EgDfKLjlucDkdhqukDDHjOCCCLtCT
+tApc+LVnB0OyMojxnaArW7rgSEmz5CWm9TGCS6WdZ6aZtlgUNbGVp8znrabM3JuV
+k3ZtJ4TTb+nS32NPEgnFTOdvKbR4jOJTZMn/51iz0k0CggEANAGCfQ3zEc/SM6FE
+H+7bzMMpvseuVk1Svjpk+xOjS37ZsitGBYT/B+EWt/HBETATiim1xKTNGEtC2GF0
++BdHFzuQphRdYepx3Tv/oO9hgUJ+Kubcr/2W2z/oTphYRhdCn52PouT56e1LArxr
+XXqRzk6u2FYDW07QBApp6AASi6J4sxFVT1uZRhn8ibAXm/AY29jcuJgPbz2J/0gt
+ch2W3zJBoe3BeYh8LoQ+jYXh96G1mqmqo5lWlKaAv184SNazk4iY0DTahdgFXdjg
+kW7ikyyG5Y4plUPBwbJP0sW9EC4ETP9mfMO7uc99UPgpHwoPCEi7V2cEcLkASMJ1
+XL87MQKCAQAP8pTnr6T/SceM3uQCr6XTwYnk2ZhWgJSMh4lu6taPAIZZp5E62FHB
+61k5hJdI288F3mw4LhyVHc/NjW5fracEzTjRZjupfn1TTQGBmBU7V6CXVaVY6Ry8
+d2u23frX+YRKHXwsNKmmIGjCQvFK9RXKhM/F4jQqkpLX0YhgWdhSPiWSukakeQHT
+e2yxGUS2zsx39oqwMFSj/etuzUUjcIT2XmfnV1v+/XzSEtP8V/ZSVKLEGWnGvkRl
+DkAT5y8+k6bzPdMWhJVVZfigSLWOhIb6oiSJFtVKVgF4S47lxBVtQ+cBi5Dsy8to
++DlU0/WHeTSpTdD2xhXTSfmT6FQ7dC4NAoIBAF+V7Ntyb2mSHhJkSA4Sw/pKdz+I
+qL4jTdwm9Vjh9Vi4Gqcy1AoE/nzxIj0c+qaZzp+3L3ssAApKOS+BY3Y7Iqr82+X2
+1P3oTnJYZjG8mxyxeMguT824CjgWZvkd6Q0jSz8H4nLaeYlpG2jIov10voBJd5Zw
+NqY0sKkTzDVvl/l1k+Dp+hxUzAFfxIgU3x3qs/fPw9ahoI0oBH/+Xmg6vGg9T+te
+N7D4w5wpK/SHbjZBvSNp5kNlnqfDPjmfAwlGW1J6CBDcWWaEHWIcc4n3l2bCg3At
+LTLKB76sourXcEDVvZA6xrYv9GJukUqmc5SlHhJZQOhu48ITKXH18U7iuy8=
+-----END RSA PRIVATE KEY-----]],
+
+ key_encrypted = {
+ -- openssl pkcs8 -v1 PBE-SHA1-3DES -topk8 -in 1.crt -passout pass:foobar
+ standard = [[-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIIJajAcBgoqhkiG9w0BDAEDMA4ECG8hq5qM1tTYAgIIAASCCUh/UgGOrRj5QQT6
+O1SyC87rmUohZPwutRqyPamsCiMH8PT8dfUrQfv4zjxWe/laxQIMxmdH1+o4bSTG
+HbnexX0QO+ZNVmEuq1AxBtK1VU1SQJ3smPun9foTb83haIDFcFdKtrDup0cr9tri
+HCEnVelGlYdUXwz8HDH54IApdeF/z4U5W0IFON+T1zqDtWkfuBdz8ZGTLjoTdNmy
+loI7s0ydi8m4BONkSACTkuHH78vdC9yf1u1nAcVKYHy6jVjdVNT8lCrSKT4L4HGJ
+WLLROFQimvT0QxJCH2T2jPPEPZa1MNLowilzctNt/8XkJNnh51Jb7AFDLzwTh+oB
+eA/93IS6ShejqBo08XdVf2XRM837zufOYktqXjBvF6XGCHuL++vcD+mvJI5omVJQ
+KpeCwPSjJ0xpup9edmTsPlmeCPzqYtgOWHqzaiH3lb6f6IC1MieJX88UxJol0sCs
+mNesymP0IYcEMEtwwTIU7Hwig4vUsd93M0sSRZVc/qHe5lM8rT0tjWkl9hyQxPUA
+VvDOXInuLmTJB/2nyz2r5/2uioVJ6o4yYML7mVo7IW/UJTyFQwYRnyYNbvNJ5k+0
+vZEob1FIF91o1Uiv9cmJj4cCudIEcki8XpdFK5Zviyrw2gMXGrdinS72f8WptDOX
+dbioJfWl5FIdEUZoRUkiBZfS2Zzy5hdWiyVm4zTSXvzPDa0a+GpbZrXPbAmwq+vq
+e/HOZWicZu3rVyNLU1dytuLHQ9LB6nbSATcSQOCJqe+fVKUkYkv8O3F1FOmOebOy
+v3sY9TmFAZYQtNd4D8ObP6qDMvCMMAD+/JGcpOdo48rQI2CWnwu4LfSqbFN1eCJu
+6E9oKITDZTfbCDKZDCJgWyquJqLLPJADcuB08Gl9w+Gao0E/1ED5kUlplE+ak+8R
+1yGLY6Jcdn2v0NoOVPEGTvhfnoKSrL6B6+Q9zuK0w7upcM3HjlXpDqnSeUf+neSq
+MftvIkvxZ3rXLhj4qs2PuvjPfVuceYBxndLcX+nDICt8nbsrYcYg2dpDGHwOuTkA
++b6k050NTBtYblv4xY8aspCpaSPyne3VDOFkxXvmu3EpxiVFJxCu3l6aDT/NpoU8
+UG+xDI03o/bOdyvc7J6bgXKSjr97u24eATuin9ifCPkAmQ8IdHsFupNZyC0WEKvS
+YSGG40aZ84to4GfbYfvT9MojE6Ejc5PCOpAvhh4LJJX5KF7gCb66B8Nno54k5qwU
+0niCIwoytq1SedHWvxsbVhSiAMnRkmLzuZZ/6KR8iDnSy0bhOkXw+9zJDyxPGcsJ
+q6u4GVe8ogpcT0f2sOfRPsVxAA7cIxDEUuIQbEXAb+3ROEE689wHTkDxkKxShDSj
+pw8xSH3TSf9hMbFjhTX8mIVSrSlo5sWcSalCGLGE+3jaG/o6vqsHFGsh7KVagWmh
+Ad+UzeCvC6NDX9h4KZyPNjcUganFNCWJZ6HHqkTUqLY3/qupwJN1wOe/62bU652+
+4r1JY2GQJQHjI1sFU/cJ61ylxSVSzUpQjFUxOJ4gTGhhjPAGzEpmvDFXIbDiW4cS
+3CRpottd3tTzc3RGSDck7aVKl7R38fuWzsFdDug7+Duac/jafqhVp7wL11643ztP
+/zskQnMwOQPtXb2Gopw0vSMHIcqXF/TTARddqYahICpygys60WslN4FfnRgoz+se
+X6ot2SZM25Z6EhHhYaNVLTWQuEzU+iXMqgVOZ+KIui2ue+DgCFBPdk9Gp4Q5kbWo
+mUw+/6kjoTCzbJBX/KLyCG4MDoTgpnxOznWfWxKvtTEKIokKRQYpJuXdl1pgEp1p
+DTE+lVmhl2dWYEMkbWv5omJine4QbOjt21lL2WZjsMiqy0kAjOIh7tz39zOrN43W
+RqviyRe0FvT8tGLba2EaGkYfWLuiKVNTSWOrdSNus4cK+Q78THZL+d/agJgXrLHw
+/COY6yKmOmjYEXkQl7Fb2JJrygO+PLdARzk27RwZtIhfJyD01ZabVuasMce8BhNh
+bU4ulJPu0bJ0xzDfo0ikHpVCGF6W0tl+zl3aILT02coJ11GpBi8Se69PlwdctHMS
+ZbGaaetCK1xXstzdcs9cELI8FQ1LS/n82KqZtnTXKy8g1O2JXoK+9xFiERftpiCi
+P3Fb8KYcMcKHisWCB8BfJ3Qodb125u0YkezqJgpqvtClRT862qb8kvamMoB8NzGT
+OZa8uwgwoqt4S32ewenaSLwzuvOziEkVLedfWgbKeAHxuiZhLi5S9qt3hFGORQTi
+KUtVlSM7v42IP8RuD3GKrZ1uV3x6RY2vTkGuT45n9UDn++Q2RFdrpuI/w7xYNzMA
+FZxVrpoZeMHiXl195fFYXgUffyY2ibLJiUb2+ItecFGSzLDL5pxo3oKqKpIZuJEL
+QGp+MMpoKcxPUGfv78NTG7hCmpLf99k52i0kYQJBcLGSmnLTM6X3nIl7PEUHTUFU
+VlLALjf5aPZcFOAidhHm+feOTNOPMm5MMInf1k2ibPzxQBOZxnf4Ux57/x/lL7PN
+XG0CDDHbiEJ117pd8tpVHbkY/FnqaqjV/VZHnpg7r69+iTH6ipnokUnv3TmTywsG
+0FlytnqlSc+qi9zpg3igwzpkJ2G3HityojgHH2eNNDAOyYqW788DdIC8X3FTnxcH
+iAuXslNWNOkjabn/vCGUHNj5zyfKydIeOsMfaG2H7rSYBRl4XsQCbnx7QtofO/WR
+n85YNSfvSwBHpAg6UPAB772mf43dSJnptWwar4uH/xqaAqeH/hgmMQyzl399HYfw
+5ug95OGRv8a1NuDHoVAI7UozOnY5OqQ2N+OEl993OiZJoFuX9SqIeM9Y67TWs40/
+/GmQfIaq4hVzSGuPavRmkhymOOjxcm0LFVatEXBe/iyGpwB4WiGarSFxeIeGrHTT
+3xi+D0OMdwyG5XHQQy2LJnmhFBOU53+CPQ0ecJrLPbHdzqgEmz2d3mRwZFvBSi56
+srwdhdiFQcEdIh+CessZXIGa1ZHKFphOd93fF7bfCQk0Z9+K+kwWIfUz72hu/Dr4
+xTcKT5qkvIHl7shuWK8QC8EpDubvViM14YGns6EtR4JttY1BLZxHyndEe0p9XlJQ
+s29ceQZQEs5DYKLB9YefjxANOh8EZTmJ+BKfA/xvanySnHNRi3NojxjdbJiPKBsd
+sSy16GdFKZJctce6KPU=
+-----END ENCRYPTED PRIVATE KEY-----]],
+ --openssl rsa -aes256 -in 1.crt -passout pass:foobar
+ legacy = [[-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: AES-256-CBC,1D2DCF88CB6CDBE43D63D794511BABA6
+
+qaDyxn/sXGGouYjFTEu3vlq1lshJPR0mvBhVbuSPA04fkGFXOSg0Gykg4WFyEb84
+fuWhG7WPzNeWRsBEJQavn6R2faM4Axhe6xov4hY7u7++axCTUUe+25b9lNSsKHUL
+MakYwwUPbMFzcbEIQzyAgBqH0Uorvd9Fp8co1yYMZiVtOHI/vlTNwYXX0T8/bWxN
+62X85R3G0aFj+WkQUh4irahG+J6cg/EwKfz4TvEjVrO0sz544qd6iZDoct5juHuW
++rNSrpc3LRxmFTDn9IgjO6JvwK+ik5Hc1X3NMTPhfbnFPRiPuaAaxOX9dLYo1DOf
+ZlgwQH6gsZDfIDnxkNtyOOzgdtdnCpy8E/3robL3iZ7gqlNeLpX75D7OQR6jJe6O
+EmCjWYPtmp4Bcs71BpJGwDZOplpDEaxgJRnYE+Er3IgQ0o6eb2zpeDt6RSCk/FTu
+j045Mjrd/kf8jofLdzUNt/6ZvjliRV/FYl7I8lfLrycLev9aG52m81f7qenUCmMA
+GgaotKQK+X04ohq0Di0hKfglP5vW1aw5Z7I0qOKPC1Wr1S+7UNCWUrFZ7nXf6nAn
+SiwcaOoKWm8CikaVtWoPqD28OC6Kb3R5pIXTa7VBM4nIf9+Am/3M74wneZkUG00t
+tbVk5Rh+a/46SlBsVLaZ/A7/mChW7pobKlbnIob7xvDlWbjVe7iDH7jBZfTn6mmh
+mBdrpPO2LZ5wrWNr6m7AxhU9WqufVQqyaLQ8qPG6C6j3l7I4nTamwfde1/gXGeiO
+/BAhXvW/onOvLhGsTIj/rXjk/unix+UtbH7GxEb8RSupOn733f5qGoGPLocMtFud
+/WsUuHK0fBOs6LjuDEgL7Rrcm+U2N5wwEKbqNxhMuT4Di5gSPwRYbEFLMCqENlJ5
+6CsLdkDc1f4GWNsdguoZOBtYT5zuaD7xbl8Z3M7ZxI8JEJzhC0IhhFJX8CvumyeG
+rxVrcEVgQ1B22iZfDa1mwZBPdeJ3Ncknx6+RwpIFlfr8wQIABbVIIKa1SkHCxlib
+OxqrKO6WzH1x1KLRgUbiC3Ql+kzdXVqqc/2vg0imY1xRz+rWq/fxro5dweAlz2y9
++1ZIy58PsVFOYJ2VqP4v7Z2ydpIlP//ZJe+y2xypxMgxQ/kG41Oyerw+bB2wNNS+
+jkANfMnwHQMwQEGvCZJUGnP80utija5nDmCb5Js6G3qzkibnuN/iyvg0VPAVMB0p
+4vbQGUe+Y5tuBY1WqtYw9p+b5kGCFu+rLaHweqDcROGKRdWn99CiU//SNT5wmT50
+WCdv8YzTFWvmE0Nv9oAP00cjjsLGyhQNbj4lhfKEyKSmModfIJ5wUOEcEZUZEBj7
+8USqRpPQR2Ih5Z9e92pmi/OlmzEKuARZ6f2YMpFyuDei6IvPQD0BKV5Ca4Uvm8gh
+wLCb84Gw2N4NoziOjyDVOuGWhffpWIRFJ6wupnY8hly6t4rg/4NRKOBmnDl4SU1c
+I/qj+00Ow43blYFyGwvtuCt7GnquNJR1bPUnv32S0tMK6RS45wTVH/85MpmmF70Z
+ikh+LyRO0C/31EBWAc/KQms3KfUrXxkbvwfMrqnYL3M+Co8H+t95Fax96wAF0cd0
+JoOzSomL5HPRwbiLbXMufo5DKkfhdCNe+a6YRkxP9wmR2H1/H0c1Yjj1acnq8p11
+MxfJ2vHk1yV9MLXHsRgs3nCEqmqnJs/I5LeGEYn2Tw2A7jt7tpDkc96gEINeCCX6
+2V2BEiBWBOfWaKQzg2iALQzsPXMDgveKeaT3dAuANNJyrR80oRl8Q+HVL3REcucH
+i8A6UCuD2WmZKU6oWW3cY1ropRbNUXJLQ3w6WfPkrVDNbd+/iXbFyT5Q+losWEJk
+6fPV/vIm5MPtnfNsCEjDgwbF9WtBw6+UCAbBqKWLoPSCIshduSWmGnzgvJFMaEMO
+/6zb5p7qroN5OgpeHX07/xnUi0H+hxArAPmGovPktoDZXdBkVNxmT9a80hJphupE
+fNW9/GtvNTTXsPs9HVp3CogKWoa7hnbzQbYIOtx6NoghZr4oCS46cr+iPgT/v9Km
+sFmkTjrljtp8J9+Ywqm406gClhpMDRjj3D0z5H6nMZW6Z/aA7oECCDOos+CdRE9F
+guaNEgG8d6NrmzQVs1+mW0HTUim1UuxjC1Yn0LXZ+SkYfKx16tvbV+eil0O9xxX0
+dM9gq/cJpmMGl22Epy5TpbpPqUliqRQMkkdZzax+1AAgAU1X5S5KnJqZaAZ/tJnU
+Icv/halkNyY5e1VqXMY/pMWtVbkA9zHCPAEAkJ0LV4Y+HotIjri8maGPVa7F9nZn
+hto9G6UYfJ33Fe/+5xUPm6hBn3Z28eqephnnDLJfLIARl3t0/4VHka86L+nvZ/ka
+/luhMCRXlyzzYI6ItDShpNe0xXfd5L3GijXmblgrlaAVg7MUMNcH5f4+MEiKkBqu
+3KJaoQ+MbbWOgPtW2WzQTgXImD+h9JMxStcXym29sv98SziCpLgEwy2D85yLaSqz
+X9N5oo6rlij/eHfpiMKfIwLGryFwVylO1JuPYOievxZWgT3t2dRpHEisgdI0jjmk
+ZvgnuOq5gw7+yjGB/1slA2D3A+pztu9yfX3xOf1oTOyF3ntoFvoZtQGWHvzqxaNf
+lJ3NFOV7HHJqJ897YtdMRjMgL/mv4Wgzw8YQpzsom3u0cufUDeqDMAMXNMNEN0nL
+D9gQDTFKyy0Y3kfULmjUwHo4r0mwYMSocM4/cajJzQs68Qpy1yFLVVryjBfP6l45
+aqjwGyZFOgbdz3BdVuYq9uU3PHiV/Xi+9oaNzbhPKwiwe+tpaNM4NdJ7EdbVb3i5
+/CtEyKK147HdOAYGcbqDYFU7hcdLbA95tRX8zkz5NG684b1i5SCSbln+4iwZXWBZ
+loKPqZHrVD4qqSBFHBfvdaiUtNZIZH2bwUO5qt5goYD3egSrizNtNgzJ7nKl4PD1
+y7tnTMtP11OKqgrnls9s0LcuMNtv5Euq1o+U+vnMet6AZkC7+6g6UqPhoY6UTtB9
+X7w/9lDdh4lb64T24N6JxYlDo41gZ6r+4AA3bkr2LCDDx0mRpZzhZljXKhZvdRed
+tGJP909NhlRM6C3t8qZkFDiFvGBI+wK4Bf5bdazt/n3i4powjlgUEorwB1fDBYSK
+-----END RSA PRIVATE KEY-----]],
+ },
+ key_passphrase = "foobar",
+
+ -- Issuer: C = US, ST = California, O = Kong Testing, CN = Kong Testing Intermidiate CA
+ -- Validity
+ -- Not Before: May 2 20:03:11 2019 GMT
+ -- Not After : Apr 28 20:03:11 2029 GMT
+ -- Subject: C = US, ST = California, O = Kong Testing, CN = foo@example.com
+ -- X509v3 Key Usage: critical
+ -- Digital Signature, Non Repudiation, Key Encipherment
+ -- X509v3 Extended Key Usage:
+ -- TLS Web Client Authentication, E-mail Protection
+ -- X509v3 Subject Alternative Name:
+ -- email:foo@example.com, email:bar@example.com
+ -- Issuer: C = US, ST = California, O = Kong Testing, CN = Kong Testing Intermidiate CA
+ -- Validity
+ -- Not Before: May 2 20:03:11 2019 GMT
+ -- Not After : Apr 28 20:03:11 2029 GMT
+ -- Subject: C = US, ST = California, O = Kong Testing, CN = foo@example.com
+ -- X509v3 Key Usage: critical
+ -- Digital Signature, Non Repudiation, Key Encipherment
+ -- X509v3 Extended Key Usage:
+ -- TLS Web Client Authentication, E-mail Protection
+ -- X509v3 Subject Alternative Name:
+ -- email:foo@example.com, email:bar@example.com
+ --[[
+ Signature Algorithm: ecdsa-with-SHA256
+ Issuer: C = US, ST = California, L = San Francisco, O = Kong, OU = Core, CN = ssl-example.com
+ Validity
+ Not Before: Nov 18 16:17:30 2020 GMT
+ Not After : Sep 3 16:17:30 2294 GMT
+ --]]
+ cert_ecdsa = [[-----BEGIN CERTIFICATE-----
+MIICPDCCAeGgAwIBAgIUOIK1sCtPyUL5h7vHdxpN5PhpukMwCgYIKoZIzj0EAwIw
+cjELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExFjAUBgNVBAcMDVNh
+biBGcmFuY2lzY28xDTALBgNVBAoMBEtvbmcxDTALBgNVBAsMBENvcmUxGDAWBgNV
+BAMMD3NzbC1leGFtcGxlLmNvbTAgFw0yMDExMTgxNjE3MzBaGA8yMjk0MDkwMzE2
+MTczMFowcjELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExFjAUBgNV
+BAcMDVNhbiBGcmFuY2lzY28xDTALBgNVBAoMBEtvbmcxDTALBgNVBAsMBENvcmUx
+GDAWBgNVBAMMD3NzbC1leGFtcGxlLmNvbTBZMBMGByqGSM49AgEGCCqGSM49AwEH
+A0IABDFm7D+CfVzbkRyRTR/2DI4o1sOxDCdc1UEdbQkA5e6j5b4smyuW4xlZjVwV
+CXeADYvtpBaykzZ+NC5Zlf3EAkWjUzBRMB0GA1UdDgQWBBQcXSBVifOMnYaC632X
+NzdazHkuEjAfBgNVHSMEGDAWgBQcXSBVifOMnYaC632XNzdazHkuEjAPBgNVHRMB
+Af8EBTADAQH/MAoGCCqGSM49BAMCA0kAMEYCIQDbSwXZ15UJ0hX/7KTKxd/mER7b
+s5oBurNijw1iPMyi+wIhALixa/LN3i+AykB4Jxj89scpXilIH+6q5fJI9exuaLtv
+-----END CERTIFICATE-----]],
+ key_ecdsa = [[-----BEGIN EC PRIVATE KEY-----
+MHcCAQEEIDCpckzH9Z6YpE48cmSIqcNXDZ29peoeMkFP2NqZb/MUoAoGCCqGSM49
+AwEHoUQDQgAEMWbsP4J9XNuRHJFNH/YMjijWw7EMJ1zVQR1tCQDl7qPlviybK5bj
+GVmNXBUJd4ANi+2kFrKTNn40LlmV/cQCRQ==
+-----END EC PRIVATE KEY-----]],
+
+ --[[
+ Issuer: C = US, ST = California, O = Kong Testing, CN = Kong Testing Intermidiate CA
+ Validity
+ Not Before: May 2 20:03:11 2019 GMT
+ Not After : Apr 28 20:03:11 2029 GMT
+ Subject: C = US, ST = California, O = Kong Testing, CN = foo@example.com
+ X509v3 Key Usage: critical
+ Digital Signature, Non Repudiation, Key Encipherment
+ X509v3 Extended Key Usage:
+ TLS Web Client Authentication, E-mail Protection
+ X509v3 Subject Alternative Name:
+ email:foo@example.com, email:bar@example.com
+ --]]
+ cert_client = [[-----BEGIN CERTIFICATE-----
+MIIFIjCCAwqgAwIBAgICIAEwDQYJKoZIhvcNAQELBQAwYDELMAkGA1UEBhMCVVMx
+EzARBgNVBAgMCkNhbGlmb3JuaWExFTATBgNVBAoMDEtvbmcgVGVzdGluZzElMCMG
+A1UEAwwcS29uZyBUZXN0aW5nIEludGVybWlkaWF0ZSBDQTAeFw0xOTA1MDIyMDAz
+MTFaFw0yOTA0MjgyMDAzMTFaMFMxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxp
+Zm9ybmlhMRUwEwYDVQQKDAxLb25nIFRlc3RpbmcxGDAWBgNVBAMMD2Zvb0BleGFt
+cGxlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJldMxsZHDxA
+RpbSXdIFZiTf8D0dYgsPnsmx5tVjA/zrVBSVBPO9KunaXNm4Z6JWmUwenzFGbzWP
+NLfbLn4khuoczzqSru5XfbyH1HrD0cd5lkf44Dw1/otfIFDBleiR/OWEiAxwS4zi
+xIajNyvLr3gC5dv+F+JuWpW1yVQxybIDQWoI25xpd3+ZkXO+OLkToo+YpuwIDlUj
+6Rkm5kbqoxDpaDihA2bsAqjNG7G+SHthaNyACsQsU/t6BHSWzHumScN0CxJ+TeVH
+fTZklelItZ6YP0B0RQjzvSGA423UgALzqJglGPe8UDjm3BMlg2xhTfnfy1J6Vmbt
+5jx6FOXUARsCAwEAAaOB8jCB7zAJBgNVHRMEAjAAMBEGCWCGSAGG+EIBAQQEAwIF
+oDAzBglghkgBhvhCAQ0EJhYkT3BlblNTTCBHZW5lcmF0ZWQgQ2xpZW50IENlcnRp
+ZmljYXRlMB0GA1UdDgQWBBRTzNOmhGRXaZamxVfnlKXarIOEmDAfBgNVHSMEGDAW
+gBQLDgQOl/htYk8k8DvGb9IKO40RETAOBgNVHQ8BAf8EBAMCBeAwHQYDVR0lBBYw
+FAYIKwYBBQUHAwIGCCsGAQUFBwMEMCsGA1UdEQQkMCKBD2Zvb0BleGFtcGxlLmNv
+bYEPYmFyQGV4YW1wbGUuY29tMA0GCSqGSIb3DQEBCwUAA4ICAQBziDuVjU0I1CwO
+b1Cx2TJpzi3l5FD/ozrMZT6F3EpkJFGZWgXrsXHz/0qKTrsbB2m3/fcyd0lwQ5Lh
+fz8X1HPrwXa3BqZskNu1vOUNiqAYWvQ5gtbpweJ96LzMSYVGLK78NigYTtK+Rgq3
+As5CVfLXDBburrQNGyRTsilCQDNBvIpib0eqg/HJCNDFMPrBzTMPpUutyatfpFH2
+UwTiVBfA14YYDxZaetYWeksy28XH6Uj0ylyz67VHND+gBMmQNLXQHJTIDh8JuIf2
+ec6o4HrtyyuRE3urNQmcPMAokacm4NKw2+og6Rg1VS/pckaSPOlSEmNnKFiXStv+
+AVd77NGriUWDFCmnrFNOPOIS019W0oOk6YMwTUDSa86Ii6skCtBLHmp/cingkTWg
+7KEbdT1uVVPgseC2AFpQ1BWJOjjtyW3GWuxERIhuab9/ckTz6BuIiuK7mfsvPBrn
+BqjZyt9WAx8uaWMS/ZrmIj3fUXefaPtl27jMSsiU5oi2vzFu0xiXJb6Jr7RQxD3O
+XRnycL/chWnp7eVV1TQS+XzZ3ZZQIjckDWX4E+zGo4o9pD1YC0eytbIlSuqYVr/t
+dZmD2gqju3Io9EXPDlRDP2VIX9q1euF9caz1vpLCfV+F8wVPtZe5p6JbNugdgjix
+nDZ2sD2xGXy6/fNG75oHveYo6MREFw==
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIIFmjCCA4KgAwIBAgICEAAwDQYJKoZIhvcNAQELBQAwWDELMAkGA1UEBhMCVVMx
+EzARBgNVBAgMCkNhbGlmb3JuaWExFTATBgNVBAoMDEtvbmcgVGVzdGluZzEdMBsG
+A1UEAwwUS29uZyBUZXN0aW5nIFJvb3QgQ0EwHhcNMTkwNTAyMTk0MDQ4WhcNMjkw
+NDI5MTk0MDQ4WjBgMQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEV
+MBMGA1UECgwMS29uZyBUZXN0aW5nMSUwIwYDVQQDDBxLb25nIFRlc3RpbmcgSW50
+ZXJtaWRpYXRlIENBMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA0dnj
+oHlJmNM94vQnK2FIIQJm9OAVvyMtAAkBKL7Cxt8G062GHDhq6gjQ9enuNQE0l3Vv
+mSAh7N9gNlma6YbRB9VeG54BCuRQwCxveOBiwQvC2qrTzYI34kF/AeflrDOdzuLb
+zj5cLADKXGCbGDtrSPKUwdlkuLs3pRr/YAyIQr7zJtlLz+E0GBYp0GWnLs0FiLSP
+qSBWllC9u8gt2MiKyNlXw+kZ8lofOehCJzfFr6qagVklPw+8IpU6OGmRLFQVwVhp
+zdAJmAGmSo/AGNKGqDdjzC4N2l4uYGH6n2KmY2yxsLBGZgwtLDst3fK4a3Wa5Tj7
+cUwCcGLGtfVTaIXZYbqQ0nGsaYUd/mhx3B3Jk1p3ILZ72nVYowhpj22ipPGal5hp
+ABh1MX3s/B+2ybWyDTtSaspcyhsRQsS6axB3DwLOLRy5Xp/kqEdConCtGCsjgm+U
+FzdupubXK+KIAmTKXDx8OM7Af/K7kLDfFTre40sEB6fwrWwH8yFojeqkA/Uqhn5S
+CzB0o4F3ON0xajsw2dRCziiq7pSe6ALLXetKpBr+xnVbUswH6BANUoDvh9thVPPx
+1trkv+OuoJalkruZaT+38+iV9xwdqxnR7PUawqSyvrEAxjqUo7dDPsEuOpx1DJjO
+XwRJCUjd7Ux913Iks24BqpPhEQz/rZzJLBApRVsCAwEAAaNmMGQwHQYDVR0OBBYE
+FAsOBA6X+G1iTyTwO8Zv0go7jRERMB8GA1UdIwQYMBaAFAdP8giF4QLaR0HEj9N8
+apTFYnD3MBIGA1UdEwEB/wQIMAYBAf8CAQAwDgYDVR0PAQH/BAQDAgGGMA0GCSqG
+SIb3DQEBCwUAA4ICAQAWzIvIVM32iurqM451Amz0HNDG9j84cORnnaRR5opFTr3P
+EqI3QkgCyP6YOs9t0QSbA4ur9WUzd3c9Ktj3qRRgTE+98JBOPO0rv+Kjj48aANDV
+5tcbI9TZ9ap6g0jYr4XNT+KOO7E8QYlpY/wtokudCUDJE9vrsp1on4Bal2gjvCdh
+SU0C1lnj6q6kBdQSYHrcjiEIGJH21ayVoNaBVP/fxyCHz472w1xN220dxUI/GqB6
+pjcuy9cHjJHJKJbrkdt2eDRAFP5cILXc3mzUoGUDHY2JA1gtOHV0p4ix9R9AfI9x
+snBEFiD8oIpcQay8MJH/z3NLEPLoBW+JaAAs89P+jcppea5N9vbiAkrPi687BFTP
+PWPdstyttw6KrvtPQR1+FsVFcGeTjo32/UrckJixdiOEZgHk+deXpp7JoRdcsgzD
++okrsG79/LgS4icLmzNEp0IV36QckEq0+ALKDu6BXvWTkb5DB/FUrovZKJgkYeWj
+GKogyrPIXrYi725Ff306124kLbxiA+6iBbKUtCutQnvut78puC6iP+a2SrfsbUJ4
+qpvBFOY29Mlww88oWNGTA8QeW84Y1EJbRkHavzSsMFB73sxidQW0cHNC5t9RCKAQ
+uibeZgK1Yk7YQKXdvbZvXwrgTcAjCdbppw2L6e0Uy+OGgNjnIps8K460SdaIiA==
+-----END CERTIFICATE-----]],
+ key_client = [[-----BEGIN RSA PRIVATE KEY-----
+MIIEpgIBAAKCAQEAmV0zGxkcPEBGltJd0gVmJN/wPR1iCw+eybHm1WMD/OtUFJUE
+870q6dpc2bhnolaZTB6fMUZvNY80t9sufiSG6hzPOpKu7ld9vIfUesPRx3mWR/jg
+PDX+i18gUMGV6JH85YSIDHBLjOLEhqM3K8uveALl2/4X4m5albXJVDHJsgNBagjb
+nGl3f5mRc744uROij5im7AgOVSPpGSbmRuqjEOloOKEDZuwCqM0bsb5Ie2Fo3IAK
+xCxT+3oEdJbMe6ZJw3QLEn5N5Ud9NmSV6Ui1npg/QHRFCPO9IYDjbdSAAvOomCUY
+97xQOObcEyWDbGFN+d/LUnpWZu3mPHoU5dQBGwIDAQABAoIBAQCLqQzeM3q7/4iI
+1l+r31DKacgbz4M2MW5XnJNqZTX/f8pcx+vvjqfiuADwH/b4JcaKRCSSOeMSMiw+
+9fGb2+WkksHARE3bLH+LTWKYvXRvI/FP73s8Oato/iKuh+vdE/zqgktmkGisjuGK
+/l1Cm8VaE8GBGh5kDDyfsyD5dDGJ0fYzJkfQqygd5B5TSaWflQsB//AXvHzkNy+G
+RHbrMl7t9rDCTtwnefSEJIEwAZerGKV0p+VlRy23mQLwxTxJ5jEjVvcFIMalnD4R
+nKaZYb3LgkCCTQ5Lw/xrkdAEJwfafhdu1CmvKelv1qpcz1vJdrFSfX5NOYS/93jI
+aKJT8Nm5AoGBAMmOOUTvbUd9nlbZXYGLTsoy+qA+OhLkB59krddH4mFoRvbggD6U
+Y/h7O/fA4spqtts+aVoEh/jyuwGTxMn0NPLjD0G8YZr1A4GUx1hgEQ1NIWvRlXrX
+s1bgIlaOc14hOpKf0to3mIovyhRm8PaDbQfHWfyl4yKtFgKiO4OCMK0/AoGBAMLK
+e9C5sedDKt8ESycaXnui1hA4WQkeMdXFflnabuhE29dkC7kDFEVurlmsQb3zFa0V
+dF40niT7xYqzdEJIbaZ3JZIrSFhnPSSBna+B1FjMhTVb/5sjPJS87BvjVYiZd5GY
+5Az4RgSlU3PlsaiuR95NH1vDxHXb5GcMs/EfnEklAoGBAIVFe2yve+yXjUkT9RYh
+TPm596pZOwEeskOcyK3epDuQPcwj6eh3Khs1MRPDALKjGUGi5PpWoKnlpe2HDcoT
+pacsp/vpWgiiFa1q+NzguKW46G5oaJSPZ8/75/ifvHzzL82fzEXqGPzWWKJg5te5
+UzCfikraTXOySyl2qC9uuEz1AoGBAILH8eNMmb48YW9EcbS6Ro9Z38EaI+U0SZ9O
+LqvjNS1q9fMiL6CzCYwoaJS6S5VdvMLtsaiCSV9pTtL182uBN2VZf3co6jS4c9ur
+zpQEZe6Mui7+KpodSVJPmXKL6mSBLT8q2IpAsrnxyhr5L5OiF4yQWSqCQMgkr6/k
+XnfYklSlAoGBAKBePjIdBGLy3ckdlTfbuTeO3kp2eZFBDtGzxP515+LcoRfOjd8T
+ZDX/porUMcgbtIF/B4SNso+8D/aHTCg3QAo6nDjFFjUBHhftgy+GP3BFfMvjqou6
+utJFRkc3FvrrkkeWHnyDQrPmAHjar94/xq1k1Vo+KQHQVQOrvtQt6KXK
+-----END RSA PRIVATE KEY-----]],
+
+ --[[
+ Issuer: C = US, ST = California, O = Kong Testing, CN = Kong Testing Root CA
+ Validity
+ Not Before: Apr 13 23:48:41 2020 GMT
+ Not After : Apr 11 23:48:41 2030 GMT
+ Subject: C = US, ST = CA, O = Kong Testing, CN = example2.com
+ --]]
+ cert_client2 = [[-----BEGIN CERTIFICATE-----
+MIIEJzCCAg8CFAQ6oTnLBUHbumx1bxyY9kV0W21BMA0GCSqGSIb3DQEBCwUAMFgx
+CzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRUwEwYDVQQKDAxLb25n
+IFRlc3RpbmcxHTAbBgNVBAMMFEtvbmcgVGVzdGluZyBSb290IENBMB4XDTIwMDQx
+MzIzNDg0MVoXDTMwMDQxMTIzNDg0MVowSDELMAkGA1UEBhMCVVMxCzAJBgNVBAgM
+AkNBMRUwEwYDVQQKDAxLb25nIFRlc3RpbmcxFTATBgNVBAMMDGV4YW1wbGUyLmNv
+bTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAK+kZhxdN8PA3SW9cXiv
+xgtANq57PIWNnSDsg9Yxn0/+JKR45pSU+SKYtZUJJJuOdkv4IIJLm6uG6LbOPUDO
+g9EaV0Zw7RQtbY6EDFDFzeyq0/Mwl9wLJtXf0fPsXGyFIdeelBjzoSVsGGJKPWbP
+rlUtSHCrpFX53NTPnNVUJz9V6CdzZJgbyoiWP7ggKJeRPq6jCW5pt+cd+sR4+EPh
+daBmEVWeifLEKCbBvsQaOGfU1aVG1AlX0RpLBkTxOOFIIk/3dgWOsrek2ofjku4F
+g0MeWmD8oXOHUX2JxO77/BbLDQt0lzD27y/EkDoqy6mMAH85/LTYrU+P0WsEyexg
+CHcCAwEAATANBgkqhkiG9w0BAQsFAAOCAgEAwWAxQjQOoGxU5LQu4ZmsCkps9y0B
+kNj8MUpLcFmK+02VIUh3hM4vuB6Gct2Ph+6zqCge3oqTXltU0Bs2MTwAKs/scsxq
+Mtanz4W00UlmG3QdgHaEs196tYQ8cKIaGZsNBv15VgBBduUG478pKqYE8bJKBbw7
+1Ym390hSPo0dNe7jLFXx6AaJvlEYh09P4FgfkXuY5VVTGXfN7XgJI073pLRY6iGH
+Qd+Egymh86AQtnoNpmqSCMNcjRVAyR8Ti3qnyro8ruZCnNYHieGeh/ZsZvhGDeWX
+v4YXjW2NDQ5+Ok6Gtvhf/l6RSrnXLbZtv8NStqwQJ+ydu05BJglZ/7Sb0uQYVNq2
+H8V+MtApFT6fG6ANM6hadNFG+p8Hwz6k4BLrc9ZxeWYKWIIusqExR9JIlGzEjvFJ
+6NmNjm3eZE9Ue4YgURj1KTr53wAso4LbJpz/zuZS+m9PMz7n8fRL25/Z5b/92L3a
+w0vsxUJyTDeMvYf8oT6OkxNVJ0zBRZNtEg5AJKdP6nU53V998jHP9vUisrU2ALhu
+Jw3QiWiDKnRtx8PiiRx7dWo+Xwn9+xVypytqNz3w/XJlOjMwOg73q399w+vMiFTl
+qdr7eYvaQBGOZVc3OdiP8afyVxlhHBowUoi8G+iPbgOsARHv/j4UeMVyIThzxv73
+a2EQ5BzyOzQ81H4=
+-----END CERTIFICATE-----]],
+ key_client2 = [[-----BEGIN RSA PRIVATE KEY-----
+MIIEpAIBAAKCAQEAr6RmHF03w8DdJb1xeK/GC0A2rns8hY2dIOyD1jGfT/4kpHjm
+lJT5Ipi1lQkkm452S/gggkubq4bots49QM6D0RpXRnDtFC1tjoQMUMXN7KrT8zCX
+3Asm1d/R8+xcbIUh156UGPOhJWwYYko9Zs+uVS1IcKukVfnc1M+c1VQnP1XoJ3Nk
+mBvKiJY/uCAol5E+rqMJbmm35x36xHj4Q+F1oGYRVZ6J8sQoJsG+xBo4Z9TVpUbU
+CVfRGksGRPE44UgiT/d2BY6yt6Tah+OS7gWDQx5aYPyhc4dRfYnE7vv8FssNC3SX
+MPbvL8SQOirLqYwAfzn8tNitT4/RawTJ7GAIdwIDAQABAoIBAHMJzgdN1rRToYSS
+a7uMBL5htG7bMGyYsA1cW4zyu1F9NyqyNPOkDvjl5ChU8LEhwcFIJqKwOqlBlzIE
+KoJDwHo4MmlklSLeDh+FxTsyEwmraV6iuRPaCfmSusR0TqSVHfFHX+Bn0WfdQKs/
+zK+F3rzTB9sj0GKvYD/SKvpeP8Zuu9EBqo4N7PU3VHwDq5t32Ut/+M5XWtulsQcs
+qXr2R3agj/DnODANT6Dn/mJboTrYOSV18S/Yw/+OnWBcLzlT5sj0aLgrtXvIputv
+9caux4HklAQr29+lKB8nBTfjhXnBntMaEgqCVJ3ri83MuEfVDhmjwo6PnX22/J0h
+2XbCyUECgYEA2v8m+CTBTjdAqOuje34+UiWRzT2P9OFONV8nYgzEcQW5JkUoFCun
+KgQQIvjCsX4jY6/8w/IPF1ieTconZYJUWSyMZFtBBDCVif1GZRiiM2C4Zcero1KV
+U0V3wZcnYkzafzIHkqFUYZwamvdKWVI4c6F5MhSEKCgcbgKKI52TEokCgYEAzVHr
+KjQt+dqNkbipYoGH2ywLdcogDwKoyUFbgcvz/q625gu4am025wF25yRKExm7Dyjx
+eCQC+KOsBfJSc78fG5R6KPIDK1JrpUEGSCeqFICiqGv9kUzPf5zeGZVf9cU4tyPT
+5wYUEM7NX8VRoasZ4OUvYyYBw1Cx8vMdvQn/gv8CgYAIhxcFYqkEWrJx4XskO+5B
+VKUw0MziREO/YE0wTD76B7cF/ntpDaocwLvAIN+z+a13HEtDdhGQXysK7GxMT57p
+OgrdfZAykZHBJdOv7B2k0odbr0LHwVd/Pp1DNJecBFId0dzpoM6gXmvKzQZgJAt+
+tTL6+EGNLsKspfyrFl+7wQKBgQDAt2VuJbAJ1xQOdS+4IDCujfbrxp60uCBJVylW
++WK56LAP2WxtqLlhtsQuTKeiqgIkRp/vzo1jZ+0tX7f4oKnIL2NCT3aeESys3g3R
+aDmCKQOD5mkJGvmgpFLr3INHoqiLbfuV2uS2qgWnIQRwJLOTnksOWzxIYdPFYGDH
+cTz9bQKBgQDGv929DUinrKXe/uKJHLAcq+MjmF/+kZU9yn+svq6SSdplqp7xbXX4
+3T5HCWqD4Sy+PVzGaDg5YfXC8yaFPPfY0/35T2FoQEiCAPQO+07Smg6RqJ3yVpIm
+LTsbLleJTc8CX0bI4SukQ7MVQsiHimzyEzx3eyLt1S8aBdJuRFZ2mg==
+-----END RSA PRIVATE KEY-----]],
+
+ --[[
+ Issuer: C=US, ST=California, L=San Francisco, O=Mashape, OU=Kong, CN=ssl-alt.com
+ Validity
+ Not Before: May 24 23:46:58 2017 GMT
+ Not After : Jun 23 23:46:58 2017 GMT
+ Subject: C=US, ST=California, L=San Francisco, O=Mashape, OU=Kong, CN=ssl-alt.com
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ Public-Key: (4096 bit)
+ --]]
+ cert_alt = [[-----BEGIN CERTIFICATE-----
+MIIFXjCCA0YCCQCsb6B5OWdHXDANBgkqhkiG9w0BAQsFADBxMQswCQYDVQQGEwJV
+UzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNU2FuIEZyYW5jaXNjbzEQ
+MA4GA1UECgwHTWFzaGFwZTENMAsGA1UECwwES29uZzEUMBIGA1UEAwwLc3NsLWFs
+dC5jb20wHhcNMTcwNTI0MjM0NjU4WhcNMTcwNjIzMjM0NjU4WjBxMQswCQYDVQQG
+EwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNU2FuIEZyYW5jaXNj
+bzEQMA4GA1UECgwHTWFzaGFwZTENMAsGA1UECwwES29uZzEUMBIGA1UEAwwLc3Ns
+LWFsdC5jb20wggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC4SEsrn5zj
+f2w/mT9zxw9RZJxIo325HPHUV27U1gX5YFnCGdA6znvzd+GzUwohJMFhH7X7k3+g
+NhXZlUaxJ01N98QBmNH6GfzAoZexny+QGRU7/jkziQMH1A94yXBxQa5cfg3WA4ti
+JaIDZHRTVLDTvONm4a1GUuU6p6aUarZznCzzvkCqPzSBamHMu2jMWmozdVwPQufH
+mzJLbNLa7TVjVnalKgAdnXz8Rdnivb8pRVj8ASJU+iGQBCaXRAtRm4Hd0PAdJPXH
+6ObregxF0uhwDlHr2FbmdYjWKf6WB5xz18LVreWF07VN5AHsa+H/wMYOpuInmiYt
+9Xzl3h8dt8KiFwaMf4jYyNRRyLZhJEM8F7pSAuTLXTcluK79hWhliwO7DFKGbrJY
+YDQoLQFX6E0xyfYXXnaNTVuiu9503wwX2+IoomUEFXQ0TJ1+9gBg855Jx6Xw5/Zb
+njQS9ayYl5HlGzWKR+Dul13JgDDMYSqvI69tTmL1JOdufopmFUr50C0TPdp2cQlP
+gHXhqMbAua+EcpPiBSk9mQ0jY2CpRczos5Ais4TV8r71VEqJgaTVd39tG63/q/ig
+XFvoPRzi53/tBWy3cVroEvsajNzObuQcwW7b70AULnp0VFDhrRuAsQ9ULXOi6gMP
+K0hyONTdXijtHk6ndEFH9qpYMXQOmpCYtQIDAQABMA0GCSqGSIb3DQEBCwUAA4IC
+AQCvuEsqWpgRqLgvfJXgoLRpoeADG3OlY0ikuOaW+dPapbC9WC02Sa0f7Iy6gED7
+8UFGUorZVYKKTuR8SJk27Q/vVKV7Ljtj9mkIRcBPWpePr08qzVBd3xrSONPVwRgU
+cORI2xNFaz0NwtKOHZ7MIQ8SJbvlqCHYUrl165eIJIiUF2hyzMv4Ymg8Vb0gwGtG
+DEibtQweiMZ17STlZ/q1qW5q9nlEvIUNHb8uno77r+l7LdBNWfSwwme+TQHXfR8q
+UzMzLvgKJQzkayaNQI9BD+Ztm0BcYzC72MrHfpTyM3PndbL5Kkws40XZ5bmwgbYn
+JsIUW1cGxBUc3+lVVQUO4zpihO5oQXwV5LcMkIfYEc1VA1LfqmveXB8/5bGTsHVX
+HVWGNNB6Eb5t+jlGRWE61KU79kw3jBuhG/MXSsjeR3rPX6mqoVMNtPzMuG7V9f+a
+bbsKp5oLfDPw1D7x7HgBDH7wlbovXavbF/7gqApdssYqtPqVC9MekYAOhC63tuuP
+oBthw0f9wa7vQc50VLSIOAUZbgg3Qpic+abkUpLLqPH2nIp0ffBAZ054+u7GkMwQ
+daRqH/ssQmfPQxd1l4x8mynx876bgWrg2y6EJoM1N5zCoA2C1hloDL4EApJHCmP2
+OoLwADN8ov3ctgXUAv9wgYkJHkQ7TO1dRpvuIzXc/oJA1w==
+-----END CERTIFICATE-----]],
+
+ key_alt = [[-----BEGIN RSA PRIVATE KEY-----
+MIIJKAIBAAKCAgEAuEhLK5+c439sP5k/c8cPUWScSKN9uRzx1Fdu1NYF+WBZwhnQ
+Os5783fhs1MKISTBYR+1+5N/oDYV2ZVGsSdNTffEAZjR+hn8wKGXsZ8vkBkVO/45
+M4kDB9QPeMlwcUGuXH4N1gOLYiWiA2R0U1Sw07zjZuGtRlLlOqemlGq2c5ws875A
+qj80gWphzLtozFpqM3VcD0Lnx5syS2zS2u01Y1Z2pSoAHZ18/EXZ4r2/KUVY/AEi
+VPohkAQml0QLUZuB3dDwHST1x+jm63oMRdLocA5R69hW5nWI1in+lgecc9fC1a3l
+hdO1TeQB7Gvh/8DGDqbiJ5omLfV85d4fHbfCohcGjH+I2MjUUci2YSRDPBe6UgLk
+y103Jbiu/YVoZYsDuwxShm6yWGA0KC0BV+hNMcn2F152jU1borvedN8MF9viKKJl
+BBV0NEydfvYAYPOeScel8Of2W540EvWsmJeR5Rs1ikfg7pddyYAwzGEqryOvbU5i
+9STnbn6KZhVK+dAtEz3adnEJT4B14ajGwLmvhHKT4gUpPZkNI2NgqUXM6LOQIrOE
+1fK+9VRKiYGk1Xd/bRut/6v4oFxb6D0c4ud/7QVst3Fa6BL7Gozczm7kHMFu2+9A
+FC56dFRQ4a0bgLEPVC1zouoDDytIcjjU3V4o7R5Op3RBR/aqWDF0DpqQmLUCAwEA
+AQKCAgBn/HtWaWHJSdzWYm5YsYnmPuSlZIQMEdYwIQosVXzXhFQB4DkNBfkRoKMe
+YoxDuY7ZdGBnTork58AaoE5cprXLejUDRa2u+D0UodqMYywentjJmqHCf9zS7Qmx
++dFWR17RWFwMWMGtJ1ktmuC9KPwC7wJOyqfRF/O7zmCEPVcpE4aWH9QzfSjuog3/
+zfzL23U0BlRlVDaf/uY5g3XUDahjnqWie3nHPFgLrorNlI6rBjO5OBacZuzLbFwu
+XToZ2atFdKIZgAKkxLqRQ7RrLiD1Ik99yvz2XHpThyzekfrpr2WE1/S9OIKFKlUf
+iJzliWz5VZgmCqjipDTPLTDXvxq3EJDGbOlsD3eLXGeIufbQY4SqV73rth+0gER4
+m0S7cGjUuUASvtoX0pyxFwlZ3/DISMDKvGDGvx3FlYhDs/8D54C9nuuYXpCflw/g
+8+C6uIF4zIcQ4JNI9RKQDlUYCTKiz8klCzXQxVy4HVyPVYWQxXfNYVkyQjf7PxQi
+Xr1TwgE2snGjxqfWbuEnqTz2LADGUjtTwwZcOkur3CAAKqd86Keka6ZUaAe8IM+D
+xuUDH/v3cH8qb5PDZ2OIoVTJk3DDr2NZ3JOX55UV7AutWFYTCRhX3qNY9aQ8iol7
+AjfMIRzB6uupMgbpCuuAYlvDtSxNK2hPFWlO24ybqh15F8NkoQKCAQEA6UWA5Lgc
+E4+b7Yr9vqFqoTlpWmPBvPR1F4GolOOxs2R3pL45Uqc8afgQPXSB/vGH9o4asF6X
+8XfqRNyObTzSvbwuOMw1G1lTMPiWVHY2MNs4fZwEoCdVJJSYJorEJlyPRxsZ86xD
+ltGsa7RiLUk2IoYrocgrMz6MN03eNET5mVu1eLb59fMSwEoer6CY2n8kE56SvsaK
+3ulwaJeKBUWWXsoZ+e7NWx55sPQ/95F2exk9aCGdRUsFMM+vjunIq+7jq5DyL/O0
+Jqe9g4QTGLTT9DydKZhjvPlnW51Ehl42nwoQNSpCwHmR9qfV/lqjU21tnwJ0lAEd
+AuVaRyMfyLE/3QKCAQEAyjzalPsVBNL+/9Tl4dabR0VpP00oTl1g8fguke8sE+ay
+BKwipAQHoCvFufB/wmTR/H2U7ogGhwUWxkjeJIk44BAqI2wbq4HdKE1Yo2k2QB6m
+VkWOqdf47OKupTOhxIeNrRapCQ5r44LVjK7jgvMvbOJ9OGZm+/5IgkoYgRK4jOYk
+h89iM3g5bEQ4zgugQP85ghQQ9pwwAy3d/06V2auCJo4pitjluKctB5HtXubTJSMl
+axRpVQ8fhtlC8MUpDx1v8OZRkxQIa82VR9v8cUM0Zlw8t1vOz/W8ECzyfJtsFMUC
+ykMTTBmpt9+sAXaCR0Mwo3GJABrsSn2z5vGmiKEauQKCAQBoxisKkBcsQgiLPS6T
+fPTjzWGgk8XlFPeywy3xEgQyyyFiAX7FvQ/JmP3SXI428E1dVJ5wMUyVzIKQw2/F
+aNhPGEK6iB4iVpCjIkSDU0Ur1IsfAACj3obDk2pzhUhs4o4IJggWBn2lNC/5gF/I
+b2W9Q/49ACdHMQTRokv3tjNVyndL7QOAkNkPPTtjLwL4wLp3hXXr8klVrgwrLkVz
+8LmFgckBFV1vW9TUwiApFlDdIY0PRGnbQcLnFaGI00Cq2PWxjbz6BMAZzKW2eJAL
+PM0mmkMM98F0k6D06UJqB88IyABXoM+ym+gPnXrkb9mEE1Z1YSjzgTyCnHlcEk6o
+WdSRAoIBACg1bSgNu6IX6UcoJwR9zKWg8Un6pzbdbfbt5yRwrwzN4zr2lnSRsIpx
+6YAMhvo5XV6cAU5jkRirNFn8Bt6wwbQawqYESoQQ782hgywKMRUSgvPIJJM0M3O1
+pg+GcnVGli6BwN3iFiVHz/mGlAlnHFjDty3NflA/wF7XKIQRGsw4va6a1uVw08no
+znp46UXC+MYaAz1k1E7tgaPPFhAO/3N29F98vD+4TUWiB9XEgtpxYHEnv8F/nj8L
+VznTmVQ+ABGfWTyq0PnOCA4feNN0DykC0beK81V5gAifRx7rL9P5T5KzP1T0DUBX
+ojUwQLq2aycz3Y89yxkMYQZbqUak8VECggEBAMj0qzxSPrboxNOwKRcpGGhRFscJ
+K/4iNG165/q2btZiDZ9BiUO8WZGR8Ww50fZb21fIJBaU+znLaDiY6b4UDc0H4d0H
+vt9bkm9BmNkdbHlDR++7XcRIuq1w4EDtgvDqT8oCuW8mWOt+oqnQof3MOO0Z0AbI
+Ksbcnvk0qf75vZUVPoPCoIAuex23PxWhewb3BM9ifeRr4EUjWWH9+iJ0ucnGHndq
+MRz5bk6HBaxa2Twpa6yra+pobyWhRyU/X40wV7nUs3wd1vZNMjn0i8vXwnT6zdNv
+11htsJRdoyo2gXnVNMWN1D+8QTozSXFTTyM2LG4k06Dw3dAl5KHQjKWX+ac=
+-----END RSA PRIVATE KEY-----]],
+
+ --[[
+ Signature Algorithm: ecdsa-with-SHA256
+ Issuer: C = US, ST = California, L = San Francisco, O = Kong, OU = Core, CN = ssl-example.com
+ Validity
+ Not Before: Nov 18 16:49:53 2020 GMT
+ Not After : Sep 3 16:49:53 2294 GMT
+ --]]
+ cert_alt_ecdsa = [[-----BEGIN CERTIFICATE-----
+MIICOjCCAeGgAwIBAgIUbsAIMsTeD3F1oNLKOyRabSN6O9EwCgYIKoZIzj0EAwIw
+cjELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExFjAUBgNVBAcMDVNh
+biBGcmFuY2lzY28xDTALBgNVBAoMBEtvbmcxDTALBgNVBAsMBENvcmUxGDAWBgNV
+BAMMD3NzbC1leGFtcGxlLmNvbTAgFw0yMDExMTgxNjQ5NTNaGA8yMjk0MDkwMzE2
+NDk1M1owcjELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExFjAUBgNV
+BAcMDVNhbiBGcmFuY2lzY28xDTALBgNVBAoMBEtvbmcxDTALBgNVBAsMBENvcmUx
+GDAWBgNVBAMMD3NzbC1leGFtcGxlLmNvbTBZMBMGByqGSM49AgEGCCqGSM49AwEH
+A0IABCwjAZ7WZIwBJQOER5LB6g554ecpBVUnHKjYq8xiWU2+giX5pg4ros6rf3tv
+MMkc3aPYz87B7bwQlZ0Z2NC7iUujUzBRMB0GA1UdDgQWBBQzR6or+QaEVZxXrX5/
+BhgA7y5mjTAfBgNVHSMEGDAWgBQzR6or+QaEVZxXrX5/BhgA7y5mjTAPBgNVHRMB
+Af8EBTADAQH/MAoGCCqGSM49BAMCA0cAMEQCIEDzO105JmNu3RLib3DyIZ4TqDTF
+/iEr+t+W6+rZqiHuAiBvhIxGlLfkypQa9p4iNKRLmFcEk/S/shQ4d0hzd9SDbg==
+-----END CERTIFICATE-----]],
+ key_alt_ecdsa = [[-----BEGIN EC PRIVATE KEY-----
+MHcCAQEEIECo5oNJH83ZUFUm3SfjRHyPyRU5pJ5D1V0zk4KtrlNZoAoGCCqGSM49
+AwEHoUQDQgAELCMBntZkjAElA4RHksHqDnnh5ykFVSccqNirzGJZTb6CJfmmDiui
+zqt/e28wyRzdo9jPzsHtvBCVnRnY0LuJSw==
+-----END EC PRIVATE KEY-----]],
+
+ --[[
+ Issuer: C = US, ST = California, L = San Francico, O = Kong Inc., CN = ssl-alt-alt.com
+ Validity
+ Not Before: Nov 18 07:28:56 2018 GMT
+ Not After : Dec 18 07:28:56 2018 GMT
+ Subject: C = US, ST = California, L = San Francico, O = Kong Inc., CN = ssl-alt-alt.com
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ Public-Key: (2048 bit)
+ --]]
+ cert_alt_alt = [[-----BEGIN CERTIFICATE-----
+MIIDpDCCAoygAwIBAgIJAIAQMZH+2V26MA0GCSqGSIb3DQEBCwUAMGcxCzAJBgNV
+BAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRUwEwYDVQQHDAxTYW4gRnJhbmNp
+Y28xEjAQBgNVBAoMCUtvbmcgSW5jLjEYMBYGA1UEAwwPc3NsLWFsdC1hbHQuY29t
+MB4XDTE4MTExODA3Mjg1NloXDTE4MTIxODA3Mjg1NlowZzELMAkGA1UEBhMCVVMx
+EzARBgNVBAgMCkNhbGlmb3JuaWExFTATBgNVBAcMDFNhbiBGcmFuY2ljbzESMBAG
+A1UECgwJS29uZyBJbmMuMRgwFgYDVQQDDA9zc2wtYWx0LWFsdC5jb20wggEiMA0G
+CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDCngZ5grKAV5bR/FRSkIiR9Y54OWMt
+endztlp3scp4vTVci4mMOhsSMkTJSpxOieOWACCKpHksux8kUJjOgJ12p9FrWII4
+SYj3+5R+I8ujD3zmx3IDol8UIFsCuibVhN9FKDcVHySPtNGwIM0NnjuVm2fl79hU
+ILNmtOq/GoUbScecaMnKzFZy+VUPXRIdQtHOUUteVdppFrx2EPP+Az9l2CN75CRi
+VjwxTA8REkYm9C2okVdj38JodiBnkO1z0aEIlQD8qKgG86C+YF7qTlSzUtoOHvkt
+Km+PoKoMlDvcZ/ItXz7b2I+x3jhsnVETGTXV8jHIRncl+o7jKV5H/gxDAgMBAAGj
+UzBRMB0GA1UdDgQWBBR2h+rYF8B91WE7tUpeCST8TOQrUjAfBgNVHSMEGDAWgBR2
+h+rYF8B91WE7tUpeCST8TOQrUjAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEB
+CwUAA4IBAQARP3bVbTHYlB/V6Ws0jvjJtRGs6RkIB8Hvwcn9hltoKpgdRcrkpkCI
+50jmipO2ssP5uEhhBuS3D53K3GEYWJJh35MW7iAzJw1+Yn+/00/1nwhoaYvjbxv+
+k5rtGHIR8oj8Uf0ijh+ah508cavls/jotQXqkGkkg3QNDJ/2H+QmxMtAM5VJ/dU9
+66IeVk1e/y4wBMFyCzMQQ/HluLmOXlrhttEgwpcCfm4/dksRPav5nPi75OqabI0V
+bpTBKoI0Llp45GWNeQyF9kPV3wTDF0UmzZnkD95hoe4CHZV7dsUGS8YfM9Wv6Cvh
+wcqsNL5LjIUJiNuykV2pruOsf5IoCKlG
+-----END CERTIFICATE-----]],
+
+ key_alt_alt = [[-----BEGIN PRIVATE KEY-----
+MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQDCngZ5grKAV5bR
+/FRSkIiR9Y54OWMtendztlp3scp4vTVci4mMOhsSMkTJSpxOieOWACCKpHksux8k
+UJjOgJ12p9FrWII4SYj3+5R+I8ujD3zmx3IDol8UIFsCuibVhN9FKDcVHySPtNGw
+IM0NnjuVm2fl79hUILNmtOq/GoUbScecaMnKzFZy+VUPXRIdQtHOUUteVdppFrx2
+EPP+Az9l2CN75CRiVjwxTA8REkYm9C2okVdj38JodiBnkO1z0aEIlQD8qKgG86C+
+YF7qTlSzUtoOHvktKm+PoKoMlDvcZ/ItXz7b2I+x3jhsnVETGTXV8jHIRncl+o7j
+KV5H/gxDAgMBAAECggEBAJhVXTgLZ3EyHimrWs1tuJiXHrdYJBta+tkl6VY7YgJ0
+B6qyxi1u5fWuR01QC10mbW/iFZav+vFaXpvsQk+ROK/B2BgwJW2tkXqZ/7dkiWbP
+HrL9dm8Fz2pPkS1nTDJhWOom+kacI+AgZul4I0j/jCAkjoTa4fenyQUho4WGWp3q
+GIVcawNfprrXObMUgs+31eps3A/iza7w3eBuH4aR2npW6DtBr3KPwH9H1yBLpOqq
+E7vY/oyfndKyMMdJGk9Ql8AN5SA4B/r2t5nw+liRUUxIj+yWf5q5pj2FftBo2Ldn
+0JGWKXDUTdniLzK+akynRv5o1GFR0SeK7TLRzASfavECgYEA+nojt54CTglUOPCY
+rpoM898SypItYJOhlvE/HlfmsLmRMpkCAIYo7yCtCTdRC9gd9FPxEJIAC/P3MzTa
+KlVfwXqlFIC+oflfIkF8I5Zw4JsqqF+aqEY4b2xTLfxnfK5gMID2rRstUVQO1BiE
+Jb6KzB/67e1yokGgKLIeGsOkqdcCgYEAxuiTVt1RZzqOKTvKYLd8tANzm+lwD6Dd
+kpVl3xZcHEVd/nWfdtR8VZ+V+mbe71Hn7ZX/UBBktLeB6djd0cdd8jIOCkvhW/aw
+vLm2VAM7J6H5Up92q9Jtpid+993fbd07d7peO+boMYzPW0f7wqU0PL+ZK9R9FdS2
+cHaTcFvrW3UCgYEA6DRa8FqXoGidn7vMj/FYmKzw6sLhNmsmnpw/+41Z2/PsW4/l
+fz7gq+8K+0RA6k4MVvmKveXcDTi6rsoMhrpm7yMX7w37rIVWYJd80jEhq9etkDIx
+Wlbe8szlv/gCqF+v5Mdp58kOFhtrM80WlTczzVDIe9JpN2rHY3Lc3csJ2DkCgYEA
+hCAHhyLaKNT3i6JAyz/24OiOCdnlaywzImSE18xVgR3+0sE1HM0GjiXEjSF6IsRo
+aCREBN3u1zAyZrB8oBVrbS8crnA7EUhrm+FMoL/IsongQKbWQEo2NbF0oJdMDAFx
+uBUe9XFreUaMkpjdPi1Y5qVqzHeIY1D5ovjQ9UjJrOUCgYA/GJPhcZbEz4MgokqE
+CCWCLF6Ia5fehznO6VrbKZUUklURFIaw6Uc+DIbGpJZZwVt9l7R3x2pJlF1NlaCJ
+IqGzqSWne1tW86drBcfSip714wsZOoF8PT6iUCa0LC1sum1P4vS2cnRw8jXwIL6g
+gEuhDrQHJ5V1U/Qc1HrqWYH4cA==
+-----END PRIVATE KEY-----]],
+
+ --[[
+ Signature Algorithm: ecdsa-with-SHA256
+ Issuer: C = US, ST = California, L = San Francisco, O = Kong, OU = Core, CN = ssl-alt-alt.com
+ Validity
+ Not Before: Nov 25 14:47:53 2020 GMT
+ Not After : Sep 10 14:47:53 2294 GMT
+ Subject: C = US, ST = California, L = San Francisco, O = Kong, OU = Core, CN = ssl-alt-alt.com
+ --]]
+ cert_alt_alt_ecdsa = [[-----BEGIN CERTIFICATE-----
+MIICPDCCAeGgAwIBAgIUUN+dYLgQkk8az6KLufNic5LFKrYwCgYIKoZIzj0EAwIw
+cjELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExFjAUBgNVBAcMDVNh
+biBGcmFuY2lzY28xDTALBgNVBAoMBEtvbmcxDTALBgNVBAsMBENvcmUxGDAWBgNV
+BAMMD3NzbC1hbHQtYWx0LmNvbTAgFw0yMDExMjUxNDQ3NTNaGA8yMjk0MDkxMDE0
+NDc1M1owcjELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExFjAUBgNV
+BAcMDVNhbiBGcmFuY2lzY28xDTALBgNVBAoMBEtvbmcxDTALBgNVBAsMBENvcmUx
+GDAWBgNVBAMMD3NzbC1hbHQtYWx0LmNvbTBZMBMGByqGSM49AgEGCCqGSM49AwEH
+A0IABKnmBOy/odm9rUNVTz2vMzGtXVnodngWFY7wf2W99aLcDLz32WNg10oYdGKW
+MuPCtO6vwWGgOi+/mYSToEU7U0qjUzBRMB0GA1UdDgQWBBQtbY0EZpt9Nlf2spRC
+IfphGjYmijAfBgNVHSMEGDAWgBQtbY0EZpt9Nlf2spRCIfphGjYmijAPBgNVHRMB
+Af8EBTADAQH/MAoGCCqGSM49BAMCA0kAMEYCIQC7MFmBMdan3DIsgzLDDwTOLkOI
++Vj2qMdBL4XRWt9c6gIhAMAbZ8M3kMTxPuI+bjZ31Zuu+bGg0Quo4EgU8yMmhJLt
+-----END CERTIFICATE-----]],
+
+ key_alt_alt_ecdsa = [[-----BEGIN EC PRIVATE KEY-----
+MHcCAQEEILefTUI90Vsu3JV1WZVrYgl82HbAICC/9/sMIL6j1RThoAoGCCqGSM49
+AwEHoUQDQgAEqeYE7L+h2b2tQ1VPPa8zMa1dWeh2eBYVjvB/Zb31otwMvPfZY2DX
+Shh0YpYy48K07q/BYaA6L7+ZhJOgRTtTSg==
+-----END EC PRIVATE KEY-----]],
+
+ --[[
+ Issuer: C = US, ST = California, O = Kong Testing, CN = Kong Testing Root CA
+ Validity
+ Not Before: May 2 19:34:42 2019 GMT
+ Not After : Apr 27 19:34:42 2039 GMT
+ Subject: C = US, ST = California, O = Kong Testing, CN = Kong Testing Root CA
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ X509v3 Key Usage: critical
+ Digital Signature, Certificate Sign, CRL Sign
+ --]]
+ cert_ca = [[-----BEGIN CERTIFICATE-----
+MIIFoTCCA4mgAwIBAgIUQDBLwIychoRbVRO44IzBBk9R4oYwDQYJKoZIhvcNAQEL
+BQAwWDELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExFTATBgNVBAoM
+DEtvbmcgVGVzdGluZzEdMBsGA1UEAwwUS29uZyBUZXN0aW5nIFJvb3QgQ0EwHhcN
+MTkwNTAyMTkzNDQyWhcNMzkwNDI3MTkzNDQyWjBYMQswCQYDVQQGEwJVUzETMBEG
+A1UECAwKQ2FsaWZvcm5pYTEVMBMGA1UECgwMS29uZyBUZXN0aW5nMR0wGwYDVQQD
+DBRLb25nIFRlc3RpbmcgUm9vdCBDQTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCC
+AgoCggIBAMp6IggUp3aSNRbLAac8oOkrbUnFuxtlKGYgg8vfA2UU71qTktigdwO6
+Kod0/M+daO3RDqJJXQL2rD14NDO3MaextICanoQSEe+nYyMFUIk+QplXLD3fbshU
+nHoJcMS2w0x4cm1os4ebxR2Evndo6luz39ivcjau+BL+9iBAYL1g6+eGOjcSy7ft
+1nAMvbxcQ7dmbAH2KP6OmF8cok+eQWVqXEjqtVx5GDMDlj1BjX6Kulmh/vhNi3Hr
+NEi+kPrw/YtRgnqnN0sv3NnAyKnantxy7w0TDicFjiBsSIhjB5aUfWYErBR+Nj/m
+uumwc/kRJcHWklqDzxrZKCIyOyWcE5Dyjjr46cnF8HxhYwgZcwkmgTtaXOLpBMlo
+XUTgOQrWpm9HYg2vOJMMA/ZPUJ2tJ34/4RgiA00EJ5xG8r24suZmT775l+XFLFzp
+Ihxvs3BMbrWsXlcZkI5neNk7Q/1jLoBhWeTYjMpUS7bJ/49YVGQZFs3xu2IcLqeD
+5WsB1i+EqBAI0jm4vWEynsyX+kS2BqAiDtCsS6WYT2q00DTeP5eIHh/vHsm75jJ+
+yUEb1xFxGnNevLKNTcHUeXxPUnowdC6wqFnaJm7l09qVGDom7tLX9i6MCojgpAP0
+hMpBxzh8jLxHh+zZQdiORSFdYxNnlnWwbic2GUJruiQVLuhpseenAgMBAAGjYzBh
+MB0GA1UdDgQWBBQHT/IIheEC2kdBxI/TfGqUxWJw9zAfBgNVHSMEGDAWgBQHT/II
+heEC2kdBxI/TfGqUxWJw9zAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIB
+hjANBgkqhkiG9w0BAQsFAAOCAgEAqXZjy4EltJCRtBmN0ohAHPWqH4ZJQCI2HrM3
+wHB6c4oPWcJ+M2PfmYPUJo9VMjvn4S3sZuAysyoHduvRdGDnElW4wglL1xxpoUOx
+FqoZUoYWV8hDFmUTWM5b4CtJxOPdTAd8VgypulM3iUEzBQrjR6tnMOdkiFMOmVag
+0/Nnr+Tcfk/crMCx3xsVnisYjJoQBFBH4UY+gWE/V/MS1Sya4/qTbuuCUq+Qym5P
+r8TkWAJlg7iVVLbZ2j94VUdpiQPWJEGMtJck/NEmOTruhhQlT7c1u/lqXCGj7uci
+LmhLsBVmdtWT9AWS8Rl7Qo5GXbjxKIaP3IM9axhDLm8WHwPRLx7DuIFEc+OBxJhz
+wkr0g0yLS0AMZpaC6UGbWX01ed10U01mQ/qPU5uZiB0GvruwsYWZsyL1QXUeqLz3
+/KKrx3XsXjtBu3ZG4LAnwuxfeZCNw9ofg8CqF9c20ko+7tZAv6DCu9UL+2oZnEyQ
+CboRDwpnAlQ7qJVSp2xMgunO3xxVMlhD5LZpEJz1lRT0nQV3uuLpMYNM4FS9OW/X
+MZSzwHhDdCTDWtc/iRszimOnYYV8Y0ubJcb59uhwcsHmdfnwL9DVO6X5xyzb8wsf
+wWaPbub8SN2jKnT0g6ZWuca4VwEo1fRaBkzSZDqXwhkBDWP8UBqLXMXWHdZaT8NK
+0NEO74c=
+-----END CERTIFICATE-----]],
+
+ key_ca = [[-----BEGIN RSA PRIVATE KEY-----
+MIIJKAIBAAKCAgEAynoiCBSndpI1FssBpzyg6SttScW7G2UoZiCDy98DZRTvWpOS
+2KB3A7oqh3T8z51o7dEOokldAvasPXg0M7cxp7G0gJqehBIR76djIwVQiT5CmVcs
+Pd9uyFSceglwxLbDTHhybWizh5vFHYS+d2jqW7Pf2K9yNq74Ev72IEBgvWDr54Y6
+NxLLt+3WcAy9vFxDt2ZsAfYo/o6YXxyiT55BZWpcSOq1XHkYMwOWPUGNfoq6WaH+
++E2Lces0SL6Q+vD9i1GCeqc3Sy/c2cDIqdqe3HLvDRMOJwWOIGxIiGMHlpR9ZgSs
+FH42P+a66bBz+RElwdaSWoPPGtkoIjI7JZwTkPKOOvjpycXwfGFjCBlzCSaBO1pc
+4ukEyWhdROA5Ctamb0diDa84kwwD9k9Qna0nfj/hGCIDTQQnnEbyvbiy5mZPvvmX
+5cUsXOkiHG+zcExutaxeVxmQjmd42TtD/WMugGFZ5NiMylRLtsn/j1hUZBkWzfG7
+Yhwup4PlawHWL4SoEAjSObi9YTKezJf6RLYGoCIO0KxLpZhParTQNN4/l4geH+8e
+ybvmMn7JQRvXEXEac168so1NwdR5fE9SejB0LrCoWdombuXT2pUYOibu0tf2LowK
+iOCkA/SEykHHOHyMvEeH7NlB2I5FIV1jE2eWdbBuJzYZQmu6JBUu6Gmx56cCAwEA
+AQKCAgBh8MQHbp42r7B4bwhEsgIP5868kaXZMYxiIjY+ZojI22CQSrQMj0oihmnO
+Dhu//Z9k8ewHOj+AkHtuXHe70FB3knECiEhHEEqWxzwgE5EKYhBrBgzDfRGkW7E5
+ItnmfZVopxaKr8uvu/yUM8LCFgDPDOopcWxo4SfkYGoD3cAtuvVBj98XBsN+G9DP
+cIpS07p5u1RheoYH5Ef2Me6dXqq5eMJdDxNdQMIg4wpIZS4hWM+dTcv8pd3e4+vt
+iCivCeVK/8mCtOH9P5Cv0B4Ac1zGu93AUEhXPcurCVXoiyZ/gyJJN9dZLlflfyFI
+qu7eOpot8jHnEL0cepB8Qhn0LlQTuv6rjJqmnl3tJA3S6rcM/mOjihkk1uo7JdDK
+vH498XR5qZPDlXZ8PVu3nI5EgXpmFIcCBuuVFS5QI63NZ32YqoGYXK37K7C9lQsL
+L/iR+YpwuQqDmM+UEETjBCIMKvxghFH0ICR041yg9tkjRhNKCAGc6n70wQDUq57s
+jjZmTQ4ZydxCsWVjLo7fCcoyQ9B7IUGPUUn8WavPUwtz1kG6VK7RDGa0KtgCD0vc
+iEwbWi9uwkZdoZdHcB8qLgCPjMGgRJLOyJ67xQ0RP+r+WkhUAjYcaucFonyyBhtv
+OrqNyEM3SEpgrzgttyyg+dP/cDvPbp4NXoxKAMyd8c7mjPploQKCAQEA+BL/qxLe
+LTKwe3TKpjAeyTB2iOxoWjtCqe3/xKbTS32Tn/VGwqhXyNeh+FTRhQu7fg5iL2C2
+JCOdYXWxRYIBwUh4HfApkgYzznUAU2vOh653MzW6LsOtDdgYF2cijN1ZFcbRTGpw
+eoA6U/cijuglwpTHF7zmRd9rSsv+PZ/fTDgY82MOdeaOUwyKuVyPUpNWfqSwxPd9
+tWEdOYjgq1llPbl1mktR0gYHIdHcSr1By7kmFw3/TQuic5Nm+FDidtfJYO36xFI1
+/CfwGVYeH42iul+KzdlITLAMRm2PAcWFjvxpw78T+xeUNpZlnZSgCIjtpfjywmXb
+uQvJoMMEX5PN1wKCAQEA0PIx4sgXiwqASa/foBB0Tk5jG3QWxucpqnLJURZeRqLQ
+BmF4WRrjs5V2y6iizegIcNmL0ZfwFBU79HwtAgFiTELLQL2xivhpMVjXL7QHeE4r
+A/9+49iO8wu8W/hwKxCDdGqXKyCKtW9b1yfUVB09j29GtApcV9v8KCTmDwYGrHI0
+DcEMtNLUbJvUeWFYFadJNFKxbsBtJPJIrYaiIyv2sL+Y3tZrYES72tTAYhMFwd0r
+9ooL5Ufrpuh4pHOxxA0Sh0EVUhNmyoq/ZJZ5wia+WB5NXBSD9JbciC5M4J8BMl/u
+Bx5RZbJSoAktYiOzev//6NHUmXsDjg3Kh9P48JVasQKCAQBVjt/k1bYQ6pmZirdV
+x+TmSLOpF7gJ3sRoLTB4V30qXR4sHgEQo9Ta7RvstPwqIdjBah6M7pMDNdFSyq+g
+JG2Mhvz+flUoCsGVZB7/pn/tpctwuwgClvQ5gR0V/TkaUkEmVJLdAxzV8yGq0eJ2
+XTSgvoVH95uH3712Z5LBGEGAXRyl3LUhDqpplDrIIVdBCJXdSdm5pQ4TH3Jf5Ihw
+MH3NYwhfdbi7cd7F2EZc9Jcbtzie3PH/VZLqv5zU6bihelz29Dz3ts7tr6yMYHo1
+Mbk9BDSwOE9KO7GQHLskxkYBAadMnrs6b3Brv0U+qwLizq7//jNjvpOgZ6Nbscbx
+W92zAoIBAQCNCK17cavSgggNtNSw6epXYLmssjMdlrKdBlW0kfCYpRTc+bWOD4Ra
+lyxUU0Nw0InCAlVJ59B4/cw2PgrzK5P5/avLyz6nmv0F/f1hiZbxMXH/hNlVWbtD
+ekxtl8e+iarxTXEz/wchaEUJeSzsicAfrPCAXe3ur+IIBr/yrBKdG4jfL8sv0o7n
+sFc+huI522yiEJ8LLn99TLyZxCJ0sxwUOX8qCnj3xe02zBv/Fu/v5yXhh1R4Mo9x
+XcDw39bBikFTYi7N86KSXAzMDHWrAxO/ztRQrthSo/G/SeFCTJE2O2IjE+fFSRRU
+SV2EvKxM/bbyo49o+YtwuwZVoFKLsYRBAoIBADaL9sx49XTHIIFGqEQP7NLEhs7D
+eJgSKP5oQ54J0iaoVpsoxng8DrTBkMVW75hiWzTW75EJnMXrauo/YfAbvsMM//3e
+BfRWvYpS5xKcHmXg2QJxy2VpvElHLg5Y2lligEZhO+5Sm2OG/hixBmiFvEvxPEB8
+8YIvYKcRAGA/HgDY9hGWSNsBP7qDXWP5kRm8qnB6zn33TVZMsXwUv6TP0cwsBKf7
+XDbnPBpOQK9nicehY7oscy9yTB9Q3bUHecYLY822ueCwaJgwJWFUH+Xe4u6xIH5l
+A/IyIfyOqxjUc34Me+37ehNmbTIxZ1BqLddppm9QsSAD7cDMurfb3pRpju4=
+-----END RSA PRIVATE KEY-----]],
+
+ dhparam = [[-----BEGIN DH PARAMETERS-----
+MIIBDAKCAQEA//////////+t+FRYortKmq/cViAnPTzx2LnFg84tNpWp4TZBFGQz
++8yTnc4kmz75fS/jY2MMddj2gbICrsRhetPfHtXV/WVhJDP1H18GbtCFY2VVPe0a
+87VXE15/V8k1mE8McODmi3fipona8+/och3xWKE2rec1MKzKT0g6eXq8CrGCsyT7
+YdEIqUuyyOP7uWrat2DX9GgdT0Kj3jlN9K5W7edjcrsZCwenyO4KbXCeAvzhzffi
+7MA0BM0oNC9hkXL+nOmFg/+OTxIy7vKBg8P+OxtMb61zO7X8vC7CIAXFjvGDfRaD
+ssbzSibBsu/6iGtCOGEoXJf//////////wIBAgICAOE=
+-----END DH PARAMETERS-----]],
+}
diff --git a/kong-versions/3.9.0.0/kong/spec/fixtures/stress_generator.lua b/kong-versions/3.9.0.0/kong/spec/fixtures/stress_generator.lua
new file mode 100644
index 00000000..dab93e6d
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/fixtures/stress_generator.lua
@@ -0,0 +1,151 @@
+-- This software is copyright Kong Inc. and its licensors.
+-- Use of the software is subject to the agreement between your organization
+-- and Kong Inc. If there is no such agreement, use is governed by and
+-- subject to the terms of the Kong Master Software License Agreement found
+-- at https://konghq.com/enterprisesoftwarelicense/.
+-- [ END OF LICENSE 0867164ffc95e54f04670b5169c09574bdbd9bba ]
+
+local stress_generator = {}
+stress_generator.__index = stress_generator
+
+
+local cjson = require "cjson"
+local pl_file = require "pl.file"
+local pl_path = require "pl.path"
+local uuid = require "resty.jit-uuid"
+
+
+local fmt = string.format
+local tmp_root = os.getenv("TMPDIR") or "/tmp"
+
+
+-- we need this to get random UUIDs
+math.randomseed(os.time())
+
+
+local attack_cmds = {
+ ["http"] = "GET http://%s:%d%s",
+}
+
+
+function stress_generator.is_running(self)
+ if self.finish_time == nil or self.finish_time <= os.time() then
+ return false
+ end
+
+ return true
+end
+
+
+function stress_generator.get_results(self)
+ if self.results ~= nil then
+ return self.results
+ end
+
+ if self.results_filename == nil then
+ return nil, "stress_generator was not run yet"
+ end
+
+ if stress_generator:is_running() then
+ return nil, "stress_generator results not available yet"
+ end
+
+ local report_cmd = fmt("vegeta report -type=json %s 2>&1", self.results_filename)
+ local report_pipe = io.popen(report_cmd)
+ local output = report_pipe:read('*all')
+ report_pipe:close()
+
+ if pl_path.exists(self.results_filename) then
+ pl_file.delete(self.results_filename)
+ end
+
+
+ local vegeta_results = cjson.decode(output)
+ local results = {
+ ["successes"] = 0,
+ ["remote_failures"] = 0,
+ ["proxy_failures"] = 0,
+ ["failures"] = 0,
+ }
+
+ vegeta_results.status_codes = vegeta_results.status_codes or {}
+
+ for status, count in pairs(vegeta_results.status_codes) do
+ if status == "200" then
+ results.successes = count
+ elseif status == "502" or status == "504" then
+ results.remote_failures = results.remote_failures + count
+ results.failures = results.failures + count
+ elseif status == "500" or status == "503" then
+ results.proxy_failures = results.proxy_failures + count
+ results.failures = results.failures + count
+ else
+ results.failures = results.failures + count
+ end
+ end
+
+ self.results = results
+
+ if self.debug then
+ -- show pretty results
+ local report_cmd = fmt("vegeta report %s 2>&1", self.results_filename)
+ local report_pipe = io.popen(report_cmd)
+ local output = report_pipe:read('*all')
+ report_pipe:close()
+ print(output)
+ end
+
+ return self.results
+end
+
+
+function stress_generator.run(self, uri, headers, duration, rate)
+ if stress_generator:is_running() then
+ return nil, "already running"
+ end
+
+ self.results_filename = fmt("%s/vegeta_%s", tmp_root, uuid())
+
+ duration = duration or 1
+ rate = rate or 100
+ local attack_cmd = fmt(attack_cmds[self.protocol], self.host, self.port, uri)
+ local req_headers = ""
+
+ for name, value in pairs(headers) do
+ req_headers = fmt("-header=%s:%s %s", name, value, req_headers)
+ end
+
+ local vegeta_cmd = fmt(
+ "echo %s | vegeta attack %s -rate=%d -duration=%ds -workers=%d -timeout=5s -output=%s",
+ attack_cmd, req_headers, rate, duration, self.workers, self.results_filename)
+
+ self.pipe = io.popen(vegeta_cmd)
+ -- we will rely on vegeta's duration
+ self.finish_time = os.time() + duration
+end
+
+
+function stress_generator.new(protocol, host, port, workers, debug)
+ if io.popen == nil then
+ error("stress_generator is not supported in this platform", 2)
+ end
+
+ local self = setmetatable({}, stress_generator)
+
+ protocol = protocol or "http"
+
+ if protocol ~= "http" then
+ error("stress_generator supports only http")
+ end
+
+ self.debug = debug == true
+ self.host = host or "127.0.0.1"
+ self.port = port or "80"
+ self.protocol = protocol
+ self.workers = workers or 10
+
+ return self
+end
+
+
+return stress_generator
diff --git a/kong-versions/3.9.0.0/kong/spec/fixtures/template_inject/nginx_kong_test_custom_inject_http.lua b/kong-versions/3.9.0.0/kong/spec/fixtures/template_inject/nginx_kong_test_custom_inject_http.lua
new file mode 100644
index 00000000..02ea74e8
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/fixtures/template_inject/nginx_kong_test_custom_inject_http.lua
@@ -0,0 +1,271 @@
+-- This software is copyright Kong Inc. and its licensors.
+-- Use of the software is subject to the agreement between your organization
+-- and Kong Inc. If there is no such agreement, use is governed by and
+-- subject to the terms of the Kong Master Software License Agreement found
+-- at https://konghq.com/enterprisesoftwarelicense/.
+-- [ END OF LICENSE 0867164ffc95e54f04670b5169c09574bdbd9bba ]
+
+return [[
+lua_shared_dict kong_mock_upstream_loggers 10m;
+
+> if role ~= "data_plane" then
+ server {
+ server_name mock_upstream;
+
+ listen 15555 reuseport;
+ listen 15556 ssl reuseport;
+
+> for i = 1, #ssl_cert do
+ ssl_certificate $(ssl_cert[i]);
+ ssl_certificate_key $(ssl_cert_key[i]);
+> end
+ ssl_protocols TLSv1.2 TLSv1.3;
+
+ set_real_ip_from 127.0.0.1;
+
+ location / {
+ content_by_lua_block {
+ local mu = require "spec.fixtures.mock_upstream"
+ ngx.status = 404
+ return mu.send_default_json_response()
+ }
+ }
+
+ location = / {
+ content_by_lua_block {
+ local mu = require "spec.fixtures.mock_upstream"
+ return mu.send_default_json_response({
+ valid_routes = {
+ ["/ws"] = "Websocket echo server",
+ ["/get"] = "Accepts a GET request and returns it in JSON format",
+ ["/xml"] = "Returns a simple XML document",
+ ["/post"] = "Accepts a POST request and returns it in JSON format",
+ ["/response-headers?:key=:val"] = "Returns given response headers",
+ ["/cache/:n"] = "Sets a Cache-Control header for n seconds",
+ ["/anything"] = "Accepts any request and returns it in JSON format",
+ ["/request"] = "Alias to /anything",
+ ["/delay/:duration"] = "Delay the response for seconds",
+ ["/basic-auth/:user/:pass"] = "Performs HTTP basic authentication with the given credentials",
+ ["/status/:code"] = "Returns a response with the specified ",
+ ["/stream/:num"] = "Stream chunks of JSON data via chunked Transfer Encoding",
+ },
+ })
+ }
+ }
+
+ location = /ws {
+ content_by_lua_block {
+ local mu = require "spec.fixtures.mock_upstream"
+ return mu.serve_web_sockets()
+ }
+ }
+
+ location = /ws/log {
+ content_by_lua_block {
+ local mu = require "spec.fixtures.mock_upstream"
+ return mu.retrieve_ws_log()
+ }
+ }
+
+ location /get {
+ access_by_lua_block {
+ local mu = require "spec.fixtures.mock_upstream"
+ return mu.filter_access_by_method("GET")
+ }
+ content_by_lua_block {
+ local mu = require "spec.fixtures.mock_upstream"
+ return mu.send_default_json_response()
+ }
+ }
+
+ location /xml {
+ content_by_lua_block {
+ local mu = require "spec.fixtures.mock_upstream"
+ local xml = [=[
+
+
+ Kong, Monolith destroyer.
+
+ ]=]
+ return mu.send_text_response(xml, "application/xml")
+ }
+ }
+
+ location /post {
+ access_by_lua_block {
+ local mu = require "spec.fixtures.mock_upstream"
+ return mu.filter_access_by_method("POST")
+ }
+ content_by_lua_block {
+ local mu = require "spec.fixtures.mock_upstream"
+ return mu.send_default_json_response()
+ }
+ }
+
+ location = /response-headers {
+ access_by_lua_block {
+ local mu = require "spec.fixtures.mock_upstream"
+ return mu.filter_access_by_method("GET")
+ }
+ content_by_lua_block {
+ local mu = require "spec.fixtures.mock_upstream"
+ return mu.send_default_json_response({}, ngx.req.get_uri_args(0))
+ }
+ }
+
+ location = /hop-by-hop {
+ content_by_lua_block {
+ local header = ngx.header
+ header["Keep-Alive"] = "timeout=5, max=1000"
+ header["Proxy"] = "Remove-Me"
+ header["Proxy-Connection"] = "close"
+ header["Proxy-Authenticate"] = "Basic"
+ header["Proxy-Authorization"] = "Basic YWxhZGRpbjpvcGVuc2VzYW1l"
+ header["Content-Length"] = nil
+ header["TE"] = "trailers, deflate;q=0.5"
+ header["Trailer"] = "Expires"
+ header["Upgrade"] = "example/1, foo/2"
+
+ ngx.print("hello\r\n\r\nExpires: Wed, 21 Oct 2015 07:28:00 GMT\r\n\r\n")
+ ngx.exit(200)
+ }
+ }
+
+ location ~ "^/cache/(?\d+)$" {
+ content_by_lua_block {
+ local mu = require "spec.fixtures.mock_upstream"
+ return mu.send_default_json_response({}, {
+ ["Cache-Control"] = "public, max-age=" .. ngx.var.n,
+ })
+ }
+ }
+
+ location ~ "^/basic-auth/(?[a-zA-Z0-9_]+)/(?.+)$" {
+ access_by_lua_block {
+ local mu = require "spec.fixtures.mock_upstream"
+ return mu.filter_access_by_basic_auth(ngx.var.username,
+ ngx.var.password)
+ }
+ content_by_lua_block {
+ local mu = require "spec.fixtures.mock_upstream"
+ return mu.send_default_json_response({
+ authenticated = true,
+ user = ngx.var.username,
+ })
+ }
+ }
+
+ location ~ "^/(request|anything)" {
+ content_by_lua_block {
+ local mu = require "spec.fixtures.mock_upstream"
+ return mu.send_default_json_response()
+ }
+ }
+
+ location ~ "^/delay/(?\d{1,3})$" {
+ content_by_lua_block {
+ local mu = require "spec.fixtures.mock_upstream"
+ local delay_seconds = tonumber(ngx.var.delay_seconds)
+ if not delay_seconds then
+ return ngx.exit(ngx.HTTP_NOT_FOUND)
+ end
+
+ ngx.sleep(delay_seconds)
+
+ return mu.send_default_json_response({
+ delay = delay_seconds,
+ })
+ }
+ }
+
+ location ~ "^/status/(?\d{3})$" {
+ content_by_lua_block {
+ local mu = require "spec.fixtures.mock_upstream"
+ local code = tonumber(ngx.var.code)
+ if not code then
+ return ngx.exit(ngx.HTTP_NOT_FOUND)
+ end
+ ngx.status = code
+ return mu.send_default_json_response({
+ code = code,
+ })
+ }
+ }
+
+ location ~ "^/stream/(?\d+)$" {
+ content_by_lua_block {
+ local mu = require "spec.fixtures.mock_upstream"
+ local rep = tonumber(ngx.var.num)
+ local res = require("cjson").encode(mu.get_default_json_response())
+
+ ngx.header["X-Powered-By"] = "mock_upstream"
+ ngx.header["Content-Type"] = "application/json"
+
+ for i = 1, rep do
+ ngx.say(res)
+ end
+ }
+ }
+
+ location ~ "^/post_log/(?[a-z0-9_]+)$" {
+ content_by_lua_block {
+ local mu = require "spec.fixtures.mock_upstream"
+ return mu.store_log(ngx.var.logname)
+ }
+ }
+
+ location ~ "^/post_auth_log/(?[a-z0-9_]+)/(?[a-zA-Z0-9_]+)/(?.+)$" {
+ access_by_lua_block {
+ local mu = require "spec.fixtures.mock_upstream"
+ return mu.filter_access_by_basic_auth(ngx.var.username,
+ ngx.var.password)
+ }
+ content_by_lua_block {
+ local mu = require "spec.fixtures.mock_upstream"
+ return mu.store_log(ngx.var.logname)
+ }
+ }
+
+ location ~ "^/read_log/(?[a-z0-9_]+)$" {
+ content_by_lua_block {
+ local mu = require "spec.fixtures.mock_upstream"
+ return mu.retrieve_log(ngx.var.logname)
+ }
+ }
+
+ location ~ "^/count_log/(?[a-z0-9_]+)$" {
+ content_by_lua_block {
+ local mu = require "spec.fixtures.mock_upstream"
+ return mu.count_log(ngx.var.logname)
+ }
+ }
+
+ location ~ "^/reset_log/(?[a-z0-9_]+)$" {
+ content_by_lua_block {
+ local mu = require "spec.fixtures.mock_upstream"
+ return mu.reset_log(ngx.var.logname)
+ }
+ }
+
+ location = /echo_sni {
+ return 200 'SNI=$ssl_server_name\n';
+ }
+
+ location = /ocsp {
+ content_by_lua_block {
+ local mu = require "spec.fixtures.mock_upstream"
+ return mu.handle_ocsp()
+ }
+ }
+
+ location = /set_ocsp {
+ content_by_lua_block {
+ local mu = require "spec.fixtures.mock_upstream"
+ return mu.set_ocsp(ngx.var.arg_status)
+ }
+ }
+ }
+> end -- role ~= "data_plane"
+
+ include '*.http_mock';
+]]
diff --git a/kong-versions/3.9.0.0/kong/spec/fixtures/template_inject/nginx_kong_test_custom_inject_stream.lua b/kong-versions/3.9.0.0/kong/spec/fixtures/template_inject/nginx_kong_test_custom_inject_stream.lua
new file mode 100644
index 00000000..75e4124a
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/fixtures/template_inject/nginx_kong_test_custom_inject_stream.lua
@@ -0,0 +1,61 @@
+-- This software is copyright Kong Inc. and its licensors.
+-- Use of the software is subject to the agreement between your organization
+-- and Kong Inc. If there is no such agreement, use is governed by and
+-- subject to the terms of the Kong Master Software License Agreement found
+-- at https://konghq.com/enterprisesoftwarelicense/.
+-- [ END OF LICENSE 0867164ffc95e54f04670b5169c09574bdbd9bba ]
+
+return [[
+server {
+ listen 15557;
+ listen 15558 ssl;
+ listen 15557 udp;
+
+> for i = 1, #ssl_cert do
+ ssl_certificate $(ssl_cert[i]);
+ ssl_certificate_key $(ssl_cert_key[i]);
+> end
+ ssl_protocols TLSv1.2 TLSv1.3;
+
+ content_by_lua_block {
+ local sock = assert(ngx.req.socket())
+ local data = sock:receive() -- read a line from downstream
+
+ if string.find(data, "get_sni") then
+ sock:send(ngx.var.ssl_server_name)
+ sock:send("\n")
+ return
+ end
+
+ if ngx.var.protocol == "TCP" then
+ ngx.say(data)
+
+ else
+ sock:send(data) -- echo whatever was sent
+ end
+ }
+}
+
+include '*.stream_mock';
+
+> if cluster_ssl_tunnel then
+server {
+ listen unix:${{SOCKET_PATH}}/${{CLUSTER_PROXY_SSL_TERMINATOR_SOCK}};
+
+ proxy_pass ${{cluster_ssl_tunnel}};
+ proxy_ssl on;
+ # as we are essentially talking in HTTPS, passing SNI should default turned on
+ proxy_ssl_server_name on;
+> if proxy_server_ssl_verify then
+ proxy_ssl_verify on;
+> if lua_ssl_trusted_certificate_combined then
+ proxy_ssl_trusted_certificate '${{LUA_SSL_TRUSTED_CERTIFICATE_COMBINED}}';
+> end
+ proxy_ssl_verify_depth 5; # 5 should be sufficient
+> else
+ proxy_ssl_verify off;
+> end
+ proxy_socket_keepalive on;
+}
+> end -- cluster_ssl_tunnel
+]]
diff --git a/kong-versions/3.9.0.0/kong/spec/fixtures/template_inject/nginx_kong_test_tcp_echo_server_custom_inject_stream.lua b/kong-versions/3.9.0.0/kong/spec/fixtures/template_inject/nginx_kong_test_tcp_echo_server_custom_inject_stream.lua
new file mode 100644
index 00000000..2479a426
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/fixtures/template_inject/nginx_kong_test_tcp_echo_server_custom_inject_stream.lua
@@ -0,0 +1,30 @@
+-- This software is copyright Kong Inc. and its licensors.
+-- Use of the software is subject to the agreement between your organization
+-- and Kong Inc. If there is no such agreement, use is governed by and
+-- subject to the terms of the Kong Master Software License Agreement found
+-- at https://konghq.com/enterprisesoftwarelicense/.
+-- [ END OF LICENSE 0867164ffc95e54f04670b5169c09574bdbd9bba ]
+
+return [[
+server {
+ listen 8188;
+ listen 8189 ssl;
+
+> for i = 1, #ssl_cert do
+ ssl_certificate $(ssl_cert[i]);
+ ssl_certificate_key $(ssl_cert_key[i]);
+> end
+ ssl_protocols TLSv1.2 TLSv1.3;
+
+ content_by_lua_block {
+ local sock = assert(ngx.req.socket())
+ local data = sock:receive() -- read a line from downstream
+ if data then
+ sock:send(data.."\n") -- echo whatever was sent
+ ngx.log(ngx.INFO, "received data: " .. data)
+ else
+ ngx.log(ngx.WARN, "Nothing received")
+ end
+ }
+}
+]]
diff --git a/kong-versions/3.9.0.0/kong/spec/fixtures/tls-handshake-modifier/bad_client.crt b/kong-versions/3.9.0.0/kong/spec/fixtures/tls-handshake-modifier/bad_client.crt
new file mode 100644
index 00000000..3f43c148
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/fixtures/tls-handshake-modifier/bad_client.crt
@@ -0,0 +1,26 @@
+openssl req -new -newkey rsa:2048 -days 3650 -nodes -x509 -keyout spec/fixtures/bad_client.key -out spec/fixtures/bad_client.crt -subj '/C=US/ST=California/L=San Francisco/O=Kong Inc/OU=Kong Inc/CN=test.com/emailAddress=test@test.test/'
+
+-----BEGIN CERTIFICATE-----
+MIIEBzCCAu+gAwIBAgIUEBt2Elq2RETO+maonV9goQDotrEwDQYJKoZIhvcNAQEL
+BQAwgZIxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRYwFAYDVQQH
+DA1TYW4gRnJhbmNpc2NvMREwDwYDVQQKDAhLb25nIEluYzERMA8GA1UECwwIS29u
+ZyBJbmMxETAPBgNVBAMMCHRlc3QuY29tMR0wGwYJKoZIhvcNAQkBFg50ZXN0QHRl
+c3QudGVzdDAeFw0yNDAxMDkwMzAzNTVaFw0zNDAxMDYwMzAzNTVaMIGSMQswCQYD
+VQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNU2FuIEZyYW5j
+aXNjbzERMA8GA1UECgwIS29uZyBJbmMxETAPBgNVBAsMCEtvbmcgSW5jMREwDwYD
+VQQDDAh0ZXN0LmNvbTEdMBsGCSqGSIb3DQEJARYOdGVzdEB0ZXN0LnRlc3QwggEi
+MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCjryLxJf9xMRPXZTkV0S0Lylx7
+FCv/R5KD7p8gvnl+C/jgfZmguuUWhSpqOcmbQyeAS7hHB6p/J1mcCZK0M0hClQIg
+/76Tfc446yMfq8R35QBxb4ziMOBJUxYSc/PGl3jZaW1OqzCYGVMfszi3Nc1WCl5Q
+7cZbf5oPnmkMvKVWq8tlMFkjMekqJhzY3mdikCZY8rhu2ASqDDEYNrYWDPV2WJUa
+y0JnQgbyPu8Mb2idSASmS3eylPirr98/RqiVZ2qRW4qhlk/5iELN0CQ/c/jcLz4/
+MIahnPdBqvJk6heQ3/wIgf6X6hPXsDHZHO4h5zVM+WBdYBy1hQot83S3lOYpAgMB
+AAGjUzBRMB0GA1UdDgQWBBSa8yH5acw8T2Sd1PyiGzlAXBJEOjAfBgNVHSMEGDAW
+gBSa8yH5acw8T2Sd1PyiGzlAXBJEOjAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3
+DQEBCwUAA4IBAQBPSaq+7ZlIsBomQHretkhp/bXgpUmtJHmWY/p0Ct/jzol19QKn
+9Dpi63LWCmt5qXYvr55k8QhCg+wHHpq4NrX1yZxK29mFnTV9ErhyeWBWs3Um+F6D
+QVdJWH9LGwWffE571shyirvLekrqQbt9h1jKB8a4MEg6ZzrbeCU4UcHrXGq8Nouv
+9jkgUttXj80lArisduvqxDCEJLlVEPlVeYt7TGNSbC1bMjqHU7LkrDiLIQ9B62CH
+H+qzk/f5I4yrEwb3vORdojLald3XG+RWZ4IgxqHlYesNvN0kmuWoSv96r9mVrFc2
+xYfbZi1AB9kQjVZtlsUct5NCFVk5/MTvPgpy
+-----END CERTIFICATE-----
diff --git a/kong-versions/3.9.0.0/kong/spec/fixtures/tls-handshake-modifier/bad_client.key b/kong-versions/3.9.0.0/kong/spec/fixtures/tls-handshake-modifier/bad_client.key
new file mode 100644
index 00000000..71b741fa
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/fixtures/tls-handshake-modifier/bad_client.key
@@ -0,0 +1,28 @@
+-----BEGIN PRIVATE KEY-----
+MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCjryLxJf9xMRPX
+ZTkV0S0Lylx7FCv/R5KD7p8gvnl+C/jgfZmguuUWhSpqOcmbQyeAS7hHB6p/J1mc
+CZK0M0hClQIg/76Tfc446yMfq8R35QBxb4ziMOBJUxYSc/PGl3jZaW1OqzCYGVMf
+szi3Nc1WCl5Q7cZbf5oPnmkMvKVWq8tlMFkjMekqJhzY3mdikCZY8rhu2ASqDDEY
+NrYWDPV2WJUay0JnQgbyPu8Mb2idSASmS3eylPirr98/RqiVZ2qRW4qhlk/5iELN
+0CQ/c/jcLz4/MIahnPdBqvJk6heQ3/wIgf6X6hPXsDHZHO4h5zVM+WBdYBy1hQot
+83S3lOYpAgMBAAECggEAGXqK3Iam+x5B5xFhOr1+CYvNAXY5CFpCZY717h7iwnVn
+9BRuSXqja5ym5t9qkQ8kTZrRFcgNCLs9/kVEihBBezu+l8G3ZItSAmzM4YKB6TfC
+7eVd71ze92BGMJvOomcJmgNdzxUOp15UdhFruU5X/BX5FcKCpyjMTl9rcrQaoyGH
+3LiO0l77INChxH3+SBsam+oZh8WEbhtOkbRqocTy+D3FUDW7jTu1VvMEQoBfvivR
+/xAv6E3itY7CwvrHKfFcgX54wAB4U1R+hb/jWxlQ+zHquQhnkbVZGvQhxCzglEXj
+ebiDnuIyVINapJtkOx7eTh4wrqczYKC+DPe5srkOEQKBgQC16OOsJJfMKLeQR1h7
+wvU/5ZsTCaoO/DQM21P9QN86atcxa4jqI4nGbwniFhdy6nub0TYf1vMw8OGg4s7h
+mBEkoywQzSPAC+aQeIhcyPi6bzMAuXM/KWxrlbrD4dOcRlvPmQy/QBOO1VaGYaTg
+RkJGzpt/qRUUemw4lhb6DMwK+wKBgQDmWe0GqO72f6XTm80esnmbSpIY6wI5Cvgc
+rxvlacAIAXt+tCsQFaGAdEZ4MidR6pYzW7y7/YxsmXnzXitNNjSNILw3yQpk3uOI
+QF/gNwZmkIOAzX+ywU85dCE/vHAzl3HxwcThmq2ihQBjGCh/2+atdOsstBhj4Zbc
+bLh6AN/KKwKBgEOEtoSdbG5Nqpx1rsT4/tiBm4Z8bs9zEsq22bzFSFXBdDAWrtHg
+8PFjI3L0Ki3wFIMoKwO0X72JmuWBabJYI/zKR7/QtHVCtYhoBI0T1yYzweWB7+HA
+uUpRX+n2tvlpMAik0RNncBry2lO0iGLqEQ2BADxpALcCHYr/QnX7K/zjAoGAYVqM
+NI5dQEy+lup4DIs9ngYsLN/V9qnOJsFTNug0wq1ttiULNicONK3vwojf2V0d0eLp
+p0IHgTZ0NgkMn/tSxnqZUbJj9DHHVCRw4OAgkmRtT5iKadANXajZDIjlmshc3eIZ
+BYhL7i3r9fWV2EPmAFUzt5b93+jNy6cfaGDKNDUCgYEAiIu32O9htG7kdLMB8Ejs
+O8MIbmRQNN5BUQHS3BBnQWpTsseX/1+MSuba7pO7//tn0zekXbwOxe4lB05JAfcZ
+zQK9Hzfu60oA2TTC6kaAFgHpVe7eJ265uzn12RFol8/NYJofOp3FD80pDLRZY6Ri
+HmiFMd2gGD/DWoJagi6ZMYM=
+-----END PRIVATE KEY-----
diff --git a/kong-versions/3.9.0.0/kong/spec/fixtures/tls-handshake-modifier/client_example.com.crt b/kong-versions/3.9.0.0/kong/spec/fixtures/tls-handshake-modifier/client_example.com.crt
new file mode 100644
index 00000000..71d9e236
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/fixtures/tls-handshake-modifier/client_example.com.crt
@@ -0,0 +1,62 @@
+-----BEGIN CERTIFICATE-----
+MIIFIjCCAwqgAwIBAgICIAEwDQYJKoZIhvcNAQELBQAwYDELMAkGA1UEBhMCVVMx
+EzARBgNVBAgMCkNhbGlmb3JuaWExFTATBgNVBAoMDEtvbmcgVGVzdGluZzElMCMG
+A1UEAwwcS29uZyBUZXN0aW5nIEludGVybWlkaWF0ZSBDQTAeFw0xOTA1MDIyMDAz
+MTFaFw0yOTA0MjgyMDAzMTFaMFMxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxp
+Zm9ybmlhMRUwEwYDVQQKDAxLb25nIFRlc3RpbmcxGDAWBgNVBAMMD2Zvb0BleGFt
+cGxlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJldMxsZHDxA
+RpbSXdIFZiTf8D0dYgsPnsmx5tVjA/zrVBSVBPO9KunaXNm4Z6JWmUwenzFGbzWP
+NLfbLn4khuoczzqSru5XfbyH1HrD0cd5lkf44Dw1/otfIFDBleiR/OWEiAxwS4zi
+xIajNyvLr3gC5dv+F+JuWpW1yVQxybIDQWoI25xpd3+ZkXO+OLkToo+YpuwIDlUj
+6Rkm5kbqoxDpaDihA2bsAqjNG7G+SHthaNyACsQsU/t6BHSWzHumScN0CxJ+TeVH
+fTZklelItZ6YP0B0RQjzvSGA423UgALzqJglGPe8UDjm3BMlg2xhTfnfy1J6Vmbt
+5jx6FOXUARsCAwEAAaOB8jCB7zAJBgNVHRMEAjAAMBEGCWCGSAGG+EIBAQQEAwIF
+oDAzBglghkgBhvhCAQ0EJhYkT3BlblNTTCBHZW5lcmF0ZWQgQ2xpZW50IENlcnRp
+ZmljYXRlMB0GA1UdDgQWBBRTzNOmhGRXaZamxVfnlKXarIOEmDAfBgNVHSMEGDAW
+gBQLDgQOl/htYk8k8DvGb9IKO40RETAOBgNVHQ8BAf8EBAMCBeAwHQYDVR0lBBYw
+FAYIKwYBBQUHAwIGCCsGAQUFBwMEMCsGA1UdEQQkMCKBD2Zvb0BleGFtcGxlLmNv
+bYEPYmFyQGV4YW1wbGUuY29tMA0GCSqGSIb3DQEBCwUAA4ICAQBziDuVjU0I1CwO
+b1Cx2TJpzi3l5FD/ozrMZT6F3EpkJFGZWgXrsXHz/0qKTrsbB2m3/fcyd0lwQ5Lh
+fz8X1HPrwXa3BqZskNu1vOUNiqAYWvQ5gtbpweJ96LzMSYVGLK78NigYTtK+Rgq3
+As5CVfLXDBburrQNGyRTsilCQDNBvIpib0eqg/HJCNDFMPrBzTMPpUutyatfpFH2
+UwTiVBfA14YYDxZaetYWeksy28XH6Uj0ylyz67VHND+gBMmQNLXQHJTIDh8JuIf2
+ec6o4HrtyyuRE3urNQmcPMAokacm4NKw2+og6Rg1VS/pckaSPOlSEmNnKFiXStv+
+AVd77NGriUWDFCmnrFNOPOIS019W0oOk6YMwTUDSa86Ii6skCtBLHmp/cingkTWg
+7KEbdT1uVVPgseC2AFpQ1BWJOjjtyW3GWuxERIhuab9/ckTz6BuIiuK7mfsvPBrn
+BqjZyt9WAx8uaWMS/ZrmIj3fUXefaPtl27jMSsiU5oi2vzFu0xiXJb6Jr7RQxD3O
+XRnycL/chWnp7eVV1TQS+XzZ3ZZQIjckDWX4E+zGo4o9pD1YC0eytbIlSuqYVr/t
+dZmD2gqju3Io9EXPDlRDP2VIX9q1euF9caz1vpLCfV+F8wVPtZe5p6JbNugdgjix
+nDZ2sD2xGXy6/fNG75oHveYo6MREFw==
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIIFmjCCA4KgAwIBAgICEAAwDQYJKoZIhvcNAQELBQAwWDELMAkGA1UEBhMCVVMx
+EzARBgNVBAgMCkNhbGlmb3JuaWExFTATBgNVBAoMDEtvbmcgVGVzdGluZzEdMBsG
+A1UEAwwUS29uZyBUZXN0aW5nIFJvb3QgQ0EwHhcNMTkwNTAyMTk0MDQ4WhcNMjkw
+NDI5MTk0MDQ4WjBgMQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEV
+MBMGA1UECgwMS29uZyBUZXN0aW5nMSUwIwYDVQQDDBxLb25nIFRlc3RpbmcgSW50
+ZXJtaWRpYXRlIENBMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA0dnj
+oHlJmNM94vQnK2FIIQJm9OAVvyMtAAkBKL7Cxt8G062GHDhq6gjQ9enuNQE0l3Vv
+mSAh7N9gNlma6YbRB9VeG54BCuRQwCxveOBiwQvC2qrTzYI34kF/AeflrDOdzuLb
+zj5cLADKXGCbGDtrSPKUwdlkuLs3pRr/YAyIQr7zJtlLz+E0GBYp0GWnLs0FiLSP
+qSBWllC9u8gt2MiKyNlXw+kZ8lofOehCJzfFr6qagVklPw+8IpU6OGmRLFQVwVhp
+zdAJmAGmSo/AGNKGqDdjzC4N2l4uYGH6n2KmY2yxsLBGZgwtLDst3fK4a3Wa5Tj7
+cUwCcGLGtfVTaIXZYbqQ0nGsaYUd/mhx3B3Jk1p3ILZ72nVYowhpj22ipPGal5hp
+ABh1MX3s/B+2ybWyDTtSaspcyhsRQsS6axB3DwLOLRy5Xp/kqEdConCtGCsjgm+U
+FzdupubXK+KIAmTKXDx8OM7Af/K7kLDfFTre40sEB6fwrWwH8yFojeqkA/Uqhn5S
+CzB0o4F3ON0xajsw2dRCziiq7pSe6ALLXetKpBr+xnVbUswH6BANUoDvh9thVPPx
+1trkv+OuoJalkruZaT+38+iV9xwdqxnR7PUawqSyvrEAxjqUo7dDPsEuOpx1DJjO
+XwRJCUjd7Ux913Iks24BqpPhEQz/rZzJLBApRVsCAwEAAaNmMGQwHQYDVR0OBBYE
+FAsOBA6X+G1iTyTwO8Zv0go7jRERMB8GA1UdIwQYMBaAFAdP8giF4QLaR0HEj9N8
+apTFYnD3MBIGA1UdEwEB/wQIMAYBAf8CAQAwDgYDVR0PAQH/BAQDAgGGMA0GCSqG
+SIb3DQEBCwUAA4ICAQAWzIvIVM32iurqM451Amz0HNDG9j84cORnnaRR5opFTr3P
+EqI3QkgCyP6YOs9t0QSbA4ur9WUzd3c9Ktj3qRRgTE+98JBOPO0rv+Kjj48aANDV
+5tcbI9TZ9ap6g0jYr4XNT+KOO7E8QYlpY/wtokudCUDJE9vrsp1on4Bal2gjvCdh
+SU0C1lnj6q6kBdQSYHrcjiEIGJH21ayVoNaBVP/fxyCHz472w1xN220dxUI/GqB6
+pjcuy9cHjJHJKJbrkdt2eDRAFP5cILXc3mzUoGUDHY2JA1gtOHV0p4ix9R9AfI9x
+snBEFiD8oIpcQay8MJH/z3NLEPLoBW+JaAAs89P+jcppea5N9vbiAkrPi687BFTP
+PWPdstyttw6KrvtPQR1+FsVFcGeTjo32/UrckJixdiOEZgHk+deXpp7JoRdcsgzD
++okrsG79/LgS4icLmzNEp0IV36QckEq0+ALKDu6BXvWTkb5DB/FUrovZKJgkYeWj
+GKogyrPIXrYi725Ff306124kLbxiA+6iBbKUtCutQnvut78puC6iP+a2SrfsbUJ4
+qpvBFOY29Mlww88oWNGTA8QeW84Y1EJbRkHavzSsMFB73sxidQW0cHNC5t9RCKAQ
+uibeZgK1Yk7YQKXdvbZvXwrgTcAjCdbppw2L6e0Uy+OGgNjnIps8K460SdaIiA==
+-----END CERTIFICATE-----
diff --git a/kong-versions/3.9.0.0/kong/spec/fixtures/tls-handshake-modifier/client_example.com.key b/kong-versions/3.9.0.0/kong/spec/fixtures/tls-handshake-modifier/client_example.com.key
new file mode 100644
index 00000000..fb823431
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/fixtures/tls-handshake-modifier/client_example.com.key
@@ -0,0 +1,27 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIEpgIBAAKCAQEAmV0zGxkcPEBGltJd0gVmJN/wPR1iCw+eybHm1WMD/OtUFJUE
+870q6dpc2bhnolaZTB6fMUZvNY80t9sufiSG6hzPOpKu7ld9vIfUesPRx3mWR/jg
+PDX+i18gUMGV6JH85YSIDHBLjOLEhqM3K8uveALl2/4X4m5albXJVDHJsgNBagjb
+nGl3f5mRc744uROij5im7AgOVSPpGSbmRuqjEOloOKEDZuwCqM0bsb5Ie2Fo3IAK
+xCxT+3oEdJbMe6ZJw3QLEn5N5Ud9NmSV6Ui1npg/QHRFCPO9IYDjbdSAAvOomCUY
+97xQOObcEyWDbGFN+d/LUnpWZu3mPHoU5dQBGwIDAQABAoIBAQCLqQzeM3q7/4iI
+1l+r31DKacgbz4M2MW5XnJNqZTX/f8pcx+vvjqfiuADwH/b4JcaKRCSSOeMSMiw+
+9fGb2+WkksHARE3bLH+LTWKYvXRvI/FP73s8Oato/iKuh+vdE/zqgktmkGisjuGK
+/l1Cm8VaE8GBGh5kDDyfsyD5dDGJ0fYzJkfQqygd5B5TSaWflQsB//AXvHzkNy+G
+RHbrMl7t9rDCTtwnefSEJIEwAZerGKV0p+VlRy23mQLwxTxJ5jEjVvcFIMalnD4R
+nKaZYb3LgkCCTQ5Lw/xrkdAEJwfafhdu1CmvKelv1qpcz1vJdrFSfX5NOYS/93jI
+aKJT8Nm5AoGBAMmOOUTvbUd9nlbZXYGLTsoy+qA+OhLkB59krddH4mFoRvbggD6U
+Y/h7O/fA4spqtts+aVoEh/jyuwGTxMn0NPLjD0G8YZr1A4GUx1hgEQ1NIWvRlXrX
+s1bgIlaOc14hOpKf0to3mIovyhRm8PaDbQfHWfyl4yKtFgKiO4OCMK0/AoGBAMLK
+e9C5sedDKt8ESycaXnui1hA4WQkeMdXFflnabuhE29dkC7kDFEVurlmsQb3zFa0V
+dF40niT7xYqzdEJIbaZ3JZIrSFhnPSSBna+B1FjMhTVb/5sjPJS87BvjVYiZd5GY
+5Az4RgSlU3PlsaiuR95NH1vDxHXb5GcMs/EfnEklAoGBAIVFe2yve+yXjUkT9RYh
+TPm596pZOwEeskOcyK3epDuQPcwj6eh3Khs1MRPDALKjGUGi5PpWoKnlpe2HDcoT
+pacsp/vpWgiiFa1q+NzguKW46G5oaJSPZ8/75/ifvHzzL82fzEXqGPzWWKJg5te5
+UzCfikraTXOySyl2qC9uuEz1AoGBAILH8eNMmb48YW9EcbS6Ro9Z38EaI+U0SZ9O
+LqvjNS1q9fMiL6CzCYwoaJS6S5VdvMLtsaiCSV9pTtL182uBN2VZf3co6jS4c9ur
+zpQEZe6Mui7+KpodSVJPmXKL6mSBLT8q2IpAsrnxyhr5L5OiF4yQWSqCQMgkr6/k
+XnfYklSlAoGBAKBePjIdBGLy3ckdlTfbuTeO3kp2eZFBDtGzxP515+LcoRfOjd8T
+ZDX/porUMcgbtIF/B4SNso+8D/aHTCg3QAo6nDjFFjUBHhftgy+GP3BFfMvjqou6
+utJFRkc3FvrrkkeWHnyDQrPmAHjar94/xq1k1Vo+KQHQVQOrvtQt6KXK
+-----END RSA PRIVATE KEY-----
diff --git a/kong-versions/3.9.0.0/kong/spec/fixtures/tls-metadata-headers/bad_tls_client.crt b/kong-versions/3.9.0.0/kong/spec/fixtures/tls-metadata-headers/bad_tls_client.crt
new file mode 100644
index 00000000..3f43c148
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/fixtures/tls-metadata-headers/bad_tls_client.crt
@@ -0,0 +1,26 @@
+openssl req -new -newkey rsa:2048 -days 3650 -nodes -x509 -keyout spec/fixtures/bad_client.key -out spec/fixtures/bad_client.crt -subj '/C=US/ST=California/L=San Francisco/O=Kong Inc/OU=Kong Inc/CN=test.com/emailAddress=test@test.test/'
+
+-----BEGIN CERTIFICATE-----
+MIIEBzCCAu+gAwIBAgIUEBt2Elq2RETO+maonV9goQDotrEwDQYJKoZIhvcNAQEL
+BQAwgZIxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRYwFAYDVQQH
+DA1TYW4gRnJhbmNpc2NvMREwDwYDVQQKDAhLb25nIEluYzERMA8GA1UECwwIS29u
+ZyBJbmMxETAPBgNVBAMMCHRlc3QuY29tMR0wGwYJKoZIhvcNAQkBFg50ZXN0QHRl
+c3QudGVzdDAeFw0yNDAxMDkwMzAzNTVaFw0zNDAxMDYwMzAzNTVaMIGSMQswCQYD
+VQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNU2FuIEZyYW5j
+aXNjbzERMA8GA1UECgwIS29uZyBJbmMxETAPBgNVBAsMCEtvbmcgSW5jMREwDwYD
+VQQDDAh0ZXN0LmNvbTEdMBsGCSqGSIb3DQEJARYOdGVzdEB0ZXN0LnRlc3QwggEi
+MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCjryLxJf9xMRPXZTkV0S0Lylx7
+FCv/R5KD7p8gvnl+C/jgfZmguuUWhSpqOcmbQyeAS7hHB6p/J1mcCZK0M0hClQIg
+/76Tfc446yMfq8R35QBxb4ziMOBJUxYSc/PGl3jZaW1OqzCYGVMfszi3Nc1WCl5Q
+7cZbf5oPnmkMvKVWq8tlMFkjMekqJhzY3mdikCZY8rhu2ASqDDEYNrYWDPV2WJUa
+y0JnQgbyPu8Mb2idSASmS3eylPirr98/RqiVZ2qRW4qhlk/5iELN0CQ/c/jcLz4/
+MIahnPdBqvJk6heQ3/wIgf6X6hPXsDHZHO4h5zVM+WBdYBy1hQot83S3lOYpAgMB
+AAGjUzBRMB0GA1UdDgQWBBSa8yH5acw8T2Sd1PyiGzlAXBJEOjAfBgNVHSMEGDAW
+gBSa8yH5acw8T2Sd1PyiGzlAXBJEOjAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3
+DQEBCwUAA4IBAQBPSaq+7ZlIsBomQHretkhp/bXgpUmtJHmWY/p0Ct/jzol19QKn
+9Dpi63LWCmt5qXYvr55k8QhCg+wHHpq4NrX1yZxK29mFnTV9ErhyeWBWs3Um+F6D
+QVdJWH9LGwWffE571shyirvLekrqQbt9h1jKB8a4MEg6ZzrbeCU4UcHrXGq8Nouv
+9jkgUttXj80lArisduvqxDCEJLlVEPlVeYt7TGNSbC1bMjqHU7LkrDiLIQ9B62CH
+H+qzk/f5I4yrEwb3vORdojLald3XG+RWZ4IgxqHlYesNvN0kmuWoSv96r9mVrFc2
+xYfbZi1AB9kQjVZtlsUct5NCFVk5/MTvPgpy
+-----END CERTIFICATE-----
diff --git a/kong-versions/3.9.0.0/kong/spec/fixtures/tls-metadata-headers/bad_tls_client.key b/kong-versions/3.9.0.0/kong/spec/fixtures/tls-metadata-headers/bad_tls_client.key
new file mode 100644
index 00000000..71b741fa
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/fixtures/tls-metadata-headers/bad_tls_client.key
@@ -0,0 +1,28 @@
+-----BEGIN PRIVATE KEY-----
+MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCjryLxJf9xMRPX
+ZTkV0S0Lylx7FCv/R5KD7p8gvnl+C/jgfZmguuUWhSpqOcmbQyeAS7hHB6p/J1mc
+CZK0M0hClQIg/76Tfc446yMfq8R35QBxb4ziMOBJUxYSc/PGl3jZaW1OqzCYGVMf
+szi3Nc1WCl5Q7cZbf5oPnmkMvKVWq8tlMFkjMekqJhzY3mdikCZY8rhu2ASqDDEY
+NrYWDPV2WJUay0JnQgbyPu8Mb2idSASmS3eylPirr98/RqiVZ2qRW4qhlk/5iELN
+0CQ/c/jcLz4/MIahnPdBqvJk6heQ3/wIgf6X6hPXsDHZHO4h5zVM+WBdYBy1hQot
+83S3lOYpAgMBAAECggEAGXqK3Iam+x5B5xFhOr1+CYvNAXY5CFpCZY717h7iwnVn
+9BRuSXqja5ym5t9qkQ8kTZrRFcgNCLs9/kVEihBBezu+l8G3ZItSAmzM4YKB6TfC
+7eVd71ze92BGMJvOomcJmgNdzxUOp15UdhFruU5X/BX5FcKCpyjMTl9rcrQaoyGH
+3LiO0l77INChxH3+SBsam+oZh8WEbhtOkbRqocTy+D3FUDW7jTu1VvMEQoBfvivR
+/xAv6E3itY7CwvrHKfFcgX54wAB4U1R+hb/jWxlQ+zHquQhnkbVZGvQhxCzglEXj
+ebiDnuIyVINapJtkOx7eTh4wrqczYKC+DPe5srkOEQKBgQC16OOsJJfMKLeQR1h7
+wvU/5ZsTCaoO/DQM21P9QN86atcxa4jqI4nGbwniFhdy6nub0TYf1vMw8OGg4s7h
+mBEkoywQzSPAC+aQeIhcyPi6bzMAuXM/KWxrlbrD4dOcRlvPmQy/QBOO1VaGYaTg
+RkJGzpt/qRUUemw4lhb6DMwK+wKBgQDmWe0GqO72f6XTm80esnmbSpIY6wI5Cvgc
+rxvlacAIAXt+tCsQFaGAdEZ4MidR6pYzW7y7/YxsmXnzXitNNjSNILw3yQpk3uOI
+QF/gNwZmkIOAzX+ywU85dCE/vHAzl3HxwcThmq2ihQBjGCh/2+atdOsstBhj4Zbc
+bLh6AN/KKwKBgEOEtoSdbG5Nqpx1rsT4/tiBm4Z8bs9zEsq22bzFSFXBdDAWrtHg
+8PFjI3L0Ki3wFIMoKwO0X72JmuWBabJYI/zKR7/QtHVCtYhoBI0T1yYzweWB7+HA
+uUpRX+n2tvlpMAik0RNncBry2lO0iGLqEQ2BADxpALcCHYr/QnX7K/zjAoGAYVqM
+NI5dQEy+lup4DIs9ngYsLN/V9qnOJsFTNug0wq1ttiULNicONK3vwojf2V0d0eLp
+p0IHgTZ0NgkMn/tSxnqZUbJj9DHHVCRw4OAgkmRtT5iKadANXajZDIjlmshc3eIZ
+BYhL7i3r9fWV2EPmAFUzt5b93+jNy6cfaGDKNDUCgYEAiIu32O9htG7kdLMB8Ejs
+O8MIbmRQNN5BUQHS3BBnQWpTsseX/1+MSuba7pO7//tn0zekXbwOxe4lB05JAfcZ
+zQK9Hzfu60oA2TTC6kaAFgHpVe7eJ265uzn12RFol8/NYJofOp3FD80pDLRZY6Ri
+HmiFMd2gGD/DWoJagi6ZMYM=
+-----END PRIVATE KEY-----
diff --git a/kong-versions/3.9.0.0/kong/spec/fixtures/tls-metadata-headers/ca.crt b/kong-versions/3.9.0.0/kong/spec/fixtures/tls-metadata-headers/ca.crt
new file mode 100644
index 00000000..a60fd5d9
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/fixtures/tls-metadata-headers/ca.crt
@@ -0,0 +1,33 @@
+-----BEGIN CERTIFICATE-----
+MIIFoTCCA4mgAwIBAgIUQDBLwIychoRbVRO44IzBBk9R4oYwDQYJKoZIhvcNAQEL
+BQAwWDELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExFTATBgNVBAoM
+DEtvbmcgVGVzdGluZzEdMBsGA1UEAwwUS29uZyBUZXN0aW5nIFJvb3QgQ0EwHhcN
+MTkwNTAyMTkzNDQyWhcNMzkwNDI3MTkzNDQyWjBYMQswCQYDVQQGEwJVUzETMBEG
+A1UECAwKQ2FsaWZvcm5pYTEVMBMGA1UECgwMS29uZyBUZXN0aW5nMR0wGwYDVQQD
+DBRLb25nIFRlc3RpbmcgUm9vdCBDQTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCC
+AgoCggIBAMp6IggUp3aSNRbLAac8oOkrbUnFuxtlKGYgg8vfA2UU71qTktigdwO6
+Kod0/M+daO3RDqJJXQL2rD14NDO3MaextICanoQSEe+nYyMFUIk+QplXLD3fbshU
+nHoJcMS2w0x4cm1os4ebxR2Evndo6luz39ivcjau+BL+9iBAYL1g6+eGOjcSy7ft
+1nAMvbxcQ7dmbAH2KP6OmF8cok+eQWVqXEjqtVx5GDMDlj1BjX6Kulmh/vhNi3Hr
+NEi+kPrw/YtRgnqnN0sv3NnAyKnantxy7w0TDicFjiBsSIhjB5aUfWYErBR+Nj/m
+uumwc/kRJcHWklqDzxrZKCIyOyWcE5Dyjjr46cnF8HxhYwgZcwkmgTtaXOLpBMlo
+XUTgOQrWpm9HYg2vOJMMA/ZPUJ2tJ34/4RgiA00EJ5xG8r24suZmT775l+XFLFzp
+Ihxvs3BMbrWsXlcZkI5neNk7Q/1jLoBhWeTYjMpUS7bJ/49YVGQZFs3xu2IcLqeD
+5WsB1i+EqBAI0jm4vWEynsyX+kS2BqAiDtCsS6WYT2q00DTeP5eIHh/vHsm75jJ+
+yUEb1xFxGnNevLKNTcHUeXxPUnowdC6wqFnaJm7l09qVGDom7tLX9i6MCojgpAP0
+hMpBxzh8jLxHh+zZQdiORSFdYxNnlnWwbic2GUJruiQVLuhpseenAgMBAAGjYzBh
+MB0GA1UdDgQWBBQHT/IIheEC2kdBxI/TfGqUxWJw9zAfBgNVHSMEGDAWgBQHT/II
+heEC2kdBxI/TfGqUxWJw9zAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIB
+hjANBgkqhkiG9w0BAQsFAAOCAgEAqXZjy4EltJCRtBmN0ohAHPWqH4ZJQCI2HrM3
+wHB6c4oPWcJ+M2PfmYPUJo9VMjvn4S3sZuAysyoHduvRdGDnElW4wglL1xxpoUOx
+FqoZUoYWV8hDFmUTWM5b4CtJxOPdTAd8VgypulM3iUEzBQrjR6tnMOdkiFMOmVag
+0/Nnr+Tcfk/crMCx3xsVnisYjJoQBFBH4UY+gWE/V/MS1Sya4/qTbuuCUq+Qym5P
+r8TkWAJlg7iVVLbZ2j94VUdpiQPWJEGMtJck/NEmOTruhhQlT7c1u/lqXCGj7uci
+LmhLsBVmdtWT9AWS8Rl7Qo5GXbjxKIaP3IM9axhDLm8WHwPRLx7DuIFEc+OBxJhz
+wkr0g0yLS0AMZpaC6UGbWX01ed10U01mQ/qPU5uZiB0GvruwsYWZsyL1QXUeqLz3
+/KKrx3XsXjtBu3ZG4LAnwuxfeZCNw9ofg8CqF9c20ko+7tZAv6DCu9UL+2oZnEyQ
+CboRDwpnAlQ7qJVSp2xMgunO3xxVMlhD5LZpEJz1lRT0nQV3uuLpMYNM4FS9OW/X
+MZSzwHhDdCTDWtc/iRszimOnYYV8Y0ubJcb59uhwcsHmdfnwL9DVO6X5xyzb8wsf
+wWaPbub8SN2jKnT0g6ZWuca4VwEo1fRaBkzSZDqXwhkBDWP8UBqLXMXWHdZaT8NK
+0NEO74c=
+-----END CERTIFICATE-----
\ No newline at end of file
diff --git a/kong-versions/3.9.0.0/kong/spec/fixtures/tls-metadata-headers/client_example.com.crt b/kong-versions/3.9.0.0/kong/spec/fixtures/tls-metadata-headers/client_example.com.crt
new file mode 100644
index 00000000..71d9e236
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/fixtures/tls-metadata-headers/client_example.com.crt
@@ -0,0 +1,62 @@
+-----BEGIN CERTIFICATE-----
+MIIFIjCCAwqgAwIBAgICIAEwDQYJKoZIhvcNAQELBQAwYDELMAkGA1UEBhMCVVMx
+EzARBgNVBAgMCkNhbGlmb3JuaWExFTATBgNVBAoMDEtvbmcgVGVzdGluZzElMCMG
+A1UEAwwcS29uZyBUZXN0aW5nIEludGVybWlkaWF0ZSBDQTAeFw0xOTA1MDIyMDAz
+MTFaFw0yOTA0MjgyMDAzMTFaMFMxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxp
+Zm9ybmlhMRUwEwYDVQQKDAxLb25nIFRlc3RpbmcxGDAWBgNVBAMMD2Zvb0BleGFt
+cGxlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJldMxsZHDxA
+RpbSXdIFZiTf8D0dYgsPnsmx5tVjA/zrVBSVBPO9KunaXNm4Z6JWmUwenzFGbzWP
+NLfbLn4khuoczzqSru5XfbyH1HrD0cd5lkf44Dw1/otfIFDBleiR/OWEiAxwS4zi
+xIajNyvLr3gC5dv+F+JuWpW1yVQxybIDQWoI25xpd3+ZkXO+OLkToo+YpuwIDlUj
+6Rkm5kbqoxDpaDihA2bsAqjNG7G+SHthaNyACsQsU/t6BHSWzHumScN0CxJ+TeVH
+fTZklelItZ6YP0B0RQjzvSGA423UgALzqJglGPe8UDjm3BMlg2xhTfnfy1J6Vmbt
+5jx6FOXUARsCAwEAAaOB8jCB7zAJBgNVHRMEAjAAMBEGCWCGSAGG+EIBAQQEAwIF
+oDAzBglghkgBhvhCAQ0EJhYkT3BlblNTTCBHZW5lcmF0ZWQgQ2xpZW50IENlcnRp
+ZmljYXRlMB0GA1UdDgQWBBRTzNOmhGRXaZamxVfnlKXarIOEmDAfBgNVHSMEGDAW
+gBQLDgQOl/htYk8k8DvGb9IKO40RETAOBgNVHQ8BAf8EBAMCBeAwHQYDVR0lBBYw
+FAYIKwYBBQUHAwIGCCsGAQUFBwMEMCsGA1UdEQQkMCKBD2Zvb0BleGFtcGxlLmNv
+bYEPYmFyQGV4YW1wbGUuY29tMA0GCSqGSIb3DQEBCwUAA4ICAQBziDuVjU0I1CwO
+b1Cx2TJpzi3l5FD/ozrMZT6F3EpkJFGZWgXrsXHz/0qKTrsbB2m3/fcyd0lwQ5Lh
+fz8X1HPrwXa3BqZskNu1vOUNiqAYWvQ5gtbpweJ96LzMSYVGLK78NigYTtK+Rgq3
+As5CVfLXDBburrQNGyRTsilCQDNBvIpib0eqg/HJCNDFMPrBzTMPpUutyatfpFH2
+UwTiVBfA14YYDxZaetYWeksy28XH6Uj0ylyz67VHND+gBMmQNLXQHJTIDh8JuIf2
+ec6o4HrtyyuRE3urNQmcPMAokacm4NKw2+og6Rg1VS/pckaSPOlSEmNnKFiXStv+
+AVd77NGriUWDFCmnrFNOPOIS019W0oOk6YMwTUDSa86Ii6skCtBLHmp/cingkTWg
+7KEbdT1uVVPgseC2AFpQ1BWJOjjtyW3GWuxERIhuab9/ckTz6BuIiuK7mfsvPBrn
+BqjZyt9WAx8uaWMS/ZrmIj3fUXefaPtl27jMSsiU5oi2vzFu0xiXJb6Jr7RQxD3O
+XRnycL/chWnp7eVV1TQS+XzZ3ZZQIjckDWX4E+zGo4o9pD1YC0eytbIlSuqYVr/t
+dZmD2gqju3Io9EXPDlRDP2VIX9q1euF9caz1vpLCfV+F8wVPtZe5p6JbNugdgjix
+nDZ2sD2xGXy6/fNG75oHveYo6MREFw==
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIIFmjCCA4KgAwIBAgICEAAwDQYJKoZIhvcNAQELBQAwWDELMAkGA1UEBhMCVVMx
+EzARBgNVBAgMCkNhbGlmb3JuaWExFTATBgNVBAoMDEtvbmcgVGVzdGluZzEdMBsG
+A1UEAwwUS29uZyBUZXN0aW5nIFJvb3QgQ0EwHhcNMTkwNTAyMTk0MDQ4WhcNMjkw
+NDI5MTk0MDQ4WjBgMQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEV
+MBMGA1UECgwMS29uZyBUZXN0aW5nMSUwIwYDVQQDDBxLb25nIFRlc3RpbmcgSW50
+ZXJtaWRpYXRlIENBMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA0dnj
+oHlJmNM94vQnK2FIIQJm9OAVvyMtAAkBKL7Cxt8G062GHDhq6gjQ9enuNQE0l3Vv
+mSAh7N9gNlma6YbRB9VeG54BCuRQwCxveOBiwQvC2qrTzYI34kF/AeflrDOdzuLb
+zj5cLADKXGCbGDtrSPKUwdlkuLs3pRr/YAyIQr7zJtlLz+E0GBYp0GWnLs0FiLSP
+qSBWllC9u8gt2MiKyNlXw+kZ8lofOehCJzfFr6qagVklPw+8IpU6OGmRLFQVwVhp
+zdAJmAGmSo/AGNKGqDdjzC4N2l4uYGH6n2KmY2yxsLBGZgwtLDst3fK4a3Wa5Tj7
+cUwCcGLGtfVTaIXZYbqQ0nGsaYUd/mhx3B3Jk1p3ILZ72nVYowhpj22ipPGal5hp
+ABh1MX3s/B+2ybWyDTtSaspcyhsRQsS6axB3DwLOLRy5Xp/kqEdConCtGCsjgm+U
+FzdupubXK+KIAmTKXDx8OM7Af/K7kLDfFTre40sEB6fwrWwH8yFojeqkA/Uqhn5S
+CzB0o4F3ON0xajsw2dRCziiq7pSe6ALLXetKpBr+xnVbUswH6BANUoDvh9thVPPx
+1trkv+OuoJalkruZaT+38+iV9xwdqxnR7PUawqSyvrEAxjqUo7dDPsEuOpx1DJjO
+XwRJCUjd7Ux913Iks24BqpPhEQz/rZzJLBApRVsCAwEAAaNmMGQwHQYDVR0OBBYE
+FAsOBA6X+G1iTyTwO8Zv0go7jRERMB8GA1UdIwQYMBaAFAdP8giF4QLaR0HEj9N8
+apTFYnD3MBIGA1UdEwEB/wQIMAYBAf8CAQAwDgYDVR0PAQH/BAQDAgGGMA0GCSqG
+SIb3DQEBCwUAA4ICAQAWzIvIVM32iurqM451Amz0HNDG9j84cORnnaRR5opFTr3P
+EqI3QkgCyP6YOs9t0QSbA4ur9WUzd3c9Ktj3qRRgTE+98JBOPO0rv+Kjj48aANDV
+5tcbI9TZ9ap6g0jYr4XNT+KOO7E8QYlpY/wtokudCUDJE9vrsp1on4Bal2gjvCdh
+SU0C1lnj6q6kBdQSYHrcjiEIGJH21ayVoNaBVP/fxyCHz472w1xN220dxUI/GqB6
+pjcuy9cHjJHJKJbrkdt2eDRAFP5cILXc3mzUoGUDHY2JA1gtOHV0p4ix9R9AfI9x
+snBEFiD8oIpcQay8MJH/z3NLEPLoBW+JaAAs89P+jcppea5N9vbiAkrPi687BFTP
+PWPdstyttw6KrvtPQR1+FsVFcGeTjo32/UrckJixdiOEZgHk+deXpp7JoRdcsgzD
++okrsG79/LgS4icLmzNEp0IV36QckEq0+ALKDu6BXvWTkb5DB/FUrovZKJgkYeWj
+GKogyrPIXrYi725Ff306124kLbxiA+6iBbKUtCutQnvut78puC6iP+a2SrfsbUJ4
+qpvBFOY29Mlww88oWNGTA8QeW84Y1EJbRkHavzSsMFB73sxidQW0cHNC5t9RCKAQ
+uibeZgK1Yk7YQKXdvbZvXwrgTcAjCdbppw2L6e0Uy+OGgNjnIps8K460SdaIiA==
+-----END CERTIFICATE-----
diff --git a/kong-versions/3.9.0.0/kong/spec/fixtures/tls-metadata-headers/client_example.com.key b/kong-versions/3.9.0.0/kong/spec/fixtures/tls-metadata-headers/client_example.com.key
new file mode 100644
index 00000000..fb823431
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/fixtures/tls-metadata-headers/client_example.com.key
@@ -0,0 +1,27 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIEpgIBAAKCAQEAmV0zGxkcPEBGltJd0gVmJN/wPR1iCw+eybHm1WMD/OtUFJUE
+870q6dpc2bhnolaZTB6fMUZvNY80t9sufiSG6hzPOpKu7ld9vIfUesPRx3mWR/jg
+PDX+i18gUMGV6JH85YSIDHBLjOLEhqM3K8uveALl2/4X4m5albXJVDHJsgNBagjb
+nGl3f5mRc744uROij5im7AgOVSPpGSbmRuqjEOloOKEDZuwCqM0bsb5Ie2Fo3IAK
+xCxT+3oEdJbMe6ZJw3QLEn5N5Ud9NmSV6Ui1npg/QHRFCPO9IYDjbdSAAvOomCUY
+97xQOObcEyWDbGFN+d/LUnpWZu3mPHoU5dQBGwIDAQABAoIBAQCLqQzeM3q7/4iI
+1l+r31DKacgbz4M2MW5XnJNqZTX/f8pcx+vvjqfiuADwH/b4JcaKRCSSOeMSMiw+
+9fGb2+WkksHARE3bLH+LTWKYvXRvI/FP73s8Oato/iKuh+vdE/zqgktmkGisjuGK
+/l1Cm8VaE8GBGh5kDDyfsyD5dDGJ0fYzJkfQqygd5B5TSaWflQsB//AXvHzkNy+G
+RHbrMl7t9rDCTtwnefSEJIEwAZerGKV0p+VlRy23mQLwxTxJ5jEjVvcFIMalnD4R
+nKaZYb3LgkCCTQ5Lw/xrkdAEJwfafhdu1CmvKelv1qpcz1vJdrFSfX5NOYS/93jI
+aKJT8Nm5AoGBAMmOOUTvbUd9nlbZXYGLTsoy+qA+OhLkB59krddH4mFoRvbggD6U
+Y/h7O/fA4spqtts+aVoEh/jyuwGTxMn0NPLjD0G8YZr1A4GUx1hgEQ1NIWvRlXrX
+s1bgIlaOc14hOpKf0to3mIovyhRm8PaDbQfHWfyl4yKtFgKiO4OCMK0/AoGBAMLK
+e9C5sedDKt8ESycaXnui1hA4WQkeMdXFflnabuhE29dkC7kDFEVurlmsQb3zFa0V
+dF40niT7xYqzdEJIbaZ3JZIrSFhnPSSBna+B1FjMhTVb/5sjPJS87BvjVYiZd5GY
+5Az4RgSlU3PlsaiuR95NH1vDxHXb5GcMs/EfnEklAoGBAIVFe2yve+yXjUkT9RYh
+TPm596pZOwEeskOcyK3epDuQPcwj6eh3Khs1MRPDALKjGUGi5PpWoKnlpe2HDcoT
+pacsp/vpWgiiFa1q+NzguKW46G5oaJSPZ8/75/ifvHzzL82fzEXqGPzWWKJg5te5
+UzCfikraTXOySyl2qC9uuEz1AoGBAILH8eNMmb48YW9EcbS6Ro9Z38EaI+U0SZ9O
+LqvjNS1q9fMiL6CzCYwoaJS6S5VdvMLtsaiCSV9pTtL182uBN2VZf3co6jS4c9ur
+zpQEZe6Mui7+KpodSVJPmXKL6mSBLT8q2IpAsrnxyhr5L5OiF4yQWSqCQMgkr6/k
+XnfYklSlAoGBAKBePjIdBGLy3ckdlTfbuTeO3kp2eZFBDtGzxP515+LcoRfOjd8T
+ZDX/porUMcgbtIF/B4SNso+8D/aHTCg3QAo6nDjFFjUBHhftgy+GP3BFfMvjqou6
+utJFRkc3FvrrkkeWHnyDQrPmAHjar94/xq1k1Vo+KQHQVQOrvtQt6KXK
+-----END RSA PRIVATE KEY-----
diff --git a/kong-versions/3.9.0.0/kong/spec/fixtures/tls-metadata-headers/client_example_validated.com.crt b/kong-versions/3.9.0.0/kong/spec/fixtures/tls-metadata-headers/client_example_validated.com.crt
new file mode 100644
index 00000000..6fafa161
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/fixtures/tls-metadata-headers/client_example_validated.com.crt
@@ -0,0 +1,30 @@
+-----BEGIN CERTIFICATE-----
+MIIFIjCCAwqgAwIBAgICIAEwDQYJKoZIhvcNAQELBQAwYDELMAkGA1UEBhMCVVMx
+EzARBgNVBAgMCkNhbGlmb3JuaWExFTATBgNVBAoMDEtvbmcgVGVzdGluZzElMCMG
+A1UEAwwcS29uZyBUZXN0aW5nIEludGVybWlkaWF0ZSBDQTAeFw0xOTA1MDIyMDAz
+MTFaFw0yOTA0MjgyMDAzMTFaMFMxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxp
+Zm9ybmlhMRUwEwYDVQQKDAxLb25nIFRlc3RpbmcxGDAWBgNVBAMMD2Zvb0BleGFt
+cGxlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJldMxsZHDxA
+RpbSXdIFZiTf8D0dYgsPnsmx5tVjA/zrVBSVBPO9KunaXNm4Z6JWmUwenzFGbzWP
+NLfbLn4khuoczzqSru5XfbyH1HrD0cd5lkf44Dw1/otfIFDBleiR/OWEiAxwS4zi
+xIajNyvLr3gC5dv+F+JuWpW1yVQxybIDQWoI25xpd3+ZkXO+OLkToo+YpuwIDlUj
+6Rkm5kbqoxDpaDihA2bsAqjNG7G+SHthaNyACsQsU/t6BHSWzHumScN0CxJ+TeVH
+fTZklelItZ6YP0B0RQjzvSGA423UgALzqJglGPe8UDjm3BMlg2xhTfnfy1J6Vmbt
+5jx6FOXUARsCAwEAAaOB8jCB7zAJBgNVHRMEAjAAMBEGCWCGSAGG+EIBAQQEAwIF
+oDAzBglghkgBhvhCAQ0EJhYkT3BlblNTTCBHZW5lcmF0ZWQgQ2xpZW50IENlcnRp
+ZmljYXRlMB0GA1UdDgQWBBRTzNOmhGRXaZamxVfnlKXarIOEmDAfBgNVHSMEGDAW
+gBQLDgQOl/htYk8k8DvGb9IKO40RETAOBgNVHQ8BAf8EBAMCBeAwHQYDVR0lBBYw
+FAYIKwYBBQUHAwIGCCsGAQUFBwMEMCsGA1UdEQQkMCKBD2Zvb0BleGFtcGxlLmNv
+bYEPYmFyQGV4YW1wbGUuY29tMA0GCSqGSIb3DQEBCwUAA4ICAQBziDuVjU0I1CwO
+b1Cx2TJpzi3l5FD/ozrMZT6F3EpkJFGZWgXrsXHz/0qKTrsbB2m3/fcyd0lwQ5Lh
+fz8X1HPrwXa3BqZskNu1vOUNiqAYWvQ5gtbpweJ96LzMSYVGLK78NigYTtK+Rgq3
+As5CVfLXDBburrQNGyRTsilCQDNBvIpib0eqg/HJCNDFMPrBzTMPpUutyatfpFH2
+UwTiVBfA14YYDxZaetYWeksy28XH6Uj0ylyz67VHND+gBMmQNLXQHJTIDh8JuIf2
+ec6o4HrtyyuRE3urNQmcPMAokacm4NKw2+og6Rg1VS/pckaSPOlSEmNnKFiXStv+
+AVd77NGriUWDFCmnrFNOPOIS019W0oOk6YMwTUDSa86Ii6skCtBLHmp/cingkTWg
+7KEbdT1uVVPgseC2AFpQ1BWJOjjtyW3GWuxERIhuab9/ckTz6BuIiuK7mfsvPBrn
+BqjZyt9WAx8uaWMS/ZrmIj3fUXefaPtl27jMSsiU5oi2vzFu0xiXJb6Jr7RQxD3O
+XRnycL/chWnp7eVV1TQS+XzZ3ZZQIjckDWX4E+zGo4o9pD1YC0eytbIlSuqYVr/t
+dZmD2gqju3Io9EXPDlRDP2VIX9q1euF9caz1vpLCfV+F8wVPtZe5p6JbNugdgjix
+nDZ2sD2xGXy6/fNG75oHveYo6MREFw==
+-----END CERTIFICATE-----
diff --git a/kong-versions/3.9.0.0/kong/spec/fixtures/tls-metadata-headers/good_tls_client.crt b/kong-versions/3.9.0.0/kong/spec/fixtures/tls-metadata-headers/good_tls_client.crt
new file mode 100644
index 00000000..af214d21
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/fixtures/tls-metadata-headers/good_tls_client.crt
@@ -0,0 +1,31 @@
+-----BEGIN CERTIFICATE-----
+MIIFQDCCAygCAWUwDQYJKoZIhvcNAQEFBQAwZjELMAkGA1UEBhMCQVUxDDAKBgNV
+BAgMA05TVzEPMA0GA1UEBwwGU3lkbmV5MQ0wCwYDVQQKDARLb25nMQswCQYDVQQL
+DAJQUzEcMBoGCSqGSIb3DQEJARYNdGVzdEB0ZXN0LmNvbTAeFw0yMDA2MTAyMzIx
+MThaFw0yMTA2MTAyMzIxMThaMGYxCzAJBgNVBAYTAkFVMQwwCgYDVQQIDANOU1cx
+DzANBgNVBAcMBlN5ZG5leTENMAsGA1UECgwES29uZzELMAkGA1UECwwCUFMxHDAa
+BgkqhkiG9w0BCQEWDXRlc3RAdGVzdC5jb20wggIiMA0GCSqGSIb3DQEBAQUAA4IC
+DwAwggIKAoICAQDH1JuwgFDvXpLA0kXhFoDhM/Ip7J3GVwkulSyamKbTvfNTcV7B
+fCCwwyP++XLZ7E6k3POnQwtUv6oDT7TldmutgZvlVfc9hUnMhoe2PEL6qbDZbzto
+UE7GDgpASHIbNTeU8AvZY9cCaFg9aF3gK36NSOAmBXMXsISN28MiVcxFZlgpZfpk
+LIAvtaUXD6TMxpC2H5DCcVDlv7ikcwpoN5lhTP3WtpuGN8IIA8euf0Bsqr+UfWtS
+gcOPWFBipY1aOuzSZ/VacHxyiPfM7pMhp3O3Cbuqf5hhadtDGCq8ZeBORBpJyfXh
+hPx3j/jWtapinQO0Sl+4ODZA/0/41d8+sh5ZPuNzsDNzufiH1PQkJuDcLa1DivTM
+sHD1NYFQpBLKZU9F6Vr7Pu6ntckW/iRfXZCQuYusBzk2xGquuMd4LqLmTstXsgDy
+iYoeAF4JsypsPLorJrmR/64d3urNTUeiZfXvAwV3sFLxJg8eekdEVXSGIVl7wmDZ
+2guYq6jG33dvmyq6U7Rbtpi4qWJdMOclboU7p6C06T8FPvyDMZUolJ3fghN7HIHZ
+G4PDDQXTjCtG2MAY1wwxnLj5RI0iLt8RA15p+NkdWwuWCb/YA03hb4vafjk+fqgj
+JqC/wI2d/FLCqhET1qqHXB/wMKCpVra+aBuDB1QIdK3CbHPUNpoqcMreVwIDAQAB
+MA0GCSqGSIb3DQEBBQUAA4ICAQBPv3626lgITncOD5qM8t0NIqamJMKFGh0VQUHY
+IBO9weGbczyP72ZzXwxTKinCHirVLRiGjItrD4zAPDuMsQ1NCMHjmytXlS0jnuMw
+i2xWtcXoKuOlA2Y/AzU9s/SkZNTUgnZBVCbPp8q+ezJCtODgY1x0xDS6KJgWCCTQ
+YVTt4vFyfWGTJYS9cgeYI/q8znZOs8slRwgSI063ICD5TyHQeQWDqTsYAssVaMt6
+amiNKx1DKEgIbgTOEqUzYeZpBqNL/pRxkHB9PAbUE57+n3zSBKmxXQfmAoCDGGhy
+IPmYqh3FJFx98iud//O5awC4184A7eGyC+nVapv23yXaQHoEeH7huiNJwucml3Ja
+L2AY0VeEmj1HKYbwh4SV6CVjgTv002tiDjId04nf4DLL6hU+YjBsg9z6K1ZXrIUB
+WX9UIpPlXv3N3Uq+R+1sidfYNwOcAy5VLbj+mwN2uHdCH2DFkvo9W5abCMaxLlKh
+tH3V9xijK54Ph79ySkgyjC20o+KsL+ZJR75fniTjn716m+uJys4B+BWGJCgDzi1X
+pRGnW6Yj1IAErPRtKQU3FRG7frNrpRPTt/F8tPTPBqi2bSeMaCn2X2u0gVDo7FhX
+pkh6xnPZ/qHUXwDqjngDinNQ8zTMgxt/sv84zabDAf67ZkAyYriQx8H6kWULgcou
+1h+bNg==
+-----END CERTIFICATE-----
diff --git a/kong-versions/3.9.0.0/kong/spec/fixtures/tls-metadata-headers/good_tls_client.key b/kong-versions/3.9.0.0/kong/spec/fixtures/tls-metadata-headers/good_tls_client.key
new file mode 100644
index 00000000..ae247909
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/fixtures/tls-metadata-headers/good_tls_client.key
@@ -0,0 +1,51 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIJKAIBAAKCAgEAx9SbsIBQ716SwNJF4RaA4TPyKeydxlcJLpUsmpim073zU3Fe
+wXwgsMMj/vly2exOpNzzp0MLVL+qA0+05XZrrYGb5VX3PYVJzIaHtjxC+qmw2W87
+aFBOxg4KQEhyGzU3lPAL2WPXAmhYPWhd4Ct+jUjgJgVzF7CEjdvDIlXMRWZYKWX6
+ZCyAL7WlFw+kzMaQth+QwnFQ5b+4pHMKaDeZYUz91rabhjfCCAPHrn9AbKq/lH1r
+UoHDj1hQYqWNWjrs0mf1WnB8coj3zO6TIadztwm7qn+YYWnbQxgqvGXgTkQaScn1
+4YT8d4/41rWqYp0DtEpfuDg2QP9P+NXfPrIeWT7jc7Azc7n4h9T0JCbg3C2tQ4r0
+zLBw9TWBUKQSymVPRela+z7up7XJFv4kX12QkLmLrAc5NsRqrrjHeC6i5k7LV7IA
+8omKHgBeCbMqbDy6Kya5kf+uHd7qzU1HomX17wMFd7BS8SYPHnpHRFV0hiFZe8Jg
+2doLmKuoxt93b5squlO0W7aYuKliXTDnJW6FO6egtOk/BT78gzGVKJSd34ITexyB
+2RuDww0F04wrRtjAGNcMMZy4+USNIi7fEQNeafjZHVsLlgm/2ANN4W+L2n45Pn6o
+Iyagv8CNnfxSwqoRE9aqh1wf8DCgqVa2vmgbgwdUCHStwmxz1DaaKnDK3lcCAwEA
+AQKCAgEAl7fmVQW3bWYiid+cSp9pTpLAA/CwgYxHXmTILsBDuXP4sJvc045Iy6v9
+QnNmLerqcuWG4LFYgwnaLRVxRN66Nku3b1Hrm3v9YhmqJERwnhwEN7HqKvL+PAUg
+51mZuOqYvq3acT0KW7uZc1YwICkltmNkO7nbflr46TO3XfRCWVaxDQ1uJGxdDtwc
+8ftgplEEQiKJJ/gc8bK0n7bwadv8yhFIkKKoRilDWg50pxnacibZugXXXBdFwSnO
+Lnd/cMhYUg+4CuhotBUl/yQL9XtLsebj4zlpGlziqnhIyi2XNhUi2G9MDeOIQ8a9
+qVbYfHK2A0aMkjOrjYHK2CSZkOJvgv6qqpqDYwGSdI1AXtbP0+Oed2z0CQkj57qY
+hJXDkOjBgkldKL/MPI6g3LGnIa53RvX2oaFUZ0gKjO5F1m4c4cogF0xZUmQ9qt4v
+aHuzP5TBQdgms2yKIK/CafXXOmN435xdWJgkPxaM1JZq3K8hegL+rTHH8Obsf1p4
+sRvUGjsHY655YwvQkU6oBSPvtw3g9sYM+RsWTQKMXv2CAc+8q7D3byCr6ZL2CTC5
+gf5ZwQounjeDEzbwDFnCE2RV70N+xlqyLaQy3/Ftsee0L4Bi9amIIhlFSZs2ACS3
+Jk2WcC4ar7JhwvMq3pjs7QhfEpfbISUWhgNnqVK5m14fq9ZzcBECggEBAPIkCEV3
+ywMtkA/4/+mjAOlgjdaD5Yc5p7NkhQSn8TTxx5f4b6C0dADLolE0qinelRU2CQGX
+AK/QO53BFxnIt+9+FzmOf1oSWlzlzESNQz21YfQwmu+b7Bhw7ZwnJ0xdXeYmqfg8
+zXuwR9FfeXjo8fv89YbxhBM2Uxp/v0GZMw+DEC70yhcuhJZFHx4E7OabR/ozc/0b
+bhiIVdcOlRvgonKserXtei1J0aDFlfCF/t/eUUtFu5dOHKgYP0/yLUeFTIh5wSlj
+zQGjF9y10tztErOL0pFnzzTXu/nD19eelF0gWB1+OviGa21iJzKABnPYjPdW91lk
+ntBlF0KSSZrA3uMCggEBANNEn/X8KHJbrtjd0K4Q3arLZxqhv6xIXnvdhG+5LmMH
+sRKxKK08L6NYlfM6FgALuSnWJfMcoDpQ+bZoQzM7NuhaLcWLnXAGl1y/F5Sa8PU3
+7vbKJJQXb5jVy0aPP9kCu0DhNNs+DrN6NBr4gff02QijmFRfHWT4SVlEDY0cLknP
+/JiwNWjcPVGjdrWFF8+577CouQOvZcE51htkgpEaXTpbQqqe5WIHoAlx1XSQ9kA7
+szPPtTNS87Ey2cMgMlSJzU4Ad0ETwWUk7zWIx9kVGkWxbRz333YakzZyS46iL2i3
+51tdGzraXbwIkcZ5HRvBWH5b0egwLr292Xe5gEQCiP0CggEAPAY+nqnhg3op+iup
+lMs5kKDEyGaN4YWjUs8aQls3af59keieE2JoV0IjjKnXfOWWY1mvxdse6nZeMO8K
+wPOG1TGWpEf0velKyTiV+HBkOMnb7GKYJcmrLyvfWxRBo6aJfmIbRFQeRAkg5IAc
+ZqKoSeUdIESCjxiqZSlBygsmIzREML+x0SlQ6MddvV1PNKNNpnJW0GmaUy6IyPTu
+dair3G1xReQGo29nLcmNL8Cnu+sqj9RLemh8phbMqw7HtrEOlc5I2e/JhBxf7/CK
+wwVp22RP4IexT9Ii4Plxahv/f05jSXxfNfhsbQMl4FjoQJNv7mh6jIhq7hIBQBlv
+cZNaLQKCAQA0vFGNjnbuLNKVUbEwcgdTBdjjvfJhZ+Ml2iKf3MKmd5oMx2oW7Aoc
+JRWxFBO/yS1cMxdf+wpH5ESg8p+rnyFSmIgKYpJXD14jCZQyRQbWvzKIKec9jCgQ
+J3XJVCKk4diqFk0iWPhEdsGg5d1TbqvqSyPQE7n7pTpx7NnRGnK3fBJabsm2Nhuc
+UEhmgSVzdb9OAp/EOrkUpYI7bjhlTgZtdbBLdMRfVvXsxZx5r2G4oO5XhYZ+nDs2
+RTI0UcoebhNwYA9kkDDbNX/8hfsUxf673NEWxQzjpziOA7O2k+dvpVA77x7H7xAs
+yprQxxSsA/Q5/mOEKNrSBBzPlN9emp9lAoIBACmJyhsQUxeyzghKOEK1OeC0klC0
+Hr3p8ZobyFk9nCEsyAWoU/uY97JJmYxZ2NSJiNEcWm/s59+K2T7oc9Wm9fbheKVY
+kpjq+dQcDWQTa0DWqDIjMBRkDyg4lGTTjEZwA9mLj074HNIbHFfh6rzRYWfOMJ4+
+FcCjue9y7by+00wTZ2ZAHqU2BchizjYU2fY1dVAhM21/85bRX4YlUXlcQnCOMPCE
+3tsPDn0K+magZ8VWhTdSGKj1vNfpf6P7u5CV6IjUyc18EJwzjsRbBa+OtRWrVB44
+/Jejes+G3Gln86S0SuHQVJcE8VVsEgKzKjdqXM+eJSYI8gGCapd++lNv7D0=
+-----END RSA PRIVATE KEY-----
\ No newline at end of file
diff --git a/kong-versions/3.9.0.0/kong/spec/fixtures/tls-metadata-headers/intermediate_ca.crt b/kong-versions/3.9.0.0/kong/spec/fixtures/tls-metadata-headers/intermediate_ca.crt
new file mode 100644
index 00000000..24a25c8d
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/fixtures/tls-metadata-headers/intermediate_ca.crt
@@ -0,0 +1,17 @@
+-----BEGIN CERTIFICATE-----
+MIICsjCCAZqgAwIBAgICEAAwDQYJKoZIhvcNAQELBQAwEjEQMA4GA1UEAwwHUm9v
+dC1jYTAgFw0yMjEwMTkxNDQzNDVaGA8yMTIyMDkyNTE0NDM0NVowEjEQMA4GA1UE
+AwwHSW50ZXJtLjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJ6uSUl/
+FBmIzbq+UD1HROTiJ+ftJa0KwgEg0JwsKbd+9Ne92MlNNzG9glO8eWlIRsZTlkz9
+DxDXFJIMRqP7Fn9ZPeOAi2/VH+xIctBaIRcF/E/RwwrxnKOpaJvXOFudUg+YIPjP
+H59Wof4PQMU9ijArc6KNRuVlMDQlC9MSaX9lhUzO4Nk8IT9rmLi0Z5O0KK+mFkWv
+uN2uL9TqEumvea+Y5JKDitJxwFmGjGB18GIoKT0fOZVio/xyMuv7t7PybzE87wsd
+bACkqO48pwwIMC/TCpeWaxZ1+sSoT3zZXdD+tua/MLIM2ubrmBZFJKYP8mxOqUgK
+D29gWpcuZAIlrnUCAwEAAaMQMA4wDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsF
+AAOCAQEAVHSP6GPjLmvAuyOWncRKgBWJaP17UF0lZYIkJDW258nTqmQD2FMlNrp5
+l/r/5pkl45BOsf3kxsqjZNx/1QuyLfeb6R7BIWMSzdFvNuzYjqyfQHADxTuq6cCA
+3/eZ+fQA8da6LSLeIH+zKftNjDLjqAEVziID4ZQd1U2tHTMgFwNjlAH/ydAtqmdN
+HkWpdejvtYnUSWQrcJZN/C/vFGukNly06LFRd71iTHyPWg+8nybJXFOMfrW6qfMi
+SRAb/oQJaOMxXNrpXEQv/vbO8BK3LGmq2Bm2WIVFUhDKEdOqSvmeWoa8eM0bKT39
+fs6geD+F2d4dQAUspVmBp1z6nlb/FA==
+-----END CERTIFICATE-----
diff --git a/kong-versions/3.9.0.0/kong/spec/fixtures/tls-metadata-headers/intermediate_client_example.com.crt b/kong-versions/3.9.0.0/kong/spec/fixtures/tls-metadata-headers/intermediate_client_example.com.crt
new file mode 100644
index 00000000..f269b54d
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/fixtures/tls-metadata-headers/intermediate_client_example.com.crt
@@ -0,0 +1,66 @@
+Certificate:
+ Data:
+ Version: 1 (0x0)
+ Serial Number: 4097 (0x1001)
+ Signature Algorithm: sha256WithRSAEncryption
+ Issuer: CN=Interm.
+ Validity
+ Not Before: Oct 19 14:43:45 2022 GMT
+ Not After : Sep 25 14:43:45 2122 GMT
+ Subject: CN=1.example.com
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ Public-Key: (2048 bit)
+ Modulus:
+ 00:af:68:30:1c:0b:f7:10:dc:aa:06:71:27:6d:08:
+ f2:d4:48:b9:21:49:e2:8d:7b:63:c8:55:d6:1c:18:
+ 63:83:c9:26:91:86:4e:b3:55:ca:32:12:83:f0:c0:
+ f1:ef:3f:a4:2e:ac:09:48:8f:60:cf:9c:ff:49:93:
+ 49:c9:f5:21:32:81:87:ea:d0:9c:82:fa:f5:64:6a:
+ ea:f1:1b:ad:b6:2a:d0:c6:d4:75:72:6c:8c:9e:0c:
+ 2f:9c:a9:d7:98:14:aa:53:a9:a4:b6:94:d2:99:73:
+ 09:4d:87:da:bf:fd:9e:91:5b:22:58:81:c5:a4:6a:
+ 8d:1e:30:51:f9:38:8d:fb:3d:dc:10:d7:b2:f8:83:
+ 66:1d:c5:a5:ad:2f:67:bc:cb:ac:33:a1:2c:ec:10:
+ 05:fd:b4:99:01:69:fe:a9:5f:4e:68:bc:0e:1f:30:
+ 5d:a5:07:8c:91:00:c6:3b:56:c2:19:e9:0a:2e:ab:
+ e5:e2:7e:d5:f3:9a:56:3f:7c:85:45:f3:e4:86:32:
+ 25:38:ce:6a:79:14:58:5b:65:06:4f:fc:92:dc:61:
+ 1a:c7:b9:85:26:88:6c:79:dd:d5:4d:62:23:b9:d0:
+ 32:5a:89:48:94:a6:d8:fb:d9:70:23:97:e7:23:9a:
+ 7e:b9:f5:6d:16:54:08:2e:0e:31:70:36:fc:94:1f:
+ a0:c1
+ Exponent: 65537 (0x10001)
+ Signature Algorithm: sha256WithRSAEncryption
+ 78:be:c7:52:d3:84:ac:7d:a9:e4:75:7a:83:70:98:b4:61:f2:
+ e7:c7:13:85:62:e7:5f:68:00:a4:39:f3:01:55:36:d1:e7:24:
+ 5a:31:cc:94:cf:3a:c7:ba:da:83:6a:5a:90:e4:e2:da:7f:0c:
+ eb:87:ef:9b:82:78:ca:af:1b:84:18:94:d9:69:e8:d9:a8:c0:
+ aa:0f:66:31:aa:8b:d5:e9:b9:04:ef:e9:20:df:02:e9:50:47:
+ 4a:20:a5:ad:43:49:9e:2d:ce:a3:74:57:e6:b1:ce:23:e4:d1:
+ 3e:91:2d:4f:4b:26:33:f1:3a:93:a3:3c:9d:ef:2a:2c:68:f2:
+ 38:fa:ef:55:d2:19:06:25:d7:a8:1b:d1:35:04:9f:32:13:6c:
+ 2a:c7:e0:4a:bd:7e:52:5f:2a:f6:97:62:1d:c0:c0:a4:fa:19:
+ 06:71:8b:56:54:09:bd:95:cb:8e:20:f6:22:79:c1:e6:e6:a9:
+ 22:17:0b:98:e5:70:d1:c8:0f:8f:2b:16:c3:b5:ef:f5:af:ee:
+ 97:63:b1:18:4e:e6:8e:dc:87:d9:ae:cf:70:df:64:f7:5e:62:
+ e8:12:a0:f9:79:d8:c9:a0:81:54:3b:15:1a:35:83:82:ef:12:
+ 5b:99:b7:34:5f:d4:73:83:cf:bd:55:ea:19:ca:fe:7b:a0:78:
+ 03:6e:88:06
+-----BEGIN CERTIFICATE-----
+MIICoTCCAYkCAhABMA0GCSqGSIb3DQEBCwUAMBIxEDAOBgNVBAMMB0ludGVybS4w
+IBcNMjIxMDE5MTQ0MzQ1WhgPMjEyMjA5MjUxNDQzNDVaMBgxFjAUBgNVBAMMDTEu
+ZXhhbXBsZS5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCvaDAc
+C/cQ3KoGcSdtCPLUSLkhSeKNe2PIVdYcGGODySaRhk6zVcoyEoPwwPHvP6QurAlI
+j2DPnP9Jk0nJ9SEygYfq0JyC+vVkaurxG622KtDG1HVybIyeDC+cqdeYFKpTqaS2
+lNKZcwlNh9q//Z6RWyJYgcWkao0eMFH5OI37PdwQ17L4g2YdxaWtL2e8y6wzoSzs
+EAX9tJkBaf6pX05ovA4fMF2lB4yRAMY7VsIZ6Qouq+XiftXzmlY/fIVF8+SGMiU4
+zmp5FFhbZQZP/JLcYRrHuYUmiGx53dVNYiO50DJaiUiUptj72XAjl+cjmn659W0W
+VAguDjFwNvyUH6DBAgMBAAEwDQYJKoZIhvcNAQELBQADggEBAHi+x1LThKx9qeR1
+eoNwmLRh8ufHE4Vi519oAKQ58wFVNtHnJFoxzJTPOse62oNqWpDk4tp/DOuH75uC
+eMqvG4QYlNlp6NmowKoPZjGqi9XpuQTv6SDfAulQR0ogpa1DSZ4tzqN0V+axziPk
+0T6RLU9LJjPxOpOjPJ3vKixo8jj671XSGQYl16gb0TUEnzITbCrH4Eq9flJfKvaX
+Yh3AwKT6GQZxi1ZUCb2Vy44g9iJ5webmqSIXC5jlcNHID48rFsO17/Wv7pdjsRhO
+5o7ch9muz3DfZPdeYugSoPl52MmggVQ7FRo1g4LvEluZtzRf1HODz71V6hnK/nug
+eANuiAY=
+-----END CERTIFICATE-----
diff --git a/kong-versions/3.9.0.0/kong/spec/fixtures/tls-metadata-headers/intermediate_client_example.com.key b/kong-versions/3.9.0.0/kong/spec/fixtures/tls-metadata-headers/intermediate_client_example.com.key
new file mode 100644
index 00000000..60fb28ca
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/fixtures/tls-metadata-headers/intermediate_client_example.com.key
@@ -0,0 +1,28 @@
+-----BEGIN PRIVATE KEY-----
+MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCvaDAcC/cQ3KoG
+cSdtCPLUSLkhSeKNe2PIVdYcGGODySaRhk6zVcoyEoPwwPHvP6QurAlIj2DPnP9J
+k0nJ9SEygYfq0JyC+vVkaurxG622KtDG1HVybIyeDC+cqdeYFKpTqaS2lNKZcwlN
+h9q//Z6RWyJYgcWkao0eMFH5OI37PdwQ17L4g2YdxaWtL2e8y6wzoSzsEAX9tJkB
+af6pX05ovA4fMF2lB4yRAMY7VsIZ6Qouq+XiftXzmlY/fIVF8+SGMiU4zmp5FFhb
+ZQZP/JLcYRrHuYUmiGx53dVNYiO50DJaiUiUptj72XAjl+cjmn659W0WVAguDjFw
+NvyUH6DBAgMBAAECggEBAKraBfpboTSYazhJIUjwLW6ew0xsZjK/HCs3iIznKI9l
+755RvvipOIBbTo7DsSQDzkzznztBBOBUoMiuoXIIxWQnjRcoSTq/bSR5jAx7lFFb
+FO6GZTumBbWwUvP67xegEWPaWqjI/vUeetI84NKfG8OjjCm/hZ6ndnsQP9hLwOgU
+9PbkT6PSu0cvTn9Md8NZQS1y0bMjOImzdqQk5foRBzLz1yiP2B86hEQyzkWtfQD2
+Bp1lI02GIfm5W2lMkz+pQIG4JZRJYmemD1kRXlg7cpTZ//lRuZXS3UUzgN+3S1YB
+Z3OcLXh7q4dLeydwV5ogNXuoWd1rkkW9Q3dXjYPzo0ECgYEA2j4pXcnKz3v7X4m1
+Vijb48YxAh76OWsjnJ47DfIFlWxO9FRWzF0//0A9iAAxphQLRQDjznOeVJRduxSI
+Ij1ihltVMSLdfMPtjRrvXaxDv2asi2k03AR1AoBtvSm1mMOFH8j9eMT9RW8ezSUp
+Bf7RktpsL/oqmPOHZrcL2/hDmGkCgYEAzcDamtFHVgWRrF8psG6h5WEbO0u6XFTa
+8XTybot1EWsJAZm0AgfhVR6nN4ozpOsFXbLID4e0B1iTARukqcJEwvzLMMKpnjDD
+ra3VsE0G/P9n72hUJeJxJbGuiPQM8GsfnVqyvmpqtMuq0nbvDcLG5MqdZIAfL29W
+J1b0hvVr+pkCgYAipxgeYjons8H4K391jMtNYVzKv2xvzYk8BwvNbQ5h6W6n8PRP
+Qsc0mliqzY0Ul74qWLfTQhxzxZMUb3AmL6UDPGFMigKtGtcPPqWfNAkVzRG8mRnh
+jXueyBGkpYjGFtV+dIV6tZyZd8lmPW5EG2/fZ3siKxC0dIadUpc5eDQTcQKBgAeN
+uvjQEhRgY/a2D6vAhAUNyZglsZPOMbOHnZbdW9Dl4xDB+c/RRj5/v5fUZQz669mC
+xMF9M+jJIax6vVLWJPwbl8IUg3GhTK3FogC08zq6jbBGXkB9zbWajlPM0eTJqgF2
+4PUIpx44E+9iGmig6/heT+TupzZwmfMbyCJkRDCRAoGAeUwdiyCIFrionWxZa48w
+yqFzmSCER1h88iRHHtz8v1u8O7L2x5t1Mg1zPmhNa+QfrPk3+6UEY40gER+Co3GW
+zLydHYbbOlrVscvFzyiR0BqNEUsnCsihH8p9yFGfKcXhelQcDKwcV6Z7tjWI+QUR
+Nfdgx5VEqMmh07wIqW8hIyY=
+-----END PRIVATE KEY-----
diff --git a/kong-versions/3.9.0.0/kong/spec/fixtures/to-strip.conf b/kong-versions/3.9.0.0/kong/spec/fixtures/to-strip.conf
new file mode 100644
index 00000000..1e1e0ddc
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/fixtures/to-strip.conf
@@ -0,0 +1,9 @@
+database = postgres # strip me
+log_level = debug # strip this
+ # comment too
+pg_ssl = off # Toggles client-server TLS connections
+ # between Kong and PostgreSQL.
+
+pg_password = test\#123 # do not strip an escaped octothorpe
+
+plugins = foobar, hello-world, bundled
diff --git a/kong-versions/3.9.0.0/kong/spec/fixtures/valid-module.lua b/kong-versions/3.9.0.0/kong/spec/fixtures/valid-module.lua
new file mode 100644
index 00000000..51c53187
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/fixtures/valid-module.lua
@@ -0,0 +1,15 @@
+-- This software is copyright Kong Inc. and its licensors.
+-- Use of the software is subject to the agreement between your organization
+-- and Kong Inc. If there is no such agreement, use is governed by and
+-- subject to the terms of the Kong Master Software License Agreement found
+-- at https://konghq.com/enterprisesoftwarelicense/.
+-- [ END OF LICENSE 0867164ffc95e54f04670b5169c09574bdbd9bba ]
+
+-- Valid module (exposing data and having a global variable) for utils.load_module_if_exists unit tests.
+-- Assert that load_module_if_exists returns a module if it was valid
+
+local _M = {
+ exposed = "All your base are belong to us."
+}
+
+return _M
diff --git a/kong-versions/3.9.0.0/kong/spec/helpers.lua b/kong-versions/3.9.0.0/kong/spec/helpers.lua
new file mode 100644
index 00000000..c7c00315
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/helpers.lua
@@ -0,0 +1,289 @@
+-- This software is copyright Kong Inc. and its licensors.
+-- Use of the software is subject to the agreement between your organization
+-- and Kong Inc. If there is no such agreement, use is governed by and
+-- subject to the terms of the Kong Master Software License Agreement found
+-- at https://konghq.com/enterprisesoftwarelicense/.
+-- [ END OF LICENSE 0867164ffc95e54f04670b5169c09574bdbd9bba ]
+
+------------------------------------------------------------------
+-- Collection of utilities to help testing Kong features and plugins.
+--
+-- @copyright Copyright 2016-2022 Kong Inc. All rights reserved.
+-- @license [Apache 2.0](https://opensource.org/licenses/Apache-2.0)
+-- @module spec.helpers
+
+
+-- XXX EE [[
+local dist_constants = require("kong.enterprise_edition.distributions_constants")
+-- XXX EE ]]
+
+
+local log = require("kong.cmd.utils.log")
+local reload_module = require("spec.internal.module").reload
+
+
+log.set_lvl(log.levels.quiet) -- disable stdout logs in tests
+
+
+-- reload some modules when env or _G changes
+local CONSTANTS = reload_module("spec.internal.constants")
+local conf = reload_module("spec.internal.conf")
+local shell = reload_module("spec.internal.shell")
+local misc = reload_module("spec.internal.misc")
+local DB = reload_module("spec.internal.db")
+local grpc = reload_module("spec.internal.grpc")
+local dns_mock = reload_module("spec.internal.dns")
+local asserts = reload_module("spec.internal.asserts") -- luacheck: ignore
+local pid = reload_module("spec.internal.pid")
+local cmd = reload_module("spec.internal.cmd")
+local server = reload_module("spec.internal.server")
+local client = reload_module("spec.internal.client")
+local wait = reload_module("spec.internal.wait")
+
+
+--- Create a temporary directory, and return its path.
+-- @function tmpdir
+-- @return string path to the temporary directory
+local function tmpdir()
+ local handle = assert(io.popen("mktemp -d"))
+ local path = handle:read("*a")
+ handle:close()
+ return path:sub(1, #path - 1)
+end
+
+
+--- Gets the path to the fixtures directory calculating from the calling script.
+--- Useful for plugins-ee tests where `spec/fixtures` is not bundled for each plugin.
+-- @function get_fixtures_path
+-- @return string path to the fixtures directory
+local function get_fixtures_path()
+ local lfs = require("lfs")
+
+ local str = debug.getinfo(2, "S").source:sub(2)
+ local path = str:match("(.*/)") .. "fixtures/"
+ if path:sub(1, 1) ~= "/" then -- relative path
+ return lfs.currentdir() .. "/" .. path
+ end
+
+ return path
+end
+
+
+----------------
+-- Variables/constants
+-- @section exported-fields
+
+
+--- Below is a list of fields/constants exported on the `helpers` module table:
+-- @table helpers
+-- @field dir The [`pl.dir` module of Penlight](http://tieske.github.io/Penlight/libraries/pl.dir.html)
+-- @field path The [`pl.path` module of Penlight](http://tieske.github.io/Penlight/libraries/pl.path.html)
+-- @field file The [`pl.file` module of Penlight](http://tieske.github.io/Penlight/libraries/pl.file.html)
+-- @field utils The [`pl.utils` module of Penlight](http://tieske.github.io/Penlight/libraries/pl.utils.html)
+-- @field test_conf The Kong test configuration. See also `get_running_conf` which might be slightly different.
+-- @field test_conf_path The configuration file in use.
+-- @field mock_upstream_hostname
+-- @field mock_upstream_protocol
+-- @field mock_upstream_host
+-- @field mock_upstream_port
+-- @field mock_upstream_url Base url constructed from the components
+-- @field mock_upstream_ssl_protocol
+-- @field mock_upstream_ssl_host
+-- @field mock_upstream_ssl_port
+-- @field mock_upstream_ssl_url Base url constructed from the components
+-- @field mock_upstream_stream_port
+-- @field mock_upstream_stream_ssl_port
+-- @field mock_grpc_upstream_proto_path
+-- @field grpcbin_host The host for grpcbin service, it can be set by env KONG_SPEC_TEST_GRPCBIN_HOST.
+-- @field grpcbin_port The port (SSL disabled) for grpcbin service, it can be set by env KONG_SPEC_TEST_GRPCBIN_PORT.
+-- @field grpcbin_ssl_port The port (SSL enabled) for grpcbin service it can be set by env KONG_SPEC_TEST_GRPCBIN_SSL_PORT.
+-- @field grpcbin_url The URL (SSL disabled) for grpcbin service
+-- @field grpcbin_ssl_url The URL (SSL enabled) for grpcbin service
+-- @field redis_host The host for Redis, it can be set by env KONG_SPEC_TEST_REDIS_HOST.
+-- @field redis_port The port (SSL disabled) for Redis, it can be set by env KONG_SPEC_TEST_REDIS_PORT.
+-- @field redis_ssl_port The port (SSL enabled) for Redis, it can be set by env KONG_SPEC_TEST_REDIS_SSL_PORT.
+-- @field redis_ssl_sni The server name for Redis, it can be set by env KONG_SPEC_TEST_REDIS_SSL_SNI.
+-- @field zipkin_host The host for Zipkin service, it can be set by env KONG_SPEC_TEST_ZIPKIN_HOST.
+-- @field zipkin_port the port for Zipkin service, it can be set by env KONG_SPEC_TEST_ZIPKIN_PORT.
+-- @field otelcol_host The host for OpenTelemetry Collector service, it can be set by env KONG_SPEC_TEST_OTELCOL_HOST.
+-- @field otelcol_http_port the port for OpenTelemetry Collector service, it can be set by env KONG_SPEC_TEST_OTELCOL_HTTP_PORT.
+-- @field old_version_kong_path the path for the old version kong source code, it can be set by env KONG_SPEC_TEST_OLD_VERSION_KONG_PATH.
+-- @field otelcol_zpages_port the port for OpenTelemetry Collector Zpages service, it can be set by env KONG_SPEC_TEST_OTELCOL_ZPAGES_PORT.
+-- @field otelcol_file_exporter_path the path of for OpenTelemetry Collector's file exporter, it can be set by env KONG_SPEC_TEST_OTELCOL_FILE_EXPORTER_PATH.
+
+----------
+-- Exposed
+----------
+-- @export
+ return {
+ -- Penlight
+ dir = require("pl.dir"),
+ path = require("pl.path"),
+ file = require("pl.file"),
+ utils = require("pl.utils"),
+
+ -- Kong testing properties
+ db = DB.db,
+ blueprints = DB.blueprints,
+ get_db_utils = DB.get_db_utils,
+ get_cache = DB.get_cache,
+ bootstrap_database = DB.bootstrap_database,
+ bin_path = CONSTANTS.BIN_PATH,
+ test_conf = conf,
+ test_conf_path = CONSTANTS.TEST_CONF_PATH,
+ external_plugins_path = CONSTANTS.EXTERNAL_PLUGINS_PATH,
+ mock_upstream_hostname = CONSTANTS.MOCK_UPSTREAM_HOSTNAME,
+ mock_upstream_protocol = CONSTANTS.MOCK_UPSTREAM_PROTOCOL,
+ mock_upstream_host = CONSTANTS.MOCK_UPSTREAM_HOST,
+ mock_upstream_port = CONSTANTS.MOCK_UPSTREAM_PORT,
+ mock_upstream_url = CONSTANTS.MOCK_UPSTREAM_PROTOCOL .. "://" ..
+ CONSTANTS.MOCK_UPSTREAM_HOST .. ':' ..
+ CONSTANTS.MOCK_UPSTREAM_PORT,
+
+ mock_upstream_ssl_protocol = CONSTANTS.MOCK_UPSTREAM_SSL_PROTOCOL,
+ mock_upstream_ssl_host = CONSTANTS.MOCK_UPSTREAM_HOST,
+ mock_upstream_ssl_port = CONSTANTS.MOCK_UPSTREAM_SSL_PORT,
+ mock_upstream_ssl_url = CONSTANTS.MOCK_UPSTREAM_SSL_PROTOCOL .. "://" ..
+ CONSTANTS.MOCK_UPSTREAM_HOST .. ':' ..
+ CONSTANTS.MOCK_UPSTREAM_SSL_PORT,
+
+ mock_upstream_stream_port = CONSTANTS.MOCK_UPSTREAM_STREAM_PORT,
+ mock_upstream_stream_ssl_port = CONSTANTS.MOCK_UPSTREAM_STREAM_SSL_PORT,
+ mock_grpc_upstream_proto_path = CONSTANTS.MOCK_GRPC_UPSTREAM_PROTO_PATH,
+
+ zipkin_host = CONSTANTS.ZIPKIN_HOST,
+ zipkin_port = CONSTANTS.ZIPKIN_PORT,
+
+ otelcol_host = CONSTANTS.OTELCOL_HOST,
+ otelcol_http_port = CONSTANTS.OTELCOL_HTTP_PORT,
+ otelcol_zpages_port = CONSTANTS.OTELCOL_ZPAGES_PORT,
+ otelcol_file_exporter_path = CONSTANTS.OTELCOL_FILE_EXPORTER_PATH,
+
+ grpcbin_host = CONSTANTS.GRPCBIN_HOST,
+ grpcbin_port = CONSTANTS.GRPCBIN_PORT,
+ grpcbin_ssl_port = CONSTANTS.GRPCBIN_SSL_PORT,
+ grpcbin_url = string.format("grpc://%s:%d", CONSTANTS.GRPCBIN_HOST, CONSTANTS.GRPCBIN_PORT),
+ grpcbin_ssl_url = string.format("grpcs://%s:%d", CONSTANTS.GRPCBIN_HOST, CONSTANTS.GRPCBIN_SSL_PORT),
+
+ redis_host = CONSTANTS.REDIS_HOST,
+ redis_port = CONSTANTS.REDIS_PORT,
+ redis_ssl_port = CONSTANTS.REDIS_SSL_PORT,
+ redis_ssl_sni = CONSTANTS.REDIS_SSL_SNI,
+ redis_auth_port = CONSTANTS.REDIS_AUTH_PORT,
+
+ blackhole_host = CONSTANTS.BLACKHOLE_HOST,
+
+ old_version_kong_path = CONSTANTS.OLD_VERSION_KONG_PATH,
+
+ -- Kong testing helpers
+ execute = shell.exec,
+ dns_mock = dns_mock,
+ kong_exec = shell.kong_exec,
+ get_version = cmd.get_version,
+ get_running_conf = cmd.get_running_conf,
+ http_client = client.http_client,
+ grpc_client = client.grpc_client,
+ http2_client = client.http2_client,
+ make_synchronized_clients = client.make_synchronized_clients,
+ wait_until = wait.wait_until,
+ pwait_until = wait.pwait_until,
+ wait_pid = pid.wait_pid,
+ wait_timer = wait.wait_timer,
+ wait_for_all_config_update = wait.wait_for_all_config_update,
+ wait_for_file = wait.wait_for_file,
+ wait_for_file_contents = wait.wait_for_file_contents,
+ tcp_server = server.tcp_server,
+ udp_server = server.udp_server,
+ kill_tcp_server = server.kill_tcp_server,
+ is_echo_server_ready = server.is_echo_server_ready,
+ echo_server_reset = server.echo_server_reset,
+ get_echo_server_received_data = server.get_echo_server_received_data,
+ http_mock = server.http_mock,
+ get_proxy_ip = client.get_proxy_ip,
+ get_proxy_port = client.get_proxy_port,
+ proxy_client = client.proxy_client,
+ proxy_client_grpc = client.proxy_client_grpc,
+ proxy_client_grpcs = client.proxy_client_grpcs,
+ proxy_client_h2c = client.proxy_client_h2c,
+ proxy_client_h2 = client.proxy_client_h2,
+ admin_client = client.admin_client,
+ admin_gui_client = client.admin_gui_client,
+ proxy_ssl_client = client.proxy_ssl_client,
+ admin_ssl_client = client.admin_ssl_client,
+ admin_gui_ssl_client = client.admin_gui_ssl_client,
+ prepare_prefix = cmd.prepare_prefix,
+ clean_prefix = cmd.clean_prefix,
+ clean_logfile = cmd.clean_logfile,
+ wait_for_invalidation = wait.wait_for_invalidation,
+ each_strategy = DB.each_strategy,
+ all_strategies = DB.all_strategies,
+ validate_plugin_config_schema = DB.validate_plugin_config_schema,
+ clustering_client = client.clustering_client,
+ tmpdir = tmpdir,
+ https_server = require("spec.fixtures.https_server"),
+ stress_generator = require("spec.fixtures.stress_generator"),
+ get_fixtures_path = get_fixtures_path,
+
+ -- miscellaneous
+ intercept = misc.intercept,
+ openresty_ver_num = misc.openresty_ver_num,
+ unindent = misc.unindent,
+ make_yaml_file = misc.make_yaml_file,
+ setenv = misc.setenv,
+ unsetenv = misc.unsetenv,
+ deep_sort = misc.deep_sort,
+ generate_keys = misc.generate_keys,
+
+ -- launching Kong subprocesses
+ start_kong = cmd.start_kong,
+ stop_kong = cmd.stop_kong,
+ cleanup_kong = cmd.cleanup_kong,
+ restart_kong = cmd.restart_kong,
+ reload_kong = wait.reload_kong,
+ get_kong_workers = wait.get_kong_workers,
+ wait_until_no_common_workers = wait.wait_until_no_common_workers,
+
+ start_grpc_target = grpc.start_grpc_target,
+ stop_grpc_target = grpc.stop_grpc_target,
+ get_grpc_target_port = grpc.get_grpc_target_port,
+
+ -- plugin compatibility test
+ use_old_plugin = misc.use_old_plugin,
+
+ -- Only use in CLI tests from spec/02-integration/01-cmd
+ kill_all = cmd.kill_all,
+
+ with_current_ws = misc.with_current_ws,
+
+ signal = cmd.signal,
+
+ -- send signal to all Nginx workers, not including the master
+ signal_workers = cmd.signal_workers,
+
+ -- returns the plugins and version list that is used by Hybrid mode tests
+ get_plugins_list = DB.clone_plugins_list,
+
+ get_available_port = wait.get_available_port,
+
+ make_temp_dir = misc.make_temp_dir,
+
+ -- XXX EE [[
+ is_enterprise_plugin = function(plugin_name)
+ for _, ee_plugin_name in pairs(dist_constants.plugins) do
+ if ee_plugin_name == plugin_name then
+ return true
+ end
+ end
+ return false
+ end,
+
+ is_fips_build = function()
+ local pro = require "resty.openssl.provider"
+ local p = pro.load("fips")
+ if p then p:unload() end
+ return p ~= nil
+ end,
+ -- XXX EE ]]
+
+ build_go_plugins = cmd.build_go_plugins,
+}
diff --git a/kong-versions/3.9.0.0/kong/spec/helpers/ai/embeddings_mock.lua b/kong-versions/3.9.0.0/kong/spec/helpers/ai/embeddings_mock.lua
new file mode 100644
index 00000000..c31ae142
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/helpers/ai/embeddings_mock.lua
@@ -0,0 +1,106 @@
+-- This software is copyright Kong Inc. and its licensors.
+-- Use of the software is subject to the agreement between your organization
+-- and Kong Inc. If there is no such agreement, use is governed by and
+-- subject to the terms of the Kong Master Software License Agreement found
+-- at https://konghq.com/enterprisesoftwarelicense/.
+-- [ END OF LICENSE 0867164ffc95e54f04670b5169c09574bdbd9bba ]
+
+--
+-- imports
+--
+
+local cjson = require("cjson")
+local gzip = require("kong.tools.gzip")
+
+--
+-- public vars
+--
+
+-- some previously generated text embeddings for mocking, using OpenAI's
+-- text-embedding-3-small model and 4 dimensions.
+local known_text_embeddings = {
+ ["dog"] = { 0.56267416, -0.20551957, -0.047182854, 0.79933304 },
+ ["cat"] = { 0.4653789, -0.42677408, -0.29335415, 0.717795 },
+ ["capacitor"] = { 0.350534, -0.025470039, -0.9204002, -0.17129119 },
+ ["smell"] = { 0.23342973, -0.08322083, -0.8492907, -0.46614397 },
+ ["Non-Perturbative Quantum Field Theory and Resurgence in Supersymmetric Gauge Theories"] = {
+ -0.6826024,
+ -0.08655233,
+ -0.72073454,
+ -0.084287055,
+ },
+ ["taco"] = { -0.4407651, -0.85174876, -0.27901474, -0.048999753 },
+ ["If it discuss any topic about Amazon"] = { -0.86724466, 0.36718428, -0.21300745, -0.26017338 },
+ ["If it discuss any topic about Microsoft"] = { -0.8649115, 0.2526763, -0.41767937, -0.11673351 },
+ ["If it discuss any topic about Google"] = { -0.8108202, -0.22810346, -0.3790472, -0.38322666 },
+ ["If it discuss any topic about Apple"] = { -0.8892975, 0.30626073, -0.336221, 0.048061296 },
+ ["tell me something about Microsoft"] = { -0.48062202, -0.4189232, -0.7663229, -0.07908846 },
+ ["tell me something about Amazon"] = { -0.9346679, 0.10783355, -0.13593763, -0.31030443 },
+ ["tell me something about Google"] = { -0.3132111, -0.87082464, -0.33971936, -0.16779166 },
+}
+
+--
+-- public functions
+--
+
+local function mock_embeddings(opts)
+ if opts.method ~= "POST" then
+ return nil, "Only POST method is supported"
+ end
+
+ if opts.headers["Content-Type"] ~= "application/json" then
+ return nil, "Only application/json content type is supported"
+ end
+
+ if opts.headers["Accept-Encoding"] ~= "gzip" then
+ return nil, "Only gzip encoding is supported"
+ end
+
+ local request_body = cjson.decode(opts.body)
+
+ if not request_body.dimensions then
+ request_body.dimensions = 4
+ end
+ if request_body.dimensions ~= 4 then
+ return nil, "Only 4 dimensions are supported"
+ end
+
+ local prompt = request_body.input
+ local embedding = known_text_embeddings[prompt]
+ if not embedding then
+ return nil, "Invalid prompt"
+ end
+
+ local response_body = {
+ data = {
+ { embedding = embedding },
+ },
+ usage = {
+ prompt_tokens = 8,
+ total_tokens = 8
+ },
+ }
+
+ local encoded_response_body = cjson.encode(response_body)
+ local gzipped_response_body = gzip.deflate_gzip(encoded_response_body)
+
+ return {
+ status = 200,
+ body = gzipped_response_body,
+ headers = {
+ ["Content-Encoding"] = "gzip",
+ },
+ }
+end
+
+--
+-- module
+--
+
+return {
+ -- vars
+ known_text_embeddings = known_text_embeddings,
+
+ -- functions
+ mock_embeddings = mock_embeddings,
+}
diff --git a/kong-versions/3.9.0.0/kong/spec/helpers/ai/mistralai_mock.lua b/kong-versions/3.9.0.0/kong/spec/helpers/ai/mistralai_mock.lua
new file mode 100644
index 00000000..724c8739
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/helpers/ai/mistralai_mock.lua
@@ -0,0 +1,64 @@
+-- This software is copyright Kong Inc. and its licensors.
+-- Use of the software is subject to the agreement between your organization
+-- and Kong Inc. If there is no such agreement, use is governed by and
+-- subject to the terms of the Kong Master Software License Agreement found
+-- at https://konghq.com/enterprisesoftwarelicense/.
+-- [ END OF LICENSE 0867164ffc95e54f04670b5169c09574bdbd9bba ]
+
+--
+-- imports
+--
+
+local mocker = require("spec.fixtures.mocker")
+
+local mock_embeddings = require("spec.helpers.ai.embeddings_mock").mock_embeddings
+
+--
+-- private vars
+--
+
+local api = "https://api.mistral.ai"
+local embeddings_url = api .. "/v1/embeddings"
+
+--
+-- private functions
+--
+
+local mock_request_router = function(_self, url, opts)
+ if not string.find("^" .. url, api) then
+ return nil, "what are you doing?"
+ end
+
+ if url == embeddings_url then
+ return mock_embeddings(opts)
+ end
+
+ return nil, "URL " .. url .. " is not supported by mocking"
+end
+
+--
+-- public functions
+--
+
+local function setup(finally)
+ mocker.setup(finally, {
+ modules = {
+ { "resty.http", {
+ new = function()
+ return {
+ request_uri = mock_request_router,
+ }
+ end,
+ } },
+ }
+ })
+end
+
+--
+-- module
+--
+
+return {
+ -- functions
+ setup = setup,
+}
diff --git a/kong-versions/3.9.0.0/kong/spec/helpers/ai/openai_mock.lua b/kong-versions/3.9.0.0/kong/spec/helpers/ai/openai_mock.lua
new file mode 100644
index 00000000..1366c9d6
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/helpers/ai/openai_mock.lua
@@ -0,0 +1,64 @@
+-- This software is copyright Kong Inc. and its licensors.
+-- Use of the software is subject to the agreement between your organization
+-- and Kong Inc. If there is no such agreement, use is governed by and
+-- subject to the terms of the Kong Master Software License Agreement found
+-- at https://konghq.com/enterprisesoftwarelicense/.
+-- [ END OF LICENSE 0867164ffc95e54f04670b5169c09574bdbd9bba ]
+
+--
+-- imports
+--
+
+local mocker = require("spec.fixtures.mocker")
+
+local mock_embeddings = require("spec.helpers.ai.embeddings_mock").mock_embeddings
+
+--
+-- private vars
+--
+
+local api = "https://api.openai.com"
+local embeddings_url = api .. "/v1/embeddings"
+
+--
+-- private functions
+--
+
+local mock_request_router = function(_self, url, opts)
+ if not string.find("^" .. url, api) then
+ return nil, "what are you doing?"
+ end
+
+ if url == embeddings_url then
+ return mock_embeddings(opts)
+ end
+
+ return nil, "URL " .. url .. " is not supported by mocking"
+end
+
+--
+-- public functions
+--
+
+local function setup(finally)
+ mocker.setup(finally, {
+ modules = {
+ { "resty.http", {
+ new = function()
+ return {
+ request_uri = mock_request_router,
+ }
+ end,
+ } },
+ }
+ })
+end
+
+--
+-- module
+--
+
+return {
+ -- functions
+ setup = setup,
+}
diff --git a/kong-versions/3.9.0.0/kong/spec/helpers/ai/redis_mock.lua b/kong-versions/3.9.0.0/kong/spec/helpers/ai/redis_mock.lua
new file mode 100644
index 00000000..036fab81
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/helpers/ai/redis_mock.lua
@@ -0,0 +1,381 @@
+-- This software is copyright Kong Inc. and its licensors.
+-- Use of the software is subject to the agreement between your organization
+-- and Kong Inc. If there is no such agreement, use is governed by and
+-- subject to the terms of the Kong Master Software License Agreement found
+-- at https://konghq.com/enterprisesoftwarelicense/.
+-- [ END OF LICENSE 0867164ffc95e54f04670b5169c09574bdbd9bba ]
+
+--
+-- imports
+--
+
+local cjson = require("cjson.safe")
+local ffi = require("ffi")
+
+local mocker = require("spec.fixtures.mocker")
+
+--
+-- private vars
+--
+
+-- the error message to force on the next Redis call
+local forced_error_msg = nil
+
+--
+-- private functions
+--
+
+-- the default precision to round to during conversion
+local default_precision = 1e-6
+
+-- Redis requires a vector to be converted to a byte string, this function reverses
+-- that process so that we can compare vectors.
+--
+-- @param bytes the byte string to convert
+-- @param precision the precision to round to (optional)
+-- @return the vector
+local function convert_bytes_to_vector(bytes, precision)
+ precision = precision or default_precision
+ local float_size = ffi.sizeof("float")
+ local num_floats = #bytes / float_size
+ local float_array = ffi.cast("float*", bytes)
+ local vector = {}
+ for i = 0, num_floats - 1 do
+ local value = float_array[i]
+ value = math.floor(value / precision + 0.5) * precision -- round to precision
+ table.insert(vector, value)
+ end
+ return vector
+end
+
+-- Searches for the cosine distance between two vectors, and compares it
+-- against a threshold.
+--
+-- @param v1 the first vector
+-- @param v2 the second vector
+-- @param threshold the threshold to compare against
+-- @return true if the vectors are within the threshold, false otherwise
+-- @return the distance between the vectors
+local function cosine_distance(v1, v2, threshold)
+ local dot_product = 0.0
+ local magnitude_v1 = 0.0
+ local magnitude_v2 = 0.0
+
+ for i = 1, #v1 do
+ dot_product = dot_product + v1[i] * v2[i]
+ magnitude_v1 = magnitude_v1 + v1[i] ^ 2
+ magnitude_v2 = magnitude_v2 + v2[i] ^ 2
+ end
+
+ magnitude_v1 = math.sqrt(magnitude_v1)
+ magnitude_v2 = math.sqrt(magnitude_v2)
+
+ local cosine_similarity = dot_product / (magnitude_v1 * magnitude_v2)
+ local cosine_distance = 1 - cosine_similarity
+
+ return cosine_distance <= threshold, cosine_distance
+end
+
+-- Searches for the euclidean distance between two vectors, and compares it
+-- against a threshold.
+--
+-- @param v1 the first vector
+-- @param v2 the second vector
+-- @param threshold the threshold to compare against
+-- @return true if the vectors are within the threshold, false otherwise
+-- @return the distance between the vectors
+local function euclidean_distance(v1, v2, threshold)
+ local distance = 0.0
+ for i = 1, #v1 do
+ distance = distance + (v1[i] - v2[i]) ^ 2
+ end
+
+ distance = math.sqrt(distance)
+
+ return distance <= threshold, distance
+end
+
+local data = {}
+local indexes = {}
+local ttl = {}
+
+--
+-- public functions
+--
+
+local function setup(finally)
+ mocker.setup(finally, {
+ modules = {
+ { "resty.redis.connector", {
+ new = function()
+ return {
+ -- function mocks
+ set_timeouts = function() end,
+ connect = function(red)
+ if forced_error_msg then
+ return false, forced_error_msg
+ end
+ return red
+ end,
+ auth = function()
+ if forced_error_msg then
+ return false, forced_error_msg
+ end
+ return true
+ end,
+ ping = function()
+ if forced_error_msg then
+ return false, forced_error_msg
+ end
+ return true
+ end,
+ set_keepalive = function()
+ if forced_error_msg then
+ return false, forced_error_msg
+ end
+ return true
+ end,
+
+ init_pipeline = function(red)
+ red.in_pipeline = true
+ red.pipeline_results = {}
+ end,
+
+ commit_pipeline = function(red)
+ red.in_pipeline = false
+ return red.pipeline_results
+ end,
+
+ -- either return or saved in pipeline results
+ ret = function(red, ret, err)
+ if red.in_pipeline then
+ if err then
+ table.insert(red.pipeline_results, {ret, err})
+ else
+ table.insert(red.pipeline_results, ret)
+ end
+ return true
+ end
+
+ return ret, err
+ end,
+
+ -- raw command mocks
+ ["FT.CREATE"] = function(red, index, ...)
+ if forced_error_msg then
+ return red:ret(false, forced_error_msg)
+ end
+
+ if not index or index == "idx:_vss" then
+ return red:ret(false, "Invalid index name")
+ end
+
+ -- gather the distance metric
+ local args = { ... }
+ local distance_metric
+ for _, k in pairs(args) do
+ distance_metric = k
+ end
+ if distance_metric ~= "L2" and distance_metric ~= "COSINE" then
+ return red:ret(false, "Invalid distance metric " .. (distance_metric or "nil"))
+ end
+
+ indexes[index] = {
+ metric = distance_metric,
+ }
+ return red:ret(true, nil)
+ end,
+ ["FT.INFO"] = function(red, index, ...)
+ if forced_error_msg then
+ return red:ret(false, forced_error_msg)
+ end
+
+ if not index or index == "idx:_vss" then
+ return red:ret(false, "Invalid index name")
+ end
+
+ if not indexes[index] then
+ return red:ret(nil)
+ end
+
+ return red:ret({ "index_name", index,
+ "index_options", {},
+ "index_definition", {"key_type", "JSON", "prefixes", { index }, "default_score", "1" },
+ "attributes", {
+ { "identifier", "$.vector", "attribute", "vector", "type", "VECTOR", "algorithm", "FLAT", "data_type", "FLOAT32", "dim", 4, "distance_metric", indexes[index].metric, }
+ } })
+ end,
+ ["FT.DROPINDEX"] = function(red, index, ...)
+ if forced_error_msg then
+ return red:ret(false, forced_error_msg)
+ end
+
+ if not indexes[index] then
+ return red:ret(false, "Index not found")
+ end
+
+ indexes[index] = nil
+ return red:ret(true, nil)
+ end,
+ ["FT.SEARCH"] = function(red, index, ...)
+ if forced_error_msg then
+ return red:ret(nil, forced_error_msg)
+ end
+
+ -- verify whether the index for the search is valid,
+ -- and determine whether the index was configured
+ -- with euclidean or cosine distance
+ local distance_metric = indexes[index].metric
+ if not distance_metric then
+ return red:ret(nil, "Index not found")
+ end
+
+ -- determine the threshold, and record
+ local num_args = select("#", ...)
+ local threshold = select(num_args, ...)
+ red.last_threshold_received = threshold
+
+ -- determine the vector
+ local vector_bytes = select(num_args - 2, ...)
+ local search_vector = convert_bytes_to_vector(vector_bytes)
+
+ -- The caller can override the response with mock_next_search to set this next_response_key
+ -- and that will force a specific payload to be returned, if desired.
+ local payload = data[red.next_response_key]
+ if payload then
+ -- reset the override
+ red.next_response_key = nil
+
+ -- the structure Redis would respond with, but we only care about the proximity and payload
+ return red:ret({ {}, {}, { {}, "1.0", {}, payload } })
+ end
+
+ -- if the payload wasn't forced with an override, we'll do a vector search.
+ -- we won't try to fully emulate Redis' vector search but we can do a simple
+ -- distance comparison to emulate it.
+ local payloads = {}
+ for _key, value in pairs(data) do
+ local decoded_payload, err = cjson.decode(value)
+ if err then
+ return red:ret(nil, err)
+ end
+
+ -- check the proximity of the found vector
+ local found_vector = decoded_payload.vector
+ local proximity_match, distance
+ if distance_metric == "COSINE" then
+ proximity_match, distance = cosine_distance(search_vector, found_vector, threshold)
+ elseif distance_metric == "L2" then
+ proximity_match, distance = euclidean_distance(search_vector, found_vector, threshold)
+ else
+ error("unknown metric " .. distance_metric)
+ end
+ if proximity_match then
+ table.insert(payloads, { "vector_score", tostring(distance), "$", value })
+ end
+ end
+
+ -- sort the payloads by distance
+ table.sort(payloads, function(a, b)
+ return tonumber(a[2]) < tonumber(b[2])
+ end)
+
+ -- if no payloads were found, just return red:ret(an empty table to emulate cache miss)
+ if #payloads < 1 then
+ return red:ret({})
+ end
+
+ -- the structure Redis would respond with, but we only care about the proximity and payload
+ local res = { {}, {} } -- filler response information from Redis we don't use
+ for i = 1, #payloads do
+ table.insert(res, payloads[i])
+ end
+ return red:ret(res, nil)
+ end,
+ ["JSON.GET"] = function(red, key, path)
+ if forced_error_msg then
+ return red:ret(nil, forced_error_msg)
+ end
+
+ local ret = data[key] and cjson.decode(data[key])
+ if ret and path == ".payload" then
+ ret = cjson.encode(ret.payload)
+ elseif path then
+ error("unsupported path other than .payload, got " .. path)
+ end
+
+ return red:ret(ret, nil)
+ end,
+ ["JSON.SET"] = function(red, key, _path, payload) -- currently, path is not used because we only set cache at root
+ if forced_error_msg then
+ return red:ret(false, forced_error_msg)
+ end
+
+ red.key_count = red.key_count + 1
+ data[key] = payload
+
+ return red:ret(true, nil)
+ end,
+ ["JSON.DEL"] = function(red, key, path)
+ if forced_error_msg then
+ return red:ret(false, forced_error_msg)
+ end
+
+ red.key_count = red.key_count - 1
+ data[key] = nil
+
+ return red:ret(true, nil)
+ end,
+ ["FLUSHALL"] = function(red)
+ data = {}
+ return red:ret(true, nil)
+ end,
+ ["expire"] = function(red, key, t)
+ ngx.update_time()
+ ttl[key] = t + ngx.now()
+ return red:ret(true)
+ end,
+ ["ttl"] = function(red, key)
+ ngx.update_time()
+ local t = ttl[key]
+ if not t then
+ return red:ret(-1)
+ end
+ return red:ret(t - ngx.now())
+ end,
+
+ -- internal tracking
+ indexes = {},
+ key_count = 0,
+ cache = {},
+ next_response_key = nil,
+ last_threshold_received = 0.0,
+ pipeline_results = {},
+ }
+ end,
+ mock_next_search = function(red, key)
+ red.next_response_key = key
+ end,
+ forced_failure = function(err_msg)
+ forced_error_msg = err_msg
+ end,
+ } },
+ }
+ })
+end
+
+local function clear()
+ data = {}
+ indexes = {}
+ ttl = {}
+end
+
+--
+-- module
+--
+
+return {
+ -- functions
+ setup = setup,
+ clear = clear,
+}
diff --git a/kong-versions/3.9.0.0/kong/spec/helpers/dns.lua b/kong-versions/3.9.0.0/kong/spec/helpers/dns.lua
new file mode 100644
index 00000000..5c6a985d
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/helpers/dns.lua
@@ -0,0 +1,209 @@
+-- This software is copyright Kong Inc. and its licensors.
+-- Use of the software is subject to the agreement between your organization
+-- and Kong Inc. If there is no such agreement, use is governed by and
+-- subject to the terms of the Kong Master Software License Agreement found
+-- at https://konghq.com/enterprisesoftwarelicense/.
+-- [ END OF LICENSE 0867164ffc95e54f04670b5169c09574bdbd9bba ]
+
+
+--- test helper methods for DNS and load-balancers
+-- @module spec.helpers.dns
+
+local _M = {}
+
+
+if ngx then
+ _M.gettime = ngx.now
+ _M.sleep = ngx.sleep
+else
+ local socket = require("socket")
+ _M.gettime = socket.gettime
+ _M.sleep = socket.sleep
+end
+local gettime = _M.gettime
+
+
+--- Iterator over different balancer types.
+-- returns; consistent-hash, round-robin, least-conn
+-- @return `algorithm_name`, `balancer_module`
+function _M.balancer_types()
+ local b_types = {
+ -- algorithm name
+ { "consistent-hashing", "consistent_hashing" },
+ { "round-robin", "round_robin" },
+ { "least-connections", "least_connections" },
+ }
+ local i = 0
+ return function()
+ i = i + 1
+ if b_types[i] then
+ return b_types[i][1], require("resty.dns.balancer." .. b_types[i][2])
+ end
+ end
+end
+
+
+--- Expires a record now.
+-- @param record a DNS record previously created
+function _M.dnsExpire(client, record)
+ local dnscache = client.getcache()
+ dnscache:delete(record[1].name .. ":" .. record[1].type)
+ dnscache:delete(record[1].name .. ":-1") -- A/AAAA
+ record.expire = gettime() - 1
+end
+
+
+--- Creates an SRV record in the cache.
+-- @tparam dnsclient client the dns client in which cache it is to be stored
+-- @tparam table records a single entry, or a list of entries for the hostname
+-- @tparam[opt=4] number staleTtl the staleTtl to use for the record TTL (see Kong config reference for description)
+-- @usage
+-- local host = "konghq.com" -- must be the same for all entries obviously...
+-- local rec = dnsSRV(dnsCLient, {
+-- -- defaults: weight = 10, priority = 20, ttl = 600
+-- { name = host, target = "20.20.20.20", port = 80, weight = 10, priority = 20, ttl = 600 },
+-- { name = host, target = "50.50.50.50", port = 80, weight = 10, priority = 20, ttl = 600 },
+-- })
+function _M.dnsSRV(client, records, staleTtl)
+ local dnscache = client.getcache()
+ -- if single table, then insert into a new list
+ if not records[1] then records = { records } end
+
+ for _, record in ipairs(records) do
+ record.type = client.TYPE_SRV
+
+ -- check required input
+ assert(record.target, "target field is required for SRV record")
+ assert(record.name, "name field is required for SRV record")
+ assert(record.port, "port field is required for SRV record")
+ record.name = record.name:lower()
+
+ -- optionals, insert defaults
+ record.weight = record.weight or 10
+ record.ttl = record.ttl or 600
+ record.priority = record.priority or 20
+ record.class = record.class or 1
+ end
+ -- set timeouts
+ records.touch = gettime()
+ records.expire = gettime() + records[1].ttl
+ records.ttl = records[1].ttl
+
+ -- create key, and insert it
+
+ -- for orignal dns client
+ local key = records[1].type..":"..records[1].name
+ dnscache:set(key, records, records[1].ttl + (staleTtl or 4))
+ -- insert last-succesful lookup type
+ dnscache:set(records[1].name, records[1].type)
+
+ -- for new dns client
+ local key = records[1].name..":"..records[1].type
+ dnscache:set(key, records, records[1].ttl + (staleTtl or 4))
+
+ return records
+end
+
+
+--- Creates an A record in the cache.
+-- @tparam dnsclient client the dns client in which cache it is to be stored
+-- @tparam table records a single entry, or a list of entries for the hostname
+-- @tparam[opt=4] number staleTtl the staleTtl to use for the record TTL (see Kong config reference for description)
+-- @usage
+-- local host = "konghq.com" -- must be the same for all entries obviously...
+-- local rec = dnsSRV(dnsCLient, {
+-- -- defaults: ttl = 600
+-- { name = host, address = "20.20.20.20", ttl = 600 },
+-- { name = host, address = "50.50.50.50", ttl = 600 },
+-- })
+function _M.dnsA(client, records, staleTtl)
+ local dnscache = client.getcache()
+ -- if single table, then insert into a new list
+ if not records[1] then records = { records } end
+
+ for _, record in ipairs(records) do
+ record.type = client.TYPE_A
+
+ -- check required input
+ assert(record.address, "address field is required for A record")
+ assert(record.name, "name field is required for A record")
+ record.name = record.name:lower()
+
+ -- optionals, insert defaults
+ record.ttl = record.ttl or 600
+ record.class = record.class or 1
+ end
+ -- set timeouts
+ records.touch = gettime()
+ records.expire = gettime() + records[1].ttl
+ records.ttl = records[1].ttl
+
+ -- create key, and insert it
+
+ -- for original dns client
+ local key = records[1].type..":"..records[1].name
+ dnscache:set(key, records, records[1].ttl + (staleTtl or 4))
+ -- insert last-succesful lookup type
+ dnscache:set(records[1].name, records[1].type)
+
+ -- for new dns client
+ local key = records[1].name..":"..records[1].type
+ dnscache:set(key, records, records[1].ttl)
+ key = records[1].name..":-1" -- A/AAAA
+ dnscache:set(key, records, records[1].ttl)
+
+ return records
+end
+
+
+--- Creates an AAAA record in the cache.
+-- @tparam dnsclient client the dns client in which cache it is to be stored
+-- @tparam table records a single entry, or a list of entries for the hostname
+-- @tparam[opt=4] number staleTtl the staleTtl to use for the record TTL (see Kong config reference for description)
+-- @usage
+-- local host = "konghq.com" -- must be the same for all entries obviously...
+-- local rec = dnsSRV(dnsCLient, {
+-- -- defaults: ttl = 600
+-- { name = host, address = "::1", ttl = 600 },
+-- })
+function _M.dnsAAAA(client, records, staleTtl)
+ local dnscache = client.getcache()
+ -- if single table, then insert into a new list
+ if not records[1] then records = { records } end
+
+ for _, record in ipairs(records) do
+ record.type = client.TYPE_AAAA
+
+ -- check required input
+ assert(record.address, "address field is required for AAAA record")
+ assert(record.name, "name field is required for AAAA record")
+ record.name = record.name:lower()
+
+ -- optionals, insert defaults
+ record.ttl = record.ttl or 600
+ record.class = record.class or 1
+ end
+ -- set timeouts
+ records.touch = gettime()
+ records.expire = gettime() + records[1].ttl
+ records.ttl = records[1].ttl
+
+ -- create key, and insert it
+
+ -- for orignal dns client
+ local key = records[1].type..":"..records[1].name
+ dnscache:set(key, records, records[1].ttl + (staleTtl or 4))
+ -- insert last-succesful lookup type
+ dnscache:set(records[1].name, records[1].type)
+
+ -- for new dns client
+ local key = records[1].name..":"..records[1].type
+ dnscache:set(key, records, records[1].ttl + (staleTtl or 4))
+ key = records[1].name..":-1" -- A/AAAA
+ dnscache:set(key, records, records[1].ttl + (staleTtl or 4))
+
+ return records
+end
+
+
+return _M
diff --git a/kong-versions/3.9.0.0/kong/spec/helpers/http_mock.lua b/kong-versions/3.9.0.0/kong/spec/helpers/http_mock.lua
new file mode 100644
index 00000000..1813f125
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/helpers/http_mock.lua
@@ -0,0 +1,283 @@
+-- This software is copyright Kong Inc. and its licensors.
+-- Use of the software is subject to the agreement between your organization
+-- and Kong Inc. If there is no such agreement, use is governed by and
+-- subject to the terms of the Kong Master Software License Agreement found
+-- at https://konghq.com/enterprisesoftwarelicense/.
+-- [ END OF LICENSE 0867164ffc95e54f04670b5169c09574bdbd9bba ]
+
+--- Module implementing http_mock, a HTTP mocking server for testing.
+-- @module spec.helpers.http_mock
+
+local helpers = require "spec.helpers"
+
+local pairs = pairs
+local ipairs = ipairs
+local type = type
+local setmetatable = setmetatable
+
+local modules = {
+ require "spec.helpers.http_mock.nginx_instance",
+ require "spec.helpers.http_mock.asserts",
+ require "spec.helpers.http_mock.debug_port",
+ require "spec.helpers.http_mock.clients",
+}
+
+local http_mock = {}
+
+-- since http_mock contains a lot of functionality, it is implemented in separate submodules
+-- and combined into one large http_mock module here.
+for _, module in ipairs(modules) do
+ for k, v in pairs(module) do
+ http_mock[k] = v
+ end
+end
+
+-- get a session from the logs with a timeout
+-- throws error if no request is recieved within the timeout
+-- @treturn table the session
+function http_mock:get_session()
+ local ret
+ self.eventually:has_session_satisfy(function(s)
+ ret = s
+ return true
+ end)
+ return ret
+end
+
+-- get a request from the logs with a timeout
+-- throws error if no request is recieved within the timeout
+-- @treturn table the request
+function http_mock:get_request()
+ return self:get_session().req
+end
+
+-- get a response from the logs with a timeout
+-- throws error if no request is recieved within the timeout
+-- @treturn table the response
+function http_mock:get_response()
+ return self:get_session().resp
+end
+
+local http_mock_MT = { __index = http_mock, __gc = http_mock.stop }
+
+
+-- TODO: make default_mocking the same to the `mock_upstream`
+local default_mocking = {
+ ["/"] = {
+ access = [[
+ ngx.req.set_header("X-Test", "test")
+ ngx.print("ok")
+ ngx.exit(200)
+ ]],
+ },
+}
+
+local function default_field(tbl, key, default)
+ if tbl[key] == nil then
+ tbl[key] = default
+ end
+end
+
+--- create a mock instance which represents a HTTP mocking server
+-- @tparam[opt] table|string|number listens the listen directive of the mock server. This can be
+-- a single directive (string), or a list of directives (table), or a number which will be used as the port.
+-- Defaults to a random available port
+-- @tparam[opt] table|string routes the code of the mock server, defaults to a simple response. See Examples.
+-- @tparam[opt={}] table opts options for the mock server, supporting fields:
+-- @tparam[opt="servroot_tapping"] string opts.prefix the prefix of the mock server
+-- @tparam[opt="_"] string opts.hostname the hostname of the mock server
+-- @tparam[opt=false] bool opts.tls whether to use tls
+-- @tparam[opt={}] table opts.directives the extra directives of the mock server
+-- @tparam[opt={}] table opts.log_opts the options for logging with fields listed below:
+-- @tparam[opt=true] bool opts.log_opts.collect_req whether to log requests()
+-- @tparam[opt=true] bool opts.log_opts.collect_req_body_large whether to log large request bodies
+-- @tparam[opt=false] bool opts.log_opts.collect_resp whether to log responses
+-- @tparam[opt=false] bool opts.log_opts.collect_resp_body whether to log response bodies
+-- @tparam[opt=true] bool opts.log_opts.collect_err: whether to log errors
+-- @tparam[opt] string opts.init: the lua code injected into the init_by_lua_block
+-- @treturn http_mock a mock instance
+-- @treturn string the port the mock server listens to
+-- @usage
+-- local mock = http_mock.new(8000, [[
+-- ngx.req.set_header("X-Test", "test")
+-- ngx.print("hello world")
+-- ]], {
+-- prefix = "mockserver",
+-- log_opts = {
+-- resp = true,
+-- resp_body = true,
+-- },
+-- tls = true,
+-- })
+--
+-- mock:start()
+-- local client = mock:get_client() -- get a client to access the mocking port
+-- local res = assert(client:send({}))
+-- assert.response(res).has.status(200)
+-- assert.response(res).has.header("X-Test", "test")
+-- assert.response(res).has.body("hello world")
+-- mock.eventually:has_response(function(resp)
+-- assert.same(resp.body, "hello world")
+-- end)
+-- mock:wait_until_no_request() -- wait until all the requests are finished
+-- mock:clean() -- clean the logs
+-- client:send({})
+-- client:send({})
+-- local logs = mock:retrieve_mocking_logs() -- get all the logs of HTTP sessions
+-- mock:stop()
+--
+-- listens can be a number, which will be used as the port of the mock server;
+-- or a string, which will be used as the param of listen directive of the mock server;
+-- or a table represents multiple listen ports.
+-- if the port is not specified, a random port will be used.
+-- call mock:get_default_port() to get the first port the mock server listens to.
+-- if the port is a number and opts.tls is set to ture, ssl will be appended.
+--
+-- routes can be a table like this:
+-- routes = {
+-- ["/"] = {
+-- access = [[
+-- ngx.req.set_header("X-Test", "test")
+-- ngx.print("hello world")
+-- ]],
+-- log = [[
+-- ngx.log(ngx.ERR, "log test!")
+-- ]],
+-- directives = {
+-- "rewrite ^/foo /bar break;",
+-- },
+-- },
+-- }
+--
+-- -- or single a string, which will be used as the access phase handler.
+-- routes = [[ ngx.print("hello world") ]]
+-- -- which is equivalent to:
+-- routes = {
+-- ["/"] = {
+-- access = [[ ngx.print("hello world") ]],
+-- },
+-- }
+function http_mock.new(listens, routes, opts)
+ opts = opts or {}
+
+ if listens == nil then
+ listens = helpers.get_available_port()
+ end
+
+ if type(listens) == "number" then
+ listens = "0.0.0.0:" .. listens .. (opts.tls and " ssl" or "")
+ end
+
+ if type(listens) == "string" then
+ listens = { listens, }
+ end
+
+ if routes == nil then
+ routes = default_mocking
+ elseif type(routes) == "string" then
+ routes = {
+ ["/"] = {
+ access = routes,
+ }
+ }
+ end
+
+ opts.log_opts = opts.log_opts or {}
+ local log_opts = opts.log_opts
+ default_field(log_opts, "req", true)
+ default_field(log_opts, "req_body_large", true)
+ -- usually we can check response from client side
+ default_field(log_opts, "resp", false)
+ default_field(log_opts, "resp_body", false)
+ default_field(log_opts, "err", true)
+
+ local prefix = opts.prefix or "servroot_mock"
+ local hostname = opts.hostname or "_"
+ local directives = opts.directives or {}
+
+ local _self = setmetatable({
+ prefix = prefix,
+ hostname = hostname,
+ listens = listens,
+ routes = routes,
+ directives = directives,
+ dicts = opts.dicts,
+ init = opts.init,
+ log_opts = log_opts,
+ logs = {},
+ tls = opts.tls,
+ eventually_timeout = opts.eventually_timeout or 5,
+ }, http_mock_MT)
+
+ local port = _self:get_default_port()
+
+ if port then
+ _self.client_opts = {
+ port = port,
+ tls = opts.tls,
+ }
+ end
+
+ _self:_set_eventually_table()
+ _self:_setup_debug()
+ return _self, port
+end
+
+--- @type http_mock
+
+--- returns the default port of the mock server.
+-- @function http_mock:get_default_port
+-- @treturn string the port of the mock server (from the first listen directive)
+function http_mock:get_default_port()
+ return self.listens[1]:match(":(%d+)")
+end
+
+--- retrieve the logs of HTTP sessions
+-- @function http_mock:retrieve_mocking_logs
+-- @treturn table the logs of HTTP sessions
+
+--- purge the logs of HTTP sessions
+-- @function http_mock:purge_mocking_logs
+
+--- clean the logs of HTTP sessions
+-- @function http_mock:clean
+
+--- wait until all the requests are finished
+-- @function http_mock:wait_until_no_request
+-- @tparam[opt=true,default=5] number timeout the timeout to wait for the nginx process to exit
+
+--- make assertions on HTTP requests.
+-- with a timeout to wait for the requests to arrive
+-- @table http_mock.eventually
+
+--- assert if the condition is true for one of the logs.
+--- Replace "session" in the name of the function to assert on fields of the log.
+--- The field can be one of "session", "request", "response", "error".
+-- @function http_mock.eventually:has_session_satisfy
+-- @tparam function check the check function, accept a log and throw error if the condition is not satisfied
+
+--- assert if the condition is true for all the logs.
+-- Replace "session" in the name of the function to assert on fields of the log.
+-- The field can be one of "session", "request", "response", "error".
+-- @function http_mock.eventually:all_session_satisfy
+-- @tparam function check the check function, accept a log and throw error if the condition is not satisfied
+
+--- assert if none of the logs satisfy the condition.
+-- Replace "session" in the name of the function to assert on fields of the log.
+-- The field can be one of "session", "request", "response", "error".
+-- @function http_mock.eventually:has_no_session_satisfy
+-- @tparam function check the check function, accept a log and throw error if the condition is not satisfied
+
+--- assert if not all the logs satisfy the condition.
+-- Replace "session" in the name of the function to assert on fields of the log.
+-- The field can be one of "session", "request", "response", "error".
+-- @function http_mock.eventually:not_all_session_satisfy
+-- @tparam function check the check function, accept a log and throw error if the condition is not satisfied
+
+--- alias for eventually:not_all_{session,request,response,error}_satisfy.
+-- Replace "session" in the name of the function to assert on fields of the log.
+-- The field can be one of "session", "request", "response", "error".
+-- @function http_mock.eventually:has_one_without_session_satisfy
+-- @tparam function check the check function, accept a log and throw error if the condition is not satisfied
+
+return http_mock
diff --git a/kong-versions/3.9.0.0/kong/spec/helpers/http_mock/asserts.lua b/kong-versions/3.9.0.0/kong/spec/helpers/http_mock/asserts.lua
new file mode 100644
index 00000000..5bd8de5e
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/helpers/http_mock/asserts.lua
@@ -0,0 +1,171 @@
+-- This software is copyright Kong Inc. and its licensors.
+-- Use of the software is subject to the agreement between your organization
+-- and Kong Inc. If there is no such agreement, use is governed by and
+-- subject to the terms of the Kong Master Software License Agreement found
+-- at https://konghq.com/enterprisesoftwarelicense/.
+-- [ END OF LICENSE 0867164ffc95e54f04670b5169c09574bdbd9bba ]
+
+
+local setmetatable = setmetatable
+local ipairs = ipairs
+local pairs = pairs
+local pcall = pcall
+local error = error
+
+local http_mock = {}
+
+local build_in_checks = {}
+
+local eventually_MT = {}
+eventually_MT.__index = eventually_MT
+
+local step_time = 0.01
+
+-- example for a check function
+-- local function(session, status)
+-- -- must throw error if the assertion is not true
+-- -- instead of return false
+-- assert.same(session.resp.status, status)
+-- -- return a string to tell what condition is satisfied
+-- -- so we can construct an error message for reverse assertion
+-- -- in this case it would be "we don't expect that: has a response with status 200"
+-- return "has a response with status " .. status
+-- end
+
+local function eventually_has(check, mock, ...)
+ local time = 0
+ local ok, err
+ while time < mock.eventually_timeout do
+ local logs = mock:retrieve_mocking_logs()
+ for _, log in ipairs(logs) do
+ -- use pcall so the user may use lua assert like assert.same
+ ok, err = pcall(check, log, ...)
+ if ok then
+ return true
+ end
+ end
+
+ ngx.sleep(step_time)
+ time = time + step_time
+ end
+
+ error(err or "assertion fail. No request is sent and recorded.", 2)
+end
+
+-- wait until timeout to check if the assertion is true for all logs
+local function eventually_all(check, mock, ...)
+ local time = 0
+ local ok, err
+ while time < mock.eventually_timeout do
+ local logs = mock:retrieve_mocking_logs()
+ for _, log in ipairs(logs) do
+ ok, err = pcall(check, log, ...)
+ if not ok then
+ error(err or "assertion fail", 2)
+ end
+ end
+
+ ngx.sleep(step_time)
+ time = time + step_time
+ end
+
+ return true
+end
+
+-- a session is a request/response pair
+function build_in_checks.session_satisfy(session, f)
+ return f(session) or "session satisfy"
+end
+
+function build_in_checks.request_satisfy(session, f)
+ return f(session.req) or "request satisfy"
+end
+
+function build_in_checks.request()
+ return "request exist"
+end
+
+function build_in_checks.response_satisfy(session, f)
+ return f(session.resp) or "response satisfy"
+end
+
+function build_in_checks.error_satisfy(session, f)
+ return f(session.err) or "error satisfy"
+end
+
+function build_in_checks.error(session)
+ assert(session.err, "has no error")
+ return "has error"
+end
+
+local function register_assert(name, impl)
+ eventually_MT["has_" .. name] = function(self, ...)
+ return eventually_has(impl, self.__mock, ...)
+ end
+
+ eventually_MT["all_" .. name] = function(self, ...)
+ return eventually_all(impl, self.__mock, ...)
+ end
+
+ local function reverse_impl(session, ...)
+ local ok, err = pcall(impl, session, ...)
+ if ok then
+ error("we don't expect that: " .. (name or err), 2)
+ end
+ return true
+ end
+
+ eventually_MT["has_no_" .. name] = function(self, ...)
+ return eventually_all(reverse_impl, self.__mock, ...)
+ end
+
+ eventually_MT["not_all_" .. name] = function(self, ...)
+ return eventually_has(reverse_impl, self.__mock, ...)
+ end
+
+ eventually_MT["has_one_without_" .. name] = eventually_MT["not_all_" .. name]
+end
+
+for name, impl in pairs(build_in_checks) do
+ register_assert(name, impl)
+end
+
+
+function http_mock:_set_eventually_table()
+ local eventually = setmetatable({}, eventually_MT)
+ eventually.__mock = self
+ self.eventually = eventually
+ return eventually
+end
+
+-- usually this function is not called by a user. I will add more assertions in the future with it. @StarlightIbuki
+
+-- @function http_mock.register_assert()
+-- @param name: the name of the assertion
+-- @param impl: the implementation of the assertion
+-- implement a new eventually assertion
+-- @usage:
+-- impl is a function
+-- -- @param session: the session object, with req, resp, err, start_time, end_time as fields
+-- -- @param ...: the arguments passed to the assertion
+-- -- @return: human readable message if the assertion is true, or throw error if not
+--
+-- a session means a request/response pair.
+-- The impl callback throws error if the assertion is not true
+-- and returns a string to tell what condition is satisfied
+-- This design is to allow the user to use lua asserts in the callback
+-- (or even callback the registered assertion accept as argument), like the example;
+-- and for has_no/not_all assertions, we can construct an error message for it like:
+-- "we don't expect that: has header foo"
+-- @example:
+-- http_mock.register_assert("req_has_header", function(mock, name)
+-- assert.same(name, session.req.headers[name])
+-- return "has header " .. name
+-- end)
+-- mock.eventually:has_req_has_header("foo")
+-- mock.eventually:has_no_req_has_header("bar")
+-- mock.eventually:all_req_has_header("baz")
+-- mock.eventually:not_all_req_has_header("bar")
+http_mock.register_assert = register_assert
+
+return http_mock
diff --git a/kong-versions/3.9.0.0/kong/spec/helpers/http_mock/clients.lua b/kong-versions/3.9.0.0/kong/spec/helpers/http_mock/clients.lua
new file mode 100644
index 00000000..40e1c89b
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/helpers/http_mock/clients.lua
@@ -0,0 +1,38 @@
+-- This software is copyright Kong Inc. and its licensors.
+-- Use of the software is subject to the agreement between your organization
+-- and Kong Inc. If there is no such agreement, use is governed by and
+-- subject to the terms of the Kong Master Software License Agreement found
+-- at https://konghq.com/enterprisesoftwarelicense/.
+-- [ END OF LICENSE 0867164ffc95e54f04670b5169c09574bdbd9bba ]
+
+--- part of http_mock
+-- @submodule spec.helpers.http_mock
+
+local helpers = require "spec.helpers"
+local http_client = helpers.http_client
+
+local http_mock = {}
+
+--- get a `helpers.http_client` to access the mock server
+-- @function http_mock:get_client
+-- @treturn http_client a `helpers.http_client` instance
+-- @within http_mock
+-- @usage
+-- httpc = http_mock:get_client()
+-- result = httpc:get("/services/foo", opts)
+function http_mock:get_client()
+ local client = self.client
+ if not client then
+ client = http_client({
+ scheme = self.client_opts.tls and "https" or "http",
+ host = "localhost",
+ port = self.client_opts.port,
+ })
+
+ self.client = client
+ end
+
+ return client
+end
+
+return http_mock
diff --git a/kong-versions/3.9.0.0/kong/spec/helpers/http_mock/debug_port.lua b/kong-versions/3.9.0.0/kong/spec/helpers/http_mock/debug_port.lua
new file mode 100644
index 00000000..3933e178
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/helpers/http_mock/debug_port.lua
@@ -0,0 +1,125 @@
+-- This software is copyright Kong Inc. and its licensors.
+-- Use of the software is subject to the agreement between your organization
+-- and Kong Inc. If there is no such agreement, use is governed by and
+-- subject to the terms of the Kong Master Software License Agreement found
+-- at https://konghq.com/enterprisesoftwarelicense/.
+-- [ END OF LICENSE 0867164ffc95e54f04670b5169c09574bdbd9bba ]
+
+
+local helpers = require "spec.helpers"
+local http = require "resty.http"
+local cjson = require "cjson"
+local match = string.match
+local ipairs = ipairs
+local insert = table.insert
+local assert = assert
+
+local http_mock = {}
+
+-- POST as it's not idempotent
+local retrieve_mocking_logs_param = {
+ method = "POST",
+ path = "/logs",
+ headers = {
+ ["Host"] = "mock_debug"
+ }
+}
+
+local purge_mocking_logs_param = {
+ method = "DELETE",
+ path = "/logs",
+ headers = {
+ ["Host"] = "mock_debug"
+ }
+}
+
+local get_status_param = {
+ method = "GET",
+ path = "/status",
+ headers = {
+ ["Host"] = "mock_debug"
+ }
+}
+
+-- internal API
+function http_mock:_setup_debug(debug_param)
+ local debug_port = helpers.get_available_port()
+ local debug_client = assert(http.new())
+ local debug_connect = {
+ scheme = "http",
+ host = "localhost",
+ port = debug_port,
+ }
+
+ self.debug = {
+ port = debug_port,
+ client = debug_client,
+ connect = debug_connect,
+ param = debug_param,
+ }
+end
+
+function http_mock:debug_connect()
+ local debug = self.debug
+ local client = debug.client
+ assert(client:connect(debug.connect))
+ return client
+end
+
+function http_mock:retrieve_mocking_logs_json()
+ local debug = self:debug_connect()
+ local res = assert(debug:request(retrieve_mocking_logs_param))
+ assert(res.status == 200)
+ local body = assert(res:read_body())
+ debug:close()
+ return body
+end
+
+function http_mock:purge_mocking_logs()
+ local debug = self:debug_connect()
+ local res = assert(debug:request(purge_mocking_logs_param))
+ assert(res.status == 204)
+ debug:close()
+ return true
+end
+
+function http_mock:retrieve_mocking_logs()
+ local new_logs = cjson.decode(self:retrieve_mocking_logs_json())
+ for _, log in ipairs(new_logs) do
+ insert(self.logs, log)
+ end
+
+ return new_logs
+end
+
+function http_mock:wait_until_no_request(timeout)
+ local debug = self:debug_connect()
+
+ -- wait until we have no requests on going
+ helpers.wait_until(function()
+ local res = assert(debug:request(get_status_param))
+ assert(res.status == 200)
+ local body = assert(res:read_body())
+ local reading, writing, _ = match(body, "Reading: (%d+) Writing: (%d+) Waiting: (%d+)")
+ -- the status is the only request
+ return assert(reading) + assert(writing) <= 1
+ end, timeout)
+end
+
+function http_mock:get_all_logs(timeout)
+ self:wait_until_no_request(timeout)
+ self:retrieve_mocking_logs()
+ return self.logs
+end
+
+function http_mock:clean(timeout)
+ -- if we wait, the http_client may timeout and cause error
+ -- self:wait_until_no_request(timeout)
+
+ -- clean unwanted logs
+ self.logs = {}
+ self:purge_mocking_logs()
+ return true
+end
+
+return http_mock
diff --git a/kong-versions/3.9.0.0/kong/spec/helpers/http_mock/nginx_instance.lua b/kong-versions/3.9.0.0/kong/spec/helpers/http_mock/nginx_instance.lua
new file mode 100644
index 00000000..1a1cecc5
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/helpers/http_mock/nginx_instance.lua
@@ -0,0 +1,102 @@
+-- This software is copyright Kong Inc. and its licensors.
+-- Use of the software is subject to the agreement between your organization
+-- and Kong Inc. If there is no such agreement, use is governed by and
+-- subject to the terms of the Kong Master Software License Agreement found
+-- at https://konghq.com/enterprisesoftwarelicense/.
+-- [ END OF LICENSE 0867164ffc95e54f04670b5169c09574bdbd9bba ]
+
+--- part of http_mock
+-- @submodule spec.helpers.http_mock
+
+local template_str = require "spec.helpers.http_mock.template"
+local pl_template = require "pl.template"
+local pl_path = require "pl.path"
+local pl_dir = require "pl.dir"
+local pl_file = require "pl.file"
+local pl_utils = require "pl.utils"
+local shell = require "resty.shell"
+
+local print = print
+local error = error
+local assert = assert
+local ngx = ngx
+local io = io
+
+local shallow_copy
+do
+ local clone = require "table.clone"
+
+ shallow_copy = function(orig)
+ assert(type(orig) == "table")
+ return clone(orig)
+ end
+end
+
+local template = assert(pl_template.compile(template_str))
+local render_env = {ipairs = ipairs, pairs = pairs, error = error, }
+local http_mock = {}
+
+--- start a dedicate nginx instance for this mock
+-- @tparam[opt=false] bool error_on_exist whether to throw error if the directory already exists
+-- @within http_mock
+-- @usage http_mock:start(true)
+function http_mock:start(error_on_exist)
+ local ok = (pl_path.mkdir(self.prefix))
+ and (pl_path.mkdir(self.prefix .. "/logs"))
+ and (pl_path.mkdir(self.prefix .. "/conf"))
+ if error_on_exist then assert(ok, "failed to create directory " .. self.prefix) end
+
+ local render = assert(template:render(shallow_copy(self), render_env))
+ local conf_path = self.prefix .. "/conf/nginx.conf"
+ local conf_file = assert(io.open(conf_path, "w"))
+ assert(conf_file:write(render))
+ assert(conf_file:close())
+
+ local cmd = "nginx -p " .. self.prefix
+ local ok, code, _, stderr = pl_utils.executeex(cmd)
+ assert(ok and code == 0, "failed to start nginx: " .. stderr)
+ return true
+end
+
+local sleep_step = 0.01
+
+--- stop a dedicate nginx instance for this mock
+-- @function http_mock:stop
+-- @tparam[opt=false] bool no_clean whether to preserve the logs
+-- @tparam[opt="TERM"] string signal the signal name to send to the nginx process
+-- @tparam[opt=10] number timeout the timeout to wait for the nginx process to exit
+-- @within http_mock
+-- @usage http_mock:stop(false, "TERM", 10)
+function http_mock:stop(no_clean, signal, timeout)
+ signal = signal or "TERM"
+ timeout = timeout or 10
+ local pid_filename = self.prefix .. "/logs/nginx.pid"
+ local pid_file = assert(io.open(pid_filename, "r"))
+ local pid = assert(pid_file:read("*a"))
+ pid_file:close()
+
+ local kill_nginx_cmd = "kill -s " .. signal .. " " .. pid
+ if not shell.run(kill_nginx_cmd, nil, 0) then
+ error("failed to kill nginx at " .. self.prefix, 2)
+ end
+
+ local time = 0
+ while pl_file.access_time(pid_filename) ~= nil do
+ ngx.sleep(sleep_step)
+ time = time + sleep_step
+ if(time > timeout) then
+ error("nginx does not exit at " .. self.prefix, 2)
+ end
+ end
+
+ if no_clean then return true end
+
+ local _, err = pl_dir.rmtree(self.prefix)
+ if err then
+ print("could not remove ", self.prefix, ": ", tostring(err))
+ end
+
+ return true
+end
+
+return http_mock
diff --git a/kong-versions/3.9.0.0/kong/spec/helpers/http_mock/tapping.lua b/kong-versions/3.9.0.0/kong/spec/helpers/http_mock/tapping.lua
new file mode 100644
index 00000000..7db07e46
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/helpers/http_mock/tapping.lua
@@ -0,0 +1,54 @@
+-- This software is copyright Kong Inc. and its licensors.
+-- Use of the software is subject to the agreement between your organization
+-- and Kong Inc. If there is no such agreement, use is governed by and
+-- subject to the terms of the Kong Master Software License Agreement found
+-- at https://konghq.com/enterprisesoftwarelicense/.
+-- [ END OF LICENSE 0867164ffc95e54f04670b5169c09574bdbd9bba ]
+
+--- A http_mock subclass for tapping.
+-- @module spec.helpers.http_mock.tapping
+
+local http_mock = require "spec.helpers.http_mock"
+
+local tapping = {}
+
+-- create a new tapping route
+-- @tparam string|number target the target host/port of the tapping route
+-- @return the tapping route instance
+function tapping.new_tapping_route(target)
+ if tonumber(target) then
+ -- TODO: handle the resovler!
+ target = "http://127.0.0.1:" .. target
+ end
+
+ if not target:find("://") then
+ target = "http://" .. target
+ end
+
+ return {
+ ["/"] = {
+ directives = [[proxy_pass ]] .. target .. [[;]],
+ }
+ }
+end
+
+--- create a new `http_mock.tapping` instance with a tapping route
+-- @tparam string|number target the target host/port of the tapping route
+-- @tparam[opt] table|string|number listens see `http_mock.new`
+-- @tparam[opt="servroot_tapping"] string prefix the prefix of the mock server
+-- @tparam[opt={}] table log_opts see `http_mock.new`, uses the defaults, with `req_large_body` enabled
+-- @treturn http_mock.tapping a tapping instance
+-- @treturn string the port the mock server listens to
+function tapping.new(target, listens, prefix, log_opts)
+ ---@diagnostic disable-next-line: return-type-mismatch
+ return http_mock.new(listens, tapping.new_tapping_route(target), {
+ prefix = prefix or "servroot_tapping",
+ log_opts = log_opts or {
+ req = true,
+ req_body = true,
+ req_large_body = true,
+ },
+ })
+end
+
+return tapping
diff --git a/kong-versions/3.9.0.0/kong/spec/helpers/http_mock/template.lua b/kong-versions/3.9.0.0/kong/spec/helpers/http_mock/template.lua
new file mode 100644
index 00000000..91af44d5
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/helpers/http_mock/template.lua
@@ -0,0 +1,255 @@
+-- This software is copyright Kong Inc. and its licensors.
+-- Use of the software is subject to the agreement between your organization
+-- and Kong Inc. If there is no such agreement, use is governed by and
+-- subject to the terms of the Kong Master Software License Agreement found
+-- at https://konghq.com/enterprisesoftwarelicense/.
+-- [ END OF LICENSE 0867164ffc95e54f04670b5169c09574bdbd9bba ]
+
+
+return [[
+# if not hostname then
+# hostname = "_"
+# end
+# if not debug.port then
+# error("debug.port is required")
+# end
+# if not shm_size then
+# shm_size = "20m"
+# end
+daemon on;
+# if not worker_num then
+# worker_num = 1
+# end
+worker_processes $(worker_num);
+error_log logs/error.log info;
+pid logs/nginx.pid;
+worker_rlimit_nofile 8192;
+
+events {
+ worker_connections 1024;
+}
+
+http {
+ lua_shared_dict mock_logs $(shm_size);
+
+# for dict, size in pairs(dicts or {}) do
+ lua_shared_dict $(dict) $(size);
+# end
+
+ init_by_lua_block {
+# if log_opts.err then
+ -- disable warning of global variable
+ local g_meta = getmetatable(_G)
+ setmetatable(_G, nil)
+
+ original_assert = assert -- luacheck: ignore
+
+ local function insert_err(err)
+ local err_t = ngx.ctx.err
+ if not err_t then
+ err_t = {}
+ ngx.ctx.err = err_t
+ end
+ table.insert(err_t, {err, debug.traceback("", 3)})
+ end
+
+ function assert(truthy, err, ...) -- luacheck: ignore
+ if not truthy and ngx.ctx then
+ insert_err(err)
+ end
+
+ return original_assert(truthy, err, ...)
+ end
+
+ original_error = error -- luacheck: ignore
+
+ function error(msg, ...) -- luacheck: ignore
+ if ngx.ctx then
+ insert_err(msg)
+ end
+
+ return original_error(msg, ...)
+ end
+
+ err_patched = true -- luacheck: ignore
+
+ setmetatable(_G, g_meta)
+# end
+# if init then
+$(init)
+# end
+ }
+
+ server {
+ listen 0.0.0.0:$(debug.port);
+ server_name mock_debug;
+
+ location = /status {
+ stub_status;
+ }
+
+ location /logs {
+ default_type application/json;
+
+ access_by_lua_block {
+ local mock_logs = ngx.shared.mock_logs
+
+ if ngx.req.get_method() == "DELETE" then
+ mock_logs:flush_all()
+ return ngx.exit(204)
+ end
+
+ if ngx.req.get_method() ~= "POST" then
+ return ngx.exit(405)
+ end
+
+ ngx.print("[")
+ local ele, err
+ repeat
+ local old_ele = ele
+ ele, err = mock_logs:lpop("mock_logs")
+ if old_ele and ele then
+ ngx.print(",", ele)
+ elseif ele then
+ ngx.print(ele)
+ end
+ if err then
+ return ngx.exit(500)
+ end
+ until not ele
+ ngx.print("]")
+ ngx.exit(200)
+ }
+ }
+ }
+
+ server {
+# for _, listen in ipairs(listens or {}) do
+ listen $(listen);
+# end
+ server_name $(hostname);
+
+# for _, directive in ipairs(directives or {}) do
+ $(directive)
+
+# end
+# if tls then
+ ssl_certificate ../../spec/fixtures/kong_spec.crt;
+ ssl_certificate_key ../../spec/fixtures/kong_spec.key;
+ ssl_protocols TLSv1.2;
+ ssl_ciphers HIGH:!aNULL:!MD5;
+
+# end
+# for location, route in pairs(routes or {}) do
+ location $(location) {
+# if route.directives then
+ $(route.directives)
+
+# end
+# if route.access or log_opts.req then
+ access_by_lua_block {
+# if log_opts.req then
+ -- collect request
+ local method = ngx.req.get_method()
+ local uri = ngx.var.request_uri
+ local headers = ngx.req.get_headers(nil, true)
+
+
+ ngx.req.read_body()
+ local body
+# if log_opts.req_body then
+ -- collect body
+ body = ngx.req.get_body_data()
+ if not body then
+ local file = ngx.req.get_body_file()
+ if file then
+# if log_opts.req_large_body then
+ local f = io.open(file, "r")
+ if f then
+ body = f:read("*a")
+ f:close()
+ end
+# else
+ body = { "body is too large" }
+# end -- if log_opts.req_large_body
+ end
+ end
+# end -- if log_opts.req_body
+ ngx.ctx.req = {
+ method = method,
+ uri = uri,
+ headers = headers,
+ body = body,
+ }
+
+# end -- if log_opts.req
+# if route.access then
+ $(route.access)
+# end
+ }
+# end
+
+# if route.header_filter then
+ header_filter_by_lua_block {
+ $(route.header)
+ }
+
+# end
+# if route.content then
+ content_by_lua_block {
+ $(route.content)
+ }
+
+# end
+# if route.body_filter or log_opts.resp_body then
+ body_filter_by_lua_block {
+# if route.body_filter then
+ $(route.body)
+
+# end
+# if log_opts.resp_body then
+ -- collect body
+ ngx.ctx.resp_body = ngx.ctx.resp_body or {}
+ if not ngx.arg[2] then
+ table.insert(ngx.ctx.resp_body, ngx.arg[1])
+ end
+# end -- if log_opts.resp_body
+ }
+
+# end
+ log_by_lua_block {
+# if route.log then
+ $(route.log)
+
+# end
+ -- collect session data
+ local cjson = require "cjson"
+ local start_time = ngx.req.start_time()
+ local end_time = ngx.now()
+
+ local req = ngx.ctx.req or {}
+ local resp
+# if log_opts.resp then
+ resp = {
+ status = ngx.status,
+ headers = ngx.resp.get_headers(nil, true),
+ body = ngx.ctx.resp_body and table.concat(ngx.ctx.resp_body),
+ }
+# else -- if log_opts.resp
+ resp = {}
+# end -- if log_opts.resp
+ local err = ngx.ctx.err
+
+ ngx.shared.mock_logs:rpush("mock_logs", cjson.encode({
+ start_time = start_time,
+ end_time = end_time,
+ req = req,
+ resp = resp,
+ err = err,
+ }))
+ }
+ }
+# end -- for location, route in pairs(routes)
+ }
+}
+]]
diff --git a/kong-versions/3.9.0.0/kong/spec/helpers/oauth_client.lua b/kong-versions/3.9.0.0/kong/spec/helpers/oauth_client.lua
new file mode 100644
index 00000000..ad3ae4f1
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/helpers/oauth_client.lua
@@ -0,0 +1,493 @@
+-- This software is copyright Kong Inc. and its licensors.
+-- Use of the software is subject to the agreement between your organization
+-- and Kong Inc. If there is no such agreement, use is governed by and
+-- subject to the terms of the Kong Master Software License Agreement found
+-- at https://konghq.com/enterprisesoftwarelicense/.
+-- [ END OF LICENSE 0867164ffc95e54f04670b5169c09574bdbd9bba ]
+
+local utils = require("kong.tools.utils")
+local resty_http = require("resty.http")
+local cjson = require("cjson")
+local jwks = require "kong.openid-connect.jwks"
+local jwa = require("kong.openid-connect.jwa")
+local uuid = require("resty.jit-uuid")
+local base64url_encode = require("ngx.base64").encode_base64url
+local json_encode = cjson.encode
+
+
+local WELL_KNOWN_PATH = "/.well-known/openid-configuration"
+local ENDPOINT_SUFFIX = "_endpoint"
+
+
+local _M = {}
+
+
+---- utility functions
+
+local function dump_request(url, opts, is_rp)
+ print("\n==", is_rp and "RP" or "IDP", " request==")
+ print(opts.method, " ", url)
+ for k, v in pairs(opts.headers) do
+ print(k, ": ", v)
+ end
+ print()
+ print(opts.body)
+ print("===============")
+end
+
+
+local function dump_response(resp, is_rp)
+ print("\n==", is_rp and "RP" or "IDP", " response==")
+ print("HTTP ", resp.status)
+ for k, v in pairs(resp.headers) do
+ print(k, ": ", v)
+ end
+ print()
+ print(resp.body)
+ print("===============")
+end
+
+
+local function get_value_fallback(key, ...)
+ for i = 1, select("#", ...) do
+ local source = select(i, ...)
+ if source[key] then
+ return source[key]
+ end
+ end
+end
+
+
+function _M.update_cookies(self, res)
+ local set_cookie_headers = res.headers["Set-Cookie"]
+ if type(set_cookie_headers) ~= "table" then
+ set_cookie_headers = { set_cookie_headers }
+ end
+
+ for _, cookie in ipairs(set_cookie_headers) do
+ local k, v = cookie:match("^([^;=]*)=([^;=]*)")
+ self.cookies[k] = v or ""
+ end
+end
+
+
+local function cookies_to_header(cookies)
+ local cookie = {}
+ for k, v in pairs(cookies) do
+ cookie[#cookie + 1] = k .. "=" .. v
+ end
+ return table.concat(cookie, "; ")
+end
+
+
+local function append_query(url, args)
+ if url:find("?") then
+ return url .. "&" .. args
+ else
+ return url .. "?" .. args
+ end
+end
+
+
+---- end of utility functions
+
+---- methods
+
+-- to use a public client, set client_secret to false explicitly
+function _M.new(opts)
+ opts = opts or {}
+ opts.http_client = opts.http_client or resty_http.new()
+ opts.issuer = opts.issuer or "http://localhost:8080/realms/master"
+ opts.client_uri = opts.client_uri or "http://localhost"
+ opts.auth_callback_uri = opts.auth_callback_uri or "/callback/auth/"
+ opts.user_login_simulator = opts.user_login_simulator or _M.keycloak_login
+ opts.cookies = opts.cookies or {}
+
+ -- default to using end-to-end binding unless explicitly set to false
+ if opts.using_dpop and opts.auth_dpop == nil then
+ opts.auth_dpop = true
+ end
+
+ return setmetatable(opts, _M)
+end
+
+function _M.__index(self, key)
+ if _M[key] then
+ return _M[key]
+ end
+
+ if key:sub(-#ENDPOINT_SUFFIX) == ENDPOINT_SUFFIX then
+ local ret = self:get_endpoint(key)
+ self[key] = ret
+ return ret
+ end
+
+ local get_f = "get_" .. key
+ if _M[get_f] then
+ self[key] = _M[get_f](self)
+ return self[key]
+ end
+end
+
+function _M:get_idp_config()
+ local issuer = self.issuer
+ if not issuer then
+ error("no discovery_url set")
+ end
+
+ if issuer:sub(-#WELL_KNOWN_PATH) ~= WELL_KNOWN_PATH then
+ issuer = issuer .. WELL_KNOWN_PATH
+ end
+
+ local res, err = self:idp_request(issuer, {
+ method = "GET",
+ headers = {
+ ["Accept"] = "application/json",
+ },
+ })
+
+ if not res then
+ error("failed to fetch openid-configuration: " .. err)
+ end
+
+ if res.status ~= 200 then
+ error("failed to fetch openid-configuration: status " .. res.status)
+ end
+
+ return cjson.decode(res.body)
+end
+
+
+function _M:generate_dpop_proof(req, payload, alg)
+ local jwk = assert(self.client_jwk, "no client_jwk set")
+ local jwk_public = assert(self.client_jwk_public, "no client_jwk set")
+ local htm = assert(req.method, "request method required to sign DPoP header")
+ local htu = assert(req.url, "request uri required to sign DPoP header")
+ htu = htu:match("^[^?#]*") -- remove query string and fragment
+ payload = payload or {}
+
+ if (not payload.ath) and payload.access_token then
+ payload.ath = base64url_encode(jwa.S256(payload.access_token))
+ payload.access_token = nil
+ end
+
+ local header = {
+ typ = "dpop+jwt",
+ alg = alg or jwk.alg,
+ jwk = jwk_public,
+ }
+
+ for k, v in pairs(payload) do
+ payload[k] = v
+ end
+
+ payload.iat = payload.iat or ngx.now()
+ payload.jti = payload.jti or uuid.generate_v4()
+ payload.htm = payload.htm or htm
+ payload.htu = payload.htu or htu
+
+ local str_to_sign = base64url_encode(json_encode(header)) .. "." .. base64url_encode(json_encode(payload))
+
+ local jwt_token = assert(jwa.sign(header.alg, jwk, str_to_sign))
+
+ return str_to_sign .. "." .. jwt_token
+end
+
+
+function _M:get_endpoint(name)
+ local idp_config = assert(self.idp_config, "no idp_config set")
+ local endpoint
+
+ if self.using_mtls and idp_config.mtls_endpoint_aliases then
+ endpoint = idp_config.mtls_endpoint_aliases[name]
+ end
+
+ if not endpoint then
+ endpoint = idp_config[name]
+ end
+
+ return endpoint
+end
+
+
+function _M:request(url, opts, is_rp)
+ local access_token = is_rp and self:get_access_token() or nil
+ local nonce_name = is_rp and "rp_last_dpop_nonce" or "idp_last_dpop_nonce"
+ local desigated_dpop = opts.headers["DPoP"]
+ local res
+
+ -- opts.headers["Host"] = opts.headers["Host"] or url:match("^https?://([^/]+)")
+
+ -- retry if nonce is required and we are recieving one for the first time
+ local retried = false
+ ::retry::
+ if self.using_dpop then
+ opts.headers["DPoP"] = desigated_dpop or assert(self:generate_dpop_proof({
+ method = opts.method,
+ url = url,
+ }, {
+ access_token = access_token,
+ nonce = self[nonce_name], -- if exists
+ }), "failed to generate DPoP proof")
+ end
+
+ if self.dump_req then
+ dump_request(url, opts, is_rp)
+ end
+
+ res = assert(self.http_client:request_uri(url, opts))
+ self:update_cookies(res)
+
+ if res.headers["DPoP-Nonce"] then
+ self[nonce_name] = res.headers["DPoP-Nonce"]
+ end
+
+ if self.dump_req or (res.status >= 400 and self.dump_on_err) then
+ dump_response(res, is_rp)
+ end
+
+ if (res.status == 400 or res.status == 401) and res.headers["DPoP-Nonce"] and not retried then
+ if self.dump_req then
+ print("retrying with nonce")
+ end
+
+ retried = true
+ goto retry
+ end
+
+ return res
+end
+
+
+function _M:idp_request(url, opts, query_args, client_cred)
+ opts.headers = opts.headers or {}
+ local args = opts.args or {}
+
+ if client_cred == "public" or "secret" then
+ args.client_id = get_value_fallback("client_id", args, self)
+ end
+
+ if client_cred == "secret" then
+ args.client_secret = get_value_fallback("client_secret", args, self)
+ end
+
+ local cookies = get_value_fallback("cookies", opts, self)
+ if cookies then
+ opts.headers["Cookie"] = cookies_to_header(cookies)
+ end
+ opts.cookies = nil
+
+ local string_args = ngx.encode_args(args)
+
+ if opts.args and opts.method == "GET" then
+ url = append_query(url, string_args)
+ else
+ opts.headers["Content-Type"] = opts.headers["Content-Type"] or "application/x-www-form-urlencoded"
+ opts.body = opts.body or string_args
+ end
+
+ if query_args then
+ url = append_query(url, ngx.encode_args(query_args))
+ end
+
+ opts.args = nil
+
+ return self:request(url, opts)
+end
+
+
+function _M:token_request(args, query_args)
+ args = args or {}
+ local token_endpoint = assert(self.token_endpoint, "no token_endpoint found")
+ args.auth_method = get_value_fallback("auth_method", args, self) or "client_secret_basic"
+
+ local res = self:idp_request(token_endpoint, {
+ method = "POST",
+ args = args,
+ }, query_args, "secret", self.using_dpop and "header")
+
+ assert(res.status == 200, "failed to fetch token: status " .. res.status)
+
+ return res.body
+end
+
+
+function _M:get_token(args, query_args)
+ local ret = cjson.decode(self:token_request(args, query_args))
+ self.token_response = ret
+ self.token_time = ngx.now()
+ assert(ret.access_token, "no access_token found in token response")
+ return ret
+end
+
+
+function _M:refresh_token()
+ local token_response = assert(self.token_response, "no token_response found")
+ local refresh_token = assert(token_response.refresh_token, "no refresh_token found in token_response")
+
+ local refresh_expires_in = token_response.refresh_expires_in
+
+ if refresh_expires_in and ngx.now() - self.token_time > refresh_expires_in then
+ if self.auto_login then
+ return self:login()
+ else
+ error("refresh token expired")
+ end
+ end
+
+ return self:get_token({
+ grant_type = "refresh_token",
+ refresh_token = refresh_token,
+ })
+end
+
+
+function _M:authenticate_request(args, query_args)
+ args = args or {}
+ local auth_endpoint = assert(self.authorization_endpoint, "no authorization_endpoint found")
+
+ if args.client_secret == nil then
+ args.client_secret = false
+ end
+
+ if args.redirect_uri == nil then
+ args.redirect_uri = self.client_uri .. self.auth_callback_uri
+ end
+
+ args.response_type = args.response_type or "code"
+ args.code_challenge_method = self.code_challenge_method or args.code_challenge_method or "S256"
+ if args.code_challenge_method == "S256" then
+ args.code_challenge = base64url_encode(jwa.S256(args.code_challenge))
+ end
+
+ local dpop_jkt
+
+ if self.auth_dpop then
+ dpop_jkt = jwks.compute_thumbprint(assert(self.client_jwk_public))
+ end
+
+ local res = self:idp_request(auth_endpoint, {
+ method = "POST",
+ args = args,
+ dpop_jkt = dpop_jkt,
+ }, query_args, "public")
+
+ if res.status == 302 then
+ local redirect_uri = assert(res.headers["Location"], "no redirect_uri found")
+ local callback_args = redirect_uri:match(args.redirect_uri .. "%?([^?]+)")
+ callback_args = ngx.decode_args(callback_args)
+ if callback_args.error then
+ error("authenticate failed: " .. (callback_args.error_description or callback_args.error))
+ end
+
+ return res
+ end
+
+ assert(res.status == 200, "failed to request for authentication: status " .. res.status)
+
+ return res
+end
+
+
+-- auth_code flow
+function _M:login(user_login_simulator)
+ user_login_simulator = user_login_simulator or self.user_login_simulator
+
+ local code_verifier
+ if self.use_pkce then
+ code_verifier = base64url_encode(utils.random_string(64))
+ end
+
+ local res = self:authenticate_request({
+ grant_type = "authorization_code",
+ code_challenge = code_verifier
+ })
+
+ local args = assert(user_login_simulator(self, res))
+ local code = assert(args.code, "no code found")
+
+ return self:get_token({
+ grant_type = "authorization_code",
+ code = code,
+ code_verifier = code_verifier,
+ auth_method = "code",
+ redirect_uri = self.client_uri .. self.auth_callback_uri,
+ })
+end
+
+
+local function extract_args(res)
+ local redirect_uri = assert(res.headers["Location"], "no redirect_uri found")
+ return ngx.decode_args(redirect_uri:match("%?(.*)"))
+end
+
+
+function _M.keycloak_login(client, res)
+ if res.status == 302 then
+ return extract_args(res)
+ end
+
+ local login_page = res.body
+ local login_url = login_page:match('action="([^"]+)"')
+ local login_args = {
+ username = client.username,
+ password = client.password,
+ }
+
+ local login_res = client:idp_request(login_url, {
+ method = "POST",
+ args = login_args,
+ })
+
+ if login_res.status == 200 then
+ local failure_reason = login_res.body:match(']*>%s*([^<]-)%s*')
+ if failure_reason then
+ error("login failed: " .. failure_reason)
+
+ else
+ error("login failed with unknown reason")
+ end
+ end
+
+ assert(login_res.status == 302, "failed to login: status " .. login_res.status)
+
+ return extract_args(login_res)
+end
+
+
+function _M.rp_request(self, url, opts)
+ opts = opts or {}
+ opts.headers = opts.headers or {}
+
+ local access_token = self:get_access_token()
+
+ opts.headers["Authorization"] = opts.headers["Authorization"] or self.token_response.token_type .. " " .. access_token
+ opts.headers["Cookie"] = cookies_to_header(self.cookies)
+ opts.method = opts.method or "GET"
+
+ if not url:match("^https?://") then
+ url = self.client_uri .. url
+ end
+
+ return self:request(url, opts, true)
+end
+
+
+function _M.get_access_token(self)
+ if not self.token_response then
+ if self.auto_login then
+ self:login()
+ else
+ error("no token")
+ end
+ end
+
+ if ngx.now() - self.token_time > self.token_response.expires_in then
+ self:refresh_token()
+ end
+
+ return assert(self.token_response.access_token)
+end
+
+
+return _M
\ No newline at end of file
diff --git a/kong-versions/3.9.0.0/kong/spec/helpers/perf.lua b/kong-versions/3.9.0.0/kong/spec/helpers/perf.lua
new file mode 100644
index 00000000..46de48be
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/helpers/perf.lua
@@ -0,0 +1,581 @@
+-- This software is copyright Kong Inc. and its licensors.
+-- Use of the software is subject to the agreement between your organization
+-- and Kong Inc. If there is no such agreement, use is governed by and
+-- subject to the terms of the Kong Master Software License Agreement found
+-- at https://konghq.com/enterprisesoftwarelicense/.
+-- [ END OF LICENSE 0867164ffc95e54f04670b5169c09574bdbd9bba ]
+
+
+--- Module with performance test tools
+-- @module spec.helpers.perf
+
+local pl_tablex = require("pl.tablex")
+
+local logger = require("spec.helpers.perf.logger")
+local utils = require("spec.helpers.perf.utils")
+local git = require("spec.helpers.perf.git")
+local charts = require("spec.helpers.perf.charts")
+local read_all_env = require("kong.cmd.utils.env").read_all
+
+local my_logger = logger.new_logger("[controller]")
+
+utils.register_busted_hook()
+utils.add_lua_package_paths()
+
+charts.register_busted_hook()
+
+-- how many times for each "driver" operation
+local RETRY_COUNT = 3
+local DRIVER
+local DRIVER_NAME
+local LAST_KONG_VERSION
+
+-- Real user facing functions
+local driver_functions = {
+ "start_worker", "start_kong", "stop_kong", "setup", "setup_kong", "teardown",
+ "get_start_load_cmd", "get_start_stapxx_cmd", "get_wait_stapxx_cmd",
+ "generate_flamegraph", "save_error_log", "get_admin_uri",
+ "save_pgdump", "load_pgdump", "get_based_version", "remote_execute",
+}
+
+local function check_driver_sanity(mod)
+ if type(mod) ~= "table" then
+ error("Driver must return a table")
+ end
+
+ for _, func in ipairs(driver_functions) do
+ if not mod[func] then
+ error("Driver " .. debug.getinfo(mod.new, "S").source ..
+ " must implement function " .. func, 2)
+ end
+ end
+end
+
+local known_drivers = { "docker", "terraform" }
+
+--- Set the driver to use.
+-- @function use_driver
+-- @tparam string name name of the driver to use
+-- @tparam[opt] table opts config parameters passed to the driver
+-- @return nothing. Throws an error if any.
+local function use_driver(name, opts)
+ name = name or "docker"
+
+ if not pl_tablex.find(known_drivers, name) then
+ local err = ("Unknown perf test driver \"%s\", expect one of \"%s\""):format(
+ name, table.concat(known_drivers, "\", \"")
+ )
+ error(err, 2)
+ end
+
+ local pok, mod = pcall(require, "spec.helpers.perf.drivers." .. name)
+
+ if not pok then
+ error(("Unable to load perf test driver %s: %s"):format(name, mod))
+ end
+
+ check_driver_sanity(mod)
+
+ DRIVER = mod.new(opts)
+ DRIVER_NAME = name
+end
+
+--- Set driver operation retry count
+-- @function set_retry_count
+-- @tparam number try the number of retries for each driver operation
+-- @return nothing.
+local function set_retry_count(try)
+ if type(try) ~= "number" then
+ error("expect a number, got " .. type(try))
+ end
+ RETRY_COUNT = try
+end
+
+--- Setup a default perf test instance.
+-- Creates an instance that's ready to use on most common cases including Github Actions
+-- @function use_defaults
+-- @return nothing.
+local function use_defaults()
+ logger.set_log_level(ngx.DEBUG)
+ set_retry_count(3)
+
+ local driver = os.getenv("PERF_TEST_DRIVER") or "docker"
+ local use_daily_image = os.getenv("PERF_TEST_USE_DAILY_IMAGE")
+ local ssh_user
+
+ if driver == "terraform" then
+ local seperate_db_node = not not os.getenv("PERF_TEST_SEPERATE_DB_NODE")
+
+ local tf_provider = os.getenv("PERF_TEST_TERRAFORM_PROVIDER") or "equinix-metal"
+ local tfvars = {}
+ if tf_provider == "equinix-metal" then
+ tfvars = {
+ -- Kong Benchmarking
+ metal_project_id = os.getenv("PERF_TEST_METAL_PROJECT_ID"),
+ -- TODO: use an org token
+ metal_auth_token = os.getenv("PERF_TEST_METAL_AUTH_TOKEN"),
+ metal_plan = os.getenv("PERF_TEST_METAL_PLAN"), -- "c3.small.x86"
+ -- metal_region = ["sv15", "sv16", "la4"], -- not support setting from lua for now
+ metal_os = os.getenv("PERF_TEST_METAL_OS"), -- "ubuntu_20_04",
+ }
+ elseif tf_provider == "digitalocean" then
+ tfvars = {
+ do_project_name = os.getenv("PERF_TEST_DIGITALOCEAN_PROJECT_NAME"), -- "Benchmark",
+ do_token = os.getenv("PERF_TEST_DIGITALOCEAN_TOKEN"),
+ do_size = os.getenv("PERF_TEST_DIGITALOCEAN_SIZE"), -- "c2-8vpcu-16gb",
+ do_region = os.getenv("PERF_TEST_DIGITALOCEAN_REGION"), --"sfo3",
+ do_os = os.getenv("PERF_TEST_DIGITALOCEAN_OS"), -- "ubuntu-20-04-x64",
+ }
+ elseif tf_provider == "aws-ec2" then
+ tfvars = {
+ aws_region = os.getenv("PERF_TEST_AWS_REGION"), -- "us-east-2",
+ ec2_instance_type = os.getenv("PERF_TEST_EC2_INSTANCE_TYPE"), -- "c5a.2xlarge",
+ ec2_os = os.getenv("PERF_TEST_EC2_OS"), -- "ubuntu/images/hvm-ssd/ubuntu-focal-20.04-amd64-server-*",
+ }
+ ssh_user = "ubuntu"
+ elseif tf_provider == "bring-your-own" then
+ tfvars = {
+ kong_ip = os.getenv("PERF_TEST_BYO_KONG_IP"),
+ kong_internal_ip = os.getenv("PERF_TEST_BYO_KONG_INTERNAL_IP"), -- fallback to kong_ip
+ db_ip = os.getenv("PERF_TEST_BYO_DB_IP"),
+ db_internal_ip = os.getenv("PERF_TEST_BYO_DB_INTERNAL_IP"), -- fallback to db_ip
+ worker_ip = os.getenv("PERF_TEST_BYO_WORKER_IP"),
+ worker_internal_ip = os.getenv("PERF_TEST_BYO_WORKER_INTERNAL_IP"), -- fallback to worker_ip
+ ssh_key_path = os.getenv("PERF_TEST_BYO_SSH_KEY_PATH") or "root",
+ }
+ ssh_user = os.getenv("PERF_TEST_BYO_SSH_USER")
+ end
+
+ tfvars.seperate_db_node = seperate_db_node
+
+ use_driver("terraform", {
+ provider = tf_provider,
+ tfvars = tfvars,
+ use_daily_image = use_daily_image,
+ seperate_db_node = seperate_db_node,
+ ssh_user = ssh_user,
+ })
+ else
+ use_driver(driver, {
+ use_daily_image = use_daily_image,
+ })
+ end
+end
+
+local function invoke_driver(method, ...)
+ if not DRIVER then
+ error("No driver selected, call use_driver first", 2)
+ end
+
+ if not DRIVER[method] then
+ my_logger.warn(method, " not implemented by driver ", DRIVER_NAME)
+ return
+ end
+
+ local happy
+ local r, err
+ for i = 1, RETRY_COUNT + 1 do
+ r, err = DRIVER[method](DRIVER, ...)
+ if not err then
+ happy = true
+ break
+ end
+
+ my_logger.warn("failed in ", method, ": ", err or "nil", ", tries: ", i)
+ end
+
+ if not happy then
+ error(method .. " finally failed" .. (RETRY_COUNT > 0 and " after " .. RETRY_COUNT .. " retries" or ""), 2)
+ end
+
+ return r
+end
+
+local _M = {
+ use_driver = use_driver,
+ set_retry_count = set_retry_count,
+ use_defaults = use_defaults,
+
+ new_logger = logger.new_logger,
+ set_log_level = logger.set_log_level,
+
+ setenv = utils.setenv,
+ unsetenv = utils.unsetenv,
+ execute = utils.execute,
+ wait_output = utils.wait_output,
+ parse_docker_image_labels = utils.parse_docker_image_labels,
+ clear_loaded_package = utils.clear_loaded_package,
+
+ git_checkout = git.git_checkout,
+ git_restore = git.git_restore,
+ get_kong_version = git.get_kong_version,
+}
+
+--- Start the worker (nginx) with given conf with multiple ports.
+-- @tparam string conf the Nginx snippet under server{} context
+-- @tparam[opt=1] number port_count number of ports the upstream listens to
+-- @return upstream_uri string or table if `port_count` is more than 1
+function _M.start_worker(conf, port_count)
+ port_count = port_count or 1
+ local ret = invoke_driver("start_worker", conf, port_count)
+ return port_count == 1 and ret[1] or ret
+end
+
+--- Start Kong with given version and conf.
+-- @tparam[opt] table kong_confs Kong configuration as a lua table
+-- @tparam[opt] table driver_confs driver configuration as a lua table
+-- @return nothing. Throws an error if any.
+function _M.start_kong(kong_confs, driver_confs)
+ kong_confs = kong_confs or {}
+ for k, v in pairs(read_all_env()) do
+ k = k:match("^KONG_([^=]+)")
+ k = k and k:lower()
+ if k then
+ kong_confs[k] = os.getenv("KONG_" .. k:upper())
+ end
+ end
+ return invoke_driver("start_kong", kong_confs, driver_confs or {})
+end
+
+--- Stop Kong.
+-- @param ... args passed to the driver "stop_kong" command
+-- @return nothing. Throws an error if any.
+function _M.stop_kong(...)
+ return invoke_driver("stop_kong", ...)
+end
+
+--- Setup environment.
+-- This is not necessary if `setup_kong` is called
+-- @return nothing. Throws an error if any.
+function _M.setup()
+ return invoke_driver("setup")
+end
+
+--- Installs Kong. Setup env vars and return the configured helpers utility
+-- @tparam string version Kong version
+-- @return table the `helpers` utility as if it's require("spec.helpers")
+function _M.setup_kong(version)
+ LAST_KONG_VERSION = version
+ return invoke_driver("setup_kong", version)
+end
+
+--- Cleanup the test.
+-- @tparam[opt=false] boolean full teardown all stuff, including those will make next test spin up faster
+-- @return nothing. Throws an error if any.
+function _M.teardown(full)
+ LAST_KONG_VERSION = nil
+ return invoke_driver("teardown", full)
+end
+
+local load_thread
+local load_should_stop
+
+--- Start to send load to Kong.
+-- @tparam table opts options table
+-- @tparam[opt="/"] string opts.path request path
+-- @tparam[opt="http://kong-ip:kong-port/"] string opts.uri base URI except path
+-- @tparam[opt=1000] number opts.connections connection count
+-- @tparam[opt=5] number opts.threads request thread count
+-- @tparam[opt=10] number opts.duration perf test duration in seconds
+-- @tparam[opt] string opts.script content of wrk script
+-- @tparam[opt] string opts.kong_name specify the kong name to send load to; will automatically pick one if not specified
+-- @return nothing. Throws an error if any.
+function _M.start_load(opts)
+ if load_thread then
+ error("load is already started, stop it using wait_result() first", 2)
+ end
+
+ local path = opts.path or ""
+ -- strip leading /
+ if path:sub(1, 1) == "/" then
+ path = path:sub(2)
+ end
+
+ local prog = opts.wrk2 and "wrk2" or "wrk"
+ if opts.wrk2 then
+ if DRIVER_NAME ~= "terraform" then
+ error("wrk2 not supported in docker driver", 2)
+ elseif not opts.rate then
+ error("wrk2 requires rate", 2)
+ end
+ end
+
+ local load_cmd_stub = prog .. " -c " .. (opts.connections or 1000) ..
+ " -t " .. (opts.threads or 5) ..
+ " -d " .. (opts.duration or 10) .. "s" ..
+ (opts.wrk2 and " -R " .. opts.rate or "") ..
+ " %s " .. -- script place holder
+ " %s/" .. path ..
+ " --latency"
+
+ local load_cmd = invoke_driver("get_start_load_cmd", load_cmd_stub, opts.script, opts.uri, opts.kong_name)
+ load_should_stop = false
+
+ load_thread = ngx.thread.spawn(function()
+ return utils.execute(load_cmd,
+ {
+ stop_signal = function() if load_should_stop then return 9 end end,
+ })
+ end)
+end
+
+local stapxx_thread
+local stapxx_should_stop
+
+--- Start to send load to Kong.
+-- @tparam string sample_name stapxx sample name
+-- @tparam string arg extra arguments passed to stapxx script
+-- @tparam table driver_confs driver configuration as a lua table
+-- @return nothing. Throws an error if any.
+function _M.start_stapxx(sample_name, arg, driver_confs)
+ if stapxx_thread then
+ error("stapxx is already started, stop it using wait_result() first", 2)
+ end
+
+ local start_cmd = invoke_driver("get_start_stapxx_cmd", sample_name, arg, driver_confs or {})
+ stapxx_should_stop = false
+
+ stapxx_thread = ngx.thread.spawn(function()
+ return utils.execute(start_cmd,
+ {
+ stop_signal = function() if stapxx_should_stop then return 3 end end,
+ })
+ end)
+
+ local wait_cmd = invoke_driver("get_wait_stapxx_cmd")
+ if not utils.wait_output(wait_cmd, "stap_", 30) then
+ return false, "timeout waiting systemtap probe to load"
+ end
+
+ return true
+end
+
+--- Wait for the load test to finish.
+-- @treturn string the test report text
+function _M.wait_result()
+ if not load_thread then
+ error("load haven't been started or already collected, " ..
+ "start it using start_load() first", 2)
+ end
+
+ -- local timeout = opts and opts.timeout or 3
+ -- local ok, res, err
+
+ -- ngx.update_time()
+ -- local s = ngx.now()
+ -- while not found and ngx.now() - s <= timeout do
+ -- ngx.update_time()
+ -- ngx.sleep(0.1)
+ -- if coroutine.status(self.load_thread) ~= "running" then
+ -- break
+ -- end
+ -- end
+ -- print(coroutine.status(self.load_thread), coroutine.running(self.load_thread))
+
+ -- if coroutine.status(self.load_thread) == "running" then
+ -- self.load_should_stop = true
+ -- return false, "timeout waiting for load to stop (" .. timeout .. "s)"
+ -- end
+
+ if stapxx_thread then
+ local ok, res, err = ngx.thread.wait(stapxx_thread)
+ stapxx_should_stop = true
+ stapxx_thread = nil
+ if not ok or err then
+ my_logger.warn("failed to wait stapxx to finish: ",
+ (res or "nil"),
+ " err: " .. (err or "nil"))
+ end
+ my_logger.debug("stap++ output: ", res)
+ end
+
+ local ok, res, err = ngx.thread.wait(load_thread)
+ load_should_stop = true
+ load_thread = nil
+
+ if not ok or err then
+ error("failed to wait result: " .. (res or "nil") ..
+ " err: " .. (err or "nil"))
+ end
+
+ return res
+end
+
+local function sum(t)
+ local s = 0
+ for _, i in ipairs(t) do
+ if type(i) == "number" then
+ s = s + i
+ end
+ end
+
+ return s
+end
+
+-- Note: could also use custom lua code in wrk
+local nan = 0/0
+local function parse_wrk_result(r)
+ local rps = string.match(r, "Requests/sec:%s+([%d%.]+)")
+ rps = tonumber(rps)
+ local count = string.match(r, "([%d]+)%s+requests in")
+ count = tonumber(count)
+
+ local lat_avg, avg_m, lat_max, max_m = string.match(r, "Latency%s+([%d%.]+)([mu]?)s%s+[%d%.]+[mu]?s%s+([%d%.]+)([mu]?)s")
+ lat_avg = tonumber(lat_avg or nan) * (avg_m == "u" and 0.001 or (avg_m == "m" and 1 or 1000))
+ lat_max = tonumber(lat_max or nan) * (max_m == "u" and 0.001 or (max_m == "m" and 1 or 1000))
+
+ local p90, p90_m = string.match(r, "90%%%s+([%d%.]+)([mu]?)s")
+ local p99, p99_m = string.match(r, "99%%%s+([%d%.]+)([mu]?)s")
+ p90 = tonumber(p90 or nan) * (p90_m == "u" and 0.001 or (p90_m == "m" and 1 or 1000))
+ p99 = tonumber(p99 or nan) * (p99_m == "u" and 0.001 or (p99_m == "m" and 1 or 1000))
+
+ return rps, count, lat_avg, lat_max, p90, p99
+end
+
+--- Compute average of RPS and latency from multiple wrk output.
+-- @tparam table results the table holds raw wrk outputs
+-- @tparam string suite xaxis suite name
+-- @treturn string The human readable result of average RPS and latency
+function _M.combine_results(results, suite)
+ local count = #results
+ if count == 0 then
+ return "(no results)"
+ end
+
+ local rpss = table.new(count, 0)
+ local latencies_avg = table.new(count, 0)
+ local latencies_max = table.new(count, 0)
+ local latencies_p90 = table.new(count, 0)
+ local latencies_p99 = table.new(count, 0)
+ local count = 0
+
+ for i, result in ipairs(results) do
+ local r, c, la, lm, p90, p99 = parse_wrk_result(result)
+ rpss[i] = r
+ count = count + c
+ latencies_avg[i] = la * c
+ latencies_max[i] = lm
+ latencies_p90[i] = p90
+ latencies_p99[i] = p99
+ end
+
+ local rps = sum(rpss) / #results
+ local latency_avg = sum(latencies_avg) / count
+ local latency_max = math.max(unpack(latencies_max))
+
+ if LAST_KONG_VERSION then
+ charts.ingest_combined_results(LAST_KONG_VERSION, {
+ rpss = rpss,
+ rps = rps,
+ latencies_p90 = latencies_p90,
+ latencies_p99 = latencies_p99,
+ latency_max = latency_max,
+ latency_avg = latency_avg,
+ }, suite)
+ end
+
+ return ([[
+RPS Avg: %3.2f
+Latency Avg: %3.2fms Max: %3.2fms
+ P90 (ms): %s
+ P99 (ms): %s
+ ]]):format(rps, latency_avg, latency_max, table.concat(latencies_p90, ", "), table.concat(latencies_p99, ", "))
+end
+
+--- Wait until the systemtap probe is loaded.
+-- @tparam[opt=20] number timeout in seconds
+function _M.wait_stap_probe(timeout)
+ return invoke_driver("wait_stap_probe", timeout or 20)
+end
+
+--- Generate the flamegraph and return SVG.
+-- @tparam string filename the target filename to store the generated SVG.
+-- @tparam[opt] string title the title for flamegraph
+-- @tparam[opt] string opts the command line options string (not a table) for `flamegraph.pl`
+-- @return Nothing. Throws an error if any.
+function _M.generate_flamegraph(filename, title, opts)
+ if not filename then
+ error("filename must be specified for generate_flamegraph")
+ end
+ if string.sub(filename, #filename-3, #filename):lower() ~= ".svg" then
+ filename = filename .. ".svg"
+ end
+
+ if not title then
+ title = "Flame graph"
+ end
+
+ -- If current test is git-based, also attach the Kong binary package
+ -- version it based on
+ if git.is_git_repo() and git.is_git_based() then
+ -- use driver to get the version; driver could implement version override
+ -- based on setups (like using the daily image)
+ local v = invoke_driver("get_based_version")
+ title = title .. " (based on " .. v .. ")"
+ end
+
+ local out = invoke_driver("generate_flamegraph", title, opts)
+
+ local f, err = io.open(filename, "w")
+ if not f then
+ error("failed to open " .. filename .. " for writing flamegraph: " .. err)
+ end
+
+ f:write(out)
+ f:close()
+
+ my_logger.debug("flamegraph written to ", filename)
+end
+
+--- Enable or disable charts generation.
+-- @tparam[opt=false] boolean enabled enable or not
+-- @return Nothing. Throws an error if any.
+function _M.enable_charts(enabled)
+ return enabled and charts.on() or charts.off()
+end
+
+
+--- Save Kong error log locally.
+-- @tparam string filename filename where to save the log
+-- @return Nothing. Throws an error if any.
+function _M.save_error_log(filename)
+ if not filename then
+ error("filename must be specified for save_error_log")
+ end
+
+ invoke_driver("save_error_log", filename)
+
+ my_logger.debug("Kong error log written to ", filename)
+end
+
+--- Get the Admin URI accessible from worker.
+-- @tparam[opt] string kong_name specify the kong name; will automatically pick one if not specified
+-- @return Nothing. Throws an error if any.
+function _M.get_admin_uri(kong_name)
+ return invoke_driver("get_admin_uri", kong_name)
+end
+
+--- Save a .sql file of the database.
+-- @tparam string path the .sql file path to save to
+-- @return Nothing. Throws an error if any.
+function _M.save_pgdump(path)
+ return invoke_driver("save_pgdump", path)
+end
+
+--- Load a .sql file into the database.
+-- @tparam string path the .sql file path
+-- @tparam[opt=false] boolean dont_patch_service set to true to skip update all services to upstream started by this framework
+-- @return Nothing. Throws an error if any.
+function _M.load_pgdump(path, dont_patch_service)
+ return invoke_driver("load_pgdump", path, dont_patch_service)
+end
+
+--- Execute command on remote instance.
+-- @tparam string node_type the node to exeute the command on, can be; "kong", "db", or "worker"
+-- @tparam array cmds array of commands to execute
+-- @tparam boolean continue_on_error if true, will continue on error
+function _M.remote_execute(node_type, cmds, continue_on_error)
+ return invoke_driver("remote_execute", node_type, cmds, continue_on_error)
+end
+
+return _M
diff --git a/kong-versions/3.9.0.0/kong/spec/helpers/perf/charts.lua b/kong-versions/3.9.0.0/kong/spec/helpers/perf/charts.lua
new file mode 100644
index 00000000..4aa2c922
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/helpers/perf/charts.lua
@@ -0,0 +1,121 @@
+-- This software is copyright Kong Inc. and its licensors.
+-- Use of the software is subject to the agreement between your organization
+-- and Kong Inc. If there is no such agreement, use is governed by and
+-- subject to the terms of the Kong Master Software License Agreement found
+-- at https://konghq.com/enterprisesoftwarelicense/.
+-- [ END OF LICENSE 0867164ffc95e54f04670b5169c09574bdbd9bba ]
+
+local math = require "math"
+local utils = require("spec.helpers.perf.utils")
+local logger = require("spec.helpers.perf.logger")
+local cjson = require "cjson"
+local cycle_aware_deep_copy = require("kong.tools.table").cycle_aware_deep_copy
+
+local fmt = string.format
+local my_logger = logger.new_logger("[charts]")
+
+math.randomseed(ngx.now())
+
+local options
+local current_test_element
+local enabled = true
+local unsaved_results_lookup = {}
+local unsaved_results = {}
+
+local function gen_plots(results, fname, opts)
+ local shell = require "resty.shell"
+ opts = opts or options
+
+ if not results or not next(results) then
+ my_logger.warn("no result found, skipping plot generation")
+ return
+ end
+
+ shell.run("mkdir -p output", nil, 0)
+
+ local output_data = {
+ options = opts,
+ data = results,
+ }
+
+ local f = io.open(fmt("output/%s.data.json", fname), "w")
+ f:write(cjson.encode(output_data))
+ f:close()
+ my_logger.info(fmt("parsed result saved to output/%s.json", fname))
+
+ return true
+end
+
+local function on_test_start(element, parent, status, debug)
+ if not enabled then
+ return true
+ end
+
+ current_test_element = element
+end
+
+local function on_test_end(element, parent, status, debug)
+ if not enabled then
+ return true
+ end
+
+end
+
+local function on_file_end(file)
+ if not enabled then
+ return true
+ end
+
+ local results = unsaved_results
+ unsaved_results = {}
+
+ local fname = file.name:gsub("[:/]", "#"):gsub("[ ,]", "_"):gsub("__", "_")
+ return gen_plots(results, fname, options)
+end
+
+local function ingest_combined_results(ver, results, suite_name)
+ if not suite_name then
+ local desc = utils.get_test_descriptor(false, current_test_element)
+ -- escape lua patterns
+ local pattern = ver:gsub([=[[%[%(%)%.%%%+%-%*%?%[%^%$%]]]=], "%%%1")
+ -- remove version and surround string from title
+ suite_name = desc:gsub("%s?"..pattern, ""):gsub(pattern.."%s?", "")
+ end
+
+ if not unsaved_results_lookup[suite_name] then
+ unsaved_results_lookup[suite_name] = {}
+
+ elseif unsaved_results_lookup[suite_name][ver] then
+ my_logger.warn(fmt("version %s for \"%s\" already has results, current result will be discarded",
+ ver, suite_name))
+ return false
+ end
+
+ local row = cycle_aware_deep_copy(results)
+ row.version = ver
+ row.suite = suite_name
+
+ -- save as ordered-array
+ table.insert(unsaved_results, row)
+
+ return true
+end
+
+local function register_busted_hook(opts)
+ local busted = require("busted")
+
+ busted.subscribe({'file', 'end' }, on_file_end)
+ busted.subscribe({'test', 'start'}, on_test_start)
+ busted.subscribe({'test', 'end'}, on_test_end)
+end
+
+return {
+ gen_plots = gen_plots,
+ register_busted_hook = register_busted_hook,
+ ingest_combined_results = ingest_combined_results,
+ on = function() enabled = true end,
+ off = function() enabled = false end,
+ options = function(opts)
+ options = opts
+ end,
+}
diff --git a/kong-versions/3.9.0.0/kong/spec/helpers/perf/charts/.gitignore b/kong-versions/3.9.0.0/kong/spec/helpers/perf/charts/.gitignore
new file mode 100644
index 00000000..6e4266f3
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/helpers/perf/charts/.gitignore
@@ -0,0 +1,3 @@
+__pycache__/
+*.py[cod]
+*$py.class
diff --git a/kong-versions/3.9.0.0/kong/spec/helpers/perf/charts/charts.py b/kong-versions/3.9.0.0/kong/spec/helpers/perf/charts/charts.py
new file mode 100644
index 00000000..3d1c2454
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/helpers/perf/charts/charts.py
@@ -0,0 +1,127 @@
+import argparse
+import pprint
+from pathlib import Path
+import plotly.express as px
+from plotly.subplots import make_subplots
+import pandas as pd
+import textwrap
+import json
+
+pprint = pprint.PrettyPrinter(indent=4).pprint
+
+def adjust_fig_tick_y(fig, min_y, max_y, row):
+ if max_y - min_y <= 5:
+ fig.update_yaxes(range=[min_y*0.9, max_y*1.1], row=row)
+
+def main(args: dict):
+ fname = Path(args.file).stem
+ output_dir = args.output_dir
+
+ with open(args.file) as f:
+ input_json = json.load(f)
+
+ df = pd.DataFrame(input_json["data"])
+
+ pprint(df)
+
+ df["rps_error"] = df["rpss"].apply(max) - df["rpss"].apply(min)
+ df["latency_p99_error"] = df["latencies_p99"].apply(
+ max) - df["latencies_p99"].apply(min)
+ df["latency_p90_error"] = df["latencies_p90"].apply(
+ max) - df["latencies_p90"].apply(min)
+
+ suite_sequential = "options" in input_json and \
+ "suite_sequential" in input_json["options"] and \
+ input_json["options"]["suite_sequential"]
+
+ if suite_sequential:
+ # Suite must be int if suite_sequential is True, plotly uses suites as x-axis
+ df["suite"] = df["suite"].apply(int)
+ else:
+ # Wrap long labels as suites are string types
+ df["suite"] = df["suite"].apply(
+ lambda x: " ".join(textwrap.wrap(x, width=40)))
+
+ df.sort_values(by=["version", "suite"], inplace=True)
+
+ xaxis_title = "options" in input_json and \
+ "xaxis_title" in input_json["options"] and \
+ input_json["options"]["xaxis_title"] or "Test Suites"
+
+ # RPS plot
+ fig_rps = px.bar(df, x="suite", y="rps", error_y="rps_error",
+ color="version", barmode="group", title="RPS",
+ labels={"suite": xaxis_title})
+
+ # flatten multiple values of each role into separate rows
+ df_p99 = df.explode("latencies_p99")
+ df_p90 = df.explode("latencies_p90")
+
+ # P99/90 plot
+ fig_p99 = px.box(df_p99, x="suite", y="latencies_p99", color="version",
+ points="all", title="P99 Latency", boxmode="group",
+ labels={"suite": xaxis_title, "latencies_p99": "P99 Latency (ms)"})
+ adjust_fig_tick_y(fig_p99, min(df_p99['latencies_p99']), max(df_p99['latencies_p99']), 1)
+
+ fig_p90 = px.box(df_p90, x="suite", y="latencies_p90", color="version",
+ points="all", title="P90 Latency", boxmode="group",
+ labels={"suite": xaxis_title, "latencies_p90": "P90 Latency (ms)"})
+ adjust_fig_tick_y(fig_p90, min(df_p90['latencies_p90']), max(df_p90['latencies_p90']), 1)
+
+ # Max latency
+ fig_max_latency = px.bar(df, x="suite", y="latency_max", color="version",
+ barmode="group", title="Max Latency",
+ labels={"suite": xaxis_title, "latency_max": "Max Latency (ms)"})
+
+ if suite_sequential:
+ # Ordinary Least Square Regression
+ fig_p99 = px.scatter(
+ df_p99, x="suite", y="latencies_p99", color="version", trendline="ols",
+ labels={"suite": xaxis_title, "latencies_p99": "P99 Latency (ms)"},
+ title="P99 Latency")
+ fig_p90 = px.scatter(
+ df_p90, x="suite", y="latencies_p90", color="version", trendline="ols",
+ labels={"suite": xaxis_title, "latencies_p90": "P90 Latency (ms)"},
+ title="P90 Latency")
+ fig_max_latency = px.scatter(
+ df, x="suite", y="latency_max", color="version", trendline="ols",
+ labels={"suite": xaxis_title, "latency_max": "Max Latency (ms)"},
+ title="Max Latency")
+
+ # RPS and P99 plot
+ combined = make_subplots(rows=2, cols=1, subplot_titles=[
+ fig_rps.layout.title.text, fig_p99.layout.title.text], vertical_spacing=0.12)
+ combined.add_traces(fig_rps.data)
+ combined.add_traces(fig_p99.data, rows=[
+ 2]*len(fig_p99.data), cols=[1]*len(fig_p99.data))
+ combined.update_xaxes(title_text=xaxis_title)
+
+ # Adjust y-axis ticks only if tickes are too close
+ if not suite_sequential:
+ adjust_fig_tick_y(combined, min(df_p99['latencies_p99']), max(df_p99['latencies_p99']), 2)
+
+ combined.update_yaxes(title_text="RPS")
+ combined.update_yaxes(title_text="P99 Latency (ms)", row=2)
+ combined.update_layout(title_text=fname, boxmode="group")
+ combined.write_image(
+ Path(output_dir, fname + ".combined.png"), width=1080, height=1080, scale=2)
+ combined.write_image(
+ Path(output_dir, fname + ".combined.svg"), width=1080, height=1080, scale=2)
+
+ # HTML is seperated and interactive graphs
+ with open(Path(output_dir, fname + ".plots.html"), "w") as f:
+ f.write("
" + fname + " Report:
")
+ f.write(fig_rps.to_html(include_plotlyjs="cdn", full_html=False))
+ f.write(fig_p99.to_html(include_plotlyjs=False, full_html=False))
+ f.write(fig_p90.to_html(include_plotlyjs=False, full_html=False))
+ f.write(fig_max_latency.to_html(
+ include_plotlyjs=False, full_html=False))
+
+if __name__ == "__main__":
+ parser = argparse.ArgumentParser()
+ parser.add_argument("file", help="path of json result file")
+ parser.add_argument("-o", "--output-dir", default="",
+ help="whether the suite is sequential")
+ args = parser.parse_args()
+
+ main(args)
diff --git a/kong-versions/3.9.0.0/kong/spec/helpers/perf/charts/requirements.txt b/kong-versions/3.9.0.0/kong/spec/helpers/perf/charts/requirements.txt
new file mode 100644
index 00000000..1e554d3a
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/helpers/perf/charts/requirements.txt
@@ -0,0 +1,4 @@
+pandas==1.4.3
+plotly==5.9.0
+statsmodels==0.13.2
+kaleido==0.2.1
diff --git a/kong-versions/3.9.0.0/kong/spec/helpers/perf/drivers/docker.lua b/kong-versions/3.9.0.0/kong/spec/helpers/perf/drivers/docker.lua
new file mode 100644
index 00000000..bf3d3f71
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/helpers/perf/drivers/docker.lua
@@ -0,0 +1,629 @@
+-- This software is copyright Kong Inc. and its licensors.
+-- Use of the software is subject to the agreement between your organization
+-- and Kong Inc. If there is no such agreement, use is governed by and
+-- subject to the terms of the Kong Master Software License Agreement found
+-- at https://konghq.com/enterprisesoftwarelicense/.
+-- [ END OF LICENSE 0867164ffc95e54f04670b5169c09574bdbd9bba ]
+
+local nkeys = require "table.nkeys"
+local perf = require("spec.helpers.perf")
+local tools = require("kong.tools.rand")
+local helpers
+
+local _M = {}
+local mt = {__index = _M}
+
+local UPSTREAM_PORT = 18088
+local KONG_DEFAULT_HYBRID_CERT = "/etc/kong-hybrid-cert.pem"
+local KONG_DEFAULT_HYBRID_CERT_KEY = "/etc/kong-hybrid-key.pem"
+
+function _M.new(opts)
+ return setmetatable({
+ opts = opts,
+ log = perf.new_logger("[docker]"),
+ psql_ct_id = nil,
+ kong_ct_ids = {},
+ worker_ct_id = nil,
+ daily_image_desc = nil,
+ }, mt)
+end
+
+local function start_container(cid)
+ if not cid then
+ return false, "container does not exist"
+ end
+
+ local _, err = perf.execute("docker start " .. cid)
+ if err then
+ return false, "docker start:" .. err
+ end
+
+ local out, err = perf.execute("docker inspect --format='{{.State.Running}}' " .. cid)
+ if err then
+ return false, "docker inspect:" .. err
+ end
+
+ if out:gsub("\n", "") ~= "true" then
+ local out, err = perf.execute("docker logs -n5 " .. cid)
+ if err then
+ return false, "docker logs:" .. err
+ end
+ return false, out
+ end
+
+ return true
+end
+
+local function create_container(self, args, img, cmd)
+ local out, err = perf.execute("docker images --format '{{.Repository}}:{{.Tag}}' " .. img)
+ -- plain pattern find
+ if err or not out:find(img, nil, true) then
+ local _, err = perf.execute("docker pull " .. img, { logger = self.log.log_exec })
+ if err then
+ return false, err
+ end
+ end
+
+ args = args or ""
+ cmd = cmd or ""
+ out, err = perf.execute("docker create " .. args .. " " .. img .. " " .. cmd)
+ if err then
+ return false, err
+ end
+ local cid = out:match("^[a-f0-9]+$")
+ if not cid then
+ return false, "invalid container ID: " .. out
+ end
+ return cid
+end
+
+local function get_container_port(cid, ct_port)
+ local out, err = perf.execute(
+ "docker inspect " ..
+ "--format='{{range $p, $conf := .NetworkSettings.Ports}}" ..
+ "{{if eq $p \"" .. ct_port .. "\" }}{{(index $conf 0).HostPort}}{{end}}" ..
+ "{{end}}' " .. cid)
+ if err then
+ return false, "docker inspect:" .. err .. ": " .. (out or "nil")
+ end
+
+ return tonumber(out)
+end
+
+local function get_container_vip(cid)
+ local out, err = perf.execute("docker inspect --format='{{.NetworkSettings.Networks.bridge.IPAddress}}' " .. cid)
+ if err then
+ return false, "docker inspect:" .. err .. ": " .. (out or "nil")
+ end
+
+ return out
+end
+
+function _M:teardown()
+ self.setup_kong_called = false
+
+ local ct_ids = {"worker_ct_id", "psql_ct_id" }
+ for _, cid in ipairs(ct_ids) do
+ if self[cid] then
+ perf.execute("docker rm -f " .. self[cid], { logger = self.log.log_exec })
+ self[cid] = nil
+ end
+ end
+
+ for conf_id, kong_ct_id in pairs(self.kong_ct_ids) do
+ perf.execute("docker rm -f " .. kong_ct_id, { logger = self.log.log_exec })
+ self.kong_ct_ids[conf_id] = nil
+ end
+
+ perf.git_restore()
+
+ return true
+end
+
+local function prepare_spec_helpers(self, use_git, version)
+ local psql_port, err = get_container_port(self.psql_ct_id, "5432/tcp")
+ if not psql_port then
+ return false, "failed to get psql port: " .. (err or "nil")
+ end
+
+ -- wait
+ if not perf.wait_output("docker logs -f " .. self.psql_ct_id, "is ready to accept connections") then
+ return false, "timeout waiting psql to start (5s)"
+ end
+
+ self.log.info("psql is started to listen at port ", psql_port)
+ perf.setenv("KONG_PG_PORT", ""..psql_port)
+
+ ngx.sleep(3) -- TODO: less flaky
+
+ if not use_git then
+ local current_spec_helpers_version = perf.get_kong_version(true)
+ if current_spec_helpers_version ~= version then
+ self.log.info("Current spec helpers version " .. current_spec_helpers_version ..
+ " doesn't match with version to be tested " .. version .. ", checking out remote version")
+
+ version = version:match("%d+%.%d+%.%d+%.%d+") or version:match("%d+%.%d+%.%d+")
+
+ perf.git_checkout(version) -- throws
+ end
+ end
+
+ -- reload the spec.helpers module, since it may have been loaded with
+ -- a different set of env vars
+ perf.clear_loaded_package()
+
+ -- just to let spec.helpers happy, we are not going to start kong locally
+ require("kong.meta")._DEPENDENCIES.nginx = {"0.0.0.0", "9.9.9.9"}
+
+ helpers = require("spec.helpers")
+
+ package.loaded['kong.meta'] = nil
+ require("kong.meta")
+
+ perf.unsetenv("KONG_PG_PORT")
+
+ helpers.admin_client = function(timeout)
+ if nkeys(self.kong_ct_ids) < 1 then
+ error("helpers.admin_client can only be called after perf.start_kong")
+ end
+
+ -- find all kong containers with first one that exposes admin port
+ for _, kong_id in pairs(kong.ct_ids) do
+ local admin_port, err = get_container_port(kong_id, "8001/tcp")
+ if err then
+ error("failed to get kong admin port: " .. (err or "nil"))
+ end
+ if admin_port then
+ return helpers.http_client("127.0.0.1", admin_port, timeout or 60000)
+ end
+ -- not admin_port, it's fine, maybe it's a dataplane
+ end
+
+ error("failed to get kong admin port from all Kong containers")
+ end
+ return helpers
+end
+
+function _M:setup()
+ if not self.psql_ct_id then
+ local cid, err = create_container(self, "-p5432 " ..
+ "-e POSTGRES_HOST_AUTH_METHOD=trust -e POSTGRES_DB=kong_tests " ..
+ "-e POSTGRES_USER=kong " ..
+ "--name kong_perf_psql_$(date +%s)",
+ "postgres:13",
+ "-c max_connections=5000")
+ if err then
+ return false, "error running docker create when creating kong container: " .. err
+ end
+ self.psql_ct_id = cid
+ end
+
+ self.log.info("psql container ID is ", self.psql_ct_id)
+ local ok, err = start_container(self.psql_ct_id)
+ if not ok then
+ return false, "psql is not running: " .. err
+ end
+
+ return true
+end
+
+function _M:start_worker(conf, port_count)
+ conf = conf or [[
+ location = /test {
+ return 200;
+ }
+ ]]
+
+ local listeners = {}
+ for i=1,port_count do
+ listeners[i] = ("listen %d reuseport;"):format(UPSTREAM_PORT+i-1)
+ end
+ listeners = table.concat(listeners, "\n")
+
+ if not self.worker_ct_id then
+ local _, err = perf.execute(
+ "docker build --progress plain -t perf-test-worker -",
+ {
+ logger = self.log.log_exec,
+ stdin = ([[
+ FROM nginx:alpine
+ RUN apk update && apk add wrk
+ RUN echo -e '\
+ server {\
+ %s\
+ access_log off;\
+ location =/health { \
+ return 200; \
+ } \
+ %s \
+ }' > /etc/nginx/conf.d/perf-test.conf
+
+ # copy paste
+ ENTRYPOINT ["/docker-entrypoint.sh"]
+
+ STOPSIGNAL SIGQUIT
+
+ CMD ["nginx", "-g", "daemon off;"]
+ ]]):format(listeners:gsub("\n", "\\n"), conf:gsub("\n", "\\n"))
+ }
+ )
+ if err then
+ return false, err
+ end
+
+ local cid, err = create_container(self, "--name kong_perf_worker_$(date +%s) -p " .. UPSTREAM_PORT, "perf-test-worker")
+ if err then
+ return false, "error running docker create when creating worker: " .. err
+ end
+ self.worker_ct_id = cid
+ end
+
+ self.log.info("worker container ID is ", self.worker_ct_id)
+
+ local ok, err = start_container(self.worker_ct_id)
+ if not ok then
+ return false, "worker is not running: " .. err
+ end
+ ngx.sleep(3) -- TODO: less flaky
+
+ local worker_vip, err = get_container_vip(self.worker_ct_id)
+ if err then
+ return false, "unable to read worker container's private IP: " .. err
+ end
+
+ if not perf.wait_output("docker logs -f " .. self.worker_ct_id, " start worker process") then
+ self.log.info("worker container logs:")
+ perf.execute("docker logs " .. self.worker_ct_id, { logger = self.log.log_exec })
+ return false, "timeout waiting worker(nginx) to start (5s)"
+ end
+
+ self.log.info("worker is started")
+
+ local uris = {}
+ for i=1,port_count do
+ uris[i] = "http://" .. worker_vip .. ":" .. UPSTREAM_PORT+i-1
+ end
+ return uris
+end
+
+
+function _M:setup_kong(version)
+ local ok, err = _M.setup(self)
+ if not ok then
+ return ok, err
+ end
+
+ local git_repo_path
+
+ self.daily_image_desc = nil
+ if version:startswith("git:") then
+ git_repo_path = perf.git_checkout(version:sub(#("git:")+1))
+ version = perf.get_kong_version()
+
+ if self.opts.use_daily_image then
+ self.kong_image = "kong/kong-gateway-internal:master-ubuntu"
+ perf.execute("docker pull " .. self.kong_image, { logger = self.log.log_exec })
+ local manifest, err = perf.execute("docker inspect " .. self.kong_image)
+ if err then
+ return nil, "failed to inspect daily image: " .. err
+ end
+ local labels, err = perf.parse_docker_image_labels(manifest)
+ if err then
+ return nil, "failed to use parse daily image manifest: " .. err
+ end
+ self.log.debug("daily image " .. labels.version .." was pushed at ", labels.created)
+ self.daily_image_desc = labels.version .. ", " .. labels.created
+
+ else
+ self.kong_image = "kong:" .. version
+ end
+ self.log.debug("current git hash resolves to docker version ", version)
+
+ elseif version:match("rc") or version:match("beta") then
+ self.kong_image = "kong/kong:" .. version
+ elseif version:match("%d+%.%d+%.%d+%.%d+") then -- EE
+ if version:match("internal%-preview") then
+ self.kong_image = "kong/kong-gateway-internal:" .. version
+ else
+ self.kong_image = "kong/kong-gateway:" .. version
+ end
+ else
+ self.kong_image = "kong:" .. version
+ end
+
+ self.git_repo_path = git_repo_path
+
+ local docker_args = "--link " .. self.psql_ct_id .. ":postgres " ..
+ "-e KONG_PG_HOST=postgres " ..
+ "-e KONG_PG_DATABASE=kong_tests "
+
+ local _, err = perf.execute("docker run --rm " .. docker_args .. " " .. self.kong_image .. " kong migrations bootstrap",
+ { logger = self.log.log_exec })
+ if err then
+ return nil, "error running initial migration: " .. err
+ end
+
+ self.setup_kong_called = true
+
+ return prepare_spec_helpers(self, git_repo_path, version)
+end
+
+function _M:start_kong(kong_conf, driver_conf)
+ if not self.setup_kong_called then
+ return false, "setup_kong() must be called before start_kong()"
+ end
+
+ local kong_name = driver_conf.name
+ or 'default'
+
+ if not driver_conf.ports then
+ driver_conf.ports = { 8000 }
+ end
+
+ if self.kong_ct_ids[kong_name] == nil then
+ if not kong_conf['cluster_cert'] then
+ kong_conf['cluster_cert'] = KONG_DEFAULT_HYBRID_CERT
+ kong_conf['cluster_cert_key'] = KONG_DEFAULT_HYBRID_CERT_KEY
+ end
+
+ local docker_args = "--name kong_perf_kong_$(date +%s)_" .. kong_name .. " "
+ for k, v in pairs(kong_conf) do
+ docker_args = docker_args .. string.format("-e KONG_%s=%s ", k:upper(), v)
+ end
+ docker_args = docker_args .. "-e KONG_PROXY_ACCESS_LOG=/dev/null "
+
+ -- adds database configuration
+ if kong_conf['database'] == nil then
+ docker_args = docker_args .. "--link " .. self.psql_ct_id .. ":postgres " ..
+ "-e KONG_PG_HOST=postgres " ..
+ "-e KONG_PG_DATABASE=kong_tests "
+ end
+
+ -- link to other kong instances
+ for name, ctid in pairs(self.kong_ct_ids) do
+ docker_args = docker_args .. string.format("--link %s:%s ", ctid, name)
+ end
+
+ for _, port in ipairs(driver_conf.ports) do
+ docker_args = docker_args .. string.format("-p %d ", port)
+ end
+
+ local cid, err = create_container(self, docker_args, self.kong_image,
+ "/bin/bash -c 'kong migrations bootstrap; kong migrations up -y; kong migrations finish -y; /docker-entrypoint.sh kong docker-start'")
+
+ if err then
+ return false, "error running docker create when creating kong container: " .. err
+ end
+
+ self.kong_ct_ids[kong_name] = cid
+ perf.execute("docker cp ./spec/fixtures/kong_clustering.crt " .. cid .. ":" .. KONG_DEFAULT_HYBRID_CERT)
+ perf.execute("docker cp ./spec/fixtures/kong_clustering.key " .. cid .. ":" .. KONG_DEFAULT_HYBRID_CERT_KEY)
+
+ if self.git_repo_path then
+ perf.execute("docker exec --user=root " .. cid ..
+ " find /usr/local/share/lua/5.1/kong -name '*.ljbc' -delete; true")
+ perf.execute("docker cp " .. self.git_repo_path .. "/kong " .. cid .. ":/usr/local/share/lua/5.1/")
+ -- TODO: folllowing doesn't work
+ perf.execute("(cd " .. self.git_repo_path .. " && tar zc plugins-ee/*/kong/plugins/* --transform='s,plugins-ee/[^/]*/kong,kong,') | "
+ .. "docker exec --user=root " .. cid .. " tar zx -C /usr/local/share/lua/5.1/")
+ end
+ end
+
+ self.log.info("starting kong container \"" .. kong_name .. "\" with ID ", self.kong_ct_ids[kong_name])
+ local ok, err = start_container(self.kong_ct_ids[kong_name])
+ if not ok then
+ return false, "kong is not running: " .. err
+ end
+
+ -- wait
+ if not perf.wait_output("docker logs -f " .. self.kong_ct_ids[kong_name], " start worker process", 30) then
+ self.log.info("kong container logs:")
+ perf.execute("docker logs " .. self.kong_ct_ids[kong_name], { logger = self.log.log_exec })
+ return false, "timeout waiting kong to start (5s)"
+ end
+
+ local ports = driver_conf.ports
+ local port_maps = {}
+ for _, port in ipairs(ports) do
+ local mport, err = get_container_port(self.kong_ct_ids[kong_name], port .. "/tcp")
+ if not mport then
+ return false, "can't find exposed port " .. port .. " for kong " ..
+ self.kong_ct_ids[kong_name] .. " :" .. err
+ end
+ table.insert(port_maps, string.format("%s->%s/tcp", mport, port))
+ end
+
+ self.log.info("kong container \"" .. kong_name .. "\" is started to listen at port ", table.concat(port_maps, ", "))
+ return self.kong_ct_ids[kong_name]
+end
+
+function _M:stop_kong()
+ for conf_id, kong_ct_id in pairs(self.kong_ct_ids) do
+ local _, err = perf.execute("docker stop " .. kong_ct_id)
+ if err then
+ return false
+ end
+ end
+
+ return true
+end
+
+function _M:get_start_load_cmd(stub, script, uri, kong_name)
+ if not self.worker_ct_id then
+ return false, "worker container is not started, 'start_worker' must be called first"
+ end
+
+ local kong_id
+ if not uri then
+ if not kong_name then
+ -- find all kong containers with first one that exposes proxy port
+ for name, ct_id in pairs(self.kong_ct_ids) do
+ local admin_port, err = get_container_port(ct_id, "8000/tcp")
+ if err then
+ -- this is fine, it means this kong doesn't have a proxy port
+ self.log.debug("failed to get kong proxy port for " .. ct_id .. ": " .. (err or "nil"))
+ elseif admin_port then
+ kong_id = ct_id
+ self.log.info("automatically picked kong container \"", name, "\" with ID " .. ct_id .. " for proxy port")
+ break
+ end
+ end
+ if not kong_id then
+ return false, "failed to find kong proxy port"
+ end
+ else
+ kong_id = self.kong_ct_ids[kong_name]
+ if not kong_id then
+ return false, "kong container \"" .. kong_name .. "\" is not found"
+ end
+ end
+
+ local kong_vip, err = get_container_vip(kong_id)
+ if err then
+ return false, "unable to read kong container's private IP: " .. err
+ end
+ uri = string.format("http://%s:8000", kong_vip)
+ end
+
+ local script_path
+ if script then
+ script_path = string.format("/tmp/wrk-%s.lua", tools.random_string())
+ local out, err = perf.execute(string.format(
+ "docker exec -i %s tee %s", self.worker_ct_id, script_path),
+ {
+ stdin = script,
+ })
+ if err then
+ return false, "failed to write script in " .. self.worker_ct_id .. " container: " .. (out or err)
+ end
+ end
+
+ script_path = script_path and ("-s " .. script_path) or ""
+
+ return "docker exec " .. self.worker_ct_id .. " " ..
+ stub:format(script_path, uri)
+end
+
+function _M:get_admin_uri(kong_name)
+ local kong_id
+ if not kong_name then
+ -- find all kong containers with first one that exposes admin port
+ for name, ct_id in pairs(self.kong_ct_ids) do
+ local admin_port, err = get_container_port(ct_id, "8001/tcp")
+ if err then
+ -- this is fine, it means this kong doesn't have an admin port
+ self.log.warn("failed to get kong admin port for " .. ct_id .. ": " .. (err or "nil"))
+ elseif admin_port then
+ kong_id = ct_id
+ self.log.info("automatically picked kong container \"", name, "\" with ID " .. ct_id .. " for admin port")
+ break
+ end
+ end
+ if not kong_id then
+ return nil, "failed to find kong admin port"
+ end
+ else
+ kong_id = self.kong_ct_ids[kong_name]
+ if not kong_id then
+ return false, "kong container \"" .. kong_name .. "\" is not found"
+ end
+ end
+
+ local kong_vip, err = get_container_vip(kong_id)
+ if err then
+ return false, "unable to read kong container's private IP: " .. err
+ end
+
+ return string.format("http://%s:8001", kong_vip)
+end
+
+function _M:get_start_stapxx_cmd()
+ error("SystemTap support not yet implemented in docker driver")
+end
+
+function _M:get_wait_stapxx_cmd()
+ error("SystemTap support not yet implemented in docker driver")
+end
+
+function _M:generate_flamegraph()
+ error("SystemTap support not yet implemented in docker driver")
+end
+
+function _M:save_error_log(path)
+ for _, kong_ct_id in pairs(self.kong_ct_ids) do
+ local _, err = perf.execute("docker logs " .. kong_ct_id .. " 2>'" .. path .. "-" .. kong_ct_id .. "'",
+ { logger = self.log.log_exec })
+ if err then
+ return false, "failed to save error log for kong " .. kong_ct_id .. ": " .. err
+ end
+ end
+
+ return true
+end
+
+function _M:save_pgdump(path)
+ if not self.psql_ct_id then
+ return false, "postgres container not started"
+ end
+
+ return perf.execute("docker exec -i " .. self.psql_ct_id .. " pg_dump -Ukong kong_tests --data-only >'" .. path .. "'",
+ { logger = self.log.log_exec })
+end
+
+function _M:load_pgdump(path, dont_patch_service)
+ if not self.psql_ct_id then
+ return false, "postgres container not started"
+ end
+
+ local _, err = perf.execute("cat " .. path .. " |docker exec -i " .. self.psql_ct_id .. " psql -Ukong kong_tests",
+ { logger = self.log.log_exec })
+ if err then
+ return false, err
+ end
+
+ if dont_patch_service then
+ return true
+ end
+
+ if not self.worker_ct_id then
+ return false, "worker not started, can't patch_service; call start_worker first"
+ end
+
+ local worker_vip, err = get_container_vip(self.worker_ct_id)
+ if err then
+ return false, "unable to read worker container's private IP: " .. err
+ end
+
+ return perf.execute("echo \"UPDATE services set host='" .. worker_vip ..
+ "', port=" .. UPSTREAM_PORT ..
+ ", protocol='http';\" | docker exec -i " .. self.psql_ct_id .. " psql -Ukong kong_tests",
+ { logger = self.log.log_exec })
+end
+
+function _M:get_based_version()
+ return self.daily_image_desc or perf.get_kong_version()
+end
+
+function _M:remote_execute(node_type, cmds, continue_on_error)
+ local ct_id
+ if node_type == "kong" then
+ ct_id = self.kong_ct_ids[next(self.kong_ct_ids)]
+ elseif node_type == "worker" then
+ ct_id = self.worker_ct_id
+ elseif node_type == "db" then
+ ct_id = self.psql_ct_id
+ else
+ return false, "unknown node type: " .. node_type
+ end
+ for _, cmd in ipairs(cmds) do
+ local c = string.gsub(cmd, "'", "'\\''")
+ local out, err = perf.execute("docker exec -i " .. ct_id .. " '" .. c .. "'",
+ { logger = self.log.log_exec })
+ if err and not continue_on_error then
+ return false, "failed to execute command: " .. cmd .. ": " .. (out or err)
+ end
+ end
+ return true
+end
+
+return _M
diff --git a/kong-versions/3.9.0.0/kong/spec/helpers/perf/drivers/terraform.lua b/kong-versions/3.9.0.0/kong/spec/helpers/perf/drivers/terraform.lua
new file mode 100644
index 00000000..44fb81a8
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/helpers/perf/drivers/terraform.lua
@@ -0,0 +1,781 @@
+-- This software is copyright Kong Inc. and its licensors.
+-- Use of the software is subject to the agreement between your organization
+-- and Kong Inc. If there is no such agreement, use is governed by and
+-- subject to the terms of the Kong Master Software License Agreement found
+-- at https://konghq.com/enterprisesoftwarelicense/.
+-- [ END OF LICENSE 0867164ffc95e54f04670b5169c09574bdbd9bba ]
+
+local perf = require("spec.helpers.perf")
+local pl_path = require("pl.path")
+local cjson = require("cjson")
+local tools = require("kong.tools.rand")
+math.randomseed(os.time())
+
+local _M = {}
+local mt = {__index = _M}
+
+local UPSTREAM_PORT = 8088
+local KONG_ADMIN_PORT
+local PG_PASSWORD = tools.random_string()
+local KONG_ERROR_LOG_PATH = "/tmp/error.log"
+local KONG_DEFAULT_HYBRID_CERT = "/tmp/kong-hybrid-cert.pem"
+local KONG_DEFAULT_HYBRID_CERT_KEY = "/tmp/kong-hybrid-key.pem"
+-- threshold for load_avg / nproc, not based on specific research,
+-- just a arbitrary number to ensure test env is normalized
+local LOAD_NORMALIZED_THRESHOLD = 0.2
+
+function _M.new(opts)
+ local provider = opts and opts.provider or "equinix-metal"
+ local work_dir = "./spec/fixtures/perf/terraform/" .. provider
+ if not pl_path.exists(work_dir) then
+ error("Hosting provider " .. provider .. " unsupported: expect " .. work_dir .. " to exists", 2)
+ end
+
+ local tfvars = ""
+ if opts and opts.tfvars then
+ for k, v in pairs(opts.tfvars) do
+ tfvars = string.format("%s -var '%s=%s' ", tfvars, k, v)
+ end
+ end
+
+ local ssh_user = opts.ssh_user or "root"
+
+ return setmetatable({
+ opts = opts,
+ log = perf.new_logger("[terraform]"),
+ ssh_log = perf.new_logger("[terraform][ssh]"),
+ provider = provider,
+ work_dir = work_dir,
+ tfvars = tfvars,
+ kong_ip = nil,
+ kong_internal_ip = nil,
+ worker_ip = nil,
+ worker_internal_ip = nil,
+ systemtap_sanity_checked = false,
+ systemtap_dest_path = nil,
+ daily_image_desc = nil,
+ ssh_user = ssh_user,
+ }, mt)
+end
+
+local function ssh_execute_wrap(self, ip, cmd)
+ -- to quote a ', one need to finish the current ', quote the ' then start a new '
+ cmd = string.gsub(cmd, "'", "'\\''")
+ return "ssh " ..
+ "-o IdentityFile=" .. self.work_dir .. "/id_rsa " .. -- TODO: no hardcode
+ -- timeout is detected 3xServerAliveInterval
+ "-o TCPKeepAlive=yes -o ServerAliveInterval=10 " ..
+ -- turn on connection multiplexing
+ "-o ControlPath=" .. self.work_dir .. "/cm-%r@%h:%p " ..
+ "-o ControlMaster=auto -o ControlPersist=5m " ..
+ -- no interactive prompt for saving hostkey
+ "-o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no " ..
+ -- silence warnings like "Permanently added xxx"
+ "-o LogLevel=ERROR " ..
+ self.ssh_user .. "@" .. ip .. " '" .. cmd .. "'"
+end
+
+-- if remote_ip is set, run remotely; else run on host machine
+local function execute_batch(self, remote_ip, cmds, continue_on_error)
+ for _, cmd in ipairs(cmds) do
+ if remote_ip then
+ cmd = ssh_execute_wrap(self, remote_ip, cmd)
+ end
+ local _, err = perf.execute(cmd, {
+ logger = (remote_ip and self.ssh_log or self.log).log_exec
+ })
+ if err then
+ if not continue_on_error then
+ return false, "failed in \"" .. cmd .. "\": ".. (err or "nil")
+ end
+ self.log.warn("execute ", cmd, " has error: ", (err or "nil"))
+ end
+ end
+ return true
+end
+
+function _M:remote_execute(node_type, cmds, continue_on_error)
+ local ip
+ if node_type == "kong" then
+ ip = self.kong_ip
+ elseif node_type == "worker" then
+ ip = self.worker_ip
+ elseif node_type == "db" then
+ ip = self.db_ip
+ else
+ return false, "unknown node type: " .. node_type
+ end
+ return execute_batch(self, ip, cmds, continue_on_error)
+end
+
+function _M:setup(opts)
+ local bin, err = perf.execute("which terraform")
+ if err or #bin == 0 then
+ return nil, "terraform binary not found"
+ end
+
+ local ok, _
+ -- terraform apply
+ self.log.info("Running terraform to provision instances...")
+
+ _, err = execute_batch(self, nil, {
+ "terraform version",
+ "cd " .. self.work_dir .. " && terraform init",
+ "cd " .. self.work_dir .. " && terraform apply -auto-approve " .. self.tfvars,
+ })
+ if err then
+ return false, err
+ end
+
+ -- grab outputs
+ local res
+ res, err = perf.execute("cd " .. self.work_dir .. " && terraform output -json")
+ if err then
+ return false, "terraform show: " .. err
+ end
+ res = cjson.decode(res)
+
+ self.kong_ip = res["kong-ip"].value
+ self.kong_internal_ip = res["kong-internal-ip"].value
+ if self.opts.seperate_db_node then
+ self.db_ip = res["db-ip"].value
+ self.db_internal_ip = res["db-internal-ip"].value
+ else
+ self.db_ip = self.kong_ip
+ self.db_internal_ip = self.kong_internal_ip
+ end
+ self.worker_ip = res["worker-ip"].value
+ self.worker_internal_ip = res["worker-internal-ip"].value
+
+ -- install psql docker on db instance
+ ok, err = execute_batch(self, self.db_ip, {
+ "sudo apt-get purge unattended-upgrades -y",
+ "sudo apt-get update -qq", "sudo DEBIAN_FRONTEND=\"noninteractive\" apt-get install -y --force-yes docker.io",
+ "sudo docker rm -f kong-database || true", -- if exist remove it
+ "sudo docker volume rm $(sudo docker volume ls -qf dangling=true) || true", -- cleanup postgres volumes if any
+ "sudo docker run -d -p5432:5432 "..
+ "-e POSTGRES_PASSWORD=" .. PG_PASSWORD .. " " ..
+ "-e POSTGRES_DB=kong_tests " ..
+ "-e POSTGRES_USER=kong --name=kong-database postgres:13 -c max_connections=5000",
+ })
+ if not ok then
+ return ok, err
+ end
+
+ -- wait
+ local cmd = ssh_execute_wrap(self, self.db_ip,
+ "sudo docker logs -f kong-database")
+ if not perf.wait_output(cmd, "is ready to accept connections", 5) then
+ return false, "timeout waiting psql to start (5s)"
+ end
+
+ return true
+end
+
+function _M:teardown(full)
+ self.setup_kong_called = false
+
+ -- only run remote execute when terraform provisioned
+ if self.kong_ip then
+ local _, err = execute_batch(self, self.kong_ip, {
+ "sudo rm -rf /usr/local/kong_* /usr/local/kong || true",
+ "sudo pkill -kill nginx || true",
+ "sudo dpkg -r kong || true",
+ "sudo dpkg -r kong-enterprise-edition || true",
+ })
+ if err then
+ return false, err
+ end
+ end
+
+ if full then
+ -- terraform destroy
+ self.log.info("Running terraform to destroy instances...")
+
+ local ok, err = execute_batch(self, nil, {
+ "terraform version",
+ "cd " .. self.work_dir .. " && terraform init",
+ "cd " .. self.work_dir .. " && terraform destroy -auto-approve " .. self.tfvars,
+ })
+ if not ok then
+ return false, err
+ end
+ end
+
+ perf.git_restore()
+
+ -- otherwise do nothing
+ return true
+end
+
+function _M:start_worker(conf, port_count)
+ conf = conf or ""
+ local listeners = {}
+ for i=1,port_count do
+ listeners[i] = ("listen %d reuseport;"):format(UPSTREAM_PORT+i-1)
+ end
+ listeners = table.concat(listeners, "\n")
+
+ conf = ngx.encode_base64(([[
+ worker_processes auto;
+ worker_cpu_affinity auto;
+ error_log /var/log/nginx/error.log;
+ pid /run/nginx.pid;
+ worker_rlimit_nofile 20480;
+
+ events {
+ accept_mutex off;
+ worker_connections 10620;
+ }
+
+ http {
+ access_log off;
+ server_tokens off;
+ keepalive_requests 10000;
+ tcp_nodelay on;
+
+ server {
+ %s
+ location =/health {
+ return 200;
+ }
+ location / {
+ return 200 " performancetestperformancetestperformancetestperformancetestperformancetest";
+ }
+ %s
+ }
+ }]]):format(listeners, conf)):gsub("\n", "")
+
+ local ok, err = execute_batch(self, self.worker_ip, {
+ "sudo id",
+ "echo performance | sudo tee /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor || true",
+ "sudo apt-get purge unattended-upgrades -y",
+ "sudo apt-get update -qq", "sudo DEBIAN_FRONTEND=\"noninteractive\" apt-get install -y --force-yes nginx gcc make unzip libssl-dev zlib1g-dev",
+ "which wrk || (rm -rf wrk && git clone https://github.com/wg/wrk -b 4.2.0 && cd wrk && make -j$(nproc) WITH_OPENSSL=/usr && sudo cp wrk /usr/local/bin/wrk)",
+ "which wrk2 || (rm -rf wrk2 && git clone https://github.com/giltene/wrk2 && cd wrk2 && make -j$(nproc) && sudo cp wrk /usr/local/bin/wrk2)",
+ "echo " .. conf .. " | base64 -d | sudo tee /etc/nginx/nginx.conf",
+ "sudo nginx -t",
+ "sudo systemctl restart nginx",
+ })
+ if not ok then
+ return nil, err
+ end
+
+ local uris = {}
+ for i=1,port_count do
+ uris[i] = "http://" .. self.worker_internal_ip .. ":" .. UPSTREAM_PORT+i-1
+ end
+ return uris
+end
+
+local function get_admin_port(self, kong_name)
+ kong_name = kong_name or "default"
+ local port, err = perf.execute(ssh_execute_wrap(self, self.kong_ip,
+ "sudo cat /etc/kong/" .. kong_name .. ".conf | grep admin_listen | cut -d ':' -f 2 | grep -oP '\\d+' || true"))
+ if port and tonumber(port) then
+ return tonumber(port)
+ else
+ self.log.warn("unable to read admin port for " .. kong_name .. ", fallback to default port " .. KONG_ADMIN_PORT .. ": " .. tostring(err))
+ return KONG_ADMIN_PORT
+ end
+end
+
+local function prepare_spec_helpers(self, use_git, version)
+ perf.setenv("KONG_PG_HOST", self.db_ip)
+ perf.setenv("KONG_PG_PASSWORD", PG_PASSWORD)
+ -- self.log.debug("(In a low voice) pg_password is " .. PG_PASSWORD)
+
+ if not use_git then
+ local current_spec_helpers_version = perf.get_kong_version(true)
+ if current_spec_helpers_version ~= version then
+ self.log.info("Current spec helpers version " .. current_spec_helpers_version ..
+ " doesn't match with version to be tested " .. version .. ", checking out remote version")
+
+ version = version:match("%d+%.%d+%.%d+%.%d+") or version:match("%d+%.%d+%.%d+")
+
+ perf.git_checkout(version) -- throws
+ end
+ end
+
+ self.log.info("Infra is up! However, preparing database remotely may take a while...")
+ for i=1, 3 do
+ perf.clear_loaded_package()
+
+ -- just to let spec.helpers happy, we are not going to start kong locally
+ require("kong.meta")._DEPENDENCIES.nginx = {"0.0.0.0", "9.9.9.9"}
+
+ local pok, pret = pcall(require, "spec.helpers")
+ package.loaded['kong.meta'] = nil
+ require("kong.meta")
+
+ if pok then
+ pret.admin_client = function(timeout)
+ return pret.http_client(self.kong_ip, get_admin_port(self), timeout or 60000)
+ end
+ perf.unsetenv("KONG_PG_HOST")
+ perf.unsetenv("KONG_PG_PASSWORD")
+
+ return pret
+ end
+ self.log.warn("unable to load spec.helpers: " .. (pret or "nil") .. ", try " .. i)
+ ngx.sleep(1)
+ end
+ error("Unable to load spec.helpers")
+end
+
+function _M:setup_kong(version)
+ local ok, err = _M.setup(self)
+ if not ok then
+ return ok, err
+ end
+
+ local git_repo_path, _
+
+ if version:startswith("git:") then
+ git_repo_path = perf.git_checkout(version:sub(#("git:")+1))
+
+ version = perf.get_kong_version()
+ self.log.debug("current git hash resolves to Kong version ", version)
+ end
+
+ local download_path
+ local download_user, download_pass = "x", "x"
+ local major_version = version:sub(1, 1)
+ if major_version == "2" or major_version == "3" then
+ local package_name = "kong-enterprise-edition_" .. version .. "_amd64.deb"
+ if major_version == "2" then
+ package_name = "kong-enterprise-edition_" .. version .. "_all.deb"
+ end
+ if version:match("%d+%.%d+%.%d+%.%d+") then -- EE
+ if version:match("internal%-preview") then
+ download_path = "https://download.konghq.com/internal/gateway-" .. major_version .. ".x-ubuntu-focal/pool/all/k/kong-enterprise-edition/"..package_name
+ download_user = os.getenv("PULP_USERNAME")
+ download_pass = os.getenv("PULP_PASSWORD")
+ if not download_user or not download_pass then
+ return nil, "PULP_USERNAME and PULP_PASSWORD are required to download internal builds"
+ end
+ else
+ download_path = "https://download.konghq.com/gateway-" .. major_version .. ".x-ubuntu-focal/pool/all/k/kong-enterprise-edition/"..package_name
+ end
+ else
+ download_path = "https://download.konghq.com/gateway-" .. major_version .. ".x-ubuntu-focal/pool/all/k/kong/kong_" ..
+ version .. "_amd64.deb"
+ end
+ else
+ error("Unknown download location for Kong version " .. version)
+ end
+
+ local docker_extract_cmds
+ self.daily_image_desc = nil
+ -- daily image are only used when testing with git
+ -- testing upon release artifact won't apply daily image files
+ local daily_image = "kong/kong-gateway-internal:master-ubuntu"
+ if self.opts.use_daily_image and git_repo_path then
+ -- install docker on kong instance
+ local _, err = execute_batch(self, self.kong_ip, {
+ "sudo apt-get update -qq",
+ "sudo DEBIAN_FRONTEND=\"noninteractive\" apt-get install -y --force-yes docker.io",
+ "sudo docker version",
+ })
+ if err then
+ return false, err
+ end
+
+ docker_extract_cmds = {
+ "sudo docker login -u " .. (os.getenv("DOCKER_USERNAME") or "x") ..
+ " -p " .. (os.getenv("DOCKER_PASSWORD") or "x"),
+ "sudo docker rm -f daily || true",
+ "sudo docker rmi -f " .. daily_image,
+ "sudo docker pull " .. daily_image,
+ "sudo docker create --name daily " .. daily_image,
+ "sudo rm -rf /tmp/lua && sudo docker cp daily:/usr/local/share/lua/5.1/. /tmp/lua",
+ -- don't overwrite kong source code, use them from current git repo instead
+ "sudo rm -rf /tmp/lua/kong && sudo cp -r /tmp/lua/. /usr/local/share/lua/5.1/",
+ }
+
+ for _, dir in ipairs({"/usr/local/openresty",
+ "/usr/local/kong/include", "/usr/local/kong/lib"}) do
+ -- notice the /. it makes sure the content not the directory itself is copied
+ table.insert(docker_extract_cmds, "sudo docker cp daily:" .. dir .."/. " .. dir)
+ end
+
+ table.insert(docker_extract_cmds, "sudo rm -rf /tmp/lua && sudo docker cp daily:/usr/local/share/lua/5.1/. /tmp/lua")
+ table.insert(docker_extract_cmds, "sudo rm -rf /tmp/lua/kong && sudo cp -r /tmp/lua/. /usr/local/share/lua/5.1/")
+ end
+
+ local ok, err = execute_batch(self, self.kong_ip, {
+ "sudo apt-get purge unattended-upgrades -y",
+ "sudo apt-get update -qq",
+ "echo | sudo tee " .. KONG_ERROR_LOG_PATH, -- clear it
+ "sudo id",
+ -- set cpu scheduler to performance, it should lock cpufreq to static freq
+ "echo performance | sudo tee /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor || true",
+ -- increase outgoing port range to avoid 99: Cannot assign requested address
+ "sudo sysctl net.ipv4.ip_local_port_range='10240 65535'",
+ -- stop and remove kong if installed
+ "dpkg -l kong && (sudo pkill -kill nginx; sudo dpkg -r kong) || true",
+ -- stop and remove kong-ee if installed
+ "dpkg -l kong-enterprise-edition && (sudo pkill -kill nginx; sudo dpkg -r kong-enterprise-edition) || true",
+ -- have to do the pkill sometimes, because kong stop allow the process to linger for a while
+ "sudo pkill -F /usr/local/kong/pids/nginx.pid || true",
+ -- remove all lua files, not only those installed by package
+ "sudo rm -rf /usr/local/share/lua/5.1/kong",
+ "dpkg -I kong-" .. version .. ".deb || " .. -- check if already downloaded and valid because pulp flaky
+ "wget -nv " .. download_path ..
+ " --user " .. download_user .. " --password " .. download_pass .. " -O kong-" .. version .. ".deb",
+ "sudo dpkg -i kong-" .. version .. ".deb || sudo apt-get -f -y install",
+ -- generate hybrid cert
+ "kong hybrid gen_cert " .. KONG_DEFAULT_HYBRID_CERT .. " " .. KONG_DEFAULT_HYBRID_CERT_KEY .. " || true",
+ })
+ if not ok then
+ return false, err
+ end
+
+ if docker_extract_cmds then
+ _, err = execute_batch(self, self.kong_ip, docker_extract_cmds)
+ if err then
+ return false, "error extracting docker daily image:" .. err
+ end
+ local manifest
+ manifest, err = perf.execute(ssh_execute_wrap(self, self.kong_ip, "sudo docker inspect " .. daily_image))
+ if err then
+ return nil, "failed to inspect daily image: " .. err
+ end
+ local labels
+ labels, err = perf.parse_docker_image_labels(manifest)
+ if err then
+ return nil, "failed to use parse daily image manifest: " .. err
+ end
+
+ self.log.debug("daily image " .. labels.version .." was pushed at ", labels.created)
+ self.daily_image_desc = labels.version .. ", " .. labels.created
+ end
+
+ local kong_conf = {}
+ kong_conf["pg_host"] = self.db_internal_ip
+ kong_conf["pg_password"] = PG_PASSWORD
+ kong_conf["pg_database"] = "kong_tests"
+
+ local kong_conf_blob = ""
+ for k, v in pairs(kong_conf) do
+ kong_conf_blob = string.format("%s\n%s=%s\n", kong_conf_blob, k, v)
+ end
+ kong_conf_blob = ngx.encode_base64(kong_conf_blob):gsub("\n", "")
+
+ _, err = execute_batch(self, nil, {
+ -- upload
+ git_repo_path and ("(cd " .. git_repo_path .. " && tar zc kong) | " .. ssh_execute_wrap(self, self.kong_ip,
+ "sudo tar zx -C /usr/local/share/lua/5.1; sudo find /usr/local/share/lua/5.1/kong -name '*.ljbc' -delete; true"))
+ or "echo use stock files",
+ git_repo_path and (ssh_execute_wrap(self, self.kong_ip,
+ "sudo cp -r /usr/local/share/lua/5.1/kong/include/. /usr/local/kong/include/ && sudo chmod 777 -R /usr/local/kong/include/ || true"))
+ or "echo use stock files",
+ git_repo_path and ("(cd " .. git_repo_path .. " && tar zc plugins-ee/*/kong/plugins/* --transform='s,plugins-ee/[^/]*/kong,kong,') | " ..
+ ssh_execute_wrap(self, self.kong_ip, "sudo tar zx -C /usr/local/share/lua/5.1"))
+ or "echo use stock files",
+ -- run migrations with default configurations
+ ssh_execute_wrap(self, self.kong_ip,
+ "sudo mkdir -p /etc/kong"),
+ ssh_execute_wrap(self, self.kong_ip,
+ "echo " .. kong_conf_blob .. " | base64 -d | sudo tee /etc/kong/kong.conf"),
+ ssh_execute_wrap(self, self.kong_ip,
+ "sudo kong migrations bootstrap"),
+ ssh_execute_wrap(self, self.kong_ip,
+ "sudo kong migrations up -y || true"),
+ ssh_execute_wrap(self, self.kong_ip,
+ "sudo kong migrations finish -y || true"),
+ })
+ if err then
+ return false, err
+ end
+
+ self.setup_kong_called = true
+
+ return prepare_spec_helpers(self, git_repo_path, version)
+end
+
+function _M:start_kong(kong_conf, driver_conf)
+ if not self.setup_kong_called then
+ return false, "setup_kong() must be called before start_kong()"
+ end
+
+ local kong_name = driver_conf and driver_conf.name or "default"
+ local prefix = "/usr/local/kong_" .. kong_name
+ local conf_path = "/etc/kong/" .. kong_name .. ".conf"
+
+ kong_conf = kong_conf or {}
+ kong_conf["prefix"] = kong_conf["prefix"] or prefix
+ kong_conf["pg_host"] = kong_conf["pg_host"] or self.db_internal_ip
+ kong_conf["pg_password"] = kong_conf["pg_password"] or PG_PASSWORD
+ kong_conf["pg_database"] = kong_conf["pg_database"] or "kong_tests"
+
+ kong_conf['proxy_access_log'] = kong_conf['proxy_access_log'] or "/dev/null"
+ kong_conf['proxy_error_log'] = kong_conf['proxy_error_log'] or KONG_ERROR_LOG_PATH
+ kong_conf['admin_error_log'] = kong_conf['admin_error_log'] or KONG_ERROR_LOG_PATH
+
+ KONG_ADMIN_PORT = 39001
+ kong_conf['admin_listen'] = kong_conf['admin_listen'] or ("0.0.0.0:" .. KONG_ADMIN_PORT)
+ kong_conf['vitals'] = kong_conf['vitals'] or "off"
+ kong_conf['anonymous_reports'] = kong_conf['anonymous_reports'] or "off"
+ if not kong_conf['cluster_cert'] then
+ kong_conf['cluster_cert'] = KONG_DEFAULT_HYBRID_CERT
+ kong_conf['cluster_cert_key'] = KONG_DEFAULT_HYBRID_CERT_KEY
+ end
+
+ local kong_license_blob = ""
+ if kong_conf['license_data'] then
+ kong_license_blob = kong_conf['license_data']
+ kong_conf['license_data'] = nil
+ end
+
+ local kong_conf_blob = ""
+ for k, v in pairs(kong_conf) do
+ kong_conf_blob = string.format("%s\n%s=%s\n", kong_conf_blob, k, v)
+ end
+ kong_conf_blob = ngx.encode_base64(kong_conf_blob):gsub("\n", "")
+ kong_license_blob = ngx.encode_base64(kong_license_blob)
+
+ local _, err = execute_batch(self, self.kong_ip, {
+ "mkdir -p /etc/kong || true",
+ "echo " .. kong_conf_blob .. " | base64 -d | sudo tee " .. conf_path,
+ "echo " .. kong_license_blob .. " | base64 -d | sudo tee /etc/kong/license.json",
+ "sudo rm -rf " .. prefix .. " && sudo mkdir -p " .. prefix .. " && sudo chown kong:kong -R " .. prefix,
+ "sudo kong check " .. conf_path,
+ string.format("sudo kong migrations up -y -c %s || true", conf_path),
+ string.format("sudo kong migrations finish -y -c %s || true", conf_path),
+ string.format("ulimit -n 655360; sudo kong start -c %s || sudo kong restart -c %s", conf_path, conf_path),
+ -- set mapping of kong name to IP for use like Hybrid mode
+ "grep -q 'START PERF HOSTS' /etc/hosts || (echo '## START PERF HOSTS' | sudo tee -a /etc/hosts)",
+ "echo " .. self.kong_internal_ip .. " " .. kong_name .. " | sudo tee -a /etc/hosts",
+ })
+ if err then
+ return false, err
+ end
+
+ return true
+end
+
+function _M:stop_kong()
+ local load, err = perf.execute(ssh_execute_wrap(self, self.kong_ip,
+ "cat /proc/loadavg"))
+ if err then
+ self.log.err("failed to get loadavg: " .. err)
+ end
+
+ self.log.debug("Kong node end 1m loadavg is ", load:match("[%d%.]+"))
+
+ return execute_batch(self, self.kong_ip, {
+ "sudo pkill -kill nginx",
+ "sudo sed '/START PERF HOSTS/Q' -i /etc/hosts",
+ })
+end
+
+function _M:get_start_load_cmd(stub, script, uri)
+ if not uri then
+ uri = string.format("http://%s:8000", self.kong_internal_ip)
+ end
+
+ local script_path
+ if script then
+ script_path = string.format("/tmp/wrk-%s.lua", tools.random_string())
+ local out, err = perf.execute(
+ ssh_execute_wrap(self, self.worker_ip, "tee " .. script_path),
+ {
+ stdin = script,
+ })
+ if err then
+ return false, "failed to write script in remote machine: " .. (out or err)
+ end
+ end
+
+ script_path = script_path and ("-s " .. script_path) or ""
+
+ local nproc, err
+ -- find the physical cores count, instead of counting hyperthreading
+ nproc, err = perf.execute(ssh_execute_wrap(self, self.kong_ip, [[grep '^cpu\scores' /proc/cpuinfo | uniq | awk '{print $4}']]))
+ if not nproc or err then
+ return false, "failed to get core count: " .. (err or "")
+ end
+
+ if not tonumber(nproc) then
+ return false, "failed to get core count: " .. (nproc or "")
+ end
+ nproc = tonumber(nproc)
+
+ local loadavg
+
+ while true do
+ loadavg, err = perf.execute(ssh_execute_wrap(self, self.kong_ip,
+ "cat /proc/loadavg"))
+ if not loadavg or err then
+ self.log.err("failed to get loadavg: ", (err or ""))
+ goto continue
+ end
+
+ loadavg = loadavg:match("[%d%.]+")
+ if not loadavg or not tonumber(loadavg) then
+ self.log.err("failed to get loadavg: ", loadavg or "nil")
+ goto continue
+ end
+ loadavg = tonumber(loadavg)
+
+ local load_normalized = loadavg / nproc
+ if load_normalized < LOAD_NORMALIZED_THRESHOLD then
+ break
+ end
+
+ self.log.info("waiting for Kong node 1m loadavg to drop under ",
+ nproc * LOAD_NORMALIZED_THRESHOLD, ", now: ", loadavg)
+ ngx.sleep(15)
+
+ ::continue::
+ end
+ self.log.debug("Kong node start 1m loadavg is ", loadavg)
+
+ return ssh_execute_wrap(self, self.worker_ip,
+ stub:format(script_path, uri))
+end
+
+function _M:get_admin_uri(kong_name)
+ return string.format("http://%s:%s", self.kong_internal_ip, get_admin_port(self, kong_name))
+end
+
+local function check_systemtap_sanity(self)
+ local _, err
+ _, err = perf.execute(ssh_execute_wrap(self, self.kong_ip, "which stap"))
+ if err then
+ _, err = execute_batch(self, self.kong_ip, {
+ "sudo DEBIAN_FRONTEND=\"noninteractive\" apt-get install g++ libelf-dev libdw-dev libssl-dev libsqlite3-dev libnss3-dev pkg-config python3 make -y --force-yes",
+ "wget https://sourceware.org/ftp/systemtap/releases/systemtap-4.6.tar.gz -O systemtap.tar.gz",
+ "tar xf systemtap.tar.gz",
+ "cd systemtap-*/ && " ..
+ "./configure --enable-sqlite --enable-bpf --enable-nls --enable-nss --enable-avahi && " ..
+ "make PREFIX=/usr -j$(nproc) && "..
+ "sudo make install"
+ })
+ if err then
+ return false, "failed to build systemtap: " .. err
+ end
+ end
+
+ _, err = execute_batch(self, self.kong_ip, {
+ "sudo DEBIAN_FRONTEND=\"noninteractive\" apt-get install gcc linux-headers-$(uname -r) -y --force-yes",
+ "which stap",
+ "stat /tmp/stapxx || git clone https://github.com/Kong/stapxx /tmp/stapxx",
+ "stat /tmp/perf-ost || git clone https://github.com/openresty/openresty-systemtap-toolkit /tmp/perf-ost",
+ "stat /tmp/perf-fg || git clone https://github.com/brendangregg/FlameGraph /tmp/perf-fg"
+ })
+ if err then
+ return false, err
+ end
+
+ -- try compile the kernel module
+ local out
+ out, err = perf.execute(ssh_execute_wrap(self, self.kong_ip,
+ "sudo stap -ve 'probe begin { print(\"hello\\n\"); exit();}'"))
+ if err then
+ return nil, "systemtap failed to compile kernel module: " .. (out or "nil") ..
+ " err: " .. (err or "nil") .. "\n Did you install gcc and kernel headers?"
+ end
+
+ return true
+end
+
+function _M:get_start_stapxx_cmd(sample, args, driver_conf)
+ if not self.systemtap_sanity_checked then
+ local ok, err = check_systemtap_sanity(self)
+ if not ok then
+ return nil, err
+ end
+ self.systemtap_sanity_checked = true
+ end
+
+ -- find one of kong's child process hopefully it's a worker
+ -- (does kong have cache loader/manager?)
+ local kong_name = driver_conf and driver_conf.name or "default"
+ local prefix = "/usr/local/kong_" .. kong_name
+ local pid, err = perf.execute(ssh_execute_wrap(self, self.kong_ip,
+ "pid=$(cat " .. prefix .. "/pids/nginx.pid); " ..
+ "cat /proc/$pid/task/$pid/children | awk '{print $1}'"))
+ if err or not tonumber(pid) then
+ return nil, "failed to get Kong worker PID: " .. (err or "nil")
+ end
+
+ self.systemtap_dest_path = "/tmp/" .. tools.random_string()
+ return ssh_execute_wrap(self, self.kong_ip,
+ "sudo /tmp/stapxx/stap++ /tmp/stapxx/samples/" .. sample ..
+ " --skip-badvars -D MAXSKIPPED=1000000 -x " .. pid ..
+ " " .. args ..
+ " > " .. self.systemtap_dest_path .. ".bt"
+ )
+end
+
+function _M:get_wait_stapxx_cmd(timeout)
+ return ssh_execute_wrap(self, self.kong_ip, "lsmod | grep stap_")
+end
+
+function _M:generate_flamegraph(title, opts)
+ local path = self.systemtap_dest_path
+ self.systemtap_dest_path = nil
+
+ local out, err = perf.execute(ssh_execute_wrap(self, self.kong_ip, "cat " .. path .. ".bt"))
+ if err or #out == 0 then
+ return nil, "systemtap output is empty, possibly no sample are captured"
+ end
+
+ local ok, err = execute_batch(self, self.kong_ip, {
+ -- if there's any error like ee with compiled bytecode, skip fix-lua-bt
+ "/tmp/perf-ost/fix-lua-bt " .. path .. ".bt > " .. path .. ".fbt || true",
+ "stat " .. path .. ".fbt || cp " .. path .. ".bt " .. path .. ".fbt",
+ "/tmp/perf-fg/stackcollapse-stap.pl " .. path .. ".fbt > " .. path .. ".cbt",
+ "/tmp/perf-fg/flamegraph.pl --title='" .. title .. "' " .. (opts or "") .. " " .. path .. ".cbt > " .. path .. ".svg",
+ })
+ if not ok then
+ return false, err
+ end
+
+ local out, _ = perf.execute(ssh_execute_wrap(self, self.kong_ip, "cat " .. path .. ".svg"))
+
+ perf.execute(ssh_execute_wrap(self, self.kong_ip, "sudo rm -v " .. path .. ".*"),
+ { logger = self.ssh_log.log_exec })
+
+ return out
+end
+
+function _M:save_error_log(path)
+ return perf.execute(ssh_execute_wrap(self, self.kong_ip,
+ "cat " .. KONG_ERROR_LOG_PATH) .. " >'" .. path .. "'",
+ { logger = self.ssh_log.log_exec })
+end
+
+function _M:save_pgdump(path)
+ return perf.execute(ssh_execute_wrap(self, self.kong_ip,
+ "sudo docker exec -i kong-database psql -Ukong kong_tests --data-only") .. " >'" .. path .. "'",
+ { logger = self.ssh_log.log_exec })
+end
+
+function _M:load_pgdump(path, dont_patch_service)
+ local _, err = perf.execute("cat " .. path .. "| " .. ssh_execute_wrap(self, self.kong_ip,
+ "sudo docker exec -i kong-database psql -Ukong kong_tests"),
+ { logger = self.ssh_log.log_exec })
+ if err then
+ return false, err
+ end
+
+ if dont_patch_service then
+ return true
+ end
+
+ return perf.execute("echo \"UPDATE services set host='" .. self.worker_ip ..
+ "', port=" .. UPSTREAM_PORT ..
+ ", protocol='http';\" | " ..
+ ssh_execute_wrap(self, self.kong_ip,
+ "sudo docker exec -i kong-database psql -Ukong kong_tests"),
+ { logger = self.ssh_log.log_exec })
+end
+
+function _M:get_based_version()
+ return self.daily_image_desc or perf.get_kong_version()
+end
+
+return _M
diff --git a/kong-versions/3.9.0.0/kong/spec/helpers/perf/git.lua b/kong-versions/3.9.0.0/kong/spec/helpers/perf/git.lua
new file mode 100644
index 00000000..03553e48
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/helpers/perf/git.lua
@@ -0,0 +1,106 @@
+-- This software is copyright Kong Inc. and its licensors.
+-- Use of the software is subject to the agreement between your organization
+-- and Kong Inc. If there is no such agreement, use is governed by and
+-- subject to the terms of the Kong Master Software License Agreement found
+-- at https://konghq.com/enterprisesoftwarelicense/.
+-- [ END OF LICENSE 0867164ffc95e54f04670b5169c09574bdbd9bba ]
+
+local perf
+local logger = require("spec.helpers.perf.logger")
+local utils = require("spec.helpers.perf.utils")
+
+local my_logger = logger.new_logger("[git]")
+
+local git_temp_repo = "/tmp/perf-temp-repo"
+
+local function is_git_repo()
+ -- reload the perf module, for circular dependency issue
+ perf = require("spec.helpers.perf")
+
+ local _, err = perf.execute("git rev-parse HEAD")
+ return err == nil
+end
+
+-- is this test based on git versions: e.g. have we git checkout versions?
+local function is_git_based()
+ return package.path:find(git_temp_repo)
+end
+
+local function git_checkout(version)
+ -- reload the perf module, for circular dependency issue
+ perf = require("spec.helpers.perf")
+
+ local _, err = perf.execute("which git")
+ if err then
+ error("git binary not found")
+ end
+
+ if not is_git_repo() then
+ error("not in a git repo")
+ end
+
+ for _, cmd in ipairs({
+ "rm -rf " .. git_temp_repo,
+ "git clone . " .. git_temp_repo,
+ "cp -r .git/refs/ " .. git_temp_repo .. "/.git/.", -- copy refs
+ -- version is sometimes a hash so we can't always use -b
+ "cd " .. git_temp_repo .. " && git checkout " ..version
+ }) do
+ local _, err = perf.execute(cmd, { logger = my_logger.log_exec })
+ if err then
+ error("error preparing temporary repo: " .. err)
+ end
+ end
+
+ utils.add_lua_package_paths(git_temp_repo)
+
+ return git_temp_repo
+end
+
+local function git_restore()
+ return utils.restore_lua_package_paths()
+end
+
+local ee_version_suffix_old = "-dev-enterprise-edition" -- pre 3.0 suffix
+local ee_version_suffix = "-enterprise-edition"
+
+local version_map_table = {
+ -- temporary hack, fallback to previous version of artifact
+ -- if current version is not released yet
+ ["3.1.0.0"] = "3.0.0.0",
+}
+
+local alpha_pattern = "(.+)-alpha" -- new version format starting 3.0.0
+
+local function get_kong_version(raw)
+ -- unload the module if it's previously loaded
+ package.loaded["kong.meta"] = nil
+ package.loaded["kong.enterprise_edition.meta"] = nil
+
+ local ok, meta, _ = pcall(require, "kong.meta")
+
+ if ok then
+ local v = meta._VERSION
+ v = string.match(v, alpha_pattern) or v
+
+ if v:endswith(ee_version_suffix_old) then
+ v = v:sub(1, #v-#ee_version_suffix_old)
+ elseif v:endswith(ee_version_suffix) then
+ v = v:sub(1, #v-#ee_version_suffix)
+ end
+ if not raw and version_map_table[v] then
+ return version_map_table[v]
+ end
+ return v
+ end
+ error("can't read Kong version from kong.meta: " .. (meta or "nil"))
+end
+
+
+return {
+ is_git_repo = is_git_repo,
+ is_git_based = is_git_based,
+ git_checkout = git_checkout,
+ git_restore = git_restore,
+ get_kong_version = get_kong_version,
+}
diff --git a/kong-versions/3.9.0.0/kong/spec/helpers/perf/logger.lua b/kong-versions/3.9.0.0/kong/spec/helpers/perf/logger.lua
new file mode 100644
index 00000000..46b9ac37
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/helpers/perf/logger.lua
@@ -0,0 +1,69 @@
+-- This software is copyright Kong Inc. and its licensors.
+-- Use of the software is subject to the agreement between your organization
+-- and Kong Inc. If there is no such agreement, use is governed by and
+-- subject to the terms of the Kong Master Software License Agreement found
+-- at https://konghq.com/enterprisesoftwarelicense/.
+-- [ END OF LICENSE 0867164ffc95e54f04670b5169c09574bdbd9bba ]
+
+local tty = require("kong.cmd.utils.tty")
+
+local colors
+
+if not tty.isatty then
+ colors = setmetatable({}, {__index = function() return "" end})
+else
+ colors = { green = '\27[32m', yellow = '\27[33m', red = '\27[31m', reset = '\27[0m' }
+end
+
+local LOG_LEVEL = ngx.NOTICE
+
+-- Some logging helpers
+local level_cfg = {
+ [ngx.DEBUG] = { "debug", colors.green },
+ [ngx.INFO] = { "info", "" },
+ [ngx.NOTICE] = { "notice", "" },
+ [ngx.WARN] = { "warn", colors.yellow },
+ [ngx.ERR] = { "error", colors.red },
+ [ngx.CRIT] = { "crit", colors.red },
+}
+
+local function set_log_level(lvl)
+ if not level_cfg[lvl] then
+ error("Unknown log level ", lvl, 2)
+ end
+ LOG_LEVEL = lvl
+end
+
+local function log(lvl, namespace, ...)
+ lvl = lvl or ngx.INFO
+ local lvl_literal, lvl_color = unpack(level_cfg[lvl] or {"info", ""})
+ if lvl <= LOG_LEVEL then
+ ngx.update_time()
+ local msec = ngx.now()
+ print(lvl_color,
+ ("%s%s %8s %s "):format(
+ ngx.localtime():sub(12),
+ ("%.3f"):format(msec - math.floor(msec)):sub(2),
+ ("[%s]"):format(lvl_literal), namespace
+ ),
+ table.concat({...}, ""),
+ colors.reset)
+ end
+end
+local function new_logger(namespace)
+ return setmetatable({
+ debug = function(...) log(ngx.DEBUG, namespace, ...) end,
+ info = function(...) log(ngx.INFO, namespace, ...) end,
+ warn = function(...) log(ngx.WARN, namespace, ...) end,
+ err = function(...) log(ngx.ERR, namespace, ...) end,
+ crit = function(...) log(ngx.CRIT, namespace, ...) end,
+ log_exec = function(...) log(ngx.DEBUG, namespace, "=> ", ...) end,
+ }, {
+ __call = function(self, lvl, ...) log(lvl, namespace, ...) end,
+ })
+end
+
+return {
+ new_logger = new_logger,
+ set_log_level = set_log_level,
+}
\ No newline at end of file
diff --git a/kong-versions/3.9.0.0/kong/spec/helpers/perf/utils.lua b/kong-versions/3.9.0.0/kong/spec/helpers/perf/utils.lua
new file mode 100644
index 00000000..44a54b2f
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/helpers/perf/utils.lua
@@ -0,0 +1,258 @@
+-- This software is copyright Kong Inc. and its licensors.
+-- Use of the software is subject to the agreement between your organization
+-- and Kong Inc. If there is no such agreement, use is governed by and
+-- subject to the terms of the Kong Master Software License Agreement found
+-- at https://konghq.com/enterprisesoftwarelicense/.
+-- [ END OF LICENSE 0867164ffc95e54f04670b5169c09574bdbd9bba ]
+
+local ngx_pipe = require("ngx.pipe")
+local ffi = require("ffi")
+local cjson_safe = require("cjson.safe")
+local logger = require("spec.helpers.perf.logger")
+
+local log = logger.new_logger("[controller]")
+local DISABLE_EXEC_OUTPUT = os.getenv("PERF_TEST_DISABLE_EXEC_OUTPUT") or false
+
+string.startswith = function(s, start) -- luacheck: ignore
+ return s and start and start ~= "" and s:sub(1, #start) == start
+end
+
+string.endswith = function(s, e) -- luacheck: ignore
+ return s and e and e ~= "" and s:sub(#s-#e+1, #s) == e
+end
+
+--- Spawns a child process and get its exit code and outputs
+-- @param opts.stdin string the stdin buffer
+-- @param opts.logger function(lvl, _, line) stdout+stderr writer; if not defined, whole
+-- stdout and stderr is returned
+-- @param opts.stop_signal function return true to abort execution
+-- @return stdout+stderr string, err|nil
+local function execute(cmd, opts)
+ local log_output = opts and opts.logger
+
+ -- skip if PERF_TEST_DISABLE_EXEC_OUTPUT is set
+ if not DISABLE_EXEC_OUTPUT then
+ -- fallback to default logger if not defined
+ log_output = log_output or log.debug
+ log_output("[exec]: ", cmd)
+ end
+
+ local proc, err = ngx_pipe.spawn(cmd, {
+ merge_stderr = true,
+ })
+ if not proc then
+ return "", "failed to start process: " .. err
+ end
+
+ -- set stdout/stderr read timeout to 1s for faster noticing process exit
+ -- proc:set_timeouts(write_timeout?, stdout_read_timeout?, stderr_read_timeout?, wait_timeout?)
+ proc:set_timeouts(nil, 1000, 1000, nil)
+ if opts and opts.stdin then
+ proc:write(opts.stdin)
+ end
+ proc:shutdown("stdin")
+
+ local ret = {}
+
+ while true do
+ -- is it alive?
+ local ok = proc:kill(0)
+ if not ok then
+ break
+ end
+
+ local l, err = proc:stdout_read_line()
+ if l then
+ if log_output then
+ log_output(l)
+ end
+
+ -- always store output
+ table.insert(ret, l)
+ end
+ if err == "closed" then
+ break
+ end
+ local sig = opts and opts.stop_signal and opts.stop_signal()
+ if sig then
+ proc:kill(sig)
+ break
+ end
+ end
+ local ok, msg, code = proc:wait()
+ ok = ok and code == 0
+ ret = table.concat(ret, "\n")
+ if ok then
+ return ret
+ end
+
+ return ret, ("process exited with code %s: %s"):format(code, msg)
+end
+
+--- Execute a command and return until pattern is found in its output
+-- @function wait_output
+-- @param cmd string the command the execute
+-- @param pattern string the pattern to find in stdout and stderr
+-- @param timeout number time in seconds to wait for the pattern
+-- @return bool whether the pattern is found
+local function wait_output(cmd, pattern, timeout)
+ timeout = timeout or 5
+ local found
+ local co = coroutine.create(function()
+ while not found do
+ local line = coroutine.yield("yield")
+ if line:match(pattern) then
+ found = true
+ end
+ end
+ end)
+
+ -- start
+ coroutine.resume(co)
+
+ -- don't kill it, it me finish by itself
+ ngx.thread.spawn(function()
+ execute(cmd, {
+ logger = function(line)
+ return coroutine.running(co) and coroutine.resume(co, line)
+ end,
+ stop_signal = function() if found then return 9 end end,
+ })
+ end)
+
+ ngx.update_time()
+ local s = ngx.now()
+ while not found and ngx.now() - s <= timeout do
+ ngx.update_time()
+ ngx.sleep(0.1)
+ end
+
+ return found
+end
+
+ffi.cdef [[
+ int setenv(const char *name, const char *value, int overwrite);
+ int unsetenv(const char *name);
+]]
+
+--- Set an environment variable
+-- @function setenv
+-- @param env (string) name of the environment variable
+-- @param value the value to set
+-- @return true on success, false otherwise
+local function setenv(env, value)
+ return ffi.C.setenv(env, value, 1) == 0
+end
+
+
+--- Unset an environment variable
+-- @function setenv
+-- @param env (string) name of the environment variable
+-- @return true on success, false otherwise
+local function unsetenv(env)
+ return ffi.C.unsetenv(env) == 0
+end
+
+local handler = require("busted.outputHandlers.base")()
+local current_test_element
+
+local function register_busted_hook()
+ local busted = require("busted")
+
+ handler.testStart = function(element, parent)
+ current_test_element = element
+ end
+
+ busted.subscribe({'test', 'start'}, handler.testStart)
+end
+
+local function get_test_descriptor(sanitized, element_override)
+ local elem = current_test_element or element_override
+ if elem then
+ local msg = handler.getFullName(elem)
+ local common_prefix = "perf test for Kong "
+ if msg:startswith(common_prefix) then
+ msg = msg:sub(#common_prefix+1)
+ end
+ if sanitized then
+ msg = msg:gsub("[:/]", "#"):gsub("[ ,]", "_"):gsub("__", "_")
+ end
+ return msg
+ end
+end
+
+local function get_test_output_filename()
+ return get_test_descriptor(true)
+end
+
+local function parse_docker_image_labels(docker_inspect_output)
+ local m, err = cjson_safe.decode(docker_inspect_output)
+ if err then
+ return nil, err
+ end
+
+ local labels = m[1].Config.Labels or {}
+ labels.version = labels["org.opencontainers.image.version"] or "unknown_version"
+ labels.revision = labels["org.opencontainers.image.revision"] or "unknown_revision"
+ labels.created = labels["org.opencontainers.image.created"] or "unknown_created"
+ return labels
+end
+
+local original_lua_package_paths = package.path
+local function add_lua_package_paths(d)
+ d = d or "."
+ local pp = d .. "/?.lua;" ..
+ d .. "/?/init.lua;"
+ local pl_dir = require("pl.dir")
+ local pl_path = require("pl.path")
+ if pl_path.isdir(d .. "/plugins-ee") then
+ for _, p in ipairs(pl_dir.getdirectories(d .. "/plugins-ee")) do
+ pp = pp.. p .. "/?.lua;"..
+ p .. "/?/init.lua;"
+ end
+ end
+ package.path = pp .. ";" .. original_lua_package_paths
+end
+
+local function restore_lua_package_paths()
+ package.path = original_lua_package_paths
+end
+
+-- clear certain packages to allow spec.helpers to be re-imported
+-- those modules are only needed to run migrations in the "controller"
+-- and won't affect kong instances performing tests
+local function clear_loaded_package()
+ for _, p in ipairs({
+ "spec.helpers", "kong.cluster_events",
+ "kong.global", "kong.constants",
+ "kong.meta", "kong.enterprise_edition.meta",
+ "kong.cache", "kong.db", "kong.plugins", "kong.pdk", "kong.enterprise_edition.pdk",
+ }) do
+ package.loaded[p] = nil
+ end
+end
+
+local function print_and_save(s, path)
+ local shell = require "resty.shell"
+ shell.run("mkdir -p output", nil, 0)
+ print(s)
+ local f = io.open(path or "output/result.txt", "a")
+ f:write(s)
+ f:write("\n")
+ f:close()
+end
+
+return {
+ execute = execute,
+ wait_output = wait_output,
+ setenv = setenv,
+ unsetenv = unsetenv,
+ register_busted_hook = register_busted_hook,
+ get_test_descriptor = get_test_descriptor,
+ get_test_output_filename = get_test_output_filename,
+ parse_docker_image_labels = parse_docker_image_labels,
+ add_lua_package_paths = add_lua_package_paths,
+ restore_lua_package_paths = restore_lua_package_paths,
+ clear_loaded_package = clear_loaded_package,
+ print_and_save = print_and_save,
+}
diff --git a/kong-versions/3.9.0.0/kong/spec/helpers/redis/schema_migrations_templates/cluster_sentinel_addreses_to_nodes_370_to_380_spec_generator.lua b/kong-versions/3.9.0.0/kong/spec/helpers/redis/schema_migrations_templates/cluster_sentinel_addreses_to_nodes_370_to_380_spec_generator.lua
new file mode 100644
index 00000000..6b7591f7
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/helpers/redis/schema_migrations_templates/cluster_sentinel_addreses_to_nodes_370_to_380_spec_generator.lua
@@ -0,0 +1,177 @@
+-- This software is copyright Kong Inc. and its licensors.
+-- Use of the software is subject to the agreement between your organization
+-- and Kong Inc. If there is no such agreement, use is governed by and
+-- subject to the terms of the Kong Master Software License Agreement found
+-- at https://konghq.com/enterprisesoftwarelicense/.
+-- [ END OF LICENSE 0867164ffc95e54f04670b5169c09574bdbd9bba ]
+
+local assert = require "luassert"
+local busted = require "busted"
+local cjson = require "cjson"
+local uh = require "spec.upgrade_helpers"
+local pl_tablex = require "pl.tablex"
+
+
+local function test_plugin_migrations(test_configuration, minimum_supported_version)
+ if uh.database_type() == 'postgres' then
+ local handler = uh.get_busted_handler(minimum_supported_version)
+ handler("[" .. test_configuration.plugin_name .. "] plugin migration - (cluster/sentinel)_addresses to (cluster_sentinel)_nodes", function()
+ local route1_name = "test1"
+ local route2_name = "test2"
+
+ busted.describe("when redis is set to connect to redis cluster", function()
+ local cluster_node1 = { ip = "127.0.0.1", port = 26379 }
+ local cluster_node2 = { ip = "127.0.0.1", port = 26380 }
+ local cluster_node3 = { ip = "127.0.0.2", port = 26381 }
+ local cluster_nodes = { cluster_node1, cluster_node2, cluster_node3 }
+ local cluster_addresses = {
+ cluster_node1.ip .. ":" .. cluster_node1.port,
+ cluster_node2.ip .. ":" .. cluster_node2.port,
+ cluster_node3.ip .. ":" .. cluster_node3.port,
+ }
+
+ busted.lazy_setup(function()
+ assert(uh.start_kong())
+ end)
+
+ busted.lazy_teardown(function ()
+ assert(uh.stop_kong())
+ end)
+
+ uh.setup(function ()
+ local admin_client = assert(uh.admin_client())
+ local res = assert(admin_client:send {
+ method = "POST",
+ path = "/routes/",
+ body = {
+ name = route1_name,
+ hosts = { "test1.test" },
+ },
+ headers = {
+ ["Content-Type"] = "application/json"
+ }
+ })
+ assert.res_status(201, res)
+
+ res = assert(admin_client:send {
+ method = "POST",
+ path = "/routes/" .. route1_name .. "/plugins/",
+ body = {
+ name = test_configuration.plugin_name,
+ config = pl_tablex.merge(
+ test_configuration.plugin_config,
+ { redis = {
+ cluster_addresses = cluster_addresses
+ } },
+ true
+ )
+ },
+ headers = {
+ ["Content-Type"] = "application/json"
+ }
+ })
+ local body = cjson.decode(assert.res_status(201, res))
+ assert.equal(test_configuration.plugin_name, body.name)
+ assert.same(cluster_addresses, body.config.redis.cluster_addresses)
+ assert.is_nil(body.config.redis.cluster_nodes)
+ admin_client:close()
+ end)
+
+ uh.new_after_finish("has updated [" .. test_configuration.plugin_name .. "] redis configuration - cluster_addresses were translated to cluster_nodes", function ()
+ local admin_client = assert(uh.admin_client())
+ local res = assert(admin_client:send {
+ method = "GET",
+ path = "/routes/" .. route1_name .. "/plugins/",
+ })
+ local body = cjson.decode(assert.res_status(200, res))
+ assert.equal(1, #body.data)
+ assert.equal(test_configuration.plugin_name, body.data[1].name)
+ assert.same(cluster_nodes, body.data[1].config.redis.cluster_nodes)
+ assert.same(cluster_addresses, body.data[1].config.redis.cluster_addresses)
+
+ admin_client:close()
+ end)
+ end)
+
+ busted.describe("when redis is set to connect to redis sentinel", function()
+ local sentinel_node1 = { host = "localhost1", port = 26379 }
+ local sentinel_node2 = { host = "localhost2", port = 26380 }
+ local sentinel_node3 = { host = "localhost3", port = 26381 }
+ local sentinel_nodes = { sentinel_node1, sentinel_node2, sentinel_node3 }
+ local sentinel_addresses = {
+ sentinel_node1.host .. ":" .. sentinel_node1.port,
+ sentinel_node2.host .. ":" .. sentinel_node2.port,
+ sentinel_node3.host .. ":" .. sentinel_node3.port,
+ }
+
+ busted.lazy_setup(function()
+ assert(uh.start_kong())
+ end)
+
+ busted.lazy_teardown(function ()
+ assert(uh.stop_kong())
+ end)
+
+ uh.setup(function ()
+ local admin_client = assert(uh.admin_client())
+ local res = assert(admin_client:send {
+ method = "POST",
+ path = "/routes/",
+ body = {
+ name = route2_name,
+ hosts = { "test2.test" },
+ },
+ headers = {
+ ["Content-Type"] = "application/json"
+ }
+ })
+ assert.res_status(201, res)
+
+ res = assert(admin_client:send {
+ method = "POST",
+ path = "/routes/" .. route2_name .. "/plugins/",
+ body = {
+ name = test_configuration.plugin_name,
+ config = pl_tablex.merge(
+ test_configuration.plugin_config,
+ { redis = {
+ sentinel_role = "master",
+ sentinel_master = "localhost1",
+ sentinel_addresses = sentinel_addresses
+ } },
+ true
+ )
+ },
+ headers = {
+ ["Content-Type"] = "application/json"
+ }
+ })
+ local body = cjson.decode(assert.res_status(201, res))
+ assert.equal(test_configuration.plugin_name, body.name)
+ assert.same(sentinel_addresses, body.config.redis.sentinel_addresses)
+ assert.is_nil(body.config.redis.cluster_nodes)
+ admin_client:close()
+ end)
+
+ uh.new_after_finish("has updated [" .. test_configuration.plugin_name .. "] redis configuration - sentinel_addresses were translated to sentinel_nodes", function ()
+ local admin_client = assert(uh.admin_client())
+ local res = assert(admin_client:send {
+ method = "GET",
+ path = "/routes/" .. route2_name .. "/plugins/",
+ })
+ local body = cjson.decode(assert.res_status(200, res))
+ assert.equal(1, #body.data)
+ assert.equal(test_configuration.plugin_name, body.data[1].name)
+ assert.same(sentinel_nodes, body.data[1].config.redis.sentinel_nodes)
+ assert.same(sentinel_addresses, body.data[1].config.redis.sentinel_addresses)
+
+ admin_client:close()
+ end)
+ end)
+ end)
+ end
+end
+
+return {
+ test_plugin_migrations = test_plugin_migrations
+}
diff --git a/kong-versions/3.9.0.0/kong/spec/helpers/redis_helper.lua b/kong-versions/3.9.0.0/kong/spec/helpers/redis_helper.lua
new file mode 100644
index 00000000..3191aabd
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/helpers/redis_helper.lua
@@ -0,0 +1,53 @@
+-- This software is copyright Kong Inc. and its licensors.
+-- Use of the software is subject to the agreement between your organization
+-- and Kong Inc. If there is no such agreement, use is governed by and
+-- subject to the terms of the Kong Master Software License Agreement found
+-- at https://konghq.com/enterprisesoftwarelicense/.
+-- [ END OF LICENSE 0867164ffc95e54f04670b5169c09574bdbd9bba ]
+
+local redis = require "resty.redis"
+local version = require "version"
+
+local DEFAULT_TIMEOUT = 2000
+
+
+local function connect(host, port)
+ local redis_client = redis:new()
+ redis_client:set_timeout(DEFAULT_TIMEOUT)
+ assert(redis_client:connect(host, port))
+
+ local red_password = os.getenv("REDIS_PASSWORD") or nil -- This will allow for testing with a secured redis instance
+ if red_password then
+ assert(redis_client:auth(red_password))
+ end
+
+ local red_version = string.match(redis_client:info(), 'redis_version:([%g]+)\r\n')
+ return redis_client, assert(version(red_version))
+end
+
+local function reset_redis(host, port)
+ local redis_client = connect(host, port)
+ redis_client:flushall()
+ redis_client:close()
+end
+
+local function add_admin_user(redis_client, username, password)
+ assert(redis_client:acl("setuser", username, "on", "allkeys", "allcommands", ">" .. password))
+end
+
+local function add_basic_user(redis_client, username, password)
+ assert(redis_client:acl("setuser", username, "on", "allkeys", "+get", ">" .. password))
+end
+
+local function remove_user(redis_client, username)
+ assert(redis_client:acl("deluser", username))
+end
+
+
+return {
+ connect = connect,
+ add_admin_user = add_admin_user,
+ add_basic_user = add_basic_user,
+ remove_user = remove_user,
+ reset_redis = reset_redis,
+}
diff --git a/kong-versions/3.9.0.0/kong/spec/helpers/wait.lua b/kong-versions/3.9.0.0/kong/spec/helpers/wait.lua
new file mode 100644
index 00000000..2a082185
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/helpers/wait.lua
@@ -0,0 +1,497 @@
+-- This software is copyright Kong Inc. and its licensors.
+-- Use of the software is subject to the agreement between your organization
+-- and Kong Inc. If there is no such agreement, use is governed by and
+-- subject to the terms of the Kong Master Software License Agreement found
+-- at https://konghq.com/enterprisesoftwarelicense/.
+-- [ END OF LICENSE 0867164ffc95e54f04670b5169c09574bdbd9bba ]
+
+
+local say = require "say"
+local luassert = require "luassert.assert"
+local pretty = require "pl.pretty"
+
+local fmt = string.format
+local insert = table.insert
+
+---@param v any
+---@return string
+local function pretty_print(v)
+ local s, err = pretty.write(v)
+ if not s then
+ s = "ERROR: failed to pretty-print value: " .. tostring(err)
+ end
+ return s
+end
+
+
+local E_ARG_COUNT = "assertion.internal.argtolittle"
+local E_ARG_TYPE = "assertion.internal.badargtype"
+
+
+--- spec.helpers.wait.ctx.result
+-- "timeout", "error", "success", "max tries"
+local TIMEOUT = "timeout"
+local ERROR = "error"
+local SUCCESS = "success"
+local MAX_TRIES = "max tries"
+
+
+---
+-- @table spec.helpers.wait.ctx.condition
+-- helper functions that check the result of pcall() and report if the
+-- wait ctx condition has been met
+--
+-- @field "truthy"
+-- @field "falsy"
+-- @field "error"
+-- @field "no_error"
+local COND = {
+ truthy = function(pok, ok_or_err)
+ return (pok and ok_or_err and true) or false
+ end,
+
+ falsy = function(pok, ok_or_err)
+ return (pok and not ok_or_err) or false
+ end,
+
+ error = function(pok)
+ return not pok
+ end,
+
+ no_error = function(pok)
+ return (pok and true) or false
+ end,
+}
+
+
+---
+-- @param ... any
+-- @return any
+local function first_non_nil(...)
+ local n = select("#", ...)
+ for i = 1, n do
+ local v = select(i, ...)
+ if v ~= nil then
+ return v
+ end
+ end
+end
+
+
+---
+-- @param exp_type string
+-- @param field string|integer
+-- @param value any
+-- @param caller? string
+-- @param level? integer
+-- @return any
+local function check_type(exp_type, field, value, caller, level)
+ caller = caller or "wait_until"
+ level = (level or 1) + 1
+
+ local got_type = type(value)
+
+ -- accept callable tables
+ if exp_type == "function"
+ and got_type == "table"
+ and type(debug.getmetatable(value)) == "table"
+ and type(debug.getmetatable(value).__call) == "function"
+ then
+ got_type = "function"
+ end
+
+ if got_type ~= exp_type then
+ error(say(E_ARG_TYPE, { field, caller, exp_type, type(value) }),
+ level)
+ end
+
+ return value
+end
+
+
+local DEFAULTS = {
+ timeout = 5,
+ step = 0.05,
+ message = "UNSPECIFIED",
+ max_tries = 0,
+ ignore_exceptions = false,
+ condition = "truthy",
+}
+
+
+---
+-- @table spec.helpers.wait.ctx
+--
+-- @field condition "truthy"|"falsy"|"error"|"no_error"
+-- @field condition_met boolean
+-- @field debug? boolean
+-- @field elapsed number
+-- @field last_raised_error any
+-- @field error_raised boolean
+-- @field fn function
+-- @field ignore_exceptions boolean
+-- @field last_returned_error any
+-- @field last_returned_value any
+-- @field last_error any
+-- @field message? string
+-- @field result spec.helpers.wait.ctx.result
+-- @field step number
+-- @field timeout number
+-- @field tries number
+local wait_ctx = {
+ condition = nil,
+ condition_met = false,
+ debug = nil,
+ elapsed = 0,
+ error = nil,
+ error_raised = false,
+ ignore_exceptions = nil,
+ last_returned_error = nil,
+ last_returned_value = nil,
+ max_tries = nil,
+ message = nil,
+ result = "timeout",
+ step = nil,
+ timeout = nil,
+ traceback = nil,
+ tries = 0,
+}
+
+local wait_ctx_mt = { __index = wait_ctx }
+
+function wait_ctx:dd(msg)
+ if self.debug then
+ print(fmt("\n\n%s\n\n", pretty_print(msg)))
+ end
+end
+
+
+function wait_ctx:wait()
+ ngx.update_time()
+
+ local tstart = ngx.now()
+ local texp = tstart + self.timeout
+ local ok, res, err
+
+ local is_met = COND[self.condition]
+
+ if self.condition == "no_error" then
+ self.ignore_exceptions = true
+ end
+
+ local tries_remain = self.max_tries
+
+ local f = self.fn
+
+ local handle_error = function(e)
+ self.traceback = debug.traceback("", 2)
+ return e
+ end
+
+ while true do
+ ok, res, err = xpcall(f, handle_error)
+
+ if ok then
+ self.last_returned_value = first_non_nil(res, self.last_returned_value)
+ self.last_returned_error = first_non_nil(err, self.last_returned_error)
+ self.last_error = first_non_nil(err, self.last_error)
+ else
+ self.error_raised = true
+ self.last_raised_error = first_non_nil(res, self.last_raised_error)
+ self.last_error = first_non_nil(res, self.last_error)
+ end
+
+ self.tries = self.tries + 1
+ tries_remain = tries_remain - 1
+
+ self.condition_met = is_met(ok, res)
+
+ self:dd(self)
+
+ ngx.update_time()
+
+ -- yay!
+ if self.condition_met then
+ self.result = SUCCESS
+ break
+
+ elseif self.error_raised and not self.ignore_exceptions then
+ self.result = ERROR
+ break
+
+ elseif tries_remain == 0 then
+ self.result = MAX_TRIES
+ break
+
+ elseif ngx.now() >= texp then
+ self.result = TIMEOUT
+ break
+ end
+
+ ngx.sleep(self.step)
+ end
+
+ ngx.update_time()
+ self.elapsed = ngx.now() - tstart
+
+ self:dd(self)
+end
+
+
+local CTX_TYPES = {
+ condition = "string",
+ fn = "function",
+ max_tries = "number",
+ timeout = "number",
+ message = "string",
+ step = "number",
+ ignore_exceptions = "boolean",
+}
+
+
+function wait_ctx:validate(key, value, caller, level)
+ local typ = CTX_TYPES[key]
+
+ if not typ then
+ -- we don't care about validating this key
+ return value
+ end
+
+ if key == "condition" and type(value) == "string" then
+ assert(COND[value] ~= nil,
+ say(E_ARG_TYPE, { "condition", caller or "wait_until",
+ "one of: 'truthy', 'falsy', 'error', 'no_error'",
+ value }), level + 1)
+ end
+
+
+ return check_type(typ, key, value, caller, level)
+end
+
+
+---
+-- @param state table
+-- @return spec.helpers.wait.ctx
+local function get_or_create_ctx(state)
+ local ctx = rawget(state, "wait_ctx")
+
+ if not ctx then
+ ctx = setmetatable({}, wait_ctx_mt)
+ rawset(state, "wait_ctx", ctx)
+ end
+
+ return ctx
+end
+
+
+---
+-- @param ctx spec.helpers.wait.ctx
+-- @param key string
+-- @param ... any
+local function param(ctx, key, ...)
+ local value = first_non_nil(first_non_nil(...), DEFAULTS[key])
+ ctx[key] = ctx:validate(key, value, "wait_until", 3)
+end
+
+
+---
+-- @param state table
+-- @param arguments table
+-- @param level integer
+-- @return boolean ok
+-- @return table return_values
+local function wait_until(state, arguments, level)
+ assert(arguments.n > 0,
+ say(E_ARG_COUNT, { "wait_until", 1, arguments.n }),
+ level + 1)
+
+ local input = check_type("table", 1, arguments[1])
+ local ctx = get_or_create_ctx(state)
+
+ param(ctx, "fn", input.fn)
+ param(ctx, "timeout", input.timeout)
+ param(ctx, "step", input.step)
+ param(ctx, "message", input.message, arguments[2])
+ param(ctx, "max_tries", input.max_tries)
+ param(ctx, "debug", input.debug, ctx.debug, false)
+ param(ctx, "condition", input.condition)
+ param(ctx, "ignore_exceptions", input.ignore_exceptions)
+
+ -- reset the state
+ rawset(state, "wait_ctx", nil)
+
+ ctx:wait()
+
+ if ctx.condition_met then
+ return true, { ctx.last_returned_value, n = 1 }
+ end
+
+ local errors = {}
+ local result
+ if ctx.result == ERROR then
+ result = "error() raised"
+
+ elseif ctx.result == MAX_TRIES then
+ result = ("max tries (%s) reached"):format(ctx.max_tries)
+
+ elseif ctx.result == TIMEOUT then
+ result = ("timed out after %ss"):format(ctx.elapsed)
+ end
+
+ if ctx.last_returned_value ~= nil then
+ insert(errors, "Last returned value:")
+ insert(errors, "")
+ insert(errors, pretty_print(ctx.last_returned_value))
+ insert(errors, "")
+ end
+
+ if ctx.last_raised_error ~= nil then
+ insert(errors, "Last raised error:")
+ insert(errors, "")
+ insert(errors, pretty_print(ctx.last_raised_error))
+ insert(errors, "")
+
+ if ctx.traceback then
+ insert(errors, ctx.traceback)
+ insert(errors, "")
+ end
+ end
+
+ if ctx.last_returned_error ~= nil then
+ insert(errors, "Last returned error:")
+ insert(errors, "")
+ insert(errors, pretty_print(ctx.last_returned_error))
+ insert(errors, "")
+ end
+
+ arguments[1] = ctx.message
+ arguments[2] = result
+ arguments[3] = table.concat(errors, "\n")
+ arguments[4] = ctx.timeout
+ arguments[5] = ctx.step
+ arguments[6] = ctx.elapsed
+ arguments[7] = ctx.tries
+ arguments[8] = ctx.error_raised
+ arguments.n = 8
+
+ arguments.nofmt = {}
+ for i = 1, arguments.n do
+ arguments.nofmt[i] = true
+ end
+
+ return false, { ctx.last_error, n = 1 }
+end
+
+
+say:set("assertion.wait_until.failed", [[
+Failed to assert eventual condition:
+
+%q
+
+Result: %s
+
+%s
+---
+
+Timeout = %s
+Step = %s
+Elapsed = %s
+Tries = %s
+Raised = %s
+]])
+
+luassert:register("assertion", "wait_until", wait_until,
+ "assertion.wait_until.failed")
+
+
+local function wait_until_modifier(key)
+ return function(state, arguments)
+ local ctx = get_or_create_ctx(state)
+ ctx[key] = ctx:validate(key, arguments[1], key, 1)
+
+ return state
+ end
+end
+
+luassert:register("modifier", "with_timeout",
+ wait_until_modifier("timeout"))
+
+luassert:register("modifier", "with_step",
+ wait_until_modifier("step"))
+
+luassert:register("modifier", "with_max_tries",
+ wait_until_modifier("max_tries"))
+
+-- luassert blows up on us if we try to use 'error' or 'errors'
+luassert:register("modifier", "ignore_exceptions",
+ wait_until_modifier("ignore_exceptions"))
+
+luassert:register("modifier", "with_debug",
+ wait_until_modifier("debug"))
+
+
+---
+-- @param ctx spec.helpers.wait.ctx
+local function ctx_builder(ctx)
+ local self = setmetatable({}, {
+ __index = function(_, key)
+ error("unknown modifier/assertion: " .. tostring(key), 2)
+ end
+ })
+
+ local function with(field)
+ return function(value)
+ ctx[field] = ctx:validate(field, value, "with_" .. field, 2)
+ return self
+ end
+ end
+
+ self.with_timeout = with("timeout")
+ self.with_step = with("step")
+ self.with_max_tries = with("max_tries")
+ self.with_debug = with("debug")
+
+ self.ignore_exceptions = function(ignore)
+ ctx.ignore_exceptions = ctx:validate("ignore_exceptions", ignore,
+ "ignore_exceptions", 2)
+ return self
+ end
+
+ self.is_truthy = function(msg)
+ ctx.condition = "truthy"
+ return luassert.wait_until(ctx, msg)
+ end
+
+ self.is_falsy = function(msg)
+ ctx.condition = "falsy"
+ return luassert.wait_until(ctx, msg)
+ end
+
+ self.has_error = function(msg)
+ ctx.condition = "error"
+ return luassert.wait_until(ctx, msg)
+ end
+
+ self.has_no_error = function(msg)
+ ctx.condition = "no_error"
+ return luassert.wait_until(ctx, msg)
+ end
+
+ return self
+end
+
+
+local function eventually(state, arguments)
+ local ctx = get_or_create_ctx(state)
+
+ ctx.fn = first_non_nil(arguments[1], ctx.fn)
+
+ check_type("function", 1, ctx.fn, "eventually")
+
+ arguments[1] = ctx_builder(ctx)
+ arguments.n = 1
+
+ return true, arguments
+end
+
+luassert:register("assertion", "eventually", eventually)
diff --git a/kong-versions/3.9.0.0/kong/spec/internal/asserts.lua b/kong-versions/3.9.0.0/kong/spec/internal/asserts.lua
new file mode 100644
index 00000000..e08e2080
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/internal/asserts.lua
@@ -0,0 +1,874 @@
+-- This software is copyright Kong Inc. and its licensors.
+-- Use of the software is subject to the agreement between your organization
+-- and Kong Inc. If there is no such agreement, use is governed by and
+-- subject to the terms of the Kong Master Software License Agreement found
+-- at https://konghq.com/enterprisesoftwarelicense/.
+-- [ END OF LICENSE 0867164ffc95e54f04670b5169c09574bdbd9bba ]
+
+------------------------------------------------------------------
+-- Collection of utilities to help testing Kong features and plugins.
+--
+-- @copyright Copyright 2016-2022 Kong Inc. All rights reserved.
+-- @license [Apache 2.0](https://opensource.org/licenses/Apache-2.0)
+-- @module spec.helpers
+
+
+local cjson = require("cjson.safe")
+local say = require("say")
+local pl_dir = require("pl.dir")
+local pl_file = require("pl.file")
+local colors = require("ansicolors")
+local luassert = require("luassert.assert")
+
+
+local conf = require("spec.internal.conf")
+local misc = require("spec.internal.misc")
+
+
+local strip = require("kong.tools.string").strip
+local splitlines = require("pl.stringx").splitlines
+
+
+--------------------
+-- Custom assertions
+--
+-- @section assertions
+
+
+
+--- Generic modifier "response".
+-- Will set a "response" value in the assertion state, so following
+-- assertions will operate on the value set.
+-- @function response
+-- @param response_obj results from `http_client:send` function (or any of the
+-- shortcuts `client:get`, `client:post`, etc).
+-- @usage
+-- local res = client:get("/request", { .. request options here ..})
+-- local response_length = assert.response(res).has.header("Content-Length")
+local function modifier_response(state, arguments, level)
+ assert(arguments.n > 0,
+ "response modifier requires a response object as argument")
+
+ local res = arguments[1]
+
+ assert(type(res) == "table" and type(res.read_body) == "function",
+ "response modifier requires a response object as argument, got: " .. tostring(res))
+
+ rawset(state, "kong_response", res)
+ rawset(state, "kong_request", nil)
+
+ return state
+end
+luassert:register("modifier", "response", modifier_response)
+
+
+--- Generic modifier "request".
+-- Will set a "request" value in the assertion state, so following
+-- assertions will operate on the value set.
+--
+-- The request must be inside a 'response' from the `mock_upstream`. If a request
+-- is send to the `mock_upstream` endpoint `"/request"`, it will echo the request
+-- received in the body of the response.
+-- @function request
+-- @param response_obj results from `http_client:send` function (or any of the
+-- shortcuts `client:get`, `client:post`, etc).
+-- @usage
+-- local res = client:post("/request", {
+-- headers = { ["Content-Type"] = "application/json" },
+-- body = { hello = "world" },
+-- })
+-- local request_length = assert.request(res).has.header("Content-Length")
+local function modifier_request(state, arguments, level)
+ local generic = "The assertion 'request' modifier takes a http response"
+ .. " object as input to decode the json-body returned by"
+ .. " mock_upstream, to retrieve the proxied request."
+
+ local res = arguments[1]
+
+ assert(type(res) == "table" and type(res.read_body) == "function",
+ "Expected a http response object, got '" .. tostring(res) .. "'. " .. generic)
+
+ local body, request, err
+ body = assert(res:read_body())
+ request, err = cjson.decode(body)
+
+ assert(request, "Expected the http response object to have a json encoded body,"
+ .. " but decoding gave error '" .. tostring(err) .. "'. Obtained body: "
+ .. body .. "\n." .. generic)
+
+
+ if misc.lookup((res.headers or {}),"X-Powered-By") ~= "mock_upstream" then
+ error("Could not determine the response to be from mock_upstream")
+ end
+
+ rawset(state, "kong_request", request)
+ rawset(state, "kong_response", nil)
+
+ return state
+end
+luassert:register("modifier", "request", modifier_request)
+
+
+--- Generic fail assertion. A convenience function for debugging tests, always
+-- fails. It will output the values it was called with as a table, with an `n`
+-- field to indicate the number of arguments received. See also `intercept`.
+-- @function fail
+-- @param ... any set of parameters to be displayed with the failure
+-- @see intercept
+-- @usage
+-- assert.fail(some, value)
+local function fail(state, args)
+ local out = {}
+ for k,v in pairs(args) do out[k] = v end
+ args[1] = out
+ args.n = 1
+ return false
+end
+say:set("assertion.fail.negative", [[
+Fail assertion was called with the following parameters (formatted as a table);
+%s
+]])
+luassert:register("assertion", "fail", fail,
+ "assertion.fail.negative",
+ "assertion.fail.negative")
+
+
+--- Assertion to check whether a value lives in an array.
+-- @function contains
+-- @param expected The value to search for
+-- @param array The array to search for the value
+-- @param pattern (optional) If truthy, then `expected` is matched as a Lua string
+-- pattern
+-- @return the array index at which the value was found
+-- @usage
+-- local arr = { "one", "three" }
+-- local i = assert.contains("one", arr) --> passes; i == 1
+-- local i = assert.contains("two", arr) --> fails
+-- local i = assert.contains("ee$", arr, true) --> passes; i == 2
+local function contains(state, args)
+ local expected, arr, pattern = misc.unpack(args)
+ local found
+ for i = 1, #arr do
+ if (pattern and string.match(arr[i], expected)) or arr[i] == expected then
+ found = i
+ break
+ end
+ end
+ return found ~= nil, {found}
+end
+say:set("assertion.contains.negative", [[
+Expected array to contain element.
+Expected to contain:
+%s
+]])
+say:set("assertion.contains.positive", [[
+Expected array to not contain element.
+Expected to not contain:
+%s
+]])
+luassert:register("assertion", "contains", contains,
+ "assertion.contains.negative",
+ "assertion.contains.positive")
+
+
+local function copy_errlog(errlog_path)
+ local file_path = "Unknown path"
+ local line_number = "Unknown line"
+ local errlog_cache_dir = os.getenv("SPEC_ERRLOG_CACHE_DIR") or "/tmp/kong_errlog_cache"
+
+ local ok, err = pl_dir.makepath(errlog_cache_dir)
+ assert(ok, "makepath failed: " .. tostring(err))
+
+ local info = debug.getinfo(4, "Sl")
+ if info then
+ file_path = info.source:gsub("^@", "")
+ line_number = info.currentline
+ end
+
+ if string.find(file_path, '/', nil, true) then
+ file_path = string.gsub(file_path, '/', '_')
+ end
+ file_path = errlog_cache_dir .. "/" .. file_path:gsub("%.lua$", "_") .. "line_" .. line_number .. '.log'
+
+ ok, err = pl_file.copy(errlog_path, file_path)
+ if ok then
+ print(colors("%{yellow}Log saved as: " .. file_path .. "%{reset}"))
+ else
+ print(colors("%{red}Failed to save error log for test " .. file_path .. ": " .. err))
+ end
+end
+
+
+--- Assertion to check the status-code of a http response.
+-- @function status
+-- @param expected the expected status code
+-- @param response (optional) results from `http_client:send` function,
+-- alternatively use `response`.
+-- @return the response body as a string, for a json body see `jsonbody`.
+-- @usage
+-- local res = assert(client:send { .. your request params here .. })
+-- local body = assert.has.status(200, res) -- or alternativly
+-- local body = assert.response(res).has.status(200) -- does the same
+local function res_status(state, args)
+ assert(not rawget(state, "kong_request"),
+ "Cannot check statuscode against a request object,"
+ .. " only against a response object")
+
+ local expected = args[1]
+ local res = args[2] or rawget(state, "kong_response")
+
+ assert(type(expected) == "number",
+ "Expected response code must be a number value. Got: " .. tostring(expected))
+ assert(type(res) == "table" and type(res.read_body) == "function",
+ "Expected a http_client response. Got: " .. tostring(res))
+
+ if expected ~= res.status then
+ local body, err = res:read_body()
+ if not body then body = "Error reading body: " .. err end
+ table.insert(args, 1, strip(body))
+ table.insert(args, 1, res.status)
+ table.insert(args, 1, expected)
+ args.n = 3
+
+ if res.status == 500 then
+ copy_errlog(conf.nginx_err_logs)
+
+ -- on HTTP 500, we can try to read the server's error logs
+ -- for debugging purposes (very useful for travis)
+ local str = pl_file.read(conf.nginx_err_logs)
+ if not str then
+ return false -- no err logs to read in this prefix
+ end
+
+ local lines_t = splitlines(str)
+ local str_t = {}
+ -- filter out debugs as they are not usually useful in this context
+ for i = 1, #lines_t do
+ if not lines_t[i]:match(" %[debug%] ") then
+ table.insert(str_t, lines_t[i])
+ end
+ end
+
+ local first_line = #str_t - math.min(60, #str_t) + 1
+ local msg_t = {"\nError logs (" .. conf.nginx_err_logs .. "), only last 60 non-debug logs are displayed:"}
+ for i = first_line, #str_t do
+ msg_t[#msg_t+1] = str_t[i]
+ end
+
+ table.insert(args, 4, table.concat(msg_t, "\n"))
+ args.n = 4
+ end
+
+ return false
+ else
+ local body, err = res:read_body()
+ local output = body
+ if not output then output = "Error reading body: " .. err end
+ output = strip(output)
+ table.insert(args, 1, output)
+ table.insert(args, 1, res.status)
+ table.insert(args, 1, expected)
+ args.n = 3
+ return true, { strip(body) }
+ end
+end
+say:set("assertion.res_status.negative", [[
+Invalid response status code.
+Status expected:
+%s
+Status received:
+%s
+Body:
+%s
+%s]])
+say:set("assertion.res_status.positive", [[
+Invalid response status code.
+Status not expected:
+%s
+Status received:
+%s
+Body:
+%s
+%s]])
+luassert:register("assertion", "status", res_status,
+ "assertion.res_status.negative", "assertion.res_status.positive")
+luassert:register("assertion", "res_status", res_status,
+ "assertion.res_status.negative", "assertion.res_status.positive")
+
+
+--- Checks and returns a json body of an http response/request. Only checks
+-- validity of the json, does not check appropriate headers. Setting the target
+-- to check can be done through the `request` and `response` modifiers.
+--
+-- For a non-json body, see the `status` assertion.
+-- @function jsonbody
+-- @return the decoded json as a table
+-- @usage
+-- local res = assert(client:send { .. your request params here .. })
+-- local json_table = assert.response(res).has.jsonbody()
+local function jsonbody(state, args)
+ assert(args[1] == nil and rawget(state, "kong_request") or rawget(state, "kong_response"),
+ "the `jsonbody` assertion does not take parameters. " ..
+ "Use the `response`/`require` modifiers to set the target to operate on")
+
+ if rawget(state, "kong_response") then
+ local body = rawget(state, "kong_response"):read_body()
+ local json, err = cjson.decode(body)
+ if not json then
+ table.insert(args, 1, "Error decoding: " .. tostring(err) .. "\nResponse body:" .. body)
+ args.n = 1
+ return false
+ end
+ return true, {json}
+
+ else
+ local r = rawget(state, "kong_request")
+ if r.post_data
+ and (r.post_data.kind == "json" or r.post_data.kind == "json (error)")
+ and r.post_data.params
+ then
+ local pd = r.post_data
+ return true, { { params = pd.params, data = pd.text, error = pd.error, kind = pd.kind } }
+
+ else
+ error("No json data found in the request")
+ end
+ end
+end
+say:set("assertion.jsonbody.negative", [[
+Expected response body to contain valid json. Got:
+%s
+]])
+say:set("assertion.jsonbody.positive", [[
+Expected response body to not contain valid json. Got:
+%s
+]])
+luassert:register("assertion", "jsonbody", jsonbody,
+ "assertion.jsonbody.negative",
+ "assertion.jsonbody.positive")
+
+
+--- Asserts that a named header in a `headers` subtable exists.
+-- Header name comparison is done case-insensitive.
+-- @function header
+-- @param name header name to look for (case insensitive).
+-- @see response
+-- @see request
+-- @return value of the header
+-- @usage
+-- local res = client:get("/request", { .. request options here ..})
+-- local resp_header_value = assert.response(res).has.header("Content-Length")
+-- local req_header_value = assert.request(res).has.header("Content-Length")
+local function res_header(state, args)
+ local header = args[1]
+ local res = args[2] or rawget(state, "kong_request") or rawget(state, "kong_response")
+ assert(type(res) == "table" and type(res.headers) == "table",
+ "'header' assertion input does not contain a 'headers' subtable")
+ local value = misc.lookup(res.headers, header)
+ table.insert(args, 1, res.headers)
+ table.insert(args, 1, header)
+ args.n = 2
+ if not value then
+ return false
+ end
+ return true, {value}
+end
+say:set("assertion.res_header.negative", [[
+Expected header:
+%s
+But it was not found in:
+%s
+]])
+say:set("assertion.res_header.positive", [[
+Did not expected header:
+%s
+But it was found in:
+%s
+]])
+luassert:register("assertion", "header", res_header,
+ "assertion.res_header.negative",
+ "assertion.res_header.positive")
+
+
+---
+-- An assertion to look for a query parameter in a query string.
+-- Parameter name comparison is done case-insensitive.
+-- @function queryparam
+-- @param name name of the query parameter to look up (case insensitive)
+-- @return value of the parameter
+-- @usage
+-- local res = client:get("/request", {
+-- query = { hello = "world" },
+-- })
+-- local param_value = assert.request(res).has.queryparam("hello")
+local function req_query_param(state, args)
+ local param = args[1]
+ local req = rawget(state, "kong_request")
+ assert(req, "'queryparam' assertion only works with a request object")
+ local params
+ if type(req.uri_args) == "table" then
+ params = req.uri_args
+
+ else
+ error("No query parameters found in request object")
+ end
+ local value = misc.lookup(params, param)
+ table.insert(args, 1, params)
+ table.insert(args, 1, param)
+ args.n = 2
+ if not value then
+ return false
+ end
+ return true, {value}
+end
+say:set("assertion.req_query_param.negative", [[
+Expected query parameter:
+%s
+But it was not found in:
+%s
+]])
+say:set("assertion.req_query_param.positive", [[
+Did not expected query parameter:
+%s
+But it was found in:
+%s
+]])
+luassert:register("assertion", "queryparam", req_query_param,
+ "assertion.req_query_param.negative",
+ "assertion.req_query_param.positive")
+
+
+---
+-- Adds an assertion to look for a urlencoded form parameter in a request.
+-- Parameter name comparison is done case-insensitive. Use the `request` modifier to set
+-- the request to operate on.
+-- @function formparam
+-- @param name name of the form parameter to look up (case insensitive)
+-- @return value of the parameter
+-- @usage
+-- local r = assert(proxy_client:post("/request", {
+-- body = {
+-- hello = "world",
+-- },
+-- headers = {
+-- host = "mock_upstream",
+-- ["Content-Type"] = "application/x-www-form-urlencoded",
+-- },
+-- })
+-- local value = assert.request(r).has.formparam("hello")
+-- assert.are.equal("world", value)
+local function req_form_param(state, args)
+ local param = args[1]
+ local req = rawget(state, "kong_request")
+ assert(req, "'formparam' assertion can only be used with a mock_upstream request object")
+
+ local value
+ if req.post_data
+ and (req.post_data.kind == "form" or req.post_data.kind == "multipart-form")
+ then
+ value = misc.lookup(req.post_data.params or {}, param)
+ else
+ error("Could not determine the request to be from either mock_upstream")
+ end
+
+ table.insert(args, 1, req)
+ table.insert(args, 1, param)
+ args.n = 2
+ if not value then
+ return false
+ end
+ return true, {value}
+end
+say:set("assertion.req_form_param.negative", [[
+Expected url encoded form parameter:
+%s
+But it was not found in request:
+%s
+]])
+say:set("assertion.req_form_param.positive", [[
+Did not expected url encoded form parameter:
+%s
+But it was found in request:
+%s
+]])
+luassert:register("assertion", "formparam", req_form_param,
+ "assertion.req_form_param.negative",
+ "assertion.req_form_param.positive")
+
+
+---
+-- Assertion to ensure a value is greater than a base value.
+-- @function is_gt
+-- @param base the base value to compare against
+-- @param value the value that must be greater than the base value
+local function is_gt(state, arguments)
+ local expected = arguments[1]
+ local value = arguments[2]
+
+ arguments[1] = value
+ arguments[2] = expected
+
+ return value > expected
+end
+say:set("assertion.gt.negative", [[
+Given value (%s) should be greater than expected value (%s)
+]])
+say:set("assertion.gt.positive", [[
+Given value (%s) should not be greater than expected value (%s)
+]])
+luassert:register("assertion", "gt", is_gt,
+ "assertion.gt.negative",
+ "assertion.gt.positive")
+
+
+---
+-- Matcher to ensure a value is greater than a base value.
+-- @function is_gt_matcher
+-- @param base the base value to compare against
+-- @param value the value that must be greater than the base value
+local function is_gt_matcher(state, arguments)
+ local expected = arguments[1]
+ return function(value)
+ return value > expected
+ end
+end
+luassert:register("matcher", "gt", is_gt_matcher)
+
+
+--- Generic modifier "certificate".
+-- Will set a "certificate" value in the assertion state, so following
+-- assertions will operate on the value set.
+-- @function certificate
+-- @param cert The cert text
+-- @see cn
+-- @usage
+-- assert.certificate(cert).has.cn("ssl-example.com")
+local function modifier_certificate(state, arguments, level)
+ local generic = "The assertion 'certficate' modifier takes a cert text"
+ .. " as input to validate certificate parameters"
+ .. " against."
+ local cert = arguments[1]
+ assert(type(cert) == "string",
+ "Expected a certificate text, got '" .. tostring(cert) .. "'. " .. generic)
+ rawset(state, "kong_certificate", cert)
+ return state
+end
+luassert:register("modifier", "certificate", modifier_certificate)
+
+
+--- Assertion to check whether a CN is matched in an SSL cert.
+-- @function cn
+-- @param expected The CN value
+-- @param cert The cert text
+-- @return the CN found in the cert
+-- @see certificate
+-- @usage
+-- assert.cn("ssl-example.com", cert)
+--
+-- -- alternative:
+-- assert.certificate(cert).has.cn("ssl-example.com")
+local function assert_cn(state, args)
+ local expected = args[1]
+ if args[2] and rawget(state, "kong_certificate") then
+ error("assertion 'cn' takes either a 'certificate' modifier, or 2 parameters, not both")
+ end
+ local cert = args[2] or rawget(state, "kong_certificate")
+ local cn = string.match(cert, "CN%s*=%s*([^%s,]+)")
+ args[2] = cn or "(CN not found in certificate)"
+ args.n = 2
+ return cn == expected
+end
+say:set("assertion.cn.negative", [[
+Expected certificate to have the given CN value.
+Expected CN:
+%s
+Got instead:
+%s
+]])
+say:set("assertion.cn.positive", [[
+Expected certificate to not have the given CN value.
+Expected CN to not be:
+%s
+Got instead:
+%s
+]])
+luassert:register("assertion", "cn", assert_cn,
+ "assertion.cn.negative",
+ "assertion.cn.positive")
+
+
+do
+ --- Generic modifier "logfile"
+ -- Will set an "errlog_path" value in the assertion state.
+ -- @function logfile
+ -- @param path A path to the log file (defaults to the test prefix's
+ -- errlog).
+ -- @see line
+ -- @see clean_logfile
+ -- @usage
+ -- assert.logfile("./my/logfile.log").has.no.line("[error]", true)
+ local function modifier_errlog(state, args)
+ local errlog_path = args[1] or conf.nginx_err_logs
+
+ assert(type(errlog_path) == "string", "logfile modifier expects nil, or " ..
+ "a string as argument, got: " ..
+ type(errlog_path))
+
+ rawset(state, "errlog_path", errlog_path)
+
+ return state
+ end
+
+ luassert:register("modifier", "errlog", modifier_errlog) -- backward compat
+ luassert:register("modifier", "logfile", modifier_errlog)
+
+ local function substr(subject, pattern)
+ if subject:find(pattern, nil, true) ~= nil then
+ return subject
+ end
+ end
+
+ local function re_match(subject, pattern)
+ local pos, _, err = ngx.re.find(subject, pattern, "oj")
+ if err then
+ error(("invalid regex provided to logfile assertion %q: %s")
+ :format(pattern, err), 5)
+ end
+
+ if pos then
+ return subject
+ end
+ end
+
+ -- XXX EE [[
+ -- FIXME: major hack here
+ --
+ -- CI and dev environments use an auto-generated license with a very
+ -- short life span, which triggers log entries like:
+ --
+ -- ```
+ -- 2022/11/10 15:50:17 [warn] 1440109#0: *54 stream [lua] license_helpers.lua:231: log_license_state(): The Kong Enterprise license will expire on 2022-12-20. Please contact to renew your license., context: ngx.timer
+ -- ```
+ --
+ -- These log entries are a time bomb for our integration tests, because
+ -- we have many test cases that do something like this:
+ --
+ -- ```
+ -- -- ensure there are no warnings in the error.log after doing $thing
+ -- assert.logfile().has.no.line("[warn]")
+ -- ```
+ --
+ -- This code attempts to filter out license warnings.
+ local license_warning = "Please contact to renew your license."
+ local license_warning_dev = "Using development (e.g. not a release) license validation"
+ local portal_vitals_deprecated = "portal and vitals are deprecated"
+ local portal_and_vitals_key_invalid = "portal_and_vitals_key is invalid. please contact your support representative."
+
+ local function is_ee_license_warning(line)
+ return line
+ and (substr(line, license_warning)
+ or substr(line, license_warning_dev)
+ or substr(line, portal_vitals_deprecated)
+ or substr(line, portal_and_vitals_key_invalid))
+ end
+ -- XXX EE ]]
+
+ local function find_in_file(fpath, pattern, matcher)
+ local fh = assert(io.open(fpath, "r"))
+ local found
+
+ for line in fh:lines() do
+ -- XXX EE [[
+ -- see comment above re: filtering out license warnings
+ if matcher(line, pattern) and not is_ee_license_warning(line) then
+ -- XXX EE ]]
+ found = line
+ break
+ end
+ end
+
+ fh:close()
+
+ return found
+ end
+
+
+ --- Assertion checking if any line from a file matches the given regex or
+ -- substring.
+ -- @function line
+ -- @param regex The regex to evaluate against each line.
+ -- @param plain If true, the regex argument will be considered as a plain
+ -- string.
+ -- @param timeout An optional timeout after which the assertion will fail if
+ -- reached.
+ -- @param fpath An optional path to the file (defaults to the filelog
+ -- modifier)
+ -- @see logfile
+ -- @see clean_logfile
+ -- @usage
+ -- helpers.clean_logfile()
+ --
+ -- -- run some tests here
+ --
+ -- assert.logfile().has.no.line("[error]", true)
+ local function match_line(state, args)
+ local regex = args[1]
+ local plain = args[2]
+ local timeout = args[3] or 2
+ local fpath = args[4] or rawget(state, "errlog_path")
+
+ assert(type(regex) == "string",
+ "Expected the regex argument to be a string")
+ assert(type(fpath) == "string",
+ "Expected the file path argument to be a string")
+ assert(type(timeout) == "number" and timeout >= 0,
+ "Expected the timeout argument to be a number >= 0")
+
+
+ local matcher = plain and substr or re_match
+
+ local found = find_in_file(fpath, regex, matcher)
+ local deadline = ngx.now() + timeout
+
+ while not found and ngx.now() <= deadline do
+ ngx.sleep(0.05)
+ found = find_in_file(fpath, regex, matcher)
+ end
+
+ args[1] = fpath
+ args[2] = regex
+ args.n = 2
+
+ if found then
+ args[3] = found
+ args.n = 3
+ end
+
+ return found
+ end
+
+ say:set("assertion.match_line.negative", misc.unindent [[
+ Expected file at:
+ %s
+ To match:
+ %s
+ ]])
+ say:set("assertion.match_line.positive", misc.unindent [[
+ Expected file at:
+ %s
+ To not match:
+ %s
+ But matched line:
+ %s
+ ]])
+ luassert:register("assertion", "line", match_line,
+ "assertion.match_line.negative",
+ "assertion.match_line.positive")
+end
+
+
+--- Assertion to check whether a string matches a regular expression
+-- @function match_re
+-- @param string the string
+-- @param regex the regular expression
+-- @return true or false
+-- @usage
+-- assert.match_re("foobar", [[bar$]])
+--
+
+local function match_re(_, args)
+ local string = args[1]
+ local regex = args[2]
+ assert(type(string) == "string",
+ "Expected the string argument to be a string")
+ assert(type(regex) == "string",
+ "Expected the regex argument to be a string")
+ local from, _, err = ngx.re.find(string, regex)
+ if err then
+ error(err)
+ end
+ if from then
+ table.insert(args, 1, string)
+ table.insert(args, 1, regex)
+ args.n = 2
+ return true
+ else
+ return false
+ end
+end
+
+say:set("assertion.match_re.negative", misc.unindent [[
+ Expected log:
+ %s
+ To match:
+ %s
+ ]])
+say:set("assertion.match_re.positive", misc.unindent [[
+ Expected log:
+ %s
+ To not match:
+ %s
+ But matched line:
+ %s
+ ]])
+luassert:register("assertion", "match_re", match_re,
+ "assertion.match_re.negative",
+ "assertion.match_re.positive")
+
+
+---
+-- Assertion to partially compare two lua tables.
+-- @function partial_match
+-- @param partial_table the table with subset of fields expect to match
+-- @param full_table the full table that should contain partial_table and potentially other fields
+local function partial_match(state, arguments)
+
+ local function deep_matches(t1, t2, parent_keys)
+ for key, v in pairs(t1) do
+ local compound_key = (parent_keys and parent_keys .. "." .. key) or key
+ if type(v) == "table" then
+ local ok, compound_key, v1, v2 = deep_matches(t1[key], t2[key], compound_key)
+ if not ok then
+ return ok, compound_key, v1, v2
+ end
+ else
+ if (state.mod == true and t1[key] ~= t2[key]) or (state.mod == false and t1[key] == t2[key]) then
+ return false, compound_key, t1[key], t2[key]
+ end
+ end
+ end
+
+ return true
+ end
+
+ local partial_table = arguments[1]
+ local full_table = arguments[2]
+
+ local ok, compound_key, v1, v2 = deep_matches(partial_table, full_table)
+
+ if not ok then
+ arguments[1] = compound_key
+ arguments[2] = v1
+ arguments[3] = v2
+ arguments.n = 3
+
+ return not state.mod
+ end
+
+ return state.mod
+end
+
+say:set("assertion.partial_match.negative", [[
+Values at key %s should not be equal
+]])
+say:set("assertion.partial_match.positive", [[
+Values at key %s should be equal but are not.
+Expected: %s, given: %s
+]])
+luassert:register("assertion", "partial_match", partial_match,
+ "assertion.partial_match.positive",
+ "assertion.partial_match.negative")
+
+
+-- the same behivor with other modules
+return true
diff --git a/kong-versions/3.9.0.0/kong/spec/internal/client.lua b/kong-versions/3.9.0.0/kong/spec/internal/client.lua
new file mode 100644
index 00000000..bcb4480c
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/internal/client.lua
@@ -0,0 +1,914 @@
+-- This software is copyright Kong Inc. and its licensors.
+-- Use of the software is subject to the agreement between your organization
+-- and Kong Inc. If there is no such agreement, use is governed by and
+-- subject to the terms of the Kong Master Software License Agreement found
+-- at https://konghq.com/enterprisesoftwarelicense/.
+-- [ END OF LICENSE 0867164ffc95e54f04670b5169c09574bdbd9bba ]
+
+------------------------------------------------------------------
+-- Collection of utilities to help testing Kong features and plugins.
+--
+-- @copyright Copyright 2016-2022 Kong Inc. All rights reserved.
+-- @license [Apache 2.0](https://opensource.org/licenses/Apache-2.0)
+-- @module spec.helpers
+
+
+local pl_tablex = require("pl.tablex")
+local luassert = require("luassert.assert")
+local cjson = require("cjson.safe")
+local http = require("resty.http")
+local kong_table = require("kong.tools.table")
+local uuid = require("kong.tools.uuid").uuid
+local reqwest = require("reqwest")
+
+local CONSTANTS = require("spec.internal.constants")
+local conf = require("spec.internal.conf")
+local shell = require("spec.internal.shell")
+local misc = require("spec.internal.misc")
+local asserts = require("spec.internal.asserts") -- luacheck: ignore
+
+
+-----------------
+-- Custom helpers
+-----------------
+local resty_http_proxy_mt = setmetatable({}, { __index = http })
+resty_http_proxy_mt.__index = resty_http_proxy_mt
+
+
+--- Check if a request can be retried in the case of a closed connection
+--
+-- For now this is limited to "safe" methods as defined by:
+-- https://datatracker.ietf.org/doc/html/rfc7231#section-4.2.1
+--
+-- XXX Since this strictly applies to closed connections, it might be okay to
+-- open this up to include idempotent methods like PUT and DELETE if we do
+-- some more testing first
+local function can_reopen(method)
+ method = string.upper(method or "GET")
+ return method == "GET"
+ or method == "HEAD"
+ or method == "OPTIONS"
+ or method == "TRACE"
+end
+
+
+--- http_client.
+-- An http-client class to perform requests.
+--
+-- * Based on [lua-resty-http](https://github.com/pintsized/lua-resty-http) but
+-- with some modifications
+--
+-- * Additional convenience methods will be injected for the following methods;
+-- "get", "post", "put", "patch", "delete". Each of these methods comes with a
+-- built-in assert. The signature of the functions is `client:get(path, opts)`.
+--
+-- * Body will be formatted according to the "Content-Type" header, see `http_client:send`.
+--
+-- * Query parameters will be added, see `http_client:send`.
+--
+-- @section http_client
+-- @usage
+-- -- example usage of the client
+-- local client = helpers.proxy_client()
+-- -- no need to check for `nil+err` since it is already wrapped in an assert
+--
+-- local opts = {
+-- headers = {
+-- ["My-Header"] = "my header value"
+-- }
+-- }
+-- local result = client:get("/services/foo", opts)
+-- -- the 'get' is wrapped in an assert, so again no need to check for `nil+err`
+
+
+--- Send a http request.
+-- Based on [lua-resty-http](https://github.com/pintsized/lua-resty-http).
+--
+-- * If `opts.body` is a table and "Content-Type" header contains
+-- `application/json`, `www-form-urlencoded`, or `multipart/form-data`, then it
+-- will automatically encode the body according to the content type.
+--
+-- * If `opts.query` is a table, a query string will be constructed from it and
+-- appended to the request path (assuming none is already present).
+--
+-- * instead of this generic function there are also shortcut functions available
+-- for every method, eg. `client:get`, `client:post`, etc. See `http_client`.
+--
+-- @function http_client:send
+-- @param opts table with options. See [lua-resty-http](https://github.com/pintsized/lua-resty-http)
+function resty_http_proxy_mt:send(opts, is_reopen)
+ local encode_args = require("kong.tools.http").encode_args
+
+ opts = opts or {}
+
+ -- build body
+ local headers = opts.headers or {}
+ local content_type, content_type_name = misc.lookup(headers, "Content-Type")
+ content_type = content_type or ""
+ local t_body_table = type(opts.body) == "table"
+
+ if string.find(content_type, "application/json") and t_body_table then
+ opts.body = cjson.encode(opts.body)
+
+ elseif string.find(content_type, "www-form-urlencoded", nil, true) and t_body_table then
+ opts.body = encode_args(opts.body, true, opts.no_array_indexes)
+
+ elseif string.find(content_type, "multipart/form-data", nil, true) and t_body_table then
+ local form = opts.body
+ local boundary = "8fd84e9444e3946c"
+ local body = ""
+
+ for k, v in pairs(form) do
+ body = body .. "--" .. boundary .. "\r\nContent-Disposition: form-data; name=\"" .. k .. "\"\r\n\r\n" .. tostring(v) .. "\r\n"
+ end
+
+ if body ~= "" then
+ body = body .. "--" .. boundary .. "--\r\n"
+ end
+
+ local clength = misc.lookup(headers, "content-length")
+ if not clength and not opts.dont_add_content_length then
+ headers["content-length"] = #body
+ end
+
+ if not content_type:find("boundary=") then
+ headers[content_type_name] = content_type .. "; boundary=" .. boundary
+ end
+
+ opts.body = body
+ end
+
+ -- build querystring (assumes none is currently in 'opts.path')
+ if type(opts.query) == "table" then
+ local qs = encode_args(opts.query)
+ opts.path = opts.path .. "?" .. qs
+ opts.query = nil
+ end
+
+ if self.options.http_version and self.options.http_version == 2 then
+ local url = self.options.scheme .. "://" .. self.options.host .. ":" .. self.options.port .. opts.path
+ local reqwest_opt = {
+ version = 2,
+ method = opts.method,
+ body = opts.body,
+ headers = opts.headers,
+ tls_verify = false,
+ }
+ local res, err = reqwest.request(url, reqwest_opt)
+ if not res then
+ return nil, err
+ end
+ local headers_mt = {
+ __index = function(t, k)
+ return rawget(t, string.lower(k))
+ end
+ }
+ local res_headers = setmetatable(res.headers, headers_mt)
+ return {
+ status = res.status,
+ headers = res_headers,
+ read_body = function()
+ return res.body, nil
+ end
+ }
+ end
+
+ local res, err = self:request(opts)
+ if res then
+ -- wrap the read_body() so it caches the result and can be called multiple
+ -- times
+ local reader = res.read_body
+ res.read_body = function(self)
+ if not self._cached_body and not self._cached_error then
+ self._cached_body, self._cached_error = reader(self)
+ end
+ return self._cached_body, self._cached_error
+ end
+
+ elseif (err == "closed" or err == "connection reset by peer")
+ and not is_reopen
+ and self.reopen
+ and can_reopen(opts.method)
+ then
+ ngx.log(ngx.INFO, "Re-opening connection to ", self.options.scheme, "://",
+ self.options.host, ":", self.options.port)
+
+ self:_connect()
+ return self:send(opts, true)
+ end
+
+ return res, err
+end
+
+
+--- Open or re-open the client TCP connection
+function resty_http_proxy_mt:_connect()
+ local opts = self.options
+
+ if CONSTANTS.TEST_COVERAGE_MODE == "true" then
+ opts.connect_timeout = CONSTANTS.TEST_COVERAGE_TIMEOUT * 1000
+ opts.send_timeout = CONSTANTS.TEST_COVERAGE_TIMEOUT * 1000
+ opts.read_timeout = CONSTANTS.TEST_COVERAGE_TIMEOUT * 1000
+ end
+
+ if opts.http_version and opts.http_version == 2 then
+ return
+ end
+
+ local _, err = self:connect(opts)
+ if err then
+ error("Could not connect to " ..
+ (opts.host or "unknown") .. ":" .. (opts.port or "unknown") ..
+ ": " .. err)
+ end
+
+ if opts.connect_timeout and
+ opts.send_timeout and
+ opts.read_timeout
+ then
+ self:set_timeouts(opts.connect_timeout, opts.send_timeout, opts.read_timeout)
+ else
+ self:set_timeout(opts.timeout or 10000)
+ end
+end
+
+
+-- Implements http_client:get("path", [options]), as well as post, put, etc.
+-- These methods are equivalent to calling http_client:send, but are shorter
+-- They also come with a built-in assert
+for _, method_name in ipairs({"get", "post", "put", "patch", "delete", "head", "options"}) do
+ resty_http_proxy_mt[method_name] = function(self, path, options)
+ local full_options = kong.table.merge({ method = method_name:upper(), path = path}, options)
+ return assert(self:send(full_options))
+ end
+end
+
+
+--- Creates a http client from options.
+-- Instead of using this client, you'll probably want to use the pre-configured
+-- clients available as `proxy_client`, `admin_client`, etc. because these come
+-- pre-configured and connected to the underlying Kong test instance.
+--
+-- @function http_client_opts
+-- @param options connection and other options
+-- @return http client
+-- @see http_client:send
+-- @see proxy_client
+-- @see proxy_ssl_client
+-- @see admin_client
+-- @see admin_ssl_client
+local function http_client_opts(options)
+ if not options.scheme then
+ options = kong_table.cycle_aware_deep_copy(options)
+ options.scheme = "http"
+ if options.port == 443 then
+ options.scheme = "https"
+ else
+ options.scheme = "http"
+ end
+ end
+
+ local self = setmetatable(assert(http.new()), resty_http_proxy_mt)
+
+ self.options = options
+
+ if options.reopen ~= nil then
+ self.reopen = options.reopen
+ end
+
+ self:_connect()
+
+ return self
+end
+
+
+--- Creates a http client.
+-- Instead of using this client, you'll probably want to use the pre-configured
+-- clients available as `proxy_client`, `admin_client`, etc. because these come
+-- pre-configured and connected to the underlying Kong test instance.
+--
+-- @function http_client
+-- @param host hostname to connect to
+-- @param port port to connect to
+-- @param timeout in seconds
+-- @return http client
+-- @see http_client:send
+-- @see proxy_client
+-- @see proxy_ssl_client
+-- @see admin_client
+-- @see admin_ssl_client
+local function http_client(host, port, timeout)
+ if type(host) == "table" then
+ return http_client_opts(host)
+ end
+
+ if CONSTANTS.TEST_COVERAGE_MODE == "true" then
+ timeout = CONSTANTS.TEST_COVERAGE_TIMEOUT * 1000
+ end
+
+ return http_client_opts({
+ host = host,
+ port = port,
+ timeout = timeout,
+ })
+end
+
+
+--- Returns the proxy port.
+-- @function get_proxy_port
+-- @param ssl (boolean) if `true` returns the ssl port
+-- @param http2 (boolean) if `true` returns the http2 port
+local function get_proxy_port(ssl, http2)
+ if ssl == nil then ssl = false end
+ for _, entry in ipairs(conf.proxy_listeners) do
+ if entry.ssl == ssl and (http2 == nil or entry.http2 == http2) then
+ return entry.port
+ end
+ end
+ error("No proxy port found for ssl=" .. tostring(ssl), 2)
+end
+
+
+--- Returns the proxy ip.
+-- @function get_proxy_ip
+-- @param ssl (boolean) if `true` returns the ssl ip address
+-- @param http2 (boolean) if `true` returns the http2 ip address
+local function get_proxy_ip(ssl, http2)
+ if ssl == nil then ssl = false end
+ for _, entry in ipairs(conf.proxy_listeners) do
+ if entry.ssl == ssl and (http2 == nil or entry.http2 == http2) then
+ return entry.ip
+ end
+ end
+ error("No proxy ip found for ssl=" .. tostring(ssl), 2)
+end
+
+
+--- returns a pre-configured `http_client` for the Kong proxy port.
+-- @function proxy_client
+-- @param timeout (optional, number) the timeout to use
+-- @param forced_port (optional, number) if provided will override the port in
+-- the Kong configuration with this port
+-- @param forced_ip (optional, string) if provided will override the ip in
+-- the Kong configuration with this ip
+-- @param http_version (optional, number) the http version to use
+local function proxy_client(timeout, forced_port, forced_ip, http_version)
+ local proxy_ip = get_proxy_ip(false)
+ local proxy_port = get_proxy_port(false)
+ local opts_http_version
+ if http_version == 2 then
+ opts_http_version = 2
+ proxy_ip = get_proxy_ip(false, true)
+ proxy_port = get_proxy_port(false, true)
+ end
+ assert(proxy_ip, "No http-proxy found in the configuration")
+ return http_client_opts({
+ scheme = "http",
+ host = forced_ip or proxy_ip,
+ port = forced_port or proxy_port,
+ timeout = timeout or 60000,
+ http_version = opts_http_version,
+ })
+end
+
+
+--- returns a pre-configured `http_client` for the Kong SSL proxy port.
+-- @function proxy_ssl_client
+-- @param timeout (optional, number) the timeout to use
+-- @param sni (optional, string) the sni to use
+-- @param http_version (optional, number) the http version to use
+local function proxy_ssl_client(timeout, sni, http_version)
+ local proxy_ip = get_proxy_ip(true, true)
+ local proxy_port = get_proxy_port(true, true)
+ local opts_http_version
+ if http_version == 2 then
+ opts_http_version = 2
+ proxy_ip = get_proxy_ip(true, true)
+ proxy_port = get_proxy_port(true, true)
+ end
+ assert(proxy_ip, "No https-proxy found in the configuration")
+ local client = http_client_opts({
+ scheme = "https",
+ host = proxy_ip,
+ port = proxy_port,
+ timeout = timeout or 60000,
+ ssl_verify = false,
+ ssl_server_name = sni,
+ http_version = opts_http_version,
+ })
+ return client
+end
+
+
+--- returns a pre-configured `http_client` for the Kong admin port.
+-- @function admin_client
+-- @param timeout (optional, number) the timeout to use
+-- @param forced_port (optional, number) if provided will override the port in
+-- the Kong configuration with this port
+local function admin_client(timeout, forced_port)
+ local admin_ip, admin_port
+ for _, entry in ipairs(conf.admin_listeners) do
+ if entry.ssl == false then
+ admin_ip = entry.ip
+ admin_port = entry.port
+ end
+ end
+ assert(admin_ip, "No http-admin found in the configuration")
+ return http_client_opts({
+ scheme = "http",
+ host = admin_ip,
+ port = forced_port or admin_port,
+ timeout = timeout or 60000,
+ reopen = true,
+ })
+end
+
+--- returns a pre-configured `http_client` for the Kong admin SSL port.
+-- @function admin_ssl_client
+-- @param timeout (optional, number) the timeout to use
+local function admin_ssl_client(timeout)
+ if CONSTANTS.TEST_COVERAGE_MODE == "true" then
+ timeout = CONSTANTS.TEST_COVERAGE_TIMEOUT * 1000
+ end
+
+ local admin_ip, admin_port
+ for _, entry in ipairs(conf.proxy_listeners) do
+ if entry.ssl == true then
+ admin_ip = entry.ip
+ admin_port = entry.port
+ end
+ end
+ assert(admin_ip, "No https-admin found in the configuration")
+ local client = http_client_opts({
+ scheme = "https",
+ host = admin_ip,
+ port = admin_port,
+ timeout = timeout or 60000,
+ reopen = true,
+ })
+ return client
+end
+
+--- returns a pre-configured `http_client` for the Kong Admin GUI.
+-- @function admin_gui_client
+-- @tparam[opt=60000] number timeout the timeout to use
+-- @tparam[opt] number forced_port if provided will override the port in
+-- the Kong configuration with this port
+-- @return http-client, see `spec.helpers.http_client`.
+local function admin_gui_client(timeout, forced_port)
+ local admin_ip = "127.0.0.1"
+ local admin_port
+ for _, entry in ipairs(conf.admin_gui_listeners) do
+ if entry.ssl == false then
+ admin_ip = entry.ip
+ admin_port = entry.port
+ end
+ end
+ admin_port = forced_port or admin_port
+ assert(admin_port, "No http-admin found in the configuration")
+ return http_client_opts({
+ scheme = "http",
+ host = admin_ip,
+ port = admin_port,
+ timeout = timeout or 60000,
+ reopen = true,
+ })
+end
+
+--- returns a pre-configured `http_client` for the Kong admin GUI SSL port.
+-- @function admin_gui_ssl_client
+-- @tparam[opt=60000] number timeout the timeout to use
+-- @tparam[opt] number forced_port if provided will override the port in
+-- the Kong configuration with this port
+-- @return http-client, see `spec.helpers.http_client`.
+local function admin_gui_ssl_client(timeout, forced_port)
+ local admin_ip = "127.0.0.1"
+ local admin_port
+ for _, entry in ipairs(conf.admin_gui_listeners) do
+ if entry.ssl == true then
+ admin_ip = entry.ip
+ admin_port = entry.port
+ end
+ end
+ admin_port = forced_port or admin_port
+ assert(admin_port, "No https-admin found in the configuration")
+ return http_client_opts({
+ scheme = "https",
+ host = admin_ip,
+ port = admin_port,
+ timeout = timeout or 60000,
+ reopen = true,
+ })
+end
+
+
+----------------
+-- HTTP2 and GRPC clients
+-- @section Shell-helpers
+
+
+-- Generate grpcurl flags from a table of `flag-value`. If `value` is not a
+-- string, value is ignored and `flag` is passed as is.
+local function gen_grpcurl_opts(opts_t)
+ local opts_l = {}
+
+ for opt, val in pairs(opts_t) do
+ if val ~= false then
+ opts_l[#opts_l + 1] = opt .. " " .. (type(val) == "string" and val or "")
+ end
+ end
+
+ return table.concat(opts_l, " ")
+end
+
+
+--- Creates an HTTP/2 client using golang's http2 package.
+--- Sets `KONG_TEST_DEBUG_HTTP2=1` env var to print debug messages.
+-- @function http2_client
+-- @param host hostname to connect to
+-- @param port port to connect to
+local function http2_client(host, port, tls)
+ local port = assert(port)
+ tls = tls or false
+
+ -- Note: set `GODEBUG=http2debug=1` is helpful if you are debugging this go program
+ local tool_path = "bin/h2client"
+ local http2_debug
+ -- note: set env var "KONG_TEST_DEBUG_HTTP2" !! the "_TEST" will be dropped
+ if os.getenv("KONG_DEBUG_HTTP2") then
+ http2_debug = true
+ tool_path = "GODEBUG=http2debug=1 bin/h2client"
+ end
+
+
+ local meta = {}
+ meta.__call = function(_, opts)
+ local headers = opts and opts.headers
+ local timeout = opts and opts.timeout
+ local body = opts and opts.body
+ local path = opts and opts.path or ""
+ local http1 = opts and opts.http_version == "HTTP/1.1"
+
+ local url = (tls and "https" or "http") .. "://" .. host .. ":" .. port .. path
+
+ local cmd = string.format("%s -url %s -skip-verify", tool_path, url)
+
+ if headers then
+ local h = {}
+ for k, v in pairs(headers) do
+ table.insert(h, string.format("%s=%s", k, v))
+ end
+ cmd = cmd .. " -headers " .. table.concat(h, ",")
+ end
+
+ if timeout then
+ cmd = cmd .. " -timeout " .. timeout
+ end
+
+ if http1 then
+ cmd = cmd .. " -http1"
+ end
+
+ --shell.run does not support '<'
+ if body then
+ cmd = cmd .. " -post"
+ end
+
+ if http2_debug then
+ print("HTTP/2 cmd:\n" .. cmd)
+ end
+
+ --100MB for retrieving stdout & stderr
+ local ok, stdout, stderr = shell.run(cmd, body, 0, 1024*1024*100)
+ assert(ok, stderr)
+
+ if http2_debug then
+ print("HTTP/2 debug:\n")
+ print(stderr)
+ end
+
+ local stdout_decoded = cjson.decode(stdout)
+ if not stdout_decoded then
+ error("Failed to decode h2client output: " .. stdout)
+ end
+
+ local headers = stdout_decoded.headers
+ headers.get = function(_, key)
+ if string.sub(key, 1, 1) == ":" then
+ key = string.sub(key, 2)
+ end
+ return headers[key]
+ end
+ setmetatable(headers, {
+ __index = function(headers, key)
+ for k, v in pairs(headers) do
+ if key:lower() == k:lower() then
+ return v
+ end
+ end
+ end
+ })
+ return stdout_decoded.body, headers
+ end
+
+ return setmetatable({}, meta)
+end
+
+
+--- returns a pre-configured cleartext `http2_client` for the Kong proxy port.
+-- @function proxy_client_h2c
+-- @return http2 client
+local function proxy_client_h2c()
+ local proxy_ip = get_proxy_ip(false, true)
+ local proxy_port = get_proxy_port(false, true)
+ assert(proxy_ip, "No http-proxy found in the configuration")
+ return http2_client(proxy_ip, proxy_port)
+end
+
+
+--- returns a pre-configured TLS `http2_client` for the Kong SSL proxy port.
+-- @function proxy_client_h2
+-- @return http2 client
+local function proxy_client_h2()
+ local proxy_ip = get_proxy_ip(true, true)
+ local proxy_port = get_proxy_port(true, true)
+ assert(proxy_ip, "No https-proxy found in the configuration")
+ return http2_client(proxy_ip, proxy_port, true)
+end
+
+
+--- Creates a gRPC client, based on the grpcurl CLI.
+-- @function grpc_client
+-- @param host hostname to connect to
+-- @param port port to connect to
+-- @param opts table with options supported by grpcurl
+-- @return grpc client
+local function grpc_client(host, port, opts)
+ local host = assert(host)
+ local port = assert(tostring(port))
+
+ opts = opts or {}
+ if not opts["-proto"] then
+ opts["-proto"] = CONSTANTS.MOCK_GRPC_UPSTREAM_PROTO_PATH
+ end
+
+ return setmetatable({
+ opts = opts,
+ cmd_template = string.format("bin/grpcurl %%s %s:%s %%s", host, port)
+
+ }, {
+ __call = function(t, args)
+ local service = assert(args.service)
+ local body = args.body
+ local arg_opts = args.opts or {}
+
+ local t_body = type(body)
+ if t_body ~= "nil" then
+ if t_body == "table" then
+ body = cjson.encode(body)
+ end
+
+ arg_opts["-d"] = string.format("'%s'", body)
+ end
+
+ local cmd_opts = gen_grpcurl_opts(pl_tablex.merge(t.opts, arg_opts, true))
+ local cmd = string.format(t.cmd_template, cmd_opts, service)
+ local ok, _, out, err = shell.exec(cmd, true)
+
+ if ok then
+ return ok, ("%s%s"):format(out or "", err or "")
+ else
+ return nil, ("%s%s"):format(out or "", err or "")
+ end
+ end
+ })
+end
+
+
+--- returns a pre-configured `grpc_client` for the Kong proxy port.
+-- @function proxy_client_grpc
+-- @param host hostname to connect to
+-- @param port port to connect to
+-- @return grpc client
+local function proxy_client_grpc(host, port)
+ local proxy_ip = host or get_proxy_ip(false, true)
+ local proxy_port = port or get_proxy_port(false, true)
+ assert(proxy_ip, "No http-proxy found in the configuration")
+ return grpc_client(proxy_ip, proxy_port, {["-plaintext"] = true})
+end
+
+
+--- returns a pre-configured `grpc_client` for the Kong SSL proxy port.
+-- @function proxy_client_grpcs
+-- @param host hostname to connect to
+-- @param port port to connect to
+-- @return grpc client
+local function proxy_client_grpcs(host, port)
+ local proxy_ip = host or get_proxy_ip(true, true)
+ local proxy_port = port or get_proxy_port(true, true)
+ assert(proxy_ip, "No https-proxy found in the configuration")
+ return grpc_client(proxy_ip, proxy_port, {["-insecure"] = true})
+end
+
+
+---
+-- Reconfiguration completion detection helpers
+--
+
+local MAX_RETRY_TIME = 10
+
+--- Set up admin client and proxy client to so that interactions with the proxy client
+-- wait for preceding admin API client changes to have completed.
+
+-- @function make_synchronized_clients
+-- @param clients table with admin_client and proxy_client fields (both optional)
+-- @return admin_client, proxy_client
+
+local function make_synchronized_clients(clients)
+ clients = clients or {}
+ local synchronized_proxy_client = clients.proxy_client or proxy_client()
+ local synchronized_admin_client = clients.admin_client or admin_client()
+
+ -- Install the reconfiguration completion detection plugin
+ local res = synchronized_admin_client:post("/plugins", {
+ headers = { ["Content-Type"] = "application/json" },
+ body = {
+ name = "reconfiguration-completion",
+ config = {
+ version = "0",
+ }
+ },
+ })
+ local body = luassert.res_status(201, res)
+ local plugin = cjson.decode(body)
+ local plugin_id = plugin.id
+
+ -- Wait until the plugin is active on the proxy path, indicated by the presence of the X-Kong-Reconfiguration-Status header
+ luassert.eventually(function()
+ res = synchronized_proxy_client:get("/non-existent-proxy-path")
+ luassert.res_status(404, res)
+ luassert.equals("unknown", res.headers['x-kong-reconfiguration-status'])
+ end)
+ .has_no_error()
+
+ -- Save the original request functions for the admin and proxy client
+ local proxy_request = synchronized_proxy_client.request
+ local admin_request = synchronized_admin_client.request
+
+ local current_version = 0 -- incremented whenever a configuration change is made through the admin API
+ local last_configured_version = 0 -- current version of the reconfiguration-completion plugin's configuration
+
+ -- Wrap the admin API client request
+ function synchronized_admin_client.request(client, opts)
+ -- Whenever the configuration is changed through the admin API, increment the current version number
+ if opts.method == "POST" or opts.method == "PUT" or opts.method == "PATCH" or opts.method == "DELETE" then
+ current_version = current_version + 1
+ end
+ return admin_request(client, opts)
+ end
+
+ function synchronized_admin_client.synchronize_sibling(self, sibling)
+ sibling.request = self.request
+ end
+
+ -- Wrap the proxy client request
+ function synchronized_proxy_client.request(client, opts)
+ -- If the configuration has been changed through the admin API, update the version number in the
+ -- reconfiguration-completion plugin.
+ if current_version > last_configured_version then
+ last_configured_version = current_version
+ res = admin_request(synchronized_admin_client, {
+ method = "PATCH",
+ path = "/plugins/" .. plugin_id,
+ headers = { ["Content-Type"] = "application/json" },
+ body = cjson.encode({
+ config = {
+ version = tostring(current_version),
+ }
+ }),
+ })
+ luassert.res_status(200, res)
+ end
+
+ -- Retry the request until the reconfiguration is complete and the reconfiguration completion
+ -- plugin on the database has been updated to the current version.
+ if not opts.headers then
+ opts.headers = {}
+ end
+ opts.headers["If-Kong-Configuration-Version"] = tostring(current_version)
+ local retry_until = ngx.now() + MAX_RETRY_TIME
+ local err
+ :: retry ::
+ res, err = proxy_request(client, opts)
+ if err then
+ return res, err
+ end
+ if res.headers['x-kong-reconfiguration-status'] ~= "complete" then
+ res:read_body()
+ ngx.sleep(res.headers['retry-after'] or 1)
+ if ngx.now() < retry_until then
+ goto retry
+ end
+ return nil, "reconfiguration did not occur within " .. MAX_RETRY_TIME .. " seconds"
+ end
+ return res, err
+ end
+
+ function synchronized_proxy_client.synchronize_sibling(self, sibling)
+ sibling.request = self.request
+ end
+
+ return synchronized_proxy_client, synchronized_admin_client
+end
+
+
+--- Simulate a Hybrid mode DP and connect to the CP specified in `opts`.
+-- @function clustering_client
+-- @param opts Options to use, the `host`, `port`, `cert` and `cert_key` fields
+-- are required.
+-- Other fields that can be overwritten are:
+-- `node_hostname`, `node_id`, `node_version`, `node_plugins_list`. If absent,
+-- they are automatically filled.
+-- @return msg if handshake succeeded and initial message received from CP or nil, err
+local function clustering_client(opts)
+ assert(opts.host)
+ assert(opts.port)
+ assert(opts.cert)
+ assert(opts.cert_key)
+
+ local pl_file = require("pl.file")
+ local ssl = require("ngx.ssl")
+ local inflate_gzip = require("kong.tools.gzip").inflate_gzip
+ local ws_client = require("resty.websocket.client")
+ local DB = require("spec.internal.db")
+
+ local c = assert(ws_client:new())
+ local uri = "wss://" .. opts.host .. ":" .. opts.port ..
+ "/v1/outlet?node_id=" .. (opts.node_id or uuid()) ..
+ "&node_hostname=" .. (opts.node_hostname or kong.node.get_hostname()) ..
+ "&node_version=" .. (opts.node_version or CONSTANTS.KONG_VERSION)
+
+ local conn_opts = {
+ ssl_verify = false, -- needed for busted tests as CP certs are not trusted by the CLI
+ client_cert = assert(ssl.parse_pem_cert(assert(pl_file.read(opts.cert)))),
+ client_priv_key = assert(ssl.parse_pem_priv_key(assert(pl_file.read(opts.cert_key)))),
+ server_name = opts.server_name or "kong_clustering",
+ }
+
+ local res, err = c:connect(uri, conn_opts)
+ if not res then
+ return nil, err
+ end
+ local payload = assert(cjson.encode({ type = "basic_info",
+ plugins = opts.node_plugins_list or
+ DB.get_plugins_list(),
+ labels = opts.node_labels,
+ process_conf = opts.node_process_conf,
+ }))
+ assert(c:send_binary(payload))
+
+ assert(c:send_ping(string.rep("0", 32)))
+
+ local data, typ, err
+ data, typ, err = c:recv_frame()
+ c:close()
+
+ if typ == "binary" then
+ local odata = assert(inflate_gzip(data))
+ local msg = assert(cjson.decode(odata))
+ return msg
+
+ elseif typ == "pong" then
+ return "PONG"
+ end
+
+ return nil, "unknown frame from CP: " .. (typ or err)
+end
+
+
+return {
+ get_proxy_ip = get_proxy_ip,
+ get_proxy_port = get_proxy_port,
+
+ http_client = http_client,
+ grpc_client = grpc_client,
+ http2_client = http2_client,
+
+ proxy_client = proxy_client,
+ proxy_ssl_client = proxy_ssl_client,
+ proxy_client_grpc = proxy_client_grpc,
+ proxy_client_grpcs = proxy_client_grpcs,
+ proxy_client_h2c = proxy_client_h2c,
+ proxy_client_h2 = proxy_client_h2,
+
+ admin_client = admin_client,
+ admin_ssl_client = admin_ssl_client,
+
+ admin_gui_client = admin_gui_client,
+ admin_gui_ssl_client = admin_gui_ssl_client,
+
+ make_synchronized_clients = make_synchronized_clients,
+
+ clustering_client = clustering_client,
+}
+
diff --git a/kong-versions/3.9.0.0/kong/spec/internal/cmd.lua b/kong-versions/3.9.0.0/kong/spec/internal/cmd.lua
new file mode 100644
index 00000000..e0b9952c
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/internal/cmd.lua
@@ -0,0 +1,484 @@
+-- This software is copyright Kong Inc. and its licensors.
+-- Use of the software is subject to the agreement between your organization
+-- and Kong Inc. If there is no such agreement, use is governed by and
+-- subject to the terms of the Kong Master Software License Agreement found
+-- at https://konghq.com/enterprisesoftwarelicense/.
+-- [ END OF LICENSE 0867164ffc95e54f04670b5169c09574bdbd9bba ]
+
+------------------------------------------------------------------
+-- Collection of utilities to help testing Kong features and plugins.
+--
+-- @copyright Copyright 2016-2022 Kong Inc. All rights reserved.
+-- @license [Apache 2.0](https://opensource.org/licenses/Apache-2.0)
+-- @module spec.helpers
+
+
+local lfs = require("lfs")
+local version = require("version")
+local pl_dir = require("pl.dir")
+local pl_path = require("pl.path")
+local pl_utils = require("pl.utils")
+local constants = require("kong.constants")
+local conf_loader = require("kong.conf_loader")
+local kong_table = require("kong.tools.table")
+local kill = require("kong.cmd.utils.kill")
+local prefix_handler = require("kong.cmd.utils.prefix_handler")
+
+
+local CONSTANTS = require("spec.internal.constants")
+local conf = require("spec.internal.conf")
+local shell = require("spec.internal.shell")
+local DB = require("spec.internal.db")
+local pid = require("spec.internal.pid")
+local dns_mock = require("spec.internal.dns")
+
+
+-- initialized in start_kong()
+local config_yml
+
+
+--- Return the actual Kong version the tests are running against.
+-- See [version.lua](https://github.com/kong/version.lua) for the format. This
+-- is mostly useful for testing plugins that should work with multiple Kong versions.
+-- @function get_version
+-- @return a `version` object
+-- @usage
+-- local version = require 'version'
+-- if helpers.get_version() < version("0.15.0") then
+-- -- do something
+-- end
+local function get_version()
+ return version(select(3, assert(shell.kong_exec("version"))))
+end
+
+
+local function build_go_plugins(path)
+ if pl_path.exists(pl_path.join(path, "go.mod")) then
+ local ok, _, stderr = shell.run(string.format(
+ "cd %s; go mod tidy; go mod download", path), nil, 0)
+ assert(ok, stderr)
+ end
+ for _, go_source in ipairs(pl_dir.getfiles(path, "*.go")) do
+ local ok, _, stderr = shell.run(string.format(
+ "cd %s; go build %s",
+ path, pl_path.basename(go_source)
+ ), nil, 0)
+ assert(ok, stderr)
+ end
+end
+
+
+--- Prepares the Kong environment.
+-- Creates the working directory if it does not exist.
+-- @param prefix (optional) path to the working directory, if omitted the test
+-- configuration will be used
+-- @function prepare_prefix
+local function prepare_prefix(prefix)
+ return pl_dir.makepath(prefix or conf.prefix)
+end
+
+
+--- Cleans the Kong environment.
+-- Deletes the working directory if it exists.
+-- @param prefix (optional) path to the working directory, if omitted the test
+-- configuration will be used
+-- @function clean_prefix
+local function clean_prefix(prefix)
+
+ -- like pl_dir.rmtree, but ignore mount points
+ local function rmtree(fullpath)
+ if pl_path.islink(fullpath) then return false,'will not follow symlink' end
+ for root,dirs,files in pl_dir.walk(fullpath,true) do
+ if pl_path.islink(root) then
+ -- sub dir is a link, remove link, do not follow
+ local res, err = os.remove(root)
+ if not res then
+ return nil, err .. ": " .. root
+ end
+
+ else
+ for i,f in ipairs(files) do
+ f = pl_path.join(root,f)
+ local res, err = os.remove(f)
+ if not res then
+ return nil,err .. ": " .. f
+ end
+ end
+
+ local res, err = pl_path.rmdir(root)
+ -- skip errors when trying to remove mount points
+ if not res and shell.run("findmnt " .. root .. " 2>&1 >/dev/null", nil, 0) == 0 then
+ return nil, err .. ": " .. root
+ end
+ end
+ end
+ return true
+ end
+
+ prefix = prefix or conf.prefix
+ if pl_path.exists(prefix) then
+ local _, err = rmtree(prefix)
+ if err then
+ error(err)
+ end
+ end
+end
+
+
+local function render_fixtures(conf, env, prefix, fixtures)
+
+ if fixtures and (fixtures.http_mock or fixtures.stream_mock) then
+ -- prepare the prefix so we get the full config in the
+ -- hidden `.kong_env` file, including test specified env vars etc
+ assert(shell.kong_exec("prepare --conf " .. conf, env))
+ local render_config = assert(conf_loader(prefix .. "/.kong_env", nil,
+ { from_kong_env = true }))
+
+ for _, mocktype in ipairs { "http_mock", "stream_mock" } do
+
+ for filename, contents in pairs(fixtures[mocktype] or {}) do
+ -- render the file using the full configuration
+ contents = assert(prefix_handler.compile_conf(render_config, contents))
+
+ -- write file to prefix
+ filename = prefix .. "/" .. filename .. "." .. mocktype
+ assert(pl_utils.writefile(filename, contents))
+ end
+ end
+ end
+
+ if fixtures and fixtures.dns_mock then
+ -- write the mock records to the prefix
+ assert(getmetatable(fixtures.dns_mock) == dns_mock,
+ "expected dns_mock to be of a helpers.dns_mock class")
+ assert(pl_utils.writefile(prefix .. "/dns_mock_records.json",
+ tostring(fixtures.dns_mock)))
+
+ -- add the mock resolver to the path to ensure the records are loaded
+ if env.lua_package_path then
+ env.lua_package_path = CONSTANTS.DNS_MOCK_LUA_PATH .. ";" .. env.lua_package_path
+ else
+ env.lua_package_path = CONSTANTS.DNS_MOCK_LUA_PATH
+ end
+ else
+ -- remove any old mocks if they exist
+ os.remove(prefix .. "/dns_mock_records.json")
+ end
+
+ return true
+end
+
+
+--- Return the actual configuration running at the given prefix.
+-- It may differ from the default, as it may have been modified
+-- by the `env` table given to start_kong.
+-- @function get_running_conf
+-- @param prefix (optional) The prefix path where the kong instance is running,
+-- defaults to the prefix in the default config.
+-- @return The conf table of the running instance, or nil + error.
+local function get_running_conf(prefix)
+ local default_conf = conf_loader(nil, {prefix = prefix or conf.prefix})
+ return conf_loader.load_config_file(default_conf.kong_env)
+end
+
+
+--- Clears the logfile. Will overwrite the logfile with an empty file.
+-- @function clean_logfile
+-- @param logfile (optional) filename to clear, defaults to the current
+-- error-log file
+-- @return nothing
+-- @see line
+local function clean_logfile(logfile)
+ logfile = logfile or (get_running_conf() or conf).nginx_err_logs
+
+ assert(type(logfile) == "string", "'logfile' must be a string")
+
+ local fh, err, errno = io.open(logfile, "w+")
+
+ if fh then
+ fh:close()
+ return
+
+ elseif errno == 2 then -- ENOENT
+ return
+ end
+
+ error("failed to truncate logfile: " .. tostring(err))
+end
+
+
+--- Start the Kong instance to test against.
+-- The fixtures passed to this function can be 3 types:
+--
+-- * DNS mocks
+--
+-- * Nginx server blocks to be inserted in the http module
+--
+-- * Nginx server blocks to be inserted in the stream module
+-- @function start_kong
+-- @param env table with Kong configuration parameters (and values)
+-- @param tables list of database tables to truncate before starting
+-- @param preserve_prefix (boolean) if truthy, the prefix will not be cleaned
+-- before starting
+-- @param fixtures tables with fixtures, dns, http and stream mocks.
+-- @return return values from `execute`
+-- @usage
+-- -- example mocks
+-- -- Create a new DNS mock and add some DNS records
+-- local fixtures = {
+-- http_mock = {},
+-- stream_mock = {},
+-- dns_mock = helpers.dns_mock.new()
+-- }
+--
+-- **DEPRECATED**: http_mock fixture is deprecated. Please use `spec.helpers.http_mock` instead.
+--
+-- fixtures.dns_mock:A {
+-- name = "a.my.srv.test.com",
+-- address = "127.0.0.1",
+-- }
+--
+-- -- The blocks below will be rendered by the Kong template renderer, like other
+-- -- custom Kong templates. Hence the `${{xxxx}}` values.
+-- -- Multiple mocks can be added each under their own filename ("my_server_block" below)
+-- fixtures.http_mock.my_server_block = [[
+-- server {
+-- server_name my_server;
+-- listen 10001 ssl;
+--
+-- ssl_certificate ${{SSL_CERT}};
+-- ssl_certificate_key ${{SSL_CERT_KEY}};
+-- ssl_protocols TLSv1.2 TLSv1.3;
+--
+-- location ~ "/echobody" {
+-- content_by_lua_block {
+-- ngx.req.read_body()
+-- local echo = ngx.req.get_body_data()
+-- ngx.status = status
+-- ngx.header["Content-Length"] = #echo + 1
+-- ngx.say(echo)
+-- }
+-- }
+-- }
+-- ]]
+--
+-- fixtures.stream_mock.my_server_block = [[
+-- server {
+-- -- insert stream server config here
+-- }
+-- ]]
+--
+-- assert(helpers.start_kong( {database = "postgres"}, nil, nil, fixtures))
+local function start_kong(env, tables, preserve_prefix, fixtures)
+ if tables ~= nil and type(tables) ~= "table" then
+ error("arg #2 must be a list of tables to truncate")
+ end
+ env = env or {}
+ local prefix = env.prefix or conf.prefix
+
+ -- go plugins are enabled
+ -- compile fixture go plugins if any setting mentions it
+ for _,v in pairs(env) do
+ if type(v) == "string" and v:find(CONSTANTS.EXTERNAL_PLUGINS_PATH .. "/go") then
+ build_go_plugins(CONSTANTS.EXTERNAL_PLUGINS_PATH .. "/go")
+ break
+ end
+ end
+
+ -- note: set env var "KONG_TEST_DONT_CLEAN" !! the "_TEST" will be dropped
+ if not (preserve_prefix or os.getenv("KONG_DONT_CLEAN")) then
+ clean_prefix(prefix)
+ end
+
+ local ok, err = prepare_prefix(prefix)
+ if not ok then return nil, err end
+
+ DB.truncate_tables(DB.db, tables)
+
+ local nginx_conf = ""
+ local nginx_conf_flags = { "test" }
+ if env.nginx_conf then
+ nginx_conf = " --nginx-conf " .. env.nginx_conf
+ end
+
+ if CONSTANTS.TEST_COVERAGE_MODE == "true" then
+ -- render `coverage` blocks in the templates
+ nginx_conf_flags[#nginx_conf_flags + 1] = 'coverage'
+ end
+
+ if next(nginx_conf_flags) then
+ nginx_conf_flags = " --nginx-conf-flags " .. table.concat(nginx_conf_flags, ",")
+ else
+ nginx_conf_flags = ""
+ end
+
+ local dcbp = DB.get_dcbp()
+ if dcbp and not env.declarative_config and not env.declarative_config_string then
+ if not config_yml then
+ config_yml = prefix .. "/config.yml"
+ local cfg = dcbp.done()
+ local declarative = require "kong.db.declarative"
+ local ok, err = declarative.to_yaml_file(cfg, config_yml)
+ if not ok then
+ return nil, err
+ end
+ end
+ env = kong_table.cycle_aware_deep_copy(env)
+ env.declarative_config = config_yml
+ end
+
+ assert(render_fixtures(CONSTANTS.TEST_CONF_PATH .. nginx_conf, env, prefix, fixtures))
+ return shell.kong_exec("start --conf " .. CONSTANTS.TEST_CONF_PATH .. nginx_conf .. nginx_conf_flags, env)
+end
+
+
+-- Cleanup after kong test instance, should be called if start_kong was invoked with the nowait flag
+-- @function cleanup_kong
+-- @param prefix (optional) the prefix where the test instance runs, defaults to the test configuration.
+-- @param preserve_prefix (boolean) if truthy, the prefix will not be deleted after stopping
+-- @param preserve_dc ???
+local function cleanup_kong(prefix, preserve_prefix, preserve_dc)
+ -- remove socket files to ensure `pl.dir.rmtree()` ok
+ prefix = prefix or conf.prefix
+ local socket_path = pl_path.join(prefix, constants.SOCKET_DIRECTORY)
+ for child in lfs.dir(socket_path) do
+ local path = pl_path.join(socket_path, child)
+ if lfs.attributes(path, "mode") == "socket" then
+ os.remove(path)
+ end
+ end
+
+ -- note: set env var "KONG_TEST_DONT_CLEAN" !! the "_TEST" will be dropped
+ if not (preserve_prefix or os.getenv("KONG_DONT_CLEAN")) then
+ clean_prefix(prefix)
+ end
+
+ if not preserve_dc then
+ config_yml = nil
+ end
+ ngx.ctx.workspace = nil
+end
+
+
+-- Stop the Kong test instance.
+-- @function stop_kong
+-- @param prefix (optional) the prefix where the test instance runs, defaults to the test configuration.
+-- @param preserve_prefix (boolean) if truthy, the prefix will not be deleted after stopping
+-- @param preserve_dc ???
+-- @param signal (optional string) signal name to send to kong, defaults to TERM
+-- @param nowait (optional) if truthy, don't wait for kong to terminate. caller needs to wait and call cleanup_kong
+-- @return true or nil+err
+local function stop_kong(prefix, preserve_prefix, preserve_dc, signal, nowait)
+ prefix = prefix or conf.prefix
+ signal = signal or "TERM"
+
+ local running_conf, err = get_running_conf(prefix)
+ if not running_conf then
+ return nil, err
+ end
+
+ local id, err = pid.get_pid_from_file(running_conf.nginx_pid)
+ if not id then
+ return nil, err
+ end
+
+ local ok, _, err = shell.run(string.format("kill -%s %d", signal, id), nil, 0)
+ if not ok then
+ return nil, err
+ end
+
+ if nowait then
+ return running_conf.nginx_pid
+ end
+
+ pid.wait_pid(running_conf.nginx_pid)
+
+ cleanup_kong(prefix, preserve_prefix, preserve_dc)
+
+ return true
+end
+
+
+--- Restart Kong. Reusing declarative config when using `database=off`.
+-- @function restart_kong
+-- @param env see `start_kong`
+-- @param tables see `start_kong`
+-- @param fixtures see `start_kong`
+-- @return true or nil+err
+local function restart_kong(env, tables, fixtures)
+ stop_kong(env.prefix, true, true)
+ return start_kong(env, tables, true, fixtures)
+end
+
+
+-- Only use in CLI tests from spec/02-integration/01-cmd
+local function kill_all(prefix, timeout)
+ local running_conf = get_running_conf(prefix)
+ if not running_conf then return end
+
+ -- kill kong_tests.conf service
+ local pid_path = running_conf.nginx_pid
+ if pl_path.exists(pid_path) then
+ kill.kill(pid_path, "-TERM")
+ pid.wait_pid(pid_path, timeout)
+ end
+end
+
+
+local function signal(prefix, signal, pid_path)
+ if not pid_path then
+ local running_conf = get_running_conf(prefix)
+ if not running_conf then
+ error("no config file found at prefix: " .. prefix)
+ end
+
+ pid_path = running_conf.nginx_pid
+ end
+
+ return kill.kill(pid_path, signal)
+end
+
+
+-- send signal to all Nginx workers, not including the master
+local function signal_workers(prefix, signal, pid_path)
+ if not pid_path then
+ local running_conf = get_running_conf(prefix)
+ if not running_conf then
+ error("no config file found at prefix: " .. prefix)
+ end
+
+ pid_path = running_conf.nginx_pid
+ end
+
+ local cmd = string.format("pkill %s -P `cat %s`", signal, pid_path)
+ local _, _, _, _, code = shell.run(cmd)
+
+ if not pid.pid_dead(pid_path) then
+ return false
+ end
+
+ return code
+end
+
+
+return {
+ get_version = get_version,
+
+ start_kong = start_kong,
+ cleanup_kong = cleanup_kong,
+ stop_kong = stop_kong,
+ restart_kong = restart_kong,
+
+ prepare_prefix = prepare_prefix,
+ clean_prefix = clean_prefix,
+
+ get_running_conf = get_running_conf,
+ clean_logfile = clean_logfile,
+
+ kill_all = kill_all,
+ signal = signal,
+ signal_workers = signal_workers,
+
+ build_go_plugins = build_go_plugins,
+}
+
diff --git a/kong-versions/3.9.0.0/kong/spec/internal/conf.lua b/kong-versions/3.9.0.0/kong/spec/internal/conf.lua
new file mode 100644
index 00000000..f64fff47
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/internal/conf.lua
@@ -0,0 +1,15 @@
+-- This software is copyright Kong Inc. and its licensors.
+-- Use of the software is subject to the agreement between your organization
+-- and Kong Inc. If there is no such agreement, use is governed by and
+-- subject to the terms of the Kong Master Software License Agreement found
+-- at https://konghq.com/enterprisesoftwarelicense/.
+-- [ END OF LICENSE 0867164ffc95e54f04670b5169c09574bdbd9bba ]
+
+local CONSTANTS = require("spec.internal.constants")
+local conf_loader = require("kong.conf_loader")
+
+
+local conf = assert(conf_loader(CONSTANTS.TEST_CONF_PATH))
+
+
+return conf
diff --git a/kong-versions/3.9.0.0/kong/spec/internal/constants.lua b/kong-versions/3.9.0.0/kong/spec/internal/constants.lua
new file mode 100644
index 00000000..b37fc65d
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/internal/constants.lua
@@ -0,0 +1,56 @@
+-- This software is copyright Kong Inc. and its licensors.
+-- Use of the software is subject to the agreement between your organization
+-- and Kong Inc. If there is no such agreement, use is governed by and
+-- subject to the terms of the Kong Master Software License Agreement found
+-- at https://konghq.com/enterprisesoftwarelicense/.
+-- [ END OF LICENSE 0867164ffc95e54f04670b5169c09574bdbd9bba ]
+
+-- contants used by helpers.lua
+local CONSTANTS = {
+ BIN_PATH = "bin/kong",
+ TEST_CONF_PATH = os.getenv("KONG_SPEC_TEST_CONF_PATH") or "spec/kong_tests.conf",
+ CUSTOM_PLUGIN_PATH = "./spec/fixtures/custom_plugins/?.lua",
+
+ -- XXX EE custom plugins for enterprise tests
+ CUSTOM_EE_PLUGIN_PATH = "./spec-ee/fixtures/custom_plugins/?.lua;./spec-ee/fixtures/custom_plugins/?/init.lua;./?/init.lua",
+
+ CUSTOM_VAULT_PATH = "./spec/fixtures/custom_vaults/?.lua;./spec/fixtures/custom_vaults/?/init.lua",
+ DNS_MOCK_LUA_PATH = "./spec/fixtures/mocks/lua-resty-dns/?.lua",
+ EXTERNAL_PLUGINS_PATH = "./spec/fixtures/external_plugins",
+ GRPC_TARGET_SRC_PATH = "./spec/fixtures/grpc/target/",
+ MOCK_UPSTREAM_PROTOCOL = "http",
+ MOCK_UPSTREAM_SSL_PROTOCOL = "https",
+ MOCK_UPSTREAM_HOST = "127.0.0.1",
+ MOCK_UPSTREAM_HOSTNAME = "localhost",
+ MOCK_UPSTREAM_PORT = 15555,
+ MOCK_UPSTREAM_SSL_PORT = 15556,
+ MOCK_UPSTREAM_STREAM_PORT = 15557,
+ MOCK_UPSTREAM_STREAM_SSL_PORT = 15558,
+ GRPCBIN_HOST = os.getenv("KONG_SPEC_TEST_GRPCBIN_HOST") or "localhost",
+ GRPCBIN_PORT = tonumber(os.getenv("KONG_SPEC_TEST_GRPCBIN_PORT")) or 9000,
+ GRPCBIN_SSL_PORT = tonumber(os.getenv("KONG_SPEC_TEST_GRPCBIN_SSL_PORT")) or 9001,
+ MOCK_GRPC_UPSTREAM_PROTO_PATH = "./spec/fixtures/grpc/hello.proto",
+ ZIPKIN_HOST = os.getenv("KONG_SPEC_TEST_ZIPKIN_HOST") or "localhost",
+ ZIPKIN_PORT = tonumber(os.getenv("KONG_SPEC_TEST_ZIPKIN_PORT")) or 9411,
+ OTELCOL_HOST = os.getenv("KONG_SPEC_TEST_OTELCOL_HOST") or "localhost",
+ OTELCOL_HTTP_PORT = tonumber(os.getenv("KONG_SPEC_TEST_OTELCOL_HTTP_PORT")) or 4318,
+ OTELCOL_ZPAGES_PORT = tonumber(os.getenv("KONG_SPEC_TEST_OTELCOL_ZPAGES_PORT")) or 55679,
+ OTELCOL_FILE_EXPORTER_PATH = os.getenv("KONG_SPEC_TEST_OTELCOL_FILE_EXPORTER_PATH") or "./tmp/otel/file_exporter.json",
+ REDIS_HOST = os.getenv("KONG_SPEC_TEST_REDIS_HOST") or "localhost",
+ REDIS_PORT = tonumber(os.getenv("KONG_SPEC_TEST_REDIS_PORT") or 6379),
+ REDIS_SSL_PORT = tonumber(os.getenv("KONG_SPEC_TEST_REDIS_SSL_PORT") or 6380),
+ REDIS_AUTH_PORT = tonumber(os.getenv("KONG_SPEC_TEST_REDIS_AUTH_PORT") or 6385),
+ REDIS_SSL_SNI = os.getenv("KONG_SPEC_TEST_REDIS_SSL_SNI") or "test-redis.example.com",
+ TEST_COVERAGE_MODE = os.getenv("KONG_COVERAGE"),
+ TEST_COVERAGE_TIMEOUT = 30,
+
+ -- consistent with path set in .github/workflows/build_and_test.yml and build/dockerfiles/deb.pongo.Dockerfile
+ -- XXX EE
+ OLD_VERSION_KONG_PATH = os.getenv("KONG_SPEC_TEST_OLD_VERSION_KONG_PATH") or "/usr/local/share/lua/5.1/kong/kong-ee-old",
+
+ BLACKHOLE_HOST = "10.255.255.255",
+ KONG_VERSION = require("kong.meta")._VERSION,
+}
+
+
+return CONSTANTS
diff --git a/kong-versions/3.9.0.0/kong/spec/internal/db.lua b/kong-versions/3.9.0.0/kong/spec/internal/db.lua
new file mode 100644
index 00000000..4e5bffa4
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/internal/db.lua
@@ -0,0 +1,576 @@
+-- This software is copyright Kong Inc. and its licensors.
+-- Use of the software is subject to the agreement between your organization
+-- and Kong Inc. If there is no such agreement, use is governed by and
+-- subject to the terms of the Kong Master Software License Agreement found
+-- at https://konghq.com/enterprisesoftwarelicense/.
+-- [ END OF LICENSE 0867164ffc95e54f04670b5169c09574bdbd9bba ]
+
+------------------------------------------------------------------
+-- Collection of utilities to help testing Kong features and plugins.
+--
+-- @copyright Copyright 2016-2022 Kong Inc. All rights reserved.
+-- @license [Apache 2.0](https://opensource.org/licenses/Apache-2.0)
+-- @module spec.helpers
+
+
+local pl_tablex = require("pl.tablex")
+local table_clone = require("table.clone")
+
+-- XXX EE [[
+local invoke_plugin = require "kong.enterprise_edition.invoke_plugin"
+local portal_router = require "kong.portal.router"
+local rbac = require "kong.rbac"
+local kong_vitals = require "kong.vitals"
+-- XXX EE ]]
+
+local DB = require("kong.db")
+local constants = require("kong.constants")
+local kong_global = require("kong.global")
+local Blueprints = require("spec.fixtures.blueprints")
+local dc_blueprints = require("spec.fixtures.dc_blueprints")
+
+
+-- will be initialized in get_db_utils()
+local dcbp
+local PLUGINS_LIST
+
+
+-- Add to package path so dao helpers can insert custom plugins
+-- (while running from the busted environment)
+do
+ local CONSTANTS = require("spec.internal.constants")
+
+ local paths = {}
+ table.insert(paths, os.getenv("KONG_LUA_PACKAGE_PATH"))
+ table.insert(paths, CONSTANTS.CUSTOM_PLUGIN_PATH)
+
+ -- XXX EE custom plugins for enterprise tests
+ table.insert(paths, CONSTANTS.CUSTOM_EE_PLUGIN_PATH)
+ -- XXX EE
+
+ table.insert(paths, CONSTANTS.CUSTOM_VAULT_PATH)
+ table.insert(paths, package.path)
+ package.path = table.concat(paths, ";")
+end
+
+
+-- ------------
+-- Conf and DAO
+-- ------------
+
+local conf = require("spec.internal.conf")
+
+
+_G.kong = kong_global.new()
+kong_global.init_pdk(_G.kong, conf)
+ngx.ctx.KONG_PHASE = kong_global.phases.access
+_G.kong.core_cache = {
+ get = function(self, key, opts, func, ...)
+ if key == constants.CLUSTER_ID_PARAM_KEY then
+ return "123e4567-e89b-12d3-a456-426655440000"
+ end
+
+ return func(...)
+ end
+}
+
+
+local db = assert(DB.new(conf))
+assert(db:init_connector())
+db.plugins:load_plugin_schemas(conf.loaded_plugins)
+db.vaults:load_vault_schemas(conf.loaded_vaults)
+local blueprints = assert(Blueprints.new(db))
+
+
+kong.db = db
+
+
+-- XXX EE [[
+
+local cache
+
+--- Gets the ml_cache instance.
+-- @function get_cache
+-- @param db the database object
+-- @return ml_cache instance
+local function get_cache(db)
+ if not cache then
+ local worker_events = require "resty.events.compat"
+ worker_events.configure({
+ listening = "unix:",
+ testing = true,
+ })
+
+ local cluster_events = assert(kong_global.init_cluster_events(conf, db))
+ cache = assert(kong_global.init_cache(conf,
+ cluster_events,
+ worker_events
+ ))
+ end
+
+ return cache
+end
+
+kong.cache = get_cache(db)
+
+cache._busted_hooked = false
+
+local function clear_cache_on_file_end(file)
+ if _G.kong and
+ _G.kong.cache and
+ _G.kong.cache.mlcache and
+ _G.kong.cache.mlcache.lru and
+ _G.kong.cache.mlcache.lru.free_queue and
+ _G.kong.cache.mlcache.lru.cache_queue
+ then
+ _G.kong.cache.mlcache.lru.free_queue = nil
+ _G.kong.cache.mlcache.lru.cache_queue = nil
+ _G.kong.cache.mlcache.lru = nil
+ collectgarbage()
+ end
+end
+
+local function register_busted_hook(opts)
+ local busted = require("busted")
+ if not cache or cache._busted_hooked then
+ return
+ end
+
+ cache._busted_hooked = true
+
+ busted.subscribe({'file', 'end' }, clear_cache_on_file_end)
+end
+
+register_busted_hook()
+
+local vitals
+local function get_vitals(db)
+ if not vitals then
+ vitals = kong_vitals.new({
+ db = db,
+ ttl_seconds = 3600,
+ ttl_minutes = 24 * 60,
+ ttl_days = 30,
+ })
+ end
+
+ return vitals
+end
+
+kong.vitals = get_vitals(db)
+
+local analytics
+local function get_analytics()
+ if not analytics then
+ local kong_analytics = require "kong.analytics"
+ analytics = kong_analytics.new({})
+ end
+
+ return analytics
+end
+
+kong.analytics = get_analytics()
+
+-- XXX EE ]]
+
+
+--- Iterator over DB strategies.
+-- @function each_strategy
+-- @param strategies (optional string array) explicit list of strategies to use,
+-- defaults to `{ "postgres", }`.
+-- @see all_strategies
+-- @usage
+-- -- repeat all tests for each strategy
+-- for _, strategy_name in helpers.each_strategy() do
+-- describe("my test set [#" .. strategy .. "]", function()
+--
+-- -- add your tests here
+--
+-- end)
+-- end
+local function each_strategy() -- luacheck: ignore -- required to trick ldoc into processing for docs
+end
+
+
+--- Iterator over all strategies, the DB ones and the DB-less one.
+-- To test with DB-less, check the example.
+-- @function all_strategies
+-- @param strategies (optional string array) explicit list of strategies to use,
+-- defaults to `{ "postgres", "off" }`.
+-- @see each_strategy
+-- @see make_yaml_file
+-- @usage
+-- -- example of using DB-less testing
+--
+-- -- use "all_strategies" to iterate over; "postgres", "off"
+-- for _, strategy in helpers.all_strategies() do
+-- describe(PLUGIN_NAME .. ": (access) [#" .. strategy .. "]", function()
+--
+-- lazy_setup(function()
+--
+-- -- when calling "get_db_utils" with "strategy=off", we still use
+-- -- "postgres" so we can write the test setup to the database.
+-- local bp = helpers.get_db_utils(
+-- strategy == "off" and "postgres" or strategy,
+-- nil, { PLUGIN_NAME })
+--
+-- -- Inject a test route, when "strategy=off" it will still be written
+-- -- to Postgres.
+-- local route1 = bp.routes:insert({
+-- hosts = { "test1.com" },
+-- })
+--
+-- -- start kong
+-- assert(helpers.start_kong({
+-- -- set the strategy
+-- database = strategy,
+-- nginx_conf = "spec/fixtures/custom_nginx.template",
+-- plugins = "bundled," .. PLUGIN_NAME,
+--
+-- -- The call to "make_yaml_file" will write the contents of
+-- -- the database to a temporary file, which filename is returned.
+-- -- But only when "strategy=off".
+-- declarative_config = strategy == "off" and helpers.make_yaml_file() or nil,
+--
+-- -- the below lines can be omitted, but are just to prove that the test
+-- -- really runs DB-less despite that Postgres was used as intermediary
+-- -- storage.
+-- pg_host = strategy == "off" and "unknownhost.konghq.com" or nil,
+-- }))
+-- end)
+--
+-- ... rest of your test file
+local function all_strategies() -- luacheck: ignore -- required to trick ldoc into processing for docs
+end
+
+
+do
+ local pl_Set = require "pl.Set"
+
+ local def_db_strategies = {"postgres"}
+ local def_all_strategies = {"postgres", "off"}
+ local env_var = os.getenv("KONG_DATABASE")
+ if env_var then
+ def_db_strategies = { env_var }
+ def_all_strategies = { env_var }
+ end
+ local db_available_strategies = pl_Set(def_db_strategies)
+ local all_available_strategies = pl_Set(def_all_strategies)
+
+ local function iter(strategies, i)
+ i = i + 1
+ local strategy = strategies[i]
+ if strategy then
+ return i, strategy
+ end
+ end
+
+ each_strategy = function(strategies)
+ if not strategies then
+ return iter, def_db_strategies, 0
+ end
+
+ for i = #strategies, 1, -1 do
+ if not db_available_strategies[strategies[i]] then
+ table.remove(strategies, i)
+ end
+ end
+ return iter, strategies, 0
+ end
+
+ all_strategies = function(strategies)
+ if not strategies then
+ return iter, def_all_strategies, 0
+ end
+
+ for i = #strategies, 1, -1 do
+ if not all_available_strategies[strategies[i]] then
+ table.remove(strategies, i)
+ end
+ end
+ return iter, strategies, 0
+ end
+end
+
+
+local function truncate_tables(db, tables)
+ if not tables then
+ return
+ end
+
+ for _, t in ipairs(tables) do
+ if db[t] and db[t].schema then
+ db[t]:truncate()
+ end
+ end
+end
+
+
+local function bootstrap_database(db)
+ local schema_state = assert(db:schema_state())
+
+ if schema_state.needs_bootstrap then
+ assert(db:schema_bootstrap())
+ schema_state = assert(db:schema_state())
+ end
+
+ if schema_state.new_migrations then
+ assert(db:run_migrations(schema_state.new_migrations, {
+ run_up = true,
+ run_teardown = true,
+ }))
+ end
+end
+
+
+--- Gets the database utility helpers and prepares the database for a testrun.
+-- This will a.o. bootstrap the datastore and truncate the existing data that
+-- migth be in it. The BluePrint and DB objects returned can be used to create
+-- test entities in the database.
+--
+-- So the difference between the `db` and `bp` is small. The `db` one allows access
+-- to the datastore for creating entities and inserting data. The `bp` one is a
+-- wrapper around the `db` one. It will auto-insert some stuff and check for errors;
+--
+-- - if you create a route using `bp`, it will automatically attach it to the
+-- default service that it already created, without you having to specify that
+-- service.
+-- - any errors returned by `db`, which will be `nil + error` in Lua, will be
+-- wrapped in an assertion by `bp` so if something is wrong it will throw a hard
+-- error which is convenient when testing. When using `db` you have to manually
+-- check for errors.
+--
+-- Since `bp` is a wrapper around `db` it will only know about the Kong standard
+-- entities in the database. Hence the `db` one should be used when working with
+-- custom DAO's for which no `bp` entry is available.
+-- @function get_db_utils
+-- @param strategy (optional) the database strategy to use, will default to the
+-- strategy in the test configuration.
+-- @param tables (optional) tables to truncate, this can be used to accelarate
+-- tests if only a few tables are used. By default all tables will be truncated.
+-- @param plugins (optional) array of plugins to mark as loaded. Since kong will
+-- load all the bundled plugins by default, this is useful mostly for marking
+-- custom plugins as loaded.
+-- @param vaults (optional) vault configuration to use.
+-- @param skip_migrations (optional) if true, migrations will not be run.
+-- @return BluePrint, DB
+-- @usage
+-- local PLUGIN_NAME = "my_fancy_plugin"
+-- local bp = helpers.get_db_utils("postgres", nil, { PLUGIN_NAME })
+--
+-- -- Inject a test route. No need to create a service, there is a default
+-- -- service which will echo the request.
+-- local route1 = bp.routes:insert({
+-- hosts = { "test1.com" },
+-- })
+-- -- add the plugin to test to the route we created
+-- bp.plugins:insert {
+-- name = PLUGIN_NAME,
+-- route = { id = route1.id },
+-- config = {},
+-- }
+local function get_db_utils(strategy, tables, plugins, vaults, skip_migrations)
+ strategy = strategy or conf.database
+ conf.database = strategy -- overwrite kong.configuration.database
+
+ if tables ~= nil and type(tables) ~= "table" then
+ error("arg #2 must be a list of tables to truncate", 2)
+ end
+ if plugins ~= nil and type(plugins) ~= "table" then
+ error("arg #3 must be a list of plugins to enable", 2)
+ end
+
+ if plugins then
+ for _, plugin in ipairs(plugins) do
+ conf.loaded_plugins[plugin] = true
+ end
+ end
+
+ if vaults ~= nil and type(vaults) ~= "table" then
+ error("arg #4 must be a list of vaults to enable", 2)
+ end
+
+ if vaults then
+ for _, vault in ipairs(vaults) do
+ conf.loaded_vaults[vault] = true
+ end
+ end
+
+ -- Clean workspaces from the context - otherwise, migrations will fail,
+ -- as some of them have dao calls
+ -- If `no_truncate` is falsey, `dao:truncate` and `db:truncate` are called,
+ -- and these set the workspace back again to the new `default` workspace
+ ngx.ctx.workspace = nil
+
+ -- DAO (DB module)
+ local db = assert(DB.new(conf, strategy))
+ assert(db:init_connector())
+
+ if not skip_migrations then
+ -- Drop all schema and data
+ assert(db:schema_reset())
+ bootstrap_database(db)
+ end
+
+ db:truncate("plugins")
+ assert(db.plugins:load_plugin_schemas(conf.loaded_plugins))
+ assert(db.vaults:load_vault_schemas(conf.loaded_vaults))
+
+ -- XXX EE [[
+ kong.invoke_plugin = invoke_plugin.new {
+ loaded_plugins = db.plugins:get_handlers(),
+ kong_global = kong_global,
+ }
+ -- XXX EE ]]
+
+ db:truncate("tags")
+
+ -- XXX EE [[
+ -- initialize portal router
+ kong.portal_router = portal_router.new(db)
+ -- XXX EE ]]
+
+ _G.kong.db = db
+
+ -- cleanup tables
+ if not tables then
+ assert(db:truncate())
+
+ else
+ tables[#tables + 1] = "workspaces"
+ truncate_tables(db, tables)
+ end
+
+ -- blueprints
+ local bp
+ if strategy ~= "off" then
+ bp = assert(Blueprints.new(db))
+ dcbp = nil
+ else
+ bp = assert(dc_blueprints.new(db))
+ dcbp = bp
+ end
+
+ if plugins then
+ for _, plugin in ipairs(plugins) do
+ conf.loaded_plugins[plugin] = false
+ end
+ end
+
+ -- XXX EE [[
+ rbac.register_dao_hooks(db)
+ -- XXX EE ]]
+
+ if vaults then
+ for _, vault in ipairs(vaults) do
+ conf.loaded_vaults[vault] = false
+ end
+ end
+
+ if strategy ~= "off" then
+ local workspaces = require "kong.workspaces"
+ workspaces.upsert_default(db)
+ end
+
+ -- calculation can only happen here because this function
+ -- initializes the kong.db instance
+ PLUGINS_LIST = assert(kong.db.plugins:get_handlers())
+ table.sort(PLUGINS_LIST, function(a, b)
+ return a.name:lower() < b.name:lower()
+ end)
+
+ PLUGINS_LIST = pl_tablex.map(function(p)
+ return { name = p.name, version = p.handler.VERSION, }
+ end, PLUGINS_LIST)
+
+ return bp, db
+end
+
+
+local function get_dcbp()
+ return dcbp
+end
+
+
+local function get_plugins_list()
+ return PLUGINS_LIST
+end
+
+
+-- returns the plugins and version list that is used by Hybrid mode tests
+local function clone_plugins_list()
+ assert(PLUGINS_LIST, "plugin list has not been initialized yet, " ..
+ "you must call get_db_utils first")
+ return table_clone(PLUGINS_LIST)
+end
+
+
+local validate_plugin_config_schema
+do
+ local consumers_schema_def = require("kong.db.schema.entities.consumers")
+ local services_schema_def = require("kong.db.schema.entities.services")
+ local plugins_schema_def = require("kong.db.schema.entities.plugins")
+ local routes_schema_def = require("kong.db.schema.entities.routes")
+ local Schema = require("kong.db.schema")
+ local Entity = require("kong.db.schema.entity")
+ local uuid = require("kong.tools.uuid").uuid
+
+ -- Prepopulate Schema's cache
+ Schema.new(consumers_schema_def)
+ Schema.new(services_schema_def)
+ Schema.new(routes_schema_def)
+
+ local plugins_schema = assert(Entity.new(plugins_schema_def))
+
+ --- Validate a plugin configuration against a plugin schema.
+ -- @function validate_plugin_config_schema
+ -- @param config The configuration to validate. This is not the full schema,
+ -- only the `config` sub-object needs to be passed.
+ -- @param schema_def The schema definition
+ -- @return the validated schema, or nil+error
+ validate_plugin_config_schema = function(config, schema_def, extra_fields)
+ assert(plugins_schema:new_subschema(schema_def.name, schema_def))
+ local entity = {
+ id = uuid(),
+ name = schema_def.name,
+ config = config
+ }
+
+ if extra_fields then
+ for k, v in pairs(extra_fields) do
+ entity[k] = v
+ end
+ end
+
+ local entity_to_insert, err = plugins_schema:process_auto_fields(entity, "insert")
+ if err then
+ return nil, err
+ end
+ local _, err = plugins_schema:validate_insert(entity_to_insert)
+ if err then return
+ nil, err
+ end
+ return entity_to_insert
+ end
+end
+
+
+return {
+ db = db,
+ blueprints = blueprints,
+
+ get_dcbp = get_dcbp,
+ get_plugins_list = get_plugins_list,
+ clone_plugins_list = clone_plugins_list,
+
+ get_cache = get_cache,
+ get_db_utils = get_db_utils,
+
+ truncate_tables = truncate_tables,
+ bootstrap_database = bootstrap_database,
+
+ each_strategy = each_strategy,
+ all_strategies = all_strategies,
+
+ validate_plugin_config_schema = validate_plugin_config_schema,
+}
diff --git a/kong-versions/3.9.0.0/kong/spec/internal/dns.lua b/kong-versions/3.9.0.0/kong/spec/internal/dns.lua
new file mode 100644
index 00000000..79a8cf89
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/internal/dns.lua
@@ -0,0 +1,228 @@
+-- This software is copyright Kong Inc. and its licensors.
+-- Use of the software is subject to the agreement between your organization
+-- and Kong Inc. If there is no such agreement, use is governed by and
+-- subject to the terms of the Kong Master Software License Agreement found
+-- at https://konghq.com/enterprisesoftwarelicense/.
+-- [ END OF LICENSE 0867164ffc95e54f04670b5169c09574bdbd9bba ]
+
+------------------------------------------------------------------
+-- Collection of utilities to help testing Kong features and plugins.
+--
+-- @copyright Copyright 2016-2022 Kong Inc. All rights reserved.
+-- @license [Apache 2.0](https://opensource.org/licenses/Apache-2.0)
+-- @module spec.helpers
+
+
+local cjson = require("cjson.safe")
+
+
+----------------
+-- DNS-record mocking.
+-- These function allow to create mock dns records that the test Kong instance
+-- will use to resolve names. The created mocks are injected by the `start_kong`
+-- function.
+-- @usage
+-- -- Create a new DNS mock and add some DNS records
+-- local fixtures = {
+-- dns_mock = helpers.dns_mock.new { mocks_only = true }
+-- }
+--
+-- fixtures.dns_mock:SRV {
+-- name = "my.srv.test.com",
+-- target = "a.my.srv.test.com",
+-- port = 80,
+-- }
+-- fixtures.dns_mock:SRV {
+-- name = "my.srv.test.com", -- adding same name again: record gets 2 entries!
+-- target = "b.my.srv.test.com", -- a.my.srv.test.com and b.my.srv.test.com
+-- port = 8080,
+-- }
+-- fixtures.dns_mock:A {
+-- name = "a.my.srv.test.com",
+-- address = "127.0.0.1",
+-- }
+-- fixtures.dns_mock:A {
+-- name = "b.my.srv.test.com",
+-- address = "127.0.0.1",
+-- }
+-- @section DNS-mocks
+
+
+local dns_mock = {}
+
+
+dns_mock.__index = dns_mock
+dns_mock.__tostring = function(self)
+ -- fill array to prevent json encoding errors
+ local out = {
+ mocks_only = self.mocks_only,
+ records = {}
+ }
+ for i = 1, 33 do
+ out.records[i] = self[i] or {}
+ end
+ local json = assert(cjson.encode(out))
+ return json
+end
+
+
+local TYPE_A, TYPE_AAAA, TYPE_CNAME, TYPE_SRV = 1, 28, 5, 33
+
+
+--- Creates a new DNS mock.
+-- The options table supports the following fields:
+--
+-- - `mocks_only`: boolean, if set to `true` then only mock records will be
+-- returned. If `falsy` it will fall through to an actual DNS lookup.
+-- @function dns_mock.new
+-- @param options table with mock options
+-- @return dns_mock object
+-- @usage
+-- local mock = helpers.dns_mock.new { mocks_only = true }
+function dns_mock.new(options)
+ return setmetatable(options or {}, dns_mock)
+end
+
+
+--- Adds an SRV record to the DNS mock.
+-- Fields `name`, `target`, and `port` are required. Other fields get defaults:
+--
+-- * `weight`; 20
+-- * `ttl`; 600
+-- * `priority`; 20
+-- @param rec the mock DNS record to insert
+-- @return true
+function dns_mock:SRV(rec)
+ if self == dns_mock then
+ error("can't operate on the class, you must create an instance", 2)
+ end
+ if getmetatable(self or {}) ~= dns_mock then
+ error("SRV method must be called using the colon notation", 2)
+ end
+ assert(rec, "Missing record parameter")
+ local name = assert(rec.name, "No name field in SRV record")
+
+ self[TYPE_SRV] = self[TYPE_SRV] or {}
+ local query_answer = self[TYPE_SRV][name]
+ if not query_answer then
+ query_answer = {}
+ self[TYPE_SRV][name] = query_answer
+ end
+
+ table.insert(query_answer, {
+ type = TYPE_SRV,
+ name = name,
+ target = assert(rec.target, "No target field in SRV record"),
+ port = assert(rec.port, "No port field in SRV record"),
+ weight = rec.weight or 10,
+ ttl = rec.ttl or 600,
+ priority = rec.priority or 20,
+ class = rec.class or 1
+ })
+ return true
+end
+
+
+--- Adds an A record to the DNS mock.
+-- Fields `name` and `address` are required. Other fields get defaults:
+--
+-- * `ttl`; 600
+-- @param rec the mock DNS record to insert
+-- @return true
+function dns_mock:A(rec)
+ if self == dns_mock then
+ error("can't operate on the class, you must create an instance", 2)
+ end
+ if getmetatable(self or {}) ~= dns_mock then
+ error("A method must be called using the colon notation", 2)
+ end
+ assert(rec, "Missing record parameter")
+ local name = assert(rec.name, "No name field in A record")
+
+ self[TYPE_A] = self[TYPE_A] or {}
+ local query_answer = self[TYPE_A][name]
+ if not query_answer then
+ query_answer = {}
+ self[TYPE_A][name] = query_answer
+ end
+
+ table.insert(query_answer, {
+ type = TYPE_A,
+ name = name,
+ address = assert(rec.address, "No address field in A record"),
+ ttl = rec.ttl or 600,
+ class = rec.class or 1
+ })
+ return true
+end
+
+
+--- Adds an AAAA record to the DNS mock.
+-- Fields `name` and `address` are required. Other fields get defaults:
+--
+-- * `ttl`; 600
+-- @param rec the mock DNS record to insert
+-- @return true
+function dns_mock:AAAA(rec)
+ if self == dns_mock then
+ error("can't operate on the class, you must create an instance", 2)
+ end
+ if getmetatable(self or {}) ~= dns_mock then
+ error("AAAA method must be called using the colon notation", 2)
+ end
+ assert(rec, "Missing record parameter")
+ local name = assert(rec.name, "No name field in AAAA record")
+
+ self[TYPE_AAAA] = self[TYPE_AAAA] or {}
+ local query_answer = self[TYPE_AAAA][name]
+ if not query_answer then
+ query_answer = {}
+ self[TYPE_AAAA][name] = query_answer
+ end
+
+ table.insert(query_answer, {
+ type = TYPE_AAAA,
+ name = name,
+ address = assert(rec.address, "No address field in AAAA record"),
+ ttl = rec.ttl or 600,
+ class = rec.class or 1
+ })
+ return true
+end
+
+
+--- Adds a CNAME record to the DNS mock.
+-- Fields `name` and `cname` are required. Other fields get defaults:
+--
+-- * `ttl`; 600
+-- @param rec the mock DNS record to insert
+-- @return true
+function dns_mock:CNAME(rec)
+ if self == dns_mock then
+ error("can't operate on the class, you must create an instance", 2)
+ end
+ if getmetatable(self or {}) ~= dns_mock then
+ error("CNAME method must be called using the colon notation", 2)
+ end
+ assert(rec, "Missing record parameter")
+ local name = assert(rec.name, "No name field in CNAME record")
+
+ self[TYPE_CNAME] = self[TYPE_CNAME] or {}
+ local query_answer = self[TYPE_CNAME][name]
+ if not query_answer then
+ query_answer = {}
+ self[TYPE_CNAME][name] = query_answer
+ end
+
+ table.insert(query_answer, {
+ type = TYPE_CNAME,
+ name = name,
+ cname = assert(rec.cname, "No cname field in CNAME record"),
+ ttl = rec.ttl or 600,
+ class = rec.class or 1
+ })
+ return true
+end
+
+
+return dns_mock
diff --git a/kong-versions/3.9.0.0/kong/spec/internal/grpc.lua b/kong-versions/3.9.0.0/kong/spec/internal/grpc.lua
new file mode 100644
index 00000000..241184ac
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/internal/grpc.lua
@@ -0,0 +1,97 @@
+-- This software is copyright Kong Inc. and its licensors.
+-- Use of the software is subject to the agreement between your organization
+-- and Kong Inc. If there is no such agreement, use is governed by and
+-- subject to the terms of the Kong Master Software License Agreement found
+-- at https://konghq.com/enterprisesoftwarelicense/.
+-- [ END OF LICENSE 0867164ffc95e54f04670b5169c09574bdbd9bba ]
+
+local pl_path = require("pl.path")
+local shell = require("resty.shell")
+local resty_signal = require("resty.signal")
+
+
+local CONSTANTS = require("spec.internal.constants")
+
+
+local function isnewer(path_a, path_b)
+ if not pl_path.exists(path_a) then
+ return true
+ end
+ if not pl_path.exists(path_b) then
+ return false
+ end
+ return assert(pl_path.getmtime(path_b)) > assert(pl_path.getmtime(path_a))
+end
+
+
+local function make(workdir, specs)
+ workdir = pl_path.normpath(workdir or pl_path.currentdir())
+
+ for _, spec in ipairs(specs) do
+ local targetpath = pl_path.join(workdir, spec.target)
+ for _, src in ipairs(spec.src) do
+ local srcpath = pl_path.join(workdir, src)
+ if isnewer(targetpath, srcpath) then
+ local ok, _, stderr = shell.run(string.format("cd %s; %s", workdir, spec.cmd), nil, 0)
+ assert(ok, stderr)
+ if isnewer(targetpath, srcpath) then
+ error(string.format("couldn't make %q newer than %q", targetpath, srcpath))
+ end
+ break
+ end
+ end
+ end
+
+ return true
+end
+
+
+local grpc_target_proc
+
+
+local function start_grpc_target()
+ local ngx_pipe = require("ngx.pipe")
+ assert(make(CONSTANTS.GRPC_TARGET_SRC_PATH, {
+ {
+ target = "targetservice/targetservice.pb.go",
+ src = { "../targetservice.proto" },
+ cmd = "protoc --go_out=. --go-grpc_out=. -I ../ ../targetservice.proto",
+ },
+ {
+ target = "targetservice/targetservice_grpc.pb.go",
+ src = { "../targetservice.proto" },
+ cmd = "protoc --go_out=. --go-grpc_out=. -I ../ ../targetservice.proto",
+ },
+ {
+ target = "target",
+ src = { "grpc-target.go", "targetservice/targetservice.pb.go", "targetservice/targetservice_grpc.pb.go" },
+ cmd = "go mod tidy && go mod download all && go build",
+ },
+ }))
+ grpc_target_proc = assert(ngx_pipe.spawn({ CONSTANTS.GRPC_TARGET_SRC_PATH .. "/target" }, {
+ merge_stderr = true,
+ }))
+
+ return true
+end
+
+
+local function stop_grpc_target()
+ if grpc_target_proc then
+ grpc_target_proc:kill(resty_signal.signum("QUIT"))
+ grpc_target_proc = nil
+ end
+end
+
+
+local function get_grpc_target_port()
+ return 15010
+end
+
+
+return {
+ start_grpc_target = start_grpc_target,
+ stop_grpc_target = stop_grpc_target,
+ get_grpc_target_port = get_grpc_target_port,
+}
+
diff --git a/kong-versions/3.9.0.0/kong/spec/internal/misc.lua b/kong-versions/3.9.0.0/kong/spec/internal/misc.lua
new file mode 100644
index 00000000..f7db54a4
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/internal/misc.lua
@@ -0,0 +1,330 @@
+-- This software is copyright Kong Inc. and its licensors.
+-- Use of the software is subject to the agreement between your organization
+-- and Kong Inc. If there is no such agreement, use is governed by and
+-- subject to the terms of the Kong Master Software License Agreement found
+-- at https://konghq.com/enterprisesoftwarelicense/.
+-- [ END OF LICENSE 0867164ffc95e54f04670b5169c09574bdbd9bba ]
+
+------------------------------------------------------------------
+-- Collection of utilities to help testing Kong features and plugins.
+--
+-- @copyright Copyright 2016-2022 Kong Inc. All rights reserved.
+-- @license [Apache 2.0](https://opensource.org/licenses/Apache-2.0)
+-- @module spec.helpers
+
+
+-- miscellaneous
+
+
+local pl_path = require("pl.path")
+local pl_dir = require("pl.dir")
+local pkey = require("resty.openssl.pkey")
+local nginx_signals = require("kong.cmd.utils.nginx_signals")
+local shell = require("spec.internal.shell")
+
+
+local CONSTANTS = require("spec.internal.constants")
+local sys = require("spec.internal.sys")
+
+
+local pack = function(...) return { n = select("#", ...), ... } end
+local unpack = function(t) return unpack(t, 1, t.n) end
+
+
+--- Prints all returned parameters.
+-- Simple debugging aid, it will pass all received parameters, hence will not
+-- influence the flow of the code. See also `fail`.
+-- @function intercept
+-- @see fail
+-- @usage -- modify
+-- local a,b = some_func(c,d)
+-- -- into
+-- local a,b = intercept(some_func(c,d))
+local function intercept(...)
+ local args = pack(...)
+ print(require("pl.pretty").write(args))
+ return unpack(args)
+end
+
+
+--- Returns the OpenResty version.
+-- Extract the current OpenResty version in use and returns
+-- a numerical representation of it.
+-- Ex: `1.11.2.2` -> `11122`
+-- @function openresty_ver_num
+local function openresty_ver_num()
+ local nginx_bin = assert(nginx_signals.find_nginx_bin())
+ local _, _, stderr = shell.run(string.format("%s -V", nginx_bin), nil, 0)
+
+ local a, b, c, d = string.match(stderr or "", "openresty/(%d+)%.(%d+)%.(%d+)%.(%d+)")
+ if not a then
+ error("could not execute 'nginx -V': " .. stderr)
+ end
+
+ return tonumber(a .. b .. c .. d)
+end
+
+
+--- Unindent a multi-line string for proper indenting in
+-- square brackets.
+-- @function unindent
+-- @usage
+-- local u = helpers.unindent
+--
+-- u[[
+-- hello world
+-- foo bar
+-- ]]
+--
+-- -- will return: "hello world\nfoo bar"
+local function unindent(str, concat_newlines, spaced_newlines)
+ str = string.match(str, "(.-%S*)%s*$")
+ if not str then
+ return ""
+ end
+
+ local level = math.huge
+ local prefix = ""
+ local len
+
+ str = str:match("^%s") and "\n" .. str or str
+ for pref in str:gmatch("\n(%s+)") do
+ len = #prefix
+
+ if len < level then
+ level = len
+ prefix = pref
+ end
+ end
+
+ local repl = concat_newlines and "" or "\n"
+ repl = spaced_newlines and " " or repl
+
+ return (str:gsub("^\n%s*", ""):gsub("\n" .. prefix, repl):gsub("\n$", ""):gsub("\\r", "\r"))
+end
+
+
+--- Write a yaml file.
+-- @function make_yaml_file
+-- @param content (string) the yaml string to write to the file, if omitted the
+-- current database contents will be written using `kong config db_export`.
+-- @param filename (optional) if not provided, a temp name will be created
+-- @return filename of the file written
+local function make_yaml_file(content, filename)
+ local filename = filename or pl_path.tmpname() .. ".yml"
+ if content then
+ local fd = assert(io.open(filename, "w"))
+ assert(fd:write(unindent(content)))
+ assert(fd:write("\n")) -- ensure last line ends in newline
+ assert(fd:close())
+ else
+ assert(shell.kong_exec("config db_export --conf "..CONSTANTS.TEST_CONF_PATH.." "..filename))
+ end
+ return filename
+end
+
+
+local deep_sort
+do
+ local function deep_compare(a, b)
+ if a == nil then
+ a = ""
+ end
+
+ if b == nil then
+ b = ""
+ end
+
+ deep_sort(a)
+ deep_sort(b)
+
+ if type(a) ~= type(b) then
+ return type(a) < type(b)
+ end
+
+ if type(a) == "table" then
+ return deep_compare(a[1], b[1])
+ end
+
+ -- compare cjson.null or ngx.null
+ if type(a) == "userdata" and type(b) == "userdata" then
+ return false
+ end
+
+ return a < b
+ end
+
+ deep_sort = function(t)
+ if type(t) == "table" then
+ for _, v in pairs(t) do
+ deep_sort(v)
+ end
+ table.sort(t, deep_compare)
+ end
+
+ return t
+ end
+end
+
+
+--- Generate asymmetric keys
+-- @function generate_keys
+-- @param fmt format to receive the public and private pair
+-- @return `pub, priv` key tuple or `nil + err` on failure
+local function generate_keys(fmt)
+ fmt = string.upper(fmt) or "JWK"
+ local key, err = pkey.new({
+ -- only support RSA for now
+ type = 'RSA',
+ bits = 2048,
+ exp = 65537
+ })
+ assert(key)
+ assert(err == nil, err)
+ local pub = key:tostring("public", fmt)
+ local priv = key:tostring("private", fmt)
+ return pub, priv
+end
+
+
+-- Case insensitive lookup function, returns the value and the original key. Or
+-- if not found nil and the search key
+-- @usage -- sample usage
+-- local test = { SoMeKeY = 10 }
+-- print(lookup(test, "somekey")) --> 10, "SoMeKeY"
+-- print(lookup(test, "NotFound")) --> nil, "NotFound"
+local function lookup(t, k)
+ local ok = k
+ if type(k) ~= "string" then
+ return t[k], k
+ else
+ k = k:lower()
+ end
+ for key, value in pairs(t) do
+ if tostring(key):lower() == k then
+ return value, key
+ end
+ end
+ return nil, ok
+end
+
+
+local function with_current_ws(ws,fn, db)
+ local old_ws = ngx.ctx.workspace
+ ngx.ctx.workspace = nil
+ ws = ws or {db.workspaces:select_by_name("default")}
+ ngx.ctx.workspace = ws[1] and ws[1].id
+ local res = fn()
+ ngx.ctx.workspace = old_ws
+ return res
+end
+
+
+local make_temp_dir
+do
+ local seeded = false
+
+ function make_temp_dir()
+ if not seeded then
+ ngx.update_time()
+ math.randomseed(ngx.worker.pid() + ngx.now())
+ seeded = true
+ end
+
+ local tmp
+ local ok, err
+
+ local tries = 1000
+ for _ = 1, tries do
+ local name = "/tmp/.kong-test" .. math.random()
+
+ ok, err = pl_path.mkdir(name)
+
+ if ok then
+ tmp = name
+ break
+ end
+ end
+
+ assert(tmp ~= nil, "failed to create temporary directory " ..
+ "after " .. tostring(tries) .. " tries, " ..
+ "last error: " .. tostring(err))
+
+ return tmp, function() pl_dir.rmtree(tmp) end
+ end
+end
+
+
+-- This function is used for plugin compatibility test.
+-- It will use the old version plugin by including the path of the old plugin
+-- at the first of LUA_PATH.
+-- The return value is a function which when called will recover the original
+-- LUA_PATH and remove the temporary directory if it exists.
+-- For an example of how to use it, please see:
+-- plugins-ee/rate-limiting-advanced/spec/06-old-plugin-compatibility_spec.lua
+-- spec/03-plugins/03-http-log/05-old-plugin-compatibility_spec.lua
+local function use_old_plugin(name)
+ assert(type(name) == "string", "must specify the plugin name")
+
+ local old_plugin_path
+ local temp_dir
+ if pl_path.exists(CONSTANTS.OLD_VERSION_KONG_PATH .. "/kong/plugins/" .. name) then
+ -- only include the path of the specified plugin into LUA_PATH
+ -- and keep the directory structure 'kong/plugins/...'
+ temp_dir = make_temp_dir()
+ old_plugin_path = temp_dir
+ local dest_dir = old_plugin_path .. "/kong/plugins"
+ assert(pl_dir.makepath(dest_dir), "failed to makepath " .. dest_dir)
+ assert(shell.run("cp -r " .. CONSTANTS.OLD_VERSION_KONG_PATH .. "/kong/plugins/" .. name .. " " .. dest_dir), "failed to copy the plugin directory")
+
+ -- XXX EE [[
+ elseif pl_path.exists(CONSTANTS.OLD_VERSION_KONG_PATH .. "/plugins-ee/" .. name) then
+ old_plugin_path = CONSTANTS.OLD_VERSION_KONG_PATH .. "/plugins-ee/" .. name
+ -- XXX EE ]]
+
+ else
+ error("the specified plugin " .. name .. " doesn't exist")
+ end
+
+ -- XXX EE [[
+ local plugin_include_path = old_plugin_path .. "/?.lua;" .. old_plugin_path .. "/?/init.lua;"
+
+ local origin_lua_path = os.getenv("LUA_PATH")
+ -- put the old plugin path at first
+ assert(sys.setenv("LUA_PATH", plugin_include_path .. origin_lua_path), "failed to set LUA_PATH env")
+
+ -- LUA_PATH is used by "kong commands" like "kong start", "kong config" etc.
+ -- but for busted tests that are already running (since this is spec/helpers.lua) in order to use old plugin we need to update `package.path`
+ local origin_package_path = package.path
+ package.path = plugin_include_path .. origin_package_path
+ -- XXX EE ]]
+
+ return function ()
+ sys.setenv("LUA_PATH", origin_lua_path)
+ if temp_dir then
+ pl_dir.rmtree(temp_dir)
+ end
+ end
+end
+
+
+return {
+ pack = pack,
+ unpack = unpack,
+
+ intercept = intercept,
+ openresty_ver_num = openresty_ver_num(),
+ unindent = unindent,
+ make_yaml_file = make_yaml_file,
+ setenv = sys.setenv,
+ unsetenv = sys.unsetenv,
+ deep_sort = deep_sort,
+
+ generate_keys = generate_keys,
+
+ lookup = lookup,
+
+ with_current_ws = with_current_ws,
+ make_temp_dir = make_temp_dir,
+ use_old_plugin = use_old_plugin,
+}
diff --git a/kong-versions/3.9.0.0/kong/spec/internal/module.lua b/kong-versions/3.9.0.0/kong/spec/internal/module.lua
new file mode 100644
index 00000000..3085454d
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/internal/module.lua
@@ -0,0 +1,49 @@
+-- This software is copyright Kong Inc. and its licensors.
+-- Use of the software is subject to the agreement between your organization
+-- and Kong Inc. If there is no such agreement, use is governed by and
+-- subject to the terms of the Kong Master Software License Agreement found
+-- at https://konghq.com/enterprisesoftwarelicense/.
+-- [ END OF LICENSE 0867164ffc95e54f04670b5169c09574bdbd9bba ]
+
+-- totally clean the module then load it
+local function reload(name)
+ package.loaded[name] = nil
+ return require(name)
+end
+
+
+local reload_helpers
+do
+ local sys = require("spec.internal.sys")
+
+ -- flavor could be "traditional","traditional_compatible" or "expressions"
+ -- changing flavor will change db's schema
+ reload_helpers = function(flavor)
+ _G.kong = {
+ configuration = {
+ router_flavor = flavor,
+ },
+ }
+
+ sys.setenv("KONG_ROUTER_FLAVOR", flavor)
+
+ -- reload db and global module
+ reload("kong.db.schema.entities.routes_subschemas")
+ reload("kong.db.schema.entities.routes")
+ reload("kong.cache")
+ reload("kong.global")
+
+ -- reload helpers module
+ local helpers = reload("spec.helpers")
+
+ sys.unsetenv("KONG_ROUTER_FLAVOR")
+
+ return helpers
+ end
+end
+
+
+return {
+ reload = reload,
+ reload_helpers = reload_helpers,
+}
diff --git a/kong-versions/3.9.0.0/kong/spec/internal/pid.lua b/kong-versions/3.9.0.0/kong/spec/internal/pid.lua
new file mode 100644
index 00000000..0a59e204
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/internal/pid.lua
@@ -0,0 +1,85 @@
+-- This software is copyright Kong Inc. and its licensors.
+-- Use of the software is subject to the agreement between your organization
+-- and Kong Inc. If there is no such agreement, use is governed by and
+-- subject to the terms of the Kong Master Software License Agreement found
+-- at https://konghq.com/enterprisesoftwarelicense/.
+-- [ END OF LICENSE 0867164ffc95e54f04670b5169c09574bdbd9bba ]
+
+------------------------------------------------------------------
+-- Collection of utilities to help testing Kong features and plugins.
+--
+-- @copyright Copyright 2016-2022 Kong Inc. All rights reserved.
+-- @license [Apache 2.0](https://opensource.org/licenses/Apache-2.0)
+-- @module spec.helpers
+
+
+local shell = require("resty.shell")
+
+
+local CONSTANTS = require("spec.internal.constants")
+
+
+-- Reads the pid from a pid file and returns it, or nil + err
+local function get_pid_from_file(pid_path)
+ local pid
+ local fd, err = io.open(pid_path)
+ if not fd then
+ return nil, err
+ end
+
+ pid = fd:read("*l")
+ fd:close()
+
+ return pid
+end
+
+
+local function pid_dead(pid, timeout)
+ local max_time = ngx.now() + (timeout or 10)
+
+ repeat
+ if not shell.run("ps -p " .. pid .. " >/dev/null 2>&1", nil, 0) then
+ return true
+ end
+ -- still running, wait some more
+ ngx.sleep(0.05)
+ until ngx.now() >= max_time
+
+ return false
+end
+
+
+-- Waits for the termination of a pid.
+-- @param pid_path Filename of the pid file.
+-- @param timeout (optional) in seconds, defaults to 10.
+local function wait_pid(pid_path, timeout, is_retry)
+ local pid = get_pid_from_file(pid_path)
+
+ if CONSTANTS.TEST_COVERAGE_MODE == "true" then
+ timeout = CONSTANTS.TEST_COVERAGE_TIMEOUT
+ end
+
+ if pid then
+ if pid_dead(pid, timeout) then
+ return
+ end
+
+ if is_retry then
+ return
+ end
+
+ -- Timeout reached: kill with SIGKILL
+ shell.run("kill -9 " .. pid .. " >/dev/null 2>&1", nil, 0)
+
+ -- Sanity check: check pid again, but don't loop.
+ wait_pid(pid_path, timeout, true)
+ end
+end
+
+
+return {
+ get_pid_from_file = get_pid_from_file,
+ pid_dead = pid_dead,
+ wait_pid = wait_pid,
+}
+
diff --git a/kong-versions/3.9.0.0/kong/spec/internal/server.lua b/kong-versions/3.9.0.0/kong/spec/internal/server.lua
new file mode 100644
index 00000000..017828e8
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/internal/server.lua
@@ -0,0 +1,514 @@
+-- This software is copyright Kong Inc. and its licensors.
+-- Use of the software is subject to the agreement between your organization
+-- and Kong Inc. If there is no such agreement, use is governed by and
+-- subject to the terms of the Kong Master Software License Agreement found
+-- at https://konghq.com/enterprisesoftwarelicense/.
+-- [ END OF LICENSE 0867164ffc95e54f04670b5169c09574bdbd9bba ]
+
+------------------------------------------------------------------
+-- Collection of utilities to help testing Kong features and plugins.
+--
+-- @copyright Copyright 2016-2022 Kong Inc. All rights reserved.
+-- @license [Apache 2.0](https://opensource.org/licenses/Apache-2.0)
+-- @module spec.helpers
+
+
+local CONSTANTS = require("spec.internal.constants")
+
+
+---
+-- TCP/UDP server helpers
+--
+-- @section servers
+
+
+--- Starts a local TCP server.
+-- Accepts a single connection (or multiple, if given `opts.requests`)
+-- and then closes, echoing what was received (last read, in case
+-- of multiple requests).
+-- @function tcp_server
+-- @tparam number port The port where the server will be listening on
+-- @tparam[opt] table opts options defining the server's behavior with the following fields:
+-- @tparam[opt=60] number opts.timeout time (in seconds) after which the server exits
+-- @tparam[opt=1] number opts.requests the number of requests to accept before exiting
+-- @tparam[opt=false] bool opts.tls make it a TLS server if truthy
+-- @tparam[opt] string opts.prefix a prefix to add to the echoed data received
+-- @return A thread object (from the `llthreads2` Lua package)
+-- @see kill_tcp_server
+local function tcp_server(port, opts)
+ local threads = require "llthreads2.ex"
+ opts = opts or {}
+ if CONSTANTS.TEST_COVERAGE_MODE == "true" then
+ opts.timeout = CONSTANTS.TEST_COVERAGE_TIMEOUT
+ end
+ local thread = threads.new({
+ function(port, opts)
+ local socket = require "socket"
+ local server = assert(socket.tcp())
+ server:settimeout(opts.timeout or 60)
+ assert(server:setoption("reuseaddr", true))
+ assert(server:bind("*", port))
+ assert(server:listen())
+ local line
+ local oks, fails = 0, 0
+ local handshake_done = false
+ local n = opts.requests or 1
+ for _ = 1, n + 1 do
+ local client, err
+ if opts.timeout then
+ client, err = server:accept()
+ if err == "timeout" then
+ line = "timeout"
+ break
+
+ else
+ assert(client, err)
+ end
+
+ else
+ client = assert(server:accept())
+ end
+
+ if opts.tls and handshake_done then
+ local ssl = require "spec.internal.ssl"
+
+ local params = {
+ mode = "server",
+ protocol = "any",
+ key = "spec/fixtures/kong_spec.key",
+ certificate = "spec/fixtures/kong_spec.crt",
+ }
+
+ client = ssl.wrap(client, params)
+ client:dohandshake()
+ end
+
+ line, err = client:receive()
+ if err == "closed" then
+ fails = fails + 1
+
+ else
+ if not handshake_done then
+ assert(line == "\\START")
+ client:send("\\OK\n")
+ handshake_done = true
+
+ else
+ if line == "@DIE@" then
+ client:send(string.format("%d:%d\n", oks, fails))
+ client:close()
+ break
+ end
+
+ oks = oks + 1
+
+ client:send((opts.prefix or "") .. line .. "\n")
+ end
+
+ client:close()
+ end
+ end
+ server:close()
+ return line
+ end
+ }, port, opts)
+
+ local thr = thread:start()
+
+ -- not necessary for correctness because we do the handshake,
+ -- but avoids harmless "connection error" messages in the wait loop
+ -- in case the client is ready before the server below.
+ ngx.sleep(0.001)
+
+ local sock = ngx.socket.tcp()
+ sock:settimeout(0.01)
+ while true do
+ if sock:connect("localhost", port) then
+ sock:send("\\START\n")
+ local ok = sock:receive()
+ sock:close()
+ if ok == "\\OK" then
+ break
+ end
+ end
+ end
+ sock:close()
+
+ return thr
+end
+
+
+--- Stops a local TCP server.
+-- A server previously created with `tcp_server` can be stopped prematurely by
+-- calling this function.
+-- @function kill_tcp_server
+-- @param port the port the TCP server is listening on.
+-- @return oks, fails; the number of successes and failures processed by the server
+-- @see tcp_server
+local function kill_tcp_server(port)
+ local sock = ngx.socket.tcp()
+ assert(sock:connect("localhost", port))
+ assert(sock:send("@DIE@\n"))
+ local str = assert(sock:receive())
+ assert(sock:close())
+ local oks, fails = str:match("(%d+):(%d+)")
+ return tonumber(oks), tonumber(fails)
+end
+
+
+local code_status = {
+ [200] = "OK",
+ [201] = "Created",
+ [202] = "Accepted",
+ [203] = "Non-Authoritative Information",
+ [204] = "No Content",
+ [205] = "Reset Content",
+ [206] = "Partial Content",
+ [207] = "Multi-Status",
+ [300] = "Multiple Choices",
+ [301] = "Moved Permanently",
+ [302] = "Found",
+ [303] = "See Other",
+ [304] = "Not Modified",
+ [305] = "Use Proxy",
+ [307] = "Temporary Redirect",
+ [308] = "Permanent Redirect",
+ [400] = "Bad Request",
+ [401] = "Unauthorized",
+ [402] = "Payment Required",
+ [403] = "Forbidden",
+ [404] = "Not Found",
+ [405] = "Method Not Allowed",
+ [406] = "Not Acceptable",
+ [407] = "Proxy Authentication Required",
+ [408] = "Request Timeout",
+ [409] = "Conflict",
+ [410] = "Gone",
+ [411] = "Length Required",
+ [412] = "Precondition Failed",
+ [413] = "Payload Too Large",
+ [414] = "URI Too Long",
+ [415] = "Unsupported Media Type",
+ [416] = "Range Not Satisfiable",
+ [417] = "Expectation Failed",
+ [418] = "I'm a teapot",
+ [422] = "Unprocessable Entity",
+ [423] = "Locked",
+ [424] = "Failed Dependency",
+ [426] = "Upgrade Required",
+ [428] = "Precondition Required",
+ [429] = "Too Many Requests",
+ [431] = "Request Header Fields Too Large",
+ [451] = "Unavailable For Legal Reasons",
+ [500] = "Internal Server Error",
+ [501] = "Not Implemented",
+ [502] = "Bad Gateway",
+ [503] = "Service Unavailable",
+ [504] = "Gateway Timeout",
+ [505] = "HTTP Version Not Supported",
+ [506] = "Variant Also Negotiates",
+ [507] = "Insufficient Storage",
+ [508] = "Loop Detected",
+ [510] = "Not Extended",
+ [511] = "Network Authentication Required",
+}
+
+
+local EMPTY = {}
+
+
+local function handle_response(code, body, headers)
+ if not code then
+ code = 500
+ body = ""
+ headers = EMPTY
+ end
+
+ local head_str = ""
+
+ for k, v in pairs(headers or EMPTY) do
+ head_str = head_str .. k .. ": " .. v .. "\r\n"
+ end
+
+ return code .. " " .. code_status[code] .. " HTTP/1.1" .. "\r\n" ..
+ "Content-Length: " .. #body .. "\r\n" ..
+ "Connection: close\r\n" ..
+ head_str ..
+ "\r\n" ..
+ body
+end
+
+
+local function handle_request(client, response)
+ local lines = {}
+ local headers = {}
+ local line, err
+
+ local content_length
+ repeat
+ line, err = client:receive("*l")
+ if err then
+ return nil, err
+ else
+ local k, v = line:match("^([^:]+):%s*(.+)$")
+ if k then
+ headers[k] = v
+ if k:lower() == "content-length" then
+ content_length = tonumber(v)
+ end
+ end
+ table.insert(lines, line)
+ end
+ until line == ""
+
+ local method = lines[1]:match("^(%S+)%s+(%S+)%s+(%S+)$")
+ local method_lower = method:lower()
+
+ local body
+ if content_length then
+ body = client:receive(content_length)
+
+ elseif method_lower == "put" or method_lower == "post" then
+ body = client:receive("*a")
+ end
+
+ local response_str
+ local meta = getmetatable(response)
+ if type(response) == "function" or (meta and meta.__call) then
+ response_str = response(lines, body, headers)
+
+ elseif type(response) == "table" and response.code then
+ response_str = handle_response(response.code, response.body, response.headers)
+
+ elseif type(response) == "table" and response[1] then
+ response_str = handle_response(response[1], response[2], response[3])
+
+ elseif type(response) == "string" then
+ response_str = response
+
+ elseif response == nil then
+ response_str = "HTTP/1.1 200 OK\r\nConnection: close\r\n\r\n"
+ end
+
+
+ client:send(response_str)
+ return lines, body, headers
+end
+
+
+--- Start a local HTTP server with coroutine.
+--
+-- **DEPRECATED**: please use `spec.helpers.http_mock` instead.
+--
+-- local mock = helpers.http_mock(1234, { timeout = 0.1 })
+-- wait for a request, and respond with the custom response
+-- the request is returned as the function's return values
+-- return nil, err if error
+-- local lines, body, headers = mock(custom_response)
+-- local lines, body, headers = mock()
+-- mock("closing", true) -- close the server
+local function http_mock(port, opts)
+ local socket = require "socket"
+ local server = assert(socket.tcp())
+ if CONSTANTS.TEST_COVERAGE_MODE == "true" then
+ opts.timeout = CONSTANTS.TEST_COVERAGE_TIMEOUT
+ end
+ server:settimeout(opts and opts.timeout or 60)
+ assert(server:setoption('reuseaddr', true))
+ assert(server:bind("*", port))
+ assert(server:listen())
+ return coroutine.wrap(function(response, exit)
+ local lines, body, headers
+ -- start listening
+ while not exit do
+ local client, err = server:accept()
+ if err then
+ lines, body = false, err
+
+ else
+ lines, body, headers = handle_request(client, response)
+ client:close()
+ end
+
+ response, exit = coroutine.yield(lines, body, headers)
+ end
+
+ server:close()
+ return true
+ end)
+end
+
+
+--- Starts a local UDP server.
+-- Reads the specified number of packets and then closes.
+-- The server-thread return values depend on `n`:
+--
+-- * `n = 1`; returns the received packet (string), or `nil + err`
+--
+-- * `n > 1`; returns `data + err`, where `data` will always be a table with the
+-- received packets. So `err` must explicitly be checked for errors.
+-- @function udp_server
+-- @tparam[opt] number port The port the server will be listening on, default: `MOCK_UPSTREAM_PORT`
+-- @tparam[opt=1] number n The number of packets that will be read
+-- @tparam[opt=360] number timeout Timeout per read (default 360)
+-- @return A thread object (from the `llthreads2` Lua package)
+local function udp_server(port, n, timeout)
+ local threads = require "llthreads2.ex"
+
+ if CONSTANTS.TEST_COVERAGE_MODE == "true" then
+ timeout = CONSTANTS.TEST_COVERAGE_TIMEOUT
+ end
+
+ local thread = threads.new({
+ function(port, n, timeout)
+ local socket = require "socket"
+ local server = assert(socket.udp())
+ server:settimeout(timeout or 360)
+ server:setoption("reuseaddr", true)
+ server:setsockname("127.0.0.1", port)
+ local err
+ local data = {}
+ local handshake_done = false
+ local i = 0
+ while i < n do
+ local pkt, rport
+ pkt, err, rport = server:receivefrom()
+ if not pkt then
+ break
+ end
+ if pkt == "KONG_UDP_HELLO" then
+ if not handshake_done then
+ handshake_done = true
+ server:sendto("KONG_UDP_READY", "127.0.0.1", rport)
+ end
+ else
+ i = i + 1
+ data[i] = pkt
+ err = nil -- upon succes it would contain the remote ip address
+ end
+ end
+ server:close()
+ return (n > 1 and data or data[1]), err
+ end
+ }, port or CONSTANTS.MOCK_UPSTREAM_PORT, n or 1, timeout)
+ thread:start()
+
+ local socket = require "socket"
+ local handshake = socket.udp()
+ handshake:settimeout(0.01)
+ handshake:setsockname("127.0.0.1", 0)
+ while true do
+ handshake:sendto("KONG_UDP_HELLO", "127.0.0.1", port)
+ local data = handshake:receive()
+ if data == "KONG_UDP_READY" then
+ break
+ end
+ end
+ handshake:close()
+
+ return thread
+end
+
+
+local is_echo_server_ready, get_echo_server_received_data, echo_server_reset
+do
+ local shell = require("spec.internal.shell")
+ local cmd = require("spec.internal.cmd")
+
+ -- Message id is maintained within echo server context and not
+ -- needed for echo server user.
+ -- This id is extracted from the number in nginx error.log at each
+ -- line of log. i.e.:
+ -- 2023/12/15 14:10:12 [info] 718291#0: *303 stream [lua] content_by_lua ...
+ -- in above case, the id is 303.
+ local msg_id = -1
+ local prefix_dir = "servroot"
+
+ --- Check if echo server is ready.
+ --
+ -- @function is_echo_server_ready
+ -- @return boolean
+ function is_echo_server_ready()
+ -- ensure server is ready.
+ local sock = ngx.socket.tcp()
+ sock:settimeout(0.1)
+ local retry = 0
+ local test_port = 8188
+
+ while true do
+ if sock:connect("localhost", test_port) then
+ sock:send("START\n")
+ local ok = sock:receive()
+ sock:close()
+ if ok == "START" then
+ return true
+ end
+ else
+ retry = retry + 1
+ if retry > 10 then
+ return false
+ end
+ end
+ end
+ end
+
+ --- Get the echo server's received data.
+ -- This function check the part of expected data with a timeout.
+ --
+ -- @function get_echo_server_received_data
+ -- @param expected part of the data expected.
+ -- @param timeout (optional) timeout in seconds, default is 0.5.
+ -- @return the data the echo server received. If timeouts, return "timeout".
+ function get_echo_server_received_data(expected, timeout)
+ if timeout == nil then
+ timeout = 0.5
+ end
+
+ local extract_cmd = "grep content_by_lua "..prefix_dir.."/logs/error.log | tail -1"
+ local _, _, log = assert(shell.exec(extract_cmd))
+ local pattern = "%*(%d+)%s.*received data: (.*)"
+ local cur_msg_id, data = string.match(log, pattern)
+
+ -- unit is second.
+ local t = 0.1
+ local time_acc = 0
+
+ -- retry it when data is not available. because sometime,
+ -- the error.log has not been flushed yet.
+ while string.find(data, expected) == nil or cur_msg_id == msg_id do
+ ngx.sleep(t)
+ time_acc = time_acc + t
+ if time_acc >= timeout then
+ return "timeout"
+ end
+
+ _, _, log = assert(shell.exec(extract_cmd))
+ cur_msg_id, data = string.match(log, pattern)
+ end
+
+ -- update the msg_id, it persists during a cycle from echo server
+ -- start to stop.
+ msg_id = cur_msg_id
+
+ return data
+ end
+
+ function echo_server_reset()
+ cmd.stop_kong(prefix_dir)
+ msg_id = -1
+ end
+end
+
+
+return {
+ tcp_server = tcp_server,
+ kill_tcp_server = kill_tcp_server,
+
+ http_mock = http_mock,
+
+ udp_server = udp_server,
+
+ is_echo_server_ready = is_echo_server_ready,
+ echo_server_reset = echo_server_reset,
+ get_echo_server_received_data = get_echo_server_received_data,
+}
diff --git a/kong-versions/3.9.0.0/kong/spec/internal/shell.lua b/kong-versions/3.9.0.0/kong/spec/internal/shell.lua
new file mode 100644
index 00000000..a592b27c
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/internal/shell.lua
@@ -0,0 +1,110 @@
+-- This software is copyright Kong Inc. and its licensors.
+-- Use of the software is subject to the agreement between your organization
+-- and Kong Inc. If there is no such agreement, use is governed by and
+-- subject to the terms of the Kong Master Software License Agreement found
+-- at https://konghq.com/enterprisesoftwarelicense/.
+-- [ END OF LICENSE 0867164ffc95e54f04670b5169c09574bdbd9bba ]
+
+------------------------------------------------------------------
+-- Collection of utilities to help testing Kong features and plugins.
+--
+-- @copyright Copyright 2016-2022 Kong Inc. All rights reserved.
+-- @license [Apache 2.0](https://opensource.org/licenses/Apache-2.0)
+-- @module spec.helpers
+
+
+local shell = require("resty.shell")
+local strip = require("kong.tools.string").strip
+
+
+local CONSTANTS = require("spec.internal.constants")
+local conf = require("spec.internal.conf")
+
+
+----------------
+-- Shell helpers
+-- @section Shell-helpers
+
+--- Execute a command.
+-- Modified version of `pl.utils.executeex()` so the output can directly be
+-- used on an assertion.
+-- @function execute
+-- @param cmd command string to execute
+-- @param returns (optional) boolean: if true, this function will
+-- return the same values as Penlight's executeex.
+-- @return if `returns` is true, returns four return values
+-- (ok, code, stdout, stderr); if `returns` is false,
+-- returns either (false, stderr) or (true, stderr, stdout).
+local function exec(cmd, returns)
+ --100MB for retrieving stdout & stderr
+ local ok, stdout, stderr, _, code = shell.run(cmd, nil, 0, 1024*1024*100)
+ if returns then
+ return ok, code, stdout, stderr
+ end
+ if not ok then
+ stdout = nil -- don't return 3rd value if fail because of busted's `assert`
+ end
+ return ok, stderr, stdout
+end
+
+
+--- Execute a Kong command.
+-- @function kong_exec
+-- @param cmd Kong command to execute, eg. `start`, `stop`, etc.
+-- @param env (optional) table with kong parameters to set as environment
+-- variables, overriding the test config (each key will automatically be
+-- prefixed with `KONG_` and be converted to uppercase)
+-- @param returns (optional) boolean: if true, this function will
+-- return the same values as Penlight's `executeex`.
+-- @param env_vars (optional) a string prepended to the command, so
+-- that arbitrary environment variables may be passed
+-- @return if `returns` is true, returns four return values
+-- (ok, code, stdout, stderr); if `returns` is false,
+-- returns either (false, stderr) or (true, stderr, stdout).
+local function kong_exec(cmd, env, returns, env_vars)
+ cmd = cmd or ""
+ env = env or {}
+
+ -- Insert the Lua path to the custom-plugin fixtures
+ do
+ local function cleanup(t)
+ if t then
+ t = strip(t)
+ if t:sub(-1,-1) == ";" then
+ t = t:sub(1, -2)
+ end
+ end
+ return t ~= "" and t or nil
+ end
+ local paths = {}
+ table.insert(paths, cleanup(CONSTANTS.CUSTOM_PLUGIN_PATH))
+ table.insert(paths, cleanup(CONSTANTS.CUSTOM_VAULT_PATH))
+ table.insert(paths, cleanup(env.lua_package_path))
+ table.insert(paths, cleanup(conf.lua_package_path))
+ env.lua_package_path = table.concat(paths, ";")
+ -- note; the nginx config template will add a final ";;", so no need to
+ -- include that here
+ end
+
+ if not env.plugins then
+ env.plugins = "bundled,dummy,cache,rewriter,error-handler-log," ..
+ "error-generator,error-generator-last," ..
+ "short-circuit"
+ end
+
+ -- build Kong environment variables
+ env_vars = env_vars or ""
+ for k, v in pairs(env) do
+ env_vars = string.format("%s KONG_%s='%s'", env_vars, k:upper(), v)
+ end
+
+ return exec(env_vars .. " " .. CONSTANTS.BIN_PATH .. " " .. cmd, returns)
+end
+
+
+return {
+ run = shell.run,
+
+ exec = exec,
+ kong_exec = kong_exec,
+}
diff --git a/kong-versions/3.9.0.0/kong/spec/internal/ssl.lua b/kong-versions/3.9.0.0/kong/spec/internal/ssl.lua
new file mode 100644
index 00000000..b378c77f
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/internal/ssl.lua
@@ -0,0 +1,273 @@
+-- This software is copyright Kong Inc. and its licensors.
+-- Use of the software is subject to the agreement between your organization
+-- and Kong Inc. If there is no such agreement, use is governed by and
+-- subject to the terms of the Kong Master Software License Agreement found
+-- at https://konghq.com/enterprisesoftwarelicense/.
+-- [ END OF LICENSE 0867164ffc95e54f04670b5169c09574bdbd9bba ]
+
+local ffi = require "ffi"
+local C = ffi.C
+local bit = require "bit"
+local format_error = require("resty.openssl.err").format_error
+require "resty.openssl.include.ssl"
+
+ffi.cdef [[
+ typedef struct ssl_method_st SSL_METHOD;
+ const SSL_METHOD *TLS_method(void);
+ const SSL_METHOD *TLS_server_method(void);
+
+ SSL_CTX *SSL_CTX_new(const SSL_METHOD *method);
+ void SSL_CTX_free(SSL_CTX *ctx);
+
+ int SSL_CTX_use_certificate_chain_file(SSL_CTX *ctx, const char *file);
+ int SSL_CTX_use_PrivateKey_file(SSL_CTX *ctx, const char *file, int type);
+
+ SSL *SSL_new(SSL_CTX *ctx);
+ void SSL_free(SSL *s);
+
+ long SSL_ctrl(SSL *ssl, int cmd, long larg, void *parg);
+ long SSL_set_mode(SSL *ssl, long mode);
+
+ int SSL_set_fd(SSL *ssl, int fd);
+
+ void SSL_set_accept_state(SSL *ssl);
+
+ int SSL_do_handshake(SSL *ssl);
+ int SSL_get_error(const SSL *ssl, int ret);
+
+ int SSL_read(SSL *ssl, void *buf, int num);
+ int SSL_write(SSL *ssl, const void *buf, int num);
+ int SSL_shutdown(SSL *ssl);
+
+
+ typedef struct pollfd {
+ int fd; /* file descriptor */
+ short events; /* requested events */
+ short revents; /* returned events */
+ } pollfd;
+
+ int poll(struct pollfd *fds, unsigned long nfds, int timeout);
+]]
+
+
+local SSL = {}
+local ssl_mt = { __index = SSL }
+
+local modes = {
+ SSL_MODE_ENABLE_PARTIAL_WRITE = 0x001,
+ SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER = 0x002,
+ SSL_MODE_AUTO_RETRY = 0x004,
+ SSL_MODE_NO_AUTO_CHAIN = 0x008,
+ SSL_MODE_RELEASE_BUFFERS = 0x010,
+ SSL_MODE_SEND_CLIENTHELLO_TIME = 0x020,
+ SSL_MODE_SEND_SERVERHELLO_TIME = 0x040,
+ SSL_MODE_SEND_FALLBACK_SCSV = 0x080,
+ SSL_MODE_ASYNC = 0x100,
+ SSL_MODE_DTLS_SCTP_LABEL_LENGTH_BUG = 0x400,
+}
+
+local errors = {
+ SSL_ERROR_NONE = 0,
+ SSL_ERROR_SSL = 1,
+ SSL_ERROR_WANT_READ = 2,
+ SSL_ERROR_WANT_WRITE = 3,
+ SSL_ERROR_WANT_X509_LOOKUP = 4,
+ SSL_ERROR_SYSCALL = 5,
+ SSL_ERROR_ZERO_RETURN = 6,
+ SSL_ERROR_WANT_CONNECT = 7,
+ SSL_ERROR_WANT_ACCEPT = 8,
+ SSL_ERROR_WANT_ASYNC = 9,
+ SSL_ERROR_WANT_ASYNC_JOB = 10,
+ SSL_ERROR_WANT_CLIENT_HELLO_CB = 11,
+ SSL_ERROR_WANT_RETRY_VERIFY = 12,
+}
+
+local SOCKET_INVALID = -1
+local SSL_FILETYPE_PEM = 1
+
+local errors_literal = {}
+for k, v in pairs(errors) do
+ errors_literal[v] = k
+end
+
+local function ssl_set_mode(ctx, mode)
+ return C.SSL_ctrl(ctx, 33, mode, nil)
+end
+
+local function ssl_ctx_new(cfg)
+ if cfg.protocol and cfg.protocol ~= "any" then
+ return nil, "protocol other than 'any' is currently not supported"
+ elseif cfg.mode and cfg.mode ~= "server" then
+ return nil, "mode other than 'server' is currently not supported"
+ end
+ cfg.protocol = nil
+ cfg.mode = nil
+
+ local ctx = C.SSL_CTX_new(C.TLS_server_method())
+ if ctx == nil then
+ return nil, format_error("SSL_CTX_new")
+ end
+ ffi.gc(ctx, C.SSL_CTX_free)
+
+ for k, v in pairs(cfg) do
+ if k == "certificate" then
+ if C.SSL_CTX_use_certificate_chain_file(ctx, v) ~= 1 then
+ return nil, format_error("SSL_CTX_use_certificate_chain_file")
+ end
+ elseif k == "key" then -- password protected key is NYI
+ if C.SSL_CTX_use_PrivateKey_file(ctx, v, SSL_FILETYPE_PEM) ~= 1 then
+ return nil, format_error("SSL_CTX_use_PrivateKey_file")
+ end
+ else
+ return nil, "unknown option \"" .. k .. "\""
+ end
+ end
+
+ return ctx
+end
+
+local function ssl_new(ssl_ctx)
+ if not ssl_ctx or not ffi.istype("SSL_CTX*", ssl_ctx) then
+ return nil, "ssl_new: expect SSL_CTX* as first argument"
+ end
+
+ local ctx = C.SSL_new(ssl_ctx)
+ if ctx == nil then
+ return nil, format_error("SSL_new")
+ end
+ ffi.gc(ctx, C.SSL_free)
+
+ C.SSL_set_fd(ctx, SOCKET_INVALID)
+ ssl_set_mode(ctx, bit.bor(modes.SSL_MODE_ENABLE_PARTIAL_WRITE,
+ modes.SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER))
+ ssl_set_mode(ctx, modes.SSL_MODE_RELEASE_BUFFERS)
+
+ C.SSL_set_accept_state(ctx) -- me is server
+
+ return ctx
+end
+
+function SSL.wrap(sock, cfg)
+ local ctx, err
+ if type(cfg) == "table" then
+ ctx, err = ssl_ctx_new(cfg)
+ if not ctx then return nil, err end
+ else
+ ctx = cfg
+ end
+ local s, err = ssl_new(ctx)
+ if s then
+ local fd = sock:getfd()
+ C.SSL_set_fd(s, fd)
+
+ local self = setmetatable({
+ ssl_ctx = ctx,
+ ctx = s,
+ fd = fd,
+ sock = sock,
+ }, ssl_mt)
+
+ return self, nil
+ end
+ return nil, err
+end
+
+local function socket_waitfd(fd, events, timeout)
+ local pfd = ffi.new("pollfd")
+ pfd.fd = fd
+ pfd.events = events
+ pfd.revents = 0
+ local ppfd = ffi.new("pollfd[1]", pfd)
+
+ local wait = timeout and 1 or -1
+
+ while true do
+ local ret = C.poll(ppfd, 1, wait)
+ timeout = timeout and timeout - 1
+ if ret ~= -1 then
+ break
+ end
+ end
+end
+
+local POLLIN = 1
+local POLLOUT = 2
+
+local function handle_ssl_io(self, cb, ...)
+ local err, code
+ while true do
+ err = cb(self.ctx, ...)
+ code = C.SSL_get_error(self.ctx, err)
+ if code == errors.SSL_ERROR_NONE then
+ break
+ elseif code == errors.SSL_ERROR_WANT_READ then
+ err = socket_waitfd(self.fd, POLLIN, 10)
+ if err then return nil, "want read: " .. err end
+ elseif code == errors.SSL_ERROR_WANT_WRITE then
+ err = socket_waitfd(self.fd, POLLOUT, 10)
+ if err then return nil, "want write: " .. err end
+ elseif code == errors.SSL_ERROR_SYSCALL then
+ if err == 0 then
+ return nil, "closed"
+ end
+ if C.ERR_peek_error() then
+ return nil, format_error("SSL_ERROR_SYSCALL")
+ end
+ else
+ return nil, errors_literal[code] or "unknown error"
+ end
+ end
+end
+
+function SSL:dohandshake()
+ return handle_ssl_io(self, C.SSL_do_handshake)
+end
+
+
+function SSL:receive(pattern)
+ if pattern and pattern ~= "*l" then
+ return nil, "receive pattern other than '*l' is currently not supported"
+ end
+
+ local buf = ffi.new("char[1024]")
+ local ret = ""
+
+ while true do
+ local ok, err = handle_ssl_io(self, C.SSL_read, ffi.cast("void *", buf), 1024)
+ if err then
+ if err == "SSL_ERROR_ZERO_RETURN" then
+ err = "closed"
+ end
+ return ok, err
+ end
+
+ local current = ffi.string(buf)
+ -- do we need to find \r?
+ local pos = current:find("\n")
+ if pos then -- found a newline
+ ret = ret .. current:sub(1, pos-1)
+ break
+ else
+ ret = ret .. current
+ end
+ end
+
+ return ret
+end
+
+function SSL:send(s)
+ local buf = ffi.new("char[?]", #s+1, s)
+ local ok, err = handle_ssl_io(self, C.SSL_write, ffi.cast("void *", buf), #s)
+ if err then
+ return ok, err
+ end
+
+ return true
+end
+
+function SSL:close()
+ self.sock:close()
+ return true
+end
+
+return SSL
diff --git a/kong-versions/3.9.0.0/kong/spec/internal/sys.lua b/kong-versions/3.9.0.0/kong/spec/internal/sys.lua
new file mode 100644
index 00000000..63d911a5
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/internal/sys.lua
@@ -0,0 +1,50 @@
+-- This software is copyright Kong Inc. and its licensors.
+-- Use of the software is subject to the agreement between your organization
+-- and Kong Inc. If there is no such agreement, use is governed by and
+-- subject to the terms of the Kong Master Software License Agreement found
+-- at https://konghq.com/enterprisesoftwarelicense/.
+-- [ END OF LICENSE 0867164ffc95e54f04670b5169c09574bdbd9bba ]
+
+------------------------------------------------------------------
+-- Collection of utilities to help testing Kong features and plugins.
+--
+-- @copyright Copyright 2016-2022 Kong Inc. All rights reserved.
+-- @license [Apache 2.0](https://opensource.org/licenses/Apache-2.0)
+-- @module spec.helpers
+
+
+local ffi = require("ffi")
+
+
+ffi.cdef [[
+ int setenv(const char *name, const char *value, int overwrite);
+ int unsetenv(const char *name);
+]]
+
+
+--- Set an environment variable
+-- @function setenv
+-- @param env (string) name of the environment variable
+-- @param value the value to set
+-- @return true on success, false otherwise
+local function setenv(env, value)
+ assert(type(env) == "string", "env must be a string")
+ assert(type(value) == "string", "value must be a string")
+ return ffi.C.setenv(env, value, 1) == 0
+end
+
+
+--- Unset an environment variable
+-- @function unsetenv
+-- @param env (string) name of the environment variable
+-- @return true on success, false otherwise
+local function unsetenv(env)
+ assert(type(env) == "string", "env must be a string")
+ return ffi.C.unsetenv(env) == 0
+end
+
+
+return {
+ setenv = setenv,
+ unsetenv = unsetenv,
+}
diff --git a/kong-versions/3.9.0.0/kong/spec/internal/wait.lua b/kong-versions/3.9.0.0/kong/spec/internal/wait.lua
new file mode 100644
index 00000000..51651caf
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/internal/wait.lua
@@ -0,0 +1,719 @@
+-- This software is copyright Kong Inc. and its licensors.
+-- Use of the software is subject to the agreement between your organization
+-- and Kong Inc. If there is no such agreement, use is governed by and
+-- subject to the terms of the Kong Master Software License Agreement found
+-- at https://konghq.com/enterprisesoftwarelicense/.
+-- [ END OF LICENSE 0867164ffc95e54f04670b5169c09574bdbd9bba ]
+
+------------------------------------------------------------------
+-- Collection of utilities to help testing Kong features and plugins.
+--
+-- @copyright Copyright 2016-2022 Kong Inc. All rights reserved.
+-- @license [Apache 2.0](https://opensource.org/licenses/Apache-2.0)
+-- @module spec.helpers
+
+
+local cjson = require("cjson.safe")
+local lfs = require("lfs")
+local pl_file = require("pl.file")
+local luassert = require("luassert.assert")
+local https_server = require("spec.fixtures.https_server")
+
+
+local CONSTANTS = require("spec.internal.constants")
+local shell = require("spec.internal.shell")
+local asserts = require("spec.internal.asserts") -- luacheck: ignore
+local client = require("spec.internal.client")
+
+
+local get_available_port
+do
+ local USED_PORTS = {}
+
+ function get_available_port()
+ for _i = 1, 10 do
+ local port = math.random(10000, 30000)
+
+ if not USED_PORTS[port] then
+ USED_PORTS[port] = true
+
+ local ok = shell.run("netstat -lnt | grep \":" .. port .. "\" > /dev/null", nil, 0)
+
+ if not ok then
+ -- return code of 1 means `grep` did not found the listening port
+ return port
+
+ else
+ print("Port " .. port .. " is occupied, trying another one")
+ end
+ end
+ end
+
+ error("Could not find an available port after 10 tries")
+ end
+end
+
+
+--------------------
+-- Custom assertions
+--
+-- @section assertions
+
+require("spec.helpers.wait")
+
+--- Waits until a specific condition is met.
+-- The check function will repeatedly be called (with a fixed interval), until
+-- the condition is met. Throws an error on timeout.
+--
+-- NOTE: this is a regular Lua function, not a Luassert assertion.
+-- @function wait_until
+-- @param f check function that should return `truthy` when the condition has
+-- been met
+-- @param timeout (optional) maximum time to wait after which an error is
+-- thrown, defaults to 5.
+-- @param step (optional) interval between checks, defaults to 0.05.
+-- @return nothing. It returns when the condition is met, or throws an error
+-- when it times out.
+-- @usage
+-- -- wait 10 seconds for a file "myfilename" to appear
+-- helpers.wait_until(function() return file_exist("myfilename") end, 10)
+local function wait_until(f, timeout, step)
+ if CONSTANTS.TEST_COVERAGE_MODE == "true" then
+ timeout = CONSTANTS.TEST_COVERAGE_TIMEOUT
+ end
+
+ luassert.wait_until({
+ condition = "truthy",
+ fn = f,
+ timeout = timeout,
+ step = step,
+ })
+end
+
+
+--- Waits until no Lua error occurred
+-- The check function will repeatedly be called (with a fixed interval), until
+-- there is no Lua error occurred
+--
+-- NOTE: this is a regular Lua function, not a Luassert assertion.
+-- @function pwait_until
+-- @param f check function
+-- @param timeout (optional) maximum time to wait after which an error is
+-- thrown, defaults to 5.
+-- @param step (optional) interval between checks, defaults to 0.05.
+-- @return nothing. It returns when the condition is met, or throws an error
+-- when it times out.
+local function pwait_until(f, timeout, step)
+ if CONSTANTS.TEST_COVERAGE_MODE == "true" then
+ timeout = CONSTANTS.TEST_COVERAGE_TIMEOUT
+ end
+
+ luassert.wait_until({
+ condition = "no_error",
+ fn = f,
+ timeout = timeout,
+ step = step,
+ })
+end
+
+
+--- Wait for some timers, throws an error on timeout.
+--
+-- NOTE: this is a regular Lua function, not a Luassert assertion.
+-- @function wait_timer
+-- @tparam string timer_name_pattern the call will apply to all timers matching this string
+-- @tparam boolean plain if truthy, the `timer_name_pattern` will be matched plain, so without pattern matching
+-- @tparam string mode one of: "all-finish", "all-running", "any-finish", "any-running", or "worker-wide-all-finish"
+--
+-- any-finish: At least one of the timers that were matched finished
+--
+-- all-finish: All timers that were matched finished
+--
+-- any-running: At least one of the timers that were matched is running
+--
+-- all-running: All timers that were matched are running
+--
+-- worker-wide-all-finish: All the timers in the worker that were matched finished
+-- @tparam number timeout maximum time to wait (optional, default: 2)
+-- @tparam number admin_client_timeout, to override the default timeout setting (optional)
+-- @tparam number forced_admin_port to override the default port of admin API (optional)
+-- @usage helpers.wait_timer("rate-limiting", true, "all-finish", 10)
+local function wait_timer(timer_name_pattern, plain,
+ mode, timeout,
+ admin_client_timeout, forced_admin_port)
+ if not timeout then
+ timeout = 2
+ end
+
+ local _admin_client
+
+ local all_running_each_worker = nil
+ local all_finish_each_worker = nil
+ local any_running_each_worker = nil
+ local any_finish_each_worker = nil
+
+ wait_until(function ()
+ if _admin_client then
+ _admin_client:close()
+ end
+
+ _admin_client = client.admin_client(admin_client_timeout, forced_admin_port)
+ local res = assert(_admin_client:get("/timers"))
+ local body = luassert.res_status(200, res)
+ local json = assert(cjson.decode(body))
+ local worker_id = json.worker.id
+ local worker_count = json.worker.count
+
+ if not all_running_each_worker then
+ all_running_each_worker = {}
+ all_finish_each_worker = {}
+ any_running_each_worker = {}
+ any_finish_each_worker = {}
+
+ for i = 0, worker_count - 1 do
+ all_running_each_worker[i] = false
+ all_finish_each_worker[i] = false
+ any_running_each_worker[i] = false
+ any_finish_each_worker[i] = false
+ end
+ end
+
+ local is_matched = false
+
+ for timer_name, timer in pairs(json.stats.timers) do
+ if string.find(timer_name, timer_name_pattern, 1, plain) then
+ is_matched = true
+
+ all_finish_each_worker[worker_id] = false
+
+ if timer.is_running then
+ all_running_each_worker[worker_id] = true
+ any_running_each_worker[worker_id] = true
+ goto continue
+ end
+
+ all_running_each_worker[worker_id] = false
+
+ goto continue
+ end
+
+ ::continue::
+ end
+
+ if not is_matched then
+ any_finish_each_worker[worker_id] = true
+ all_finish_each_worker[worker_id] = true
+ end
+
+ local all_running = false
+
+ local all_finish = false
+ local all_finish_worker_wide = true
+
+ local any_running = false
+ local any_finish = false
+
+ for _, v in pairs(all_running_each_worker) do
+ all_running = all_running or v
+ end
+
+ for _, v in pairs(all_finish_each_worker) do
+ all_finish = all_finish or v
+ all_finish_worker_wide = all_finish_worker_wide and v
+ end
+
+ for _, v in pairs(any_running_each_worker) do
+ any_running = any_running or v
+ end
+
+ for _, v in pairs(any_finish_each_worker) do
+ any_finish = any_finish or v
+ end
+
+ if mode == "all-running" then
+ return all_running
+ end
+
+ if mode == "all-finish" then
+ return all_finish
+ end
+
+ if mode == "worker-wide-all-finish" then
+ return all_finish_worker_wide
+ end
+
+ if mode == "any-finish" then
+ return any_finish
+ end
+
+ if mode == "any-running" then
+ return any_running
+ end
+
+ error("unexpected error")
+ end, timeout)
+end
+
+
+--- Waits for invalidation of a cached key by polling the mgt-api
+-- and waiting for a 404 response. Throws an error on timeout.
+--
+-- NOTE: this is a regular Lua function, not a Luassert assertion.
+-- @function wait_for_invalidation
+-- @param key (string) the cache-key to check
+-- @param timeout (optional) in seconds (for default see `wait_until`).
+-- @return nothing. It returns when the key is invalidated, or throws an error
+-- when it times out.
+-- @usage
+-- local cache_key = "abc123"
+-- helpers.wait_for_invalidation(cache_key, 10)
+local function wait_for_invalidation(key, timeout)
+ -- TODO: this code is duplicated all over the codebase,
+ -- search codebase for "/cache/" endpoint
+ local api_client = client.admin_client()
+ wait_until(function()
+ local res = api_client:get("/cache/" .. key)
+ res:read_body()
+ return res.status == 404
+ end, timeout)
+end
+
+
+--- Wait for all targets, upstreams, services, and routes update
+--
+-- NOTE: this function is not available for DBless-mode
+-- @function wait_for_all_config_update
+-- @tparam[opt] table opts a table contains params
+-- @tparam[opt=30] number opts.timeout maximum seconds to wait, defatuls is 30
+-- @tparam[opt] number opts.admin_client_timeout to override the default timeout setting
+-- @tparam[opt] number opts.forced_admin_port to override the default Admin API port
+-- @tparam[opt] bollean opts.stream_enabled to enable stream module
+-- @tparam[opt] number opts.proxy_client_timeout to override the default timeout setting
+-- @tparam[opt] number opts.forced_proxy_port to override the default proxy port
+-- @tparam[opt] number opts.stream_port to set the stream port
+-- @tparam[opt] string opts.stream_ip to set the stream ip
+-- @tparam[opt=false] boolean opts.override_global_rate_limiting_plugin to override the global rate-limiting plugin in waiting
+-- @tparam[opt=false] boolean opts.override_global_key_auth_plugin to override the global key-auth plugin in waiting
+local function wait_for_all_config_update(opts)
+ opts = opts or {}
+ if CONSTANTS.TEST_COVERAGE_MODE == "true" then
+ opts.timeout = CONSTANTS.TEST_COVERAGE_TIMEOUT
+ end
+ local timeout = opts.timeout or 30
+ local admin_client_timeout = opts.admin_client_timeout
+ local forced_admin_port = opts.forced_admin_port
+ local proxy_client_timeout = opts.proxy_client_timeout
+ local forced_proxy_port = opts.forced_proxy_port
+ local stream_port = opts.stream_port
+ local stream_ip = opts.stream_ip
+ local stream_enabled = opts.stream_enabled or false
+ local override_rl = opts.override_global_rate_limiting_plugin or false
+ local override_auth = opts.override_global_key_auth_plugin or false
+ local headers = opts.override_default_headers or { ["Content-Type"] = "application/json" }
+ local disable_ipv6 = opts.disable_ipv6 or false
+
+ local function call_admin_api(method, path, body, expected_status, headers)
+ local client = client.admin_client(admin_client_timeout, forced_admin_port)
+
+ local res
+
+ if string.upper(method) == "POST" then
+ res = client:post(path, {
+ headers = headers,
+ body = body,
+ })
+
+ elseif string.upper(method) == "DELETE" then
+ res = client:delete(path, {
+ headers = headers
+ })
+ end
+
+ local ok, json_or_nil_or_err = pcall(function ()
+ assert(res.status == expected_status, "unexpected response code: " .. res.status)
+
+ if string.upper(method) == "DELETE" then
+ return
+ end
+
+ local json = cjson.decode((res:read_body()))
+ assert(json ~= nil, "unexpected response body")
+ return json
+ end)
+
+ client:close()
+
+ assert(ok, json_or_nil_or_err)
+
+ return json_or_nil_or_err
+ end
+
+ local upstream_id, target_id, service_id, route_id
+ local stream_upstream_id, stream_target_id, stream_service_id, stream_route_id
+ local consumer_id, rl_plugin_id, key_auth_plugin_id, credential_id
+ local upstream_name = "really.really.really.really.really.really.really.mocking.upstream.test"
+ local service_name = "really-really-really-really-really-really-really-mocking-service"
+ local stream_upstream_name = "stream-really.really.really.really.really.really.really.mocking.upstream.test"
+ local stream_service_name = "stream-really-really-really-really-really-really-really-mocking-service"
+ local route_path = "/really-really-really-really-really-really-really-mocking-route"
+ local key_header_name = "really-really-really-really-really-really-really-mocking-key"
+ local consumer_name = "really-really-really-really-really-really-really-mocking-consumer"
+ local test_credentials = "really-really-really-really-really-really-really-mocking-credentials"
+
+ local host = "localhost"
+ local port = get_available_port()
+
+ local server = https_server.new(port, host, "http", nil, 1, nil, disable_ipv6)
+
+ server:start()
+
+ -- create mocking upstream
+ local res = assert(call_admin_api("POST",
+ "/upstreams",
+ { name = upstream_name },
+ 201, headers))
+ upstream_id = res.id
+
+ -- create mocking target to mocking upstream
+ res = assert(call_admin_api("POST",
+ string.format("/upstreams/%s/targets", upstream_id),
+ { target = host .. ":" .. port },
+ 201, headers))
+ target_id = res.id
+
+ -- create mocking service to mocking upstream
+ res = assert(call_admin_api("POST",
+ "/services",
+ { name = service_name, url = "http://" .. upstream_name .. "/always_200" },
+ 201, headers))
+ service_id = res.id
+
+ -- create mocking route to mocking service
+ res = assert(call_admin_api("POST",
+ string.format("/services/%s/routes", service_id),
+ { paths = { route_path }, strip_path = true, path_handling = "v0",},
+ 201, headers))
+ route_id = res.id
+
+ if override_rl then
+ -- create rate-limiting plugin to mocking mocking service
+ res = assert(call_admin_api("POST",
+ string.format("/services/%s/plugins", service_id),
+ { name = "rate-limiting", config = { minute = 999999, policy = "local" } },
+ 201, headers))
+ rl_plugin_id = res.id
+ end
+
+ if override_auth then
+ -- create key-auth plugin to mocking mocking service
+ res = assert(call_admin_api("POST",
+ string.format("/services/%s/plugins", service_id),
+ { name = "key-auth", config = { key_names = { key_header_name } } },
+ 201, headers))
+ key_auth_plugin_id = res.id
+
+ -- create consumer
+ res = assert(call_admin_api("POST",
+ "/consumers",
+ { username = consumer_name },
+ 201, headers))
+ consumer_id = res.id
+
+ -- create credential to key-auth plugin
+ res = assert(call_admin_api("POST",
+ string.format("/consumers/%s/key-auth", consumer_id),
+ { key = test_credentials },
+ 201, headers))
+ credential_id = res.id
+ end
+
+ if stream_enabled then
+ -- create mocking upstream
+ local res = assert(call_admin_api("POST",
+ "/upstreams",
+ { name = stream_upstream_name },
+ 201, headers))
+ stream_upstream_id = res.id
+
+ -- create mocking target to mocking upstream
+ res = assert(call_admin_api("POST",
+ string.format("/upstreams/%s/targets", stream_upstream_id),
+ { target = host .. ":" .. port },
+ 201, headers))
+ stream_target_id = res.id
+
+ -- create mocking service to mocking upstream
+ res = assert(call_admin_api("POST",
+ "/services",
+ { name = stream_service_name, url = "tcp://" .. stream_upstream_name },
+ 201, headers))
+ stream_service_id = res.id
+
+ -- create mocking route to mocking service
+ res = assert(call_admin_api("POST",
+ string.format("/services/%s/routes", stream_service_id),
+ { destinations = { { port = stream_port }, }, protocols = { "tcp" },},
+ 201, headers))
+ stream_route_id = res.id
+ end
+
+ local ok, err = pcall(function ()
+ -- wait for mocking route ready
+ pwait_until(function ()
+ local proxy = client.proxy_client(proxy_client_timeout, forced_proxy_port)
+
+ if override_auth then
+ res = proxy:get(route_path, { headers = { [key_header_name] = test_credentials } })
+
+ else
+ res = proxy:get(route_path)
+ end
+
+ local ok, err = pcall(assert, res.status == 200)
+ proxy:close()
+ assert(ok, err)
+ end, timeout / 2)
+
+ if stream_enabled then
+ pwait_until(function ()
+ local proxy = client.proxy_client(proxy_client_timeout, stream_port, stream_ip)
+
+ res = proxy:get("/always_200")
+ local ok, err = pcall(assert, res.status == 200)
+ proxy:close()
+ assert(ok, err)
+ end, timeout)
+ end
+ end)
+ if not ok then
+ server:shutdown()
+ error(err)
+ end
+
+ -- delete mocking configurations
+ if override_auth then
+ call_admin_api("DELETE", string.format("/consumers/%s/key-auth/%s", consumer_id, credential_id), nil, 204, headers)
+ call_admin_api("DELETE", string.format("/consumers/%s", consumer_id), nil, 204, headers)
+ call_admin_api("DELETE", "/plugins/" .. key_auth_plugin_id, nil, 204, headers)
+ end
+
+ if override_rl then
+ call_admin_api("DELETE", "/plugins/" .. rl_plugin_id, nil, 204, headers)
+ end
+
+ call_admin_api("DELETE", "/routes/" .. route_id, nil, 204, headers)
+ call_admin_api("DELETE", "/services/" .. service_id, nil, 204, headers)
+ call_admin_api("DELETE", string.format("/upstreams/%s/targets/%s", upstream_id, target_id), nil, 204, headers)
+ call_admin_api("DELETE", "/upstreams/" .. upstream_id, nil, 204, headers)
+
+ if stream_enabled then
+ call_admin_api("DELETE", "/routes/" .. stream_route_id, nil, 204, headers)
+ call_admin_api("DELETE", "/services/" .. stream_service_id, nil, 204, headers)
+ call_admin_api("DELETE", string.format("/upstreams/%s/targets/%s", stream_upstream_id, stream_target_id), nil, 204, headers)
+ call_admin_api("DELETE", "/upstreams/" .. stream_upstream_id, nil, 204, headers)
+ end
+
+ ok, err = pcall(function ()
+ -- wait for mocking configurations to be deleted
+ pwait_until(function ()
+ local proxy = client.proxy_client(proxy_client_timeout, forced_proxy_port)
+ res = proxy:get(route_path)
+ local ok, err = pcall(assert, res.status == 404)
+ proxy:close()
+ assert(ok, err)
+ end, timeout / 2)
+ end)
+
+ server:shutdown()
+
+ if not ok then
+ error(err)
+ end
+
+end
+
+
+--- Waits for a file to meet a certain condition
+-- The check function will repeatedly be called (with a fixed interval), until
+-- there is no Lua error occurred
+--
+-- NOTE: this is a regular Lua function, not a Luassert assertion.
+-- @function wait_for_file
+-- @tparam string mode one of:
+--
+-- "file", "directory", "link", "socket", "named pipe", "char device", "block device", "other"
+--
+-- @tparam string path the file path
+-- @tparam[opt=10] number timeout maximum seconds to wait
+local function wait_for_file(mode, path, timeout)
+ pwait_until(function()
+ local result, err = lfs.attributes(path, "mode")
+ local msg = string.format("failed to wait for the mode (%s) of '%s': %s",
+ mode, path, tostring(err))
+ assert(result == mode, msg)
+ end, timeout or 10)
+end
+
+
+local wait_for_file_contents
+do
+ --- Wait until a file exists and is non-empty.
+ --
+ -- If, after the timeout is reached, the file does not exist, is not
+ -- readable, or is empty, an assertion error will be raised.
+ --
+ -- @function wait_for_file_contents
+ -- @param fname the filename to wait for
+ -- @param timeout (optional) maximum time to wait after which an error is
+ -- thrown, defaults to 10.
+ -- @return contents the file contents, as a string
+ function wait_for_file_contents(fname, timeout)
+ assert(type(fname) == "string",
+ "filename must be a string")
+
+ timeout = timeout or 10
+ assert(type(timeout) == "number" and timeout >= 0,
+ "timeout must be nil or a number >= 0")
+
+ local data = pl_file.read(fname)
+ if data and #data > 0 then
+ return data
+ end
+
+ pcall(wait_until, function()
+ data = pl_file.read(fname)
+ return data and #data > 0
+ end, timeout)
+
+ assert(data, "file (" .. fname .. ") does not exist or is not readable"
+ .. " after " .. tostring(timeout) .. " seconds")
+
+ assert(#data > 0, "file (" .. fname .. ") exists but is empty after " ..
+ tostring(timeout) .. " seconds")
+
+ return data
+ end
+end
+
+
+-- XXX EE [[
+--- Wait until no common workers.
+-- This will wait until all the worker PID's listed have gone (others may have appeared). If an `expected_total` is specified, it will also wait until the new workers have reached this number.
+-- @function wait_until_no_common_workers
+-- @tparam table workers an array of worker PID's (the return value of `get_kong_workers`)
+-- @tparam[opt] number expected_total the expected total workers count
+-- @tparam[opt] table wait_opts options to use, the available fields are:
+-- @tparam[opt] number wait_opts.timeout timeout passed to `wait_until`
+-- @tparam[opt] number wait_opts.step step passed to `wait_until`
+local function wait_until_no_common_workers(workers, expected_total, wait_opts)
+ wait_opts = wait_opts or {}
+ wait_until(function()
+ local pok, admin_client = pcall(client.admin_client)
+ if not pok then
+ return false
+ end
+ local res = assert(admin_client:send {
+ method = "GET",
+ path = "/",
+ })
+ luassert.res_status(200, res)
+ local json = cjson.decode(luassert.res_status(200, res))
+ admin_client:close()
+
+ local new_workers = json.pids.workers
+ local total = 0
+ local common = 0
+ if new_workers then
+ for _, v in ipairs(new_workers) do
+ total = total + 1
+ for _, v_old in ipairs(workers) do
+ if v == v_old then
+ common = common + 1
+ break
+ end
+ end
+ end
+ end
+ return common == 0 and total == (expected_total or total)
+ end, wait_opts.timeout, wait_opts.step)
+end
+-- XXX EE ]]
+
+
+--- Gets the Kong workers PID's.
+-- Will wait for a successful call to the admin-api for a maximum of 10 seconds,
+-- before returning a timeout.
+-- @function get_kong_workers
+-- @tparam[opt] number expected_total the expected total workers count
+-- @return array of worker PID's
+local function get_kong_workers(expected_total)
+ local workers
+
+ wait_until(function()
+ local pok, admin_client = pcall(client.admin_client)
+ if not pok then
+ return false
+ end
+ local res = admin_client:send {
+ method = "GET",
+ path = "/",
+ }
+ if not res or res.status ~= 200 then
+ return false
+ end
+ local body = luassert.res_status(200, res)
+ local json = cjson.decode(body)
+
+ admin_client:close()
+
+ workers = {}
+
+ for _, item in ipairs(json.pids.workers) do
+ if item ~= ngx.null then
+ table.insert(workers, item)
+ end
+ end
+
+ if expected_total and #workers ~= expected_total then
+ return nil, ("expected %s worker pids, got %s"):format(expected_total,
+ #workers)
+
+ elseif #workers == 0 then
+ return nil, "GET / returned no worker pids"
+ end
+
+ return true
+ end, 10)
+ return workers
+end
+
+
+-- XXX EE [[
+--- Reload Kong and wait all workers are restarted.
+local function reload_kong(...)
+ local workers = get_kong_workers()
+ local ok, err = shell.kong_exec(...)
+ if ok then
+ local opts = { ... }
+ wait_until_no_common_workers(workers, 1, opts[2])
+ end
+ return ok, err
+end
+-- XXX EE ]]
+
+
+return {
+ get_available_port = get_available_port,
+
+ wait_until = wait_until,
+ pwait_until = pwait_until,
+ wait_timer = wait_timer,
+ wait_for_invalidation = wait_for_invalidation,
+ wait_for_all_config_update = wait_for_all_config_update,
+ wait_for_file = wait_for_file,
+ wait_for_file_contents = wait_for_file_contents,
+ wait_until_no_common_workers = wait_until_no_common_workers,
+
+ get_kong_workers = get_kong_workers,
+ reload_kong = reload_kong,
+}
diff --git a/kong-versions/3.9.0.0/kong/spec/kong_tests.conf b/kong-versions/3.9.0.0/kong/spec/kong_tests.conf
new file mode 100644
index 00000000..6f485bf1
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/kong_tests.conf
@@ -0,0 +1,74 @@
+# 1st digit is 9 for our test instances
+admin_gui_api_url = 127.0.0.1:9001
+admin_listen = 127.0.0.1:9001
+admin_gui_listen = off
+enforce_rbac = off
+proxy_listen = 0.0.0.0:9000, 0.0.0.0:9443 http2 ssl, 0.0.0.0:9002 http2, 0.0.0.0:9445 http2 ssl
+# avoid port conflicts when multiple Kong instances needed for tests
+status_listen = off
+stream_listen = off
+
+ssl_cert = spec/fixtures/kong_spec.crt
+ssl_cert_key = spec/fixtures/kong_spec.key
+
+admin_ssl_cert = spec/fixtures/kong_spec.crt
+admin_ssl_cert_key = spec/fixtures/kong_spec.key
+
+admin_gui_ssl_cert = spec/fixtures/kong_spec.crt
+admin_gui_ssl_cert_key = spec/fixtures/kong_spec.key
+
+portal = off
+portal_gui_listen = 0.0.0.0:9003, 0.0.0.0:9446 ssl
+portal_gui_protocol = http
+portal_gui_host = 127.0.0.1:9003
+portal_gui_ssl_cert = spec/fixtures/kong_spec.crt
+portal_gui_ssl_cert_key = spec/fixtures/kong_spec.key
+portal_api_listen = 0.0.0.0:9004, 0.0.0.0:9447 ssl
+portal_api_access_log = logs/portal_api_access.log
+portal_api_error_log = logs/portal_api_error.log
+portal_gui_access_log = logs/portal_gui_access.log
+portal_gui_error_log = logs/portal_gui_error.log
+proxy_url = http://127.0.0.1:9004
+portal_api_url = http://127.0.0.1:9004
+portal_api_ssl_cert = spec/fixtures/kong_spec.crt
+portal_api_ssl_cert_key = spec/fixtures/kong_spec.key
+
+smtp_mock = on
+
+database = postgres
+pg_host = 127.0.0.1
+pg_port = 5432
+pg_timeout = 15000
+pg_database = kong_tests
+# note: this does not trigger readonly mode to be enabled on its own
+# for that pg_ro_host is also needed
+pg_ro_user = kong_ro
+anonymous_reports = on
+
+worker_consistency = strict
+
+dedicated_config_processing = on
+
+dns_hostsfile = spec/fixtures/hosts
+resolver_hosts_file = spec/fixtures/hosts
+
+nginx_main_worker_processes = 1
+nginx_main_worker_rlimit_nofile = 4096
+nginx_events_worker_connections = 4096
+nginx_events_multi_accept = off
+
+plugins = bundled,dummy,cache,rewriter,error-handler-log,error-generator,error-generator-last,short-circuit
+
+prefix = servroot
+log_level = debug
+lua_package_path = ./spec/fixtures/custom_plugins/?.lua;./spec/fixtures/custom_vaults/?.lua;./spec/fixtures/custom_vaults/?/init.lua
+
+
+untrusted_lua = sandbox
+
+# temporarily disable hcv and aws due to loading dns issues
+vaults = env
+
+pg_password = foo\#bar# this is a comment that should be stripped
+
+wasm_filters_path = ./spec/fixtures/proxy_wasm_filters/build
diff --git a/kong-versions/3.9.0.0/kong/spec/ldoc.css b/kong-versions/3.9.0.0/kong/spec/ldoc.css
new file mode 100644
index 00000000..f6e3d99f
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/ldoc.css
@@ -0,0 +1,291 @@
+body {
+ color: #47555c;
+ font-size: 16px;
+ font-family: "Open Sans", sans-serif;
+ margin: 0;
+ background: #eff4ff;
+}
+
+a:link { color: #008fee; }
+a:visited { color: #008fee; }
+a:hover { color: #22a7ff; }
+
+h1 { font-size:26px; font-weight: normal; }
+h2 { font-size:22px; font-weight: normal; }
+h3 { font-size:18px; font-weight: normal; }
+h4 { font-size:16px; font-weight: bold; }
+
+hr {
+ height: 1px;
+ background: #c1cce4;
+ border: 0px;
+ margin: 15px 0;
+}
+
+code, tt {
+ font-family: monospace;
+}
+span.parameter {
+ font-family: monospace;
+ font-weight: bold;
+ color: rgb(99, 115, 131);
+}
+span.parameter:after {
+ content:":";
+}
+span.types:before {
+ content:"(";
+}
+span.types:after {
+ content:")";
+}
+.type {
+ font-weight: bold; font-style:italic
+}
+
+p.name {
+ font-family: "Andale Mono", monospace;
+}
+
+#navigation {
+ float: left;
+ background-color: white;
+ border-right: 1px solid #d3dbec;
+ border-bottom: 1px solid #d3dbec;
+
+ width: 14em;
+ vertical-align: top;
+ overflow: visible;
+}
+
+#navigation br {
+ display: none;
+}
+
+#navigation h1 {
+ background-color: white;
+ border-bottom: 1px solid #d3dbec;
+ padding: 15px;
+ margin-top: 0px;
+ margin-bottom: 0px;
+}
+
+#navigation h2 {
+ font-size: 18px;
+ background-color: white;
+ border-bottom: 1px solid #d3dbec;
+ padding-left: 15px;
+ padding-right: 15px;
+ padding-top: 10px;
+ padding-bottom: 10px;
+ margin-top: 30px;
+ margin-bottom: 0px;
+}
+
+#content h1 {
+ background-color: #2c3e67;
+ color: white;
+ padding: 15px;
+ margin: 0px;
+}
+
+#content h2 {
+ background-color: #6c7ea7;
+ color: white;
+ padding: 15px;
+ padding-top: 15px;
+ padding-bottom: 15px;
+ margin-top: 0px;
+}
+
+#content h2 a {
+ background-color: #6c7ea7;
+ color: white;
+ text-decoration: none;
+}
+
+#content h2 a:hover {
+ text-decoration: underline;
+}
+
+#content h3 {
+ font-style: italic;
+ padding-top: 15px;
+ padding-bottom: 4px;
+ margin-right: 15px;
+ margin-left: 15px;
+ margin-bottom: 5px;
+ border-bottom: solid 1px #bcd;
+}
+
+#content h4 {
+ margin-right: 15px;
+ margin-left: 15px;
+ border-bottom: solid 1px #bcd;
+}
+
+#content pre {
+ margin: 15px;
+}
+
+pre {
+ background-color: rgb(50, 55, 68);
+ color: white;
+ border-radius: 3px;
+ /* border: 1px solid #C0C0C0; /* silver */
+ padding: 15px;
+ overflow: auto;
+ font-family: "Andale Mono", monospace;
+}
+
+#content ul pre.example {
+ margin-left: 0px;
+}
+
+table.index {
+/* border: 1px #00007f; */
+}
+table.index td { text-align: left; vertical-align: top; }
+
+#navigation ul
+{
+ font-size:1em;
+ list-style-type: none;
+ margin: 1px 1px 10px 1px;
+ padding-left: 20px;
+}
+
+#navigation li {
+ text-indent: -1em;
+ display: block;
+ margin: 3px 0px 0px 22px;
+}
+
+#navigation li li a {
+ margin: 0px 3px 0px -1em;
+}
+
+#content {
+ margin-left: 14em;
+}
+
+#content p {
+ padding-left: 15px;
+ padding-right: 15px;
+}
+
+#content table {
+ padding-left: 15px;
+ padding-right: 15px;
+ background-color: white;
+}
+
+#content p, #content table, #content ol, #content ul, #content dl {
+ max-width: 900px;
+}
+
+#about {
+ padding: 15px;
+ padding-left: 16em;
+ background-color: white;
+ border-top: 1px solid #d3dbec;
+ border-bottom: 1px solid #d3dbec;
+}
+
+table.module_list, table.function_list {
+ border-width: 1px;
+ border-style: solid;
+ border-color: #cccccc;
+ border-collapse: collapse;
+ margin: 15px;
+}
+table.module_list td, table.function_list td {
+ border-width: 1px;
+ padding-left: 10px;
+ padding-right: 10px;
+ padding-top: 5px;
+ padding-bottom: 5px;
+ border: solid 1px rgb(193, 204, 228);
+}
+table.module_list td.name, table.function_list td.name {
+ background-color: white; min-width: 200px; border-right-width: 0px;
+}
+table.module_list td.summary, table.function_list td.summary {
+ background-color: white; width: 100%; border-left-width: 0px;
+}
+
+dl.function {
+ margin-right: 15px;
+ margin-left: 15px;
+ border-bottom: solid 1px rgb(193, 204, 228);
+ border-left: solid 1px rgb(193, 204, 228);
+ border-right: solid 1px rgb(193, 204, 228);
+ background-color: white;
+}
+
+dl.function dt {
+ color: rgb(99, 123, 188);
+ font-family: monospace;
+ border-top: solid 1px rgb(193, 204, 228);
+ padding: 15px;
+}
+
+dl.function dd {
+ margin-left: 15px;
+ margin-right: 15px;
+ margin-top: 5px;
+ margin-bottom: 15px;
+}
+
+#content dl.function dd h3 {
+ margin-top: 0px;
+ margin-left: 0px;
+ padding-left: 0px;
+ font-size: 16px;
+ color: rgb(128, 128, 128);
+ border-bottom: solid 1px #def;
+}
+
+#content dl.function dd ul, #content dl.function dd ol {
+ padding: 0px;
+ padding-left: 15px;
+ list-style-type: none;
+}
+
+ul.nowrap {
+ overflow:auto;
+ white-space:nowrap;
+}
+
+.section-description {
+ padding-left: 15px;
+ padding-right: 15px;
+}
+
+/* stop sublists from having initial vertical space */
+ul ul { margin-top: 0px; }
+ol ul { margin-top: 0px; }
+ol ol { margin-top: 0px; }
+ul ol { margin-top: 0px; }
+
+/* make the target distinct; helps when we're navigating to a function */
+a:target + * {
+ background-color: #FF9;
+}
+
+
+/* styles for prettification of source */
+pre .comment { color: #bbccaa; }
+pre .constant { color: #a8660d; }
+pre .escape { color: #844631; }
+pre .keyword { color: #ffc090; font-weight: bold; }
+pre .library { color: #0e7c6b; }
+pre .marker { color: #512b1e; background: #fedc56; font-weight: bold; }
+pre .string { color: #8080ff; }
+pre .number { color: #f8660d; }
+pre .operator { color: #2239a8; font-weight: bold; }
+pre .preprocessor, pre .prepro { color: #a33243; }
+pre .global { color: #c040c0; }
+pre .user-keyword { color: #800080; }
+pre .prompt { color: #558817; }
+pre .url { color: #272fc2; text-decoration: underline; }
diff --git a/kong-versions/3.9.0.0/kong/spec/on_demand_specs b/kong-versions/3.9.0.0/kong/spec/on_demand_specs
new file mode 100644
index 00000000..dc02f005
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/on_demand_specs
@@ -0,0 +1,4 @@
+# Whitelist regexes representing file paths that will not be tested during running busted CI
+spec/02-integration/05-proxy/10-balancer/05-stress.lua
+spec/03-plugins/16-jwt/fixtures.lua
+spec/04-perf/.*
diff --git a/kong-versions/3.9.0.0/kong/spec/renderdocs.sh b/kong-versions/3.9.0.0/kong/spec/renderdocs.sh
new file mode 100755
index 00000000..86cfe1f2
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/renderdocs.sh
@@ -0,0 +1,40 @@
+#!/bin/bash
+
+# auto-doc renderer
+#
+# will watch the spec directory and upon changes automatically
+# render the helper documentation using `ldoc .`
+# resulting docs are in ./spec/docs/index.html
+
+SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
+pushd $SCRIPT_DIR
+
+watched_files=$(find . -name '*.lua')
+
+if [ -z "$watched_files" ]; then
+ echo "Nothing to watch, abort"
+ exit 1
+else
+ echo "watching: $watched_files"
+fi
+
+previous_checksum="dummy"
+while true ; do
+ checksum=$(md5 $watched_files | md5)
+ if [ "$checksum" != "$previous_checksum" ]; then
+ ldoc .
+ result=$?
+ if [ $result -ne 0 ]; then
+ echo -e "\033[0;31mldoc failed, exitcode: $result\033[0m"
+ echo
+ else
+ echo
+ echo "docs updated at: $(pwd)/docs/index.html"
+ echo -e "\033[1;33mwatching for changes...\033[0m"
+ echo
+ fi
+ fi
+ previous_checksum="$checksum"
+ sleep 1
+done
+
diff --git a/kong-versions/3.9.0.0/kong/spec/require.lua b/kong-versions/3.9.0.0/kong/spec/require.lua
new file mode 100644
index 00000000..c7d2ce83
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/require.lua
@@ -0,0 +1,100 @@
+-- This software is copyright Kong Inc. and its licensors.
+-- Use of the software is subject to the agreement between your organization
+-- and Kong Inc. If there is no such agreement, use is governed by and
+-- subject to the terms of the Kong Master Software License Agreement found
+-- at https://konghq.com/enterprisesoftwarelicense/.
+-- [ END OF LICENSE 0867164ffc95e54f04670b5169c09574bdbd9bba ]
+
+-- Bundled from https://github.com/pygy/require.lua
+-- License MIT
+--- usage:
+-- require = require"require".require
+-- :o)
+
+local error, ipairs, newproxy, tostring, type
+ = error, ipairs, newproxy, tostring, type
+
+local t_concat = table.concat
+
+--- Helpers
+
+
+local function checkstring(s)
+ local t = type(s)
+ if t == "string" then
+ return s
+ elseif t == "number" then
+ return tostring(s)
+ else
+ error("bad argument #1 to 'require' (string expected, got "..t..")", 3)
+ end
+end
+
+--- for Lua 5.1
+
+local package, p_loaded, setmetatable = package, package.loaded, setmetatable
+
+local sentinel do
+ local function errhandler() error("the require() sentinel can't be indexed or updated", 2) end
+ sentinel = newproxy and newproxy() or setmetatable({}, {__index = errhandler, __newindex = errhandler, __metatable = false})
+end
+
+local function require51 (name)
+ name = checkstring(name)
+ if p_loaded[name] == sentinel then
+ error("loop or previous error loading module '"..name.."'", 2)
+ end
+
+ local module = p_loaded[name]
+ if module then return module end
+
+ local msg = {}
+ local loader
+ for _, searcher in ipairs(package.loaders) do
+ loader = searcher(name)
+ if type(loader) == "function" then break end
+ if type(loader) == "string" then
+ -- `loader` is actually an error message
+ msg[#msg + 1] = loader
+ end
+ loader = nil
+ end
+ if loader == nil then
+ error("module '" .. name .. "' not found: "..t_concat(msg), 2)
+ end
+ p_loaded[name] = sentinel
+ local res = loader(name)
+ if res ~= nil then
+ module = res
+ elseif p_loaded[name] == sentinel or not p_loaded[name] then
+ module = true
+ else
+ module = p_loaded[name]
+ end
+
+ p_loaded[name] = module
+ return module
+end
+
+local module = {
+ VERSION = "0.1.8",
+ require51 = require51,
+}
+
+if _VERSION == "Lua 5.1" then module.require = require51 end
+
+--- rerequire :o)
+
+for _, o in ipairs{
+ {"rerequiredefault", require},
+ {"rerequire", module.require},
+ {"rerequire51", require51},
+} do
+ local rereq, req = o[1], o[2]
+ module[rereq] = function(name)
+ p_loaded[name] = nil
+ return req(name)
+ end
+end
+
+return module
diff --git a/kong-versions/3.9.0.0/kong/spec/upgrade_helpers.lua b/kong-versions/3.9.0.0/kong/spec/upgrade_helpers.lua
new file mode 100644
index 00000000..142f7ebd
--- /dev/null
+++ b/kong-versions/3.9.0.0/kong/spec/upgrade_helpers.lua
@@ -0,0 +1,270 @@
+-- This software is copyright Kong Inc. and its licensors.
+-- Use of the software is subject to the agreement between your organization
+-- and Kong Inc. If there is no such agreement, use is governed by and
+-- subject to the terms of the Kong Master Software License Agreement found
+-- at https://konghq.com/enterprisesoftwarelicense/.
+-- [ END OF LICENSE 0867164ffc95e54f04670b5169c09574bdbd9bba ]
+
+local say = require "say"
+local assert = require "luassert"
+
+local busted = require "busted"
+
+local conf_loader = require "kong.conf_loader"
+local DB = require "kong.db"
+local helpers = require "spec.helpers"
+local utils = require "kong.tools.utils"
+
+local conf = conf_loader()
+
+local function database_type()
+ return conf['database']
+end
+
+local function get_database()
+ local db = assert(DB.new(conf))
+ assert(db:init_connector())
+ return db
+end
+
+
+local function database_has_relation(state, arguments)
+ local table_name = arguments[1]
+ local schema = arguments[2] or "public"
+ local db = get_database()
+ local res, err
+ if database_type() == 'postgres' then
+ res, err = db.connector:query(string.format(
+ "select true"
+ .. " from pg_tables"
+ .. " where tablename = '%s'"
+ .. " and schemaname = '%s'",
+ table_name, schema))
+ else
+ return false
+ end
+ if err then
+ return false
+ end
+ return not(not(res[1]))
+end
+
+say:set("assertion.database_has_relation.positive", "Expected schema to have table %s")
+say:set("assertion.database_has_relation.negative", "Expected schema not to have table %s")
+assert:register("assertion", "database_has_relation", database_has_relation, "assertion.database_has_relation.positive", "assertion.database_has_relation.negative")
+
+
+local function database_has_trigger(state, arguments)
+ local trigger_name = arguments[1]
+ local db = get_database()
+ local res, err
+ if database_type() == 'postgres' then
+ res, err = db.connector:query(string.format(
+ "select true"
+ .. " from pg_trigger"
+ .. " where tgname = '%s'",
+ trigger_name))
+ else
+ return false
+ end
+ if err then
+ return false
+ end
+ return not(not(res[1]))
+end
+
+say:set("assertion.database_has_trigger.positive", "Expected database to have trigger %s")
+say:set("assertion.database_has_trigger.negative", "Expected database not to have trigger %s")
+assert:register("assertion", "database_has_trigger", database_has_trigger, "assertion.database_has_trigger.positive", "assertion.database_has_trigger.negative")
+
+
+local function table_has_column(state, arguments)
+ local table = arguments[1]
+ local column_name = arguments[2]
+ local postgres_type = arguments[3]
+ local db = get_database()
+ local res, err
+ if database_type() == 'postgres' then
+ res, err = db.connector:query(string.format(
+ "select true"
+ .. " from information_schema.columns"
+ .. " where table_schema = 'public'"
+ .. " and table_name = '%s'"
+ .. " and column_name = '%s'"
+ .. " and data_type = '%s'",
+ table, column_name, postgres_type))
+ else
+ return false
+ end
+ if err then
+ return false
+ end
+ return not(not(res[1]))
+end
+
+say:set("assertion.table_has_column.positive", "Expected table %s to have column %s with type %s")
+say:set("assertion.table_has_column.negative", "Expected table %s not to have column %s with type %s")
+assert:register("assertion", "table_has_column", table_has_column, "assertion.table_has_column.positive", "assertion.table_has_column.negative")
+
+local function table_has_index(state, arguments)
+ local table = arguments[1]
+ local index_name = arguments[2]
+ local db = get_database()
+ local res, err
+ if database_type() == 'postgres' then
+ res, err = db.connector:query(string.format(
+ "select true"
+ .. " from pg_indexes"
+ .. " where schemaname = 'public'"
+ .. " and tablename = '%s'"
+ .. " and indexname = '%s'",
+ table, index_name))
+ else
+ return false
+ end
+ if err then
+ return false
+ end
+ return not(not(res[1]))
+end
+
+say:set("assertion.table_has_index.positive", "Expected table %s to have index %s")
+say:set("assertion.table_has_index.negative", "Expected table %s not to index %s")
+assert:register("assertion", "table_has_index", table_has_index, "assertion.table_has_index.positive", "assertion.table_has_index.negative")
+
+local upstream_server_url = "http://" .. helpers.mock_upstream_host .. ":" .. helpers.mock_upstream_port .. "/"
+
+local function create_example_service()
+ local admin_client = assert(helpers.admin_client())
+ local res = assert(admin_client:send {
+ method = "POST",
+ path = "/services/",
+ body = {
+ name = "example-service",
+ url = upstream_server_url
+ },
+ headers = {
+ ["Content-Type"] = "application/json"
+ }
+ })
+ assert.res_status(201, res)
+ res = assert(admin_client:send {
+ method = "POST",
+ path = "/services/example-service/routes",
+ body = {
+ hosts = { "example.com" },
+ },
+ headers = {
+ ["Content-Type"] = "application/json"
+ }
+ })
+ assert.res_status(201, res)
+ admin_client:close()
+end
+
+local function send_proxy_get_request()
+ local proxy_client = assert(helpers.proxy_client())
+ local res = assert(proxy_client:send {
+ method = "GET",
+ headers = {
+ ["Host"] = "example.com",
+ },
+ path = "/",
+ })
+ local body = assert.res_status(200, res)
+ proxy_client:close()
+
+ return res, body
+end
+
+local function start_kong(options)
+ local enabled_plugins = os.getenv('KONG_PLUGINS') or "bundled"
+
+ return helpers.start_kong(utils.table_merge({
+ database = database_type(),
+ dns_resolver = "",
+ proxy_listen = "0.0.0.0:9000",
+ admin_listen = "0.0.0.0:9001",
+ admin_ssl = false,
+ admin_gui_ssl = false,
+ plugins = enabled_plugins,
+ nginx_conf = "spec/fixtures/custom_nginx.template",
+ }, options))
+end
+
+local function it_when(phase, phrase, f)
+ return busted.it(phrase .. " #" .. phase, f)
+end
+
+local function setup(f)
+ return busted.it("setting up kong #setup", f)
+end
+
+local function old_after_up(phrase, f)
+ return it_when("old_after_up", phrase, f)
+end
+
+local function new_after_up(phrase, f)
+ return it_when("new_after_up", phrase, f)
+end
+
+local function new_after_finish(phrase, f)
+ return it_when("new_after_finish", phrase, f)
+end
+
+local function all_phases(phrase, f)
+ return it_when("all_phases", phrase, f)
+end
+
+
+--- Get a Busted test handler for migration tests.
+--
+-- This convenience function determines the appropriate Busted handler
+-- (`busted.describe` or `busted.pending`) based on the "old Kong version"
+-- that migrations are running on and the specified version range.
+--
+-- @function get_busted_handler
+-- @param min_version The minimum Kong version (inclusive)
+-- @param max_version The maximum Kong version (inclusive)
+-- @return `busted.describe` if Kong's version is within the specified range,
+-- `busted.pending` otherwise.
+-- @usage
+-- local handler = get_busted_handler("3.3.0", "3.6.0")
+-- handler("some migration test", function() ... end)
+local get_busted_handler
+do
+ local function get_version_num(v1, v2)
+ if v2 then
+ assert(#v2 == #v1, string.format("different version format: %s and %s", v1, v2))
+ end
+ return assert(tonumber((v1:gsub("[%.x]", ""))), "invalid version: " .. v1)
+ end
+
+ function get_busted_handler(min_version, max_version)
+ local old_version_var = assert(os.getenv("OLD_KONG_VERSION"), "old version not set")
+ local old_version = string.match(old_version_var, "[^/]+$")
+
+ local old_version_num = get_version_num(old_version)
+ local min_v_num = min_version and get_version_num(min_version, old_version) or 0
+ local max_v_num = max_version and get_version_num(max_version, old_version) or math.huge
+
+ return old_version_num >= min_v_num and old_version_num <= max_v_num and busted.describe or busted.pending
+ end
+end
+
+return {
+ database_type = database_type,
+ get_database = get_database,
+ create_example_service = create_example_service,
+ send_proxy_get_request = send_proxy_get_request,
+ start_kong = start_kong,
+ stop_kong = helpers.stop_kong,
+ admin_client = helpers.admin_client,
+ proxy_client = helpers.proxy_client,
+ setup = setup,
+ old_after_up = old_after_up,
+ new_after_up = new_after_up,
+ new_after_finish = new_after_finish,
+ all_phases = all_phases,
+ get_busted_handler = get_busted_handler,
+}