Skip to content

Commit 872b598

Browse files
committed
[proxy] don't call post_actions for already handled requests
for example oauth has own routes that can handle the request so there is no need to call post_action for them it should be called only when the access phase is evaluated
1 parent 73e1dcc commit 872b598

File tree

6 files changed

+105
-14
lines changed

6 files changed

+105
-14
lines changed

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
1818
- Use `RESOLVER` before falling back to `resolv.conf` [PR #324](https://github.com/3scale/apicast/pull/324)
1919
- Improve error logging when failing to download configuration [PR #335](https://github.com/3scale/apicast/pull/325)
2020
- Service hostnames are normalized to lower case [PR #336](https://github.com/3scale/apicast/pull/326)
21+
- Don't attempt to perform post\_action when request was handled without authentication [PR #343](https://github.com/3scale/apicast/pull/343)
2122

2223
### Fixed
2324

apicast/src/apicast.lua

+12-4
Original file line numberDiff line numberDiff line change
@@ -80,9 +80,10 @@ function _M:post_action()
8080
post_action_proxy[request_id] = nil
8181

8282
if p then
83-
p:post_action()
83+
return p:post_action()
8484
else
8585
ngx.log(ngx.INFO, 'could not find proxy for request id: ', request_id)
86+
return nil, 'no proxy for request'
8687
end
8788
end
8889

@@ -94,10 +95,17 @@ function _M:access()
9495
return nil, 'not initialized'
9596
end
9697

97-
local fun = p:call() -- proxy:access() or oauth handler
98-
local ok, err = fun()
98+
local access, handler = p:call() -- proxy:access() or oauth handler
9999

100-
post_action_proxy[ngx.var.original_request_id] = p
100+
local ok, err
101+
102+
if access then
103+
ok, err = access()
104+
post_action_proxy[ngx.var.original_request_id] = p
105+
elseif handler then
106+
ok, err = handler()
107+
-- no proxy because that would trigger post action
108+
end
101109

102110
return ok, err
103111
end

apicast/src/proxy.lua

+15-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,11 @@
1+
------------
2+
-- Proxy
3+
-- Module that handles the request authentication and proxying upstream.
4+
--
5+
-- @module proxy
6+
-- @author mikz
7+
-- @license Apache License Version 2.0
8+
19
local env = require 'resty.env'
210
local custom_config = env.get('APICAST_CUSTOM_CONFIG')
311
local configuration_store = require 'configuration_store'
@@ -266,6 +274,12 @@ function _M:set_backend_upstream(service)
266274
ngx.var.backend_host = backend.host or server or ngx.var.backend_host
267275
end
268276

277+
-----
278+
-- call the proxy and return a handler function
279+
-- that will perform an action based on the path and backend version
280+
-- @string host optional hostname, uses `ngx.var.host` otherwise
281+
-- @treturn nil|function access function (when the request needs to be authenticated with this)
282+
-- @treturn nil|function handler function (when the request is not authenticated and has some own action)
269283
function _M:call(host)
270284
host = host or ngx.var.host
271285
local service = ngx.ctx.service or self:set_service(host)
@@ -279,7 +293,7 @@ function _M:call(host)
279293

280294
if f then
281295
ngx.log(ngx.DEBUG, 'apicast oauth flow')
282-
return function() return f(params) end
296+
return nil, function() return f(params) end
283297
end
284298
end
285299

doc/config.ld

+1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
file = {
2+
'../apicast/src/proxy.lua',
23
'../apicast/src/configuration/service.lua',
34
'../apicast/src/resty/env.lua',
45
'../apicast/src/resty/http_ng.lua',

spec/apicast_spec.lua

+48-3
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,57 @@
1-
local apicast = require 'apicast'
1+
local _M = require 'apicast'
22

33
describe('APIcast module', function()
44

55
it('has a name', function()
6-
assert.truthy(apicast._NAME)
6+
assert.truthy(_M._NAME)
77
end)
88

99
it('has a version', function()
10-
assert.truthy(apicast._VERSION)
10+
assert.truthy(_M._VERSION)
11+
end)
12+
13+
describe(':access', function()
14+
15+
local apicast
16+
17+
before_each(function()
18+
apicast = _M.new()
19+
ngx.ctx.proxy = {}
20+
end)
21+
22+
it('triggers post action when access phase succeeds', function()
23+
ngx.var = { original_request_id = 'foobar' }
24+
25+
stub(ngx.ctx.proxy, 'call', function()
26+
return function() return 'ok' end
27+
end)
28+
29+
stub(ngx.ctx.proxy, 'post_action', function()
30+
return 'post_ok'
31+
end)
32+
33+
local ok, err = apicast:access()
34+
35+
assert.same('ok', ok)
36+
assert.falsy(err)
37+
38+
assert.same('post_ok', apicast:post_action())
39+
end)
40+
41+
it('skips post action when access phase not executed', function()
42+
stub(ngx.ctx.proxy, 'call', function()
43+
-- return nothing for example
44+
end)
45+
46+
local ok, err = apicast:access()
47+
48+
assert.falsy(ok)
49+
assert.falsy(err)
50+
51+
ngx.ctx.proxy = nil -- in post_action the ctx is not shared
52+
ngx.var = { original_request_id = 'foobar' }
53+
54+
assert.equal(nil, apicast:post_action())
55+
end)
1156
end)
1257
end)

spec/proxy_spec.lua

+28-6
Original file line numberDiff line numberDiff line change
@@ -13,14 +13,36 @@ describe('Proxy', function()
1313
assert.same('function', type(proxy.access))
1414
end)
1515

16-
it('has authorize function after call', function()
17-
ngx.var = { backend_endpoint = 'http://localhost:1853' }
18-
configuration:add({ id = 42, hosts = { 'localhost' }})
16+
describe(':call', function()
17+
before_each(function()
18+
ngx.var = { backend_endpoint = 'http://localhost:1853' }
19+
configuration:add({ id = 42, hosts = { 'localhost' }})
20+
end)
21+
22+
it('has authorize function after call', function()
23+
proxy:call('localhost')
1924

20-
proxy:call('localhost')
25+
assert.truthy(proxy.authorize)
26+
assert.same('function', type(proxy.authorize))
27+
end)
2128

22-
assert.truthy(proxy.authorize)
23-
assert.same('function', type(proxy.authorize))
29+
it('returns access function', function()
30+
local access = proxy:call('localhost')
31+
32+
assert.same('function', type(access))
33+
end)
34+
35+
it('returns oauth handler when matches oauth route', function()
36+
local service = configuration:find_by_id(42)
37+
service.backend_version = 'oauth'
38+
stub(ngx.req, 'get_method', function() return 'GET' end)
39+
ngx.var.uri = '/authorize'
40+
41+
local access, handler = proxy:call('localhost')
42+
43+
assert.equal(nil, access)
44+
assert.same('function', type(handler))
45+
end)
2446
end)
2547

2648
it('has post_action function', function()

0 commit comments

Comments
 (0)