├── .chglog
├── CHANGELOG.tpl.md
└── config.yml
├── .github
├── dependabot.yml
└── workflows
│ └── python-package.yml
├── .gitignore
├── CHANGELOG.md
├── LICENSE
├── README.md
├── docs
├── Makefile
├── README.md
├── make.bat
├── requirements.txt
├── run.sh
└── source
│ ├── conf.py
│ ├── index.rst
│ ├── kong.client.rst
│ ├── kong.ctx.rst
│ ├── kong.enterprise_edition.rst
│ ├── kong.nginx.rst
│ ├── kong.rst
│ ├── kong.service.rst
│ └── modules.rst
├── examples
├── py-hello.py
└── py-image.py
├── kong-pluginserver
├── kong-pluginserver.py
├── kong_pdk
├── __init__.py
├── cli.py
├── const.py
├── exception.py
├── kong.py
├── listener.py
├── logger.py
├── module.py
├── pdk
│ ├── __init__.py
│ └── kong
│ │ ├── __init__.py
│ │ ├── client
│ │ ├── __init__.py
│ │ └── tls.py
│ │ ├── cluster.py
│ │ ├── ctx
│ │ ├── __init__.py
│ │ └── shared.py
│ │ ├── enterprise_edition
│ │ ├── __init__.py
│ │ └── jwe.py
│ │ ├── ip.py
│ │ ├── log.py
│ │ ├── nginx
│ │ ├── __init__.py
│ │ └── shared.py
│ │ ├── node.py
│ │ ├── plugin.py
│ │ ├── request.py
│ │ ├── response.py
│ │ ├── router.py
│ │ ├── service
│ │ ├── __init__.py
│ │ ├── request.py
│ │ └── response.py
│ │ ├── telemetry.py
│ │ └── vault.py
└── server.py
├── requirements.txt
├── scripts
└── prepare_new_release.sh
├── setup.cfg
└── setup.py
/.chglog/CHANGELOG.tpl.md:
--------------------------------------------------------------------------------
1 | {{ if .Versions -}}
2 |
3 | ## [Unreleased]
4 |
5 | {{ if .Unreleased.CommitGroups -}}
6 | {{ range .Unreleased.CommitGroups -}}
7 | ### {{ .Title }}
8 | {{ range .Commits -}}
9 | - {{ if .Scope }}**{{ .Scope }}:** {{ end }}{{ .Subject }}
10 | {{ end }}
11 | {{ end -}}
12 | {{ end -}}
13 | {{ end -}}
14 |
15 | {{ range .Versions }}
16 |
17 | ## {{ if .Tag.Previous }}[{{ .Tag.Name }}]{{ else }}{{ .Tag.Name }}{{ end }} - {{ datetime "2006-01-02" .Tag.Date }}
18 | {{ range .CommitGroups -}}
19 | ### {{ lower .Title }}
20 | {{ range .Commits -}}
21 | - {{ if .Scope }}**{{ .Scope }}:** {{ end }}{{ .Subject }} [{{ .Hash.Short }}]({{ $.Info.RepositoryURL }}/commit/{{ .Hash.Long }})
22 | {{ end }}
23 | {{ end -}}
24 |
25 | {{- if .NoteGroups -}}
26 | {{ range .NoteGroups -}}
27 | ### {{ .Title }}
28 | {{ range .Notes }}
29 | {{ .Body }}
30 | {{ end }}
31 | {{ end -}}
32 | {{ end -}}
33 | {{ end -}}
34 |
35 | {{- if .Versions }}
36 | [Unreleased]: {{ .Info.RepositoryURL }}/compare/{{ $latest := index .Versions 0 }}{{ $latest.Tag.Name }}...HEAD
37 | {{ range .Versions -}}
38 | {{ if .Tag.Previous -}}
39 | [{{ .Tag.Name }}]: {{ $.Info.RepositoryURL }}/compare/{{ .Tag.Previous.Name }}...{{ .Tag.Name }}
40 | {{ end -}}
41 | {{ end -}}
42 | {{ end -}}
43 |
--------------------------------------------------------------------------------
/.chglog/config.yml:
--------------------------------------------------------------------------------
1 | style: github
2 | template: CHANGELOG.tpl.md
3 | info:
4 | title: CHANGELOG
5 | repository_url: https://github.com/Kong/kong-python-pdk
6 | options:
7 | sort: "semver"
8 | commits:
9 | filters:
10 | Type:
11 | - feat
12 | - fix
13 | - refactor
14 | commit_groups:
15 | title_maps:
16 | feat: Features
17 | fix: Bug Fixes
18 | perf: Performance Improvements
19 | refactor: Code Refactoring
20 | header:
21 | pattern: "^(\\w*)(?:\\([\\w\\$\\.\\-\\*\\s\\/]*\\)|:)?:?\\s(.*)$"
22 | pattern_maps:
23 | - Type
24 | - Subject
25 | notes:
26 | keywords:
27 | - BREAKING CHANGE
28 |
--------------------------------------------------------------------------------
/.github/dependabot.yml:
--------------------------------------------------------------------------------
1 | ---
2 | version: 2
3 | updates:
4 | - package-ecosystem: pip
5 | directory: /
6 | schedule:
7 | interval: daily
8 | - package-ecosystem: github-actions
9 | directory: /
10 | schedule:
11 | interval: daily
12 |
--------------------------------------------------------------------------------
/.github/workflows/python-package.yml:
--------------------------------------------------------------------------------
1 | # This workflow will install Python dependencies, run tests and lint with a variety of Python versions
2 | # For more information see: https://help.github.com/actions/language-and-framework-guides/using-python-with-github-actions
3 |
4 | name: Python package
5 |
6 | on:
7 | push:
8 | branches: [ master ]
9 | pull_request:
10 | branches: [ master ]
11 |
12 | jobs:
13 | flake8-lint:
14 | runs-on: ubuntu-latest
15 | steps:
16 | - name: Check out source repository
17 | uses: actions/checkout@v3.5.3
18 | - name: Set up Python environment
19 | uses: actions/setup-python@v4.6.1
20 | with:
21 | python-version: "3.8"
22 | - name: flake8 Lint
23 | uses: py-actions/flake8@v2
24 | with:
25 | exclude: "docs,kong_pdk/pdk/kong"
26 | build:
27 |
28 | runs-on: ubuntu-latest
29 | strategy:
30 | fail-fast: false
31 | matrix:
32 | python-version: ['3.7', '3.8', '3.9', '3.10']
33 |
34 | steps:
35 | - uses: actions/checkout@v3.5.3
36 | - name: Set up Python ${{ matrix.python-version }}
37 | uses: actions/setup-python@v4.6.1
38 | with:
39 | python-version: ${{ matrix.python-version }}
40 | - name: Cache pip
41 | uses: actions/cache@v3.3.1
42 | with:
43 | path: ~/.cache/pip
44 | key: ${{ runner.os }}-pip-${{ hashFiles('requirements.txt') }}
45 | restore-keys: |
46 | ${{ runner.os }}-pip-
47 | - name: Install dependencies
48 | run: |
49 | python -m pip install --upgrade pip
50 | pip install -r requirements.txt
51 |
52 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Byte-compiled / optimized / DLL files
2 | __pycache__/
3 | *.py[cod]
4 | *$py.class
5 |
6 | # C extensions
7 | *.so
8 |
9 | # Distribution / packaging
10 | .Python
11 | build/
12 | develop-eggs/
13 | dist/
14 | downloads/
15 | eggs/
16 | .eggs/
17 | lib/
18 | lib64/
19 | parts/
20 | sdist/
21 | var/
22 | wheels/
23 | pip-wheel-metadata/
24 | share/python-wheels/
25 | *.egg-info/
26 | .installed.cfg
27 | *.egg
28 | MANIFEST
29 |
30 | # PyInstaller
31 | # Usually these files are written by a python script from a template
32 | # before PyInstaller builds the exe, so as to inject date/other infos into it.
33 | *.manifest
34 | *.spec
35 |
36 | # Installer logs
37 | pip-log.txt
38 | pip-delete-this-directory.txt
39 |
40 | # Unit test / coverage reports
41 | htmlcov/
42 | .tox/
43 | .nox/
44 | .coverage
45 | .coverage.*
46 | .cache
47 | nosetests.xml
48 | coverage.xml
49 | *.cover
50 | *.py,cover
51 | .hypothesis/
52 | .pytest_cache/
53 |
54 | # Translations
55 | *.mo
56 | *.pot
57 |
58 | # Django stuff:
59 | *.log
60 | local_settings.py
61 | db.sqlite3
62 | db.sqlite3-journal
63 |
64 | # Flask stuff:
65 | instance/
66 | .webassets-cache
67 |
68 | # Scrapy stuff:
69 | .scrapy
70 |
71 | # Sphinx documentation
72 | docs/_build/
73 |
74 | # PyBuilder
75 | target/
76 |
77 | # Jupyter Notebook
78 | .ipynb_checkpoints
79 |
80 | # IPython
81 | profile_default/
82 | ipython_config.py
83 |
84 | # pyenv
85 | .python-version
86 |
87 | # pipenv
88 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
89 | # However, in case of collaboration, if having platform-specific dependencies or dependencies
90 | # having no cross-platform support, pipenv may install dependencies that don't work, or not
91 | # install all needed dependencies.
92 | #Pipfile.lock
93 |
94 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow
95 | __pypackages__/
96 |
97 | # Celery stuff
98 | celerybeat-schedule
99 | celerybeat.pid
100 |
101 | # SageMath parsed files
102 | *.sage.py
103 |
104 | # Environments
105 | .env
106 | .venv
107 | env/
108 | venv/
109 | ENV/
110 | env.bak/
111 | venv.bak/
112 |
113 | # Spyder project settings
114 | .spyderproject
115 | .spyproject
116 |
117 | # Rope project settings
118 | .ropeproject
119 |
120 | # mkdocs documentation
121 | /site
122 |
123 | # mypy
124 | .mypy_cache/
125 | .dmypy.json
126 | dmypy.json
127 |
128 | # Pyre type checker
129 | .pyre/
130 |
131 | docs/build/html
132 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 |
2 | ## [Unreleased]
3 |
4 |
5 |
6 | ## [0.6.0] - 2024-10-10
7 | ### bug fixes
8 | - add missing file enterprise_edition [7b9d281](https://github.com/Kong/kong-python-pdk/commit/7b9d28196c8fc4718a6ad79f0164d243de57af8a)
9 | - delete message queue when they are not needed any more ([#122](https://github.com/Kong/kong-python-pdk/issues/122)) [ffeb2f2](https://github.com/Kong/kong-python-pdk/commit/ffeb2f2185a107f0e6547c4336905fe5dd01bfd0)
10 | - serialize error and disable strict_map_key to allow ([#117](https://github.com/Kong/kong-python-pdk/issues/117)) [25db61c](https://github.com/Kong/kong-python-pdk/commit/25db61cf650b5b8e86e2df066f6bd5282e7c8b48)
11 |
12 |
13 |
14 | ## [0.3.2] - 2022-11-08
15 | ### bug fixes
16 | - add version field in PluginInfo rpc ([#79](https://github.com/Kong/kong-python-pdk/issues/79)) [132f31d](https://github.com/Kong/kong-python-pdk/commit/132f31d526ff3589ac9b93dc079adb18359519cd)
17 |
18 |
19 |
20 | ## [0.3.1] - 2022-06-13
21 | ### bug fixes
22 | - plugin closure syntax correction ([#64](https://github.com/Kong/kong-python-pdk/issues/64)) [920cc26](https://github.com/Kong/kong-python-pdk/commit/920cc26acb84ac357411a5d1d7232a6a540fb9f3)
23 | - removing upper() to allow matching of attributes ([#69](https://github.com/Kong/kong-python-pdk/issues/69)) [1997a6c](https://github.com/Kong/kong-python-pdk/commit/1997a6c9991a6bc21d96d1a7f3c0141a43e01248)
24 | - [#50](https://github.com/Kong/kong-python-pdk/issues/50): return type of get_raw_bodys should be binary string [59ab367](https://github.com/Kong/kong-python-pdk/commit/59ab367c47a3fb56e85c90674d66749dcd4ab937)
25 | - catch error from PDK methods ([#53](https://github.com/Kong/kong-python-pdk/issues/53)) [7f82677](https://github.com/Kong/kong-python-pdk/commit/7f82677de3560c23c6c95bfaccaba6cd302aa571)
26 | - [#50](https://github.com/Kong/kong-python-pdk/issues/50): return type should support binary string [fdb2c9b](https://github.com/Kong/kong-python-pdk/commit/fdb2c9b51d3081cb605af056c3c49e2048061b4e)
27 |
28 |
29 |
30 | ## [0.3.0] - 2022-02-17
31 | ### bug fixes
32 | - add option to use python style error handling to be consistent with style headers [39a75bd](https://github.com/Kong/kong-python-pdk/commit/39a75bd3b060dbda9aec4e84afa01ae6c3000fed)
33 | - include correct instances list in get_status [56d7ad7](https://github.com/Kong/kong-python-pdk/commit/56d7ad762b07d780068384cc1072d3a54f373083)
34 | - exit immediately from kong.response.{error,exit} [ba3d5fa](https://github.com/Kong/kong-python-pdk/commit/ba3d5fae2b040804b1463585641919f76390feda)
35 |
36 |
37 |
38 | ## [0.2.7] - 2021-08-04
39 | ### bug fixes
40 | - correctly pass schema in embedded server [099a498](https://github.com/Kong/kong-python-pdk/commit/099a4987d06602b094274ffd523300daa7985b5a)
41 | - no longer normalize hyphens in socket name in embedded server to keep consistent with what Kong expects [20c01da](https://github.com/Kong/kong-python-pdk/commit/20c01dae1f422e577ec107904f47a57e18788508)
42 | - listener to use msgpack.Unpacker iterrator [bed56c4](https://github.com/Kong/kong-python-pdk/commit/bed56c49160d1adb0e591f69b74337ced7820dba)
43 | - use .py file for type hint ([#13](https://github.com/Kong/kong-python-pdk/issues/13)) [1bf3820](https://github.com/Kong/kong-python-pdk/commit/1bf3820e316f73d6021897b5979af4826e9f34d6)
44 |
45 |
46 |
47 | ## [0.2.4] - 2021-06-17
48 | ### bug fixes
49 | - check correct flags existence in dedicated server ([#10](https://github.com/Kong/kong-python-pdk/issues/10)) [b18dd45](https://github.com/Kong/kong-python-pdk/commit/b18dd458def039a6a2dad4c42baa7b55d64fe027)
50 | - set larger listen queue size ([#9](https://github.com/Kong/kong-python-pdk/issues/9)) [a3eb340](https://github.com/Kong/kong-python-pdk/commit/a3eb3404a42a106cdc4a164ee2c12dcafab90684)
51 |
52 |
53 |
54 | ## [0.2.3] - 2021-05-13
55 | ### bug fixes
56 | - display defaults on cli and print PluginServerException to warning [13991ec](https://github.com/Kong/kong-python-pdk/commit/13991ec5d6373463d847c5ef073543568c0894bb)
57 | - skip running cleanup timer [e10c098](https://github.com/Kong/kong-python-pdk/commit/e10c098a5f4c959f6fce4fc74c3d987443e386bc)
58 | - standarlize error on instance not found [0dfc94f](https://github.com/Kong/kong-python-pdk/commit/0dfc94f3a6cf4ffc90cd2edb8891b1264d26b27c)
59 |
60 | ### features
61 | - add response phase ([#4](https://github.com/Kong/kong-python-pdk/issues/4)) [3aca283](https://github.com/Kong/kong-python-pdk/commit/3aca2836a63eaa6bee09c76777c8cdb39a495c39)
62 |
63 |
64 |
65 | ## [0.2.2] - 2021-03-29
66 | ### bug fixes
67 | - correct license in setup.py ([#3](https://github.com/Kong/kong-python-pdk/issues/3)) [b257c98](https://github.com/Kong/kong-python-pdk/commit/b257c98298343e2911de35d89dc44c1cb0f59547)
68 | - threading mode pipe and styles [6f73ac7](https://github.com/Kong/kong-python-pdk/commit/6f73ac76c6f3fc49081ba67b62e0d9ea4547cbb1)
69 | - enable plugin server without gevent mode [a29c4d7](https://github.com/Kong/kong-python-pdk/commit/a29c4d765fb9e2dfa1a8b27fccb333864a61d529)
70 |
71 | ### features
72 | - add typed interfaces [f98e44d](https://github.com/Kong/kong-python-pdk/commit/f98e44d75271d5daceaf00f8f011ce7efaa19865)
73 |
74 |
75 |
76 | ## [0.2.1] - 2021-02-24
77 | ### bug fixes
78 | - disable gevent in multiprocessing and make it optional [5b6fb68](https://github.com/Kong/kong-python-pdk/commit/5b6fb682d9237ebb75bc653c0536678f3efe7d67)
79 | - chmod+x on examples [1f5905d](https://github.com/Kong/kong-python-pdk/commit/1f5905dc879528c519411b2914e20e2b5236e749)
80 |
81 | ### features
82 | - set friendly process title [aa59083](https://github.com/Kong/kong-python-pdk/commit/aa59083e6ede0394fdf2cb25f9925a36a7cc5aae)
83 | - multiprocessing mode [1a97d26](https://github.com/Kong/kong-python-pdk/commit/1a97d26e773c399149f12bee08943821a3dd9c7b)
84 |
85 |
86 |
87 | ## [0.2.0] - 2021-02-22
88 | ### bug fixes
89 | - sync with Kong 2.3 update [d42de7e](https://github.com/Kong/kong-python-pdk/commit/d42de7ef9565f316890aad3132e432e6a04c77f7)
90 |
91 | ### code refactoring
92 | - rename kong_pluginserver to kong_pdk [e802627](https://github.com/Kong/kong-python-pdk/commit/e802627436e4b856a16e4d68b9329914f2a3a4cc)
93 |
94 | ### features
95 | - exit server if parent is dead [0ee2183](https://github.com/Kong/kong-python-pdk/commit/0ee2183c5679d9cc255435ff98c82d28fbf22f5b)
96 | - embed server in plugin [af55deb](https://github.com/Kong/kong-python-pdk/commit/af55deb6d2f65a8a2be654cd4c8d7f13247869ee)
97 |
98 |
99 |
100 | ## [0.1.2] - 2020-02-21
101 | ### bug fixes
102 | - python2 compatibility [0e4cf1c](https://github.com/Kong/kong-python-pdk/commit/0e4cf1cda574db778e8152b30359e6e9927b0432)
103 |
104 |
105 |
106 | ## [0.1.1] - 2020-02-20
107 |
108 |
109 | ## 0.1.0 - 2020-01-03
110 |
111 | [Unreleased]: https://github.com/Kong/kong-python-pdk/compare/0.6.0...HEAD
112 | [0.6.0]: https://github.com/Kong/kong-python-pdk/compare/0.3.2...0.6.0
113 | [0.3.2]: https://github.com/Kong/kong-python-pdk/compare/0.3.1...0.3.2
114 | [0.3.1]: https://github.com/Kong/kong-python-pdk/compare/0.3.0...0.3.1
115 | [0.3.0]: https://github.com/Kong/kong-python-pdk/compare/0.2.7...0.3.0
116 | [0.2.7]: https://github.com/Kong/kong-python-pdk/compare/0.2.4...0.2.7
117 | [0.2.4]: https://github.com/Kong/kong-python-pdk/compare/0.2.3...0.2.4
118 | [0.2.3]: https://github.com/Kong/kong-python-pdk/compare/0.2.2...0.2.3
119 | [0.2.2]: https://github.com/Kong/kong-python-pdk/compare/0.2.1...0.2.2
120 | [0.2.1]: https://github.com/Kong/kong-python-pdk/compare/0.2.0...0.2.1
121 | [0.2.0]: https://github.com/Kong/kong-python-pdk/compare/0.1.2...0.2.0
122 | [0.1.2]: https://github.com/Kong/kong-python-pdk/compare/0.1.1...0.1.2
123 | [0.1.1]: https://github.com/Kong/kong-python-pdk/compare/0.1.0...0.1.1
124 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 |
2 | Apache License
3 | Version 2.0, January 2004
4 | http://www.apache.org/licenses/
5 |
6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
7 |
8 | 1. Definitions.
9 |
10 | "License" shall mean the terms and conditions for use, reproduction,
11 | and distribution as defined by Sections 1 through 9 of this document.
12 |
13 | "Licensor" shall mean the copyright owner or entity authorized by
14 | the copyright owner that is granting the License.
15 |
16 | "Legal Entity" shall mean the union of the acting entity and all
17 | other entities that control, are controlled by, or are under common
18 | control with that entity. For the purposes of this definition,
19 | "control" means (i) the power, direct or indirect, to cause the
20 | direction or management of such entity, whether by contract or
21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
22 | outstanding shares, or (iii) beneficial ownership of such entity.
23 |
24 | "You" (or "Your") shall mean an individual or Legal Entity
25 | exercising permissions granted by this License.
26 |
27 | "Source" form shall mean the preferred form for making modifications,
28 | including but not limited to software source code, documentation
29 | source, and configuration files.
30 |
31 | "Object" form shall mean any form resulting from mechanical
32 | transformation or translation of a Source form, including but
33 | not limited to compiled object code, generated documentation,
34 | and conversions to other media types.
35 |
36 | "Work" shall mean the work of authorship, whether in Source or
37 | Object form, made available under the License, as indicated by a
38 | copyright notice that is included in or attached to the work
39 | (an example is provided in the Appendix below).
40 |
41 | "Derivative Works" shall mean any work, whether in Source or Object
42 | form, that is based on (or derived from) the Work and for which the
43 | editorial revisions, annotations, elaborations, or other modifications
44 | represent, as a whole, an original work of authorship. For the purposes
45 | of this License, Derivative Works shall not include works that remain
46 | separable from, or merely link (or bind by name) to the interfaces of,
47 | the Work and Derivative Works thereof.
48 |
49 | "Contribution" shall mean any work of authorship, including
50 | the original version of the Work and any modifications or additions
51 | to that Work or Derivative Works thereof, that is intentionally
52 | submitted to Licensor for inclusion in the Work by the copyright owner
53 | or by an individual or Legal Entity authorized to submit on behalf of
54 | the copyright owner. For the purposes of this definition, "submitted"
55 | means any form of electronic, verbal, or written communication sent
56 | to the Licensor or its representatives, including but not limited to
57 | communication on electronic mailing lists, source code control systems,
58 | and issue tracking systems that are managed by, or on behalf of, the
59 | Licensor for the purpose of discussing and improving the Work, but
60 | excluding communication that is conspicuously marked or otherwise
61 | designated in writing by the copyright owner as "Not a Contribution."
62 |
63 | "Contributor" shall mean Licensor and any individual or Legal Entity
64 | on behalf of whom a Contribution has been received by Licensor and
65 | subsequently incorporated within the Work.
66 |
67 | 2. Grant of Copyright License. Subject to the terms and conditions of
68 | this License, each Contributor hereby grants to You a perpetual,
69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
70 | copyright license to reproduce, prepare Derivative Works of,
71 | publicly display, publicly perform, sublicense, and distribute the
72 | Work and such Derivative Works in Source or Object form.
73 |
74 | 3. Grant of Patent License. Subject to the terms and conditions of
75 | this License, each Contributor hereby grants to You a perpetual,
76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
77 | (except as stated in this section) patent license to make, have made,
78 | use, offer to sell, sell, import, and otherwise transfer the Work,
79 | where such license applies only to those patent claims licensable
80 | by such Contributor that are necessarily infringed by their
81 | Contribution(s) alone or by combination of their Contribution(s)
82 | with the Work to which such Contribution(s) was submitted. If You
83 | institute patent litigation against any entity (including a
84 | cross-claim or counterclaim in a lawsuit) alleging that the Work
85 | or a Contribution incorporated within the Work constitutes direct
86 | or contributory patent infringement, then any patent licenses
87 | granted to You under this License for that Work shall terminate
88 | as of the date such litigation is filed.
89 |
90 | 4. Redistribution. You may reproduce and distribute copies of the
91 | Work or Derivative Works thereof in any medium, with or without
92 | modifications, and in Source or Object form, provided that You
93 | meet the following conditions:
94 |
95 | (a) You must give any other recipients of the Work or
96 | Derivative Works a copy of this License; and
97 |
98 | (b) You must cause any modified files to carry prominent notices
99 | stating that You changed the files; and
100 |
101 | (c) You must retain, in the Source form of any Derivative Works
102 | that You distribute, all copyright, patent, trademark, and
103 | attribution notices from the Source form of the Work,
104 | excluding those notices that do not pertain to any part of
105 | the Derivative Works; and
106 |
107 | (d) If the Work includes a "NOTICE" text file as part of its
108 | distribution, then any Derivative Works that You distribute must
109 | include a readable copy of the attribution notices contained
110 | within such NOTICE file, excluding those notices that do not
111 | pertain to any part of the Derivative Works, in at least one
112 | of the following places: within a NOTICE text file distributed
113 | as part of the Derivative Works; within the Source form or
114 | documentation, if provided along with the Derivative Works; or,
115 | within a display generated by the Derivative Works, if and
116 | wherever such third-party notices normally appear. The contents
117 | of the NOTICE file are for informational purposes only and
118 | do not modify the License. You may add Your own attribution
119 | notices within Derivative Works that You distribute, alongside
120 | or as an addendum to the NOTICE text from the Work, provided
121 | that such additional attribution notices cannot be construed
122 | as modifying the License.
123 |
124 | You may add Your own copyright statement to Your modifications and
125 | may provide additional or different license terms and conditions
126 | for use, reproduction, or distribution of Your modifications, or
127 | for any such Derivative Works as a whole, provided Your use,
128 | reproduction, and distribution of the Work otherwise complies with
129 | the conditions stated in this License.
130 |
131 | 5. Submission of Contributions. Unless You explicitly state otherwise,
132 | any Contribution intentionally submitted for inclusion in the Work
133 | by You to the Licensor shall be under the terms and conditions of
134 | this License, without any additional terms or conditions.
135 | Notwithstanding the above, nothing herein shall supersede or modify
136 | the terms of any separate license agreement you may have executed
137 | with Licensor regarding such Contributions.
138 |
139 | 6. Trademarks. This License does not grant permission to use the trade
140 | names, trademarks, service marks, or product names of the Licensor,
141 | except as required for reasonable and customary use in describing the
142 | origin of the Work and reproducing the content of the NOTICE file.
143 |
144 | 7. Disclaimer of Warranty. Unless required by applicable law or
145 | agreed to in writing, Licensor provides the Work (and each
146 | Contributor provides its Contributions) on an "AS IS" BASIS,
147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
148 | implied, including, without limitation, any warranties or conditions
149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
150 | PARTICULAR PURPOSE. You are solely responsible for determining the
151 | appropriateness of using or redistributing the Work and assume any
152 | risks associated with Your exercise of permissions under this License.
153 |
154 | 8. Limitation of Liability. In no event and under no legal theory,
155 | whether in tort (including negligence), contract, or otherwise,
156 | unless required by applicable law (such as deliberate and grossly
157 | negligent acts) or agreed to in writing, shall any Contributor be
158 | liable to You for damages, including any direct, indirect, special,
159 | incidental, or consequential damages of any character arising as a
160 | result of this License or out of the use or inability to use the
161 | Work (including but not limited to damages for loss of goodwill,
162 | work stoppage, computer failure or malfunction, or any and all
163 | other commercial damages or losses), even if such Contributor
164 | has been advised of the possibility of such damages.
165 |
166 | 9. Accepting Warranty or Additional Liability. While redistributing
167 | the Work or Derivative Works thereof, You may choose to offer,
168 | and charge a fee for, acceptance of support, warranty, indemnity,
169 | or other liability obligations and/or rights consistent with this
170 | License. However, in accepting such obligations, You may act only
171 | on Your own behalf and on Your sole responsibility, not on behalf
172 | of any other Contributor, and only if You agree to indemnify,
173 | defend, and hold each Contributor harmless for any liability
174 | incurred by, or claims asserted against, such Contributor by reason
175 | of your accepting any such warranty or additional liability.
176 |
177 | END OF TERMS AND CONDITIONS
178 |
179 | APPENDIX: How to apply the Apache License to your work.
180 |
181 | To apply the Apache License to your work, attach the following
182 | boilerplate notice, with the fields enclosed by brackets "[]"
183 | replaced with your own identifying information. (Don't include
184 | the brackets!) The text should be enclosed in the appropriate
185 | comment syntax for the file format. We also recommend that a
186 | file or class name and description of purpose be included on the
187 | same "printed page" as the copyright notice for easier
188 | identification within third-party archives.
189 |
190 | Copyright 2020-2021 Kong Inc.
191 |
192 | Licensed under the Apache License, Version 2.0 (the "License");
193 | you may not use this file except in compliance with the License.
194 | You may obtain a copy of the License at
195 |
196 | http://www.apache.org/licenses/LICENSE-2.0
197 |
198 | Unless required by applicable law or agreed to in writing, software
199 | distributed under the License is distributed on an "AS IS" BASIS,
200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
201 | See the License for the specific language governing permissions and
202 | limitations under the License.
203 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # kong-python-pluginserver
2 |
3 | [](https://badge.fury.io/py/kong-pdk)
4 |
5 | Plugin server and PDK (Plugin Development Kit) for Python language support in Kong.
6 |
7 | Requires Kong >= 2.3.0.
8 |
9 |
10 | ## Documentation
11 |
12 | See in [Kong Docs](https://docs.konghq.com/gateway/latest/plugin-development/pluginserver/python/)
13 |
14 | ## Install the plugin server
15 |
16 | ```shell
17 | pip3 install kong-pdk
18 | ```
19 |
20 | ## Usage
21 |
22 | ```
23 | usage: kong-python-pluginserver [-h] [-p prefix] [-v] [--version] [--socket-name SOCKET_NAME] [--listen-queue-size LISTEN_QUEUE_SIZE]
24 | [--no-lua-style] [-m | -g] -d directory [--dump-plugin-info name] [--dump-all-plugins]
25 |
26 | Kong Python Plugin Server.
27 |
28 | optional arguments:
29 | -h, --help show this help message and exit
30 | -p prefix, --kong-prefix prefix, -kong-prefix prefix
31 | unix domain socket path to listen (default: /usr/local/kong/)
32 | -v, --verbose turn on verbose logging (default: 1)
33 | --version, -version show program's version number and exit
34 | --socket-name SOCKET_NAME
35 | socket name to listen on (default: python_pluginserver.sock)
36 | --listen-queue-size LISTEN_QUEUE_SIZE
37 | socket listen queue size (default: 4096)
38 | --no-lua-style turn off Lua-style "data, err" return values for PDK functions and throw exception instead (default: False)
39 | -m, --multiprocessing
40 | enable multiprocessing (default: False)
41 | -g, --gevent enable gevent (default: False)
42 | -d directory, --plugins-directory directory, -plugins-directory directory
43 | plugins directory
44 | --dump-plugin-info name, -dump-plugin-info name
45 | dump specific plugin info into stdout
46 | --dump-all-plugins, -dump-all-plugins
47 | dump all plugins info into stdout
48 | ```
49 |
50 | ## PDK API reference
51 |
52 | The PDK (plugin developemet kit) API document can be viewed [here](https://kong.github.io/kong-python-pdk/).
53 |
54 | Reference is generated by Sphinx under `doc` folder and published to the `gh-pages` branch.
55 | To generate updated docs, use:
56 | ```
57 | git worktree add docs/build/html gh-pages
58 | cd docs
59 | make deps && make html
60 | ```
61 |
62 | ## Deprecation Notice
63 |
64 | In next major release of Kong Python PDK, return values will default to use Python style error handling instead of
65 | Lua style. The new style API can be turned on now with `--no-lua-style`.
66 |
67 | ```python
68 | # old lua-style PDK API
69 | host, err = kong.request.get_header("host")
70 | if err:
71 | pass # error handling
72 |
73 | # new python-style PDK API
74 | try:
75 | host = kong.request.get_header("host")
76 | # no err in return, instead they are thrown if any
77 | except Exception as ex:
78 | pass # error handling
79 | ```
80 |
81 | ## TODO
82 |
83 | - Tests
84 | - Hot reload
85 |
--------------------------------------------------------------------------------
/docs/Makefile:
--------------------------------------------------------------------------------
1 | # Minimal makefile for Sphinx documentation
2 | #
3 |
4 | # You can set these variables from the command line, and also
5 | # from the environment for the first two.
6 | SPHINXOPTS ?=
7 | SPHINXAPIDOC ?= sphinx-apidoc
8 | SPHINXBUILD ?= sphinx-build
9 | SOURCEDIR = source
10 | BUILDDIR = build
11 |
12 | # Put it first so that "make" without argument is like "make help".
13 | help:
14 | @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
15 |
16 | .PHONY: help Makefile
17 |
18 | autodoc:
19 | @$(SPHINXAPIDOC) -o "$(SOURCEDIR)" ../kong_pdk/pdk/kong/ -f $(SPHINXOPTS)
20 |
21 | deps:
22 | pip3 install -r requirements.txt
23 |
24 | # Catch-all target: route all unknown targets to Sphinx using the new
25 | # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
26 | %: autodoc Makefile
27 | @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
28 |
--------------------------------------------------------------------------------
/docs/README.md:
--------------------------------------------------------------------------------
1 | # kong-python-pdk autodoc
2 |
3 | The PDK (plugin developemet kit) API document can be viewed [here](https://kong.github.io/kong-python-pdk/).
4 |
5 | Python types `.pyi` files is generated using https://github.com/fffonion/kong-pdk-autogen: `resty run.lua -t=python -o=../kong/kong-python-pdk/kong_pdk/pdk`
6 | Reference is generated by Sphinx under `doc` folder and published to the `gh-pages` branch.
7 |
8 | To generate updated docs, use:
9 | ```
10 | git worktree add docs/build/html gh-pages
11 | cd docs
12 | make deps && make html
13 | ```
14 |
15 |
--------------------------------------------------------------------------------
/docs/make.bat:
--------------------------------------------------------------------------------
1 | @ECHO OFF
2 |
3 | pushd %~dp0
4 |
5 | REM Command file for Sphinx documentation
6 |
7 | if "%SPHINXBUILD%" == "" (
8 | set SPHINXBUILD=sphinx-build
9 | )
10 | set SOURCEDIR=source
11 | set BUILDDIR=build
12 |
13 | if "%1" == "" goto help
14 |
15 | %SPHINXBUILD% >NUL 2>NUL
16 | if errorlevel 9009 (
17 | echo.
18 | echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
19 | echo.installed, then set the SPHINXBUILD environment variable to point
20 | echo.to the full path of the 'sphinx-build' executable. Alternatively you
21 | echo.may add the Sphinx directory to PATH.
22 | echo.
23 | echo.If you don't have Sphinx installed, grab it from
24 | echo.https://www.sphinx-doc.org/
25 | exit /b 1
26 | )
27 |
28 | %SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
29 | goto end
30 |
31 | :help
32 | %SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
33 |
34 | :end
35 | popd
36 |
--------------------------------------------------------------------------------
/docs/requirements.txt:
--------------------------------------------------------------------------------
1 | sphinx
2 | myst-parser
3 | sphinx_rtd_theme
4 |
--------------------------------------------------------------------------------
/docs/run.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | sphinx-apidoc -o ./source/ ../kong_pdk/pdk/kong/ -f
4 |
5 | make html
6 |
--------------------------------------------------------------------------------
/docs/source/conf.py:
--------------------------------------------------------------------------------
1 | # Configuration file for the Sphinx documentation builder.
2 | #
3 | # This file only contains a selection of the most common options. For a full
4 | # list see the documentation:
5 | # https://www.sphinx-doc.org/en/master/usage/configuration.html
6 |
7 | # -- Path setup --------------------------------------------------------------
8 |
9 | # If extensions (or modules to document with autodoc) are in another directory,
10 | # add these directories to sys.path here. If the directory is relative to the
11 | # documentation root, use os.path.abspath to make it absolute, like shown here.
12 | #
13 | # import os
14 | # import sys
15 | # sys.path.insert(0, os.path.abspath('.'))
16 |
17 |
18 | # -- Project information -----------------------------------------------------
19 |
20 | project = 'kong-pdk'
21 | copyright = '2024, Kong'
22 | author = 'Kong'
23 |
24 |
25 | # -- General configuration ---------------------------------------------------
26 |
27 | # Add any Sphinx extension module names here, as strings. They can be
28 | # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
29 | # ones.
30 | extensions = ['sphinx.ext.todo', 'sphinx.ext.viewcode', 'sphinx.ext.autodoc']
31 |
32 | # Add any paths that contain templates here, relative to this directory.
33 | templates_path = ['_templates']
34 |
35 | # List of patterns, relative to source directory, that match files and
36 | # directories to ignore when looking for source files.
37 | # This pattern also affects html_static_path and html_extra_path.
38 | exclude_patterns = []
39 |
40 |
41 | # -- Options for HTML output -------------------------------------------------
42 | import sphinx_rtd_theme
43 |
44 | # The theme to use for HTML and HTML Help pages. See the documentation for
45 | # a list of builtin themes.
46 | #
47 | html_theme = 'sphinx_rtd_theme'
48 | html_theme_path = [sphinx_rtd_theme.get_html_theme_path()]
49 |
50 | # Add any paths that contain custom static files (such as style sheets) here,
51 | # relative to this directory. They are copied after the builtin static files,
52 | # so a file named "default.css" will overwrite the builtin "default.css".
53 | html_static_path = ['_static']
54 |
55 | import os
56 | import sys
57 |
58 | sys.path.insert(0, os.path.abspath('../../kong_pdk/pdk'))
59 |
--------------------------------------------------------------------------------
/docs/source/index.rst:
--------------------------------------------------------------------------------
1 | .. kong-pdk documentation master file, created by
2 | sphinx-quickstart on Thu Feb 17 09:21:05 2022.
3 | You can adapt this file completely to your liking, but it should at least
4 | contain the root `toctree` directive.
5 |
6 | Welcome to kong-pdk's documentation!
7 | ====================================
8 |
9 | .. toctree::
10 | :maxdepth: 2
11 | :caption: Contents:
12 |
13 |
14 |
15 | Indices and tables
16 | ==================
17 |
18 | * :ref:`genindex`
19 | * :ref:`modindex`
20 | * :ref:`search`
21 |
--------------------------------------------------------------------------------
/docs/source/kong.client.rst:
--------------------------------------------------------------------------------
1 | kong.client package
2 | ===================
3 |
4 | Submodules
5 | ----------
6 |
7 | kong.client.tls module
8 | ----------------------
9 |
10 | .. automodule:: kong.client.tls
11 | :members:
12 | :undoc-members:
13 | :show-inheritance:
14 |
15 | Module contents
16 | ---------------
17 |
18 | .. automodule:: kong.client
19 | :members:
20 | :undoc-members:
21 | :show-inheritance:
22 |
--------------------------------------------------------------------------------
/docs/source/kong.ctx.rst:
--------------------------------------------------------------------------------
1 | kong.ctx package
2 | ================
3 |
4 | Submodules
5 | ----------
6 |
7 | kong.ctx.shared module
8 | ----------------------
9 |
10 | .. automodule:: kong.ctx.shared
11 | :members:
12 | :undoc-members:
13 | :show-inheritance:
14 |
15 | Module contents
16 | ---------------
17 |
18 | .. automodule:: kong.ctx
19 | :members:
20 | :undoc-members:
21 | :show-inheritance:
22 |
--------------------------------------------------------------------------------
/docs/source/kong.enterprise_edition.rst:
--------------------------------------------------------------------------------
1 | kong.enterprise\_edition package
2 | ================================
3 |
4 | Submodules
5 | ----------
6 |
7 | kong.enterprise\_edition.jwe module
8 | -----------------------------------
9 |
10 | .. automodule:: kong.enterprise_edition.jwe
11 | :members:
12 | :undoc-members:
13 | :show-inheritance:
14 |
15 | Module contents
16 | ---------------
17 |
18 | .. automodule:: kong.enterprise_edition
19 | :members:
20 | :undoc-members:
21 | :show-inheritance:
22 |
--------------------------------------------------------------------------------
/docs/source/kong.nginx.rst:
--------------------------------------------------------------------------------
1 | kong.nginx package
2 | ==================
3 |
4 | Submodules
5 | ----------
6 |
7 | kong.nginx.shared module
8 | ------------------------
9 |
10 | .. automodule:: kong.nginx.shared
11 | :members:
12 | :undoc-members:
13 | :show-inheritance:
14 |
15 | Module contents
16 | ---------------
17 |
18 | .. automodule:: kong.nginx
19 | :members:
20 | :undoc-members:
21 | :show-inheritance:
22 |
--------------------------------------------------------------------------------
/docs/source/kong.rst:
--------------------------------------------------------------------------------
1 | kong package
2 | ============
3 |
4 | Subpackages
5 | -----------
6 |
7 | .. toctree::
8 | :maxdepth: 4
9 |
10 | kong.client
11 | kong.ctx
12 | kong.enterprise_edition
13 | kong.nginx
14 | kong.service
15 |
16 | Submodules
17 | ----------
18 |
19 | kong.cluster module
20 | -------------------
21 |
22 | .. automodule:: kong.cluster
23 | :members:
24 | :undoc-members:
25 | :show-inheritance:
26 |
27 | kong.ip module
28 | --------------
29 |
30 | .. automodule:: kong.ip
31 | :members:
32 | :undoc-members:
33 | :show-inheritance:
34 |
35 | kong.log module
36 | ---------------
37 |
38 | .. automodule:: kong.log
39 | :members:
40 | :undoc-members:
41 | :show-inheritance:
42 |
43 | kong.node module
44 | ----------------
45 |
46 | .. automodule:: kong.node
47 | :members:
48 | :undoc-members:
49 | :show-inheritance:
50 |
51 | kong.plugin module
52 | ------------------
53 |
54 | .. automodule:: kong.plugin
55 | :members:
56 | :undoc-members:
57 | :show-inheritance:
58 |
59 | kong.request module
60 | -------------------
61 |
62 | .. automodule:: kong.request
63 | :members:
64 | :undoc-members:
65 | :show-inheritance:
66 |
67 | kong.response module
68 | --------------------
69 |
70 | .. automodule:: kong.response
71 | :members:
72 | :undoc-members:
73 | :show-inheritance:
74 |
75 | kong.router module
76 | ------------------
77 |
78 | .. automodule:: kong.router
79 | :members:
80 | :undoc-members:
81 | :show-inheritance:
82 |
83 | kong.vault module
84 | -----------------
85 |
86 | .. automodule:: kong.vault
87 | :members:
88 | :undoc-members:
89 | :show-inheritance:
90 |
91 | Module contents
92 | ---------------
93 |
94 | .. automodule:: kong
95 | :members:
96 | :undoc-members:
97 | :show-inheritance:
98 |
--------------------------------------------------------------------------------
/docs/source/kong.service.rst:
--------------------------------------------------------------------------------
1 | kong.service package
2 | ====================
3 |
4 | Submodules
5 | ----------
6 |
7 | kong.service.request module
8 | ---------------------------
9 |
10 | .. automodule:: kong.service.request
11 | :members:
12 | :undoc-members:
13 | :show-inheritance:
14 |
15 | kong.service.response module
16 | ----------------------------
17 |
18 | .. automodule:: kong.service.response
19 | :members:
20 | :undoc-members:
21 | :show-inheritance:
22 |
23 | Module contents
24 | ---------------
25 |
26 | .. automodule:: kong.service
27 | :members:
28 | :undoc-members:
29 | :show-inheritance:
30 |
--------------------------------------------------------------------------------
/docs/source/modules.rst:
--------------------------------------------------------------------------------
1 | kong
2 | ====
3 |
4 | .. toctree::
5 | :maxdepth: 4
6 |
7 | kong
8 |
--------------------------------------------------------------------------------
/examples/py-hello.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 | import os
3 | import kong_pdk.pdk.kong as kong
4 |
5 | Schema = (
6 | {"message": {"type": "string"}},
7 | )
8 |
9 | version = '0.1.0'
10 | priority = 0
11 |
12 | # This is an example plugin that add a header to the response
13 |
14 | class Plugin(object):
15 | def __init__(self, config):
16 | self.config = config
17 |
18 | def access(self, kong: kong.kong):
19 | host, err = kong.request.get_header("host")
20 | if err:
21 | pass # error handling
22 | # if run with --no-lua-style
23 | # try:
24 | # host = kong.request.get_header("host")
25 | # except Exception as ex:
26 | # pass # error handling
27 | message = "hello"
28 | if 'message' in self.config:
29 | message = self.config['message']
30 | kong.response.set_header("x-hello-from-python", "Python says %s to %s" % (message, host))
31 | kong.response.set_header("x-python-pid", str(os.getpid()))
32 |
33 |
34 | # add below section to allow this plugin optionally be running in a dedicated process
35 | if __name__ == "__main__":
36 | from kong_pdk.cli import start_dedicated_server
37 | start_dedicated_server("py-hello", Plugin, version, priority, Schema)
38 |
--------------------------------------------------------------------------------
/examples/py-image.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 |
3 | from PIL import Image
4 | from PIL import ImageFont
5 | from PIL import ImageDraw
6 | import io
7 |
8 | version = '0.1.0'
9 | priority = 0
10 |
11 | # This is an example plugin that uses PIL to generate an PNG image
12 | # containing text of the request headers
13 | # Run the following commands first:
14 | '''
15 | sudo apt install ttf-mscorefonts-installer
16 | sudo apt install font-manager
17 | sudo fc-cache -f -v
18 | python3 -m pip install Pillow
19 | '''
20 |
21 | class Plugin(object):
22 | def __init__(self, config):
23 | self.config = config
24 |
25 | def access(self, kong):
26 | img = Image.new("RGB", (800, 200))
27 | draw = ImageDraw.Draw(img)
28 | font = ImageFont.truetype("Comic_Sans_MS.ttf", 24)
29 | y = 0
30 | headers, _ = kong.request.get_headers()
31 | for h in headers:
32 | y = y + 32
33 | draw.text((0, y), "%s: %s" % (h, headers[h]), (255, 255, 255), font=font)
34 | b = io.BytesIO()
35 | img.save(b, format='PNG')
36 | kong.response.exit(200,
37 | b.getvalue()
38 | )
39 |
40 |
41 | # add below section to allow this plugin optionally be running in a dedicated process
42 | if __name__ == "__main__":
43 | from kong_pdk.cli import start_dedicated_server
44 | start_dedicated_server("py-image", Plugin, version, priority, [])
45 |
--------------------------------------------------------------------------------
/kong-pluginserver:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 |
3 | from kong_pdk import cli
4 |
5 | cli.start_server()
6 |
--------------------------------------------------------------------------------
/kong-pluginserver.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 |
3 | from kong_pdk import cli
4 |
5 | cli.start_server()
6 |
--------------------------------------------------------------------------------
/kong_pdk/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Kong/kong-python-pdk/88f638a8c95f6bc31ace210e2964e19bd4e01249/kong_pdk/__init__.py
--------------------------------------------------------------------------------
/kong_pdk/cli.py:
--------------------------------------------------------------------------------
1 | # coding:utf-8
2 | # Contributor:
3 | # fffonion
4 |
5 | import os
6 | import sys
7 | import argparse
8 | import msgpack
9 | import json
10 |
11 | from .server import PluginServer
12 | from .listener import UnixStreamServer, DEFAULT_SOCKET_NAME
13 | from .logger import Logger
14 |
15 | from .const import __version__, PY3K
16 |
17 | def parse(dedicated=False):
18 | parser = argparse.ArgumentParser(description='Kong Python Plugin Server.')
19 | parser.add_argument('-p', '--kong-prefix', '-kong-prefix',
20 | dest='prefix', metavar='prefix', type=str,
21 | default="/usr/local/kong/",
22 | help='unix domain socket path to listen (default: %(default)s)')
23 | parser.add_argument('-v', '--verbose', action='count', default=1,
24 | help='turn on verbose logging (default: %(default)s)')
25 | parser.add_argument('--version', '-version', action='version',
26 | version='%(prog)s {version}'.format(version=__version__))
27 | parser.add_argument('--socket-name', type=str, dest='socket_name', default=DEFAULT_SOCKET_NAME,
28 | help='socket name to listen on (default: %(default)s)')
29 | parser.add_argument('--listen-queue-size', type=int, dest='listen_queue_size', default=4096,
30 | help='socket listen queue size (default: %(default)s)')
31 | parser.add_argument('--no-lua-style', action='store_true', dest='no_lua_style', default=False,
32 | help='turn off Lua-style "data, err" return values for PDK functions '
33 | 'and throw exception instead (default: %(default)s)')
34 | mxg = parser.add_mutually_exclusive_group()
35 | mxg.add_argument('-m', '--multiprocessing', dest='multiprocessing', action="store_true",
36 | help='enable multiprocessing (default: %(default)s)')
37 | mxg.add_argument('-g', '--gevent', dest='gevent', action="store_true",
38 | help='enable gevent (default: %(default)s)')
39 |
40 | if not dedicated:
41 | parser.add_argument('-d', '--plugins-directory', '-plugins-directory',
42 | dest='directory', metavar='directory', type=str, required=True,
43 | help='plugins directory')
44 | parser.add_argument('--dump-plugin-info', '-dump-plugin-info', dest='dump_info', metavar='name', type=str,
45 | help='dump specific plugin info into stdout')
46 | parser.add_argument('--dump-all-plugins', '-dump-all-plugins', dest='dump_all_info', action="store_true",
47 | help='dump all plugins info into stdout')
48 | else:
49 | parser.add_argument('--dump', '-dump', dest='dump', action="store_true",
50 | help='dump current plugin info into stdout')
51 |
52 | args = parser.parse_args()
53 |
54 | if ((not dedicated and not args.dump_info and not args.dump_all_info)
55 | or (dedicated and not args.dump)) and not os.path.exists(args.prefix):
56 | raise OSError("path %s doesn't exist, can't create unix socket file" % args.prefix)
57 |
58 | return args
59 |
60 | def display_lua_style_notice(lua_style, ps):
61 | if not lua_style:
62 | ps.logger.debug("python-style return values are enabled, "
63 | "errors are thrown as exception")
64 | else:
65 | ps.logger.warn("lua-style return values are used, "
66 | "this will be deprecated in the future; instead of returning "
67 | "(data, err) tuple, only data will be returned and err will be "
68 | "thrown as PDKException; please adjust your plugin to use the "
69 | "new python-style PDK API.")
70 |
71 | def start_server():
72 | args = parse()
73 |
74 | prefix = args.prefix
75 |
76 | ps = PluginServer(loglevel=Logger.WARNING - args.verbose,
77 | plugin_dir=args.directory,
78 | use_multiprocess=args.multiprocessing,
79 | use_gevent=args.gevent,
80 | lua_style=not args.no_lua_style)
81 | ss = UnixStreamServer(ps, prefix,
82 | sock_name=args.socket_name,
83 | use_gevent=args.gevent,
84 | listen_queue_size=args.listen_queue_size)
85 | if args.dump_info:
86 | ret, err = ps.get_plugin_info(args.dump_info)
87 | if err:
88 | raise Exception("error dump info: " + err)
89 | if PY3K:
90 | sys.stdout.buffer.write(msgpack.packb(ret))
91 | else:
92 | sys.stdout.write(msgpack.packb(ret))
93 | sys.exit(0)
94 | elif args.dump_all_info:
95 | ret = []
96 | for p in ps.plugins:
97 | inf = ps.get_plugin_info(p)
98 | ret.append(inf)
99 | sys.stdout.write(json.dumps(ret))
100 | sys.exit(0)
101 |
102 | display_lua_style_notice(not args.no_lua_style, ps)
103 |
104 | try:
105 | ss.serve_forever()
106 | except KeyboardInterrupt:
107 | ps.logger.info("polite exit requested, terminating...")
108 |
109 | ps.cleanup()
110 |
111 | def start_dedicated_server(name, plugin, _version=None, _priority=0, _schema=[]):
112 | from .module import Module
113 |
114 | args = parse(dedicated=True)
115 |
116 | ps = PluginServer(loglevel=Logger.WARNING - args.verbose,
117 | use_multiprocess=args.multiprocessing,
118 | use_gevent=args.gevent,
119 | name="%s version %s" % (name, _version or 'unknown'),
120 | lua_style=not args.no_lua_style)
121 | socket_name = args.socket_name
122 | if socket_name == DEFAULT_SOCKET_NAME:
123 | socket_name = "%s.sock" % name
124 | ss = UnixStreamServer(ps, args.prefix,
125 | sock_name=socket_name,
126 | use_gevent=args.gevent,
127 | listen_queue_size=args.listen_queue_size)
128 |
129 | class mod(object):
130 | Plugin = plugin
131 | Schema = _schema
132 | version = _version
133 | priority = _priority
134 |
135 | mod = Module(name, module=mod)
136 | ps.plugins[name] = mod
137 |
138 | if args.dump:
139 | ret = ps.get_plugin_info(name)
140 | # note a list is returned
141 | sys.stdout.write(json.dumps([ret]))
142 | sys.exit(0)
143 |
144 | display_lua_style_notice(not args.no_lua_style, ps)
145 |
146 | try:
147 | ss.serve_forever()
148 | except KeyboardInterrupt:
149 | ps.logger.info("polite exit requested, terminating...")
150 |
151 | ps.cleanup()
152 |
--------------------------------------------------------------------------------
/kong_pdk/const.py:
--------------------------------------------------------------------------------
1 | # coding:utf-8
2 | # constants module
3 | # Contributor:
4 | # fffonion
5 |
6 | import os
7 | import sys
8 | import locale
9 |
10 | PY3K = sys.version_info.major == 3
11 | IRONPYTHON = sys.platform == 'cli'
12 | EXEBUNDLE = getattr(sys, 'frozen', False)
13 | LOCALE = locale.getdefaultlocale()[0]
14 | CODEPAGE = locale.getdefaultlocale()[1] or 'ascii'
15 |
16 | __version__ = 0.40
17 |
18 | # https://github.com/soimort/you-get/you-get
19 | if getattr(sys, 'frozen', False):
20 | # The application is frozen
21 | FILEPATH = os.path.dirname(os.path.realpath(sys.executable))
22 | else:
23 | # The application is not frozen
24 | # Change this bit to match where you store your data files:
25 | FILEPATH = sys.path[0]
26 |
--------------------------------------------------------------------------------
/kong_pdk/exception.py:
--------------------------------------------------------------------------------
1 | class PluginServerException(Exception):
2 | pass
3 |
4 | class PDKException(Exception):
5 | pass
6 |
--------------------------------------------------------------------------------
/kong_pdk/kong.py:
--------------------------------------------------------------------------------
1 | class kong():
2 | pass
3 |
--------------------------------------------------------------------------------
/kong_pdk/listener.py:
--------------------------------------------------------------------------------
1 | import os
2 | import re
3 | import sys
4 | import time
5 | import traceback
6 | import threading
7 | import msgpack
8 |
9 | from .const import PY3K
10 | if PY3K:
11 | from socketserver import ThreadingMixIn, UnixStreamServer as sUnixStreamServer
12 | else:
13 | from SocketServer import ThreadingMixIn, UnixStreamServer as sUnixStreamServer
14 |
15 | from gevent import socket as gsocket, sleep as gsleep, spawn as gspawn
16 | from gevent.server import StreamServer as gStreamServer
17 |
18 | from .exception import PDKException, PluginServerException
19 |
20 | cmdre = re.compile("([a-z])([A-Z])")
21 |
22 | DEFAULT_SOCKET_NAME = "python_pluginserver.sock"
23 |
24 | def write_response(fd, msgid, response):
25 | fd.send(msgpack.packb([
26 | 1, # is response
27 | msgid,
28 | None,
29 | response
30 | ]))
31 |
32 | def write_error(fd, msgid, error):
33 | fd.send(msgpack.packb([
34 | 1, # is response
35 | msgid,
36 | error,
37 | None
38 | ]))
39 |
40 |
41 | class WrapSocket(object):
42 | def __init__(self, socket):
43 | self.socket = socket
44 |
45 | def read(self, n):
46 | return self.socket.recv(n)
47 |
48 | class Server(object):
49 | def __init__(self, plugin_server):
50 | self.ps = plugin_server
51 | self.logger = plugin_server.logger
52 |
53 | def handle(self, fd, address, *_):
54 | # can't use socket.makefile here, since it returns a blocking IO
55 | # msgpack.Unpacker only expects read() but no other semantics to exist
56 | sockf = WrapSocket(fd)
57 | unpacker = msgpack.Unpacker(sockf, strict_map_key=False)
58 |
59 | for _, msgid, method, args in unpacker:
60 | ns, cmd = method.split(".")
61 | if ns != "plugin":
62 | write_error(fd, msgid, "RPC for %s is not supported" % ns)
63 | continue
64 |
65 | cmd_r = cmd[0].lower() + cmdre.sub(lambda m: "%s_%s" % (m.group(1), m.group(2).lower()), cmd[1:])
66 | try:
67 | self.logger.debug("rpc: #%d method: %s args: %s" % (msgid, method, args))
68 | ret = getattr(self.ps, cmd_r)(*args)
69 | self.logger.debug("rpc: #%d return: %s" % (msgid, ret))
70 | write_response(fd, msgid, ret)
71 | except (PluginServerException, PDKException) as ex:
72 | self.logger.warn("rpc: #%d error: %s" % (msgid, str(ex)))
73 | write_error(fd, msgid, str(ex))
74 | except Exception as ex:
75 | self.logger.error("rpc: #%d exception: %s" % (msgid, traceback.format_exc()))
76 | write_error(fd, msgid, str(ex))
77 |
78 | class tUnixStreamServer(ThreadingMixIn, sUnixStreamServer):
79 | pass
80 |
81 | def watchdog(sleep, logger):
82 | while True:
83 | if os.getppid() == 1: # parent dead, process adopted by init
84 | logger.info("Kong exits, terminating...")
85 | sys.exit()
86 | sleep(1)
87 |
88 | class UnixStreamServer(Server):
89 | def __init__(self, pluginserver, path,
90 | sock_name=DEFAULT_SOCKET_NAME, use_gevent=True, listen_queue_size=4096):
91 | Server.__init__(self, pluginserver)
92 | self.path = os.path.join(path, sock_name)
93 | self.use_gevent = use_gevent
94 | self.listen_queue_size = listen_queue_size
95 |
96 | def serve_forever(self):
97 | if os.path.exists(self.path):
98 | os.remove(self.path)
99 |
100 | if self.use_gevent:
101 | listener = gsocket.socket(gsocket.AF_UNIX, gsocket.SOCK_STREAM)
102 | listener.bind(self.path)
103 | listener.listen(self.listen_queue_size)
104 |
105 | self.logger.info("server (gevent) started at path " + self.path)
106 |
107 | gspawn(watchdog, gsleep, self.logger)
108 |
109 | gStreamServer(listener, self.handle).serve_forever()
110 | else:
111 | import socket
112 | self.logger.info("server started at path " + self.path)
113 |
114 | t = threading.Thread(
115 | target=watchdog,
116 | args=(time.sleep, self.logger, ),
117 | )
118 | t.setDaemon(True)
119 | t.start()
120 | s = tUnixStreamServer(self.path, self.handle, bind_and_activate=False)
121 | s.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True)
122 | s.server_bind()
123 | s.socket.listen(self.listen_queue_size)
124 | s.serve_forever()
125 |
--------------------------------------------------------------------------------
/kong_pdk/logger.py:
--------------------------------------------------------------------------------
1 | # coding:utf-8
2 | # Contributor:
3 | # fffonion
4 |
5 | import os
6 | import sys
7 | import datetime
8 | import locale
9 | import traceback
10 | from threading import RLock
11 | from .const import PY3K
12 |
13 | class tz_GMT8(datetime.tzinfo):
14 | def utcoffset(self, dt):
15 | return datetime.timedelta(hours=8)
16 |
17 | def dst(self, dt):
18 | return datetime.timedelta(0)
19 |
20 |
21 | if PY3K:
22 | unicode = None
23 |
24 | def safestr(s):
25 | if (PY3K and isinstance(s, bytes)) or (not PY3K and not isinstance(s, unicode)):
26 | s = s.decode("utf-8")
27 | if PY3K:
28 | # python<=3.5 hack
29 | if sys.version_info.minor <= 5:
30 | return s \
31 | .encode(locale.getdefaultlocale()[1] or 'utf-8', 'replace') \
32 | .decode(locale.getdefaultlocale()[1] or 'utf-8', 'replace')
33 | return s
34 | return s.encode(locale.getdefaultlocale()[1] or 'utf-8', 'replace')
35 | # return _.decode('utf-8') if PY3K else _
36 |
37 |
38 | if os.name == 'nt':
39 | endl = '\r\n'
40 | else: # assume posix
41 | endl = '\n'
42 |
43 | class Logger(object):
44 | # paste from goagent
45 | CRITICAL = 5
46 | FATAL = CRITICAL
47 | ERROR = 4
48 | WARNING = 3
49 | WARN = WARNING
50 | INFO = 2
51 | DEBUG = 1
52 | VERBOSE = 0
53 |
54 | def __init__(self, *args, **kwargs):
55 | # self.level = self.__class__.INFO
56 | self.logf = None
57 | self.__write = __write = lambda x: sys.stdout.write(safestr(x))
58 | self.isatty = getattr(sys.stdout, 'isatty', lambda: False)()
59 | self.__set_error_color = lambda: None
60 | self.__set_warning_color = lambda: None
61 | self.__set_debug_color = lambda: None
62 | self.__set_verbose_color = lambda: None
63 | self.__reset_color = lambda: None
64 | if self.isatty:
65 | if os.name == 'nt':
66 | self._nt_color_lock = RLock()
67 | import ctypes
68 | SetConsoleTextAttribute = ctypes.windll.kernel32.SetConsoleTextAttribute
69 | GetStdHandle = ctypes.windll.kernel32.GetStdHandle
70 | self.__set_error_color = lambda: (self._nt_color_lock.acquire(), SetConsoleTextAttribute(GetStdHandle(-11), 0x0C))
71 | self.__set_warning_color = lambda: (self._nt_color_lock.acquire(), SetConsoleTextAttribute(GetStdHandle(-11), 0x06))
72 | self.__set_debug_color = lambda: (self._nt_color_lock.acquire(), SetConsoleTextAttribute(GetStdHandle(-11), 0x02))
73 | self.__set_verbose_color = lambda: (self._nt_color_lock.acquire(), SetConsoleTextAttribute(GetStdHandle(-11), 0x08))
74 | self.__set_bright_color = lambda: (self._nt_color_lock.acquire(), SetConsoleTextAttribute(GetStdHandle(-11), 0x0F))
75 | self.__reset_color = lambda: (SetConsoleTextAttribute(GetStdHandle(-11), 0x07), self._nt_color_lock.release())
76 | elif os.name == 'posix':
77 | self.__set_error_color = lambda: __write('\033[31m')
78 | self.__set_warning_color = lambda: __write('\033[33m')
79 | self.__set_debug_color = lambda: __write('\033[32m')
80 | self.__set_verbose_color = lambda: __write('\033[36m')
81 | self.__set_bright_color = lambda: __write('\033[32m')
82 | self.__reset_color = lambda: __write('\033[0m')
83 |
84 | @classmethod
85 | def getLogger(cls, *args, **kwargs):
86 | return cls(*args, **kwargs)
87 |
88 | def cleanup(self):
89 | if self.logf:
90 | _ = self.logf
91 | self.logf = None
92 | _.close()
93 |
94 | def set_logfile(self, fpath):
95 | if self.logf:
96 | self.logf.close()
97 | self.logf = open(fpath, "ab")
98 |
99 | def set_level(self, level):
100 | f = ('verbose', 'debug', 'info')
101 | lv = min(max(level, 0), 3)
102 | for p in range(lv):
103 | setattr(self, f[p], self.dummy)
104 |
105 | def log(self, level, fmt, *args, **kwargs):
106 | # fmt=du8(fmt)
107 | try:
108 | try:
109 | self.__write('%-4s - [%s] %s\n' % (level, datetime.datetime.now(tz_GMT8()).strftime('%X'), fmt % args))
110 | except (ValueError, TypeError):
111 | fmt = fmt.replace('%', '%%')
112 | self.__write('%-4s - [%s] %s\n' % (level, datetime.datetime.now(tz_GMT8()).strftime('%X'), fmt % args))
113 | except IOError: # fix for Windows console
114 | pass
115 | sys.stdout.flush()
116 | if self.logf:
117 | _ = ('[%s] %s%s' % (datetime.datetime.now(tz_GMT8()).strftime('%b %d %X'), fmt % args, endl))
118 | self.logf.write(_.encode("utf-8", 'replace'))
119 |
120 | def dummy(self, *args, **kwargs):
121 | pass
122 |
123 | def debug(self, fmt, *args, **kwargs):
124 | self.__set_debug_color()
125 | self.log('DEBG', fmt, *args, **kwargs)
126 | self.__reset_color()
127 |
128 | def info(self, fmt, *args, **kwargs):
129 | self.log('INFO', fmt, *args)
130 |
131 | def verbose(self, fmt, *args, **kwargs):
132 | self.__set_verbose_color()
133 | self.log('VERB', fmt, *args, **kwargs)
134 | self.__reset_color()
135 |
136 | def warning(self, fmt, *args, **kwargs):
137 | self.__set_warning_color()
138 | self.log('WARN', fmt, *args, **kwargs)
139 | self.__reset_color()
140 |
141 | def warn(self, fmt, *args, **kwargs):
142 | self.warning(fmt, *args, **kwargs)
143 |
144 | def error(self, fmt, *args, **kwargs):
145 | self.__set_error_color()
146 | self.log('ERROR', fmt, *args, **kwargs)
147 | self.__reset_color()
148 |
149 | def exception(self, fmt, *args, **kwargs):
150 | self.error(fmt, *args, **kwargs)
151 | traceback.print_exc(file=sys.stderr)
152 |
153 | def critical(self, fmt, *args, **kwargs):
154 | self.__set_error_color()
155 | self.log('CRITICAL', fmt, *args, **kwargs)
156 | self.__reset_color()
157 |
--------------------------------------------------------------------------------
/kong_pdk/module.py:
--------------------------------------------------------------------------------
1 | import os
2 | import sys
3 | import time
4 | from .const import PY3K, FILEPATH
5 | from .exception import PDKException
6 | if PY3K:
7 | import importlib.util
8 |
9 | def load_module(name, path):
10 | spec = importlib.util.spec_from_file_location(name, path)
11 | mod = importlib.util.module_from_spec(spec)
12 | spec.loader.exec_module(mod)
13 | sys.modules[name] = mod
14 | return mod
15 | else:
16 | import imp
17 | methods = {
18 | '.py': imp.load_source,
19 | '.pyc': imp.load_compiled,
20 | '.pyo': imp.load_compiled,
21 | '.pyd': imp.load_dynamic,
22 | '.so': imp.load_dynamic,
23 | }
24 |
25 | def load_module(name, path):
26 | ext = os.path.splitext(path)[1]
27 | mod = methods[ext](name, path)
28 | sys.modules[name] = mod
29 | return mod
30 |
31 | phases = ("certificate", "rewrite", "log", "access", "preread", "response")
32 |
33 | class Module(object):
34 | def __init__(self, name, path=None, module=None):
35 | self.name = name
36 | self.load_time = time.time()
37 |
38 | if path:
39 | mod = load_module(name, path)
40 | self.mod = mod
41 | self.mtime = os.stat(path).st_mtime
42 | elif module:
43 | mod = module
44 | self.mtime = os.stat(FILEPATH).st_mtime
45 | else:
46 | raise PDKException("either path or module needs to be passed in")
47 |
48 | self.cls = getattr(mod, "Plugin")
49 |
50 | self.phases = []
51 | for phase in phases:
52 | if hasattr(self.cls, phase):
53 | self.phases.append(phase)
54 |
55 | self.priority = 0
56 | self.version = None
57 |
58 | for attr in ('version', 'priority'):
59 | if hasattr(mod, attr):
60 | setattr(self, attr, getattr(mod, attr))
61 |
62 | if hasattr(mod, "Schema"):
63 | self.schema = mod.Schema
64 | else:
65 | self.schema = []
66 |
67 | self.last_start_instance_time = 0
68 | self.last_close_instance_time = 0
69 |
70 | def new(self, config):
71 | self.last_start_instance_time = time.time()
72 | return Instance(self.name, config, self.cls, self.set_last_close_instance_time)
73 |
74 | def set_last_close_instance_time(self):
75 | self.last_close_instance_time = time.time()
76 |
77 |
78 | class Instance(object):
79 | def __init__(self, name, config, cls, close_cb):
80 | self.cls = cls(config)
81 | self.name = name
82 | self.config = config
83 | self.start_time = time.time()
84 | self.last_used_time = 0
85 | self.close_cb = close_cb
86 |
87 | def is_expired(self, ttl=60):
88 | until = time.time() - ttl
89 | return self.start_time < until and self.last_used_time < until
90 |
91 | def reset_expire_ts(self):
92 | self.last_used_time = time.time()
93 | return self.cls
94 |
--------------------------------------------------------------------------------
/kong_pdk/pdk/__init__.py:
--------------------------------------------------------------------------------
1 | from ..exception import PDKException
2 |
3 | class FakeClasses(object):
4 | def __init__(self, prefix, call):
5 | self.prefix = prefix
6 | self.call = call
7 |
8 | def __call__(self, *a):
9 | return self.call(self.prefix, *a)
10 |
11 | # TODO
12 | def __str__(self):
13 | return self.call(self.prefix)
14 |
15 | def __getattr__(self, k):
16 | return FakeClasses(self.prefix + "." + k, self.call)
17 |
18 |
19 | # those methods never return, instead, they exit from current request immediately
20 | non_return_methods = set((
21 | "kong.response.exit",
22 | "kong.response.error",
23 | ))
24 |
25 | def rpc_of(ch, lua_style):
26 | def f(m, *a):
27 | # sanitize non-serializable objects
28 | if m == "kong.log" or m.startswith("kong.log."):
29 | a = list(a)
30 | for i in range(len(a)):
31 | if type(a[i]) not in (str, int, list, dict):
32 | a[i] = str(a[i])
33 |
34 | ch.put({
35 | "Method": m,
36 | "Args": a,
37 | })
38 | if m in non_return_methods:
39 | return
40 |
41 | data, err = ch.get()
42 | if lua_style:
43 | return data, err
44 | if err:
45 | raise PDKException("exception from %s: %s" % (m, err))
46 | return data
47 | return f
48 |
49 | class Kong(object):
50 | def __init__(self, ch, lua_style=False):
51 | self.kong = FakeClasses("kong", self.bridge)
52 | self.rpc = rpc_of(ch, lua_style)
53 |
54 | def bridge(self, attr, *args):
55 | return self.rpc(attr, *args)
56 |
--------------------------------------------------------------------------------
/kong_pdk/pdk/kong/__init__.py:
--------------------------------------------------------------------------------
1 | # AUTO GENERATED BASED ON Kong 3.8.x, DO NOT EDIT
2 | # Original source path: kong/pdk.lua
3 |
4 | from typing import TypeVar, Any, Union, List, Mapping, Tuple, Optional
5 |
6 | number = TypeVar('number', int, float)
7 | table = TypeVar('table', List[Any], Mapping[str, Any])
8 | # XXX
9 | cdata = Any
10 | err = str
11 |
12 | from .client import client as cls_client
13 | from .cluster import cluster as cls_cluster
14 | from .ctx import ctx as cls_ctx
15 | from .enterprise_edition import enterprise_edition as cls_enterprise_edition
16 | from .ip import ip as cls_ip
17 | from .log import log as cls_log
18 | from .nginx import nginx as cls_nginx
19 | from .node import node as cls_node
20 | from .plugin import plugin as cls_plugin
21 | from .request import request as cls_request
22 | from .response import response as cls_response
23 | from .router import router as cls_router
24 | from .service import service as cls_service
25 | from .telemetry import telemetry as cls_telemetry
26 | from .vault import vault as cls_vault
27 |
28 | class kong():
29 |
30 | client = cls_client
31 | cluster = cls_cluster
32 | ctx = cls_ctx
33 | enterprise_edition = cls_enterprise_edition
34 | ip = cls_ip
35 | log = cls_log
36 | nginx = cls_nginx
37 | node = cls_node
38 | plugin = cls_plugin
39 | request = cls_request
40 | response = cls_response
41 | router = cls_router
42 | service = cls_service
43 | telemetry = cls_telemetry
44 | vault = cls_vault
45 |
46 | pass
47 |
--------------------------------------------------------------------------------
/kong_pdk/pdk/kong/client/__init__.py:
--------------------------------------------------------------------------------
1 | # AUTO GENERATED BASED ON Kong 3.8.x, DO NOT EDIT
2 | # Original source path: kong/pdk/client.lua
3 |
4 | from typing import TypeVar, Any, Union, List, Mapping, Tuple, Optional
5 |
6 | number = TypeVar('number', int, float)
7 | table = TypeVar('table', List[Any], Mapping[str, Any])
8 | # XXX
9 | cdata = Any
10 | err = str
11 |
12 | from .tls import tls as cls_tls
13 |
14 | class client():
15 |
16 | tls = cls_tls
17 |
18 | @staticmethod
19 | def authenticate(consumer: table, credential: table) -> None:
20 | """
21 |
22 | Sets the authenticated consumer and/or credential as well
23 | as the authenticated consumer-group for the current request.
24 | While both `consumer` and `credential` can be `nil`,
25 | at least one of them must exist. Otherwise, this function will throw an
26 | error.
27 |
28 | Phases:
29 | access
30 |
31 | Example:
32 | # assuming `credential` and `consumer` have been set by some authentication code
33 |
34 | kong.client.authenticate(consumer, credentials)
35 |
36 | :parameter consumer: The consumer to set. If no
37 | value is provided, then any existing value will be cleared.
38 | :type consumer: table
39 | :parameter credential: The credential to set. If
40 | no value is provided, then any existing value will be cleared.
41 | :type credential: table
42 |
43 | """
44 | pass
45 |
46 | @staticmethod
47 | def authenticate_consumer_group_by_consumer_id(consumer_id: str) -> None:
48 | """
49 |
50 | If the consumer_id is neither a string nor nil, it throws an error.
51 | If the consumer group has already been authenticated, it doesn't override the group.
52 | The function performs a redis-SCAN-like lookup using a subset of the cache_key.
53 | The consumer_group_mapping is sorted by group name for deterministic behavior,
54 | but this might be changed in future releases.
55 |
56 | Phases:
57 | access
58 |
59 | Example:
60 | # assuming `consumer_id` is provided by some code
61 |
62 | kong.client.authenticate_consumer_group_by_consumer_id(consumer_id)
63 |
64 | :parameter consumer_id: The consumer id to use for setting the consumer group.
65 | If no value is provided, the current consumer group is not changed.
66 | :type consumer_id: str
67 |
68 | """
69 | pass
70 |
71 | @staticmethod
72 | def get_consumer() -> table:
73 | """
74 |
75 | Returns the `consumer` entity of the currently authenticated consumer.
76 | If not set yet, it returns `nil`.
77 |
78 | Phases:
79 | access, header_filter, response, body_filter, log
80 |
81 | Example:
82 | consumer = kong.client.get_consumer()
83 |
84 | if consumer:
85 |
86 | consumer_id = consumer.id
87 |
88 | else:
89 |
90 | # request not authenticated yet, or a credential
91 |
92 | # without a consumer (external auth)
93 |
94 | :return: The authenticated consumer entity.
95 |
96 | :rtype: table
97 | """
98 | pass
99 |
100 | @staticmethod
101 | def get_consumer_group() -> table:
102 | """
103 |
104 | This function is deprecated in favor of `get_consumer_groups`.
105 | Retrieves the authenticated consumer group for the current request.
106 |
107 | Phases:
108 | auth_and_later
109 |
110 | Example:
111 | group = kong.client.get_consumer_group()
112 |
113 | :return: The authenticated consumer group. Returns `nil` if no
114 | consumer group has been authenticated for the current request.
115 |
116 | :rtype: table
117 | """
118 | pass
119 |
120 | @staticmethod
121 | def get_consumer_groups() -> table:
122 | """
123 |
124 | Retrieves the authenticated consumer groups for the current request.
125 |
126 | Phases:
127 | auth_and_later
128 |
129 | Example:
130 | groups = kong.client.get_consumer_groups()
131 |
132 | :return: The authenticated consumer groups. Returns `nil` if no
133 | consumer groups has been authenticated for the current request.
134 |
135 | :rtype: table
136 | """
137 | pass
138 |
139 | @staticmethod
140 | def get_credential() -> str:
141 | """
142 |
143 | Returns the credentials of the currently authenticated consumer.
144 | If not set yet, it returns `nil`.
145 |
146 | Phases:
147 | access, header_filter, response, body_filter, log
148 |
149 | Example:
150 | credential = kong.client.get_credential()
151 |
152 | if credential:
153 |
154 | consumer_id = credential.consumer_id
155 |
156 | else:
157 |
158 | # request not authenticated yet
159 |
160 | :return: The authenticated credential.
161 |
162 | :rtype: str
163 | """
164 | pass
165 |
166 | @staticmethod
167 | def get_forwarded_ip() -> str:
168 | """
169 |
170 | Returns the remote address of the client making the request. Unlike
171 | `kong.client.get_ip`, this function will consider forwarded addresses in
172 | cases when a load balancer is in front of Kong. Whether this function
173 | returns a forwarded address or not depends on several Kong configuration
174 | parameters:
175 | * [trusted\_ips](https://docs.konghq.com/gateway/latest/reference/configuration/#trusted_ips)
176 | * [real\_ip\_header](https://docs.konghq.com/gateway/latest/reference/configuration/#real_ip_header)
177 | * [real\_ip\_recursive](https://docs.konghq.com/gateway/latest/reference/configuration/#real_ip_recursive)
178 |
179 | Phases:
180 | certificate, rewrite, access, header_filter, response, body_filter, log
181 |
182 | Example:
183 | # Given a client with IP 127.0.0.1 making connection through
184 |
185 | # a load balancer with IP 10.0.0.1 to Kong answering the request for
186 |
187 | # https://username:password@example.com:1234/v1/movies
188 |
189 | kong.client.get_forwarded_ip() # "127.0.0.1"
190 |
191 | # Note: This example assumes that 10.0.0.1 is one of the trusted IPs, and that
192 |
193 | # the load balancer adds the right headers matching with the configuration
194 |
195 | # of `real_ip_header`, e.g. `proxy_protocol`.
196 |
197 | :return: The remote IP address of the client making the request,
198 | considering forwarded addresses.
199 |
200 | :rtype: str
201 | """
202 | pass
203 |
204 | @staticmethod
205 | def get_forwarded_port() -> number:
206 | """
207 |
208 | Returns the remote port of the client making the request. Unlike
209 | `kong.client.get_port`, this function will consider forwarded ports in cases
210 | when a load balancer is in front of Kong. Whether this function returns a
211 | forwarded port or not depends on several Kong configuration parameters:
212 | * [trusted\_ips](https://docs.konghq.com/gateway/latest/reference/configuration/#trusted_ips)
213 | * [real\_ip\_header](https://docs.konghq.com/gateway/latest/reference/configuration/#real_ip_header)
214 | * [real\_ip\_recursive](https://docs.konghq.com/gateway/latest/reference/configuration/#real_ip_recursive)
215 |
216 | Phases:
217 | certificate, rewrite, access, header_filter, response, body_filter, log
218 |
219 | Example:
220 | # [client]:40000 <-> 80:[balancer]:30000 <-> 80:[kong]:20000 <-> 80:[service]
221 |
222 | kong.client.get_forwarded_port() # 40000
223 |
224 | # Note: This example assumes that [balancer] is one of the trusted IPs, and that
225 |
226 | # the load balancer adds the right headers matching with the configuration
227 |
228 | # of `real_ip_header`, e.g. `proxy_protocol`.
229 |
230 | :return: The remote client port, considering forwarded ports.
231 |
232 | :rtype: number
233 | """
234 | pass
235 |
236 | @staticmethod
237 | def get_ip() -> str:
238 | """
239 |
240 | Returns the remote address of the client making the request. This module
241 | **always** returns the address of the client directly connecting to Kong.
242 | That is, in cases when a load balancer is in front of Kong, this function
243 | returns the load balancer's address, and **not** that of the
244 | downstream client.
245 |
246 | Phases:
247 | certificate, rewrite, access, header_filter, response, body_filter, log
248 |
249 | Example:
250 | # Given a client with IP 127.0.0.1 making connection through
251 |
252 | # a load balancer with IP 10.0.0.1 to Kong answering the request for
253 |
254 | # https://example.com:1234/v1/movies
255 |
256 | kong.client.get_ip() # "10.0.0.1"
257 |
258 | :return: The remote IP address of the client making the request.
259 |
260 | :rtype: str
261 | """
262 | pass
263 |
264 | @staticmethod
265 | def get_port() -> number:
266 | """
267 |
268 | Returns the remote port of the client making the request. This
269 | **always** returns the port of the client directly connecting to Kong. That
270 | is, in cases when a load balancer is in front of Kong, this function
271 | returns the load balancer's port, and **not** that of the downstream client.
272 |
273 | Phases:
274 | certificate, rewrite, access, header_filter, response, body_filter, log
275 |
276 | Example:
277 | # [client]:40000 <-> 80:[balancer]:30000 <-> 80:[kong]:20000 <-> 80:[service]
278 |
279 | kong.client.get_port() # 30000
280 |
281 | :return: The remote client port.
282 |
283 | :rtype: number
284 | """
285 | pass
286 |
287 | @staticmethod
288 | def get_protocol(allow_terminated: Optional[bool]) -> Tuple[str, err]:
289 | """
290 |
291 | Returns the protocol matched by the current route (`"http"`, `"https"`, `"tcp"` or
292 | `"tls"`), or `nil`, if no route has been matched, which can happen when dealing with
293 | erroneous requests.
294 |
295 | Phases:
296 | access, header_filter, response, body_filter, log
297 |
298 | Example:
299 | kong.client.get_protocol() # "http"
300 |
301 | :parameter allow_terminated: If set, the `X-Forwarded-Proto` header is checked when checking for HTTPS.
302 | :type allow_terminated: bool
303 |
304 | :return: Can be one of `"http"`, `"https"`, `"tcp"`, `"tls"` or `nil`.
305 |
306 | :rtype: str
307 | :return: `nil` if successful, or an error message if it fails.
308 |
309 | :rtype: err
310 | """
311 | pass
312 |
313 | @staticmethod
314 | def load_consumer(consumer_id: str, search_by_username: Optional[bool]) -> Tuple[table, err]:
315 | """
316 |
317 | Returns the consumer from the datastore.
318 | Looks up the consumer by ID, and can optionally do a second search by name.
319 |
320 | Phases:
321 | access, header_filter, response, body_filter, log
322 |
323 | Example:
324 | consumer_id = "john_doe"
325 |
326 | consumer = kong.client.load_consumer(consumer_id, true)
327 |
328 | :parameter consumer_id: The consumer ID to look up.
329 | :type consumer_id: str
330 | :parameter search_by_username: If truthy,
331 | and if the consumer is not found by ID,
332 | then a second search by username will be performed.
333 | :type search_by_username: bool
334 |
335 | :return: Consumer entity or `nil`.
336 |
337 | :rtype: table
338 | :return: `nil` if successful, or an error message if it fails.
339 |
340 | :rtype: err
341 | """
342 | pass
343 |
344 | @staticmethod
345 | def set_authenticated_consumer_group(group: table) -> None:
346 | """
347 |
348 | This function is deprecated in favor of `set_authenticated_consumer_groups`.
349 | Explicitly sets the authenticated consumer group for the current request.
350 | Throws an error if the `group` is neither a table nor `nil`.
351 |
352 | Phases:
353 | auth_and_later
354 |
355 | Example:
356 | # assuming `group` is provided by some code
357 |
358 | kong.client.set_authenticated_consumer_group(group)
359 |
360 | :parameter group: The consumer group to set. If no
361 | value is provided, then any existing value will be cleared.
362 | this value should be a table with metadata of the group like its `id` and `name`.
363 | :type group: table
364 |
365 | """
366 | pass
367 |
368 | @staticmethod
369 | def set_authenticated_consumer_groups(groups: table) -> None:
370 | """
371 |
372 | Explicitly sets the authenticated consumer groups for the current request.
373 | Throws an error if the `groups` parameter is neither a table nor `nil`.
374 |
375 | Phases:
376 | auth_and_later
377 |
378 | Example:
379 | kong.client.set_authenticated_consumer_groups({
380 |
381 | {
382 |
383 | id = "fed2bf38-10c4-404e-8d45-a2b0f521464d",
384 |
385 | name = "my-group",
386 |
387 | },
388 |
389 | {
390 |
391 | id = "736bb9d9-98f2-46d5-97fc-d7361d9488ee",
392 |
393 | name = "my-other-group",
394 |
395 | }
396 |
397 | })
398 |
399 | :parameter groups: The consumer groups to set. If no
400 | value is provided, then any existing value will be cleared.
401 | This value should be a sequence-like table of tables, with each item
402 | having at least an `id` and a `name`.
403 | :type groups: table
404 |
405 | """
406 | pass
407 |
408 | pass
409 |
--------------------------------------------------------------------------------
/kong_pdk/pdk/kong/client/tls.py:
--------------------------------------------------------------------------------
1 | # AUTO GENERATED BASED ON Kong 3.8.x, DO NOT EDIT
2 | # Original source path: kong/pdk/client/tls.lua
3 |
4 | from typing import TypeVar, Any, Union, List, Mapping, Tuple, Optional
5 |
6 | number = TypeVar('number', int, float)
7 | table = TypeVar('table', List[Any], Mapping[str, Any])
8 | # XXX
9 | cdata = Any
10 | err = str
11 |
12 |
13 | class tls():
14 |
15 |
16 | @staticmethod
17 | def disable_session_reuse() -> Tuple[bool, err]:
18 | """
19 |
20 | Prevents the TLS session for the current connection from being reused
21 | by disabling the session ticket and session ID for the current TLS connection.
22 |
23 | Phases:
24 | certificate
25 |
26 | Example:
27 | res, err = kong.client.tls.disable_session_reuse()
28 |
29 | if not res:
30 |
31 | # do something with err
32 |
33 | :return: Returns `true` if successful, `nil` if it fails.
34 |
35 | :rtype: bool
36 | :return: Returns `nil` if successful, or an error message if it fails.
37 |
38 | :rtype: err
39 | """
40 | pass
41 |
42 | @staticmethod
43 | def get_full_client_certificate_chain() -> Tuple[str, err]:
44 | """
45 |
46 | Returns the PEM encoded downstream client certificate chain with the
47 | client certificate at the top and intermediate certificates
48 | (if any) at the bottom.
49 |
50 | Phases:
51 | rewrite, access, balancer, header_filter, body_filter, log
52 |
53 | Example:
54 | cert, err = kong.client.tls.get_full_client_certificate_chain()
55 |
56 | if err:
57 |
58 | # do something with errif not cert:
59 |
60 | # client did not complete mTLS# do something with cert
61 |
62 | :return: Returns a PEM-encoded client certificate if the mTLS
63 | handshake was completed, or `nil` if an error occurred or the client did
64 | not present its certificate.
65 |
66 | :rtype: str
67 | :return: Returns `nil` if successful, or an error message if it fails.
68 |
69 | :rtype: err
70 | """
71 | pass
72 |
73 | @staticmethod
74 | def request_client_certificate(ca_certs: Optional[cdata]) -> Tuple[bool, err]:
75 | """
76 |
77 | Requests the client to present its client-side certificate to initiate mutual
78 | TLS authentication between server and client.
79 | This function *requests*, but does not *require* the client to start
80 | the mTLS process. The TLS handshake can still complete even if the client
81 | doesn't present a client certificate. However, in that case, it becomes a
82 | TLS connection instead of an mTLS connection, as there is no mutual
83 | authentication.
84 | To find out whether the client honored the request, use
85 | `get_full_client_certificate_chain` in later phases.
86 | The `ca_certs` argument is the optional CA certificate chain opaque pointer,
87 | which can be created by the [parse_pem_cert](https://github.com/openresty/lua-resty-core/blob/master/lib/ngx/ssl.md#parse_pem_cert)
88 | or [resty.opensslx509.chain](https://github.com/fffonion/lua-resty-openssl#restyopensslx509chain)
89 | The Distinguished Name (DN) list hints of the CA certificates will be sent to clients.
90 | If omitted, will not send any DN list to clients.
91 |
92 | Phases:
93 | certificate
94 |
95 | Example:
96 | x509_lib = require "resty.openssl.x509"
97 |
98 | chain_lib = require "resty.openssl.x509.chain"
99 |
100 | res, err
101 |
102 | chain = chain_lib.new()
103 |
104 | # err check
105 |
106 | x509, err = x509_lib.new(pem_cert, "PEM")
107 |
108 | # err check
109 |
110 | res, err = chain:add(x509)
111 |
112 | # err check
113 |
114 | # `chain.ctx` is the raw data of the chain, i.e. `STACK_OF(X509) *`
115 |
116 | res, err = kong.client.tls.request_client_certificate(chain.ctx)
117 |
118 | if not res:
119 |
120 | # do something with err
121 |
122 | :parameter ca_certs: The CA certificate chain opaque pointer
123 | :type ca_certs: cdata
124 |
125 | :return: Returns `true` if successful, or `nil` if it fails.
126 |
127 | :rtype: bool
128 | :return: Returns `nil` if successful, or an error message if it fails.
129 |
130 | :rtype: err
131 | """
132 | pass
133 |
134 | @staticmethod
135 | def set_client_verify() -> None:
136 | """
137 |
138 | Overrides the client's verification result generated by the log serializer.
139 | By default, the `request.tls.client_verify` field inside the log
140 | generated by Kong's log serializer is the same as the
141 | [$ssl_client_verify](https://nginx.org/en/docs/http/ngx_http_ssl_module.html#var_ssl_client_verify)
142 | Nginx variable.
143 | Only `"SUCCESS"`, `"NONE"`, or `"FAILED:"` are accepted values.
144 | This function does not return anything on success, and throws a Lua error
145 | in case of a failure.
146 |
147 | Phases:
148 | rewrite, access, balancer
149 |
150 | Example:
151 | kong.client.tls.set_client_verify("FAILED:unknown CA")
152 |
153 | """
154 | pass
155 |
156 | pass
157 |
--------------------------------------------------------------------------------
/kong_pdk/pdk/kong/cluster.py:
--------------------------------------------------------------------------------
1 | # AUTO GENERATED BASED ON Kong 3.8.x, DO NOT EDIT
2 | # Original source path: kong/pdk/cluster.lua
3 |
4 | from typing import TypeVar, Any, Union, List, Mapping, Tuple, Optional
5 |
6 | number = TypeVar('number', int, float)
7 | table = TypeVar('table', List[Any], Mapping[str, Any])
8 | # XXX
9 | cdata = Any
10 | err = str
11 |
12 |
13 | class cluster():
14 |
15 |
16 | @staticmethod
17 | def get_id() -> Tuple[str, str]:
18 | """
19 |
20 | Returns the unique ID for this Kong cluster. If Kong
21 | is running in DB-less mode without a cluster ID explicitly defined,
22 | then this method returns `nil`.
23 | For hybrid mode, all control planes and data planes belonging to the same
24 | cluster return the same cluster ID. For traditional database-based
25 | deployments, all Kong nodes pointing to the same database also return
26 | the same cluster ID.
27 |
28 | Example:
29 | id, err = kong.cluster.get_id()
30 |
31 | if err:
32 |
33 | # handle errorif not id:
34 |
35 | # no cluster ID is available# use id here
36 |
37 | :return: The v4 UUID used by this cluster as its ID.
38 |
39 | :rtype: str
40 | :return: An error message.
41 |
42 | :rtype: str
43 | """
44 | pass
45 |
46 | pass
47 |
--------------------------------------------------------------------------------
/kong_pdk/pdk/kong/ctx/__init__.py:
--------------------------------------------------------------------------------
1 | # AUTO GENERATED BASED ON Kong 3.8.x, DO NOT EDIT
2 | # Original source path: kong/pdk/ctx.lua
3 |
4 | from typing import TypeVar, Any, Union, List, Mapping, Tuple, Optional
5 |
6 | number = TypeVar('number', int, float)
7 | table = TypeVar('table', List[Any], Mapping[str, Any])
8 | # XXX
9 | cdata = Any
10 | err = str
11 |
12 | from .shared import shared as cls_shared
13 |
14 | class ctx():
15 |
16 | shared = cls_shared
17 |
18 | pass
19 |
--------------------------------------------------------------------------------
/kong_pdk/pdk/kong/ctx/shared.py:
--------------------------------------------------------------------------------
1 | # AUTO GENERATED BASED ON Kong 3.8.x, DO NOT EDIT
2 | # Original source path: kong/pdk/ctx/shared.lua
3 |
4 | from typing import TypeVar, Any, Union, List, Mapping, Tuple, Optional
5 |
6 | number = TypeVar('number', int, float)
7 | table = TypeVar('table', List[Any], Mapping[str, Any])
8 | # XXX
9 | cdata = Any
10 | err = str
11 |
12 |
13 | class shared():
14 |
15 |
16 | @staticmethod
17 | def get(k: str) -> Any:
18 | """
19 |
20 | get a key-value pair from Kong's shared memory
21 |
22 | :parameter k: key for the ctx data
23 | :type k: str
24 |
25 | :return: the per-request context data in ngx.ctx
26 |
27 | :rtype: Any
28 | """
29 | pass
30 |
31 | @staticmethod
32 | def set(k: str, v: str) -> None:
33 | """
34 |
35 | set a key-value pair in Kong's shared memory
36 |
37 | :parameter k: key for the ctx data
38 | :type k: str
39 | :parameter v: value for the ctx data
40 | :type v: str
41 |
42 | """
43 | pass
44 |
45 | pass
46 |
--------------------------------------------------------------------------------
/kong_pdk/pdk/kong/enterprise_edition/__init__.py:
--------------------------------------------------------------------------------
1 | # AUTO GENERATED BASED ON Kong 3.8.x, DO NOT EDIT
2 | # Original source path: kong/pdk/enterprise_edition.lua
3 |
4 | from typing import TypeVar, Any, Union, List, Mapping, Tuple, Optional
5 |
6 | number = TypeVar('number', int, float)
7 | table = TypeVar('table', List[Any], Mapping[str, Any])
8 | # XXX
9 | cdata = Any
10 | err = str
11 |
12 | from .jwe import jwe as cls_jwe
13 |
14 | class enterprise_edition():
15 |
16 | jwe = cls_jwe
17 |
18 | pass
19 |
--------------------------------------------------------------------------------
/kong_pdk/pdk/kong/enterprise_edition/jwe.py:
--------------------------------------------------------------------------------
1 | # AUTO GENERATED BASED ON Kong 3.8.x, DO NOT EDIT
2 | # Original source path: kong/pdk/enterprise_edition/jwe.lua
3 |
4 | from typing import TypeVar, Any, Union, List, Mapping, Tuple, Optional
5 |
6 | number = TypeVar('number', int, float)
7 | table = TypeVar('table', List[Any], Mapping[str, Any])
8 | # XXX
9 | cdata = Any
10 | err = str
11 |
12 |
13 | class jwe():
14 |
15 |
16 | @staticmethod
17 | def decode(token: str) -> Tuple[str, str]:
18 | """
19 |
20 | This function will return a table that looks like this:
21 | ```
22 | {
23 | [1] = protected header (as it appears in token)
24 | [2] = encrypted key (as it appears in token)
25 | [3] = initialization vector (as it appears in token)
26 | [4] = ciphertext (as it appears in token)
27 | [5] = authentication tag (as it appears in token)
28 | protected = protected key (base64url decoded and json decoded)
29 | encrypted_key = encrypted key (base64url decoded)
30 | iv = initialization vector (base64url decoded)
31 | ciphertext = ciphertext (base64url decoded)
32 | tag = authentication tag (base64url decoded)
33 | aad = protected header (as it appears in token)
34 | }
35 | ```
36 | The original input can be reconstructed with:
37 | ```
38 | local token = table.concat(, ".")
39 | ```
40 | If there is not exactly 5 parts in JWT token, or any decoding fails,
41 | the error is returned.
42 | @usage
43 | local jwe = require "kong.enterprise_edition.jwe"
44 | local jwt, err = jwe.decode(
45 | "eyJhbGciOiJFQ0RILUVTIiwiZW5jIjoiQTI1NkdDTSIsImFwdSI6Ik1lUFhUS2oyWFR1NUktYldUSFI2bXci" ..
46 | "LCJhcHYiOiJmUHFoa2hfNkdjVFd1SG5YWFZBclVnIiwiZXBrIjp7Imt0eSI6IkVDIiwiY3J2IjoiUC0yNTYi" ..
47 | "LCJ4IjoiWWd3eF9NVXRLTW9NYUpNZXFhSjZjUFV1Z29oYkVVc0I1NndrRlpYRjVMNCIsInkiOiIxaEYzYzlR" ..
48 | "VEhELVozam1vYUp2THZwTGJqcVNaSW9KNmd4X2YtUzAtZ21RIn19..4ZrIopIhLi3LeXyE.-Ke4ofA.MI5lT" ..
49 | "kML5NIa-Twm-92F6Q")
50 | if jwt then
51 | print(jwt.protected.alg) -- outputs "ECDH-ES"
52 | end
53 |
54 | :parameter token: JWE encrypted JWT token
55 | :type token: str
56 |
57 | :return: A table containing JWT token parts decoded, or nil
58 |
59 | :rtype: str
60 | :return: Error message, or nil
61 |
62 | :rtype: str
63 | """
64 | pass
65 |
66 | @staticmethod
67 | def decrypt(key: Any, token: str) -> Tuple[str, str]:
68 | """
69 |
70 | Supported keys (`key` argument):
71 | * Supported key formats:
72 | * `JWK` (given as a `string` or `table`)
73 | * `PEM` (given as a `string`)
74 | * `DER` (given as a `string`)
75 | * Supported key types:
76 | * `RSA`
77 | * `EC`, supported curves:
78 | * `P-256`
79 | * `P-384`
80 | * `P-521`
81 | @usage
82 | local jwe = require "kong.enterprise_edition.jwe"
83 | local jwk = {
84 | kty = "EC",
85 | crv = "P-256",
86 | use = "enc",
87 | x = "MKBCTNIcKUSDii11ySs3526iDZ8AiTo7Tu6KPAqv7D4",
88 | y = "4Etl6SRW2YiLUrN5vfvVHuhp7x8PxltmWWlbbM4IFyM",
89 | d = "870MB6gfuTJ4HtUnUvYMyJpr5eUZNP4Bk43bVdj3eAE",
90 | }
91 | local plaintext, err = jwe.decrypt(jwk,
92 | "eyJhbGciOiJFQ0RILUVTIiwiZW5jIjoiQTI1NkdDTSIsImFwdSI6Ik1lUFhUS2oyWFR1NUktYldUSFI2bXci" ..
93 | "LCJhcHYiOiJmUHFoa2hfNkdjVFd1SG5YWFZBclVnIiwiZXBrIjp7Imt0eSI6IkVDIiwiY3J2IjoiUC0yNTYi" ..
94 | "LCJ4IjoiWWd3eF9NVXRLTW9NYUpNZXFhSjZjUFV1Z29oYkVVc0I1NndrRlpYRjVMNCIsInkiOiIxaEYzYzlR" ..
95 | "VEhELVozam1vYUp2THZwTGJqcVNaSW9KNmd4X2YtUzAtZ21RIn19..4ZrIopIhLi3LeXyE.-Ke4ofA.MI5lT" ..
96 | "kML5NIa-Twm-92F6Q")
97 | if plaintext then
98 | print(plaintext) -- outputs "hello"
99 | end
100 |
101 | :parameter key: Private key
102 | :type key: Any
103 | :parameter token: JWE encrypted JWT token
104 | :type token: str
105 |
106 | :return: JWT token payload in plaintext, or nil
107 |
108 | :rtype: str
109 | :return: Error message, or nil
110 |
111 | :rtype: str
112 | """
113 | pass
114 |
115 | @staticmethod
116 | def encrypt(alg: str, enc: str, key: Any, plaintext: str, options: Optional[table]) -> Tuple[str, str]:
117 | """
118 |
119 | Supported algorithms (`alg` argument):
120 | * `"RSA-OAEP"`
121 | * `"ECDH-ES"`
122 | Supported encryption algorithms (`enc` argument):
123 | * `"A256GCM"`
124 | Supported keys (`key` argument):
125 | * Supported key formats:
126 | * `JWK` (given as a `string` or `table`)
127 | * `PEM` (given as a `string`)
128 | * `DER` (given as a `string`)
129 | * Supported key types:
130 | * `RSA`
131 | * `EC`, supported curves:
132 | * `P-256`
133 | * `P-384`
134 | * `P-521`
135 | Supported options (`options` argument):
136 | * `{ zip = "DEF" }`: whether to deflate the plaintext before encrypting
137 | * `{ apu = }`: Agreement PartyUInfo header parameter
138 | * `{ apv = }`: Agreement PartyVInfo header parameter
139 | The `apu` and `apv` can also be set to `false` to prevent them from
140 | being auto-generated (sixteen random bytes) and added to ephemeral
141 | public key.
142 | @usage
143 | local jwe = require "kong.enterprise_edition.jwe"
144 | local jwk = {
145 | kty = "EC",
146 | crv = "P-256",
147 | use = "enc",
148 | x = "MKBCTNIcKUSDii11ySs3526iDZ8AiTo7Tu6KPAqv7D4",
149 | y = "4Etl6SRW2YiLUrN5vfvVHuhp7x8PxltmWWlbbM4IFyM",
150 | }
151 | local token, err = jwe.encrypt("ECDH-ES", "A256GCM", jwk, "hello", {
152 | zip = "DEF,
153 | })
154 | if token then
155 | print(token)
156 | end
157 |
158 | :parameter alg: Algorithm used for key management
159 | :type alg: str
160 | :parameter enc: Encryption algorithm used for content encryption
161 | :type enc: str
162 | :parameter key: Public key
163 | :type key: Any
164 | :parameter plaintext: Plaintext
165 | :type plaintext: str
166 | :parameter options: Options (optional), default: nil
167 | :type options: table
168 |
169 | :return: JWE encrypted JWT token, or nil
170 |
171 | :rtype: str
172 | :return: Error message, or nil
173 |
174 | :rtype: str
175 | """
176 | pass
177 |
178 | pass
179 |
--------------------------------------------------------------------------------
/kong_pdk/pdk/kong/ip.py:
--------------------------------------------------------------------------------
1 | # AUTO GENERATED BASED ON Kong 3.8.x, DO NOT EDIT
2 | # Original source path: kong/pdk/ip.lua
3 |
4 | from typing import TypeVar, Any, Union, List, Mapping, Tuple, Optional
5 |
6 | number = TypeVar('number', int, float)
7 | table = TypeVar('table', List[Any], Mapping[str, Any])
8 | # XXX
9 | cdata = Any
10 | err = str
11 |
12 |
13 | class ip():
14 |
15 |
16 | @staticmethod
17 | def is_trusted(address: str) -> bool:
18 | """
19 |
20 | Depending on the `trusted_ips` configuration property,
21 | this function returns whether a given IP is trusted or not.
22 | Both ipv4 and ipv6 are supported.
23 |
24 | Phases:
25 | init_worker, certificate, rewrite, access, header_filter, response, body_filter, log
26 |
27 | Example:
28 | if kong.ip.is_trusted("1.1.1.1"):
29 |
30 | kong.log("The IP is trusted")
31 |
32 | :parameter address: A string representing an IP address.
33 | :type address: str
34 |
35 | :return: `true` if the IP is trusted, `false` otherwise.
36 |
37 | :rtype: bool
38 | """
39 | pass
40 |
41 | pass
42 |
--------------------------------------------------------------------------------
/kong_pdk/pdk/kong/log.py:
--------------------------------------------------------------------------------
1 | # AUTO GENERATED BASED ON Kong 3.8.x, DO NOT EDIT
2 | # Original source path: kong/pdk/log.lua
3 |
4 | from typing import TypeVar, Any, Union, List, Mapping, Tuple, Optional
5 |
6 | number = TypeVar('number', int, float)
7 | table = TypeVar('table', List[Any], Mapping[str, Any])
8 | # XXX
9 | cdata = Any
10 | err = str
11 |
12 |
13 | class log():
14 |
15 |
16 | @staticmethod
17 | def alert(*args: Any) -> None:
18 | """
19 |
20 | Similar to `kong.log()`, but the produced log has the severity given by
21 | ``, instead of `notice`. The supported levels are:
22 | * `kong.log.alert()`
23 | * `kong.log.crit()`
24 | * `kong.log.err()`
25 | * `kong.log.warn()`
26 | * `kong.log.notice()`
27 | * `kong.log.info()`
28 | * `kong.log.debug()`
29 | Logs have the same format as that of `kong.log()`. For
30 | example, the following call:
31 | ``` lua
32 | kong.log.err("hello ", "world")
33 | ```
34 | would, within the core, produce a log line similar to:
35 | ``` plain
36 | 2017/07/09 19:36:25 [error] 25932#0: *1 [kong] some_file.lua:54 hello world, client: 127.0.0.1, server: localhost, request: "GET /log HTTP/1.1", host: "localhost"
37 | ```
38 | If invoked from within a plugin (for example, `key-auth`) it would include the
39 | namespace prefix:
40 | ``` plain
41 | 2017/07/09 19:36:25 [error] 25932#0: *1 [kong] some_file.lua:54 [key-auth] hello world, client: 127.0.0.1, server: localhost, request: "GET /log HTTP/1.1", host: "localhost"
42 | ```
43 |
44 | Phases:
45 | init_worker, certificate, rewrite, access, header_filter, response, body_filter, log
46 |
47 | Example:
48 | kong.log.warn("something require attention")
49 |
50 | kong.log.err("something failed: ", err)
51 |
52 | kong.log.alert("something requires immediate action")
53 |
54 | :parameter *args: All params will be concatenated and stringified before being sent to the log.
55 | :type *args: Any
56 |
57 | :return: Throws an error on invalid inputs.
58 |
59 | :rtype: None
60 | """
61 | pass
62 |
63 | @staticmethod
64 | def crit(*args: Any) -> None:
65 | """
66 |
67 | Similar to `kong.log()`, but the produced log has the severity given by
68 | ``, instead of `notice`. The supported levels are:
69 | * `kong.log.alert()`
70 | * `kong.log.crit()`
71 | * `kong.log.err()`
72 | * `kong.log.warn()`
73 | * `kong.log.notice()`
74 | * `kong.log.info()`
75 | * `kong.log.debug()`
76 | Logs have the same format as that of `kong.log()`. For
77 | example, the following call:
78 | ``` lua
79 | kong.log.err("hello ", "world")
80 | ```
81 | would, within the core, produce a log line similar to:
82 | ``` plain
83 | 2017/07/09 19:36:25 [error] 25932#0: *1 [kong] some_file.lua:54 hello world, client: 127.0.0.1, server: localhost, request: "GET /log HTTP/1.1", host: "localhost"
84 | ```
85 | If invoked from within a plugin (for example, `key-auth`) it would include the
86 | namespace prefix:
87 | ``` plain
88 | 2017/07/09 19:36:25 [error] 25932#0: *1 [kong] some_file.lua:54 [key-auth] hello world, client: 127.0.0.1, server: localhost, request: "GET /log HTTP/1.1", host: "localhost"
89 | ```
90 |
91 | Phases:
92 | init_worker, certificate, rewrite, access, header_filter, response, body_filter, log
93 |
94 | Example:
95 | kong.log.warn("something require attention")
96 |
97 | kong.log.err("something failed: ", err)
98 |
99 | kong.log.alert("something requires immediate action")
100 |
101 | :parameter *args: All params will be concatenated and stringified before being sent to the log.
102 | :type *args: Any
103 |
104 | :return: Throws an error on invalid inputs.
105 |
106 | :rtype: None
107 | """
108 | pass
109 |
110 | @staticmethod
111 | def debug(*args: Any) -> None:
112 | """
113 |
114 | Similar to `kong.log()`, but the produced log has the severity given by
115 | ``, instead of `notice`. The supported levels are:
116 | * `kong.log.alert()`
117 | * `kong.log.crit()`
118 | * `kong.log.err()`
119 | * `kong.log.warn()`
120 | * `kong.log.notice()`
121 | * `kong.log.info()`
122 | * `kong.log.debug()`
123 | Logs have the same format as that of `kong.log()`. For
124 | example, the following call:
125 | ``` lua
126 | kong.log.err("hello ", "world")
127 | ```
128 | would, within the core, produce a log line similar to:
129 | ``` plain
130 | 2017/07/09 19:36:25 [error] 25932#0: *1 [kong] some_file.lua:54 hello world, client: 127.0.0.1, server: localhost, request: "GET /log HTTP/1.1", host: "localhost"
131 | ```
132 | If invoked from within a plugin (for example, `key-auth`) it would include the
133 | namespace prefix:
134 | ``` plain
135 | 2017/07/09 19:36:25 [error] 25932#0: *1 [kong] some_file.lua:54 [key-auth] hello world, client: 127.0.0.1, server: localhost, request: "GET /log HTTP/1.1", host: "localhost"
136 | ```
137 |
138 | Phases:
139 | init_worker, certificate, rewrite, access, header_filter, response, body_filter, log
140 |
141 | Example:
142 | kong.log.warn("something require attention")
143 |
144 | kong.log.err("something failed: ", err)
145 |
146 | kong.log.alert("something requires immediate action")
147 |
148 | :parameter *args: All params will be concatenated and stringified before being sent to the log.
149 | :type *args: Any
150 |
151 | :return: Throws an error on invalid inputs.
152 |
153 | :rtype: None
154 | """
155 | pass
156 |
157 | @staticmethod
158 | def deprecation(*args: Any) -> None:
159 | """
160 |
161 | Arguments given to this function can be of any type, but table arguments
162 | are converted to strings via `tostring` (thus potentially calling a
163 | table's `__tostring` metamethod if set). When the last argument is a table,
164 | it is considered as a deprecation metadata. The table can include the
165 | following properties:
166 | ``` lua
167 | {
168 | after = "2.5.0", -- deprecated after Kong version 2.5.0 (defaults to `nil`)
169 | removal = "3.0.0", -- about to be removed with Kong version 3.0.0 (defaults to `nil`)
170 | trace = true, -- writes stack trace along with the deprecation message (defaults to `nil`)
171 | }
172 | ```
173 | For example, the following call:
174 | ``` lua
175 | kong.log.deprecation("hello ", "world")
176 | ```
177 | would, within the core, produce a log line similar to:
178 | ``` plain
179 | 2017/07/09 19:36:25 [warn] 25932#0: *1 [kong] some_file.lua:54 hello world, client: 127.0.0.1, server: localhost, request: "GET /log HTTP/1.1", host: "localhost"
180 | ```
181 | If invoked from within a plugin (for example, `key-auth`) it would include the
182 | namespace prefix:
183 | ``` plain
184 | 2017/07/09 19:36:25 [warn] 25932#0: *1 [kong] some_file.lua:54 [key-auth] hello world, client: 127.0.0.1, server: localhost, request: "GET /log HTTP/1.1", host: "localhost"
185 | ```
186 | And with metatable, the following call:
187 | ``` lua
188 | kong.log.deprecation("hello ", "world", { after = "2.5.0", removal = "3.0.0" })
189 | ```
190 | would, within the core, produce a log line similar to:
191 | ``` plain
192 | 2017/07/09 19:36:25 [warn] 25932#0: *1 [kong] some_file.lua:54 hello world (deprecated after 2.5.0, scheduled for removal in 3.0.0), client: 127.0.0.1, server: localhost, request: "GET /log HTTP/1.1", host: "localhost"
193 | ```
194 |
195 | Phases:
196 | init_worker, certificate, rewrite, access, header_filter, response, body_filter, log
197 |
198 | Example:
199 | kong.log.deprecation("hello ", "world")
200 |
201 | kong.log.deprecation("hello ", "world", { after = "2.5.0" })
202 |
203 | kong.log.deprecation("hello ", "world", { removal = "3.0.0" })
204 |
205 | kong.log.deprecation("hello ", "world", { after = "2.5.0", removal = "3.0.0" })
206 |
207 | kong.log.deprecation("hello ", "world", { trace = true })
208 |
209 | :parameter *args: all params will be concatenated and stringified before being sent to the log
210 | (if the last param is a table, it is considered as a deprecation metadata)
211 | :type *args: Any
212 |
213 | :return: throws an error on invalid inputs.
214 |
215 | :rtype: None
216 | """
217 | pass
218 |
219 | @staticmethod
220 | def err(*args: Any) -> None:
221 | """
222 |
223 | Similar to `kong.log()`, but the produced log has the severity given by
224 | ``, instead of `notice`. The supported levels are:
225 | * `kong.log.alert()`
226 | * `kong.log.crit()`
227 | * `kong.log.err()`
228 | * `kong.log.warn()`
229 | * `kong.log.notice()`
230 | * `kong.log.info()`
231 | * `kong.log.debug()`
232 | Logs have the same format as that of `kong.log()`. For
233 | example, the following call:
234 | ``` lua
235 | kong.log.err("hello ", "world")
236 | ```
237 | would, within the core, produce a log line similar to:
238 | ``` plain
239 | 2017/07/09 19:36:25 [error] 25932#0: *1 [kong] some_file.lua:54 hello world, client: 127.0.0.1, server: localhost, request: "GET /log HTTP/1.1", host: "localhost"
240 | ```
241 | If invoked from within a plugin (for example, `key-auth`) it would include the
242 | namespace prefix:
243 | ``` plain
244 | 2017/07/09 19:36:25 [error] 25932#0: *1 [kong] some_file.lua:54 [key-auth] hello world, client: 127.0.0.1, server: localhost, request: "GET /log HTTP/1.1", host: "localhost"
245 | ```
246 |
247 | Phases:
248 | init_worker, certificate, rewrite, access, header_filter, response, body_filter, log
249 |
250 | Example:
251 | kong.log.warn("something require attention")
252 |
253 | kong.log.err("something failed: ", err)
254 |
255 | kong.log.alert("something requires immediate action")
256 |
257 | :parameter *args: All params will be concatenated and stringified before being sent to the log.
258 | :type *args: Any
259 |
260 | :return: Throws an error on invalid inputs.
261 |
262 | :rtype: None
263 | """
264 | pass
265 |
266 | @staticmethod
267 | def info(*args: Any) -> None:
268 | """
269 |
270 | Similar to `kong.log()`, but the produced log has the severity given by
271 | ``, instead of `notice`. The supported levels are:
272 | * `kong.log.alert()`
273 | * `kong.log.crit()`
274 | * `kong.log.err()`
275 | * `kong.log.warn()`
276 | * `kong.log.notice()`
277 | * `kong.log.info()`
278 | * `kong.log.debug()`
279 | Logs have the same format as that of `kong.log()`. For
280 | example, the following call:
281 | ``` lua
282 | kong.log.err("hello ", "world")
283 | ```
284 | would, within the core, produce a log line similar to:
285 | ``` plain
286 | 2017/07/09 19:36:25 [error] 25932#0: *1 [kong] some_file.lua:54 hello world, client: 127.0.0.1, server: localhost, request: "GET /log HTTP/1.1", host: "localhost"
287 | ```
288 | If invoked from within a plugin (for example, `key-auth`) it would include the
289 | namespace prefix:
290 | ``` plain
291 | 2017/07/09 19:36:25 [error] 25932#0: *1 [kong] some_file.lua:54 [key-auth] hello world, client: 127.0.0.1, server: localhost, request: "GET /log HTTP/1.1", host: "localhost"
292 | ```
293 |
294 | Phases:
295 | init_worker, certificate, rewrite, access, header_filter, response, body_filter, log
296 |
297 | Example:
298 | kong.log.warn("something require attention")
299 |
300 | kong.log.err("something failed: ", err)
301 |
302 | kong.log.alert("something requires immediate action")
303 |
304 | :parameter *args: All params will be concatenated and stringified before being sent to the log.
305 | :type *args: Any
306 |
307 | :return: Throws an error on invalid inputs.
308 |
309 | :rtype: None
310 | """
311 | pass
312 |
313 | @staticmethod
314 | def notice(*args: Any) -> None:
315 | """
316 |
317 | Similar to `kong.log()`, but the produced log has the severity given by
318 | ``, instead of `notice`. The supported levels are:
319 | * `kong.log.alert()`
320 | * `kong.log.crit()`
321 | * `kong.log.err()`
322 | * `kong.log.warn()`
323 | * `kong.log.notice()`
324 | * `kong.log.info()`
325 | * `kong.log.debug()`
326 | Logs have the same format as that of `kong.log()`. For
327 | example, the following call:
328 | ``` lua
329 | kong.log.err("hello ", "world")
330 | ```
331 | would, within the core, produce a log line similar to:
332 | ``` plain
333 | 2017/07/09 19:36:25 [error] 25932#0: *1 [kong] some_file.lua:54 hello world, client: 127.0.0.1, server: localhost, request: "GET /log HTTP/1.1", host: "localhost"
334 | ```
335 | If invoked from within a plugin (for example, `key-auth`) it would include the
336 | namespace prefix:
337 | ``` plain
338 | 2017/07/09 19:36:25 [error] 25932#0: *1 [kong] some_file.lua:54 [key-auth] hello world, client: 127.0.0.1, server: localhost, request: "GET /log HTTP/1.1", host: "localhost"
339 | ```
340 |
341 | Phases:
342 | init_worker, certificate, rewrite, access, header_filter, response, body_filter, log
343 |
344 | Example:
345 | kong.log.warn("something require attention")
346 |
347 | kong.log.err("something failed: ", err)
348 |
349 | kong.log.alert("something requires immediate action")
350 |
351 | :parameter *args: All params will be concatenated and stringified before being sent to the log.
352 | :type *args: Any
353 |
354 | :return: Throws an error on invalid inputs.
355 |
356 | :rtype: None
357 | """
358 | pass
359 |
360 | @staticmethod
361 | def serialize() -> None:
362 | """
363 |
364 | """
365 | pass
366 |
367 | @staticmethod
368 | def set_serialize_value(key: str, value: Any, options: table) -> table:
369 | """
370 |
371 | Sets a value to be used on the `serialize` custom table.
372 | Logging plugins use the output of `kong.log.serialize()` as a base for their logs.
373 | This function lets you customize the log output.
374 | It can be used to replace existing values in the output, or to delete
375 | existing values by passing `nil`.
376 | **Note:** The type-checking of the `value` parameter can take some time, so
377 | it is deferred to the `serialize()` call, which happens in the log
378 | phase in most real-usage cases.
379 |
380 | Phases:
381 | certificate, rewrite, access, header_filter, response, body_filter, log
382 |
383 | Example:
384 | # Adds a new value to the serialized table
385 |
386 | kong.log.set_serialize_value("my_new_value", 1)
387 |
388 | assert(kong.log.serialize().my_new_value == 1)
389 |
390 | # Value can be a table
391 |
392 | kong.log.set_serialize_value("my", { new = { value = 2 } })
393 |
394 | assert(kong.log.serialize().my.new.value == 2)
395 |
396 | # It is possible to change an existing serialized value
397 |
398 | kong.log.set_serialize_value("my_new_value", 3)
399 |
400 | assert(kong.log.serialize().my_new_value == 3)
401 |
402 | # Unset an existing value by setting it to nil
403 |
404 | kong.log.set_serialize_value("my_new_value", nil)
405 |
406 | assert(kong.log.serialize().my_new_value == nil)
407 |
408 | # Dots in the key are interpreted as table accesses
409 |
410 | kong.log.set_serialize_value("my.new.value", 4)
411 |
412 | assert(kong.log.serialize().my.new_value == 4)
413 |
414 | :parameter key: The name of the field.
415 | :type key: str
416 | :parameter value: Value to be set. When a table is used, its keys must be numbers, strings, or booleans, and its values can be numbers, strings, or other tables like itself, recursively.
417 | :type value: Any
418 | :parameter options: Can contain two entries: options.mode can be `set` (the default, always sets), `add` (only add if entry does not already exist) and `replace` (only change value if it already exists).
419 | :type options: table
420 |
421 | :return: The request information table.
422 |
423 | :rtype: table
424 | """
425 | pass
426 |
427 | @staticmethod
428 | def warn(*args: Any) -> None:
429 | """
430 |
431 | Similar to `kong.log()`, but the produced log has the severity given by
432 | ``, instead of `notice`. The supported levels are:
433 | * `kong.log.alert()`
434 | * `kong.log.crit()`
435 | * `kong.log.err()`
436 | * `kong.log.warn()`
437 | * `kong.log.notice()`
438 | * `kong.log.info()`
439 | * `kong.log.debug()`
440 | Logs have the same format as that of `kong.log()`. For
441 | example, the following call:
442 | ``` lua
443 | kong.log.err("hello ", "world")
444 | ```
445 | would, within the core, produce a log line similar to:
446 | ``` plain
447 | 2017/07/09 19:36:25 [error] 25932#0: *1 [kong] some_file.lua:54 hello world, client: 127.0.0.1, server: localhost, request: "GET /log HTTP/1.1", host: "localhost"
448 | ```
449 | If invoked from within a plugin (for example, `key-auth`) it would include the
450 | namespace prefix:
451 | ``` plain
452 | 2017/07/09 19:36:25 [error] 25932#0: *1 [kong] some_file.lua:54 [key-auth] hello world, client: 127.0.0.1, server: localhost, request: "GET /log HTTP/1.1", host: "localhost"
453 | ```
454 |
455 | Phases:
456 | init_worker, certificate, rewrite, access, header_filter, response, body_filter, log
457 |
458 | Example:
459 | kong.log.warn("something require attention")
460 |
461 | kong.log.err("something failed: ", err)
462 |
463 | kong.log.alert("something requires immediate action")
464 |
465 | :parameter *args: All params will be concatenated and stringified before being sent to the log.
466 | :type *args: Any
467 |
468 | :return: Throws an error on invalid inputs.
469 |
470 | :rtype: None
471 | """
472 | pass
473 |
474 | pass
475 |
--------------------------------------------------------------------------------
/kong_pdk/pdk/kong/nginx/__init__.py:
--------------------------------------------------------------------------------
1 | # AUTO GENERATED BASED ON Kong 3.8.x, DO NOT EDIT
2 | # Original source path: kong/pdk/nginx.lua
3 |
4 | from typing import TypeVar, Any, Union, List, Mapping, Tuple, Optional
5 |
6 | number = TypeVar('number', int, float)
7 | table = TypeVar('table', List[Any], Mapping[str, Any])
8 | # XXX
9 | cdata = Any
10 | err = str
11 |
12 | from .shared import shared as cls_shared
13 |
14 | class nginx():
15 |
16 | shared = cls_shared
17 |
18 | @staticmethod
19 | def get_ctx(k: str) -> Any:
20 | """
21 |
22 | get a key-value pair from Kong's per-request context
23 |
24 | :parameter k: key for the ctx data
25 | :type k: str
26 |
27 | :return: the per-request context data in ngx.ctx
28 |
29 | :rtype: Any
30 | """
31 | pass
32 |
33 | @staticmethod
34 | def get_statistics() -> table:
35 | """
36 |
37 | Returns various connection and request metrics exposed by
38 | Nginx, similar to those reported by the
39 | [ngx_http_stub_status_module](https://nginx.org/en/docs/http/ngx_http_stub_status_module.html#data).
40 | The following fields are included in the returned table:
41 | * `connections_active` - the current number of active client connections including `connections_waiting`.
42 | * `connections_reading` - the current number of connections where nginx is reading the request header.
43 | * `connections_writing` - the current number of connections where nginx is writing the response back to the client.
44 | * `connections_waiting` - the current number of idle client connections waiting for a request.
45 | * `connections_accepted` - the total number of accepted client connections.
46 | * `connections_handled` - the total number of handled connections. Same as `connections_accepted` unless some resource limits have been reached
47 | (for example, the [`worker_connections`](https://nginx.org/en/docs/ngx_core_module.html#worker_connections) limit).
48 | * `total_requests` - the total number of client requests.
49 |
50 | Example:
51 | nginx_statistics = kong.nginx.get_statistics()
52 |
53 | :return: Nginx connections and requests statistics
54 |
55 | :rtype: table
56 | """
57 | pass
58 |
59 | @staticmethod
60 | def get_subsystem() -> str:
61 | """
62 |
63 | :return: the subsystem name
64 |
65 | :rtype: str
66 | """
67 | pass
68 |
69 | @staticmethod
70 | def get_tls1_version_str() -> str:
71 | """
72 |
73 | :return: the TLSv1 version string
74 |
75 | :rtype: str
76 | """
77 | pass
78 |
79 | @staticmethod
80 | def get_var() -> str:
81 | """
82 |
83 | :return: get NGINX variable value
84 |
85 | :rtype: str
86 | """
87 | pass
88 |
89 | @staticmethod
90 | def req_start_time() -> number:
91 | """
92 |
93 | get the current request's start timestamp
94 |
95 | :return: req_start_time
96 |
97 | :rtype: number
98 | """
99 | pass
100 |
101 | @staticmethod
102 | def set_ctx(k: str, any: str) -> None:
103 | """
104 |
105 | set a key-value pair in Kong's per-request context
106 |
107 | :parameter k: key for the ctx data
108 | :type k: str
109 | :parameter any: value for the ctx data
110 | :type any: str
111 |
112 | """
113 | pass
114 |
115 | pass
116 |
--------------------------------------------------------------------------------
/kong_pdk/pdk/kong/nginx/shared.py:
--------------------------------------------------------------------------------
1 | # AUTO GENERATED BASED ON Kong 3.8.x, DO NOT EDIT
2 | # Original source path: kong/pdk/nginx/shared.lua
3 |
4 | from typing import TypeVar, Any, Union, List, Mapping, Tuple, Optional
5 |
6 | number = TypeVar('number', int, float)
7 | table = TypeVar('table', List[Any], Mapping[str, Any])
8 | # XXX
9 | cdata = Any
10 | err = str
11 |
12 |
13 | class shared():
14 |
15 |
16 | @staticmethod
17 | def get(k: str) -> Any:
18 | """
19 |
20 | get a key-value pair from Kong's shared memory
21 |
22 | :parameter k: key for the ctx data
23 | :type k: str
24 |
25 | :return: the per-request context data in ngx.ctx
26 |
27 | :rtype: Any
28 | """
29 | pass
30 |
31 | @staticmethod
32 | def set(k: str, v: str) -> None:
33 | """
34 |
35 | set a key-value pair in Kong's shared memory
36 |
37 | :parameter k: key for the ctx data
38 | :type k: str
39 | :parameter v: value for the ctx data
40 | :type v: str
41 |
42 | """
43 | pass
44 |
45 | pass
46 |
--------------------------------------------------------------------------------
/kong_pdk/pdk/kong/node.py:
--------------------------------------------------------------------------------
1 | # AUTO GENERATED BASED ON Kong 3.8.x, DO NOT EDIT
2 | # Original source path: kong/pdk/node.lua
3 |
4 | from typing import TypeVar, Any, Union, List, Mapping, Tuple, Optional
5 |
6 | number = TypeVar('number', int, float)
7 | table = TypeVar('table', List[Any], Mapping[str, Any])
8 | # XXX
9 | cdata = Any
10 | err = str
11 |
12 |
13 | class node():
14 |
15 |
16 | @staticmethod
17 | def get_hostname() -> str:
18 | """
19 |
20 | Returns the name used by the local machine.
21 |
22 | Example:
23 | hostname = kong.node.get_hostname()
24 |
25 | :return: The local machine hostname.
26 |
27 | :rtype: str
28 | """
29 | pass
30 |
31 | @staticmethod
32 | def get_id() -> str:
33 | """
34 |
35 | Returns the ID used by this node to describe itself.
36 |
37 | Example:
38 | id = kong.node.get_id()
39 |
40 | :return: The v4 UUID used by this node as its ID.
41 |
42 | :rtype: str
43 | """
44 | pass
45 |
46 | @staticmethod
47 | def get_memory_stats(unit: Optional[str], scale: Optional[number]) -> table:
48 | """
49 |
50 | Returns memory usage statistics about this node.
51 |
52 | Example:
53 | res = kong.node.get_memory_stats()
54 |
55 | # res will have the following structure:
56 |
57 | {
58 |
59 | lua_shared_dicts = {
60 |
61 | kong = {
62 |
63 | allocated_slabs = 12288,
64 |
65 | capacity = 24576
66 |
67 | },
68 |
69 | kong_db_cache = {
70 |
71 | allocated_slabs = 12288,
72 |
73 | capacity = 12288
74 |
75 | }
76 |
77 | },
78 |
79 | workers_lua_vms = {
80 |
81 | {
82 |
83 | http_allocated_gc = 1102,
84 |
85 | pid = 18004
86 |
87 | },
88 |
89 | {
90 |
91 | http_allocated_gc = 1102,
92 |
93 | pid = 18005
94 |
95 | }
96 |
97 | }
98 |
99 | }
100 |
101 | res = kong.node.get_memory_stats("k", 1)
102 |
103 | # res will have the following structure:
104 |
105 | {
106 |
107 | lua_shared_dicts = {
108 |
109 | kong = {
110 |
111 | allocated_slabs = "12.0 KiB",
112 |
113 | capacity = "24.0 KiB",
114 |
115 | },
116 |
117 | kong_db_cache = {
118 |
119 | allocated_slabs = "12.0 KiB",
120 |
121 | capacity = "12.0 KiB",
122 |
123 | }
124 |
125 | },
126 |
127 | workers_lua_vms = {
128 |
129 | {
130 |
131 | http_allocated_gc = "1.1 KiB",
132 |
133 | pid = 18004
134 |
135 | },
136 |
137 | {
138 |
139 | http_allocated_gc = "1.1 KiB",
140 |
141 | pid = 18005
142 |
143 | }
144 |
145 | }
146 |
147 | }
148 |
149 | :parameter unit: The unit that memory is reported in. Can be
150 | any of `b/B`, `k/K`, `m/M`, or `g/G` for bytes, kibibytes, mebibytes,
151 | or gibibytes, respectively. Defaults to `b` (bytes).
152 | :type unit: str
153 | :parameter scale: The number of digits to the right of the decimal
154 | point. Defaults to 2.
155 | :type scale: number
156 |
157 | :return: A table containing memory usage statistics for this node.
158 | If `unit` is `b/B` (the default), reported values are Lua numbers.
159 | Otherwise, reported values are strings with the unit as a suffix.
160 |
161 | :rtype: table
162 | """
163 | pass
164 |
165 | pass
166 |
--------------------------------------------------------------------------------
/kong_pdk/pdk/kong/plugin.py:
--------------------------------------------------------------------------------
1 | # AUTO GENERATED BASED ON Kong 3.8.x, DO NOT EDIT
2 | # Original source path: kong/pdk/plugin.lua
3 |
4 | from typing import TypeVar, Any, Union, List, Mapping, Tuple, Optional
5 |
6 | number = TypeVar('number', int, float)
7 | table = TypeVar('table', List[Any], Mapping[str, Any])
8 | # XXX
9 | cdata = Any
10 | err = str
11 |
12 |
13 | class plugin():
14 |
15 |
16 | @staticmethod
17 | def get_id() -> str:
18 | """
19 |
20 | Returns the instance ID of the plugin.
21 |
22 | Phases:
23 | rewrite, access, header_filter, response, body_filter, log
24 |
25 | Example:
26 | kong.plugin.get_id() # "123e4567-e89b-12d3-a456-426614174000"
27 |
28 | :return: The ID of the running plugin
29 |
30 | :rtype: str
31 | """
32 | pass
33 |
34 | pass
35 |
--------------------------------------------------------------------------------
/kong_pdk/pdk/kong/response.py:
--------------------------------------------------------------------------------
1 | # AUTO GENERATED BASED ON Kong 3.8.x, DO NOT EDIT
2 | # Original source path: kong/pdk/response.lua
3 |
4 | from typing import TypeVar, Any, Union, List, Mapping, Tuple, Optional
5 |
6 | number = TypeVar('number', int, float)
7 | table = TypeVar('table', List[Any], Mapping[str, Any])
8 | # XXX
9 | cdata = Any
10 | err = str
11 |
12 |
13 | class response():
14 |
15 |
16 | @staticmethod
17 | def add_header(name: str, of: table) -> None:
18 | """
19 |
20 | Adds a response header with the given value. Unlike
21 | `kong.response.set_header()`, this function does not remove any existing
22 | header with the same name. Instead, another header with the same name is
23 | added to the response. If no header with this name already exists on
24 | the response, then it is added with the given value, similarly to
25 | `kong.response.set_header().`
26 |
27 | Phases:
28 | rewrite, access, header_filter, response, admin_api
29 |
30 | Example:
31 | kong.response.add_header("Cache-Control", "no-cache")
32 |
33 | kong.response.add_header("Cache-Control", "no-store")
34 |
35 | :parameter name: The header name.
36 | :type name: str
37 | :parameter of: strings|string|number|boolean value The header value.
38 | :type of: table
39 |
40 | :return: throws an error on invalid input.
41 |
42 | :rtype: None
43 | """
44 | pass
45 |
46 | @staticmethod
47 | def clear_header(name: str) -> None:
48 | """
49 |
50 | Removes all occurrences of the specified header in the response sent to
51 | the client.
52 |
53 | Phases:
54 | rewrite, access, header_filter, response, admin_api
55 |
56 | Example:
57 | kong.response.set_header("X-Foo", "foo")
58 |
59 | kong.response.add_header("X-Foo", "bar")
60 |
61 | kong.response.clear_header("X-Foo")
62 |
63 | # from here onwards, no X-Foo headers will exist in the response
64 |
65 | :parameter name: The name of the header to be cleared
66 | :type name: str
67 |
68 | :return: throws an error on invalid input.
69 |
70 | :rtype: None
71 | """
72 | pass
73 |
74 | @staticmethod
75 | def error(status: number, message: Optional[str], headers: Optional[table]) -> None:
76 | """
77 |
78 | This function interrupts the current processing and produces an error
79 | response.
80 | It is recommended to use this function in conjunction with the `return`
81 | operator, to better reflect its meaning:
82 | ```lua
83 | return kong.response.error(500, "Error", {["Content-Type"] = "text/html"})
84 | ```
85 | 1. The `status` argument sets the status code of the response that
86 | is seen by the client. The status code must an error code, that is,
87 | greater than 399.
88 | 2. The optional `message` argument sets the message describing
89 | the error, which is written in the body.
90 | 3. The optional `headers` argument can be a table specifying response
91 | headers to send. If specified, its behavior is similar to
92 | `kong.response.set_headers()`.
93 | This method sends the response formatted in JSON, XML, HTML or plaintext.
94 | The actual format is determined using one of the following options, in
95 | this order:
96 | - Manually specified in the `headers` argument using the `Content-Type`
97 | header.
98 | - Conforming to the `Accept` header from the request.
99 | - If there is no setting in the `Content-Type` or `Accept` header, the
100 | response defaults to JSON format. Also see the `Content-Length`
101 | header in the produced response for convenience.
102 |
103 | Phases:
104 | rewrite, access, admin_api, header_filter, only, if, body, is, nil
105 |
106 | Example:
107 | return kong.response.error(403, "Access Forbidden", {
108 |
109 | ["Content-Type"] = "text/plain",
110 |
111 | ["WWW-Authenticate"] = "Basic"
112 |
113 | })
114 |
115 | # -
116 |
117 | return kong.response.error(403, "Access Forbidden")
118 |
119 | # -
120 |
121 | return kong.response.error(403)
122 |
123 | :parameter status: The status to be used (>399).
124 | :type status: number
125 | :parameter message: The error message to be used.
126 | :type message: str
127 | :parameter headers: The headers to be used.
128 | :type headers: table
129 |
130 | :return: throws an error on invalid input.
131 |
132 | :rtype: None
133 | """
134 | pass
135 |
136 | @staticmethod
137 | def exit(status: number, body: Optional[bytes], headers: Optional[table]) -> None:
138 | """
139 |
140 | This function interrupts the current processing and produces a response.
141 | It is typical to see plugins using it to produce a response before Kong
142 | has a chance to proxy the request (e.g. an authentication plugin rejecting
143 | a request, or a caching plugin serving a cached response).
144 | It is recommended to use this function in conjunction with the `return`
145 | operator, to better reflect its meaning:
146 | ```lua
147 | return kong.response.exit(200, "Success")
148 | ```
149 | Calling `kong.response.exit()` interrupts the execution flow of
150 | plugins in the current phase. Subsequent phases will still be invoked.
151 | For example, if a plugin calls `kong.response.exit()` in the `access`
152 | phase, no other plugin is executed in that phase, but the
153 | `header_filter`, `body_filter`, and `log` phases are still executed,
154 | along with their plugins. Plugins should be programmed defensively
155 | against cases when a request is **not** proxied to the Service, but
156 | instead is produced by Kong itself.
157 | 1. The first argument `status` sets the status code of the response that
158 | is seen by the client.
159 | In L4 proxy mode, the `status` code provided is primarily for logging
160 | and statistical purposes, and is not visible to the client directly.
161 | In this mode, only the following status codes are supported:
162 | * 200 - OK
163 | * 400 - Bad request
164 | * 403 - Forbidden
165 | * 500 - Internal server error
166 | * 502 - Bad gateway
167 | * 503 - Service unavailable
168 | 2. The second, optional, `body` argument sets the response body. If it is
169 | a string, no special processing is done, and the body is sent
170 | as-is. It is the caller's responsibility to set the appropriate
171 | `Content-Type` header via the third argument.
172 | As a convenience, `body` can be specified as a table. In that case,
173 | the `body` is JSON-encoded and has the `application/json` Content-Type
174 | header set.
175 | On gRPC, we cannot send the `body` with this function, so
176 | it sends `"body"` in the `grpc-message` header instead.
177 | * If the body is a table, it looks for the `message` field in the body,
178 | and uses that as a `grpc-message` header.
179 | * If you specify `application/grpc` in the `Content-Type` header, the
180 | body is sent without needing the `grpc-message` header.
181 | In L4 proxy mode, `body` can only be `nil` or a string. Automatic JSON
182 | encoding is not available. When `body` is provided, depending on the
183 | value of `status`, the following happens:
184 | * When `status` is 500, 502 or 503, then `body` is logged in the Kong
185 | error log file.
186 | * When the `status` is anything else, `body` is sent back to the L4 client.
187 | 3. The third, optional, `headers` argument can be a table specifying
188 | response headers to send. If specified, its behavior is similar to
189 | `kong.response.set_headers()`. This argument is ignored in L4 proxy mode.
190 | Unless manually specified, this method automatically sets the
191 | `Content-Length` header in the produced response for convenience.
192 |
193 | Phases:
194 | preread, rewrite, access, admin_api, header_filter, only, if, body, is, nil
195 |
196 | Example:
197 | return kong.response.exit(403, "Access Forbidden", {
198 |
199 | ["Content-Type"] = "text/plain",
200 |
201 | ["WWW-Authenticate"] = "Basic"
202 |
203 | })
204 |
205 | # -
206 |
207 | return kong.response.exit(403, [[{"message":"Access Forbidden"}]], {
208 |
209 | ["Content-Type"] = "application/json",
210 |
211 | ["WWW-Authenticate"] = "Basic"
212 |
213 | })
214 |
215 | # -
216 |
217 | return kong.response.exit(403, { message = "Access Forbidden" }, {
218 |
219 | ["WWW-Authenticate"] = "Basic"
220 |
221 | })
222 |
223 | # -
224 |
225 | # In L4 proxy mode
226 |
227 | return kong.response.exit(200, "Success")
228 |
229 | :parameter status: The status to be used.
230 | :type status: number
231 | :parameter body: The body to be used.
232 | :type body: bytes
233 | :parameter headers: The headers to be used.
234 | :type headers: table
235 |
236 | :return: throws an error on invalid input.
237 |
238 | :rtype: None
239 | """
240 | pass
241 |
242 | @staticmethod
243 | def get_header(name: str) -> str:
244 | """
245 |
246 | Returns the value of the specified response header, as would be seen by
247 | the client once received.
248 | The list of headers returned by this function can consist of both response
249 | headers from the proxied Service _and_ headers added by Kong (e.g. via
250 | `kong.response.add_header()`).
251 | The return value is either a `string`, or can be `nil` if a header with
252 | `name` is not found in the response. If a header with the same name is
253 | present multiple times in the request, this function returns the value
254 | of the first occurrence of this header.
255 |
256 | Phases:
257 | header_filter, response, body_filter, log, admin_api
258 |
259 | Example:
260 | # Given a response with the following headers:
261 |
262 | # X-Custom-Header: bla
263 |
264 | # X-Another: foo bar
265 |
266 | # X-Another: baz
267 |
268 | kong.response.get_header("x-custom-header") # "bla"
269 |
270 | kong.response.get_header("X-Another") # "foo bar"
271 |
272 | kong.response.get_header("X-None") # nil
273 |
274 | :parameter name: The name of the header.
275 | Header names are case-insensitive and dashes (`-`) can be written as
276 | underscores (`_`). For example, the header `X-Custom-Header` can also be
277 | retrieved as `x_custom_header`.
278 | :type name: str
279 |
280 | :return: The value of the header.
281 |
282 | :rtype: str
283 | """
284 | pass
285 |
286 | @staticmethod
287 | def get_headers(max_headers: Optional[number]) -> Tuple[table, str]:
288 | """
289 |
290 | Returns a Lua table holding the response headers. Keys are header names.
291 | Values are either a string with the header value, or an array of strings
292 | if a header was sent multiple times. Header names in this table are
293 | case-insensitive and are normalized to lowercase, and dashes (`-`) can be
294 | written as underscores (`_`). For example, the header `X-Custom-Header` can
295 | also be retrieved as `x_custom_header`.
296 | A response initially has no headers. Headers are added when a plugin
297 | short-circuits the proxying by producing a header
298 | (e.g. an authentication plugin rejecting a request), or if the request has
299 | been proxied, and one of the latter execution phases is currently running.
300 | Unlike `kong.service.response.get_headers()`, this function returns *all*
301 | headers as the client would see them upon reception, including headers
302 | added by Kong itself.
303 | By default, this function returns up to **100** headers (or what has been
304 | configured using `lua_max_resp_headers`). The optional `max_headers` argument
305 | can be specified to customize this limit, but must be greater than **1** and
306 | equal to or less than **1000**.
307 |
308 | Phases:
309 | header_filter, response, body_filter, log, admin_api
310 |
311 | Example:
312 | # Given an response from the Service with the following headers:
313 |
314 | # X-Custom-Header: bla
315 |
316 | # X-Another: foo bar
317 |
318 | # X-Another: baz
319 |
320 | headers = kong.response.get_headers()
321 |
322 | headers.x_custom_header # "bla"
323 |
324 | headers.x_another[1] # "foo bar"
325 |
326 | headers["X-Another"][2] # "baz"
327 |
328 | :parameter max_headers: Limits the number of headers parsed.
329 | :type max_headers: number
330 |
331 | :return: headers A table representation of the headers in the
332 | response.
333 |
334 | :rtype: table
335 | :return: err If more headers than `max_headers` were present,
336 | returns a string with the error `"truncated"`.
337 |
338 | :rtype: str
339 | """
340 | pass
341 |
342 | @staticmethod
343 | def get_source() -> str:
344 | """
345 |
346 | This function helps determine where the current response originated
347 | from. Since Kong is a reverse proxy, it can short-circuit a request and
348 | produce a response of its own, or the response can come from the proxied
349 | Service.
350 | Returns a string with three possible values:
351 | * `"exit"` is returned when, at some point during the processing of the
352 | request, there has been a call to `kong.response.exit()`. This happens
353 | when the request was short-circuited by a plugin or by Kong
354 | itself (e.g. invalid credentials).
355 | * `"error"` is returned when an error has happened while processing the
356 | request. For example, a timeout while connecting to the upstream
357 | service.
358 | * `"service"` is returned when the response was originated by successfully
359 | contacting the proxied Service.
360 |
361 | Phases:
362 | header_filter, response, body_filter, log, admin_api
363 |
364 | Example:
365 | if kong.response.get_source() == "service":
366 |
367 | kong.log("The response comes from the Service")
368 |
369 | elseif kong.response.get_source() == "error":
370 |
371 | kong.log("There was an error while processing the request")
372 |
373 | elseif kong.response.get_source() == "exit":
374 |
375 | kong.log("There was an early exit while processing the request")
376 |
377 | :return: The source.
378 |
379 | :rtype: str
380 | """
381 | pass
382 |
383 | @staticmethod
384 | def get_status() -> number:
385 | """
386 |
387 | Returns the HTTP status code currently set for the downstream response (as
388 | a Lua number).
389 | If the request was proxied (as per `kong.response.get_source()`), the
390 | return value is the response from the Service (identical to
391 | `kong.service.response.get_status()`).
392 | If the request was _not_ proxied and the response was produced by Kong
393 | itself (i.e. via `kong.response.exit()`), the return value is
394 | returned as-is.
395 |
396 | Phases:
397 | header_filter, response, body_filter, log, admin_api
398 |
399 | Example:
400 | kong.response.get_status() # 200
401 |
402 | :return: status The HTTP status code currently set for the
403 | downstream response.
404 |
405 | :rtype: number
406 | """
407 | pass
408 |
409 | @staticmethod
410 | def set_header(name: str, of: table) -> None:
411 | """
412 |
413 | Sets a response header with the given value. This function overrides any
414 | existing header with the same name.
415 | Note: Underscores in header names are automatically transformed into dashes
416 | by default. If you want to deactivate this behavior, set the
417 | `lua_transform_underscores_in_response_headers` Nginx config option to `off`.
418 | This setting can be set in the Kong Config file:
419 | nginx_http_lua_transform_underscores_in_response_headers = off
420 | Be aware that changing this setting might break any plugins that
421 | rely on the automatic underscore conversion.
422 | You cannot set Transfer-Encoding header with this function. It will be ignored.
423 |
424 | Phases:
425 | rewrite, access, header_filter, response, admin_api
426 |
427 | Example:
428 | kong.response.set_header("X-Foo", "value")
429 |
430 | :parameter name: The name of the header
431 | :type name: str
432 | :parameter of: strings|string|number|boolean value The new value for the header.
433 | :type of: table
434 |
435 | :return: throws an error on invalid input.
436 |
437 | :rtype: None
438 | """
439 | pass
440 |
441 | @staticmethod
442 | def set_headers(headers: table) -> None:
443 | """
444 |
445 | Sets the headers for the response. Unlike `kong.response.set_header()`,
446 | the `headers` argument must be a table in which each key is a string
447 | corresponding to a header's name, and each value is a string, or an
448 | array of strings.
449 | The resulting headers are produced in lexicographical order. The order of
450 | entries with the same name (when values are given as an array) is
451 | retained.
452 | This function overrides any existing header bearing the same name as those
453 | specified in the `headers` argument. Other headers remain unchanged.
454 | You cannot set Transfer-Encoding header with this function. It will be ignored.
455 |
456 | Phases:
457 | rewrite, access, header_filter, response, admin_api
458 |
459 | Example:
460 | kong.response.set_headers({
461 |
462 | ["Bla"] = "boo",
463 |
464 | ["X-Foo"] = "foo3",
465 |
466 | ["Cache-Control"] = { "no-store", "no-cache" }
467 |
468 | })
469 |
470 | # Will add the following headers to the response, in this order:
471 |
472 | # X-Bar: bar1
473 |
474 | # Bla: boo
475 |
476 | # Cache-Control: no-store
477 |
478 | # Cache-Control: no-cache
479 |
480 | # X-Foo: foo3
481 |
482 | :parameter headers:
483 | :type headers: table
484 |
485 | :return: throws an error on invalid input.
486 |
487 | :rtype: None
488 | """
489 | pass
490 |
491 | @staticmethod
492 | def set_status(status: number) -> None:
493 | """
494 |
495 | Allows changing the downstream response HTTP status code before sending it
496 | to the client.
497 |
498 | Phases:
499 | rewrite, access, header_filter, response, admin_api
500 |
501 | Example:
502 | kong.response.set_status(404)
503 |
504 | :parameter status: The new status.
505 | :type status: number
506 |
507 | :return: throws an error on invalid input.
508 |
509 | :rtype: None
510 | """
511 | pass
512 |
513 | pass
514 |
--------------------------------------------------------------------------------
/kong_pdk/pdk/kong/router.py:
--------------------------------------------------------------------------------
1 | # AUTO GENERATED BASED ON Kong 3.8.x, DO NOT EDIT
2 | # Original source path: kong/pdk/router.lua
3 |
4 | from typing import TypeVar, Any, Union, List, Mapping, Tuple, Optional
5 |
6 | number = TypeVar('number', int, float)
7 | table = TypeVar('table', List[Any], Mapping[str, Any])
8 | # XXX
9 | cdata = Any
10 | err = str
11 |
12 |
13 | class router():
14 |
15 |
16 | @staticmethod
17 | def get_route() -> table:
18 | """
19 |
20 | Returns the current `route` entity. The request is matched against this
21 | route.
22 |
23 | Phases:
24 | access, header_filter, response, body_filter, log
25 |
26 | Example:
27 | route = kong.router.get_route()
28 |
29 | protocols = route.protocols
30 |
31 | :return: The `route` entity.
32 |
33 | :rtype: table
34 | """
35 | pass
36 |
37 | @staticmethod
38 | def get_service() -> table:
39 | """
40 |
41 | Returns the current `service` entity. The request is targeted to this
42 | upstream service.
43 |
44 | Phases:
45 | access, header_filter, response, body_filter, log
46 |
47 | Example:
48 | if kong.router.get_service():
49 |
50 | # routed by route & service entities
51 |
52 | else:
53 |
54 | # routed by a route without a service
55 |
56 | :return: The `service` entity.
57 |
58 | :rtype: table
59 | """
60 | pass
61 |
62 | pass
63 |
--------------------------------------------------------------------------------
/kong_pdk/pdk/kong/service/__init__.py:
--------------------------------------------------------------------------------
1 | # AUTO GENERATED BASED ON Kong 3.8.x, DO NOT EDIT
2 | # Original source path: kong/pdk/service.lua
3 |
4 | from typing import TypeVar, Any, Union, List, Mapping, Tuple, Optional
5 |
6 | number = TypeVar('number', int, float)
7 | table = TypeVar('table', List[Any], Mapping[str, Any])
8 | # XXX
9 | cdata = Any
10 | err = str
11 |
12 | from .request import request as cls_request
13 | from .response import response as cls_response
14 |
15 | class service():
16 |
17 | request = cls_request
18 | response = cls_response
19 |
20 | @staticmethod
21 | def set_retries(retries: number) -> None:
22 | """
23 |
24 | Sets the retries count for the current request. This will override the
25 | default retries count set in the Upstream entity.
26 | The `retries` argument expects an integer between 0 and 32767.
27 |
28 | Phases:
29 | access
30 |
31 | Example:
32 | kong.service.set_retries(233)
33 |
34 | :parameter retries:
35 | :type retries: number
36 |
37 | """
38 | pass
39 |
40 | @staticmethod
41 | def set_target(host: str, port: number) -> None:
42 | """
43 |
44 | Sets the host and port on which to connect to for proxying the request.
45 | Using this method is equivalent to ask Kong to not run the load-balancing
46 | phase for this request, and consider it manually overridden.
47 | Load-balancing components such as retries and health-checks will also be
48 | ignored for this request. Use `kong.service.set_retries` to overwrite
49 | retries count.
50 | The `host` argument expects the hostname or IP address of the upstream
51 | server, and the `port` expects a port number.
52 |
53 | Phases:
54 | access
55 |
56 | Example:
57 | kong.service.set_target("service.local", 443)
58 |
59 | kong.service.set_target("192.168.130.1", 80)
60 |
61 | :parameter host:
62 | :type host: str
63 | :parameter port:
64 | :type port: number
65 |
66 | """
67 | pass
68 |
69 | @staticmethod
70 | def set_timeouts(connect_timeout: number, write_timeout: number, read_timeout: number) -> None:
71 | """
72 |
73 | Sets the timeouts for the current request. This will override the
74 | default timeouts set in the Upstream entity.
75 |
76 | The `connect_timeout`, `write_timeout`, and `read_timeout` arguments expect
77 | an integer between 1 and 2147483646.
78 |
79 | Phases:
80 | access
81 |
82 | Example:
83 | kong.service.set_timeouts(233, 233, 233)
84 |
85 | :parameter connect_timeout:
86 | :type connect_timeout: number
87 | :parameter write_timeout:
88 | :type write_timeout: number
89 | :parameter read_timeout:
90 | :type read_timeout: number
91 |
92 | """
93 | pass
94 |
95 | @staticmethod
96 | def set_tls_verify(on: bool) -> Tuple[bool, str]:
97 | """
98 |
99 | Sets whether TLS verification is enabled while handshaking with the Service.
100 | The `on` argument is a boolean flag, where `true` means upstream verification
101 | is enabled and `false` disables it.
102 | This call affects only the current request. If the trusted certificate store is
103 | not set already (via [proxy_ssl_trusted_certificate](https://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_ssl_trusted_certificate)
104 | or [kong.service.set_upstream_ssl_trusted_store](#kongserviceset_upstream_ssl_trusted_store)),
105 | then TLS verification will always fail with "unable to get local issuer certificate" error.
106 |
107 | Phases:
108 | rewrite, access, balancer, preread
109 |
110 | Example:
111 | ok, err = kong.service.set_tls_verify(true)
112 |
113 | if not ok:
114 |
115 | # do something with error
116 |
117 | :parameter on: Whether to enable TLS certificate verification for the current request
118 | :type on: bool
119 |
120 | :return: `true` if the operation succeeded, `nil` if an error occurred
121 |
122 | :rtype: bool
123 | :return: An error message describing the error if there was one
124 |
125 | :rtype: str
126 | """
127 | pass
128 |
129 | @staticmethod
130 | def set_tls_verify_depth(depth: number) -> Tuple[bool, str]:
131 | """
132 |
133 | Sets the maximum depth of verification when validating upstream server's TLS certificate.
134 | This call affects only the current request. For the depth to be actually used the verification
135 | has to be enabled with either the [proxy_ssl_verify](https://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_ssl_verify)
136 | directive or using the [kong.service.set_tls_verify](#kongserviceset_tls_verify) function.
137 |
138 | Phases:
139 | rewrite, access, balancer, preread
140 |
141 | Example:
142 | ok, err = kong.service.set_tls_verify_depth(3)
143 |
144 | if not ok:
145 |
146 | # do something with error
147 |
148 | :parameter depth: Depth to use when validating. Must be non-negative
149 | :type depth: number
150 |
151 | :return: `true` if the operation succeeded, `nil` if an error occurred
152 |
153 | :rtype: bool
154 | :return: An error message describing the error if there was one
155 |
156 | :rtype: str
157 | """
158 | pass
159 |
160 | @staticmethod
161 | def set_upstream(host: str) -> Tuple[bool, str]:
162 | """
163 |
164 | Sets the desired Upstream entity to handle the load-balancing step for
165 | this request. Using this method is equivalent to creating a Service with a
166 | `host` property equal to that of an Upstream entity (in which case, the
167 | request would be proxied to one of the Targets associated with that
168 | Upstream).
169 | The `host` argument should receive a string equal to the name of one of the
170 | Upstream entities currently configured.
171 |
172 | Phases:
173 | access
174 |
175 | Example:
176 | ok, err = kong.service.set_upstream("service.prod")
177 |
178 | if not ok:
179 |
180 | kong.log.err(err)
181 |
182 | return
183 |
184 | :parameter host:
185 | :type host: str
186 |
187 | :return: `true` on success, or `nil` if no upstream entities
188 | where found
189 |
190 | :rtype: bool
191 | :return: An error message describing the error if there was
192 | one.
193 |
194 | :rtype: str
195 | """
196 | pass
197 |
198 | pass
199 |
--------------------------------------------------------------------------------
/kong_pdk/pdk/kong/service/request.py:
--------------------------------------------------------------------------------
1 | # AUTO GENERATED BASED ON Kong 3.8.x, DO NOT EDIT
2 | # Original source path: kong/pdk/service/request.lua
3 |
4 | from typing import TypeVar, Any, Union, List, Mapping, Tuple, Optional
5 |
6 | number = TypeVar('number', int, float)
7 | table = TypeVar('table', List[Any], Mapping[str, Any])
8 | # XXX
9 | cdata = Any
10 | err = str
11 |
12 |
13 | class request():
14 |
15 |
16 | @staticmethod
17 | def add_header(header: str, of: table) -> None:
18 | """
19 |
20 | Adds a request header with the given value to the request to the Service. Unlike
21 | `kong.service.request.set_header()`, this function doesn't remove any existing
22 | headers with the same name. Instead, several occurrences of the header will be
23 | present in the request. The order in which headers are added is retained.
24 |
25 | Phases:
26 | rewrite, access
27 |
28 | Example:
29 | kong.service.request.add_header("Cache-Control", "no-cache")
30 |
31 | kong.service.request.add_header("Cache-Control", "no-store")
32 |
33 | :parameter header: The header name. Example: "Cache-Control".
34 | :type header: str
35 | :parameter of: strings|string|number|boolean value The header value. Example: "no-cache".
36 | :type of: table
37 |
38 | :return: throws an error on invalid inputs.
39 |
40 | :rtype: None
41 | """
42 | pass
43 |
44 | @staticmethod
45 | def clear_header(header: str) -> None:
46 | """
47 |
48 | Removes all occurrences of the specified header from the request to the Service.
49 |
50 | Phases:
51 | rewrite, access
52 |
53 | Example:
54 | kong.service.request.set_header("X-Foo", "foo")
55 |
56 | kong.service.request.add_header("X-Foo", "bar")
57 |
58 | kong.service.request.clear_header("X-Foo")
59 |
60 | # from here onwards, no X-Foo headers will exist in the request
61 |
62 | :parameter header: The header name. Example: "X-Foo".
63 | :type header: str
64 |
65 | :return: throws an error on invalid inputs.
66 | The function does not throw an error if no header was removed.
67 |
68 | :rtype: None
69 | """
70 | pass
71 |
72 | @staticmethod
73 | def disable_tls() -> Tuple[bool, str]:
74 | """
75 |
76 | Disables the TLS handshake to upstream for [ngx\_stream\_proxy\_module](https://nginx.org/en/docs/stream/ngx_stream_proxy_module.html).
77 | This overrides the [proxy\_ssl](https://nginx.org/en/docs/stream/ngx_stream_proxy_module.html#proxy_ssl) directive, effectively setting it to `off`
78 | for the current stream session.
79 | Once this function has been called, it is not possible to re-enable TLS handshake for the current session.
80 |
81 | Phases:
82 | preread, balancer
83 |
84 | Example:
85 | ok, err = kong.service.request.disable_tls()
86 |
87 | if not ok:
88 |
89 | # do something with error
90 |
91 | :return: `true` if the operation succeeded, `nil` if an error occurred.
92 |
93 | :rtype: bool
94 | :return: An error message describing the error if there was one.
95 |
96 | :rtype: str
97 | """
98 | pass
99 |
100 | @staticmethod
101 | def enable_buffering() -> None:
102 | """
103 |
104 | Enables buffered proxying, which allows plugins to access Service body and
105 | response headers at the same time.
106 |
107 | Phases:
108 | rewrite, access, balancer
109 |
110 | Example:
111 | kong.service.request.enable_buffering()
112 |
113 | :return:
114 |
115 | :rtype: None
116 | """
117 | pass
118 |
119 | @staticmethod
120 | def set_body(args: table, mimetype: Optional[str]) -> Tuple[bool, str]:
121 | """
122 |
123 | Sets the body of the request to the Service. Unlike
124 | `kong.service.request.set_raw_body()`, the `args` argument must be a table, and
125 | is encoded with a MIME type. The encoding MIME type can be specified in
126 | the optional `mimetype` argument, or if left unspecified, is chosen based
127 | on the `Content-Type` header of the client's request.
128 | Behavior based on MIME type in the `Content-Type` header:
129 | * `application/x-www-form-urlencoded`: Encodes the arguments as
130 | form-encoded. Keys are produced in lexicographical
131 | order. The order of entries within the same key (when values are
132 | given as an array) is retained. Any string values given are URL-encoded.
133 | * `multipart/form-data`: Encodes the arguments as multipart form data.
134 | * `application/json`: Encodes the arguments as JSON (same as
135 | `kong.service.request.set_raw_body(json.encode(args))`). Lua types are
136 | converted to matching JSON types.
137 | If the MIME type is none of the above, this function returns `nil` and
138 | an error message indicating the body could not be encoded.
139 | If the `mimetype` argument is specified, the `Content-Type` header is
140 | set accordingly in the request to the Service.
141 | If further control of the body generation is needed, a raw body can be given as
142 | a string with `kong.service.request.set_raw_body()`.
143 |
144 | Phases:
145 | rewrite, access, balancer
146 |
147 | Example:
148 | kong.service.set_header("application/json")
149 |
150 | ok, err = kong.service.request.set_body({
151 |
152 | name = "John Doe",
153 |
154 | age = 42,
155 |
156 | numbers = {1, 2, 3}
157 |
158 | })
159 |
160 | # Produces the following JSON body:
161 |
162 | # { "name": "John Doe", "age": 42, "numbers":[1, 2, 3] }
163 |
164 | ok, err = kong.service.request.set_body({
165 |
166 | foo = "hello world",
167 |
168 | bar = {"baz", "bla", true},
169 |
170 | zzz = true,
171 |
172 | blo = ""
173 |
174 | }, "application/x-www-form-urlencoded")
175 |
176 | # Produces the following body:
177 |
178 | # bar=baz&bar=bla&bar&blo=&foo=hello%20world&zzz
179 |
180 | :parameter args: A table with data to be converted to the appropriate format
181 | and stored in the body.
182 | :type args: table
183 | :parameter mimetype: can be one of:
184 | :type mimetype: str
185 |
186 | :return: `true` on success, `nil` otherwise.
187 |
188 | :rtype: bool
189 | :return: `nil` on success, an error message in case of error.
190 | Throws an error on invalid inputs.
191 |
192 | :rtype: str
193 | """
194 | pass
195 |
196 | @staticmethod
197 | def set_header(header: str, of: table) -> None:
198 | """
199 |
200 | Sets a header in the request to the Service with the given value. Any existing header
201 | with the same name will be overridden.
202 | If the `header` argument is `"host"` (case-insensitive), then this also
203 | sets the SNI of the request to the Service.
204 |
205 | Phases:
206 | rewrite, access, balancer
207 |
208 | Example:
209 | kong.service.request.set_header("X-Foo", "value")
210 |
211 | :parameter header: The header name. Example: "X-Foo".
212 | :type header: str
213 | :parameter of: strings|string|boolean|number value The header value. Example: "hello world".
214 | :type of: table
215 |
216 | :return: throws an error on invalid inputs.
217 |
218 | :rtype: None
219 | """
220 | pass
221 |
222 | @staticmethod
223 | def set_headers(headers: table) -> None:
224 | """
225 |
226 | Sets the headers of the request to the Service. Unlike
227 | `kong.service.request.set_header()`, the `headers` argument must be a table in
228 | which each key is a string (corresponding to a header's name), and each value
229 | is a string, or an array of strings.
230 | The resulting headers are produced in lexicographical order. The order of
231 | entries with the same name (when values are given as an array) is retained.
232 | This function overrides any existing header bearing the same name as those
233 | specified in the `headers` argument. Other headers remain unchanged.
234 | If the `"Host"` header is set (case-insensitive), then this also sets
235 | the SNI of the request to the Service.
236 |
237 | Phases:
238 | rewrite, access
239 |
240 | Example:
241 | kong.service.request.set_header("X-Foo", "foo1")
242 |
243 | kong.service.request.add_header("X-Foo", "foo2")
244 |
245 | kong.service.request.set_header("X-Bar", "bar1")
246 |
247 | kong.service.request.set_headers({
248 |
249 | ["X-Foo"] = "foo3",
250 |
251 | ["Cache-Control"] = { "no-store", "no-cache" },
252 |
253 | ["Bla"] = "boo"
254 |
255 | })
256 |
257 | # Will add the following headers to the request, in this order:
258 |
259 | # X-Bar: bar1
260 |
261 | # Bla: boo
262 |
263 | # Cache-Control: no-store
264 |
265 | # Cache-Control: no-cache
266 |
267 | # X-Foo: foo3
268 |
269 | :parameter headers: A table where each key is a string containing a header name
270 | and each value is either a string or an array of strings.
271 | :type headers: table
272 |
273 | :return: throws an error on invalid inputs.
274 |
275 | :rtype: None
276 | """
277 | pass
278 |
279 | @staticmethod
280 | def set_method(method: str) -> None:
281 | """
282 |
283 | Sets the HTTP method for the request to the service.
284 |
285 | Phases:
286 | rewrite, access
287 |
288 | Example:
289 | kong.service.request.set_method("DELETE")
290 |
291 | :parameter method: The method string, which must be in all
292 | uppercase. Supported values are: `"GET"`, `"HEAD"`, `"PUT"`, `"POST"`,
293 | `"DELETE"`, `"OPTIONS"`, `"MKCOL"`, `"COPY"`, `"MOVE"`, `"PROPFIND"`,
294 | `"PROPPATCH"`, `"LOCK"`, `"UNLOCK"`, `"PATCH"`, or `"TRACE"`.
295 | :type method: str
296 |
297 | :return: throws an error on invalid inputs.
298 |
299 | :rtype: None
300 | """
301 | pass
302 |
303 | @staticmethod
304 | def set_path(path: str) -> None:
305 | """
306 |
307 | Sets the path component for the request to the service.
308 | The input accepts any valid *normalized* URI (including UTF-8 characters)
309 | and this API will perform necessary escaping according to the RFC
310 | to make the request valid.
311 | Input should **not** include the query string.
312 |
313 | Phases:
314 | access, rewrite, balancer
315 |
316 | Example:
317 | kong.service.request.set_path("/v2/movies")
318 |
319 | :parameter path: The path string. Special characters and UTF-8
320 | characters are allowed, for example: `"/v2/movies"` or `"/foo/😀"`.
321 | :type path: str
322 |
323 | :return: throws an error on invalid inputs.
324 |
325 | :rtype: None
326 | """
327 | pass
328 |
329 | @staticmethod
330 | def set_query(args: table) -> None:
331 | """
332 |
333 | Set the query string of the request to the Service.
334 | Unlike `kong.service.request.set_raw_query()`, the `query` argument must be a
335 | table in which each key is a string (corresponding to an argument's name), and
336 | each value is either a boolean, a string, or an array of strings or booleans.
337 | Additionally, all string values will be URL-encoded.
338 | The resulting query string contains keys in their lexicographical order. The
339 | order of entries within the same key (when values are given as an array) is
340 | retained.
341 | If further control of the query string generation is needed, a raw query
342 | string can be given as a string with `kong.service.request.set_raw_query()`.
343 |
344 | Phases:
345 | rewrite, access
346 |
347 | Example:
348 | kong.service.request.set_query({
349 |
350 | foo = "hello world",
351 |
352 | bar = {"baz", "bla", true},
353 |
354 | zzz = true,
355 |
356 | blo = ""
357 |
358 | })
359 |
360 | # Produces the following query string:
361 |
362 | # bar=baz&bar=bla&bar&blo=&foo=hello%20world&zzz
363 |
364 | :parameter args: A table where each key is a string (corresponding to an
365 | argument name), and each value is either a boolean, a string, or an array of
366 | strings or booleans. Any string values given are URL-encoded.
367 | :type args: table
368 |
369 | :return: throws an error on invalid inputs.
370 |
371 | :rtype: None
372 | """
373 | pass
374 |
375 | @staticmethod
376 | def set_raw_body(body: str) -> None:
377 | """
378 |
379 | Sets the body of the request to the Service.
380 | The `body` argument must be a string and will not be processed in any way.
381 | This function also sets the `Content-Length` header appropriately. To set an
382 | empty body, you can provide an empty string (`""`) to this function.
383 | For a higher-level function to set the body based on the request content type,
384 | see `kong.service.request.set_body()`.
385 |
386 | Phases:
387 | rewrite, access, balancer
388 |
389 | Example:
390 | kong.service.request.set_raw_body("Hello, world!")
391 |
392 | :parameter body: The raw body.
393 | :type body: str
394 |
395 | :return: throws an error on invalid inputs.
396 |
397 | :rtype: None
398 | """
399 | pass
400 |
401 | @staticmethod
402 | def set_raw_query(query: str) -> None:
403 | """
404 |
405 | Sets the query string of the request to the Service. The `query` argument is a
406 | string (without the leading `?` character), and is not processed in any
407 | way.
408 | For a higher-level function to set the query string from a Lua table of
409 | arguments, see `kong.service.request.set_query()`.
410 |
411 | Phases:
412 | rewrite, access
413 |
414 | Example:
415 | kong.service.request.set_raw_query("zzz&bar=baz&bar=bla&bar&blo=&foo=hello%20world")
416 |
417 | :parameter query: The raw querystring. Example:
418 | `"foo=bar&bla&baz=hello%20world"`.
419 | :type query: str
420 |
421 | :return: throws an error on invalid inputs.
422 |
423 | :rtype: None
424 | """
425 | pass
426 |
427 | @staticmethod
428 | def set_scheme(scheme: str) -> None:
429 | """
430 |
431 | Sets the protocol to use when proxying the request to the Service.
432 |
433 | Phases:
434 | access, rewrite, balancer
435 |
436 | Example:
437 | kong.service.request.set_scheme("https")
438 |
439 | :parameter scheme: The scheme to be used. Supported values are `"http"` or `"https"`.
440 | :type scheme: str
441 |
442 | :return: throws an error on invalid inputs.
443 |
444 | :rtype: None
445 | """
446 | pass
447 |
448 | pass
449 |
--------------------------------------------------------------------------------
/kong_pdk/pdk/kong/service/response.py:
--------------------------------------------------------------------------------
1 | # AUTO GENERATED BASED ON Kong 3.8.x, DO NOT EDIT
2 | # Original source path: kong/pdk/service/response.lua
3 |
4 | from typing import TypeVar, Any, Union, List, Mapping, Tuple, Optional
5 |
6 | number = TypeVar('number', int, float)
7 | table = TypeVar('table', List[Any], Mapping[str, Any])
8 | # XXX
9 | cdata = Any
10 | err = str
11 |
12 |
13 | class response():
14 |
15 |
16 | @staticmethod
17 | def get_body(mimetype: Optional[str], max_args: Optional[number]) -> str:
18 | """
19 |
20 | Returns the decoded buffered body.
21 |
22 | Phases:
23 | header_filter, body_filter, log
24 |
25 | Example:
26 | # Plugin needs to call kong.service.request.enable_buffering() on `rewrite`
27 |
28 | # or `access` phase prior calling this function.
29 |
30 | body = kong.service.response.get_body()
31 |
32 | :parameter mimetype: The MIME type of the response (if known).
33 | :type mimetype: str
34 | :parameter max_args: Sets a limit on the maximum number of (what?)
35 | that can be parsed.
36 | :type max_args: number
37 |
38 | :return: The decoded buffered body
39 |
40 | :rtype: str
41 | """
42 | pass
43 |
44 | @staticmethod
45 | def get_header(name: str) -> str:
46 | """
47 |
48 | Returns the value of the specified response header.
49 | Unlike `kong.response.get_header()`, this function only returns a header
50 | if it is present in the response from the Service (ignoring headers added by Kong
51 | itself).
52 |
53 | Phases:
54 | header_filter, body_filter, log
55 |
56 | Example:
57 | # Given a response with the following headers:
58 |
59 | # X-Custom-Header: bla
60 |
61 | # X-Another: foo bar
62 |
63 | # X-Another: baz
64 |
65 | kong.log.inspect(kong.service.response.get_header("x-custom-header")) # "bla"
66 |
67 | kong.log.inspect(kong.service.response.get_header("X-Another")) # "foo bar"
68 |
69 | :parameter name: The name of the header.
70 | Header names in are case-insensitive and are normalized to lowercase, and
71 | dashes (`-`) can be written as underscores (`_`); that is, the header
72 | `X-Custom-Header` can also be retrieved as `x_custom_header`.
73 | :type name: str
74 |
75 | :return: The value of the header, or `nil` if a header with
76 | `name` is not found in the response. If a header with the same name is present
77 | multiple times in the response, this function returns the value of the
78 | first occurrence of this header.
79 |
80 | :rtype: str
81 | """
82 | pass
83 |
84 | @staticmethod
85 | def get_headers(max_headers: Optional[number]) -> Tuple[table, str]:
86 | """
87 |
88 | Returns a Lua table holding the headers from the Service response. Keys are
89 | header names. Values are either a string with the header value, or an array of
90 | strings if a header was sent multiple times. Header names in this table are
91 | case-insensitive and dashes (`-`) can be written as underscores (`_`); that is,
92 | the header `X-Custom-Header` can also be retrieved as `x_custom_header`.
93 | Unlike `kong.response.get_headers()`, this function only returns headers that
94 | are present in the response from the Service (ignoring headers added by Kong itself).
95 | If the request is not proxied to a Service (e.g. an authentication plugin rejected
96 | a request and produced an HTTP 401 response), then the returned `headers` value
97 | might be `nil`, since no response from the Service has been received.
98 | By default, this function returns up to **100** headers. The optional
99 | `max_headers` argument can be specified to customize this limit, but must be
100 | greater than **1** and not greater than **1000**.
101 |
102 | Phases:
103 | header_filter, body_filter, log
104 |
105 | Example:
106 | # Given a response with the following headers:
107 |
108 | # X-Custom-Header: bla
109 |
110 | # X-Another: foo bar
111 |
112 | # X-Another: baz
113 |
114 | headers = kong.service.response.get_headers()
115 |
116 | if headers:
117 |
118 | kong.log.inspect(headers.x_custom_header) # "bla"
119 |
120 | kong.log.inspect(headers.x_another[1]) # "foo bar"
121 |
122 | kong.log.inspect(headers["X-Another"][2]) # "baz"Note that this function returns a proxy table
123 |
124 | which cannot be iterated with `pairs` or used as operand of `#`.
125 |
126 | :parameter max_headers: Sets a limit on the maximum number of
127 | headers that can be parsed.
128 | :type max_headers: number
129 |
130 | :return: The response headers in table form.
131 |
132 | :rtype: table
133 | :return: If more headers than `max_headers` are present, returns
134 | a string with the error `"truncated"`.
135 |
136 | :rtype: str
137 | """
138 | pass
139 |
140 | @staticmethod
141 | def get_raw_body() -> bytes:
142 | """
143 |
144 | Returns the raw buffered body.
145 |
146 | Phases:
147 | header_filter, body_filter, log
148 |
149 | Example:
150 | # Plugin needs to call kong.service.request.enable_buffering() on `rewrite`
151 |
152 | # or `access` phase prior calling this function.
153 |
154 | body = kong.service.response.get_raw_body()
155 |
156 | :return: The raw buffered body.
157 |
158 | :rtype: bytes
159 | """
160 | pass
161 |
162 | @staticmethod
163 | def get_status() -> number:
164 | """
165 |
166 | Returns the HTTP status code of the response from the Service as a Lua number.
167 |
168 | Phases:
169 | header_filter, body_filter, log
170 |
171 | Example:
172 | kong.log.inspect(kong.service.response.get_status()) # 418
173 |
174 | :return: The status code from the response from the Service, or `nil`
175 | if the request was not proxied (that is, if `kong.response.get_source()` returned
176 | anything other than `"service"`).
177 |
178 | :rtype: number
179 | """
180 | pass
181 |
182 | pass
183 |
--------------------------------------------------------------------------------
/kong_pdk/pdk/kong/telemetry.py:
--------------------------------------------------------------------------------
1 | # AUTO GENERATED BASED ON Kong 3.8.x, DO NOT EDIT
2 | # Original source path: kong/pdk/telemetry.lua
3 |
4 | from typing import TypeVar, Any, Union, List, Mapping, Tuple, Optional
5 |
6 | number = TypeVar('number', int, float)
7 | table = TypeVar('table', List[Any], Mapping[str, Any])
8 | # XXX
9 | cdata = Any
10 | err = str
11 |
12 |
13 | class telemetry():
14 |
15 |
16 | @staticmethod
17 | def log(plugin_name: str, plugin_config: table, message_type: str, message: str, attributes: table) -> None:
18 | """
19 |
20 | Records a structured log entry, to be reported via the OpenTelemetry plugin.
21 | This function has a dependency on the OpenTelemetry plugin, which must be
22 | configured to report OpenTelemetry logs.
23 |
24 | Phases:
25 | rewrite, access, balancer, timer, header_filter, response, body_filter, log
26 |
27 | Example:
28 | attributes = {
29 |
30 | http_method = kong.request.get_method()
31 |
32 | ["node.id"] = kong.node.get_id(),
33 |
34 | hostname = kong.node.get_hostname(),
35 |
36 | }
37 |
38 | ok, err = kong.telemetry.log("my_plugin", conf, "result", "successful operation", attributes)
39 |
40 | :parameter plugin_name: the name of the plugin
41 | :type plugin_name: str
42 | :parameter plugin_config: the plugin configuration
43 | :type plugin_config: table
44 | :parameter message_type: the type of the log message, useful to categorize
45 | the log entry
46 | :type message_type: str
47 | :parameter message: the log message
48 | :type message: str
49 | :parameter attributes: structured information to be included in the
50 | `attributes` field of the log entry
51 | :type attributes: table
52 |
53 | """
54 | pass
55 |
56 | pass
57 |
--------------------------------------------------------------------------------
/kong_pdk/pdk/kong/vault.py:
--------------------------------------------------------------------------------
1 | # AUTO GENERATED BASED ON Kong 3.8.x, DO NOT EDIT
2 | # Original source path: kong/pdk/vault.lua
3 |
4 | from typing import TypeVar, Any, Union, List, Mapping, Tuple, Optional
5 |
6 | number = TypeVar('number', int, float)
7 | table = TypeVar('table', List[Any], Mapping[str, Any])
8 | # XXX
9 | cdata = Any
10 | err = str
11 |
12 |
13 | class vault():
14 |
15 |
16 | @staticmethod
17 | def flush() -> None:
18 | """
19 |
20 | Flush vault LRU cache and start a timer to rotate secrets.
21 | @local
22 |
23 | Example:
24 | kong.vault.flush()
25 |
26 | """
27 | pass
28 |
29 | @staticmethod
30 | def get(reference: str) -> Tuple[str, str]:
31 | """
32 |
33 | Resolves the passed in reference and returns the value of it.
34 |
35 | Example:
36 | value, err = kong.vault.get("{vault://env/cert/key}")
37 |
38 | :parameter reference: reference to resolve
39 | :type reference: str
40 |
41 | :return: resolved value of the reference
42 |
43 | :rtype: str
44 | :return: error message on failure, otherwise `nil`
45 |
46 | :rtype: str
47 | """
48 | pass
49 |
50 | @staticmethod
51 | def init_worker() -> None:
52 | """
53 |
54 | Initializes vault.
55 | Registers event handlers (on non-dbless nodes) and starts a recurring secrets
56 | rotation timer. Does nothing on control planes.
57 | @local
58 |
59 | """
60 | pass
61 |
62 | @staticmethod
63 | def is_reference(reference: str) -> bool:
64 | """
65 |
66 | Checks if the passed in reference looks like a reference.
67 | Valid references start with '{vault://' and end with '}'.
68 | If you need more thorough validation,
69 | use `kong.vault.parse_reference`.
70 |
71 | Example:
72 | kong.vault.is_reference("{vault://env/key}") # true
73 |
74 | kong.vault.is_reference("not a reference") # false
75 |
76 | :parameter reference: reference to check
77 | :type reference: str
78 |
79 | :return: `true` is the passed in reference looks like a reference, otherwise `false`
80 |
81 | :rtype: bool
82 | """
83 | pass
84 |
85 | @staticmethod
86 | def parse_reference(reference: str) -> Tuple[table, str]:
87 | """
88 |
89 | Parses and decodes the passed in reference and returns a table
90 | containing its components.
91 | Given a following resource:
92 | ```lua
93 | "{vault://env/cert/key?prefix=SSL_#1}"
94 | ```
95 | This function will return following table:
96 | ```lua
97 | {
98 | name = "env", -- name of the Vault entity or Vault strategy
99 | resource = "cert", -- resource where secret is stored
100 | key = "key", -- key to lookup if the resource is secret object
101 | config = { -- if there are any config options specified
102 | prefix = "SSL_"
103 | },
104 | version = 1 -- if the version is specified
105 | }
106 | ```
107 |
108 | Example:
109 | ref, err = kong.vault.parse_reference("{vault://env/cert/key?prefix=SSL_#1}") # table
110 |
111 | :parameter reference: reference to parse
112 | :type reference: str
113 |
114 | :return: a table containing each component of the reference, or `nil` on error
115 |
116 | :rtype: table
117 | :return: error message on failure, otherwise `nil`
118 |
119 | :rtype: str
120 | """
121 | pass
122 |
123 | @staticmethod
124 | def update(options: table) -> table:
125 | """
126 |
127 | Helper function for secret rotation based on TTLs. Currently experimental.
128 |
129 | Example:
130 | options = kong.vault.update({
131 |
132 | cert = "# # -BEGIN CERTIFICATE# # -...",
133 |
134 | key = "# # -BEGIN RSA PRIVATE KEY# # -...",
135 |
136 | cert_alt = "# # -BEGIN CERTIFICATE# # -...",
137 |
138 | key_alt = "# # -BEGIN EC PRIVATE KEY# # -...",
139 |
140 | ["$refs"] = {
141 |
142 | cert = "{vault://aws/cert}",
143 |
144 | key = "{vault://aws/key}",
145 |
146 | cert_alt = "{vault://aws/cert-alt}",
147 |
148 | key_alt = "{vault://aws/key-alt}",
149 |
150 | }
151 |
152 | })
153 |
154 | # or
155 |
156 | options = {
157 |
158 | cert = "# # -BEGIN CERTIFICATE# # -...",
159 |
160 | key = "# # -BEGIN RSA PRIVATE KEY# # -...",
161 |
162 | cert_alt = "# # -BEGIN CERTIFICATE# # -...",
163 |
164 | key_alt = "# # -BEGIN EC PRIVATE KEY# # -...",
165 |
166 | ["$refs"] = {
167 |
168 | cert = "{vault://aws/cert}",
169 |
170 | key = "{vault://aws/key}",
171 |
172 | cert_alt = "{vault://aws/cert-alt}",
173 |
174 | key_alt = "{vault://aws/key-alt}",
175 |
176 | }
177 |
178 | }
179 |
180 | kong.vault.update(options)
181 |
182 | :parameter options: options containing secrets and references (this function modifies the input options)
183 | :type options: table
184 |
185 | :return: options with updated secret values
186 |
187 | :rtype: table
188 | """
189 | pass
190 |
191 | @staticmethod
192 | def warmup() -> None:
193 | """
194 |
195 | Warmups vault caches from config.
196 | @local
197 |
198 | """
199 | pass
200 |
201 | pass
202 |
--------------------------------------------------------------------------------
/kong_pdk/server.py:
--------------------------------------------------------------------------------
1 | import os
2 | import time
3 | import json
4 |
5 | from .const import PY3K
6 |
7 | import threading
8 | if PY3K:
9 | from queue import Queue
10 | else:
11 | from Queue import Queue
12 |
13 | import multiprocessing
14 | # patch connection API so it share with gevent.queue.Channel
15 | if PY3K:
16 | from multiprocessing import connection
17 | connection.Connection.get = connection.Connection.recv
18 | connection.Connection.put = connection.Connection.send
19 |
20 | from gevent import sleep as gsleep, spawn as gspawn
21 | from gevent.lock import Semaphore as gSemaphore
22 | from gevent.queue import Channel as gChannel
23 |
24 | try:
25 | import setproctitle
26 | except: # noqa: E722 do not use bare 'except
27 | setproctitle = None
28 |
29 | from .pdk import Kong
30 | from .module import Module
31 | from .exception import PluginServerException
32 | from .logger import Logger
33 |
34 | exts = ('.py', '.pyd', '.so')
35 | entities = ('service', 'consumer', 'route', 'plugin', 'credential', 'memory_stats')
36 |
37 | MSG_RET = 'ret'
38 |
39 | terminal_methods = set((
40 | "kong.response.exit",
41 | "kong.response.error",
42 | ))
43 |
44 | def locked_by(lock_name):
45 | def f(fn):
46 | def wrapper(*args, **kwargs):
47 | self = args[0]
48 | lock = getattr(self, lock_name)
49 | lock.acquire()
50 | try:
51 | r = fn(*args, **kwargs)
52 | except Exception as ex:
53 | lock.release()
54 | raise ex
55 | lock.release()
56 | return r
57 | return wrapper
58 |
59 | return f
60 |
61 | def _handler_event_func(cls_phase, ch, lua_style):
62 | cls_phase(Kong(ch, lua_style).kong)
63 | ch.put(MSG_RET)
64 |
65 | def _multiprocessing_init(pool_name):
66 | p = multiprocessing.current_process()
67 | p.name = "%s: %s (ppid: %d)" % (pool_name, p.name, os.getppid())
68 | if setproctitle:
69 | setproctitle.setproctitle(p.name)
70 |
71 | class PluginServer(object):
72 | def __init__(self, loglevel=Logger.WARNING, expire_ttl=60, plugin_dir=None,
73 | use_multiprocess=False, use_gevent=False, name=None, lua_style=True):
74 | if use_multiprocess:
75 | sem = multiprocessing.Semaphore
76 | elif use_gevent:
77 | sem = gSemaphore
78 | else:
79 | sem = threading.Semaphore
80 |
81 | self.plugin_dir = plugin_dir
82 | self.plugins = {}
83 | self.instances = {}
84 | self.instance_id = 0
85 | self.i_lock = sem()
86 | self.events = {}
87 | self.event_id = 0
88 | self.e_lock = sem()
89 |
90 | self.logger = Logger()
91 | self.logger.set_level(loglevel)
92 |
93 | if plugin_dir:
94 | self._load_plugins()
95 |
96 | title = "Kong Python Plugin Server"
97 | if name:
98 | title = "%s \"%s\"" % (title, name)
99 |
100 | self.use_multiprocess = use_multiprocess
101 | self.use_gevent = use_gevent
102 |
103 | self.lua_style = lua_style
104 |
105 | if use_multiprocess:
106 | if not PY3K:
107 | raise NotImplementedError("multiprocessing mode is only supported in Python3")
108 |
109 | self._process_pool = multiprocessing.Pool(
110 | os.cpu_count(),
111 | _multiprocessing_init,
112 | (title, ),
113 | )
114 | self.logger.debug("plugin server is in multiprocessing mode")
115 |
116 | # start cleanup timer
117 | if use_gevent:
118 | self.logger.debug("plugin server is in gevent mode")
119 | # gspawn(self._clear_expired_plugins, expire_ttl)
120 | else:
121 | pass
122 | # t = threading.Thread(
123 | # target=self._clear_expired_plugins,
124 | # args=(expire_ttl, ),
125 | # )
126 | # t.setDaemon(True)
127 | # t.start()
128 |
129 | if setproctitle:
130 | ppid = os.getppid()
131 | if use_multiprocess:
132 | setproctitle.setproctitle("%s: Manager (ppid: %d)" % (title, ppid))
133 | else:
134 | setproctitle.setproctitle("%s (ppid: %d)" % (title, ppid))
135 |
136 | def _clear_expired_plugins(self, ttl):
137 | while True:
138 | if self.use_gevent:
139 | gsleep(ttl)
140 | else:
141 | time.sleep(ttl)
142 |
143 | self.i_lock.acquire()
144 | keys = list(self.instances.keys())
145 | for iid in keys:
146 | instance = self.instances[iid]
147 | if instance.is_expired(ttl):
148 | self.logger.debug("cleanup instance #%d of %s" % (iid, instance.name))
149 | del self.instances[iid]
150 | self.i_lock.release()
151 |
152 | def cleanup(self):
153 | if self.use_multiprocess:
154 | self._process_pool.terminate()
155 | self._process_pool.join()
156 |
157 | def _load_plugins(self):
158 | if not self.plugin_dir:
159 | raise PluginServerException("plugin server is not initialized, call SetPluginDir first")
160 |
161 | for p in os.listdir(self.plugin_dir):
162 | n, ext = os.path.splitext(p)
163 | if ext in exts:
164 | path = os.path.join(self.plugin_dir, p)
165 | try:
166 | mod = Module(n, path=path)
167 | except Exception as ex:
168 | self.logger.warn("error loading plugin \"%s\": %s" % (n, ex))
169 | else:
170 | self.logger.debug("loaded plugin \"%s\" from %s" % (n, path))
171 | self.plugins[n] = mod
172 |
173 | def set_plugin_dir(self, dir):
174 | if not os.path.exists(dir):
175 | raise PluginServerException("%s not exists" % dir)
176 | self.plugin_dir = dir
177 | return "ok"
178 |
179 | @locked_by("i_lock")
180 | def get_status(self, *_):
181 | plugin_status = {}
182 | for name in self.plugins:
183 | instances = []
184 | for iid in self.instances:
185 | if self.instances[iid].name == name:
186 | i = self.instance_status(iid)
187 | instances.append(i)
188 | plugin = self.plugins[name]
189 | plugin_status[name] = {
190 | "Name": name,
191 | "Modtime": plugin.mtime,
192 | "LoadTime": plugin.load_time,
193 | "Instances": instances,
194 | "LastStartInstance": plugin.last_start_instance_time,
195 | "LastCloseInstance": plugin.last_close_instance_time,
196 | }
197 | return {
198 | "Pid": os.getpid(),
199 | "Plugins": plugin_status,
200 | }
201 |
202 | def get_plugin_info(self, name):
203 | if name not in self.plugins:
204 | raise PluginServerException("%s not initizlied" % name)
205 |
206 | plugin = self.plugins[name]
207 |
208 | info = {
209 | "Name": name,
210 | "Phases": plugin.phases,
211 | "Priority": plugin.priority,
212 | "Version": plugin.version,
213 | "Schema": {
214 | "name": name,
215 | "fields": [{
216 | "config": {
217 | "type": "record",
218 | "fields": plugin.schema,
219 | }
220 | }],
221 | },
222 | }
223 | return info
224 |
225 | @locked_by("i_lock")
226 | def start_instance(self, cfg):
227 | name = cfg['Name']
228 | if name not in self.plugins:
229 | raise PluginServerException("%s not initizlied" % name)
230 | plugin = self.plugins[name]
231 |
232 | config = json.loads(cfg['Config'])
233 | iid = self.instance_id
234 | self.instances[iid] = plugin.new(config)
235 | self.instance_id = iid + 1
236 |
237 | self.logger.info("instance #%d of %s started" % (iid, name))
238 |
239 | return {
240 | "Name": name,
241 | "Id": iid,
242 | "Config": config,
243 | "StartTime": time.time()
244 | }
245 |
246 | def instance_status(self, iid):
247 | if iid not in self.instances:
248 | # Note: Kong expect the error to start with "no plugin instance"
249 | raise PluginServerException("no plugin instance #%s" % iid)
250 |
251 | ins = self.instances[iid]
252 |
253 | return {
254 | "Name": ins.name,
255 | "Id": iid,
256 | "Config": ins.config,
257 | "StartTime": ins.start_time,
258 | }
259 |
260 | @locked_by("i_lock")
261 | def close_instance(self, iid):
262 | if iid not in self.instances:
263 | # Note: Kong expect the error to start with "no plugin instance"
264 | raise PluginServerException("no plugin instance #%s" % iid)
265 |
266 | ins = self.instances[iid]
267 | ins.close_cb()
268 | del self.instances[iid]
269 |
270 | return {
271 | "Name": ins.name,
272 | "Id": iid,
273 | "Config": ins.config,
274 | }
275 |
276 | @locked_by("e_lock")
277 | def handle_event(self, event):
278 | iid = event['InstanceId']
279 | if iid not in self.instances:
280 | # Note: Kong expect the error to start with "no plugin instance"
281 | raise PluginServerException("no plugin instance #%s" % iid)
282 |
283 | instance = self.instances[iid]
284 | instance.reset_expire_ts()
285 | cls = instance.cls
286 | phase = event['EventName']
287 |
288 | eid = self.event_id
289 | self.event_id = eid + 1
290 |
291 | if self.use_multiprocess:
292 | ch, child_ch = multiprocessing.Pipe(duplex=True)
293 | self._process_pool.apply_async(
294 | _handler_event_func,
295 | (getattr(cls, phase), child_ch, self.lua_style, ),
296 | )
297 | elif self.use_gevent:
298 | # plugin communites to Kong (RPC client) in a reverse way
299 | ch = gChannel()
300 |
301 | gspawn(_handler_event_func,
302 | getattr(cls, phase), ch, self.lua_style,
303 | )
304 | else: # normal threading mode
305 | ch = Queue()
306 | child_ch = Queue()
307 | ch.get, child_ch.get = child_ch.get, ch.get
308 | t = threading.Thread(
309 | target=_handler_event_func,
310 | args=(getattr(cls, phase), child_ch, self.lua_style, ),
311 | )
312 | t.setDaemon(True)
313 | t.start()
314 |
315 | r = ch.get()
316 | if r != MSG_RET:
317 | self.events[eid] = ch
318 |
319 | instance.reset_expire_ts()
320 |
321 | return {
322 | "Data": r,
323 | "EventId": eid,
324 | }
325 |
326 | def _step(self, data, is_error):
327 | eid = data['EventId']
328 | if eid not in self.events:
329 | raise PluginServerException("event id %s not found" % eid)
330 | dd = None
331 | if 'Data' in data:
332 | dd = data['Data']
333 | ch = self.events[eid]
334 | if is_error:
335 | ch.put((
336 | None, dd
337 | ))
338 | else:
339 | ch.put((
340 | dd, None
341 | ))
342 |
343 | ret = ch.get()
344 |
345 | if ret == MSG_RET or (isinstance(ret, dict) and ret.get("Method", None) in terminal_methods):
346 | del self.events[eid]
347 |
348 | return {
349 | "Data": ret,
350 | "EventId": eid,
351 | }
352 |
353 | def step(self, data):
354 | return self._step(data, False)
355 |
356 | def step_error(self, data):
357 | return self._step(data, True)
358 |
359 |
360 | for entity in entities:
361 | setattr(PluginServer, 'step_' + entity, PluginServer.step)
362 |
363 | setattr(PluginServer, 'step_multi_map', PluginServer.step)
364 |
--------------------------------------------------------------------------------
/requirements.txt:
--------------------------------------------------------------------------------
1 | gevent
2 | msgpack
3 | setproctitle
4 |
--------------------------------------------------------------------------------
/scripts/prepare_new_release.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash -v
2 |
3 | new_v=$1
4 | if [[ -z $1 ]]; then
5 | echo "Usage: $0 "
6 | exit 1
7 | fi
8 |
9 | if [[ $(uname) == "Darwin" ]]; then
10 | SED=gsed
11 | else
12 | SED=sed
13 | fi
14 |
15 | git reset
16 | old_v=$(python3 -c 'from kong_pdk.const import __version__ as v; print("%.1f.%d" % (v, v*100%10))')
17 | if [[ -z "$old_v" ]]; then
18 | echo "Unknown old version"
19 | exit 1
20 | fi
21 |
22 | echo "Creating new release $new_v from $old_v"
23 | git branch -D release/${new_v}
24 | git checkout -b release/${new_v}
25 |
26 | new_v_py=$(python3 -c "print('$new_v'.split('.')[0] + '.'+''.join('$new_v'.split('.')[1:]))")
27 | # file
28 | $SED -i "s/__version__ = .*/__version__ = $new_v_py/g" kong_pdk/const.py
29 | git add -u
30 |
31 | # changelog
32 | git commit -m "release: $new_v"
33 | git tag "$new_v"
34 | git-chglog --output CHANGELOG.md
35 | git add -u
36 | git tag -d "$new_v"
37 | git commit --amend -m "release: $new_v"
38 |
39 |
--------------------------------------------------------------------------------
/setup.cfg:
--------------------------------------------------------------------------------
1 | [flake8]
2 | ignore = E226,E302,E41,W503
3 | max-line-length = 160
4 | exclude = build,dist,kong_pdk/pdk/__init__.py,kong_pdk/pdk/kong/*
5 | max-complexity = 10
6 |
--------------------------------------------------------------------------------
/setup.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 | import os
3 | import imp
4 | from setuptools import setup
5 |
6 | PROJ_NAME = 'kong-pdk'
7 | PACKAGE_NAME = 'kong_pdk'
8 |
9 | PROJ_METADATA = '%s.json' % PROJ_NAME
10 |
11 | here = os.path.abspath(os.path.dirname(__file__))
12 |
13 | try:
14 | README = open(os.path.join(here, 'README.md')).read()
15 | except: # noqa: E722 do not use bare 'except
16 | README = ""
17 | try:
18 | CHANGELOG = open(os.path.join(here, 'CHANGELOG.md')).read()
19 | except: # noqa: E722 do not use bare 'except
20 | CHANGELOG = ""
21 | VERSION = "%.2f" % imp.load_source('version', os.path.join(here, '%s/const.py' % PACKAGE_NAME)).__version__
22 |
23 | packages = [
24 | 'kong_pdk',
25 | 'kong_pdk/pdk',
26 | 'kong_pdk/pdk/kong',
27 | 'kong_pdk/pdk/kong/client',
28 | 'kong_pdk/pdk/kong/ctx',
29 | 'kong_pdk/pdk/kong/nginx',
30 | 'kong_pdk/pdk/kong/service',
31 | 'kong_pdk/pdk/kong/enterprise_edition',
32 | ]
33 | requires = ['gevent', 'msgpack']
34 |
35 | setup(
36 | name=PACKAGE_NAME,
37 | version=VERSION,
38 | description='Kong PDK for Python and Plugin Server',
39 | long_description=README + '\n\n' + CHANGELOG,
40 | long_description_content_type="text/markdown",
41 | author='Kong',
42 | url='https://github.com/Kong/kong-python-pdk',
43 | packages=packages,
44 | package_dir={'requests': 'requests'},
45 | include_package_data=True,
46 | install_requires=requires,
47 | license="Apache-2.0",
48 | license_files=('LICENSE',),
49 | zip_safe=False,
50 | classifiers=(
51 | 'License :: OSI Approved :: Apache Software License',
52 | 'Programming Language :: Python',
53 | 'Programming Language :: Python :: 2.7',
54 | 'Programming Language :: Python :: 3',
55 | 'Programming Language :: Python :: 3.6',
56 | 'Programming Language :: Python :: 3.7',
57 | 'Programming Language :: Python :: 3.8',
58 | 'Programming Language :: Python :: 3.9',
59 | 'Programming Language :: Python :: Implementation :: CPython'
60 | ),
61 | requires=requires,
62 | entry_points={'console_scripts': ["kong-python-pluginserver = kong_pdk.cli:start_server"]},
63 | package_data={"kong_pdk": ["*.pyi", "**/*.pyi", "**/**/*.pyi", "**/**/**/*.pyi"]}
64 | )
65 |
--------------------------------------------------------------------------------