src/Microsoft.Azure.Functions.Worker.Extensions.OpenApi/Functions/OpenApiTriggerFunction.cs (210 lines of code) (raw):
using System;
using System.IO;
using System.Net;
using System.Threading.Tasks;
using Microsoft.Azure.Functions.Worker.Http;
using Microsoft.Azure.WebJobs.Extensions.OpenApi.Core.Abstractions;
using Microsoft.Azure.WebJobs.Extensions.OpenApi.Core.Extensions;
using Microsoft.Extensions.Logging;
namespace Microsoft.Azure.Functions.Worker.Extensions.OpenApi.Functions
{
/// <summary>
/// This represents the entity of the OpenAPI related HTTP trigger functions.
/// </summary>
public class OpenApiTriggerFunction : IOpenApiTriggerFunction
{
private const string ContentTypeText = "text/plain";
private const string ContentTypeHtml = "text/html";
private const string ContentTypeJson = "application/json";
private const string ContentTypeYaml = "text/vnd.yaml";
private readonly IOpenApiHttpTriggerContext _context;
/// <summary>
/// Initializes a new instance of the <see cref="OpenApiTriggerFunction"/> class.
/// </summary>
/// <param name="context"><see cref="IOpenApiHttpTriggerContext"/> instance.</param>
public OpenApiTriggerFunction(IOpenApiHttpTriggerContext context)
{
this._context = context.ThrowIfNullOrDefault();
}
/// <inheritdoc/>
public async Task<HttpResponseData> RenderSwaggerDocument(HttpRequestData req, string extension, FunctionContext ctx)
{
var log = ctx.GetLogger(nameof(OpenApiTriggerFunction));
log.LogInformation($"swagger.{extension} was requested.");
var fi = new FileInfo(ctx.FunctionDefinition.PathToAssembly);
var request = new HttpRequestObject(req);
var result = default(string);
var response = default(HttpResponseData);
try
{
var auth = await this._context
.SetApplicationAssemblyAsync(fi.Directory.FullName, appendBin: false)
.AuthorizeAsync(request)
.ConfigureAwait(false);
if (!auth.IsNullOrDefault())
{
response = req.CreateResponse(auth.StatusCode);
response.Headers.Add("Content-Type", auth.ContentType);
await response.WriteStringAsync(auth.Payload).ConfigureAwait(false);
return response;
}
result = await this._context
.Document
.InitialiseDocument()
.AddMetadata(this._context.OpenApiConfigurationOptions.Info)
.AddServer(request, this._context.HttpSettings.RoutePrefix, this._context.OpenApiConfigurationOptions)
.AddNamingStrategy(this._context.NamingStrategy)
.AddVisitors(this._context.GetVisitorCollection())
.Build(this._context.ApplicationAssembly, this._context.OpenApiConfigurationOptions.OpenApiVersion)
.ApplyDocumentFilters(this._context.GetDocumentFilterCollection())
.RenderAsync(this._context.GetOpenApiSpecVersion(this._context.OpenApiConfigurationOptions.OpenApiVersion), this._context.GetOpenApiFormat(extension))
.ConfigureAwait(false);
response = req.CreateResponse(HttpStatusCode.OK);
response.Headers.Add("Content-Type", this._context.GetOpenApiFormat(extension).GetContentType());
await response.WriteStringAsync(result).ConfigureAwait(false);
}
catch (Exception ex)
{
log.LogError(ex.Message);
result = ex.Message;
if (this._context.IsDevelopment)
{
result += "\r\n\r\n";
result += ex.StackTrace;
}
response = req.CreateResponse(HttpStatusCode.InternalServerError);
response.Headers.Add("Content-Type", ContentTypeText);
await response.WriteStringAsync(result).ConfigureAwait(false);
}
return response;
}
/// <inheritdoc/>
public async Task<HttpResponseData> RenderOpenApiDocument(HttpRequestData req, string version, string extension, FunctionContext ctx)
{
var log = ctx.GetLogger(nameof(OpenApiTriggerFunction));
log.LogInformation($"{version}.{extension} was requested.");
var fi = new FileInfo(ctx.FunctionDefinition.PathToAssembly);
var request = new HttpRequestObject(req);
var result = default(string);
var response = default(HttpResponseData);
try
{
var auth = await this._context
.SetApplicationAssemblyAsync(fi.Directory.FullName, appendBin: false)
.AuthorizeAsync(request)
.ConfigureAwait(false);
if (!auth.IsNullOrDefault())
{
response = req.CreateResponse(auth.StatusCode);
response.Headers.Add("Content-Type", auth.ContentType);
await response.WriteStringAsync(auth.Payload).ConfigureAwait(false);
return response;
}
result = await this._context
.Document
.InitialiseDocument()
.AddMetadata(this._context.OpenApiConfigurationOptions.Info)
.AddServer(request, this._context.HttpSettings.RoutePrefix, this._context.OpenApiConfigurationOptions)
.AddNamingStrategy(this._context.NamingStrategy)
.AddVisitors(this._context.GetVisitorCollection())
.Build(this._context.ApplicationAssembly, this._context.GetOpenApiVersionType(version))
.ApplyDocumentFilters(this._context.GetDocumentFilterCollection())
.RenderAsync(this._context.GetOpenApiSpecVersion(version), this._context.GetOpenApiFormat(extension))
.ConfigureAwait(false);
response = req.CreateResponse(HttpStatusCode.OK);
response.Headers.Add("Content-Type", this._context.GetOpenApiFormat(extension).GetContentType());
await response.WriteStringAsync(result).ConfigureAwait(false);
}
catch (Exception ex)
{
log.LogError(ex.Message);
result = ex.Message;
if (this._context.IsDevelopment)
{
result += "\r\n\r\n";
result += ex.StackTrace;
}
response = req.CreateResponse(HttpStatusCode.InternalServerError);
response.Headers.Add("Content-Type", ContentTypeText);
await response.WriteStringAsync(result).ConfigureAwait(false);
}
return response;
}
/// <inheritdoc/>
public async Task<HttpResponseData> RenderSwaggerUI(HttpRequestData req, FunctionContext ctx)
{
var log = ctx.GetLogger(nameof(OpenApiTriggerFunction));
log.LogInformation("SwaggerUI page was requested.");
var fi = new FileInfo(ctx.FunctionDefinition.PathToAssembly);
var request = new HttpRequestObject(req);
var result = default(string);
var response = default(HttpResponseData);
try
{
var auth = await this._context
.SetApplicationAssemblyAsync(fi.Directory.FullName, appendBin: false)
.AuthorizeAsync(request)
.ConfigureAwait(false);
if (!auth.IsNullOrDefault())
{
response = req.CreateResponse(auth.StatusCode);
response.Headers.Add("Content-Type", auth.ContentType);
await response.WriteStringAsync(auth.Payload).ConfigureAwait(false);
return response;
}
result = await this._context
.SwaggerUI
.AddMetadata(this._context.OpenApiConfigurationOptions.Info)
.AddServer(request, this._context.HttpSettings.RoutePrefix, this._context.OpenApiConfigurationOptions)
.BuildAsync(this._context.PackageAssembly, this._context.OpenApiCustomUIOptions)
.RenderAsync("swagger.json", this._context.GetDocumentAuthLevel(), this._context.GetSwaggerAuthKey())
.ConfigureAwait(false);
response = req.CreateResponse(HttpStatusCode.OK);
response.Headers.Add("Content-Type", ContentTypeHtml);
await response.WriteStringAsync(result).ConfigureAwait(false);
}
catch (Exception ex)
{
log.LogError(ex.Message);
result = ex.Message;
if (this._context.IsDevelopment)
{
result += "\r\n\r\n";
result += ex.StackTrace;
}
response = req.CreateResponse(HttpStatusCode.InternalServerError);
response.Headers.Add("Content-Type", ContentTypeText);
await response.WriteStringAsync(result).ConfigureAwait(false);
}
return response;
}
/// <inheritdoc/>
public async Task<HttpResponseData> RenderOAuth2Redirect(HttpRequestData req, FunctionContext ctx)
{
var log = ctx.GetLogger(nameof(OpenApiTriggerFunction));
log.LogInformation("The oauth2-redirect.html page was requested.");
var fi = new FileInfo(ctx.FunctionDefinition.PathToAssembly);
var request = new HttpRequestObject(req);
var result = default(string);
var response = default(HttpResponseData);
try
{
await this._context
.SetApplicationAssemblyAsync(fi.Directory.FullName, appendBin: false)
.ConfigureAwait(false);
result = await this._context
.SwaggerUI
.AddServer(request, this._context.HttpSettings.RoutePrefix, this._context.OpenApiConfigurationOptions)
.BuildOAuth2RedirectAsync(this._context.PackageAssembly)
.RenderOAuth2RedirectAsync("oauth2-redirect.html", this._context.GetDocumentAuthLevel(), this._context.GetSwaggerAuthKey())
.ConfigureAwait(false);
response = req.CreateResponse(HttpStatusCode.OK);
response.Headers.Add("Content-Type", ContentTypeHtml);
await response.WriteStringAsync(result).ConfigureAwait(false);
}
catch (Exception ex)
{
log.LogError(ex.Message);
result = ex.Message;
if (this._context.IsDevelopment)
{
result += "\r\n\r\n";
result += ex.StackTrace;
}
response = req.CreateResponse(HttpStatusCode.InternalServerError);
response.Headers.Add("Content-Type", ContentTypeText);
await response.WriteStringAsync(result).ConfigureAwait(false);
}
return response;
}
}
}