Skip to content

Commit

Permalink
feat(plugins/proxy-cache): add wildcard and parameter match support f…
Browse files Browse the repository at this point in the history
…or content_type
  • Loading branch information
vm-001 committed Feb 6, 2023
1 parent 8a422e5 commit 0883866
Show file tree
Hide file tree
Showing 4 changed files with 159 additions and 4 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,8 @@
as little as possible. During that time, the invalid sessions could cause failures and partial downtime.
All existing sessions are invalidated when upgrading to this version.
[#10199](https://github.com/Kong/kong/pull/10199)
- **Proxy Cache**: Add wildcard and parameter match support for content_type
[#10209](https://github.com/Kong/kong/pull/10209)

### Additions

Expand Down
27 changes: 23 additions & 4 deletions kong/plugins/proxy-cache/handler.lua
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
local require = require
local cache_key = require "kong.plugins.proxy-cache.cache_key"
local utils = require "kong.tools.utils"
local kong_meta = require "kong.meta"
local kong_meta = require "kong.meta"
local mime_type = require "kong.tools.mime_type"
local nkeys = require "table.nkeys"


local ngx = ngx
Expand All @@ -20,6 +22,7 @@ local ngx_re_gmatch = ngx.re.gmatch
local ngx_re_sub = ngx.re.gsub
local ngx_re_match = ngx.re.match
local parse_http_time = ngx.parse_http_time
local parse_mime_type = mime_type.parse_mime_type


local tab_new = require("table.new")
Expand Down Expand Up @@ -173,11 +176,27 @@ local function cacheable_response(conf, cc)
return false
end

local t, subtype, params = parse_mime_type(content_type)
local content_match = false
for i = 1, #conf.content_type do
if conf.content_type[i] == content_type then
content_match = true
break
local expected_ct = conf.content_type[i]
local exp_type, exp_subtype, exp_params = parse_mime_type(expected_ct)
if exp_type then
if (exp_type == "*" or t == exp_type) and
(exp_subtype == "*" or subtype == exp_subtype) then
local params_match = true
for key, value in pairs(exp_params or EMPTY) do
if value ~= (params or EMPTY)[key] then
params_match = false
break
end
end
if params_match and
(nkeys(params or EMPTY) == nkeys(exp_params or EMPTY)) then
content_match = true
break
end
end
end
end

Expand Down
28 changes: 28 additions & 0 deletions spec/03-plugins/31-proxy-cache/01-schema_spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -121,4 +121,32 @@ describe("proxy-cache schema", function()
assert.is_nil(err)
assert.is_truthy(entity)
end)

it("accepts wildcard content_type", function()
local entity, err = v({
strategy = "memory",
content_type = { "application/*", "*/text" },
}, proxy_cache_schema)

assert.is_nil(err)
assert.is_truthy(entity)

local entity, err = v({
strategy = "memory",
content_type = { "*/*" },
}, proxy_cache_schema)

assert.is_nil(err)
assert.is_truthy(entity)
end)

it("accepts content_type with parameter", function()
local entity, err = v({
strategy = "memory",
content_type = { "application/json; charset=UTF-8" },
}, proxy_cache_schema)

assert.is_nil(err)
assert.is_truthy(entity)
end)
end)
106 changes: 106 additions & 0 deletions spec/03-plugins/31-proxy-cache/02-access_spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,16 @@ do
local route16 = assert(bp.routes:insert({
hosts = { "route-16.com" },
}))
local route17 = assert(bp.routes:insert({
hosts = { "route-17.com" },
}))
local route18 = assert(bp.routes:insert({
hosts = { "route-18.com" },
}))
local route19 = assert(bp.routes:insert({
hosts = { "route-19.com" },
}))


local consumer1 = assert(bp.consumers:insert {
username = "bob",
Expand Down Expand Up @@ -242,6 +252,36 @@ do
},
})

assert(bp.plugins:insert {
name = "proxy-cache",
route = { id = route17.id },
config = {
strategy = policy,
[policy] = policy_config,
content_type = { "*/*" },
},
})

assert(bp.plugins:insert {
name = "proxy-cache",
route = { id = route18.id },
config = {
strategy = policy,
[policy] = policy_config,
content_type = { "application/xml; charset=UTF-8" },
},
})

assert(bp.plugins:insert {
name = "proxy-cache",
route = { id = route19.id },
config = {
strategy = policy,
[policy] = policy_config,
content_type = { "application/xml;" }, -- invalid content_type
},
})

assert(helpers.start_kong({
plugins = "bundled",
nginx_conf = "spec/fixtures/custom_nginx.template",
Expand Down Expand Up @@ -1240,5 +1280,71 @@ do
assert.matches("^%d+$", res.headers["X-Kong-Upstream-Latency"])
end)
end)

describe("content-type", function()
it("should cache a request with wildcard content_type(*/*)", function()
local request = {
method = "GET",
path = "/xml",
headers = {
host = "route-17.com",
},
}

local res = assert(client:send(request))
assert.res_status(200, res)
assert.same("application/xml", res.headers["Content-Type"])
assert.same("Miss", res.headers["X-Cache-Status"])

local res = assert(client:send(request))
assert.res_status(200, res)
assert.same("application/xml", res.headers["Content-Type"])
assert.same("Hit", res.headers["X-Cache-Status"])
end)

it("should not cache a request while parameter is not match", function()
local res = assert(client:send {
method = "GET",
path = "/xml",
headers = {
host = "route-18.com",
},
})

assert.res_status(200, res)
assert.same("application/xml", res.headers["Content-Type"])
assert.same("Bypass", res.headers["X-Cache-Status"])
end)


it("should not cause error while upstream returns a invalid content type", function()
local res = assert(client:send {
method = "GET",
path = "/response-headers?Content-Type=application/xml;",
headers = {
host = "route-18.com",
},
})

assert.res_status(200, res)
assert.same("application/xml;", res.headers["Content-Type"])
assert.same("Bypass", res.headers["X-Cache-Status"])
end)

it("should not cause error while config.content_type has invalid element", function()
local res, err = client:send {
method = "GET",
path = "/xml",
headers = {
host = "route-19.com",
},
}

assert.is_nil(err)
assert.res_status(200, res)
assert.same("application/xml", res.headers["Content-Type"])
assert.same("Bypass", res.headers["X-Cache-Status"])
end)
end)
end)
end

0 comments on commit 0883866

Please sign in to comment.