Skip to content

Commit 4e81588

Browse files
authored
Make OpenApiCustomUIOptions Injectable (Azure#483)
1 parent 14511a4 commit 4e81588

File tree

27 files changed

+1194
-604
lines changed

27 files changed

+1194
-604
lines changed

docs/openapi-core.md

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -226,18 +226,18 @@ Suppose you want to customise the look and feels of the Swagger UI page. In this
226226
1. You can inherit `DefaultOpenApiCustomUIOptions` to put additional control from your end such as changing the custom CSS and JavaScript file names or change behaviours of handing CSS and JavaScript.
227227

228228
```csharp
229-
public class OpenApiCustomUIOptions : DefaultOpenApiCustomUIOptions
229+
public class MyOpenApiCustomUIOptions : DefaultOpenApiCustomUIOptions
230230
{
231-
public OpenApiCustomUIOptions(Assembly assembly)
231+
public MyOpenApiCustomUIOptions(Assembly assembly)
232232
: base(assembly)
233233
{
234234
}
235235

236236
// Declare if you want to change the custom CSS file name.
237-
public override string CustomStylesheetPath { get; } = "dist.my-custom.css";
237+
public override string CustomStylesheetPath { get; set; } = "dist.my-custom.css";
238238

239239
// Declare if you want to change the custom JavaScript file name.
240-
public override string CustomJavaScriptPath { get; } = "dist.my-custom.js";
240+
public override string CustomJavaScriptPath { get; set; } = "dist.my-custom.js";
241241

242242
// Declare if you want to change the behaviours of handling the custom CSS file.
243243
public override async Task<string> GetStylesheetAsync()
@@ -267,17 +267,17 @@ Suppose you want to customise the look and feels of the Swagger UI page. In this
267267
Alternatively, you can use both CSS and JavaScript files from CDN, which is from the Internet.
268268

269269
```csharp
270-
public class OpenApiCustomUIOptions : DefaultOpenApiCustomUIOptions
270+
public class MyOpenApiCustomUIOptions : DefaultOpenApiCustomUIOptions
271271
{
272-
public OpenApiCustomUIOptions(Assembly assembly)
272+
public MyOpenApiCustomUIOptions(Assembly assembly)
273273
: base(assembly)
274274
{
275275
}
276276
// Declare if you want to change the custom CSS file name.
277-
public override string CustomStylesheetPath { get; }
277+
public override string CustomStylesheetPath { get; set; }
278278
= "https://raw.githubusercontent.com/Azure/azure-functions-openapi-extension/main/samples/Microsoft.Azure.WebJobs.Extensions.OpenApi.FunctionApp.V3Static/dist/my-custom.css";
279279
// Declare if you want to change the custom JavaScript file name.
280-
public override string CustomJavaScriptPath { get; }
280+
public override string CustomJavaScriptPath { get; set; }
281281
= "https://raw.githubusercontent.com/Azure/azure-functions-openapi-extension/main/samples/Microsoft.Azure.WebJobs.Extensions.OpenApi.FunctionApp.V3Static/dist/my-custom.js";
282282
// Declare if you want to change the behaviours of handling the custom CSS file.
283283
public override async Task<string> GetStylesheetAsync()
@@ -299,6 +299,14 @@ public class OpenApiCustomUIOptions : DefaultOpenApiCustomUIOptions
299299
Either way, your customised CSS and JavaScript will be applied to the Swagger UI page.
300300

301301

302+
### Injecting `OpenApiCustomUIOptions` during Startup ###
303+
304+
You may want to inject the `OpenApiCustomUIOptions` instance during startup:
305+
306+
* [in-proc worker](./openapi-in-proc.md#injecting-openapicustomuioptions-during-startup)
307+
* [out-of-proc worker](./openapi-out-of-proc.md#injecting-openapicustomuioptions-during-startup)
308+
309+
302310
## OpenAPI Response Header Customisation ##
303311

304312
Often, custom response headers need to be added. You can use `IOpenApiCustomResponseHeader` to add the custom response headers.

docs/openapi-in-proc.md

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,64 @@ namespace MyFunctionApp
8383
}
8484
```
8585

86+
87+
### Injecting `OpenApiCustomUIOptions` during Startup ###
88+
89+
You may want to inject the `OpenApiCustomUIOptions` instance during startup, through the `Startup.cs` class. Here's the example:
90+
91+
```csharp
92+
[assembly: FunctionsStartup(typeof(MyFunctionApp.Startup))]
93+
namespace MyFunctionApp
94+
{
95+
public class Startup : FunctionsStartup
96+
{
97+
public override void Configure(IFunctionsHostBuilder builder)
98+
{
99+
/* ⬇️⬇️⬇️ Add this ⬇️⬇️⬇️ */
100+
builder.Services.AddSingleton<IOpenApiCustomUIOptions>(_ =>
101+
{
102+
var assembly = Assembly.GetExecutingAssembly();
103+
var options = new OpenApiCustomUIOptions(assembly)
104+
{
105+
CustomStylesheetPath = "https://contoso.com/dist/my-custom.css",
106+
CustomJavaScriptPath = "https://contoso.com/dist/my-custom.js",
107+
108+
// ⬇️⬇️⬇️ Add your logic to get your custom stylesheet ⬇️⬇️⬇️
109+
// GetStylesheet = () =>
110+
// {
111+
// var result = string.Empty;
112+
113+
// //
114+
// // CUSTOM LOGIC TO GET STYLESHEET
115+
// //
116+
117+
// return Task.FromResult(result);
118+
// },
119+
// ⬆️⬆️⬆️ Add your logic to get your custom stylesheet ⬆️⬆️⬆️
120+
121+
// ⬇️⬇️⬇️ Add your logic to get your custom JavaScript ⬇️⬇️⬇️
122+
// GetJavaScript = () =>
123+
// {
124+
// var result = string.Empty;
125+
126+
// //
127+
// // CUSTOM LOGIC TO GET JAVASCRIPT
128+
// //
129+
130+
// return Task.FromResult(result);
131+
// },
132+
// ⬆️⬆️⬆️ Add your logic to get your custom JavaScript ⬆️⬆️⬆️
133+
};
134+
135+
return options;
136+
});
137+
/* ⬆️⬆️⬆️ Add this ⬆️⬆️⬆️ */
138+
}
139+
}
140+
}
141+
```
142+
143+
86144
### Injecting `OpenApiHttpTriggerAuthorization` during Startup ###
87145

88146
You may want to inject the `OpenApiHttpTriggerAuthorization` instance during startup, through the `Startup.cs` class. Here's the example:

docs/openapi-out-of-proc.md

Lines changed: 69 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,72 @@ namespace MyFunctionApp
8585
}
8686
```
8787

88+
89+
### Injecting `OpenApiCustomUIOptions` during Startup ###
90+
91+
You may want to inject the `OpenApiCustomUIOptions` instance during startup, through the `Program.cs` class. Here's the example:
92+
93+
```csharp
94+
namespace MyFunctionApp
95+
{
96+
public class Program
97+
{
98+
public static void Main()
99+
{
100+
var host = new HostBuilder()
101+
.ConfigureFunctionsWorkerDefaults(worker => worker.UseNewtonsoftJson())
102+
.ConfigureOpenApi()
103+
/* ⬇️⬇️⬇️ Add this ⬇️⬇️⬇️ */
104+
.ConfigureServices(services =>
105+
{
106+
services.AddSingleton<IOpenApiCustomUIOptions>(_ =>
107+
{
108+
var assembly = Assembly.GetExecutingAssembly();
109+
var options = new OpenApiCustomUIOptions(assembly)
110+
{
111+
CustomStylesheetPath = "https://contoso.com/dist/my-custom.css",
112+
CustomJavaScriptPath = "https://contoso.com/dist/my-custom.js",
113+
114+
// ⬇️⬇️⬇️ Add your logic to get your custom stylesheet ⬇️⬇️⬇️
115+
// GetStylesheet = () =>
116+
// {
117+
// var result = string.Empty;
118+
119+
// //
120+
// // CUSTOM LOGIC TO GET STYLESHEET
121+
// //
122+
123+
// return Task.FromResult(result);
124+
// },
125+
// ⬆️⬆️⬆️ Add your logic to get your custom stylesheet ⬆️⬆️⬆️
126+
127+
// ⬇️⬇️⬇️ Add your logic to get your custom JavaScript ⬇️⬇️⬇️
128+
// GetJavaScript = () =>
129+
// {
130+
// var result = string.Empty;
131+
132+
// //
133+
// // CUSTOM LOGIC TO GET JAVASCRIPT
134+
// //
135+
136+
// return Task.FromResult(result);
137+
// },
138+
// ⬆️⬆️⬆️ Add your logic to get your custom JavaScript ⬆️⬆️⬆️
139+
};
140+
141+
return options;
142+
});
143+
})
144+
/* ⬆️⬆️⬆️ Add this ⬆️⬆️⬆️ */
145+
.Build();
146+
147+
host.Run();
148+
}
149+
}
150+
}
151+
```
152+
153+
88154
### Injecting `OpenApiHttpTriggerAuthorization` during Startup ###
89155

90156
You may want to inject the `OpenApiHttpTriggerAuthorization` instance during startup, through the `Program.cs` class. Here's the example:
@@ -104,7 +170,7 @@ namespace MyFunctionApp
104170
{
105171
services.AddSingleton<IOpenApiHttpTriggerAuthorization>(_ =>
106172
{
107-
var auth = new OpenApiHttpTriggerAuthorization(async req =>
173+
var auth = new OpenApiHttpTriggerAuthorization(req =>
108174
{
109175
var result = default(OpenApiAuthorizationResult);
110176

@@ -118,10 +184,10 @@ namespace MyFunctionApp
118184
Payload = "Unauthorized",
119185
};
120186

121-
return await Task.FromResult(result).ConfigureAwait(false);
187+
return Task.FromResult(result);
122188
}
123189

124-
return await Task.FromResult(result).ConfigureAwait(false);
190+
return Task.FromResult(result);
125191
});
126192

127193
return auth;

docs/openapi.md

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -243,7 +243,7 @@ public class DefaultOpenApiHttpTriggerAuthorization : IOpenApiHttpTriggerAuthori
243243
If you want your own implementation with OAuth2, you may like to do like:
244244

245245
```csharp
246-
public class OpenApiHttpTriggerAuthorization : DefaultOpenApiHttpTriggerAuthorization
246+
public class MyOpenApiHttpTriggerAuthorization : DefaultOpenApiHttpTriggerAuthorization
247247
{
248248
public override async Task<OpenApiAuthorizationResult> AuthorizeAsync(IHttpRequestDataObject req)
249249
{
@@ -299,6 +299,11 @@ public class OpenApiHttpTriggerAuthorization : DefaultOpenApiHttpTriggerAuthoriz
299299
}
300300
```
301301

302+
You may want to inject the `OpenApiHttpTriggerAuthorization` instance during startup:
303+
304+
* [in-proc worker](./openapi-in-proc.md#injecting-openapihttptriggerauthorization-during-startup)
305+
* [out-of-proc worker](./openapi-out-of-proc.md#injecting-openapihttptriggerauthorization-during-startup)
306+
302307
Then, `OpenApiHttpTriggerContext` automatically picks it up and invokes its `AuthorizeAsync(...)` method. The following code shows how your auth results are handled within each Swagger UI and OpenAPI document endpoints.
303308

304309
```csharp
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
using System.Reflection;
2+
3+
using Microsoft.Azure.WebJobs.Extensions.OpenApi.Core.Configurations;
4+
5+
namespace Microsoft.Azure.Functions.Worker.Extensions.OpenApi.FunctionApp.OutOfProc.Configurations
6+
{
7+
public class MyOpenApiCustomUIOptions : DefaultOpenApiCustomUIOptions
8+
{
9+
public MyOpenApiCustomUIOptions(Assembly assembly)
10+
: base(assembly)
11+
{
12+
}
13+
14+
//<!-- Uncomment if you want to use the embedded file. -->
15+
//public override string CustomStylesheetPath { get; set; } = "dist.my-custom.css";
16+
//public override string CustomJavaScriptPath { get; set; } = "dist.my-custom.js";
17+
//<!-- Uncomment if you want to use the embedded file. -->
18+
19+
//<!-- Uncomment if you want to use the external URL. -->
20+
//public override string CustomStylesheetPath { get; set; } = "https://raw.githubusercontent.com/Azure/azure-functions-openapi-extension/main/samples/Microsoft.Azure.WebJobs.Extensions.OpenApi.FunctionApp.InProc/dist/my-custom.css";
21+
//public override string CustomJavaScriptPath { get; set; } = "https://raw.githubusercontent.com/Azure/azure-functions-openapi-extension/main/samples/Microsoft.Azure.WebJobs.Extensions.OpenApi.FunctionApp.InProc/dist/my-custom.js";
22+
//<!-- Uncomment if you want to use the external URL. -->
23+
}
24+
}

samples/Microsoft.Azure.Functions.Worker.Extensions.OpenApi.FunctionApp.OutOfProc/Microsoft.Azure.Functions.Worker.Extensions.OpenApi.FunctionApp.OutOfProc.csproj

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,4 +38,11 @@
3838
</None>
3939
</ItemGroup>
4040

41+
<!-- Uncomment this block if you want to use custom UI -->
42+
<!--<ItemGroup>
43+
<EmbeddedResource Include="dist\my-custom.css" />
44+
<EmbeddedResource Include="dist\my-custom.js" />
45+
</ItemGroup>-->
46+
<!-- Uncomment this block if you want to use custom UI -->
47+
4148
</Project>

samples/Microsoft.Azure.Functions.Worker.Extensions.OpenApi.FunctionApp.OutOfProc/Program.cs

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System;
2+
using System.Reflection;
23
using System.Threading.Tasks;
34

45
using AutoFixture;
@@ -55,7 +56,7 @@ public static void Main()
5556
})
5657
.AddSingleton<IOpenApiHttpTriggerAuthorization>(_ =>
5758
{
58-
var auth = new OpenApiHttpTriggerAuthorization(async req =>
59+
var auth = new OpenApiHttpTriggerAuthorization(req =>
5960
{
6061
var result = default(OpenApiAuthorizationResult);
6162

@@ -65,11 +66,44 @@ public static void Main()
6566
//
6667
// ⬆️⬆️⬆️ Add your custom authorisation logic ⬆️⬆️⬆️
6768

68-
return await Task.FromResult(result).ConfigureAwait(false);
69+
return Task.FromResult(result);
6970
});
7071

7172
return auth;
7273
})
74+
.AddSingleton<IOpenApiCustomUIOptions>(_ =>
75+
{
76+
var assembly = Assembly.GetExecutingAssembly();
77+
var options = new OpenApiCustomUIOptions(assembly)
78+
{
79+
GetStylesheet = () =>
80+
{
81+
var result = string.Empty;
82+
83+
// ⬇️⬇️⬇️ Add your logic to get your custom stylesheet ⬇️⬇️⬇️
84+
//
85+
// CUSTOM LOGIC TO GET STYLESHEET
86+
//
87+
// ⬆️⬆️⬆️ Add your logic to get your custom stylesheet ⬆️⬆️⬆️
88+
89+
return Task.FromResult(result);
90+
},
91+
GetJavaScript = () =>
92+
{
93+
var result = string.Empty;
94+
95+
// ⬇️⬇️⬇️ Add your logic to get your custom JavaScript ⬇️⬇️⬇️
96+
//
97+
// CUSTOM LOGIC TO GET JAVASCRIPT
98+
//
99+
// ⬆️⬆️⬆️ Add your logic to get your custom JavaScript ⬆️⬆️⬆️
100+
101+
return Task.FromResult(result);
102+
}
103+
};
104+
105+
return options;
106+
})
73107
;
74108
})
75109
.Build();
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
.swagger-ui .topbar {
2+
background-color: #003399
3+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
console.log("Custom UI: OpenAPI Sample on Azure Functions (OUT-OF-PROC)");
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
using System.Reflection;
2+
3+
using Microsoft.Azure.WebJobs.Extensions.OpenApi.Core.Configurations;
4+
5+
namespace Microsoft.Azure.WebJobs.Extensions.OpenApi.FunctionApp.InProc.Configurations
6+
{
7+
public class MyOpenApiCustomUIOptions : DefaultOpenApiCustomUIOptions
8+
{
9+
public MyOpenApiCustomUIOptions(Assembly assembly)
10+
: base(assembly)
11+
{
12+
}
13+
14+
//<!-- Uncomment if you want to use the embedded file. -->
15+
//public override string CustomStylesheetPath { get; set; } = "dist.my-custom.css";
16+
//public override string CustomJavaScriptPath { get; set; } = "dist.my-custom.js";
17+
//<!-- Uncomment if you want to use the embedded file. -->
18+
19+
//<!-- Uncomment if you want to use the external URL. -->
20+
//public override string CustomStylesheetPath { get; set; } = "https://raw.githubusercontent.com/Azure/azure-functions-openapi-extension/main/samples/Microsoft.Azure.WebJobs.Extensions.OpenApi.FunctionApp.InProc/dist/my-custom.css";
21+
//public override string CustomJavaScriptPath { get; set; } = "https://raw.githubusercontent.com/Azure/azure-functions-openapi-extension/main/samples/Microsoft.Azure.WebJobs.Extensions.OpenApi.FunctionApp.InProc/dist/my-custom.js";
22+
//<!-- Uncomment if you want to use the external URL. -->
23+
}
24+
}

samples/Microsoft.Azure.WebJobs.Extensions.OpenApi.FunctionApp.InProc/Configurations/OpenApiCustomUIOptions.cs

Lines changed: 0 additions & 24 deletions
This file was deleted.

0 commit comments

Comments
 (0)