Ejemplo n.º 1
0
        public OpenApiOutputModel Compile(OpenApiConfiguration configuration, IReadOnlyCollection <AbstractFunctionDefinition> abstractFunctionDefinitions, string outputBinaryFolder)
        {
            if (configuration == null)
            {
                return(null);
            }

            string apiPrefix = GetApiPrefix(outputBinaryFolder);

            if (!configuration.IsValid)
            {
                throw new ConfigurationException("Open API implementation is partially complete, a title and a version must be specified");
            }
            if (!configuration.IsOpenApiOutputEnabled)
            {
                return(null);
            }

            HttpFunctionDefinition[] functionDefinitions = abstractFunctionDefinitions.OfType <HttpFunctionDefinition>().ToArray();
            if (functionDefinitions.Length == 0)
            {
                return(null);
            }

            OpenApiDocument openApiDocument = new OpenApiDocument
            {
                Info = new OpenApiInfo
                {
                    Version = configuration.Version,
                    Title   = configuration.Title
                },
                Servers = configuration.Servers?.Select(x => new OpenApiServer {
                    Url = x
                }).ToArray(),
                Paths      = new OpenApiPaths(),
                Components = new OpenApiComponents
                {
                    Schemas = new Dictionary <string, OpenApiSchema>()
                }
            };

            var compilerConfiguration = new OpenApiCompilerConfiguration(configuration);

            SchemaReferenceRegistry registry = new SchemaReferenceRegistry(compilerConfiguration);

            CreateTags(functionDefinitions, openApiDocument);

            CreateSchemas(functionDefinitions, openApiDocument, registry);

            CreateOperationsFromRoutes(functionDefinitions, openApiDocument, registry, apiPrefix, compilerConfiguration);

            FilterDocument(compilerConfiguration, openApiDocument);

            if (openApiDocument.Paths.Count == 0)
            {
                return(null);
            }

            string             yaml   = openApiDocument.Serialize(OpenApiSpecVersion.OpenApi3_0, OpenApiFormat.Yaml);
            OpenApiOutputModel result = new OpenApiOutputModel
            {
                OpenApiSpecification = new OpenApiFileReference
                {
                    Content  = yaml,
                    Filename = "openapi.yaml"
                }
            };

            if (!string.IsNullOrWhiteSpace(configuration.UserInterfaceRoute))
            {
                result.SwaggerUserInterface = CopySwaggerUserInterfaceFilesToWebFolder();
            }

            if (!string.IsNullOrWhiteSpace(configuration.OutputPath))
            {
                if (Directory.Exists(configuration.OutputPath))
                {
                    string pathAndFilename = Path.Combine(configuration.OutputPath, "openapi.yaml");
                    if (File.Exists(pathAndFilename))
                    {
                        File.Delete(pathAndFilename);
                    }
                    File.WriteAllText(pathAndFilename, yaml, Encoding.UTF8);
                }
            }

            return(result);
        }
