More DI feature for `OpenApiConfigurationOptions` (#466)
This commit is contained in:
Родитель
1ac4a84258
Коммит
9072106051
|
@ -66,7 +66,7 @@ If the above conditions are met, add the following key to your `local.settings.j
|
|||
To generate an OpenAPI document, [OpenApiInfo object](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.1.md#infoObject) needs to be defined. ***It's totally optional***, but if you want, you can implement the `IOpenApiConfigurationOptions` interface within your Azure Functions project to provide OpenAPI metadata like below:
|
||||
|
||||
```csharp
|
||||
public class OpenApiConfigurationOptions : IOpenApiConfigurationOptions
|
||||
public class MyOpenApiConfigurationOptions : IOpenApiConfigurationOptions
|
||||
{
|
||||
public OpenApiInfo Info { get; set; } = new OpenApiInfo()
|
||||
{
|
||||
|
@ -102,7 +102,7 @@ It's often required for the API app to have more than one base URL, with differe
|
|||
Alternatively, add `OpenApiServer` details to the `Servers` property like:
|
||||
|
||||
```csharp
|
||||
public class OpenApiConfigurationOptions : IOpenApiConfigurationOptions
|
||||
public class MyOpenApiConfigurationOptions : IOpenApiConfigurationOptions
|
||||
{
|
||||
...
|
||||
|
||||
|
@ -127,7 +127,7 @@ public class OpenApiConfigurationOptions : IOpenApiConfigurationOptions
|
|||
The default version of OpenAPI document rendered is V2 (AKA Swagger). However, you can override the default rendering behaviour by implementing the `OpenApiVersion` property.
|
||||
|
||||
```csharp
|
||||
public class OpenApiConfigurationOptions : IOpenApiConfigurationOptions
|
||||
public class MyOpenApiConfigurationOptions : IOpenApiConfigurationOptions
|
||||
{
|
||||
...
|
||||
|
||||
|
@ -145,7 +145,7 @@ public class OpenApiConfigurationOptions : IOpenApiConfigurationOptions
|
|||
If you want to force either HTTP or HTTPS, configure the following properties on the `IOpenApiConfigurationOptions` interface.
|
||||
|
||||
```csharp
|
||||
public class OpenApiConfigurationOptions : IOpenApiConfigurationOptions
|
||||
public class MyOpenApiConfigurationOptions : IOpenApiConfigurationOptions
|
||||
{
|
||||
...
|
||||
|
||||
|
@ -198,65 +198,14 @@ public class MyOpenApiConfigurationOptions : DefaultOpenApiConfigurationOptions
|
|||
}
|
||||
```
|
||||
|
||||
### Dynamically configuring `IOpenApiConfigurationOptions` at Runtime ###
|
||||
|
||||
There may be instances where you want to configure the `IOpenApiConfigurationOptions` at runtime.
|
||||
### Injecting `OpenApiConfigurationOptions` during Startup ###
|
||||
|
||||
To dynamically modify your configuration options at runtime you can use the following examples:
|
||||
You may want to inject the `OpenApiConfigurationOptions` instance during startup:
|
||||
|
||||
#### In of Proc ####
|
||||
* [in-proc worker](./openapi-in-proc.md#injecting-openapiconfigurationoptions-during-startup)
|
||||
* [out-of-proc worker](./openapi-out-of-proc.md#injecting-openapiconfigurationoptions-during-startup)
|
||||
|
||||
```csharp
|
||||
public override void Configure(IFunctionsHostBuilder builder)
|
||||
{
|
||||
var fixture = new Fixture();
|
||||
builder.Services.AddSingleton(fixture);
|
||||
|
||||
// Example: If you want to change the configuration during startup of your function you can use the following code:
|
||||
services.AddSingleton<IOpenApiConfigurationOptions>(x =>
|
||||
{
|
||||
return new OpenApiConfigurationOptions()
|
||||
{
|
||||
Info = new Microsoft.OpenApi.Models.OpenApiInfo
|
||||
{
|
||||
Title = "A dynamic title generated at runtime",
|
||||
Description = "Dynamic Open API information at runtime"
|
||||
}
|
||||
};
|
||||
});
|
||||
}
|
||||
```
|
||||
|
||||
#### Out of Proc ####
|
||||
|
||||
```csharp
|
||||
public static void Main()
|
||||
{
|
||||
var host = new HostBuilder()
|
||||
.ConfigureFunctionsWorkerDefaults(worker => worker.UseNewtonsoftJson())
|
||||
.ConfigureOpenApi()
|
||||
.ConfigureServices(services => services.AddSingleton<Fixture>())
|
||||
.ConfigureServices(services => {
|
||||
services.AddSingleton<Fixture>();
|
||||
|
||||
// Example: If you want to change the configuration during startup of your function you can use the following code:
|
||||
services.AddSingleton<IOpenApiConfigurationOptions>(x =>
|
||||
{
|
||||
return new OpenApiConfigurationOptions()
|
||||
{
|
||||
Info = new Microsoft.OpenApi.Models.OpenApiInfo
|
||||
{
|
||||
Title = "A dynamic title generated at runtime",
|
||||
Description = "Dynamic Open API information at runtime"
|
||||
}
|
||||
};
|
||||
});
|
||||
})
|
||||
.Build();
|
||||
|
||||
host.Run();
|
||||
}
|
||||
```
|
||||
|
||||
## Swagger UI Customisation ##
|
||||
|
||||
|
|
|
@ -31,3 +31,52 @@ For detailed getting started document, find this [Enable OpenAPI Endpoints on Az
|
|||
## Advanced Configuration in General ##
|
||||
|
||||
If you look for the advanced configurations in general, please find the document, [Advanced Configurations for OpenAPI Extension](./openapi.md)
|
||||
|
||||
|
||||
### Injecting `OpenApiConfigurationOptions` during Startup ###
|
||||
|
||||
You may want to inject the `OpenApiConfigurationOptions` instance during startup, through the `Startup.cs` class. Here's the example:
|
||||
|
||||
```csharp
|
||||
[assembly: FunctionsStartup(typeof(MyFunctionApp.Startup))]
|
||||
namespace MyFunctionApp
|
||||
{
|
||||
public class Startup : FunctionsStartup
|
||||
{
|
||||
public override void Configure(IFunctionsHostBuilder builder)
|
||||
{
|
||||
builder.Services.AddSingleton<IOpenApiConfigurationOptions>(_ =>
|
||||
{
|
||||
var options = new OpenApiConfigurationOptions()
|
||||
{
|
||||
Info = new OpenApiInfo()
|
||||
{
|
||||
Version = "1.0.0",
|
||||
Title = "Swagger Petstore",
|
||||
Description = "This is a sample server Petstore API designed by [http://swagger.io](http://swagger.io).",
|
||||
TermsOfService = new Uri("https://github.com/Azure/azure-functions-openapi-extension"),
|
||||
Contact = new OpenApiContact()
|
||||
{
|
||||
Name = "Enquiry",
|
||||
Email = "azfunc-openapi@microsoft.com",
|
||||
Url = new Uri("https://github.com/Azure/azure-functions-openapi-extension/issues"),
|
||||
},
|
||||
License = new OpenApiLicense()
|
||||
{
|
||||
Name = "MIT",
|
||||
Url = new Uri("http://opensource.org/licenses/MIT"),
|
||||
}
|
||||
},
|
||||
Servers = DefaultOpenApiConfigurationOptions.GetHostNames(),
|
||||
OpenApiVersion = OpenApiVersionType.V2,
|
||||
IncludeRequestingHostName = true,
|
||||
ForceHttps = false,
|
||||
ForceHttp = false,
|
||||
};
|
||||
|
||||
return options;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
|
|
@ -25,3 +25,62 @@ For detailed getting started document, find this [Enable OpenAPI Endpoints on Az
|
|||
## Advanced Configuration in General ##
|
||||
|
||||
If you look for the advanced configurations in general, please find the document, [Advanced Configurations for OpenAPI Extension](./openapi.md)
|
||||
|
||||
|
||||
### Injecting `OpenApiConfigurationOptions` during Startup ###
|
||||
|
||||
You may want to inject the `OpenApiConfigurationOptions` instance during startup, through the `Program.cs` class. Here's the example:
|
||||
|
||||
```csharp
|
||||
namespace MyFunctionApp
|
||||
{
|
||||
public class Program
|
||||
{
|
||||
public static void Main()
|
||||
{
|
||||
var host = new HostBuilder()
|
||||
.ConfigureFunctionsWorkerDefaults(worker => worker.UseNewtonsoftJson())
|
||||
.ConfigureOpenApi()
|
||||
/* ⬇️⬇️⬇️ Add this ⬇️⬇️⬇️ */
|
||||
.ConfigureServices(services =>
|
||||
{
|
||||
services.AddSingleton<IOpenApiConfigurationOptions>(_ =>
|
||||
{
|
||||
var options = new OpenApiConfigurationOptions()
|
||||
{
|
||||
Info = new OpenApiInfo()
|
||||
{
|
||||
Version = "1.0.0",
|
||||
Title = "Swagger Petstore",
|
||||
Description = "This is a sample server Petstore API designed by [http://swagger.io](http://swagger.io).",
|
||||
TermsOfService = new Uri("https://github.com/Azure/azure-functions-openapi-extension"),
|
||||
Contact = new OpenApiContact()
|
||||
{
|
||||
Name = "Enquiry",
|
||||
Email = "azfunc-openapi@microsoft.com",
|
||||
Url = new Uri("https://github.com/Azure/azure-functions-openapi-extension/issues"),
|
||||
},
|
||||
License = new OpenApiLicense()
|
||||
{
|
||||
Name = "MIT",
|
||||
Url = new Uri("http://opensource.org/licenses/MIT"),
|
||||
}
|
||||
},
|
||||
Servers = DefaultOpenApiConfigurationOptions.GetHostNames(),
|
||||
OpenApiVersion = OpenApiVersionType.V2,
|
||||
IncludeRequestingHostName = true,
|
||||
ForceHttps = false,
|
||||
ForceHttp = false,
|
||||
};
|
||||
|
||||
return options;
|
||||
});
|
||||
})
|
||||
/* ⬆️⬆️⬆️ Add this ⬆️⬆️⬆️ */
|
||||
.Build();
|
||||
|
||||
host.Run();
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
|
|
@ -27,7 +27,7 @@ As a default, all endpoints to render Swagger UI and OpenAPI documents have the
|
|||
}
|
||||
```
|
||||
|
||||
You can have granular controls to both Swagger UI and OpenAPI documents by setting the authorisation level to `Anonymous`, `User`, `Function`, `System` or `Admin`. Make sure that you MUST provide the `OpenApi__AuthKey` value, if you choose the `OpenApi__AuthLevel__Document` value other than `Anonymous`. Otherwise, it will throw an error.
|
||||
You can have granular controls to both Swagger UI and OpenAPI documents by setting the authorisation level to `Anonymous`, `User`, `Function`, `System` or `Admin`. Make sure that you MUST provide the `OpenApi__ApiKey` value, if you choose the `OpenApi__AuthLevel__Document` value other than `Anonymous`. Otherwise, it will throw an error.
|
||||
|
||||
> **NOTE**: Both Swagger UI and OpenAPI document pages are allowed `Anonymous` access by default.
|
||||
|
||||
|
|
|
@ -6,13 +6,13 @@ using Microsoft.OpenApi.Models;
|
|||
|
||||
namespace Microsoft.Azure.Functions.Worker.Extensions.OpenApi.FunctionApp.OutOfProc.Configurations
|
||||
{
|
||||
public class OpenApiConfigurationOptions : DefaultOpenApiConfigurationOptions
|
||||
public class MyOpenApiConfigurationOptions : DefaultOpenApiConfigurationOptions
|
||||
{
|
||||
public override OpenApiInfo Info { get; set; } = new OpenApiInfo()
|
||||
{
|
||||
Version = GetOpenApiDocVersion(),
|
||||
Title = GetOpenApiDocTitle(),
|
||||
Description = "This is a sample server Petstore API designed by [http://swagger.io](http://swagger.io).",
|
||||
Description = GetOpenApiDocDescription(),
|
||||
TermsOfService = new Uri("https://github.com/Azure/azure-functions-openapi-extension"),
|
||||
Contact = new OpenApiContact()
|
||||
{
|
|
@ -1,40 +1,62 @@
|
|||
using AutoFixture;
|
||||
|
||||
using Microsoft.Azure.Functions.Worker.Extensions.OpenApi.Extensions;
|
||||
using Microsoft.Azure.Functions.Worker.Extensions.OpenApi.FunctionApp.OutOfProc.Configurations;
|
||||
using System;
|
||||
|
||||
using AutoFixture;
|
||||
|
||||
using Microsoft.Azure.Functions.Worker.Extensions.OpenApi.Extensions;
|
||||
using Microsoft.Azure.WebJobs.Extensions.OpenApi.Core.Abstractions;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
|
||||
namespace Microsoft.Azure.Functions.Worker.Extensions.OpenApi.FunctionApp.OutOfProc
|
||||
{
|
||||
public class Program
|
||||
{
|
||||
public static void Main()
|
||||
{
|
||||
var host = new HostBuilder()
|
||||
.ConfigureFunctionsWorkerDefaults(worker => worker.UseNewtonsoftJson())
|
||||
.ConfigureOpenApi()
|
||||
.ConfigureServices(services => {
|
||||
services.AddSingleton<Fixture>();
|
||||
using Microsoft.Azure.WebJobs.Extensions.OpenApi.Core.Configurations;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using Microsoft.OpenApi.Models;
|
||||
|
||||
// Example: If you want to change the configuration during startup of your function you can use the following code:
|
||||
namespace Microsoft.Azure.Functions.Worker.Extensions.OpenApi.FunctionApp.OutOfProc
|
||||
{
|
||||
public class Program
|
||||
{
|
||||
public static void Main()
|
||||
{
|
||||
var host = new HostBuilder()
|
||||
.ConfigureFunctionsWorkerDefaults(worker => worker.UseNewtonsoftJson())
|
||||
.ConfigureOpenApi()
|
||||
.ConfigureServices(services =>
|
||||
{
|
||||
services.AddSingleton<Fixture>()
|
||||
.AddSingleton<IOpenApiConfigurationOptions>(_ =>
|
||||
{
|
||||
var options = new OpenApiConfigurationOptions()
|
||||
{
|
||||
Info = new OpenApiInfo()
|
||||
{
|
||||
Version = DefaultOpenApiConfigurationOptions.GetOpenApiDocVersion(),
|
||||
Title = $"{DefaultOpenApiConfigurationOptions.GetOpenApiDocTitle()} (Injected)",
|
||||
Description = DefaultOpenApiConfigurationOptions.GetOpenApiDocDescription(),
|
||||
TermsOfService = new Uri("https://github.com/Azure/azure-functions-openapi-extension"),
|
||||
Contact = new OpenApiContact()
|
||||
{
|
||||
Name = "Enquiry",
|
||||
Email = "azfunc-openapi@microsoft.com",
|
||||
Url = new Uri("https://github.com/Azure/azure-functions-openapi-extension/issues"),
|
||||
},
|
||||
License = new OpenApiLicense()
|
||||
{
|
||||
Name = "MIT",
|
||||
Url = new Uri("http://opensource.org/licenses/MIT"),
|
||||
}
|
||||
},
|
||||
Servers = DefaultOpenApiConfigurationOptions.GetHostNames(),
|
||||
OpenApiVersion = DefaultOpenApiConfigurationOptions.GetOpenApiVersion(),
|
||||
IncludeRequestingHostName = DefaultOpenApiConfigurationOptions.IsFunctionsRuntimeEnvironmentDevelopment(),
|
||||
ForceHttps = DefaultOpenApiConfigurationOptions.IsHttpsForced(),
|
||||
ForceHttp = DefaultOpenApiConfigurationOptions.IsHttpForced(),
|
||||
};
|
||||
|
||||
//services.AddSingleton<IOpenApiConfigurationOptions>(x =>
|
||||
//{
|
||||
// return new OpenApiConfigurationOptions()
|
||||
// {
|
||||
// Info = new Microsoft.OpenApi.Models.OpenApiInfo
|
||||
// {
|
||||
// Title = "A dynamic title generated at runtime",
|
||||
// Description = "Dynamic Open API information at runtime"
|
||||
// }
|
||||
// };
|
||||
//});
|
||||
})
|
||||
.Build();
|
||||
|
||||
host.Run();
|
||||
}
|
||||
}
|
||||
}
|
||||
return options;
|
||||
})
|
||||
;
|
||||
})
|
||||
.Build();
|
||||
|
||||
host.Run();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
"OpenApi__Version": "v3",
|
||||
"OpenApi__DocVersion": "1.0.0",
|
||||
"OpenApi__DocTitle": "Swagger Petstore"
|
||||
"OpenApi__DocTitle": "Swagger Petstore",
|
||||
"OpenApi__DocDescription": "This is a sample server Petstore API designed by [http://swagger.io](http://swagger.io)."
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,17 +1,18 @@
|
|||
using System;
|
||||
|
||||
using Microsoft.Azure.WebJobs.Extensions.OpenApi.Core.Configurations;
|
||||
using Microsoft.Azure.WebJobs.Extensions.OpenApi.Core.Enums;
|
||||
using Microsoft.OpenApi.Models;
|
||||
|
||||
namespace Microsoft.Azure.WebJobs.Extensions.OpenApi.FunctionApp.InProc.Configurations
|
||||
{
|
||||
public class OpenApiConfigurationOptions : DefaultOpenApiConfigurationOptions
|
||||
public class MyOpenApiConfigurationOptions : DefaultOpenApiConfigurationOptions
|
||||
{
|
||||
public override OpenApiInfo Info { get; set; } = new OpenApiInfo()
|
||||
{
|
||||
Version = GetOpenApiDocVersion(),
|
||||
Title = GetOpenApiDocTitle(),
|
||||
Description = "This is a sample server Petstore API designed by [http://swagger.io](http://swagger.io).",
|
||||
Description = GetOpenApiDocDescription(),
|
||||
TermsOfService = new Uri("https://github.com/Azure/azure-functions-openapi-extension"),
|
||||
Contact = new OpenApiContact()
|
||||
{
|
|
@ -1,34 +1,54 @@
|
|||
using AutoFixture;
|
||||
|
||||
using Microsoft.Azure.Functions.Extensions.DependencyInjection;
|
||||
using System;
|
||||
|
||||
using AutoFixture;
|
||||
|
||||
using Microsoft.Azure.Functions.Extensions.DependencyInjection;
|
||||
using Microsoft.Azure.WebJobs.Extensions.OpenApi.Core.Abstractions;
|
||||
using Microsoft.Azure.WebJobs.Extensions.OpenApi.FunctionApp.InProc.Configurations;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
[assembly: FunctionsStartup(typeof(Microsoft.Azure.WebJobs.Extensions.OpenApi.FunctionApp.InProc.Startup))]
|
||||
|
||||
namespace Microsoft.Azure.WebJobs.Extensions.OpenApi.FunctionApp.InProc
|
||||
{
|
||||
public class Startup : FunctionsStartup
|
||||
{
|
||||
public override void Configure(IFunctionsHostBuilder builder)
|
||||
{
|
||||
var fixture = new Fixture();
|
||||
builder.Services.AddSingleton(fixture);
|
||||
using Microsoft.Azure.WebJobs.Extensions.OpenApi.Core.Configurations;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.OpenApi.Models;
|
||||
|
||||
// Example: If you want to change the configuration during startup of your function you can use the following code:
|
||||
[assembly: FunctionsStartup(typeof(Microsoft.Azure.WebJobs.Extensions.OpenApi.FunctionApp.InProc.Startup))]
|
||||
|
||||
//builder.Services.AddSingleton<IOpenApiConfigurationOptions>((_) =>
|
||||
//{
|
||||
// return new OpenApiConfigurationOptions()
|
||||
// {
|
||||
// Info = new Microsoft.OpenApi.Models.OpenApiInfo
|
||||
// {
|
||||
// Title = "A dynamic title generated at runtime",
|
||||
// Description = "Dynamic Open API information at runtime"
|
||||
// }
|
||||
// };
|
||||
//});
|
||||
}
|
||||
}
|
||||
}
|
||||
namespace Microsoft.Azure.WebJobs.Extensions.OpenApi.FunctionApp.InProc
|
||||
{
|
||||
public class Startup : FunctionsStartup
|
||||
{
|
||||
public override void Configure(IFunctionsHostBuilder builder)
|
||||
{
|
||||
builder.Services.AddSingleton<Fixture>()
|
||||
.AddSingleton<IOpenApiConfigurationOptions>(_ =>
|
||||
{
|
||||
var options = new OpenApiConfigurationOptions()
|
||||
{
|
||||
Info = new OpenApiInfo()
|
||||
{
|
||||
Version = DefaultOpenApiConfigurationOptions.GetOpenApiDocVersion(),
|
||||
Title = $"{DefaultOpenApiConfigurationOptions.GetOpenApiDocTitle()} (Injected)",
|
||||
Description = DefaultOpenApiConfigurationOptions.GetOpenApiDocDescription(),
|
||||
TermsOfService = new Uri("https://github.com/Azure/azure-functions-openapi-extension"),
|
||||
Contact = new OpenApiContact()
|
||||
{
|
||||
Name = "Enquiry",
|
||||
Email = "azfunc-openapi@microsoft.com",
|
||||
Url = new Uri("https://github.com/Azure/azure-functions-openapi-extension/issues"),
|
||||
},
|
||||
License = new OpenApiLicense()
|
||||
{
|
||||
Name = "MIT",
|
||||
Url = new Uri("http://opensource.org/licenses/MIT"),
|
||||
}
|
||||
},
|
||||
Servers = DefaultOpenApiConfigurationOptions.GetHostNames(),
|
||||
OpenApiVersion = DefaultOpenApiConfigurationOptions.GetOpenApiVersion(),
|
||||
IncludeRequestingHostName = DefaultOpenApiConfigurationOptions.IsFunctionsRuntimeEnvironmentDevelopment(),
|
||||
ForceHttps = DefaultOpenApiConfigurationOptions.IsHttpsForced(),
|
||||
ForceHttp = DefaultOpenApiConfigurationOptions.IsHttpForced(),
|
||||
};
|
||||
|
||||
return options;
|
||||
})
|
||||
;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
"OpenApi__Version": "v3",
|
||||
"OpenApi__DocVersion": "1.0.0",
|
||||
"OpenApi__DocTitle": "Swagger Petstore"
|
||||
"OpenApi__DocTitle": "Swagger Petstore",
|
||||
"OpenApi__DocDescription": "This is a sample server Petstore API designed by [http://swagger.io](http://swagger.io)."
|
||||
}
|
||||
}
|
||||
|
|
|
@ -40,6 +40,7 @@ namespace Microsoft.Azure.Functions.Worker.Extensions.OpenApi
|
|||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="OpenApiHttpTriggerContext"/> class.
|
||||
/// </summary>
|
||||
/// <param name="configOptions"><see cref="IOpenApiConfigurationOptions"/> instance.</param>
|
||||
public OpenApiHttpTriggerContext(IOpenApiConfigurationOptions configOptions = null)
|
||||
{
|
||||
this._configOptions = configOptions;
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Cocona.Lite" Version="1.4.0" />
|
||||
<PackageReference Include="Microsoft.Azure.WebJobs" Version="3.0.33" />
|
||||
<PackageReference Include="Microsoft.Azure.WebJobs" Version="3.0.25" />
|
||||
<PackageReference Include="Moq" Version="4.18.1" />
|
||||
<PackageReference Include="System.IO.FileSystem.Primitives" Version="4.3.0" />
|
||||
<PackageReference Include="System.Runtime.Handles" Version="4.3.0" />
|
||||
|
|
|
@ -1,6 +1,3 @@
|
|||
using System.Collections.Generic;
|
||||
|
||||
using Microsoft.Azure.WebJobs.Extensions.Http;
|
||||
using Microsoft.Azure.WebJobs.Extensions.OpenApi.Core.Enums;
|
||||
|
||||
using Newtonsoft.Json;
|
||||
|
@ -8,16 +5,16 @@ using Newtonsoft.Json;
|
|||
namespace Microsoft.Azure.WebJobs.Extensions.OpenApi.Core.Abstractions
|
||||
{
|
||||
/// <summary>
|
||||
/// This represents the metadata entity for OpenApiHttpTrigger context binding.
|
||||
/// This represents the metadata entity for OpenAPI HTTP Trigger context binding.
|
||||
/// </summary>
|
||||
public class OpenApiHttpTriggerContextBindingMetadata
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the name of the binding parameter. Default value is <c>context</c>.
|
||||
/// Gets or sets the name of the binding parameter. Default value is <c>openApiContext</c>.
|
||||
/// </summary>
|
||||
[JsonRequired]
|
||||
[JsonProperty("name")]
|
||||
public virtual string Name { get; set; } = "context";
|
||||
public virtual string Name { get; set; } = "openApiContext";
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the binding type. Default value is <c>openApiHttpTriggerContext</c>.
|
|
@ -0,0 +1,14 @@
|
|||
using System;
|
||||
|
||||
using Microsoft.Azure.WebJobs.Extensions.OpenApi.Core.Abstractions;
|
||||
|
||||
namespace Microsoft.Azure.WebJobs.Extensions.OpenApi.Core.Attributes
|
||||
{
|
||||
/// <summary>
|
||||
/// This represents the attribute entity for <see cref="IOpenApiConfigurationOptions"/> to be excluded from auto-loading.
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = false)]
|
||||
public class OpenApiConfigurationOptionsIgnoreAttribute : Attribute
|
||||
{
|
||||
}
|
||||
}
|
|
@ -3,6 +3,7 @@ using System.Collections.Generic;
|
|||
using System.Linq;
|
||||
|
||||
using Microsoft.Azure.WebJobs.Extensions.OpenApi.Core.Abstractions;
|
||||
using Microsoft.Azure.WebJobs.Extensions.OpenApi.Core.Attributes;
|
||||
using Microsoft.Azure.WebJobs.Extensions.OpenApi.Core.Enums;
|
||||
using Microsoft.Azure.WebJobs.Extensions.OpenApi.Core.Extensions;
|
||||
using Microsoft.OpenApi.Models;
|
||||
|
@ -12,10 +13,12 @@ namespace Microsoft.Azure.WebJobs.Extensions.OpenApi.Core.Configurations
|
|||
/// <summary>
|
||||
/// This represents the options entity for OpenAPI metadata configuration.
|
||||
/// </summary>
|
||||
public class DefaultOpenApiConfigurationOptions : IOpenApiConfigurationOptions
|
||||
[OpenApiConfigurationOptionsIgnore]
|
||||
public class DefaultOpenApiConfigurationOptions : OpenApiConfigurationOptions
|
||||
{
|
||||
private const string OpenApiDocVersionKey = "OpenApi__DocVersion";
|
||||
private const string OpenApiDocTitleKey = "OpenApi__DocTitle";
|
||||
private const string OpenApiDocDescriptionKey = "OpenApi__DocDescription";
|
||||
private const string OpenApiHostNamesKey = "OpenApi__HostNames";
|
||||
private const string OpenApiVersionKey = "OpenApi__Version";
|
||||
private const string FunctionsRuntimeEnvironmentKey = "AZURE_FUNCTIONS_ENVIRONMENT";
|
||||
|
@ -23,35 +26,36 @@ namespace Microsoft.Azure.WebJobs.Extensions.OpenApi.Core.Configurations
|
|||
private const string ForceHttpsKey = "OpenApi__ForceHttps";
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual OpenApiInfo Info { get; set; } = new OpenApiInfo()
|
||||
public override OpenApiInfo Info { get; set; } = new OpenApiInfo()
|
||||
{
|
||||
Version = GetOpenApiDocVersion(),
|
||||
Title = GetOpenApiDocTitle(),
|
||||
Description = GetOpenApiDocDescription(),
|
||||
};
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual List<OpenApiServer> Servers { get; set; } = GetHostNames();
|
||||
public override List<OpenApiServer> Servers { get; set; } = GetHostNames();
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual OpenApiVersionType OpenApiVersion { get; set; } = GetOpenApiVersion();
|
||||
public override OpenApiVersionType OpenApiVersion { get; set; } = GetOpenApiVersion();
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual bool IncludeRequestingHostName { get; set; } = IsFunctionsRuntimeEnvironmentDevelopment();
|
||||
public override bool IncludeRequestingHostName { get; set; } = IsFunctionsRuntimeEnvironmentDevelopment();
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual bool ForceHttp { get; set; } = IsHttpForced();
|
||||
public override bool ForceHttp { get; set; } = IsHttpForced();
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual bool ForceHttps { get; set; } = IsHttpsForced();
|
||||
public override bool ForceHttps { get; set; } = IsHttpsForced();
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual List<IDocumentFilter> DocumentFilters { get; set; } = new List<IDocumentFilter>();
|
||||
public override List<IDocumentFilter> DocumentFilters { get; set; } = new List<IDocumentFilter>();
|
||||
|
||||
/// <summary>
|
||||
/// Gets the OpenAPI document version.
|
||||
/// </summary>
|
||||
/// <returns>Returns the OpenAPI document version.</returns>
|
||||
protected static string GetOpenApiDocVersion()
|
||||
public static string GetOpenApiDocVersion()
|
||||
{
|
||||
var version = Environment.GetEnvironmentVariable(OpenApiDocVersionKey) ?? DefaultOpenApiDocVersion();
|
||||
|
||||
|
@ -62,18 +66,29 @@ namespace Microsoft.Azure.WebJobs.Extensions.OpenApi.Core.Configurations
|
|||
/// Gets the OpenAPI document title.
|
||||
/// </summary>
|
||||
/// <returns>Returns the OpenAPI document title.</returns>
|
||||
protected static string GetOpenApiDocTitle()
|
||||
public static string GetOpenApiDocTitle()
|
||||
{
|
||||
var title = Environment.GetEnvironmentVariable(OpenApiDocTitleKey) ?? DefaultOpenApiDocTitle();
|
||||
|
||||
return title;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the OpenAPI document description.
|
||||
/// </summary>
|
||||
/// <returns>Returns the OpenAPI document description.</returns>
|
||||
public static string GetOpenApiDocDescription()
|
||||
{
|
||||
var description = Environment.GetEnvironmentVariable(OpenApiDocDescriptionKey) ?? DefaultOpenApiDocDescription();
|
||||
|
||||
return description;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the list of hostnames.
|
||||
/// </summary>
|
||||
/// <returns>Returns the list of hostnames.</returns>
|
||||
protected static List<OpenApiServer> GetHostNames()
|
||||
public static List<OpenApiServer> GetHostNames()
|
||||
{
|
||||
var servers = new List<OpenApiServer>();
|
||||
var collection = Environment.GetEnvironmentVariable(OpenApiHostNamesKey);
|
||||
|
@ -95,7 +110,7 @@ namespace Microsoft.Azure.WebJobs.Extensions.OpenApi.Core.Configurations
|
|||
/// Gets the OpenAPI version.
|
||||
/// </summary>
|
||||
/// <returns>Returns the OpenAPI version.</returns>
|
||||
protected static OpenApiVersionType GetOpenApiVersion()
|
||||
public static OpenApiVersionType GetOpenApiVersion()
|
||||
{
|
||||
var version = Enum.TryParse<OpenApiVersionType>(
|
||||
Environment.GetEnvironmentVariable(OpenApiVersionKey), ignoreCase: true, out var result)
|
||||
|
@ -109,7 +124,7 @@ namespace Microsoft.Azure.WebJobs.Extensions.OpenApi.Core.Configurations
|
|||
/// Checks whether the current Azure Functions runtime environment is "Development" or not.
|
||||
/// </summary>
|
||||
/// <returns>Returns <c>True</c>, if the current Azure Functions runtime environment is "Development"; otherwise returns <c>False</c></returns>
|
||||
protected static bool IsFunctionsRuntimeEnvironmentDevelopment()
|
||||
public static bool IsFunctionsRuntimeEnvironmentDevelopment()
|
||||
{
|
||||
var development = Environment.GetEnvironmentVariable(FunctionsRuntimeEnvironmentKey) == "Development";
|
||||
|
||||
|
@ -120,7 +135,7 @@ namespace Microsoft.Azure.WebJobs.Extensions.OpenApi.Core.Configurations
|
|||
/// Checks whether HTTP is forced or not.
|
||||
/// </summary>
|
||||
/// <returns>Returns <c>True</c>, if HTTP is forced; otherwise returns <c>False</c>.</returns>
|
||||
protected static bool IsHttpForced()
|
||||
public static bool IsHttpForced()
|
||||
{
|
||||
var development = bool.TryParse(Environment.GetEnvironmentVariable(ForceHttpKey), out var result) ? result : false;
|
||||
|
||||
|
@ -131,7 +146,7 @@ namespace Microsoft.Azure.WebJobs.Extensions.OpenApi.Core.Configurations
|
|||
/// Checks whether HTTPS is forced or not.
|
||||
/// </summary>
|
||||
/// <returns>Returns <c>True</c>, if HTTPS is forced; otherwise returns <c>False</c>.</returns>
|
||||
protected static bool IsHttpsForced()
|
||||
public static bool IsHttpsForced()
|
||||
{
|
||||
var development = bool.TryParse(Environment.GetEnvironmentVariable(ForceHttpsKey), out var result) ? result : false;
|
||||
|
||||
|
@ -152,5 +167,10 @@ namespace Microsoft.Azure.WebJobs.Extensions.OpenApi.Core.Configurations
|
|||
{
|
||||
return "OpenAPI Document on Azure Functions";
|
||||
}
|
||||
|
||||
private static string DefaultOpenApiDocDescription()
|
||||
{
|
||||
return "This is the OpenAPI Document on Azure Functions";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,37 @@
|
|||
using System.Collections.Generic;
|
||||
|
||||
using Microsoft.Azure.WebJobs.Extensions.OpenApi.Core.Abstractions;
|
||||
using Microsoft.Azure.WebJobs.Extensions.OpenApi.Core.Attributes;
|
||||
using Microsoft.Azure.WebJobs.Extensions.OpenApi.Core.Enums;
|
||||
using Microsoft.OpenApi.Models;
|
||||
|
||||
namespace Microsoft.Azure.WebJobs.Extensions.OpenApi.Core.Configurations
|
||||
{
|
||||
/// <summary>
|
||||
/// This represents the options entity for OpenAPI metadata configuration.
|
||||
/// </summary>
|
||||
[OpenApiConfigurationOptionsIgnore]
|
||||
public class OpenApiConfigurationOptions : IOpenApiConfigurationOptions
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public virtual OpenApiInfo Info { get; set; } = new OpenApiInfo();
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual List<OpenApiServer> Servers { get; set; } = new List<OpenApiServer>();
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual OpenApiVersionType OpenApiVersion { get; set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual bool IncludeRequestingHostName { get; set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual bool ForceHttp { get; set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual bool ForceHttps { get; set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual List<IDocumentFilter> DocumentFilters { get; set; } = new List<IDocumentFilter>();
|
||||
}
|
||||
}
|
|
@ -1,39 +1,40 @@
|
|||
using System;
|
||||
using System.Linq;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using Microsoft.Azure.WebJobs.Extensions.OpenApi.Core.Abstractions;
|
||||
using Microsoft.Azure.WebJobs.Extensions.OpenApi.Core.Configurations;
|
||||
using Microsoft.Azure.WebJobs.Extensions.OpenApi.Core.Extensions;
|
||||
using Microsoft.OpenApi.Models;
|
||||
|
||||
namespace Microsoft.Azure.WebJobs.Extensions.OpenApi.Core.Resolvers
|
||||
{
|
||||
/// <summary>
|
||||
/// This represents the resolver entity for <see cref="OpenApiServer"/>.
|
||||
/// </summary>
|
||||
public static class OpenApiConfigurationResolver
|
||||
|
||||
using Microsoft.Azure.WebJobs.Extensions.OpenApi.Core.Abstractions;
|
||||
using Microsoft.Azure.WebJobs.Extensions.OpenApi.Core.Attributes;
|
||||
using Microsoft.Azure.WebJobs.Extensions.OpenApi.Core.Configurations;
|
||||
using Microsoft.Azure.WebJobs.Extensions.OpenApi.Core.Extensions;
|
||||
using Microsoft.OpenApi.Models;
|
||||
|
||||
namespace Microsoft.Azure.WebJobs.Extensions.OpenApi.Core.Resolvers
|
||||
{
|
||||
/// <summary>
|
||||
/// This represents the resolver entity for <see cref="OpenApiServer"/>.
|
||||
/// </summary>
|
||||
public static class OpenApiConfigurationResolver
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the <see cref="IOpenApiConfigurationOptions"/> instance from the given assembly.
|
||||
/// </summary>
|
||||
/// <param name="assembly">The executing assembly instance.</param>
|
||||
/// <returns>Returns the <see cref="IOpenApiConfigurationOptions"/> instance resolved.</returns>
|
||||
public static IOpenApiConfigurationOptions Resolve(Assembly assembly)
|
||||
{
|
||||
var type = assembly.GetLoadableTypes()
|
||||
.SingleOrDefault(p => p.GetInterface("IOpenApiConfigurationOptions", ignoreCase: true).IsNullOrDefault() == false
|
||||
&& p.IsAbstract == false
|
||||
&& p.GetCustomAttribute<ObsoleteAttribute>(inherit: false).IsNullOrDefault() == true);
|
||||
if (type.IsNullOrDefault())
|
||||
{
|
||||
var settings = new DefaultOpenApiConfigurationOptions();
|
||||
|
||||
return settings;
|
||||
/// <summary>
|
||||
/// Gets the <see cref="IOpenApiConfigurationOptions"/> instance from the given assembly.
|
||||
/// </summary>
|
||||
/// <param name="assembly">The executing assembly instance.</param>
|
||||
/// <returns>Returns the <see cref="IOpenApiConfigurationOptions"/> instance resolved.</returns>
|
||||
public static IOpenApiConfigurationOptions Resolve(Assembly assembly)
|
||||
{
|
||||
var type = assembly.GetLoadableTypes()
|
||||
.SingleOrDefault(p => p.GetInterface("IOpenApiConfigurationOptions", ignoreCase: true).IsNullOrDefault() == false
|
||||
&& p.IsAbstract == false
|
||||
&& p.GetCustomAttribute<ObsoleteAttribute>(inherit: false).IsNullOrDefault() == true
|
||||
&& p.GetCustomAttribute<OpenApiConfigurationOptionsIgnoreAttribute>(inherit: false).IsNullOrDefault() == true);
|
||||
if (type.IsNullOrDefault())
|
||||
{
|
||||
return new DefaultOpenApiConfigurationOptions();
|
||||
}
|
||||
|
||||
var options = Activator.CreateInstance(type);
|
||||
|
||||
return options as IOpenApiConfigurationOptions;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var options = Activator.CreateInstance(type);
|
||||
|
||||
return options as IOpenApiConfigurationOptions;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
using System;
|
||||
|
||||
using Microsoft.Azure.WebJobs.Description;
|
||||
|
||||
namespace Microsoft.Azure.WebJobs.Extensions.OpenApi.Attributes
|
||||
{
|
||||
/// <summary>
|
||||
/// This represents the parameter binding attribute that injects the <see cref="OpenApiHttpTriggerContext"/> instance to each OpenAPI HTTP trigger endpoint.
|
||||
/// </summary>
|
||||
[Binding]
|
||||
[AttributeUsage(AttributeTargets.Parameter)]
|
||||
public class OpenApiHttpTriggerContextAttribute : Attribute
|
||||
{
|
||||
}
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
using System.Threading.Tasks;
|
||||
|
||||
using Microsoft.Azure.WebJobs.Description;
|
||||
using Microsoft.Azure.WebJobs.Host.Bindings;
|
||||
using Microsoft.Azure.WebJobs.Host.Config;
|
||||
|
||||
namespace Microsoft.Azure.WebJobs.Extensions.OpenApi.Attributes
|
||||
{
|
||||
/// <summary>
|
||||
/// This represents the extension attribute that registers the <see cref="OpenApiHttpTriggerContextAttribute"/> to inject the <see cref="OpenApiHttpTriggerContext"/> instance.
|
||||
/// </summary>
|
||||
[Extension(nameof(OpenApiHttpTriggerContextBinding))]
|
||||
public class OpenApiHttpTriggerContextBinding : IExtensionConfigProvider
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public void Initialize(ExtensionConfigContext context)
|
||||
{
|
||||
var rule = context.AddBindingRule<OpenApiHttpTriggerContextAttribute>();
|
||||
rule.BindToInput((attr, vbContext) =>
|
||||
{
|
||||
var httpContext = vbContext.FunctionContext.CreateObjectInstance<OpenApiHttpTriggerContext>();
|
||||
|
||||
return Task.FromResult(httpContext);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,3 +1,5 @@
|
|||
using Microsoft.Azure.WebJobs.Extensions.OpenApi.Core.Enums;
|
||||
|
||||
namespace Microsoft.Azure.WebJobs.Extensions.OpenApi.Configurations
|
||||
{
|
||||
/// <summary>
|
||||
|
@ -5,13 +7,48 @@ namespace Microsoft.Azure.WebJobs.Extensions.OpenApi.Configurations
|
|||
/// </summary>
|
||||
public class OpenApiSettings
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the OpenAPI spec version.
|
||||
/// </summary>
|
||||
public virtual OpenApiVersionType Version { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the OpenAPI document version.
|
||||
/// </summary>
|
||||
public virtual string DocVersion { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the OpenAPI document title.
|
||||
/// </summary>
|
||||
public virtual string DocTitle { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the OpenAPI document description.
|
||||
/// </summary>
|
||||
public virtual string DocDescription { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the comma delimited host names.
|
||||
/// </summary>
|
||||
public virtual string HostNames { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the value indicating whether to force the HTTPS connection or not.
|
||||
/// </summary>
|
||||
public virtual bool ForceHttps { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the value indicating whether to force the HTTP connection or not.
|
||||
/// </summary>
|
||||
public virtual bool ForceHttp { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the value indicating whether to hide the Swagger UI page or not.
|
||||
/// </summary>
|
||||
public virtual bool HideSwaggerUI { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the value indicating whether to hide the document pages or not.
|
||||
/// Gets or sets the value indicating whether to hide the OpenAPI document pages or not.
|
||||
/// </summary>
|
||||
public virtual bool HideDocument { get; set; }
|
||||
|
||||
|
@ -23,16 +60,11 @@ namespace Microsoft.Azure.WebJobs.Extensions.OpenApi.Configurations
|
|||
/// <summary>
|
||||
/// Gets or sets the <see cref="OpenApiAuthLevelSettings"/> object.
|
||||
/// </summary>
|
||||
public virtual OpenApiAuthLevelSettings AuthLevel { get; set; }
|
||||
public virtual OpenApiAuthLevelSettings AuthLevel { get; set; } = new OpenApiAuthLevelSettings();
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the backend URL for Azure Functions Proxy.
|
||||
/// </summary>
|
||||
public virtual string BackendProxyUrl { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the comma delimited host names.
|
||||
/// </summary>
|
||||
public virtual string HostNames { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,332 +1,333 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using Microsoft.Azure.WebJobs.Extensions.OpenApi.Core;
|
||||
using Microsoft.Azure.WebJobs.Extensions.OpenApi.Core.Abstractions;
|
||||
using Microsoft.Azure.WebJobs.Extensions.OpenApi.Core.Configurations;
|
||||
using Microsoft.Azure.WebJobs.Extensions.OpenApi.Core.Enums;
|
||||
using Microsoft.Azure.WebJobs.Extensions.OpenApi.Core.Extensions;
|
||||
using Microsoft.Azure.WebJobs.Extensions.OpenApi.Core.Filters;
|
||||
using Microsoft.Azure.WebJobs.Extensions.OpenApi.Core.Resolvers;
|
||||
using Microsoft.Azure.WebJobs.Extensions.OpenApi.Core.Visitors;
|
||||
using Microsoft.OpenApi;
|
||||
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Serialization;
|
||||
|
||||
namespace Microsoft.Azure.WebJobs.Extensions.OpenApi
|
||||
{
|
||||
/// <summary>
|
||||
/// This represents the context entity for <see cref="OpenApiTriggerFunctionProvider"/>.
|
||||
/// </summary>
|
||||
[SuppressMessage("Design", "CA1823", Justification = "")]
|
||||
[SuppressMessage("Design", "MEN002", Justification = "")]
|
||||
[SuppressMessage("Design", "SA1206", Justification = "")]
|
||||
[SuppressMessage("Layout Rules", "SA1311", Justification = "")]
|
||||
[SuppressMessage("Layout Rules", "SA1500", Justification = "")]
|
||||
[SuppressMessage("Readability Rules", "SX1101", Justification = "")]
|
||||
public class OpenApiHttpTriggerContext : IOpenApiHttpTriggerContext
|
||||
{
|
||||
private string _dllpath;
|
||||
private Assembly _appAssembly;
|
||||
private IOpenApiConfigurationOptions _configOptions;
|
||||
private IOpenApiCustomUIOptions _uiOptions;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="OpenApiHttpTriggerContext"/> class.
|
||||
/// </summary>
|
||||
public OpenApiHttpTriggerContext(IOpenApiConfigurationOptions configOptions = null)
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using Microsoft.Azure.WebJobs.Extensions.OpenApi.Core;
|
||||
using Microsoft.Azure.WebJobs.Extensions.OpenApi.Core.Abstractions;
|
||||
using Microsoft.Azure.WebJobs.Extensions.OpenApi.Core.Configurations;
|
||||
using Microsoft.Azure.WebJobs.Extensions.OpenApi.Core.Enums;
|
||||
using Microsoft.Azure.WebJobs.Extensions.OpenApi.Core.Extensions;
|
||||
using Microsoft.Azure.WebJobs.Extensions.OpenApi.Core.Filters;
|
||||
using Microsoft.Azure.WebJobs.Extensions.OpenApi.Core.Resolvers;
|
||||
using Microsoft.Azure.WebJobs.Extensions.OpenApi.Core.Visitors;
|
||||
using Microsoft.OpenApi;
|
||||
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Serialization;
|
||||
|
||||
namespace Microsoft.Azure.WebJobs.Extensions.OpenApi
|
||||
{
|
||||
/// <summary>
|
||||
/// This represents the context entity for <see cref="OpenApiTriggerFunctionProvider"/>.
|
||||
/// </summary>
|
||||
[SuppressMessage("Design", "CA1823", Justification = "")]
|
||||
[SuppressMessage("Design", "MEN002", Justification = "")]
|
||||
[SuppressMessage("Design", "SA1206", Justification = "")]
|
||||
[SuppressMessage("Layout Rules", "SA1311", Justification = "")]
|
||||
[SuppressMessage("Layout Rules", "SA1500", Justification = "")]
|
||||
[SuppressMessage("Readability Rules", "SX1101", Justification = "")]
|
||||
public class OpenApiHttpTriggerContext : IOpenApiHttpTriggerContext
|
||||
{
|
||||
private string _dllpath;
|
||||
private Assembly _appAssembly;
|
||||
private IOpenApiConfigurationOptions _configOptions;
|
||||
private IOpenApiCustomUIOptions _uiOptions;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="OpenApiHttpTriggerContext"/> class.
|
||||
/// </summary>
|
||||
/// <param name="configOptions"><see cref="IOpenApiConfigurationOptions"/> instance.</param>
|
||||
public OpenApiHttpTriggerContext(IOpenApiConfigurationOptions configOptions = null)
|
||||
{
|
||||
this._configOptions = configOptions;
|
||||
this.PackageAssembly = this.GetAssembly<ISwaggerUI>();
|
||||
|
||||
var host = HostJsonResolver.Resolve();
|
||||
this.HttpSettings = host.GetHttpSettings();
|
||||
|
||||
var filter = new RouteConstraintFilter();
|
||||
var acceptor = new OpenApiSchemaAcceptor();
|
||||
var helper = new DocumentHelper(filter, acceptor);
|
||||
|
||||
this.Document = new Document(helper);
|
||||
this.SwaggerUI = new SwaggerUI();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual Assembly ApplicationAssembly
|
||||
{
|
||||
get
|
||||
{
|
||||
if (this._appAssembly.IsNullOrDefault())
|
||||
{
|
||||
this._appAssembly = this.GetAssembly(this._dllpath);
|
||||
}
|
||||
|
||||
return this._appAssembly;
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual Assembly PackageAssembly { get; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual IOpenApiConfigurationOptions OpenApiConfigurationOptions
|
||||
{
|
||||
get
|
||||
{
|
||||
if (this._configOptions.IsNullOrDefault())
|
||||
{
|
||||
this._configOptions = OpenApiConfigurationResolver.Resolve(this.ApplicationAssembly);
|
||||
}
|
||||
|
||||
return this._configOptions;
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual IOpenApiCustomUIOptions OpenApiCustomUIOptions
|
||||
{
|
||||
get
|
||||
{
|
||||
if (this._uiOptions.IsNullOrDefault())
|
||||
{
|
||||
this._uiOptions = OpenApiCustomUIResolver.Resolve(this.ApplicationAssembly);
|
||||
}
|
||||
|
||||
return this._uiOptions;
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual HttpSettings HttpSettings { get; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual IDocument Document { get; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual ISwaggerUI SwaggerUI { get; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual NamingStrategy NamingStrategy { get; } = new CamelCaseNamingStrategy();
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual bool IsDevelopment { get; } = Environment.GetEnvironmentVariable("AZURE_FUNCTIONS_ENVIRONMENT") == "Development";
|
||||
|
||||
/// <inheritdoc />
|
||||
[Obsolete("This method is obsolete. Use GetAssembly<T>() or GetAssembly(object) instead", error: true)]
|
||||
public virtual Assembly GetExecutingAssembly()
|
||||
{
|
||||
var assembly = Assembly.GetExecutingAssembly();
|
||||
|
||||
return assembly;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual async Task<IOpenApiHttpTriggerContext> SetApplicationAssemblyAsync(string functionAppDirectory, bool appendBin = true)
|
||||
{
|
||||
if (!this._dllpath.IsNullOrWhiteSpace())
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
var runtimepath = this.GetRuntimePath(functionAppDirectory, appendBin);
|
||||
var runtimename = await this.GetRuntimeFilenameAsync(functionAppDirectory);
|
||||
var dllpath = $"{runtimepath}{Path.DirectorySeparatorChar}{runtimename}";
|
||||
|
||||
this._dllpath = dllpath;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual async Task<OpenApiAuthorizationResult> AuthorizeAsync(IHttpRequestDataObject req)
|
||||
{
|
||||
var result = default(OpenApiAuthorizationResult);
|
||||
var type = this.ApplicationAssembly
|
||||
.GetLoadableTypes()
|
||||
.SingleOrDefault(p => p.HasInterface<IOpenApiHttpTriggerAuthorization>());
|
||||
if (type.IsNullOrDefault())
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
var auth = Activator.CreateInstance(type) as IOpenApiHttpTriggerAuthorization;
|
||||
result = await auth.AuthorizeAsync(req).ConfigureAwait(false);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual VisitorCollection GetVisitorCollection()
|
||||
{
|
||||
var collection = VisitorCollection.CreateInstance();
|
||||
|
||||
return collection;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual OpenApiVersionType GetOpenApiVersionType(string version = "v2")
|
||||
{
|
||||
var parsed = Enum.TryParse(version, true, out OpenApiVersionType output)
|
||||
? output
|
||||
: throw new InvalidOperationException("Invalid OpenAPI version");
|
||||
|
||||
return parsed;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual OpenApiSpecVersion GetOpenApiSpecVersion(string version = "v2")
|
||||
{
|
||||
var parsed = Enum.TryParse(version, true, out OpenApiVersionType output)
|
||||
? output
|
||||
: throw new InvalidOperationException("Invalid OpenAPI version");
|
||||
|
||||
return this.GetOpenApiSpecVersion(parsed);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual OpenApiSpecVersion GetOpenApiSpecVersion(OpenApiVersionType version = OpenApiVersionType.V2)
|
||||
{
|
||||
return version.ToOpenApiSpecVersion();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual OpenApiFormat GetOpenApiFormat(string format = "json")
|
||||
{
|
||||
if (format.Equals("yml", StringComparison.InvariantCultureIgnoreCase))
|
||||
{
|
||||
format = "yaml";
|
||||
}
|
||||
|
||||
var parsed = Enum.TryParse(format, true, out OpenApiFormatType output)
|
||||
? output
|
||||
: throw new InvalidOperationException("Invalid OpenAPI format");
|
||||
|
||||
return this.GetOpenApiFormat(parsed);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual OpenApiFormat GetOpenApiFormat(OpenApiFormatType format = OpenApiFormatType.Json)
|
||||
{
|
||||
return format.ToOpenApiFormat();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual OpenApiAuthLevelType GetDocumentAuthLevel(string key = "OpenApi__AuthLevel__Document")
|
||||
{
|
||||
var value = Environment.GetEnvironmentVariable(key);
|
||||
var parsed = Enum.TryParse<OpenApiAuthLevelType>(value, out var result) ? result : OpenApiAuthLevelType.Anonymous;
|
||||
|
||||
return parsed;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual OpenApiAuthLevelType GetUIAuthLevel(string key = "OpenApi__AuthLevel__UI")
|
||||
{
|
||||
var value = Environment.GetEnvironmentVariable(key);
|
||||
var parsed = Enum.TryParse<OpenApiAuthLevelType>(value, out var result) ? result : OpenApiAuthLevelType.Anonymous;
|
||||
|
||||
return parsed;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual string GetSwaggerAuthKey(string key = "OpenApi__ApiKey")
|
||||
{
|
||||
var value = Environment.GetEnvironmentVariable(key);
|
||||
|
||||
return value ?? string.Empty;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual DocumentFilterCollection GetDocumentFilterCollection()
|
||||
{
|
||||
var collection = new DocumentFilterCollection(this.OpenApiConfigurationOptions.DocumentFilters);
|
||||
|
||||
return collection;
|
||||
}
|
||||
|
||||
private string GetRuntimePath(string functionAppDirectory, bool appendBin)
|
||||
{
|
||||
var path = functionAppDirectory;
|
||||
if (appendBin)
|
||||
{
|
||||
path += $"{Path.DirectorySeparatorChar}bin";
|
||||
}
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
// **NOTE**:
|
||||
// This method relies on the dependency manifest file to find the function app runtime dll file.
|
||||
// It can be either <your_runtime>.deps.json or function.deps.json. In most cases, at least the
|
||||
// function.deps.json should exist, but in case no manifest exists, it will throw the exception.
|
||||
// In case there are multiple .deps.json files, the root project will be picked, based on the
|
||||
// dependencies mentioned in the .deps.json files.
|
||||
private async Task<string> GetRuntimeFilenameAsync(string functionAppDirectory)
|
||||
{
|
||||
var files = Directory.GetFiles(functionAppDirectory, "*.deps.json", SearchOption.AllDirectories);
|
||||
if (!files.Any())
|
||||
{
|
||||
throw new InvalidOperationException("Invalid function app directory");
|
||||
}
|
||||
|
||||
var dependencyManifests = new List<DependencyManifest>();
|
||||
foreach (var file in files)
|
||||
{
|
||||
dependencyManifests.Add(await GetDependencyManifestAsync(file));
|
||||
}
|
||||
|
||||
var runtimes = dependencyManifests
|
||||
.Select(manifest => manifest.Targets[manifest.RuntimeTarget.Name].First())
|
||||
.Where(manifest => manifest.Value.Dependencies != null)
|
||||
.Select(target => new
|
||||
{
|
||||
Name = target.Key.Split('/').First(),
|
||||
FileName = target.Value.Runtime.First().Key,
|
||||
Dependencies = target.Value.Dependencies.Keys
|
||||
});
|
||||
|
||||
var referencedRuntimes = runtimes.SelectMany(d => d.Dependencies);
|
||||
return runtimes.FirstOrDefault(r => !referencedRuntimes.Contains(r.Name))?.FileName;
|
||||
}
|
||||
|
||||
private static async Task<DependencyManifest> GetDependencyManifestAsync(string file)
|
||||
{
|
||||
var serialised = default(string);
|
||||
using (var reader = File.OpenText(file))
|
||||
{
|
||||
serialised = await reader.ReadToEndAsync();
|
||||
}
|
||||
|
||||
return JsonConvert.DeserializeObject<DependencyManifest>(serialised);
|
||||
}
|
||||
|
||||
private Assembly GetAssembly(object instance)
|
||||
{
|
||||
return this.GetAssembly(instance.GetType());
|
||||
}
|
||||
|
||||
private Assembly GetAssembly<T>()
|
||||
{
|
||||
return this.GetAssembly(typeof(T));
|
||||
}
|
||||
|
||||
private Assembly GetAssembly(Type type)
|
||||
{
|
||||
var assembly = type.Assembly;
|
||||
|
||||
return assembly;
|
||||
}
|
||||
|
||||
private Assembly GetAssembly(string dllpath)
|
||||
{
|
||||
var assembly = Assembly.LoadFile(dllpath);
|
||||
|
||||
return assembly;
|
||||
}
|
||||
}
|
||||
}
|
||||
this.PackageAssembly = this.GetAssembly<ISwaggerUI>();
|
||||
|
||||
var host = HostJsonResolver.Resolve();
|
||||
this.HttpSettings = host.GetHttpSettings();
|
||||
|
||||
var filter = new RouteConstraintFilter();
|
||||
var acceptor = new OpenApiSchemaAcceptor();
|
||||
var helper = new DocumentHelper(filter, acceptor);
|
||||
|
||||
this.Document = new Document(helper);
|
||||
this.SwaggerUI = new SwaggerUI();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual Assembly ApplicationAssembly
|
||||
{
|
||||
get
|
||||
{
|
||||
if (this._appAssembly.IsNullOrDefault())
|
||||
{
|
||||
this._appAssembly = this.GetAssembly(this._dllpath);
|
||||
}
|
||||
|
||||
return this._appAssembly;
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual Assembly PackageAssembly { get; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual IOpenApiConfigurationOptions OpenApiConfigurationOptions
|
||||
{
|
||||
get
|
||||
{
|
||||
if (this._configOptions.IsNullOrDefault())
|
||||
{
|
||||
this._configOptions = OpenApiConfigurationResolver.Resolve(this.ApplicationAssembly);
|
||||
}
|
||||
|
||||
return this._configOptions;
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual IOpenApiCustomUIOptions OpenApiCustomUIOptions
|
||||
{
|
||||
get
|
||||
{
|
||||
if (this._uiOptions.IsNullOrDefault())
|
||||
{
|
||||
this._uiOptions = OpenApiCustomUIResolver.Resolve(this.ApplicationAssembly);
|
||||
}
|
||||
|
||||
return this._uiOptions;
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual HttpSettings HttpSettings { get; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual IDocument Document { get; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual ISwaggerUI SwaggerUI { get; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual NamingStrategy NamingStrategy { get; } = new CamelCaseNamingStrategy();
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual bool IsDevelopment { get; } = Environment.GetEnvironmentVariable("AZURE_FUNCTIONS_ENVIRONMENT") == "Development";
|
||||
|
||||
/// <inheritdoc />
|
||||
[Obsolete("This method is obsolete. Use GetAssembly<T>() or GetAssembly(object) instead", error: true)]
|
||||
public virtual Assembly GetExecutingAssembly()
|
||||
{
|
||||
var assembly = Assembly.GetExecutingAssembly();
|
||||
|
||||
return assembly;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual async Task<IOpenApiHttpTriggerContext> SetApplicationAssemblyAsync(string functionAppDirectory, bool appendBin = true)
|
||||
{
|
||||
if (!this._dllpath.IsNullOrWhiteSpace())
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
var runtimepath = this.GetRuntimePath(functionAppDirectory, appendBin);
|
||||
var runtimename = await this.GetRuntimeFilenameAsync(functionAppDirectory);
|
||||
var dllpath = $"{runtimepath}{Path.DirectorySeparatorChar}{runtimename}";
|
||||
|
||||
this._dllpath = dllpath;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual async Task<OpenApiAuthorizationResult> AuthorizeAsync(IHttpRequestDataObject req)
|
||||
{
|
||||
var result = default(OpenApiAuthorizationResult);
|
||||
var type = this.ApplicationAssembly
|
||||
.GetLoadableTypes()
|
||||
.SingleOrDefault(p => p.HasInterface<IOpenApiHttpTriggerAuthorization>());
|
||||
if (type.IsNullOrDefault())
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
var auth = Activator.CreateInstance(type) as IOpenApiHttpTriggerAuthorization;
|
||||
result = await auth.AuthorizeAsync(req).ConfigureAwait(false);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual VisitorCollection GetVisitorCollection()
|
||||
{
|
||||
var collection = VisitorCollection.CreateInstance();
|
||||
|
||||
return collection;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual OpenApiVersionType GetOpenApiVersionType(string version = "v2")
|
||||
{
|
||||
var parsed = Enum.TryParse(version, true, out OpenApiVersionType output)
|
||||
? output
|
||||
: throw new InvalidOperationException("Invalid OpenAPI version");
|
||||
|
||||
return parsed;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual OpenApiSpecVersion GetOpenApiSpecVersion(string version = "v2")
|
||||
{
|
||||
var parsed = Enum.TryParse(version, true, out OpenApiVersionType output)
|
||||
? output
|
||||
: throw new InvalidOperationException("Invalid OpenAPI version");
|
||||
|
||||
return this.GetOpenApiSpecVersion(parsed);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual OpenApiSpecVersion GetOpenApiSpecVersion(OpenApiVersionType version = OpenApiVersionType.V2)
|
||||
{
|
||||
return version.ToOpenApiSpecVersion();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual OpenApiFormat GetOpenApiFormat(string format = "json")
|
||||
{
|
||||
if (format.Equals("yml", StringComparison.InvariantCultureIgnoreCase))
|
||||
{
|
||||
format = "yaml";
|
||||
}
|
||||
|
||||
var parsed = Enum.TryParse(format, true, out OpenApiFormatType output)
|
||||
? output
|
||||
: throw new InvalidOperationException("Invalid OpenAPI format");
|
||||
|
||||
return this.GetOpenApiFormat(parsed);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual OpenApiFormat GetOpenApiFormat(OpenApiFormatType format = OpenApiFormatType.Json)
|
||||
{
|
||||
return format.ToOpenApiFormat();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual OpenApiAuthLevelType GetDocumentAuthLevel(string key = "OpenApi__AuthLevel__Document")
|
||||
{
|
||||
var value = Environment.GetEnvironmentVariable(key);
|
||||
var parsed = Enum.TryParse<OpenApiAuthLevelType>(value, out var result) ? result : OpenApiAuthLevelType.Anonymous;
|
||||
|
||||
return parsed;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual OpenApiAuthLevelType GetUIAuthLevel(string key = "OpenApi__AuthLevel__UI")
|
||||
{
|
||||
var value = Environment.GetEnvironmentVariable(key);
|
||||
var parsed = Enum.TryParse<OpenApiAuthLevelType>(value, out var result) ? result : OpenApiAuthLevelType.Anonymous;
|
||||
|
||||
return parsed;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual string GetSwaggerAuthKey(string key = "OpenApi__ApiKey")
|
||||
{
|
||||
var value = Environment.GetEnvironmentVariable(key);
|
||||
|
||||
return value ?? string.Empty;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual DocumentFilterCollection GetDocumentFilterCollection()
|
||||
{
|
||||
var collection = new DocumentFilterCollection(this.OpenApiConfigurationOptions.DocumentFilters);
|
||||
|
||||
return collection;
|
||||
}
|
||||
|
||||
private string GetRuntimePath(string functionAppDirectory, bool appendBin)
|
||||
{
|
||||
var path = functionAppDirectory;
|
||||
if (appendBin)
|
||||
{
|
||||
path += $"{Path.DirectorySeparatorChar}bin";
|
||||
}
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
// **NOTE**:
|
||||
// This method relies on the dependency manifest file to find the function app runtime dll file.
|
||||
// It can be either <your_runtime>.deps.json or function.deps.json. In most cases, at least the
|
||||
// function.deps.json should exist, but in case no manifest exists, it will throw the exception.
|
||||
// In case there are multiple .deps.json files, the root project will be picked, based on the
|
||||
// dependencies mentioned in the .deps.json files.
|
||||
private async Task<string> GetRuntimeFilenameAsync(string functionAppDirectory)
|
||||
{
|
||||
var files = Directory.GetFiles(functionAppDirectory, "*.deps.json", SearchOption.AllDirectories);
|
||||
if (!files.Any())
|
||||
{
|
||||
throw new InvalidOperationException("Invalid function app directory");
|
||||
}
|
||||
|
||||
var dependencyManifests = new List<DependencyManifest>();
|
||||
foreach (var file in files)
|
||||
{
|
||||
dependencyManifests.Add(await GetDependencyManifestAsync(file));
|
||||
}
|
||||
|
||||
var runtimes = dependencyManifests
|
||||
.Select(manifest => manifest.Targets[manifest.RuntimeTarget.Name].First())
|
||||
.Where(manifest => manifest.Value.Dependencies != null)
|
||||
.Select(target => new
|
||||
{
|
||||
Name = target.Key.Split('/').First(),
|
||||
FileName = target.Value.Runtime.First().Key,
|
||||
Dependencies = target.Value.Dependencies.Keys
|
||||
});
|
||||
|
||||
var referencedRuntimes = runtimes.SelectMany(d => d.Dependencies);
|
||||
return runtimes.FirstOrDefault(r => !referencedRuntimes.Contains(r.Name))?.FileName;
|
||||
}
|
||||
|
||||
private static async Task<DependencyManifest> GetDependencyManifestAsync(string file)
|
||||
{
|
||||
var serialised = default(string);
|
||||
using (var reader = File.OpenText(file))
|
||||
{
|
||||
serialised = await reader.ReadToEndAsync();
|
||||
}
|
||||
|
||||
return JsonConvert.DeserializeObject<DependencyManifest>(serialised);
|
||||
}
|
||||
|
||||
private Assembly GetAssembly(object instance)
|
||||
{
|
||||
return this.GetAssembly(instance.GetType());
|
||||
}
|
||||
|
||||
private Assembly GetAssembly<T>()
|
||||
{
|
||||
return this.GetAssembly(typeof(T));
|
||||
}
|
||||
|
||||
private Assembly GetAssembly(Type type)
|
||||
{
|
||||
var assembly = type.Assembly;
|
||||
|
||||
return assembly;
|
||||
}
|
||||
|
||||
private Assembly GetAssembly(string dllpath)
|
||||
{
|
||||
var assembly = Assembly.LoadFile(dllpath);
|
||||
|
||||
return assembly;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ using System.Threading.Tasks;
|
|||
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.Azure.WebJobs.Extensions.OpenApi.Attributes;
|
||||
using Microsoft.Azure.WebJobs.Extensions.OpenApi.Core.Attributes;
|
||||
using Microsoft.Azure.WebJobs.Extensions.OpenApi.Core.Extensions;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
@ -23,13 +24,16 @@ namespace Microsoft.Azure.WebJobs.Extensions.OpenApi
|
|||
/// <summary>
|
||||
/// Invokes the HTTP trigger endpoint to get OpenAPI document.
|
||||
/// </summary>
|
||||
/// <param name="openApiContext"><see cref="OpenApiHttpTriggerContext"/> instance.</param>
|
||||
/// <param name="req"><see cref="HttpRequest"/> instance.</param>
|
||||
/// <param name="extension">File extension representing the document format. This MUST be either "json" or "yaml".</param>
|
||||
/// <param name="ctx"><see cref="ExecutionContext"/> instance.</param>
|
||||
/// <param name="log"><see cref="ILogger"/> instance.</param>
|
||||
/// <returns>OpenAPI document in a format of either JSON or YAML.</returns>
|
||||
[OpenApiIgnore]
|
||||
public static async Task<IActionResult> RenderSwaggerDocument([OpenApiHttpTriggerContext] OpenApiHttpTriggerContext context, HttpRequest req, string extension, ExecutionContext ctx, ILogger log)
|
||||
public static async Task<IActionResult> RenderSwaggerDocument(
|
||||
[OpenApiHttpTriggerContext] OpenApiHttpTriggerContext openApiContext,
|
||||
HttpRequest req, string extension, ExecutionContext ctx, ILogger log)
|
||||
{
|
||||
log.LogInformation($"swagger.{extension} was requested.");
|
||||
|
||||
|
@ -38,7 +42,7 @@ namespace Microsoft.Azure.WebJobs.Extensions.OpenApi
|
|||
var content = default(ContentResult);
|
||||
try
|
||||
{
|
||||
var auth = await context.SetApplicationAssemblyAsync(ctx.FunctionAppDirectory)
|
||||
var auth = await openApiContext.SetApplicationAssemblyAsync(ctx.FunctionAppDirectory)
|
||||
.AuthorizeAsync(request)
|
||||
.ConfigureAwait(false);
|
||||
if (!auth.IsNullOrDefault())
|
||||
|
@ -53,21 +57,21 @@ namespace Microsoft.Azure.WebJobs.Extensions.OpenApi
|
|||
return content;
|
||||
}
|
||||
|
||||
result = await context.Document
|
||||
result = await openApiContext.Document
|
||||
.InitialiseDocument()
|
||||
.AddMetadata(context.OpenApiConfigurationOptions.Info)
|
||||
.AddServer(request, context.HttpSettings.RoutePrefix, context.OpenApiConfigurationOptions)
|
||||
.AddNamingStrategy(context.NamingStrategy)
|
||||
.AddVisitors(context.GetVisitorCollection())
|
||||
.Build(context.ApplicationAssembly, context.OpenApiConfigurationOptions.OpenApiVersion)
|
||||
.ApplyDocumentFilters(context.GetDocumentFilterCollection())
|
||||
.RenderAsync(context.GetOpenApiSpecVersion(context.OpenApiConfigurationOptions.OpenApiVersion), context.GetOpenApiFormat(extension))
|
||||
.AddMetadata(openApiContext.OpenApiConfigurationOptions.Info)
|
||||
.AddServer(request, openApiContext.HttpSettings.RoutePrefix, openApiContext.OpenApiConfigurationOptions)
|
||||
.AddNamingStrategy(openApiContext.NamingStrategy)
|
||||
.AddVisitors(openApiContext.GetVisitorCollection())
|
||||
.Build(openApiContext.ApplicationAssembly, openApiContext.OpenApiConfigurationOptions.OpenApiVersion)
|
||||
.ApplyDocumentFilters(openApiContext.GetDocumentFilterCollection())
|
||||
.RenderAsync(openApiContext.GetOpenApiSpecVersion(openApiContext.OpenApiConfigurationOptions.OpenApiVersion), openApiContext.GetOpenApiFormat(extension))
|
||||
.ConfigureAwait(false);
|
||||
|
||||
content = new ContentResult()
|
||||
{
|
||||
Content = result,
|
||||
ContentType = context.GetOpenApiFormat(extension).GetContentType(),
|
||||
ContentType = openApiContext.GetOpenApiFormat(extension).GetContentType(),
|
||||
StatusCode = (int)HttpStatusCode.OK,
|
||||
};
|
||||
}
|
||||
|
@ -76,7 +80,7 @@ namespace Microsoft.Azure.WebJobs.Extensions.OpenApi
|
|||
log.LogError(ex.Message);
|
||||
|
||||
result = ex.Message;
|
||||
if (context.IsDevelopment)
|
||||
if (openApiContext.IsDevelopment)
|
||||
{
|
||||
result += "\r\n\r\n";
|
||||
result += ex.StackTrace;
|
||||
|
@ -95,6 +99,7 @@ namespace Microsoft.Azure.WebJobs.Extensions.OpenApi
|
|||
/// <summary>
|
||||
/// Invokes the HTTP trigger endpoint to get OpenAPI document.
|
||||
/// </summary>
|
||||
/// <param name="openApiContext"><see cref="OpenApiHttpTriggerContext"/> instance.</param>
|
||||
/// <param name="req"><see cref="HttpRequest"/> instance.</param>
|
||||
/// <param name="version">OpenAPI document spec version. This MUST be either "v2" or "v3".</param>
|
||||
/// <param name="extension">File extension representing the document format. This MUST be either "json" or "yaml".</param>
|
||||
|
@ -102,7 +107,9 @@ namespace Microsoft.Azure.WebJobs.Extensions.OpenApi
|
|||
/// <param name="log"><see cref="ILogger"/> instance.</param>
|
||||
/// <returns>OpenAPI document in a format of either JSON or YAML.</returns>
|
||||
[OpenApiIgnore]
|
||||
public static async Task<IActionResult> RenderOpenApiDocument([OpenApiHttpTriggerContext] OpenApiHttpTriggerContext context, HttpRequest req, string version, string extension, ExecutionContext ctx, ILogger log)
|
||||
public static async Task<IActionResult> RenderOpenApiDocument(
|
||||
[OpenApiHttpTriggerContext] OpenApiHttpTriggerContext openApiContext,
|
||||
HttpRequest req, string version, string extension, ExecutionContext ctx, ILogger log)
|
||||
{
|
||||
log.LogInformation($"{version}.{extension} was requested.");
|
||||
|
||||
|
@ -111,7 +118,7 @@ namespace Microsoft.Azure.WebJobs.Extensions.OpenApi
|
|||
var content = default(ContentResult);
|
||||
try
|
||||
{
|
||||
var auth = await context.SetApplicationAssemblyAsync(ctx.FunctionAppDirectory)
|
||||
var auth = await openApiContext.SetApplicationAssemblyAsync(ctx.FunctionAppDirectory)
|
||||
.AuthorizeAsync(request)
|
||||
.ConfigureAwait(false);
|
||||
if (!auth.IsNullOrDefault())
|
||||
|
@ -126,21 +133,21 @@ namespace Microsoft.Azure.WebJobs.Extensions.OpenApi
|
|||
return content;
|
||||
}
|
||||
|
||||
result = await context.Document
|
||||
result = await openApiContext.Document
|
||||
.InitialiseDocument()
|
||||
.AddMetadata(context.OpenApiConfigurationOptions.Info)
|
||||
.AddServer(new HttpRequestObject(req), context.HttpSettings.RoutePrefix, context.OpenApiConfigurationOptions)
|
||||
.AddNamingStrategy(context.NamingStrategy)
|
||||
.AddVisitors(context.GetVisitorCollection())
|
||||
.Build(context.ApplicationAssembly, context.GetOpenApiVersionType(version))
|
||||
.ApplyDocumentFilters(context.GetDocumentFilterCollection())
|
||||
.RenderAsync(context.GetOpenApiSpecVersion(version), context.GetOpenApiFormat(extension))
|
||||
.AddMetadata(openApiContext.OpenApiConfigurationOptions.Info)
|
||||
.AddServer(new HttpRequestObject(req), openApiContext.HttpSettings.RoutePrefix, openApiContext.OpenApiConfigurationOptions)
|
||||
.AddNamingStrategy(openApiContext.NamingStrategy)
|
||||
.AddVisitors(openApiContext.GetVisitorCollection())
|
||||
.Build(openApiContext.ApplicationAssembly, openApiContext.GetOpenApiVersionType(version))
|
||||
.ApplyDocumentFilters(openApiContext.GetDocumentFilterCollection())
|
||||
.RenderAsync(openApiContext.GetOpenApiSpecVersion(version), openApiContext.GetOpenApiFormat(extension))
|
||||
.ConfigureAwait(false);
|
||||
|
||||
content = new ContentResult()
|
||||
{
|
||||
Content = result,
|
||||
ContentType = context.GetOpenApiFormat(extension).GetContentType(),
|
||||
ContentType = openApiContext.GetOpenApiFormat(extension).GetContentType(),
|
||||
StatusCode = (int)HttpStatusCode.OK,
|
||||
};
|
||||
}
|
||||
|
@ -149,7 +156,7 @@ namespace Microsoft.Azure.WebJobs.Extensions.OpenApi
|
|||
log.LogError(ex.Message);
|
||||
|
||||
result = ex.Message;
|
||||
if (context.IsDevelopment)
|
||||
if (openApiContext.IsDevelopment)
|
||||
{
|
||||
result += "\r\n\r\n";
|
||||
result += ex.StackTrace;
|
||||
|
@ -168,12 +175,15 @@ namespace Microsoft.Azure.WebJobs.Extensions.OpenApi
|
|||
/// <summary>
|
||||
/// Invokes the HTTP trigger endpoint to render Swagger UI in HTML.
|
||||
/// </summary>
|
||||
/// <param name="openApiContext"><see cref="OpenApiHttpTriggerContext"/> instance.</param>
|
||||
/// <param name="req"><see cref="HttpRequest"/> instance.</param>
|
||||
/// <param name="ctx"><see cref="ExecutionContext"/> instance.</param>
|
||||
/// <param name="log"><see cref="ILogger"/> instance.</param>
|
||||
/// <returns>Swagger UI in HTML.</returns>
|
||||
[OpenApiIgnore]
|
||||
public static async Task<IActionResult> RenderSwaggerUI([OpenApiHttpTriggerContext] OpenApiHttpTriggerContext context, HttpRequest req, ExecutionContext ctx, ILogger log)
|
||||
public static async Task<IActionResult> RenderSwaggerUI(
|
||||
[OpenApiHttpTriggerContext] OpenApiHttpTriggerContext openApiContext,
|
||||
HttpRequest req, ExecutionContext ctx, ILogger log)
|
||||
{
|
||||
log.LogInformation("SwaggerUI page was requested.");
|
||||
|
||||
|
@ -182,7 +192,7 @@ namespace Microsoft.Azure.WebJobs.Extensions.OpenApi
|
|||
var content = default(ContentResult);
|
||||
try
|
||||
{
|
||||
var auth = await context.SetApplicationAssemblyAsync(ctx.FunctionAppDirectory)
|
||||
var auth = await openApiContext.SetApplicationAssemblyAsync(ctx.FunctionAppDirectory)
|
||||
.AuthorizeAsync(request)
|
||||
.ConfigureAwait(false);
|
||||
if (!auth.IsNullOrDefault())
|
||||
|
@ -197,11 +207,11 @@ namespace Microsoft.Azure.WebJobs.Extensions.OpenApi
|
|||
return content;
|
||||
}
|
||||
|
||||
result = await context.SwaggerUI
|
||||
.AddMetadata(context.OpenApiConfigurationOptions.Info)
|
||||
.AddServer(new HttpRequestObject(req), context.HttpSettings.RoutePrefix, context.OpenApiConfigurationOptions)
|
||||
.BuildAsync(context.PackageAssembly, context.OpenApiCustomUIOptions)
|
||||
.RenderAsync("swagger.json", context.GetDocumentAuthLevel(), context.GetSwaggerAuthKey())
|
||||
result = await openApiContext.SwaggerUI
|
||||
.AddMetadata(openApiContext.OpenApiConfigurationOptions.Info)
|
||||
.AddServer(new HttpRequestObject(req), openApiContext.HttpSettings.RoutePrefix, openApiContext.OpenApiConfigurationOptions)
|
||||
.BuildAsync(openApiContext.PackageAssembly, openApiContext.OpenApiCustomUIOptions)
|
||||
.RenderAsync("swagger.json", openApiContext.GetDocumentAuthLevel(), openApiContext.GetSwaggerAuthKey())
|
||||
.ConfigureAwait(false);
|
||||
|
||||
content = new ContentResult()
|
||||
|
@ -216,7 +226,7 @@ namespace Microsoft.Azure.WebJobs.Extensions.OpenApi
|
|||
log.LogError(ex.Message);
|
||||
|
||||
result = ex.Message;
|
||||
if (context.IsDevelopment)
|
||||
if (openApiContext.IsDevelopment)
|
||||
{
|
||||
result += "\r\n\r\n";
|
||||
result += ex.StackTrace;
|
||||
|
@ -235,12 +245,15 @@ namespace Microsoft.Azure.WebJobs.Extensions.OpenApi
|
|||
/// <summary>
|
||||
/// Invokes the HTTP trigger endpoint to render oauth2-redirect.html.
|
||||
/// </summary>
|
||||
/// <param name="openApiContext"><see cref="OpenApiHttpTriggerContext"/> instance.</param>
|
||||
/// <param name="req"><see cref="HttpRequest"/> instance.</param>
|
||||
/// <param name="ctx"><see cref="ExecutionContext"/> instance.</param>
|
||||
/// <param name="log"><see cref="ILogger"/> instance.</param>
|
||||
/// <returns>oauth2-redirect.html.</returns>
|
||||
[OpenApiIgnore]
|
||||
public static async Task<IActionResult> RenderOAuth2Redirect([OpenApiHttpTriggerContext] OpenApiHttpTriggerContext context, HttpRequest req, ExecutionContext ctx, ILogger log)
|
||||
public static async Task<IActionResult> RenderOAuth2Redirect(
|
||||
[OpenApiHttpTriggerContext] OpenApiHttpTriggerContext openApiContext,
|
||||
HttpRequest req, ExecutionContext ctx, ILogger log)
|
||||
{
|
||||
log.LogInformation("The oauth2-redirect.html page was requested.");
|
||||
|
||||
|
@ -249,13 +262,13 @@ namespace Microsoft.Azure.WebJobs.Extensions.OpenApi
|
|||
var content = default(ContentResult);
|
||||
try
|
||||
{
|
||||
await context.SetApplicationAssemblyAsync(ctx.FunctionAppDirectory)
|
||||
await openApiContext.SetApplicationAssemblyAsync(ctx.FunctionAppDirectory)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
result = await context.SwaggerUI
|
||||
.AddServer(request, context.HttpSettings.RoutePrefix, context.OpenApiConfigurationOptions)
|
||||
.BuildOAuth2RedirectAsync(context.PackageAssembly)
|
||||
.RenderOAuth2RedirectAsync("oauth2-redirect.html", context.GetDocumentAuthLevel(), context.GetSwaggerAuthKey())
|
||||
result = await openApiContext.SwaggerUI
|
||||
.AddServer(request, openApiContext.HttpSettings.RoutePrefix, openApiContext.OpenApiConfigurationOptions)
|
||||
.BuildOAuth2RedirectAsync(openApiContext.PackageAssembly)
|
||||
.RenderOAuth2RedirectAsync("oauth2-redirect.html", openApiContext.GetDocumentAuthLevel(), openApiContext.GetSwaggerAuthKey())
|
||||
.ConfigureAwait(false);
|
||||
|
||||
content = new ContentResult()
|
||||
|
@ -270,7 +283,7 @@ namespace Microsoft.Azure.WebJobs.Extensions.OpenApi
|
|||
log.LogError(ex.Message);
|
||||
|
||||
result = ex.Message;
|
||||
if (context.IsDevelopment)
|
||||
if (openApiContext.IsDevelopment)
|
||||
{
|
||||
result += "\r\n\r\n";
|
||||
result += ex.StackTrace;
|
||||
|
|
|
@ -1,18 +1,15 @@
|
|||
using Microsoft.Azure.WebJobs.Description;
|
||||
using Microsoft.Azure.WebJobs.Extensions.OpenApi;
|
||||
using Microsoft.Azure.WebJobs.Extensions.OpenApi.Attributes;
|
||||
using Microsoft.Azure.WebJobs.Extensions.OpenApi.Configurations;
|
||||
using Microsoft.Azure.WebJobs.Extensions.OpenApi.Configurations.AppSettings.Extensions;
|
||||
using Microsoft.Azure.WebJobs.Extensions.OpenApi.Configurations.AppSettings.Resolvers;
|
||||
using Microsoft.Azure.WebJobs.Extensions.OpenApi.Core.Abstractions;
|
||||
using Microsoft.Azure.WebJobs.Host.Bindings;
|
||||
using Microsoft.Azure.WebJobs.Host.Config;
|
||||
using Microsoft.Azure.WebJobs.Hosting;
|
||||
using Microsoft.Azure.WebJobs.Script.Description;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
[assembly: WebJobsStartup(typeof(OpenApiWebJobsStartup))]
|
||||
|
||||
namespace Microsoft.Azure.WebJobs.Extensions.OpenApi
|
||||
{
|
||||
/// <summary>
|
||||
|
@ -35,31 +32,4 @@ namespace Microsoft.Azure.WebJobs.Extensions.OpenApi
|
|||
builder.AddExtension<OpenApiHttpTriggerContextBinding>();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Binding for injecting the OpenApiTriggerContext during InProc function creation
|
||||
/// </summary>
|
||||
[Binding]
|
||||
[AttributeUsage(AttributeTargets.Parameter)]
|
||||
public class OpenApiHttpTriggerContextAttribute : Attribute
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Extension to register the [OpenApiHttpTriggerContext] attribute to inject IOpenApHttpTriggerContext
|
||||
/// </summary>
|
||||
[Extension(nameof(OpenApiHttpTriggerContextBinding))]
|
||||
public class OpenApiHttpTriggerContextBinding : IExtensionConfigProvider
|
||||
{
|
||||
public void Initialize(ExtensionConfigContext context)
|
||||
{
|
||||
var rule = context.AddBindingRule<OpenApiHttpTriggerContextAttribute>();
|
||||
rule.BindToInput((OpenApiHttpTriggerContextAttribute attr, ValueBindingContext vbContext) =>
|
||||
{
|
||||
var httpContext = vbContext.FunctionContext.CreateObjectInstance<OpenApiHttpTriggerContext>();
|
||||
|
||||
return Task.FromResult(httpContext);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
|
||||
using FluentAssertions;
|
||||
|
||||
|
@ -15,16 +14,23 @@ namespace Microsoft.Azure.WebJobs.Extensions.OpenApi.Core.Tests.Configurations
|
|||
[TestClass]
|
||||
public class DefaultOpenApiConfigurationOptionsTests
|
||||
{
|
||||
[TestMethod]
|
||||
public void Given_Type_When_Instantiated_Then_Properties_Should_Return_Value()
|
||||
[TestCleanup]
|
||||
public void Cleanup()
|
||||
{
|
||||
Environment.SetEnvironmentVariable("OpenApi__DocVersion", null);
|
||||
Environment.SetEnvironmentVariable("OpenApi__DocTitle", null);
|
||||
Environment.SetEnvironmentVariable("OpenApi__DocDescription", null);
|
||||
Environment.SetEnvironmentVariable("OpenApi__HostNames", null);
|
||||
Environment.SetEnvironmentVariable("OpenApi__Version", null);
|
||||
Environment.SetEnvironmentVariable("AZURE_FUNCTIONS_ENVIRONMENT", "Development");
|
||||
Environment.SetEnvironmentVariable("OpenApi__ForceHttp", null);
|
||||
Environment.SetEnvironmentVariable("OpenApi__ForceHttps", null);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Given_Type_When_Instantiated_Then_Properties_Should_Return_Value()
|
||||
{
|
||||
Environment.SetEnvironmentVariable("AZURE_FUNCTIONS_ENVIRONMENT", "Development");
|
||||
|
||||
var options = new DefaultOpenApiConfigurationOptions();
|
||||
|
||||
|
@ -68,6 +74,19 @@ namespace Microsoft.Azure.WebJobs.Extensions.OpenApi.Core.Tests.Configurations
|
|||
options.Info.Title.Should().Be(expected);
|
||||
}
|
||||
|
||||
[DataTestMethod]
|
||||
[DataRow(null, "This is the OpenAPI Document on Azure Functions")]
|
||||
[DataRow("", "This is the OpenAPI Document on Azure Functions")]
|
||||
[DataRow("hello world", "hello world")]
|
||||
public void Given_OpenApiDocDescription_When_Instantiated_Then_Property_Should_Return_Value(string description, string expected)
|
||||
{
|
||||
Environment.SetEnvironmentVariable("OpenApi__DocDescription", description);
|
||||
|
||||
var options = new DefaultOpenApiConfigurationOptions();
|
||||
|
||||
options.Info.Description.Should().Be(expected);
|
||||
}
|
||||
|
||||
[DataTestMethod]
|
||||
[DataRow(0, null)]
|
||||
[DataRow(0, "")]
|
||||
|
@ -145,10 +164,7 @@ namespace Microsoft.Azure.WebJobs.Extensions.OpenApi.Core.Tests.Configurations
|
|||
{
|
||||
Environment.SetEnvironmentVariable("OpenApi__DocVersion", version);
|
||||
|
||||
var options = new DefaultOpenApiConfigurationOptions();
|
||||
var method = typeof(DefaultOpenApiConfigurationOptions).GetMethod("GetOpenApiDocVersion", BindingFlags.NonPublic | BindingFlags.Static);
|
||||
|
||||
var result = method.Invoke(options, null);
|
||||
var result = DefaultOpenApiConfigurationOptions.GetOpenApiDocVersion();
|
||||
|
||||
result.Should().BeOfType<string>();
|
||||
(result as string).Should().Be(expected);
|
||||
|
@ -162,10 +178,21 @@ namespace Microsoft.Azure.WebJobs.Extensions.OpenApi.Core.Tests.Configurations
|
|||
{
|
||||
Environment.SetEnvironmentVariable("OpenApi__DocTitle", title);
|
||||
|
||||
var options = new DefaultOpenApiConfigurationOptions();
|
||||
var method = typeof(DefaultOpenApiConfigurationOptions).GetMethod("GetOpenApiDocTitle", BindingFlags.NonPublic | BindingFlags.Static);
|
||||
var result = DefaultOpenApiConfigurationOptions.GetOpenApiDocTitle();
|
||||
|
||||
var result = method.Invoke(options, null);
|
||||
result.Should().BeOfType<string>();
|
||||
(result as string).Should().Be(expected);
|
||||
}
|
||||
|
||||
[DataTestMethod]
|
||||
[DataRow(null, "This is the OpenAPI Document on Azure Functions")]
|
||||
[DataRow("", "This is the OpenAPI Document on Azure Functions")]
|
||||
[DataRow("hello world", "hello world")]
|
||||
public void Given_OpenApiDocDescription_When_Instantiated_Then_Property_Should_Return_Result(string description, string expected)
|
||||
{
|
||||
Environment.SetEnvironmentVariable("OpenApi__DocDescription", description);
|
||||
|
||||
var result = DefaultOpenApiConfigurationOptions.GetOpenApiDocDescription();
|
||||
|
||||
result.Should().BeOfType<string>();
|
||||
(result as string).Should().Be(expected);
|
||||
|
@ -180,10 +207,7 @@ namespace Microsoft.Azure.WebJobs.Extensions.OpenApi.Core.Tests.Configurations
|
|||
{
|
||||
Environment.SetEnvironmentVariable("OpenApi__HostNames", hostnames);
|
||||
|
||||
var options = new DefaultOpenApiConfigurationOptions();
|
||||
var method = typeof(DefaultOpenApiConfigurationOptions).GetMethod("GetHostNames", BindingFlags.NonPublic | BindingFlags.Static);
|
||||
|
||||
var result = method.Invoke(options, null);
|
||||
var result = DefaultOpenApiConfigurationOptions.GetHostNames();
|
||||
|
||||
result.Should().BeOfType<List<OpenApiServer>>();
|
||||
(result as List<OpenApiServer>).Should().HaveCount(expected);
|
||||
|
@ -200,13 +224,9 @@ namespace Microsoft.Azure.WebJobs.Extensions.OpenApi.Core.Tests.Configurations
|
|||
{
|
||||
Environment.SetEnvironmentVariable("OpenApi__Version", version);
|
||||
|
||||
var options = new DefaultOpenApiConfigurationOptions();
|
||||
var method = typeof(DefaultOpenApiConfigurationOptions).GetMethod("GetOpenApiVersion", BindingFlags.NonPublic | BindingFlags.Static);
|
||||
var result = DefaultOpenApiConfigurationOptions.GetOpenApiVersion();
|
||||
|
||||
var result = method.Invoke(options, null);
|
||||
|
||||
result.Should().BeOfType<OpenApiVersionType>();
|
||||
((OpenApiVersionType)result).Should().Be(expected);
|
||||
result.Should().Be(expected);
|
||||
}
|
||||
|
||||
[DataTestMethod]
|
||||
|
@ -216,13 +236,9 @@ namespace Microsoft.Azure.WebJobs.Extensions.OpenApi.Core.Tests.Configurations
|
|||
{
|
||||
Environment.SetEnvironmentVariable("AZURE_FUNCTIONS_ENVIRONMENT", environment);
|
||||
|
||||
var options = new DefaultOpenApiConfigurationOptions();
|
||||
var method = typeof(DefaultOpenApiConfigurationOptions).GetMethod("IsFunctionsRuntimeEnvironmentDevelopment", BindingFlags.NonPublic | BindingFlags.Static);
|
||||
var result = DefaultOpenApiConfigurationOptions.IsFunctionsRuntimeEnvironmentDevelopment();
|
||||
|
||||
var result = method.Invoke(options, null);
|
||||
|
||||
result.Should().BeOfType<bool>();
|
||||
((bool)result).Should().Be(expected);
|
||||
result.Should().Be(expected);
|
||||
}
|
||||
|
||||
[DataTestMethod]
|
||||
|
@ -234,13 +250,9 @@ namespace Microsoft.Azure.WebJobs.Extensions.OpenApi.Core.Tests.Configurations
|
|||
{
|
||||
Environment.SetEnvironmentVariable("OpenApi__ForceHttp", forceHttps);
|
||||
|
||||
var options = new DefaultOpenApiConfigurationOptions();
|
||||
var method = typeof(DefaultOpenApiConfigurationOptions).GetMethod("IsHttpForced", BindingFlags.NonPublic | BindingFlags.Static);
|
||||
var result = DefaultOpenApiConfigurationOptions.IsHttpForced();
|
||||
|
||||
var result = method.Invoke(options, null);
|
||||
|
||||
result.Should().BeOfType<bool>();
|
||||
((bool)result).Should().Be(expected);
|
||||
result.Should().Be(expected);
|
||||
}
|
||||
|
||||
[DataTestMethod]
|
||||
|
@ -252,13 +264,9 @@ namespace Microsoft.Azure.WebJobs.Extensions.OpenApi.Core.Tests.Configurations
|
|||
{
|
||||
Environment.SetEnvironmentVariable("OpenApi__ForceHttps", forceHttps);
|
||||
|
||||
var options = new DefaultOpenApiConfigurationOptions();
|
||||
var method = typeof(DefaultOpenApiConfigurationOptions).GetMethod("IsHttpsForced", BindingFlags.NonPublic | BindingFlags.Static);
|
||||
var result = DefaultOpenApiConfigurationOptions.IsHttpsForced();
|
||||
|
||||
var result = method.Invoke(options, null);
|
||||
|
||||
result.Should().BeOfType<bool>();
|
||||
((bool)result).Should().Be(expected);
|
||||
result.Should().Be(expected);
|
||||
}
|
||||
|
||||
public void Given_Type_When_Instantiated_Then_It_Should_Return_EmptyListOfDocumentFilters()
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
using FluentAssertions;
|
||||
|
||||
using Microsoft.Azure.WebJobs.Extensions.OpenApi.Core.Configurations;
|
||||
using Microsoft.Azure.WebJobs.Extensions.OpenApi.Core.Enums;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
|
||||
namespace Microsoft.Azure.WebJobs.Extensions.OpenApi.Core.Tests.Configurations
|
||||
{
|
||||
[TestClass]
|
||||
public class OpenApiConfigurationOptionsTests
|
||||
{
|
||||
[TestMethod]
|
||||
public void Given_Type_When_Instantiated_Then_Properties_Should_Return_Result()
|
||||
{
|
||||
var options = new OpenApiConfigurationOptions();
|
||||
|
||||
options.Info.Should().NotBeNull();
|
||||
options.Info.Version.Should().BeNull();
|
||||
options.Info.Title.Should().BeNull();
|
||||
options.Info.Description.Should().BeNull();
|
||||
|
||||
options.Servers.Should().NotBeNull();
|
||||
options.Servers.Should().HaveCount(0);
|
||||
|
||||
options.OpenApiVersion.Should().Be(OpenApiVersionType.V2);
|
||||
options.IncludeRequestingHostName.Should().BeFalse();
|
||||
options.ForceHttp.Should().BeFalse();
|
||||
options.ForceHttps.Should().BeFalse();
|
||||
|
||||
options.DocumentFilters.Should().NotBeNull();
|
||||
options.DocumentFilters.Should().HaveCount(0);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -6,6 +6,7 @@ using Microsoft.Azure.WebJobs.Extensions.Http;
|
|||
using Microsoft.Azure.WebJobs.Extensions.OpenApi.Configurations;
|
||||
using Microsoft.Azure.WebJobs.Extensions.OpenApi.Configurations.AppSettings.Extensions;
|
||||
using Microsoft.Azure.WebJobs.Extensions.OpenApi.Configurations.AppSettings.Resolvers;
|
||||
using Microsoft.Azure.WebJobs.Extensions.OpenApi.Core.Enums;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
|
||||
|
@ -14,35 +15,228 @@ namespace Microsoft.Azure.WebJobs.Extensions.OpenApi.Tests.Configurations
|
|||
[TestClass]
|
||||
public class OpenApiSettingsTests
|
||||
{
|
||||
[DataTestMethod]
|
||||
[DataRow("true", true, "false", false, "lorem", "Function", AuthorizationLevel.Function, "Anonymous", AuthorizationLevel.Anonymous, "http://localhost:7071", "https://contoso.com/api/")]
|
||||
[DataRow("false", false, "false", false, "ipsum", "Anonymous", AuthorizationLevel.Anonymous, "Function", AuthorizationLevel.Function, "http://contoso", "https://fabrikam.com/api/")]
|
||||
[DataRow("false", false, "true", true, "ipsum", "Anonymous", AuthorizationLevel.Anonymous, "Function", AuthorizationLevel.Function, "http://contoso", "https://fabrikam.com/api/")]
|
||||
public void Given_EnvironmentVariables_When_Instantiated_Then_It_Should_Return_Result(string hideSwaggerUI, bool expectedHideSwaggerUI,
|
||||
string hideDocument, bool expectedHideDocument,
|
||||
string apiKey,
|
||||
string authLevelDoc, AuthorizationLevel expectedAuthLevelDoc,
|
||||
string authLevelUI, AuthorizationLevel expectedAuthLevelUI,
|
||||
string proxyUrl, string hostnames)
|
||||
[TestCleanup]
|
||||
public void Cleanup()
|
||||
{
|
||||
Environment.SetEnvironmentVariable("OpenApi__Version", null);
|
||||
Environment.SetEnvironmentVariable("OpenApi__DocVersion", null);
|
||||
Environment.SetEnvironmentVariable("OpenApi__DocTitle", null);
|
||||
Environment.SetEnvironmentVariable("OpenApi__DocDescription", null);
|
||||
Environment.SetEnvironmentVariable("OpenApi__HostNames", null);
|
||||
Environment.SetEnvironmentVariable("OpenApi__ForceHttps", null);
|
||||
Environment.SetEnvironmentVariable("OpenApi__ForceHttp", null);
|
||||
Environment.SetEnvironmentVariable("OpenApi__HideSwaggerUI", null);
|
||||
Environment.SetEnvironmentVariable("OpenApi__HideDocument", null);
|
||||
Environment.SetEnvironmentVariable("OpenApi__ApiKey", null);
|
||||
Environment.SetEnvironmentVariable("OpenApi__AuthLevel__Document", null);
|
||||
Environment.SetEnvironmentVariable("OpenApi__AuthLevel__UI", null);
|
||||
Environment.SetEnvironmentVariable("OpenApi__BackendProxyUrl", null);
|
||||
}
|
||||
|
||||
[DataTestMethod]
|
||||
[DataRow(null, OpenApiVersionType.V2)]
|
||||
[DataRow("", OpenApiVersionType.V2)]
|
||||
[DataRow("v2", OpenApiVersionType.V2)]
|
||||
[DataRow("v3", OpenApiVersionType.V3)]
|
||||
public void Given_Version_When_Instantiated_Then_It_Should_Return_Result(string version, OpenApiVersionType expected)
|
||||
{
|
||||
Environment.SetEnvironmentVariable("OpenApi__Version", version);
|
||||
|
||||
var config = ConfigurationResolver.Resolve();
|
||||
var settings = config.Get<OpenApiSettings>("OpenApi");
|
||||
|
||||
settings.Version.Should().Be(expected);
|
||||
}
|
||||
|
||||
[DataTestMethod]
|
||||
[DataRow(null, null)]
|
||||
[DataRow("", null)]
|
||||
[DataRow("1.0.0", "1.0.0")]
|
||||
public void Given_DocVersion_When_Instantiated_Then_It_Should_Return_Result(string version, string expected)
|
||||
{
|
||||
Environment.SetEnvironmentVariable("OpenApi__DocVersion", version);
|
||||
|
||||
var config = ConfigurationResolver.Resolve();
|
||||
var settings = config.Get<OpenApiSettings>("OpenApi");
|
||||
|
||||
settings.DocVersion.Should().Be(expected);
|
||||
}
|
||||
|
||||
[DataTestMethod]
|
||||
[DataRow(null, null)]
|
||||
[DataRow("", null)]
|
||||
[DataRow("hello", "hello")]
|
||||
public void Given_DocTitle_When_Instantiated_Then_It_Should_Return_Result(string title, string expected)
|
||||
{
|
||||
Environment.SetEnvironmentVariable("OpenApi__DocTitle", title);
|
||||
|
||||
var config = ConfigurationResolver.Resolve();
|
||||
var settings = config.Get<OpenApiSettings>("OpenApi");
|
||||
|
||||
settings.DocTitle.Should().Be(expected);
|
||||
}
|
||||
|
||||
[DataTestMethod]
|
||||
[DataRow(null, null)]
|
||||
[DataRow("", null)]
|
||||
[DataRow("world", "world")]
|
||||
public void Given_DocDescription_When_Instantiated_Then_It_Should_Return_Result(string description, string expected)
|
||||
{
|
||||
Environment.SetEnvironmentVariable("OpenApi__DocDescription", description);
|
||||
|
||||
var config = ConfigurationResolver.Resolve();
|
||||
var settings = config.Get<OpenApiSettings>("OpenApi");
|
||||
|
||||
settings.DocDescription.Should().Be(expected);
|
||||
}
|
||||
|
||||
[DataTestMethod]
|
||||
[DataRow(null, null)]
|
||||
[DataRow("", null)]
|
||||
[DataRow("https://contoso", "https://contoso")]
|
||||
[DataRow("https://contoso, https://fabrikam", "https://contoso, https://fabrikam")]
|
||||
public void Given_HostNames_When_Instantiated_Then_It_Should_Return_Result(string hostnames, string expected)
|
||||
{
|
||||
Environment.SetEnvironmentVariable("OpenApi__HideSwaggerUI", hideSwaggerUI);
|
||||
Environment.SetEnvironmentVariable("OpenApi__HideDocument", hideDocument);
|
||||
Environment.SetEnvironmentVariable("OpenApi__ApiKey", apiKey);
|
||||
Environment.SetEnvironmentVariable("OpenApi__AuthLevel__Document", authLevelDoc);
|
||||
Environment.SetEnvironmentVariable("OpenApi__AuthLevel__UI", authLevelUI);
|
||||
Environment.SetEnvironmentVariable("OpenApi__BackendProxyUrl", proxyUrl);
|
||||
Environment.SetEnvironmentVariable("OpenApi__HostNames", hostnames);
|
||||
|
||||
var config = ConfigurationResolver.Resolve();
|
||||
var settings = config.Get<OpenApiSettings>("OpenApi");
|
||||
|
||||
settings.HideSwaggerUI.Should().Be(expectedHideSwaggerUI);
|
||||
settings.HideDocument.Should().Be(expectedHideDocument);
|
||||
settings.ApiKey.Should().Be(apiKey);
|
||||
settings.AuthLevel.Document.Should().Be(expectedAuthLevelDoc);
|
||||
settings.AuthLevel.UI.Should().Be(expectedAuthLevelUI);
|
||||
settings.BackendProxyUrl.Should().Be(proxyUrl);
|
||||
settings.HostNames.Should().Be(hostnames);
|
||||
settings.HostNames.Should().Be(expected);
|
||||
}
|
||||
|
||||
[DataTestMethod]
|
||||
[DataRow(null, false)]
|
||||
[DataRow("", false)]
|
||||
[DataRow("true", true)]
|
||||
[DataRow("false", false)]
|
||||
public void Given_ForceHttps_When_Instantiated_Then_It_Should_Return_Result(string https, bool expected)
|
||||
{
|
||||
Environment.SetEnvironmentVariable("OpenApi__ForceHttps", https);
|
||||
|
||||
var config = ConfigurationResolver.Resolve();
|
||||
var settings = config.Get<OpenApiSettings>("OpenApi");
|
||||
|
||||
settings.ForceHttps.Should().Be(expected);
|
||||
}
|
||||
|
||||
[DataTestMethod]
|
||||
[DataRow(null, false)]
|
||||
[DataRow("", false)]
|
||||
[DataRow("true", true)]
|
||||
[DataRow("false", false)]
|
||||
public void Given_ForceHttp_When_Instantiated_Then_It_Should_Return_Result(string http, bool expected)
|
||||
{
|
||||
Environment.SetEnvironmentVariable("OpenApi__ForceHttp", http);
|
||||
|
||||
var config = ConfigurationResolver.Resolve();
|
||||
var settings = config.Get<OpenApiSettings>("OpenApi");
|
||||
|
||||
settings.ForceHttp.Should().Be(expected);
|
||||
}
|
||||
|
||||
[DataTestMethod]
|
||||
[DataRow(null, false)]
|
||||
[DataRow("", false)]
|
||||
[DataRow("true", true)]
|
||||
[DataRow("false", false)]
|
||||
public void Given_HideSwaggerUI_When_Instantiated_Then_It_Should_Return_Result(string hide, bool expected)
|
||||
{
|
||||
Environment.SetEnvironmentVariable("OpenApi__HideSwaggerUI", hide);
|
||||
|
||||
var config = ConfigurationResolver.Resolve();
|
||||
var settings = config.Get<OpenApiSettings>("OpenApi");
|
||||
|
||||
settings.HideSwaggerUI.Should().Be(expected);
|
||||
}
|
||||
|
||||
[DataTestMethod]
|
||||
[DataRow(null, false)]
|
||||
[DataRow("", false)]
|
||||
[DataRow("true", true)]
|
||||
[DataRow("false", false)]
|
||||
public void Given_HideDocument_When_Instantiated_Then_It_Should_Return_Result(string hide, bool expected)
|
||||
{
|
||||
Environment.SetEnvironmentVariable("OpenApi__HideDocument", hide);
|
||||
|
||||
var config = ConfigurationResolver.Resolve();
|
||||
var settings = config.Get<OpenApiSettings>("OpenApi");
|
||||
|
||||
settings.HideDocument.Should().Be(expected);
|
||||
}
|
||||
|
||||
[DataTestMethod]
|
||||
[DataRow(null, null)]
|
||||
[DataRow("", null)]
|
||||
[DataRow("lorem", "lorem")]
|
||||
public void Given_ApiKey_When_Instantiated_Then_It_Should_Return_Result(string apiKey, string expected)
|
||||
{
|
||||
Environment.SetEnvironmentVariable("OpenApi__ApiKey", apiKey);
|
||||
|
||||
var config = ConfigurationResolver.Resolve();
|
||||
var settings = config.Get<OpenApiSettings>("OpenApi");
|
||||
|
||||
settings.ApiKey.Should().Be(expected);
|
||||
}
|
||||
|
||||
[DataTestMethod]
|
||||
[DataRow(null, null)]
|
||||
[DataRow("", null)]
|
||||
[DataRow("Anonymous", AuthorizationLevel.Anonymous)]
|
||||
[DataRow("anonymous", AuthorizationLevel.Anonymous)]
|
||||
[DataRow("Function", AuthorizationLevel.Function)]
|
||||
[DataRow("function", AuthorizationLevel.Function)]
|
||||
[DataRow("User", AuthorizationLevel.User)]
|
||||
[DataRow("user", AuthorizationLevel.User)]
|
||||
[DataRow("Admin", AuthorizationLevel.Admin)]
|
||||
[DataRow("admin", AuthorizationLevel.Admin)]
|
||||
[DataRow("System", AuthorizationLevel.System)]
|
||||
[DataRow("system", AuthorizationLevel.System)]
|
||||
public void Given_AuthLevelDoc_When_Instantiated_Then_It_Should_Return_Result(string authLevel, AuthorizationLevel? expected)
|
||||
{
|
||||
Environment.SetEnvironmentVariable("OpenApi__AuthLevel__Document", authLevel);
|
||||
|
||||
var config = ConfigurationResolver.Resolve();
|
||||
var settings = config.Get<OpenApiSettings>("OpenApi");
|
||||
|
||||
settings.AuthLevel.Document.Should().Be(expected);
|
||||
}
|
||||
|
||||
[DataTestMethod]
|
||||
[DataRow(null, null)]
|
||||
[DataRow("", null)]
|
||||
[DataRow("Anonymous", AuthorizationLevel.Anonymous)]
|
||||
[DataRow("anonymous", AuthorizationLevel.Anonymous)]
|
||||
[DataRow("Function", AuthorizationLevel.Function)]
|
||||
[DataRow("function", AuthorizationLevel.Function)]
|
||||
[DataRow("User", AuthorizationLevel.User)]
|
||||
[DataRow("user", AuthorizationLevel.User)]
|
||||
[DataRow("Admin", AuthorizationLevel.Admin)]
|
||||
[DataRow("admin", AuthorizationLevel.Admin)]
|
||||
[DataRow("System", AuthorizationLevel.System)]
|
||||
[DataRow("system", AuthorizationLevel.System)]
|
||||
public void Given_AuthLevelUI_When_Instantiated_Then_It_Should_Return_Result(string authLevel, AuthorizationLevel? expected)
|
||||
{
|
||||
Environment.SetEnvironmentVariable("OpenApi__AuthLevel__UI", authLevel);
|
||||
|
||||
var config = ConfigurationResolver.Resolve();
|
||||
var settings = config.Get<OpenApiSettings>("OpenApi");
|
||||
|
||||
settings.AuthLevel.UI.Should().Be(expected);
|
||||
}
|
||||
|
||||
[DataTestMethod]
|
||||
[DataRow(null, null)]
|
||||
[DataRow("", null)]
|
||||
[DataRow("lorem", "lorem")]
|
||||
public void Given_BackendProxyUrl_When_Instantiated_Then_It_Should_Return_Result(string url, string expected)
|
||||
{
|
||||
Environment.SetEnvironmentVariable("OpenApi__BackendProxyUrl", url);
|
||||
|
||||
var config = ConfigurationResolver.Resolve();
|
||||
var settings = config.Get<OpenApiSettings>("OpenApi");
|
||||
|
||||
settings.BackendProxyUrl.Should().Be(expected);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче