Skip to content

Commit

Permalink
feat: add gzip plugin
Browse files Browse the repository at this point in the history
Signed-off-by: spacewander <spacewanderlzx@gmail.com>
  • Loading branch information
spacewander committed Jul 21, 2021
1 parent 1bd710d commit 41374c1
Show file tree
Hide file tree
Showing 8 changed files with 718 additions and 2 deletions.
158 changes: 158 additions & 0 deletions apisix/plugins/gzip.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
--
-- 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.
--
local core = require("apisix.core")
local is_apisix_or, response = pcall(require, "resty.apisix.response")
local ngx_header = ngx.header
local req_http_version = ngx.req.http_version
local str_sub = string.sub
local ipairs = ipairs
local tonumber = tonumber


local schema = {
type = "object",
properties = {
types = {
type = "array",
minItems = 1,
items = {
type = "string",
minLength = 1,
},
default = {"text/html"}
},
min_length = {
type = "integer",
minimum = 1,
default = 20,
},
comp_level = {
type = "integer",
minimum = 1,
maximum = 9,
default = 1,
},
http_version = {
enum = {1.1, 1.0},
default = 1.1,
},
buffers = {
type = "object",
properties = {
number = {
type = "integer",
minimum = 1,
default = 32,
},
size = {
type = "integer",
minimum = 1,
default = 4096,
}
},
default = {
number = 32,
size = 4096,
}
},
vary = {
type = "boolean",
}
},
}


local plugin_name = "gzip"


local _M = {
version = 0.1,
priority = 995,
name = plugin_name,
schema = schema,
}


function _M.check_schema(conf)
return core.schema.check(schema, conf)
end


function _M.header_filter(conf, ctx)
if not is_apisix_or then
core.log.error("need to build APISIX-OpenResty to support setting gzip")
return 501
end

local types = conf.types
local content_type = ngx_header["Content-Type"]
if not content_type then
-- Like Nginx, don't gzip if Content-Type is missing
return
end
local from = core.string.find(content_type, ";")
if from then
content_type = str_sub(content_type, 1, from - 1)
end

local matched = false
for _, ty in ipairs(types) do
if content_type == ty then
matched = true
break
end
end
if not matched then
return
end

local content_length = tonumber(ngx_header["Content-Length"])
if content_length then
local min_length = conf.min_length
if content_length < min_length then
return
end
-- Like Nginx, don't check min_length if Content-Length is missing
end

local http_version = req_http_version()
if http_version < conf.http_version then
return
end

local buffers = conf.buffers

core.log.info("set gzip with buffers: ", buffers.number, " ", buffers.size,
", level: ", conf.comp_level)

local ok, err = response.set_gzip({
buffer_num = buffers.number,
buffer_size = buffers.size,
compress_level = conf.comp_level,
})
if not ok then
core.log.error("failed to set gzip: ", err)
return
end

if conf.vary then
core.response.add_header("Vary", "Accept-Encoding")
end
end


return _M
1 change: 1 addition & 0 deletions conf/config-default.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -300,6 +300,7 @@ plugins: # plugin list (sorted by priority)
- limit-count # priority: 1002
- limit-req # priority: 1001
#- node-status # priority: 1000
- gzip # priority: 995
- server-info # priority: 990
- traffic-split # priority: 966
- redirect # priority: 900
Expand Down
1 change: 1 addition & 0 deletions docs/en/latest/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
"plugins/serverless",
"plugins/redirect",
"plugins/echo",
"plugins/gzip",
"plugins/server-info",
"plugins/ext-plugin-pre-req",
"plugins/ext-plugin-post-req"
Expand Down
112 changes: 112 additions & 0 deletions docs/en/latest/plugins/gzip.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
---
title: gzip
---

<!--
#
# 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.
#
-->

## Summary