Ejemplo n.º 2
0
        public OpenApiOutputModel Compile(OpenApiConfiguration configuration, IReadOnlyCollection <AbstractFunctionDefinition> abstractFunctionDefinitions, string outputBinaryFolder)
        {
            if (configuration == null)
            {
                return(null);
            }

            string apiPrefix = GetApiPrefix(outputBinaryFolder);

            if (!configuration.IsValid)
            {
                throw new ConfigurationException("Open API implementation is partially complete, a title and a version must be specified");
            }
            if (!configuration.IsOpenApiOutputEnabled)
            {
                return(null);
            }

            var functionDefinitions = abstractFunctionDefinitions.OfType <HttpFunctionDefinition>().ToList();

            if (functionDefinitions.Count() == 0)
            {
                return(null);
            }

            IDictionary <string, OpenApiDocumentsSpec> openApiDocumentsSpec = new Dictionary <string, OpenApiDocumentsSpec>();
            IDictionary <string, OpenApiDocumentsSpec> reDocDocumentsSpec   = new Dictionary <string, OpenApiDocumentsSpec>();
            OpenApiOutputModel outputModel = new OpenApiOutputModel();

            foreach (var keyValuePair in configuration.OpenApiDocumentInfos)
            {
                OpenApiDocument openApiDocument = new OpenApiDocument
                {
                    Info    = keyValuePair.Value.OpenApiInfo,
                    Servers = configuration.Servers?.Select(x => new OpenApiServer {
                        Url = x
                    }).ToArray(),
                    Paths      = new OpenApiPaths(),
                    Components = new OpenApiComponents
                    {
                        Schemas = new Dictionary <string, OpenApiSchema>(),
                    }
                };

                var functionFilter = keyValuePair.Value.HttpFunctionFilter;
                if (functionFilter == null)
                {
                    functionFilter = new OpenApiHttpFunctionFilterDummy();
                }

                var compilerConfiguration = new OpenApiCompilerConfiguration(configuration);

                SchemaReferenceRegistry registry = new SchemaReferenceRegistry(compilerConfiguration);

                CreateTags(functionDefinitions, functionFilter, openApiDocument);

                CreateSchemas(functionDefinitions, functionFilter, openApiDocument, registry);

                CreateOperationsFromRoutes(functionDefinitions, functionFilter, openApiDocument, registry, apiPrefix, compilerConfiguration);

                CreateSecuritySchemes(openApiDocument, configuration);

                FilterDocument(compilerConfiguration.DocumentFilters, openApiDocument, keyValuePair.Value.DocumentRoute);

                if (openApiDocument.Paths.Count == 0)
                {
                    continue;
                }

                // TODO: FIXME:
                // Hack: Empty OpenApiSecurityRequirement lists are not serialized by the standard Microsoft
                // implementation. Therefore we add a null object to the list and fix it here by hand.
                var yaml = openApiDocument.Serialize(OpenApiSpecVersion.OpenApi3_0, OpenApiFormat.Yaml);
                yaml = Regex.Replace(yaml, $"security:\n.*?- \n", "security: []\n");

                outputModel.OpenApiFileReferences.Add(
                    new OpenApiFileReference
                {
                    Filename = $"OpenApi.{keyValuePair.Value.DocumentRoute.Replace('/', '.')}",
                    Content  = Encoding.UTF8.GetBytes(yaml)
                }
                    );

                openApiDocumentsSpec.Add(openApiDocument.Info.Title, new OpenApiDocumentsSpec
                {
                    Title    = keyValuePair.Value.OpenApiInfo.Title,
                    Selected = keyValuePair.Value.Selected,
                    Path     = $"/{configuration.UserInterfaceRoute ?? "openapi"}/{keyValuePair.Value.DocumentRoute}"
                });

                // Create reDoc YAML
                if (!string.IsNullOrWhiteSpace(configuration.ReDocUserInterfaceRoute))
                {
                    FilterDocument(compilerConfiguration.ReDocDocumentFilters, openApiDocument, keyValuePair.Value.DocumentRoute);

                    // TODO: FIXME:
                    // Hack: Empty OpenApiSecurityRequirement lists are not serialized by the standard Microsoft
                    // implementation. Therefore we add a null object to the list and fix it here by hand.
                    var reDocYaml = openApiDocument.Serialize(OpenApiSpecVersion.OpenApi3_0, OpenApiFormat.Yaml);
                    reDocYaml = Regex.Replace(reDocYaml, $"security:\n.*?- \n", "security: []\n");

                    outputModel.OpenApiFileReferences.Add(
                        new OpenApiFileReference
                    {
                        Filename = $"ReDoc.{keyValuePair.Value.DocumentRoute.Replace('/', '.')}",
                        Content  = Encoding.UTF8.GetBytes(reDocYaml)
                    }
                        );

                    reDocDocumentsSpec.Add(openApiDocument.Info.Title, new OpenApiDocumentsSpec
                    {
                        Title    = keyValuePair.Value.OpenApiInfo.Title,
                        Selected = keyValuePair.Value.Selected,
                        Path     = $"/{configuration.ReDocUserInterfaceRoute ?? "redoc"}/{keyValuePair.Value.DocumentRoute}"
                    });
                }
            }

            if (!string.IsNullOrWhiteSpace(configuration.UserInterfaceRoute))
            {
                outputModel.OpenApiFileReferences.Add(
                    new OpenApiFileReference
                {
                    Filename = "OpenApi.openapi-documents-spec.json",
                    Content  = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(openApiDocumentsSpec.Values.ToArray()))
                }
                    );

                CopySwaggerUserInterfaceFilesToWebFolder(configuration, outputModel.OpenApiFileReferences);
            }

            if (!string.IsNullOrWhiteSpace(configuration.ReDocUserInterfaceRoute))
            {
                outputModel.OpenApiFileReferences.Add(
                    new OpenApiFileReference
                {
                    Filename = "ReDoc.redoc-documents-spec.json",
                    Content  = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(reDocDocumentsSpec.Values.ToArray()))
                }
                    );

                CopyReDocUserInterfaceFilesToWebFolder(configuration, outputModel.OpenApiFileReferences);
            }

            outputModel.UserInterfaceRoute      = configuration.UserInterfaceRoute;
            outputModel.ReDocUserInterfaceRoute = configuration.ReDocUserInterfaceRoute;
            return(outputModel);
        }