mdeuser commented on a change in pull request #2966: WIP: Path parameter
support for API GW
URL:
https://github.com/apache/incubator-openwhisk/pull/2966#discussion_r156205446
##########
File path: core/routemgmt/common/apigw-utils.js
##########
@@ -24,6 +24,177 @@ var _ = require('lodash');
const ApimgmtUserAgent = "OpenWhisk-apimgmt/1.0.0";
var UserAgent = ApimgmtUserAgent;
+/**
+ * Helper method for the validateFinalSwagger function. Generates a map of
operationId to target-url strings so we
+ * can validate that each operationId we find that has a parameter in the path
also has its target-url appended with
+ * $(request.path)
+ *
+ * @param ibmConfig Required. The 'x-ibm-configuration' portion of the
swaggerApi.
+ * @return A map of operationId->target-url pairs for checking.
+ */
+function generateTargetUrlMap(ibmConfig) {
+ var targetUrls = {};
+ ibmConfig['assembly']['execute'].forEach(function(exec) {
+ if (exec['operation-switch'] && exec['operation-switch']['case']) {
+ exec['operation-switch']['case'].forEach(function(element) {
+ var operations = element['operations'];
+ var isOperationWereLookingFor = false;
+ var ops = [];
+ if (operations) {
+ operations.forEach(function(op){
+ ops.push(op);
+ });
+ }
+ ops.forEach(function(op){
+ element['execute'].forEach(function(exec) {
+ targetUrls[op] = exec['invoke']['target-url'];
+ });
+ });
+ });
+ }
+
+ });
+ return targetUrls;
+}
+
+/**
+ * Helper function that just validates whether a relative path meets the
following conditions:
+ * 1. It has not path parameters
+ * 2. If it has path parameters, that the parameters are well formed (i.e.
each param is surrounded by {}).
+ *
+ * @param relativePath Required. The relative path we are checking.
+ * @return True if the path is valid, false otherwise.
+ */
+function isValidRelativePath(relativePath) {
+ if (isParameterizedPath(relativePath)) {
+ var open = relativePath.indexOf('{', 0);
+ var close = relativePath.indexOf('}', open);
+ while (open != -1 || close != -1) {
+ if (open == -1 || close == -1) {
+ //Could not find a matching close brace
+ return false;
+ }
+ open = relativePath.indexOf('{', close);
+ close = open == -1 ? relativePath.indexOf('}', close + 1) :
relativePath.indexOf('}', open);
+ }
+ }
+ return true;
+}
+
+/**
+ * Simple function to get the name of each path parameter defined in the path.
+ *
+ * @param path Required. The path we are checking.
+ * @return An array that contains each named path parameter, or an empty list
if none are found.
+ */
+function getPathParameters(relativePath) {
+ var params = [];
+ var validNameRegex = /\{([^\/]+)\}/g
+ //Match returns all the matches found, including the {} chars. so we have
to remove them.
+ var namesFound = relativePath.match(validNameRegex);
+ if (namesFound) {
+ params = namesFound.map(function (pathName){
+ return pathName.substring(1,pathName.length-1);
+ });
+ }
+ return params;
+}
+
+/**
+ * Simple function to determine whether this path contains parameters
+ *
+ * @param path Required. The path we are checking.
+ * @return True if the path contains parameters, false otherwise.
+ */
+function isParameterizedPath(path) {
+ return path != null && ((path.indexOf('{') != -1) || path.indexOf('}') >= 0);
+}
+
+/**
+ * Currently this only checks the final swagger that will be passed into API
GW whether the path parameter definition
+ * is correct.
+ *
+ * @param swaggerApi Required. The API swagger object to send to the API
gateway
+ * @return A promise with the fully validated swaggerApi, or an error response
if rejected.
+ */
+function validateFinalSwagger(swaggerApi) {
+ return new Promise(function(resolve, reject) {
+ // This returns a map of urls to check for path parameters.
+ console.log("validateFinalSwagger: Validating swapper before posting to
API GW.")
+ var errorMsg;
+ var paths = swaggerApi['paths'];
+
+ if (swaggerApi.basePath && isParameterizedPath(swaggerApi.basePath)) {
+ errorMsg = "The base path (" + swaggerApi.basePath + ") cannot have
parameters. Only the relative path supports path parameters.";
+ }
+ /*
+ * This code will look at each path defined, and look at all the
parameters in each path, and validate that each
+ * verb (GET,POST, etc) for each path defines parameter objects for each
parameter defined in the path. For each of
+ * these that contain parameters, it will also check that its target-url
ends in $(request.path).
+ * #beginPathValidation
+ */
+ var targetUrlMap = generateTargetUrlMap(swaggerApi['x-ibm-configuration']);
+ for (var key in paths) {
+ if (errorMsg) { break; }
+ var idx = 0;
+ if (isParameterizedPath(key)) {
+ if (!isValidRelativePath(key)) {
+ errorMsg = "Relative path '" + key + "' does not include valid path
parameters. "
+ errorMsg += "Each parameter must be enclosed in curly braces{}.";
+ break;
+ }
+ //Path is valid, lets check that we have parameters defined for each
path parameter and that the target-url
+ //has $(request.path) at the end.
+ var namedParamsInPath = getPathParameters(key);
+ //Loop over each verb (GET,POST,etc), each should contain path
parameters.
+ for (var httpType in paths[key]) {
+ var parameters = paths[key][httpType].parameters;
+ var opId = paths[key][httpType].operationId;
+ var xOpenWhisk = paths[key][httpType]['x-openwhisk']
+ //Look at all the parameters in each verb to ensure they match those
defined in the path.
+ if (namedParamsInPath == null || parameters == null ||
namedParamsInPath.length != parameters.length) {
Review comment:
```
if ((namedParamsInPath != null && parameters != null &&
namedParamsInPath.length != parameters.length) ||
(namedParamsInPath != null && parameters == null) ||
(namedParamsInPath == null && parameters != null))```
----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on GitHub and use the
URL above to go to the specific comment.
For queries about this service, please contact Infrastructure at:
[email protected]
With regards,
Apache Git Services