Skip to main content

Python helps you develop Apache APISIX plugin

· 7 min read

The Java Plugin and Go Plugin languages have been supported in the community before the Apache APISIX Python Runner, and today Python Runner is now available, giving the community another option for developing plugins for Apache APISIX.

Introduction#

Apache APISIX#

Apache APISIX is a high-performance cloud-native open-source API gateway that provides unified request interception and governance (e.g., authentication, caching, versioning, fusing, auditing, etc.) to help developers easily provide secure and reliable services to the outside world, while developers only need to focus on business implementation with Apache APISIX, which saves a lot of time in developing and maintaining generic capabilities and reduces the complexity of the overall business architecture.

Python#

Python is an interpreted high-level programming language with a simple syntax, good code readability, cross-platform, portability, and development efficiency. As a high-level programming language, it has a high degree of abstraction and shields a lot of underlying details (e.g., GC). ) allows us to focus more on the development of application logic in the development process. As a 30-year old development language, Python has a well-developed ecology and various modules, and most of our development and application scenarios can be found in mature modules or solutions from the community. Python We won't go into all the other advantages. The disadvantages of Python are also obvious: Python, as an interpreted language, has a relatively large performance gap compared to compiled languages like C++ and Go.

Apache APISIX Python Runner#

apache-apisix-python-runner This project can be interpreted as Apache APISIX and Python. The most important thing is to let more Python developers who are interested in Apache APISIX and API gateways to learn more about the use of Apache APISIX and API gateways through this project. The following is a diagram of the architecture of Apache APISIX multi-language support.

Apache APISIX work flow

The above diagram shows the workflow of Apache APISIX on the left, and the Plugin Runner on the right is the plug-in runner for each language, the apisix-python-plugin-runner introduced in this article is the one that supports Python. language.

When you configure a Plugin Runner in Apache APISIX, Apache APISIX will start a child process to run the Plugin Runner that belongs to the same user as the Apache APISIX process belongs to the same user, and when we restart or reload Apache APISIX, Plugin Runner will also be restarted.

If you configure the ext-plugin-* plugin for a given route, a request to hit that route will trigger an Apache APISIX RPC call to the Plugin Runner via the Unix Socket. The call is split into two phases.

You can choose and configure the execution timing of Plugin Runner as needed.

The Plugin Runner handles the RPC call, creates a simulated request inside it, and then runs the multilingual plugin and returns the result to Apache APISIX.

The execution order of multilingual plugins is defined in the ext-plugin-* plugin configuration entry, and like other plugins, they can be enabled and redefined on the fly.

Deploy test#

Base runtime environment#

  • Apache APISIX 2.7
  • Python 3.6+

To deploy Apache APISIX, please refer to the Apache APISIX official documentation: How to build Apache APISIX for details.

Download and install Python Runner#

$ git clone https://github.com/apache/apisix-python-plugin-runner.git$ cd apisix-python-plugin-runner$ make install

Configuring Python Runner#

development mode#

Run Python Runner#
$ cd /path/to/apisix-python-plugin-runner$ APISIX_LISTEN_ADDRESS=unix:/tmp/runner.sock python3 apisix/main.py start
Modify APISIX configuration file#
$ vim /path/to/apisix/conf/config.yamlapisix:  admin_key:    - name: "admin"      key: edd1c9f034335f136f87ad84b625c8f1      role: adminext-plugin:  path_for_test: /tmp/runner.sock

Production mode#

Modify APISIX configuration file#
$ vim /path/to/apisix/conf/config.yamlapisix:  admin_key:    - name: "admin"      key: edd1c9f034335f136f87ad84b625c8f1      role: adminext-plugin:  cmd: [ "python3", "/path/to/apisix-python-plugin-runner/apisix/main.py", "start" ]

Python Runner configuration (optional)#

If you need to adjust the Log Level or Unix Domain Socket environment variables, you can modify the Runner configuration file

$ vim /path/to/apisix-python-plugin-runner/apisix/config.yamlsocket:  file: $env.APISIX_LISTEN_ADDRESS # Environment variable or absolute path
logging:  level: debug # error warn info debugdebug

Start Python Runner#

$ cd /path/to/apisix# Start or Restart$ ./bin/apisix [ start | restart ]

Start or restart APISIX, when APISIX and Python Runner have been configured and started.

Testing Python Runner#

Configuring Apache APISIX Routing and Plugin Information#

# Test with the default demo plugin$ curl http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '{  "uri": "/get",  "plugins": {    "ext-plugin-pre-req": {      "conf": [        { "name": "stop", "value":"{\"body\":\"hello\"}"}      ]    }  },  "upstream": {        "type": "roundrobin",        "nodes": {            "127.0.0.1:1980": 1        }    }}'
  • plugins.ext-plugin-pre-req.conf is the Runner plugin configuration, conf is an array format to set multiple plugins at the same time.
  • The name in the plugin configuration object is the name of the plugin, which should be the same as the plugin code file and object name.
  • value in the plugin configuration object is the plugin configuration, which can be a JSON string.

access verification#

$ curl http://127.0.0.1:9080/get -iHTTP/1.1 200 OKDate: Fri, 13 Aug 2021 13:39:18 GMTContent-Type: text/plain; charset=utf-8Transfer-Encoding: chunkedConnection: keep-alivehost: 127.0.0.1:9080accept: */*user-agent: curl/7.64.1X-Resp-A6-Runner: PythonServer: APISIX/2.7
Hello, Python Runner of APISIX

Plugin Development#

Plugin directory#

/path/to/apisix-python-plugin-runner/apisix/plugins

The .py files in this directory will be loaded automatically.

Plugin example#

/path/to/apisix-python-plugin-runner/apisix/plugins/stop.py/path/to/apisix-python-plugin-runner/apisix/plugins/rewrite.py

Plugin format#

from apisix.runner.plugin.base import Basefrom apisix.runner.http.request import Requestfrom apisix.runner.http.response import Response

class Stop(Base):    def __init__(self):        """        Example of `stop` type plugin, features:            This type of plugin can customize response `body`, `header`, `http_code`            This type of plugin will interrupt the request        """        super(Stop, self). __init__(self.__class__. __name__)
    def filter(self, request: Request, response: Response):        """        The plugin executes the main function        :param request:            request parameters and information        :param response:            response parameters and information        :return:        """        # In the plugin you can get the configuration information through `self.config`,        # if the plugin configuration is JSON it will be automatically converted to        # a dictionary structure        # print(self.config)
        # set the response headers        headers = request.headers        headers["X-Resp-A6-Runner"] = "Python"        response.headers = headers
        # Set the response body information        response.body = "Hello, Python Runner of APISIX"
        # Set the response status code        response.status_code = 201
        # Interrupt the request process by calling `self.stop()`, which will immediately respond to the client        # If `self.stop()` is not shown or if `self.rewrite()` is shown, the request will continue        # Default is `self.rewrite()`        self.stop()

Plugin specifications and considerations#

  • Plugin object implementation must inherit from the Base class
  • The plugin must implement the filter function
  • filter function parameters can only contain Request and Response class objects as parameters
  • Request object parameter can get request information
  • Response object parameter can set the response information
  • self.config can get the plugin configuration information
  • Calling self.stop() in the filter function will immediately break the request and respond to the data.
  • When self.rewrite() is called in the filter function, the request will continue.

Welcome to participate#

The Runner for Apache APISIX languages is still in the early stages of development, and we will continue to improve its functionality. A successful open source project cannot be achieved without everyone's participation and contribution, welcome to participate in Apache APISIX Runner. Let's build a bridge between Apache APISIX and other languages together.

Related Reading#