Skip to content

Commit 5dd14af

Browse files
authored
Add support for generating OpenAPI v2 spec. Closes #952 (#954)
* Add support for generating OpenAPI v2 spec. Closes #952 * Refactor OpenAPI spec version handling to use string type and improve error logging for unsupported versions * Refactor OpenAPI spec version handling to use enum type and improve version validation
1 parent f99ea8f commit 5dd14af

File tree

1 file changed

+23
-3
lines changed

1 file changed

+23
-3
lines changed

dev-proxy-plugins/RequestLogs/OpenApiSpecGeneratorPlugin.cs

+23-3
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
using System.Collections.Specialized;
1616
using Microsoft.Extensions.Logging;
1717
using Microsoft.DevProxy.Abstractions.LanguageModel;
18+
using System.Text.Json.Serialization;
1819

1920
namespace Microsoft.DevProxy.Plugins.RequestLogs;
2021

@@ -42,9 +43,18 @@ public void Write(IOpenApiWriter writer, OpenApiSpecVersion specVersion)
4243
}
4344
}
4445

46+
[JsonConverter(typeof(JsonStringEnumConverter))]
47+
internal enum SpecVersion
48+
{
49+
v2_0,
50+
v3_0
51+
}
52+
4553
internal class OpenApiSpecGeneratorPluginConfiguration
4654
{
4755
public bool IncludeOptionsRequests { get; set; } = false;
56+
57+
public SpecVersion SpecVersion { get; set; } = SpecVersion.v3_0;
4858
}
4959

5060
public class OpenApiSpecGeneratorPlugin(IPluginEvents pluginEvents, IProxyContext context, ILogger logger, ISet<UrlToWatch> urlsToWatch, IConfigurationSection? configSection = null) : BaseReportingPlugin(pluginEvents, context, logger, urlsToWatch, configSection)
@@ -355,7 +365,15 @@ request.Context is null ||
355365
{
356366
var server = openApiDoc.Servers.First();
357367
var fileName = GetFileNameFromServerUrl(server.Url);
358-
var docString = openApiDoc.SerializeAsJson(OpenApiSpecVersion.OpenApi3_0);
368+
369+
var openApiSpecVersion = _configuration.SpecVersion switch
370+
{
371+
SpecVersion.v2_0 => OpenApiSpecVersion.OpenApi2_0,
372+
SpecVersion.v3_0 => OpenApiSpecVersion.OpenApi3_0,
373+
_ => OpenApiSpecVersion.OpenApi3_0
374+
};
375+
376+
var docString = openApiDoc.SerializeAsJson(openApiSpecVersion);
359377

360378
Logger.LogDebug(" Writing OpenAPI spec to {fileName}...", fileName);
361379
File.WriteAllText(fileName, docString);
@@ -449,7 +467,8 @@ private async Task<string> GetOperationIdAsync(string method, string serverUrl,
449467
{
450468
var prompt = $"For the specified request, generate an operation ID, compatible with an OpenAPI spec. Respond with just the ID in plain-text format. For example, for request such as `GET https://api.contoso.com/books/{{books-id}}` you return `getBookById`. For a request like `GET https://api.contoso.com/books/{{books-id}}/authors` you return `getAuthorsForBookById`. Request: {method.ToUpper()} {serverUrl}{parametrizedPath}";
451469
ILanguageModelCompletionResponse? id = null;
452-
if (await Context.LanguageModelClient.IsEnabledAsync()) {
470+
if (await Context.LanguageModelClient.IsEnabledAsync())
471+
{
453472
id = await Context.LanguageModelClient.GenerateCompletionAsync(prompt);
454473
}
455474
return id?.Response ?? $"{method}{parametrizedPath.Replace('/', '.')}";
@@ -459,7 +478,8 @@ private async Task<string> GetOperationDescriptionAsync(string method, string se
459478
{
460479
var prompt = $"You're an expert in OpenAPI. You help developers build great OpenAPI specs for use with LLMs. For the specified request, generate a one-sentence description. Respond with just the description. For example, for a request such as `GET https://api.contoso.com/books/{{books-id}}` you return `Get a book by ID`. Request: {method.ToUpper()} {serverUrl}{parametrizedPath}";
461480
ILanguageModelCompletionResponse? description = null;
462-
if (await Context.LanguageModelClient.IsEnabledAsync()) {
481+
if (await Context.LanguageModelClient.IsEnabledAsync())
482+
{
463483
description = await Context.LanguageModelClient.GenerateCompletionAsync(prompt);
464484
}
465485
return description?.Response ?? $"{method} {parametrizedPath}";

0 commit comments

Comments
 (0)