Beispiel #1
0
        public void IdentifyReachabilityPaths(ILinkAnalyzer linkAnalyzer)
        {
            //step 1: pre-allocate variable path segments
            PreAllocateAllPathSegmentsOnThePathFromThisToRoot();

            //step 2: identify one-to-pne reachability paths
            IList <ReachabilityPath> identifiedOneToOneReachabilityPaths = IdentifyOneToOneReachabilityPath();

            //step 3: identify one-to-many reachability paths
            IList <ReachabilityPath> identifiedOneToManyReachabilityPath = IdentifyOneToManyReachabilityPath(linkAnalyzer);

            //step 4: add all identified reachability paths
            foreach (ReachabilityPath reachabilityPath in identifiedOneToOneReachabilityPaths)
            {
                this.ReachabilityPaths.Add(reachabilityPath);
            }
            foreach (ReachabilityPath reachabilityPath in identifiedOneToManyReachabilityPath)
            {
                this.ReachabilityPaths.Add(reachabilityPath);
            }

            //step 5: reset pre-allocation
            this.Root.ResetAllocation();
        }
Beispiel #2
0
        public AnalysisResult AnalyzeSingleApi(string rawContent, string apiKey, string apiName, string versionKey, string versionName, string apiAdded, string versionAdded, ILinkAnalyzer linkAnalyzer)
        {
            OpenApiDiagnostic openApiDiagnostic = new OpenApiDiagnostic();
            OpenApiDocument   openApiDocument   = null;

            try
            {
                //step 1: convert OpenAPI documentation into object model
                openApiDocument = new OpenApiStringReader().Read(rawContent, out openApiDiagnostic);
            }
            catch (Exception e)
            {
                // possibly IO Exception or Exception due to mal-formed OpenAPI documentation
                return(AnalysisResult.Create(apiKey, apiName, versionKey, versionName, apiAdded, versionAdded, null, 0, 0, false, e));
            }

            //step 2: write diagnostic to log
            int openApiReaderErrors = 0;

            foreach (OpenApiError openApiError in openApiDiagnostic.Errors)
            {
                openApiReaderErrors++;
                //TODO: write to log
            }

            //step 3: create URI Model
            UriModel uriModel = null;

            try
            {
                uriModel = CustomizedUriModelFactory.Instance.Create(openApiDocument);
            }
            catch (Exception e)
            {
                return(AnalysisResult.Create(apiKey, apiName, versionKey, versionName, apiAdded, versionAdded, null, openApiReaderErrors, 0, false, e));
            }

            //step 4: check whether URI Model contains variable path segments that have more than one path parameter
            bool hasUriModelVariablePathSegmentsWithMoreThanOnePathParameter = HasUriModelVariablePathSegmentsWithMoreThanOnePathParameter(uriModel);

            if (hasUriModelVariablePathSegmentsWithMoreThanOnePathParameter)
            {
                return(AnalysisResult.Create(apiKey, apiName, versionKey, versionName, apiAdded, versionAdded, uriModel, openApiReaderErrors, 0, true, null));
            }

            //step 5: identify reachability paths
            int missingMediaCounter = 0;

            try
            {
                IList <PathSegment> pathSegmentsRepresentingResources = uriModel.Root.QuerySubTree.HasOperations().Results;
                for (int i = 0; i < pathSegmentsRepresentingResources.Count; i++)
                {
                    ((CustomizedPathSegment)pathSegmentsRepresentingResources[i]).IdentifyReachabilityPaths(linkAnalyzer);
                    Out.UpdateStatusBar(((double)i / (double)pathSegmentsRepresentingResources.Count) * 100);
                }

                missingMediaCounter = linkAnalyzer.MissingMediaCounter;
            }
            catch (Exception e)
            {
                //possibly Exception due to mal-formed OpenAPI documentation
                return(AnalysisResult.Create(apiKey, apiName, versionKey, versionName, apiAdded, versionAdded, uriModel, openApiReaderErrors, 0, hasUriModelVariablePathSegmentsWithMoreThanOnePathParameter, e));
            }

            return(AnalysisResult.Create(apiKey, apiName, versionKey, versionName, apiAdded, versionAdded, uriModel, openApiReaderErrors, missingMediaCounter, hasUriModelVariablePathSegmentsWithMoreThanOnePathParameter, null));
        }
