Refactor management interface
diff --git a/api-gateway-config/conf.d/management_apis.conf b/api-gateway-config/conf.d/management_apis.conf
index 3561720..5a806d7 100644
--- a/api-gateway-config/conf.d/management_apis.conf
+++ b/api-gateway-config/conf.d/management_apis.conf
@@ -33,78 +33,27 @@
access_log /var/log/api-gateway/access.log platform;
error_log /var/log/api-gateway/management.log debug;
- location /v1/apis {
+ location ~ /v1/apis/?(?<api_id>[^/]*)?/?(?<query>[^/]*)? {
access_by_lua_block {
local apis = require("management/apis")
- local requestMethod = ngx.req.get_method()
- if requestMethod == "GET" then
- apis.getAPIs()
- elseif requestMethod == "PUT" then
- apis.addAPI()
- elseif requestMethod == "POST" then
- apis.addAPI()
- elseif requestMethod == "DELETE" then
- apis.deleteAPI()
- else
- ngx.status = 400
- ngx.say("Invalid verb")
- end
+ apis.requestHandler()
}
}
- location /v1/tenants {
+ location ~ /v1/tenants/?(?<tenant_id>[^/]*)?/?(?<query>[^/]*)? {
access_by_lua_block {
local tenants = require("management/tenants")
- local requestMethod = ngx.req.get_method()
- if requestMethod == "GET" then
- tenants.getTenants()
- elseif requestMethod == "PUT" then
- tenants.addTenant()
- elseif requestMethod == "POST" then
- tenants.addTenant()
- elseif requestMethod == "DELETE" then
- tenants.deleteTenant()
- else
- ngx.status = 400
- ngx.say("Invalid verb")
- end
+ tenants.requestHandler()
}
}
location /v1/subscriptions {
access_by_lua_block {
local subscriptions = require("management/subscriptions")
- local requestMethod = ngx.req.get_method()
- if requestMethod == "PUT" then
- subscriptions.addSubscription()
- elseif requestMethod == "DELETE" then
- subscriptions.deleteSubscription()
- else
- ngx.status = 400
- ngx.say("Invalid verb")
- end
+ subscriptions.requestHandler()
}
}
- location /v1/subscribe {
- access_by_lua_block {
- local requestMethod = ngx.req.get_method()
- if requestMethod == "GET" then
- local redis = require "lib/redis"
- local logger = require "lib/logger"
- local utils = require "lib/utils"
- local REDIS_HOST = os.getenv("REDIS_HOST")
- local REDIS_PORT = os.getenv("REDIS_PORT")
- local REDIS_PASS = os.getenv("REDIS_PASS")
- redis.init(REDIS_HOST, REDIS_PORT, REDIS_PASS)
- logger.info(utils.concatStrings({"Connected to redis at ", REDIS_HOST, ":", REDIS_PORT}))
- while true do end
- else
- ngx.say("Invalid verb")
- end
- }
- }
-
location /v1/health-check {
access_by_lua_block {
local requestMethod = ngx.req.get_method()
diff --git a/api-gateway-config/scripts/lua/lib/utils.lua b/api-gateway-config/scripts/lua/lib/utils.lua
index 0db0201..2a99642 100644
--- a/api-gateway-config/scripts/lua/lib/utils.lua
+++ b/api-gateway-config/scripts/lua/lib/utils.lua
@@ -95,5 +95,17 @@
return false
end
+--- Check if all required fields exist in the table
+-- @param table table to check
+-- @param requiredFields list of required fields
+function _Utils.tableContainsAll(table, requiredFields)
+ for i, field in ipairs(requiredFields) do
+ if not table[field] then
+ return false, { statusCode = 400, message = _Utils.concatStrings({"\"", field, "\" missing from request body."}) }
+ end
+ end
+ return true
+end
+
return _Utils
diff --git a/api-gateway-config/scripts/lua/management/apis.lua b/api-gateway-config/scripts/lua/management/apis.lua
index 7144ac0..bbc12af 100644
--- a/api-gateway-config/scripts/lua/management/apis.lua
+++ b/api-gateway-config/scripts/lua/management/apis.lua
@@ -37,6 +37,23 @@
local _M = {}
+--- Request handler for routing API calls appropriately
+function _M.requestHandler()
+ local requestMethod = ngx.req.get_method()
+ if requestMethod == "GET" then
+ getAPIs()
+ elseif requestMethod == "PUT" then
+ addAPI()
+ elseif requestMethod == "POST" then
+ addAPI()
+ elseif requestMethod == "DELETE" then
+ deleteAPI()
+ else
+ ngx.status = 400
+ ngx.say("Invalid verb")
+ end
+end
+
--- Add an api to the Gateway
-- PUT /v1/apis
-- body:
@@ -46,12 +63,11 @@
-- "tenantId": *(String) tenant id
-- "resources": *(String) resources to add
-- }
-function _M.addAPI()
+function addAPI()
-- Open connection to redis or use one from connection pool
local red = redis.init(REDIS_HOST, REDIS_PORT, REDIS_PASS, 10000)
-- Check for api id from uri and use existingAPI if it already exists in redis
- local uri = string.gsub(ngx.var.request_uri, "?.*", "")
- local existingAPI = checkURIForExistingAPI(red, uri)
+ local existingAPI = checkForExistingAPI(red)
-- Read in the PUT JSON Body
ngx.req.read_body()
local args = ngx.req.get_body_data()
@@ -108,19 +124,11 @@
--- Check for api id from uri and use existing API if it already exists in redis
-- @param red Redis client instance
--- @param uri Uri of request. Eg. /v1/apis/{id}
-function checkURIForExistingAPI(red, uri)
- local id, existing
- local index = 1
- -- Check if id is in the uri
- for word in string.gmatch(uri, '([^/]+)') do
- if index == 3 then
- id = word
- end
- index = index + 1
- end
+function checkForExistingAPI(red)
+ local id = ngx.var.api_id
+ local existing
-- Get object from redis
- if id ~= nil then
+ if id ~= nil and id ~= '' then
existing = redis.getAPI(red, id)
if existing == nil then
request.err(404, utils.concatStrings({"Unknown API id ", id}))
@@ -243,31 +251,21 @@
--- Get one or all APIs from the gateway
-- GET /v1/apis
-function _M.getAPIs()
- local uri = string.gsub(ngx.var.request_uri, "?.*", "")
+function getAPIs()
local queryParams = ngx.req.get_uri_args()
- local id
- local index = 1
- local tenantQuery = false
- for word in string.gmatch(uri, '([^/]+)') do
- if index == 3 then
- id = word
- elseif index == 4 then
- if word == 'tenant' then
- tenantQuery = true
- else
- request.err(400, "Invalid request")
- end
- end
- index = index + 1
- end
- if id == nil then
+ local id = ngx.var.api_id
+ if id == nil or id == '' then
getAllAPIs(queryParams)
else
- if tenantQuery == false then
- getAPI(id)
+ local query = ngx.var.query
+ if (query ~= nil and query ~= '') then
+ if query ~= "tenant" then
+ request.err(400, "Invalid request")
+ else
+ getAPITenant(id)
+ end
else
- getAPITenant(id)
+ getAPI(id)
end
end
end
@@ -311,9 +309,9 @@
if k%2 == 0 then
local api = cjson.decode(v)
if (basePath ~= nil and name == nil and api.basePath == basePath) or
- (name ~= nil and basePath == nil and api.name == name) or
- (basePath ~= nil and name ~= nil and api.basePath == basePath and api.name == name) then
- apiList[#apiList+1] = api
+ (name ~= nil and basePath == nil and api.name == name) or
+ (basePath ~= nil and name ~= nil and api.basePath == basePath and api.name == name) then
+ apiList[#apiList+1] = api
end
end
end
@@ -353,17 +351,9 @@
--- Delete API from gateway
-- DELETE /v1/apis/<id>
-function _M.deleteAPI()
- local uri = string.gsub(ngx.var.request_uri, "?.*", "")
- local index = 1
- local id
- for word in string.gmatch(uri, '([^/]+)') do
- if index == 3 then
- id = word
- end
- index = index + 1
- end
- if id == nil then
+function deleteAPI()
+ local id = ngx.var.api_id
+ if id == nil or id == '' then
request.err(400, "No id specified.")
end
local red = redis.init(REDIS_HOST, REDIS_PORT, REDIS_PASS, 10000)
diff --git a/api-gateway-config/scripts/lua/management/resources.lua b/api-gateway-config/scripts/lua/management/resources.lua
index 6ec4095..9df4e41 100644
--- a/api-gateway-config/scripts/lua/management/resources.lua
+++ b/api-gateway-config/scripts/lua/management/resources.lua
@@ -36,14 +36,8 @@
-- Create resource object and add to redis
local redisKey = utils.concatStrings({"resources", ":", tenantId, ":", gatewayPath})
local apiId
- local operations
- for k, v in pairs(resource) do
- if k == 'apiId' then
- apiId = v
- elseif k == 'operations' then
- operations = v
- end
- end
+ local operations = resource.operations
+ local apiId = resource.apiId
local resourceObj = redis.generateResourceObj(operations, apiId)
redis.createResource(red, redisKey, REDIS_FIELD, resourceObj)
end
diff --git a/api-gateway-config/scripts/lua/management/subscriptions.lua b/api-gateway-config/scripts/lua/management/subscriptions.lua
index e87af10..6193272 100644
--- a/api-gateway-config/scripts/lua/management/subscriptions.lua
+++ b/api-gateway-config/scripts/lua/management/subscriptions.lua
@@ -32,6 +32,19 @@
local _M = {}
+--- Request handler for routing API calls appropriately
+function _M.requestHandler()
+ local requestMethod = ngx.req.get_method()
+ if requestMethod == "PUT" then
+ addSubscription()
+ elseif requestMethod == "DELETE" then
+ deleteSubscription()
+ else
+ ngx.status = 400
+ ngx.say("Invalid verb")
+ end
+end
+
--- Add an apikey/subscription to redis
-- PUT /v1/subscriptions
-- Body:
@@ -42,7 +55,7 @@
-- resource: (String) url-encoded resource path
-- apiId: (String) api id
-- }
-function _M.addSubscription()
+function addSubscription()
-- Validate body and create redisKey
local redisKey = validateSubscriptionBody()
-- Open connection to redis or use one from connection pool
@@ -63,7 +76,7 @@
-- resource: (String) url-encoded resource path
-- apiId: (String) api id
-- }
-function _M.deleteSubscription()
+function deleteSubscription()
-- Validate body and create redisKey
local redisKey = validateSubscriptionBody()
-- Initialize and connect to redis
@@ -87,11 +100,9 @@
-- Convert json into Lua table
local decoded = cjson.decode(args)
-- Check required fields
- local requiredFieldList = {"key", "scope", "tenantId"}
- for i, field in ipairs(requiredFieldList) do
- if not decoded[field] then
- request.err(400, utils.concatStrings({"\"", field, "\" missing from request body."}))
- end
+ local res, err = utils.tableContainsAll(decoded, {"key", "scope", "tenantId"})
+ if res == false then
+ request.err(err.statusCode, err.message)
end
-- Check if we're using tenant or resource or api
local resource = decoded.resource
diff --git a/api-gateway-config/scripts/lua/management/tenants.lua b/api-gateway-config/scripts/lua/management/tenants.lua
index f2f798d..a173e12 100644
--- a/api-gateway-config/scripts/lua/management/tenants.lua
+++ b/api-gateway-config/scripts/lua/management/tenants.lua
@@ -31,6 +31,23 @@
local _M = {};
+--- Request handler for routing tenant calls appropriately
+function _M.requestHandler()
+ local requestMethod = ngx.req.get_method()
+ if requestMethod == "GET" then
+ getTenants()
+ elseif requestMethod == "PUT" then
+ addTenant()
+ elseif requestMethod == "POST" then
+ addTenant()
+ elseif requestMethod == "DELETE" then
+ deleteTenant()
+ else
+ ngx.status = 400
+ ngx.say("Invalid verb")
+ end
+end
+
--- Add a tenant to the Gateway
-- PUT /v1/tenants
-- body:
@@ -38,12 +55,11 @@
-- "namespace": *(String) tenant namespace
-- "instance": *(String) tenant instance
-- }
-function _M.addTenant()
+function addTenant()
-- Open connection to redis or use one from connection pool
local red = redis.init(REDIS_HOST, REDIS_PORT, REDIS_PASS, 10000)
-- Check for tenant id and use existingTenant if it already exists in redis
- local uri = string.gsub(ngx.var.request_uri, "?.*", "")
- local existingTenant = checkURIForExistingTenant(red, uri)
+ local existingTenant = checkForExistingTenant(red)
-- Read in the PUT JSON Body
ngx.req.read_body()
local args = ngx.req.get_body_data()
@@ -60,11 +76,9 @@
end
end
-- Error checking
- local fields = {"namespace", "instance"}
- for k, v in pairs(fields) do
- if not decoded[v] then
- request.err(400, utils.concatStrings({"Missing field '", v, "' in request body."}))
- end
+ local res, err = utils.tableContainsAll(decoded, {"namespace", "instance"})
+ if res == false then
+ request.err(err.statusCode, err.message)
end
-- Return tenant object
local uuid = existingTenant ~= nil and existingTenant.id or utils.uuid()
@@ -81,19 +95,11 @@
--- Check for tenant id from uri and use existing tenant if it already exists in redis
-- @param red Redis client instance
--- @param uri Uri of request. Eg. /v1/tenants/{id}
-function checkURIForExistingTenant(red, uri)
- local id, existing
- local index = 1
- -- Check if id is in the uri
- for word in string.gmatch(uri, '([^/]+)') do
- if index == 3 then
- id = word
- end
- index = index + 1
- end
+function checkForExistingTenant(red)
+ local id = ngx.var.tenant_id
+ local existing
-- Get object from redis
- if id ~= nil then
+ if id ~= nil and id ~= '' then
existing = redis.getTenant(red, id)
if existing == nil then
request.err(404, utils.concatStrings({"Unknown Tenant id ", id}))
@@ -104,31 +110,21 @@
--- Get one or all tenants from the gateway
-- GET /v1/tenants
-function _M.getTenants()
- local uri = string.gsub(ngx.var.request_uri, "?.*", "")
+function getTenants()
local queryParams = ngx.req.get_uri_args()
- local id
- local index = 1
- local apiQuery = false
- for word in string.gmatch(uri, '([^/]+)') do
- if index == 3 then
- id = word
- elseif index == 4 then
- if word:lower() == 'apis' then
- apiQuery = true
- else
- request.err(400, "Invalid request")
- end
- end
- index = index + 1
- end
- if id == nil then
+ local id = ngx.var.tenant_id
+ if id == nil or id == '' then
getAllTenants(queryParams)
else
- if apiQuery == false then
- getTenant(id)
+ local query = ngx.var.query
+ if (query ~= nil and query ~= '') then
+ if query ~= "apis" then
+ request.err(400, "Invalid request")
+ else
+ getTenantAPIs(id, queryParams)
+ end
else
- getTenantAPIs(id, queryParams)
+ getTenant(id)
end
end
end
@@ -172,7 +168,7 @@
if k%2 == 0 then
local tenant = cjson.decode(v)
if (namespace ~= nil and instance == nil and tenant.namespace == namespace) or
- (namespace ~= nil and instance ~= nil and tenant.namespace == namespace and tenant.instance == instance) then
+ (namespace ~= nil and instance ~= nil and tenant.namespace == namespace and tenant.instance == instance) then
tenantList[#tenantList+1] = tenant
end
end
@@ -235,10 +231,10 @@
if k%2 == 0 then
local api = cjson.decode(v)
if api.tenantId == id and
- ((basePath ~= nil and name == nil and api.basePath == basePath) or
- (name ~= nil and basePath == nil and api.name == name) or
- (basePath ~= nil and name ~= nil and api.basePath == basePath and api.name == name)) then
- apiList[#apiList+1] = api
+ ((basePath ~= nil and name == nil and api.basePath == basePath) or
+ (name ~= nil and basePath == nil and api.name == name) or
+ (basePath ~= nil and name ~= nil and api.basePath == basePath and api.name == name)) then
+ apiList[#apiList+1] = api
end
end
end
@@ -247,20 +243,16 @@
--- Delete tenant from gateway
-- DELETE /v1/tenants/<id>
-function _M.deleteTenant()
- local uri = string.gsub(ngx.var.request_uri, "?.*", "")
- local index = 1
- local id
- for word in string.gmatch(uri, '([^/]+)') do
- if index == 3 then
- id = word
- end
- index = index + 1
- end
- if id == nil then
+function deleteTenant()
+ local id = ngx.var.tenant_id
+ if id == nil or id == '' then
request.err(400, "No id specified.")
end
- local red = redis.init(REDIS_HOST, REDIS_PORT, REDIS_PASS, 1000)
+ local red = redis.init(REDIS_HOST, REDIS_PORT, REDIS_PASS, 10000)
+ local tenant = redis.getTenant(red, id)
+ if tenant == nil then
+ request.err(404, utils.concatStrings({"Unknown tenant id ", id}))
+ end
redis.deleteTenant(red, id)
redis.close(red)
request.success(200, {})