using System; using System.Collections.Generic; using System.Globalization; using System.Linq; using System.Net.Http; using System.Web.Http; using System.Web.Http.Description; using System.Xml.XPath; using Newtonsoft.Json; using Swashbuckle.Swagger; using Swashbuckle.Swagger.Annotations; using Swashbuckle.Swagger.FromUriParams; using Swashbuckle.Swagger.XmlComments; namespace Swashbuckle.Application { public class SwaggerDocsConfig { private VersionInfoBuilder _versionInfoBuilder; private Func _versionSupportResolver; private IEnumerable _schemes; private IDictionary _securitySchemeBuilders; private bool _prettyPrint; private bool _ignoreObsoleteActions; private Func _groupingKeySelector; private IComparer _groupingKeyComparer; private readonly IDictionary> _customSchemaMappings; private readonly IList> _schemaFilters; private readonly IList> _modelFilters; private Func _schemaIdSelector; private bool _ignoreObsoleteProperties; private bool _describeAllEnumsAsStrings; private bool _describeStringEnumsInCamelCase; private bool _applyFiltersToAllSchemas; private readonly IList> _operationFilters; private readonly IList> _documentFilters; private readonly IList> _xmlDocFactories; private Func, ApiDescription> _conflictingActionsResolver; private Func _rootUrlResolver; private Func _customProviderFactory; /// /// 是否显示开发者信息 /// internal static bool ShowDeveloper = false; public SwaggerDocsConfig() { _versionInfoBuilder = new VersionInfoBuilder(); _securitySchemeBuilders = new Dictionary(); _prettyPrint = false; _ignoreObsoleteActions = false; _customSchemaMappings = new Dictionary>(); _schemaFilters = new List>(); _modelFilters = new List>(); _ignoreObsoleteProperties = false; _describeAllEnumsAsStrings = false; _describeStringEnumsInCamelCase = false; _applyFiltersToAllSchemas = false; _operationFilters = new List>(); _documentFilters = new List>(); _xmlDocFactories = new List>(); _rootUrlResolver = DefaultRootUrlResolver; SchemaFilter(); OperationFilter(); OperationFilter(); OperationFilter(); OperationFilter(); } public InfoBuilder SingleApiVersion(string version, string title) { _versionSupportResolver = null; _versionInfoBuilder = new VersionInfoBuilder(); return _versionInfoBuilder.Version(version, title, true); } public void MultipleApiVersions( Func versionSupportResolver, Action configure) { _versionSupportResolver = versionSupportResolver; _versionInfoBuilder = new VersionInfoBuilder(); configure(_versionInfoBuilder); } public void Schemes(IEnumerable schemes) { _schemes = schemes; } public BasicAuthSchemeBuilder BasicAuth(string name) { var schemeBuilder = new BasicAuthSchemeBuilder(); _securitySchemeBuilders[name] = schemeBuilder; return schemeBuilder; } public ApiKeySchemeBuilder ApiKey(string name) { var schemeBuilder = new ApiKeySchemeBuilder(); _securitySchemeBuilders[name] = schemeBuilder; return schemeBuilder; } public OAuth2SchemeBuilder OAuth2(string name) { var schemeBuilder = new OAuth2SchemeBuilder(); _securitySchemeBuilders[name] = schemeBuilder; return schemeBuilder; } public void PrettyPrint() { _prettyPrint = true; } public void IgnoreObsoleteActions() { _ignoreObsoleteActions = true; } public void GroupActionsBy(Func keySelector) { _groupingKeySelector = keySelector; } public void OrderActionGroupsBy(IComparer keyComparer) { _groupingKeyComparer = keyComparer; } public void MapType(Func factory) { MapType(typeof(T), factory); } public void MapType(Type type, Func factory) { _customSchemaMappings.Add(type, factory); } public void SchemaFilter() where TFilter : ISchemaFilter, new() { SchemaFilter(() => new TFilter()); } public void SchemaFilter(Func factory) { _schemaFilters.Add(factory); } // NOTE: In next major version, ModelFilter will completely replace SchemaFilter internal void ModelFilter() where TFilter : IModelFilter, new() { ModelFilter(() => new TFilter()); } // NOTE: In next major version, ModelFilter will completely replace SchemaFilter internal void ModelFilter(Func factory) { _modelFilters.Add(factory); } public void SchemaId(Func schemaIdStrategy) { _schemaIdSelector = schemaIdStrategy; } public void UseFullTypeNameInSchemaIds() { _schemaIdSelector = t => t.FriendlyId(true); } public void DescribeAllEnumsAsStrings(bool camelCase = false) { _describeAllEnumsAsStrings = true; _describeStringEnumsInCamelCase = camelCase; } public void IgnoreObsoleteProperties() { _ignoreObsoleteProperties = true; } [Obsolete("This will be removed in 6.0.0; it will always be true.")] public void ApplyFiltersToAllSchemas() { _applyFiltersToAllSchemas = true; } public void OperationFilter() where TFilter : IOperationFilter, new() { OperationFilter(() => new TFilter()); } public void OperationFilter(Func factory) { _operationFilters.Add(factory); } public void DocumentFilter() where TFilter : IDocumentFilter, new() { DocumentFilter(() => new TFilter()); } public void DocumentFilter(Func factory) { _documentFilters.Add(factory); } public void IncludeXmlComments(Func xmlDocFactory) { _xmlDocFactories.Add(xmlDocFactory); } public void IncludeXmlComments(string filePath) { _xmlDocFactories.Add(() => new XPathDocument(filePath)); } public void ResolveConflictingActions(Func, ApiDescription> conflictingActionsResolver) { _conflictingActionsResolver = conflictingActionsResolver; } public void RootUrl(Func rootUrlResolver) { _rootUrlResolver = rootUrlResolver; } public void CustomProvider(Func customProviderFactory) { _customProviderFactory = customProviderFactory; } /// /// 显示开发者信息 /// public void ShowDeveloperInfo() { ShowDeveloper = true; } internal ISwaggerProvider GetSwaggerProvider(HttpRequestMessage swaggerRequest) { var httpConfig = swaggerRequest.GetConfiguration(); var securityDefintitions = _securitySchemeBuilders.Any() ? _securitySchemeBuilders.ToDictionary(kvp => kvp.Key, kvp => kvp.Value.Build()) : null; // NOTE: Instantiate & add the XML comments filters here so they're executed before any // custom filters AND so they can share the same XPathDocument (perf. optimization) var modelFilters = _modelFilters.Select(factory => factory()).ToList(); var operationFilters = _operationFilters.Select(factory => factory()).ToList(); foreach (var xmlDocFactory in _xmlDocFactories) { var xmlDoc = xmlDocFactory(); modelFilters.Insert(0, new ApplyXmlTypeComments(xmlDoc)); operationFilters.Insert(0, new ApplyXmlActionComments(xmlDoc)); } var options = new SwaggerGeneratorOptions( versionSupportResolver: _versionSupportResolver, schemes: _schemes, securityDefinitions: securityDefintitions, ignoreObsoleteActions: _ignoreObsoleteActions, groupingKeySelector: _groupingKeySelector, groupingKeyComparer: _groupingKeyComparer, customSchemaMappings: _customSchemaMappings, schemaFilters: _schemaFilters.Select(factory => factory()).ToList(), modelFilters: modelFilters, ignoreObsoleteProperties: _ignoreObsoleteProperties, schemaIdSelector: _schemaIdSelector, describeAllEnumsAsStrings: _describeAllEnumsAsStrings, describeStringEnumsInCamelCase: _describeStringEnumsInCamelCase, applyFiltersToAllSchemas: _applyFiltersToAllSchemas, operationFilters: operationFilters, documentFilters: _documentFilters.Select(factory => factory()).ToList(), conflictingActionsResolver: _conflictingActionsResolver ); var defaultProvider = new SwaggerGenerator( httpConfig.Services.GetApiExplorer(), httpConfig.SerializerSettingsOrDefault(), _versionInfoBuilder.Build(), options); return (_customProviderFactory != null) ? _customProviderFactory(defaultProvider) : defaultProvider; } internal string GetRootUrl(HttpRequestMessage swaggerRequest) { return _rootUrlResolver(swaggerRequest); } internal IEnumerable GetApiVersions() { return _versionInfoBuilder.Build().Select(entry => entry.Key); } internal Formatting GetFormatting() { return _prettyPrint ? Formatting.Indented : Formatting.None; } public static string DefaultRootUrlResolver(HttpRequestMessage request) { var scheme = GetHeaderValue(request, "X-Forwarded-Proto") ?? request.RequestUri.Scheme; var host = GetHeaderValue(request, "X-Forwarded-Host") ?? request.RequestUri.Host; var port = GetHeaderValue(request, "X-Forwarded-Port") ?? request.RequestUri.Port.ToString(CultureInfo.InvariantCulture); var httpConfiguration = request.GetConfiguration(); var virtualPathRoot = httpConfiguration.VirtualPathRoot.TrimEnd('/'); return string.Format("{0}://{1}:{2}{3}", scheme, host, port, virtualPathRoot); } private static string GetHeaderValue(HttpRequestMessage request, string headerName) { IEnumerable list; return request.Headers.TryGetValues(headerName, out list) ? list.FirstOrDefault() : null; } } }