Handle APIs directly from redis instead of using filemgmt
diff --git a/api-gateway-config/conf.d/managed_endpoints.conf b/api-gateway-config/conf.d/managed_endpoints.conf
index 6edacd0..8d459db 100644
--- a/api-gateway-config/conf.d/managed_endpoints.conf
+++ b/api-gateway-config/conf.d/managed_endpoints.conf
@@ -58,11 +58,22 @@
';
}
+ location ~ ^/api/([a-zA-Z0-9\-]+)/([a-zA-Z0-9\-\/\-\_\{\}]+)(\\b) {
+ set $upstream https://172.17.0.1;
+ set $tenant $1;
+ set $backendUrl '';
+ set $gatewayPath $2;
+ add_header Access-Control-Allow-Methods 'GET, POST, PUT, DELETE, PATCH, HEAD, OPTIONS';
+ access_by_lua_block {
+ local routing = require "routing"
+ routing.processCall()
+ }
+ proxy_pass $upstream;
+ }
+
location = /health {
proxy_pass http://0.0.0.0:9000/v1/health-check;
}
-
- include /etc/api-gateway/managed_confs/*/*.conf;
}
diff --git a/api-gateway-config/scripts/lua/lib/redis.lua b/api-gateway-config/scripts/lua/lib/redis.lua
index 6ba3853..dfdcb7a 100644
--- a/api-gateway-config/scripts/lua/lib/redis.lua
+++ b/api-gateway-config/scripts/lua/lib/redis.lua
@@ -23,13 +23,11 @@
-- @author Alex Song (songs)
local cjson = require "cjson"
-local filemgmt = require "lib/filemgmt"
local utils = require "lib/utils"
local logger = require "lib/logger"
local request = require "lib/request"
local REDIS_FIELD = "resources"
-local BASE_CONF_DIR = "/etc/api-gateway/managed_confs/"
local _M = {}
@@ -357,31 +355,7 @@
------- Pub/Sub with Redis --------
-----------------------------------
-local syncStatus = false
---- Sync with redis on startup and create conf files for resources that are already in redis
--- @param red redis client instance
-function _M.syncWithRedis(red)
- logger.info("Sync with redis in progress...")
- setSyncStatus(true)
- local resourceKeys = getAllResourceKeys(red)
- for k, resourceKey in pairs(resourceKeys) do
- local prefix, tenant, gatewayPath = resourceKey:match("([^,]+):([^,]+):([^,]+)")
- local resourceObj = _M.getResource(red, resourceKey, REDIS_FIELD)
- filemgmt.createResourceConf(BASE_CONF_DIR, tenant, ngx.escape_uri(gatewayPath), resourceObj)
- end
- os.execute("/usr/local/sbin/nginx -s reload")
- setSyncStatus(false)
- logger.info("All resources synced.")
-end
-
-function setSyncStatus(status)
- syncStatus = status
-end
-
-function getSyncStatus()
- return syncStatus
-end
-
+local gatewayReady = false
--- Subscribe to redis
-- @param redisSubClient the redis client that is listening for the redis key changes
-- @param redisGetClient the redis client that gets the changed resource to update the conf file
@@ -396,10 +370,8 @@
if not ok then
request.err(500, utils.concatStrings({"Failed to subscribe to redis: ", err}))
end
- -- Update nginx conf file when redis is updated
- local redisUpdated = false
- local startTime = ngx.now()
while true do
+ gatewayReady = true
local res, err = redisSubClient:read_reply()
if not res then
if err ~= "timeout" then
@@ -416,31 +388,18 @@
local resourceObj = _M.getResource(redisGetClient, redisKey, REDIS_FIELD)
if resourceObj == nil then
logger.debug(utils.concatStrings({"Redis key deleted: ", redisKey}))
- local fileLocation = filemgmt.deleteResourceConf(BASE_CONF_DIR, tenant, ngx.escape_uri(gatewayPath))
- logger.debug(utils.concatStrings({"Deleted file: ", fileLocation}))
else
logger.debug(utils.concatStrings({"Redis key updated: ", redisKey}))
- local fileLocation = filemgmt.createResourceConf(BASE_CONF_DIR, tenant, ngx.escape_uri(gatewayPath), resourceObj)
- logger.debug(utils.concatStrings({"Updated file: ", fileLocation}))
end
- redisUpdated = true
end
end
- -- reload Nginx only if redis has been updated and it has been at least 1 second since last reload
- local timeDiff = ngx.now() - startTime
- if(redisUpdated == true and timeDiff >= 1) then
- os.execute("/usr/local/sbin/nginx -s reload")
- logger.info("Nginx reloaded.")
- redisUpdated = false
- startTime = ngx.now()
- end
end
end
--- Get gateway sync status
function _M.healthCheck()
- if getSyncStatus() == true then
- request.success(503, "Status: Gateway syncing.")
+ if gatewayReady == false then
+ request.success(503, "Status: Gateway starting up.")
else
request.success(200, "Status: Gateway ready.")
end
diff --git a/api-gateway-config/scripts/lua/routing.lua b/api-gateway-config/scripts/lua/routing.lua
index d1b45ec..ab62bb7 100644
--- a/api-gateway-config/scripts/lua/routing.lua
+++ b/api-gateway-config/scripts/lua/routing.lua
@@ -22,27 +22,31 @@
-- Used to dynamically handle nginx routing based on an object containing implementation details
-- @author Cody Walker (cmwalker), Alex Song (songs)
-
+local cjson = require "cjson"
local utils = require "lib/utils"
local request = require "lib/request"
+local redis = require "lib/redis"
local url = require "url"
-- load policies
local security = require "policies/security"
local mapping = require "policies/mapping"
local rateLimit = require "policies/rateLimit"
+local REDIS_HOST = os.getenv("REDIS_HOST")
+local REDIS_PORT = os.getenv("REDIS_PORT")
+local REDIS_PASS = os.getenv("REDIS_PASS")
+
local _M = {}
--- Main function that handles parsing of invocation details and carries out implementation
--- @param obj Lua table object containing implementation details for the given resource
--- {
--- {{GatewayMethod (GET / PUT / POST / DELETE)}} = {
--- "backendMethod": (GET / PUT / POST / DELETE) - Method to use for invocation (if different from gatewayMethod),
--- "backendUrl": STRING - fully composed url of backend invocation,
--- "policies": LIST - list of table objects containing type and value fields
--- }, ...
--- }
-function processCall(obj)
+function processCall()
+ -- Handle path parameters
+ ngx.var.gatewayPath = ngx.unescape_uri(ngx.var.gatewayPath):gsub("%{(%w*)%}", utils.convertTemplatedPathParam)
+ -- Get resource object from redis
+ local red = redis.init(REDIS_HOST, REDIS_PORT, REDIS_PASS, 10000)
+ local redisKey = utils.concatStrings({"resources:", ngx.var.tenant, ":", ngx.var.gatewayPath})
+ local obj = redis.getResource(red, redisKey, "resources")
+ obj = cjson.decode(obj)
local found = false
for verb, opFields in pairs(obj.operations) do
if string.upper(verb) == ngx.req.get_method() then
diff --git a/init.sh b/init.sh
index e32c38f..aa7269f 100755
--- a/init.sh
+++ b/init.sh
@@ -55,7 +55,6 @@
sleep 1 # sleep until api-gateway is set up
tail -f /var/log/api-gateway/access.log -f /var/log/api-gateway/error.log \
-f /var/log/api-gateway/gateway_error.log -f /var/log/api-gateway/management.log &
- curl -s http://0.0.0.0:9000/v1/sync & # sync with redis
curl -s http://0.0.0.0:9000/v1/subscribe # subscribe to redis key changes for routes
else
echo "REDIS_HOST and/or REDIS_PORT not defined"