diff --git a/gateway/src/apicast/threescale_utils.lua b/gateway/src/apicast/threescale_utils.lua index d634178f0..f8f65d70a 100644 --- a/gateway/src/apicast/threescale_utils.lua +++ b/gateway/src/apicast/threescale_utils.lua @@ -124,7 +124,7 @@ function _M.connect_redis(options) local opts = {} local url = options and options.url or env.get('REDIS_URL') - + local resilient = options.resilient or false if url then url = resty_url.split(url, 'redis') @@ -152,14 +152,14 @@ function _M.connect_redis(options) local ok, err = red:connect(_M.resolve(host, port)) if not ok then - return nil, _M.error("failed to connect to redis on ", host, ":", port, ": ", err) + return nil, _M.error(resilient, "failed to connect to redis on ", host, ":", port, ": ", err) end if opts.password then ok = red:auth(opts.password) if not ok then - return nil, _M.error("failed to auth on redis ", host, ":", port) + return nil, _M.error(resilient, "failed to auth on redis ", host, ":", port) end end @@ -167,7 +167,7 @@ function _M.connect_redis(options) ok = red:select(opts.db) if not ok then - return nil, _M.error("failed to select db ", opts.db, " on redis ", host, ":", port) + return nil, _M.error(resilient, "failed to select db ", opts.db, " on redis ", host, ":", port) end end @@ -188,13 +188,15 @@ function _M.match_xml_element(xml, element, value) end -- error and exit -function _M.error(...) +function _M.error(resilient, ...) if ngx.get_phase() == 'timer' then return table.concat(table.pack(...)) else ngx.status = ngx.HTTP_INTERNAL_SERVER_ERROR ngx.say(...) - ngx.exit(ngx.status) + if not resilient then + ngx.exit(ngx.status) + end end end diff --git a/spec/threescale_utils_spec.lua b/spec/threescale_utils_spec.lua index 04ca1cf36..b90904c8c 100644 --- a/spec/threescale_utils_spec.lua +++ b/spec/threescale_utils_spec.lua @@ -4,11 +4,20 @@ describe('3scale utils', function() describe('.error', function() it('returns concatenated error in timer phase', function() local get_phase = spy.on(ngx, 'get_phase', function() return 'timer' end) - local error = _M.error('one', ' two', ' three') + local error = _M.error(nil, 'one', ' two', ' three') assert.spy(get_phase).was_called(1) assert.equal('one two three', error) end) + + it('does not terminate with nginx.exit if resilient flag is set', function() + local exit = spy.on(ngx, 'exit', function() return 'exited!' end) + local error = _M.error(true, 'redis is not reachable') + + assert.spy(exit).was_not_called() + + assert.equal('redis is not reachable', error) + end) end) end)