- [**Name**](#name)
- [**Attributes**](#attributes)
- [**How To Enable**](#how-to-enable)
- [**Test Plugin**](#test-plugin)
- [**Disable Plugin**](#disable-plugin)

## Name

The `gzip` plugin dynamically set the gzip behavior of Nginx.

This plugin requires APISIX to run on [APISIX-OpenResty](../how-to-build.md#6-build-openresty-for-apisix).

## Attributes

| Name | Type | Requirement | Default | Valid | Description |
| --------- | ------------- | ----------- | ---------- | ------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------- |
| types | array | optional | ["text/html"] | | dynamically set the `gzip_types` directive |
| min_length | integer | optional | 20 | >= 1 | dynamically set the `gzip_min_length` directive |
| comp_level | integer | optional | 1 | [1, 9] | dynamically set the `gzip_comp_level` directive |
| http_version | number | optional | 1.1 | 1.1, 1.0 | dynamically set the `gzip_http_version` directive |
| buffers.number | integer | optional | 32 | >= 1 | dynamically set the `gzip_buffers` directive |
| buffers.size | integer | optional | 4096 | >= 1 | dynamically set the `gzip_buffers` directive |
| vary | boolean | optional | false | | dynamically set the `gzip_vary` directive |

## How To Enable

Here's an example, enable this plugin on the specified route:

```shell
curl -i http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
{
"uri": "/index.html",
"plugins": {
"gzip": {
"buffers": {
"number": 8
}
}
},
"upstream": {
"type": "roundrobin",
"nodes": {
"127.0.0.1:1980": 1
}
}
}'
```

## Test Plugin

Use curl to access:

```shell
curl http://127.0.0.1:9080/index.html -i -H "Accept-Encoding: gzip"
HTTP/1.1 404 Not Found
Content-Type: text/html; charset=utf-8
Transfer-Encoding: chunked
Connection: keep-alive
Date: Wed, 21 Jul 2021 03:52:55 GMT
Server: APISIX/2.7
Content-Encoding: gzip

Warning: Binary output can mess up your terminal. Use "--output -" to tell
Warning: curl to output it to your terminal anyway, or consider "--output
Warning: <FILE>" to save to a file.
```

## Disable Plugin

When you want to disable this plugin, it is very simple,
you can delete the corresponding JSON configuration in the plugin configuration,
no need to restart the service, it will take effect immediately:

```shell
curl http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
{
"uri": "/index.html",
"upstream": {
"type": "roundrobin",
"nodes": {
"127.0.0.1:1980": 1
}
}
}'
```

This plugin has been disabled now. It works for other plugins.
2 changes: 1 addition & 1 deletion t/admin/plugins.t
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ __DATA__
--- request
GET /apisix/admin/plugins/list
--- response_body_like eval
qr/\["client-control","ext-plugin-pre-req","zipkin","request-id","fault-injection","serverless-pre-function","batch-requests","cors","ip-restriction","referer-restriction","uri-blocker","request-validation","openid-connect","wolf-rbac","hmac-auth","basic-auth","jwt-auth","key-auth","consumer-restriction","authz-keycloak","proxy-mirror","proxy-cache","proxy-rewrite","api-breaker","limit-conn","limit-count","limit-req","server-info","traffic-split","redirect","response-rewrite","grpc-transcode","prometheus","echo","http-logger","sls-logger","tcp-logger","kafka-logger","syslog","udp-logger","example-plugin","serverless-post-function","ext-plugin-post-req"\]/
qr/\["client-control","ext-plugin-pre-req","zipkin","request-id","fault-injection","serverless-pre-function","batch-requests","cors","ip-restriction","referer-restriction","uri-blocker","request-validation","openid-connect","wolf-rbac","hmac-auth","basic-auth","jwt-auth","key-auth","consumer-restriction","authz-keycloak","proxy-mirror","proxy-cache","proxy-rewrite","api-breaker","limit-conn","limit-count","limit-req","gzip","server-info","traffic-split","redirect","response-rewrite","grpc-transcode","prometheus","echo","http-logger","sls-logger","tcp-logger","kafka-logger","syslog","udp-logger","example-plugin","serverless-post-function","ext-plugin-post-req"\]/
--- no_error_log
[error]
Expand Down
1 change: 1 addition & 0 deletions t/debug/debug-mode.t
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ loaded plugin and sort by priority: 1005 name: api-breaker
loaded plugin and sort by priority: 1003 name: limit-conn
loaded plugin and sort by priority: 1002 name: limit-count
loaded plugin and sort by priority: 1001 name: limit-req
loaded plugin and sort by priority: 995 name: gzip
loaded plugin and sort by priority: 990 name: server-info
loaded plugin and sort by priority: 966 name: traffic-split
loaded plugin and sort by priority: 900 name: redirect
Expand Down
2 changes: 1 addition & 1 deletion t/lib/server.lua
Original file line number Diff line number Diff line change
Expand Up @@ -376,7 +376,7 @@ function _M.echo()
for k, v in pairs(hdrs) do
ngx.header[k] = v
end
ngx.say(ngx.req.get_body_data() or "")
ngx.print(ngx.req.get_body_data() or "")
end


Expand Down
Loading

0 comments on commit 41374c1

Please sign in to comment.