Beispiel #3
0
        /// <summary>
        /// Identifies and returns the list of one-to-many <see cref="ReachabilityPath"/>s
        /// </summary>
        /// <returns></returns>
        private IList <ReachabilityPath> IdentifyOneToManyReachabilityPath(ILinkAnalyzer linkAnalyzer)
        {
            IList <ReachabilityPath> reachabilityPaths = new List <ReachabilityPath>();

            //step 1: load API Root
            PathSegment apiRoot = this.Root;

            //step 2: load all variable path segments of the URI Model (note that pre-allocated variable path segments are ignored)
            IList <PathSegment> variablePathSegments = apiRoot.QuerySubTree.IsVariable().Results;

            //step 3: prepare and identify list of variable path segments that are on the path between this path segment and the next descendants
            IList <PathSegment> variablePathSegmentsOnThePathBetweenThisPathSegmentAndNextDescendants = new List <PathSegment>();

            foreach (PathSegment variablePathSegment in variablePathSegments)
            {
                //calculate path between API Root and the respective variable path segment
                //Note that for our case it does not matter, whether calculating the path between this path segment and the variable path segment
                //or the API Root and the variable path segment, since between API root and this path segment cannot be any variable path segment
                Stack <Node <string> > path = apiRoot.Path(variablePathSegment);

                //in the course of the next step, we will count the number of variable path segments being on the path between the API Root (or this path segment) and the respective variable path segment.
                int variablePathSegmentCounter = 0;
                while (path.Count > 0)
                {
                    PathSegment pathSegment = (PathSegment)path.Pop();
                    if (pathSegment.IsVariable)
                    {
                        //increase counter for each found variable path segment
                        variablePathSegmentCounter++;
                    }
                }

                //if there is exactely one variable path segment (namely the variable path segment
                if (variablePathSegmentCounter == 1)
                {
                    variablePathSegmentsOnThePathBetweenThisPathSegmentAndNextDescendants.Add(variablePathSegment);
                }
            }

            //step 4: iterate over the list of identified variable path segments
            foreach (PathSegment variablePathSegment in variablePathSegmentsOnThePathBetweenThisPathSegmentAndNextDescendants)
            {
                IList <Link> links = new List <Link>();

                //iterate over all path parameters of the respective variable path segment
                foreach (PathParameter pathParameter in variablePathSegment.PathParameters)
                {
                    //analyze response payload schemas
                    IList <Link> linksToPathParameter = linkAnalyzer.AnalyzeResource(this, pathParameter);
                    foreach (Link linkToPathParameter in linksToPathParameter)
                    {
                        links.Add(linkToPathParameter);
                    }
                }

                //step 5: now we determine the target of the one-to-many reachability paths
                //if the respective variable path segment has operations (i.e. represents multiple resources)...
                if (variablePathSegment.HasOperations)
                {
                    //...then it is the target
                    ReachabilityPath reachabilityPath = new ReachabilityPath(this, variablePathSegment, ReachabilityPathType.oneToMany);
                    foreach (Link link in links)
                    {
                        reachabilityPath.Links.Add(link);
                        //activates the back reference (i.e. adds the link to the path parameter)
                        link.ActivateBackReferenceToPathParameter();
                    }
                    reachabilityPaths.Add(reachabilityPath);
                }
                //if the respective variable path segment HAS NOT any operation (i.e. DOES NOT represent multiple resources)
                else
                {
                    //...then whe have to identify the next descendants of this variable path segment and set them as targets
                    //Note that we want only next descendants that are NOT variable or whose path between the respective variable path segment and the next descendant
                    //is not blocked by a variable path segment, since on the path from the source to the target can only be one variable path segment
                    foreach (PathSegment nextDescendant in ((CustomizedPathSegment)variablePathSegment).NextDescendantsRepresentingResourcesButWithoutVariablePathSegments)
                    {
                        //...then the next descendant is one target
                        ReachabilityPath reachabilityPath = new ReachabilityPath(this, nextDescendant, ReachabilityPathType.oneToMany);
                        foreach (Link link in links)
                        {
                            reachabilityPath.Links.Add(link);
                            //activates the back reference (i.e. adds the link to the path parameter)
                            link.ActivateBackReferenceToPathParameter();
                        }
                        reachabilityPaths.Add(reachabilityPath);
                    }
                }
            }
            return(reachabilityPaths);
        }
        public static void Main(string[] args)
        {
            //step 1: load arguments
            CustomizedArguments arguments = CustomizedArguments.Parse(args);

            //step 2: load log writer
            if (arguments.Has(CustomizedArguments.ARG_LOG_OUT))
            {
                //console
                if (arguments.Get(CustomizedArguments.ARG_LOG_OUT).CompareTo(CustomizedArguments.OPT_LOG_OUT_CONSOLE) == 0)
                {
                    Log.LogWriters.Add(new CustomizedConsoleLogWriter()
                    {
                        LogLevel = arguments.LogLevel
                    });
                }
                //file
                else
                {
                    Log.LogWriters.Add(new FileLogWriter(arguments.LogPath + DateTime.Now.ToString(String.Format("yyyy-MM-dd_HH.mm.ss.FFF")) + ".log")
                    {
                        LogLevel = arguments.LogLevel
                    });
                }
                Log.Debug(TAG, "log_out:" + arguments.Get(CustomizedArguments.ARG_LOG_OUT));
            }
            //default (console)
            else
            {
                Log.LogWriters.Add(new CustomizedConsoleLogWriter()
                {
                    LogLevel = arguments.LogLevel
                });
            }

            //step 3: load OpenAPI documentation
            Log.Info(TAG, "Load OpenAPI documentation from '" + arguments.Get(CustomizedArguments.ARG_SOURCE) + "'");
            OpenApiDiagnostic openApiDiagnostic = new OpenApiDiagnostic();
            OpenApiDocument   openApiDocument   = new OpenApiStringReader().Read(File.ReadAllText(arguments.Get(CustomizedArguments.ARG_SOURCE)), out openApiDiagnostic);

            foreach (OpenApiError openApiError in openApiDiagnostic.Errors)
            {
                Log.Error(TAG, "OpenAPI Reader Error: " + openApiError.Message);
            }
            Log.Info(TAG, "Load OpenAPI documentation - completed\n");

            //step 4: create URI Model
            Log.Info(TAG, "Create URI Model:");
            UriModel uriModel = CustomizedUriModelFactory.Instance.Create(openApiDocument);

            Log.Info(TAG, "\n" + uriModel.ToString() + "\n");

            //step 5: identify reachability associations
            Log.Info(TAG, "Identify reachability associations:");
            ILinkAnalyzer       linkAnalyzer = LinkAnalyzerFactory.Create();
            IList <PathSegment> pathSegmentsRepresentingResources = uriModel.Root.QuerySubTree.HasOperations().Results;

            foreach (PathSegment pathSegmentRepresentingResources in pathSegmentsRepresentingResources)
            {
                ((CustomizedPathSegment)pathSegmentRepresentingResources).IdentifyReachabilityPaths(linkAnalyzer);
                Log.Info(TAG, pathSegmentRepresentingResources.UriPath);
                foreach (ReachabilityPath association in ((CustomizedPathSegment)pathSegmentRepresentingResources).ReachabilityPaths)
                {
                    Log.Info(TAG, association.ToString());
                }
            }

            //step 6: set base path
            string basePath = "";

            if (arguments.Has(CustomizedArguments.ARG_API_BASE_PATH))
            {
                basePath = arguments.Get(CustomizedArguments.ARG_API_BASE_PATH);
            }
            else
            {
                foreach (OpenApiServer openApiServer in openApiDocument.Servers)
                {
                    basePath = openApiServer.Url;
                }
            }
            Log.Info(TAG, "\nBase path of remote API: '" + basePath + "'");

            //step 7: load property name prefix of injected properties
            string propertyNamePrefix = "";

            if (arguments.Has(CustomizedArguments.ARG_INJECTION_PREFIX))
            {
                propertyNamePrefix = arguments.Get(CustomizedArguments.ARG_INJECTION_PREFIX);
            }

            //step 8: prepare proxy
            IProxyHandler handler = new CustomizedProxyHandler(basePath, uriModel, propertyNamePrefix, arguments.Has(CustomizedArguments.ARG_EXTENDED_HYPERLINK), arguments.Has(CustomizedArguments.ARG_PREFLIGHT_HEAD_COUNTER)?Int32.Parse(arguments.Get(CustomizedArguments.ARG_PREFLIGHT_HEAD_COUNTER)):10);

            ApiRequest.IgnoreBadCertificates();

            if (arguments.Has(CustomizedArguments.ARG_ACCESS_TOKEN))
            {
                handler.UpdateAcessTokenAutomatically = false;
                handler.UpdateAuthorization(arguments.Get(CustomizedArguments.ARG_ACCESS_TOKEN));
                Log.Info(TAG, "Access token has been loaded from arguments and will be injected into API requests automatically");
            }
            else
            {
                handler.UpdateAcessTokenAutomatically = true;
                Log.Warning(TAG, "Access token is not specified in arguments. If the API expects an access token, make sure that the client specifies this token in each request.");
            }

            HttpController controller = new ProxyController(handler);

            //step 9: start proxy
            HttpService service = new DefaultHttpSysService(false, "+", Int32.Parse(arguments.Get(CustomizedArguments.ARG_PORT)));

            service.AddController(controller);

            Log.Info(TAG, "Proxy routes:");
            Log.Info(TAG, service.Routes);
            service.Start();
            Log.Info(TAG, "Proxy is listening on port '" + arguments.Get(CustomizedArguments.ARG_PORT) + "'");

            Console.WriteLine("PRESS KEY TO TERMINATE SERVICE");
            Console.ReadKey();
        }