blob: 81e027273acce1d1c6f3183bfaabc589d196de46 [file] [log] [blame]
-- Copyright (c) 2016 IBM. All rights reserved.
--
-- Permission is hereby granted, free of charge, to any person obtaining a
-- copy of this software and associated documentation files (the "Software"),
-- to deal in the Software without restriction, including without limitation
-- the rights to use, copy, modify, merge, publish, distribute, sublicense,
-- and/or sell copies of the Software, and to permit persons to whom the
-- Software is furnished to do so, subject to the following conditions:
--
-- The above copyright notice and this permission notice shall be included in
-- all copies or substantial portions of the Software.
--
-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-- FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-- DEALINGS IN THE SOFTWARE.
--- @module backendRouting
-- Used to set the backend Url either statically or dynamically
local url = require "url"
local utils = require "lib/utils"
local request = require "lib/request"
local logger = require "lib/logger"
local _M = {}
--- Set upstream based on the backendUrl
function _M.setRoute(backendUrl)
local u = url.parse(backendUrl)
if u.scheme == nil then
u = url.parse(utils.concatStrings({'http://', backendUrl}))
end
ngx.var.backendUrl = backendUrl
ngx.req.set_uri(getUriPath(u.path))
setUpstream(u)
end
--- Set dynamic route based on the based on the header that is passed in
function _M.setDynamicRoute(obj)
local whitelist = obj.whitelist
for k in pairs(whitelist) do
whitelist[k] = whitelist[k]:lower()
end
local header = obj.header ~= nil and obj.header or 'X-Cf-Forwarded-Url'
local dynamicBackend = ngx.req.get_headers()[header];
if dynamicBackend ~= nil and dynamicBackend ~= '' then
local u = url.parse(dynamicBackend)
if u.scheme == nil or u.scheme == '' then
u = url.parse(utils.concatStrings({'http://', dynamicBackend}))
end
if utils.tableContains(whitelist, u.host) then
if header:lower() ~= 'x-cf-forwarded-url' then
ngx.req.set_uri(getUriPath(u.path))
end
setUpstream(u)
else
request.err(403, 'Dynamic backend host not part of whitelist.')
end
else
logger.info('Header for dynamic routing not found. Defaulting to backendUrl.')
end
end
function getUriPath(backendPath)
local gatewayPath = ngx.unescape_uri(ngx.var.gatewayPath)
gatewayPath = gatewayPath:gsub('-', '%%-')
local uri = string.gsub(ngx.var.request_uri, '?.*', '')
local _, j = uri:find(gatewayPath)
local incomingPath = ((j and uri:sub(j + 1)) or nil)
-- Check for backendUrl path
if backendPath == nil or backendPath == '' or backendPath == '/' then
incomingPath = (incomingPath and incomingPath ~= '') and incomingPath or '/'
incomingPath = string.sub(incomingPath, 1, 1) == '/' and incomingPath or utils.concatStrings({'/', incomingPath})
return incomingPath
else
return utils.concatStrings({backendPath, incomingPath})
end
end
function setUpstream(u)
local upstream = utils.concatStrings({u.scheme, '://', u.host})
if u.port ~= nil and u.port ~= '' then
upstream = utils.concatStrings({upstream, ':', u.port})
end
ngx.var.upstream = upstream
end
return _M