blob: 91800fbdfdb8a931c1fb0da12f2767806c53e520 [file] [view]
---
title: Development
---
<!--
#
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You under the Apache License, Version 2.0
# (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
-->
## Overview
This document explains how to write custom plugins.
#### The name of filter execution
The requests go through filters that are dynamically configured on APISIX.
For example, if the following configuration is done on APISIX
```shell
curl http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
{
"uri":"/hello",
"plugins":{
"ext-plugin-pre-req":{
"conf":[
{
"name":"FooFilter",
"value":"bar"
}
]
}
},
"upstream":{
"nodes":{
"127.0.0.1:1980":1
},
"type":"roundrobin"
}
}'
```
apisix-java-plugin-runner will look for implementation classes named `FooFilter`,
and the name of each filter's implementation class is the return value of its overridden function `public String name()`.
#### The functions must be implemented of filter execution
- `String name();`
description: return the name of plugin filter
code example:
```java
@Override
public String name() {
return "FooFilter";
}
```
- `void filter(HttpRequest request, HttpResponse response, PluginFilterChain chain);`
description: implementing custom business logic
code example:
```java
@Override
public void filter(HttpRequest request, HttpResponse response, PluginFilterChain chain) {
// get conf of current filter
String configStr = request.getConfig(this);
Gson gson = new Gson();
Map<String, Object> conf = new HashMap<>();
// convert according to the actual configured conf type
conf = gson.fromJson(configStr, conf.getClass());
// get extra info
String remoteAddr = request.getVars("remote_addr");
String serverPort = request.getVars("server_port");
String body = request.getBody();
chain.filter(request, response);
}
```
- `List<String> requiredVars();`
description: declare in advance the nginx variables you want to use in the current filter
code example:
```java
@Override
public List<String> requiredVars() {
List<String> vars = new ArrayList<>();
vars.add("remote_addr");
vars.add("server_port");
return vars;
}
```
- `Boolean requiredBody();`
description: whether the request body is required in the current filter, true means yes.
code example:
```java
@Override
public Boolean requiredBody() {
return true;
}
```
#### Rewrite Request
If you perform the following function call in the filter chain of the implementation class
* request.getConfig()
* request.setPath()
* request.setHeader()
* request.setArg()
this means to rewrit the current request, the upstream server will receive
the relevant parameters rewritten here.
#### Stop Request
If you perform the following function call in the filter chain of the implementation class
* response.setStatusCode()
* response.setHeader()
* response.setBody()
this means to stop the current request, the client will receive
the relevant parameters generated here.
#### Get the upstream response and process
You can override the `postFilter` function, in your override function,
you can get the origin upstream response by `PostRequest`,
and you can also set the `PostResponse` to override the origin upstream response and return it to the client.
##### PostRequest
* request.getConfig()
* request.getUpstreamHeaders()
* request.getUpstreamStatusCode()
* request.getBody()
##### PostResponse
* response.setStatusCode()
* response.setHeader()
* response.setBody()
Test
----
### Run Unit Test Suites
```shell
cd /path/to/apisix-java-plugin-runner
./mvnw test
```
### Mimic practical environment
If you want to mimic the practical environment, you need to configure the route on APISIX
by having the request go through the filter you want to test, for example
```json
"plugins":{
"ext-plugin-pre-req":{
"conf":[
{
"name":"FooFilter",
"value":"bar"
}
]
}
}
```
and then make a request to APISIX to trigger the route.