Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

using Azure.AI.OpenAI;

using AzureOpenAIProxy.ApiApp.Filters;
using AzureOpenAIProxy.ApiApp.Models;
using AzureOpenAIProxy.ApiApp.Services;

Expand Down Expand Up @@ -36,8 +37,8 @@ public class ChatCompletionsController(
/// <returns>Returns the chat completions response.</returns>
[HttpPost("deployments/{deploymentName}/chat/completions", Name = "GetChatCompletions")]
public async Task<IActionResult> GetChatCompletionsAsync(
[OpenApiParameterIgnore][FromHeader(Name = "api-key")] string apiKey,
[FromRoute] string deploymentName,
[FromHeader(Name = "api-key")] string apiKey,
[FromQuery(Name = "api-version")] string apiVersion,
[FromBody] ChatCompletionsOptions req)
{
Expand Down Expand Up @@ -87,8 +88,8 @@ public async Task<IActionResult> GetChatCompletionsAsync(
/// <returns>Returns the chat completions response.</returns>
[HttpPost("deployments/{deploymentName}/extensions/chat/completions", Name = "GetExtensionsChatCompletions")]
public async Task<IActionResult> GetExtensionsChatCompletionsAsync(
[OpenApiParameterIgnore][FromHeader(Name = "api-key")] string apiKey,
[FromRoute] string deploymentName,
[FromHeader(Name = "api-key")] string apiKey,
[FromQuery(Name = "api-version")] string apiVersion,
[FromBody] ChatCompletionsOptions req)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

using Azure.AI.OpenAI;

using AzureOpenAIProxy.ApiApp.Filters;
using AzureOpenAIProxy.ApiApp.Models;
using AzureOpenAIProxy.ApiApp.Services;

Expand Down Expand Up @@ -36,8 +37,8 @@ public class CompletionsController(
/// <returns>Returns the chat completions response.</returns>
[HttpPost("deployments/{deploymentName}/completions", Name = "GetCompletions")]
public async Task<IActionResult> GetCompletionsAsync(
[OpenApiParameterIgnore][FromHeader(Name = "api-key")] string apiKey,
[FromRoute] string deploymentName,
[FromHeader(Name = "api-key")] string apiKey,
[FromQuery(Name = "api-version")] string apiVersion,
[FromBody] CompletionsOptions req)
{
Expand Down Expand Up @@ -87,8 +88,8 @@ public async Task<IActionResult> GetCompletionsAsync(
/// <returns>Returns the completions response.</returns>
[HttpPost("deployments/{deploymentName}/extensions/completions", Name = "GetExtensionsCompletions")]
public async Task<IActionResult> GetExtensionsCompletionsAsync(
[OpenApiParameterIgnore][FromHeader(Name = "api-key")] string apiKey,
[FromRoute] string deploymentName,
[FromHeader(Name = "api-key")] string apiKey,
[FromQuery(Name = "api-version")] string apiVersion,
[FromBody] CompletionsOptions req)
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using AzureOpenAIProxy.ApiApp.Models;
using AzureOpenAIProxy.ApiApp.Filters;
using AzureOpenAIProxy.ApiApp.Models;

using Microsoft.AspNetCore.Mvc;

Expand All @@ -19,7 +20,7 @@ public partial class ManagementController
/// <returns>Returns the <see cref="AccessCodeResponseCollection"/> instance.</returns>
[HttpGet("events/{eventId}/access-codes", Name = "GetListOfEventAccessCodes")]
public async Task<IActionResult> GetEventAccessCodesByEventIdAsync(
[FromHeader(Name = "Authorization")] string apiKey,
[OpenApiParameterIgnore][FromHeader(Name = "api-key")] string apiKey,
[FromRoute] string eventId,
[FromQuery(Name = "page")] int? page = 0,
[FromQuery(Name = "size")] int? size = 20)
Expand Down Expand Up @@ -66,7 +67,7 @@ public async Task<IActionResult> GetEventAccessCodesByEventIdAsync(
/// <returns>Returns the <see cref="AccessCodeResponse"/> instance.</returns>
[HttpPost("events/{eventId}/access-codes", Name = "CreateEventAccessCode")]
public async Task<IActionResult> CreateEventAccessCodeAsync(
[FromHeader(Name = "Authorization")] string apiKey,
[OpenApiParameterIgnore][FromHeader(Name = "api-key")] string apiKey,
[FromRoute] string eventId,
[FromBody] AccessCodeRequest req)
{
Expand Down Expand Up @@ -119,7 +120,7 @@ public async Task<IActionResult> CreateEventAccessCodeAsync(
/// <returns>Returns the <see cref="AccessCodeResponse"/> instance.</returns>
[HttpGet("events/{eventId}/access-codes/{gitHubAlias}", Name = "GetEventAccessCodeByGitHubAlias")]
public async Task<IActionResult> GetEventAccessCodeByGitHubAliasAsync(
[FromHeader(Name = "Authorization")] string apiKey,
[OpenApiParameterIgnore][FromHeader(Name = "api-key")] string apiKey,
[FromRoute] string eventId,
[FromRoute] string gitHubAlias)
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using AzureOpenAIProxy.ApiApp.Models;
using AzureOpenAIProxy.ApiApp.Filters;
using AzureOpenAIProxy.ApiApp.Models;
using AzureOpenAIProxy.ApiApp.Services;

using Microsoft.AspNetCore.Mvc;
Expand Down Expand Up @@ -31,7 +32,7 @@ public partial class ManagementController(
/// <returns>Returns the <see cref="EventResponseCollection"/> instance.</returns>
[HttpGet("events", Name = "GetListOfEvents")]
public async Task<IActionResult> GetEventsAsync(
[FromHeader(Name = "Authorization")] string apiKey,
[OpenApiParameterIgnore][FromHeader(Name = "api-key")] string apiKey,
[FromQuery(Name = "page")] int? page = 0,
[FromQuery(Name = "size")] int? size = 20)
{
Expand Down Expand Up @@ -69,7 +70,7 @@ public async Task<IActionResult> GetEventsAsync(
/// <returns>Returns the <see cref="EventResponse"/> instance.</returns>
[HttpPost("events", Name = "CreateEvent")]
public async Task<IActionResult> CreateEventAsync(
[FromHeader(Name = "Authorization")] string apiKey,
[OpenApiParameterIgnore][FromHeader(Name = "api-key")] string apiKey,
[FromBody] EventRequest req)
{
this._logger.LogInformation("Received a request to generate an event");
Expand Down Expand Up @@ -113,7 +114,7 @@ public async Task<IActionResult> CreateEventAsync(
/// <returns>Returns the <see cref="EventResponse"/> instance.</returns>
[HttpGet("events/{eventId}", Name = "GetEventById")]
public async Task<IActionResult> GetEventByEventIdAsync(
[FromHeader(Name = "Authorization")] string apiKey,
[OpenApiParameterIgnore][FromHeader(Name = "api-key")] string apiKey,
[FromRoute] string eventId)
{
this._logger.LogInformation("Received a request to get an event details by event ID");
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
using Microsoft.AspNetCore.Mvc.ApiExplorer;
using Microsoft.AspNetCore.Mvc.ModelBinding.Metadata;
using Microsoft.OpenApi.Models;

using Swashbuckle.AspNetCore.SwaggerGen;

namespace AzureOpenAIProxy.ApiApp.Filters;

/// <summary>
/// This represents the attribute entity for parameters to be ignored from the OpenAPI document generation.
/// </summary>
[AttributeUsage(AttributeTargets.Parameter)]
public class OpenApiParameterIgnoreAttribute : Attribute
{
}

/// <summary>
/// This represents the filter entity for parameters to be ignored from the OpenAPI document generation.
/// </summary>
/// <remarks>https://stackoverflow.com/questions/69651135/hide-parameter-from-swagger-swashbuckle</remarks>
public class OpenApiParameterIgnoreFilter : IOperationFilter
{
/// <inheritdoc />
public void Apply(OpenApiOperation operation, OperationFilterContext context)
{
if (operation == null || context == null || context.ApiDescription?.ParameterDescriptions == null)
{
return;
}

var parametersToHide = context.ApiDescription.ParameterDescriptions
.Where(ParameterHasIgnoreAttribute);

if (parametersToHide.Any() == false)
{
return;
}

foreach (var parameterToHide in parametersToHide)
{
var parameter = operation.Parameters
.FirstOrDefault(parameter => parameter.Name.Equals(parameterToHide.Name, StringComparison.InvariantCultureIgnoreCase));
if (parameter != null)
{
operation.Parameters.Remove(parameter);
}
}
}

private static bool ParameterHasIgnoreAttribute(ApiParameterDescription parameterDescription)
{
return parameterDescription.ModelMetadata is DefaultModelMetadata metadata
? metadata.Attributes.ParameterAttributes.Any(attribute => attribute.GetType() == typeof(OpenApiParameterIgnoreAttribute))
: false;
}
}
35 changes: 34 additions & 1 deletion src/AzureOpenAIProxy.ApiApp/Program.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
using AzureOpenAIProxy.ApiApp.Configurations;
using AzureOpenAIProxy.ApiApp.Filters;
using AzureOpenAIProxy.ApiApp.Models;
using AzureOpenAIProxy.ApiApp.Services;

using Microsoft.OpenApi.Models;

var builder = WebApplication.CreateBuilder(args);

builder.AddServiceDefaults();
Expand All @@ -17,7 +20,37 @@
builder.Services.AddControllers();
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
builder.Services.AddSwaggerGen(options =>
{
options.SwaggerDoc(
"v1",
new OpenApiInfo()
{
Version = "1.0.0",
Title = "Azure OpenAI Proxy Service",
Description = "Providing a proxy service to Azure OpenAI",
});
options.AddSecurityDefinition(
"apiKey",
new OpenApiSecurityScheme()
{
Name = "api-key",
Type = SecuritySchemeType.ApiKey,
Description = "API key needed to access the endpoints.",
In = ParameterLocation.Header,
});
options.AddSecurityRequirement(new OpenApiSecurityRequirement
{
{
new OpenApiSecurityScheme
{
Reference = new OpenApiReference { Type = ReferenceType.SecurityScheme, Id = "apiKey" }
},
new string[] {}
}
});
options.OperationFilter<OpenApiParameterIgnoreFilter>();
});

var app = builder.Build();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@
"Instances": [
{
"Endpoint": "https://{account_name}.openai.azure.com/",
"ApiKey": "random.apikey.aoai"
"ApiKey": "random.api-key.aoai",
"DeploymentName": "random.deployment-name.aoai"
}
]
}
Expand Down
3 changes: 2 additions & 1 deletion src/AzureOpenAIProxy.ApiApp/appsettings.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@
"Instances": [
{
"Endpoint": "https://{account_name}.openai.azure.com/",
"ApiKey": "random.apikey.aoai"
"ApiKey": "random.api-key.aoai",
"DeploymentName": "random.deployment-name.aoai"
}
]
},
Expand Down