Skip to content

Commit

Permalink
fix(autodoc): don't override GroupName if it's already specified
Browse files Browse the repository at this point in the history
  • Loading branch information
Artemiy Izakov committed Nov 24, 2023
1 parent 35ebfca commit 233f025
Show file tree
Hide file tree
Showing 9 changed files with 66 additions and 6 deletions.
5 changes: 4 additions & 1 deletion src/Tochka.JsonRpc.ApiExplorer/JsonRpcDescriptionProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,10 @@ public void OnProvidersExecuting(ApiDescriptionProviderContext context)
var serializerMetadata = actionDescriptor.EndpointMetadata.Get<JsonRpcSerializerOptionsAttribute>();
var serializerOptionsProviderType = serializerMetadata?.ProviderType;

description.GroupName = ApiExplorerUtils.GetDocumentName(ApiExplorerConstants.DefaultDocumentName, serializerOptionsProviderType);
if (string.IsNullOrWhiteSpace(description.GroupName))
{
description.GroupName = ApiExplorerUtils.GetDocumentName(ApiExplorerConstants.DefaultDocumentName, serializerOptionsProviderType);
}

description.HttpMethod = HttpMethods.Post;
description.RelativePath += $"#{methodMetadata.Method}";
Expand Down
8 changes: 5 additions & 3 deletions src/Tochka.JsonRpc.Client/Extensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ namespace Tochka.JsonRpc.Client;
public static class Extensions
{
/// <summary>
/// Register JSON-RPC client as <typeparamref name="TClient"/>
/// Register JSON-RPC client as <typeparamref name="TClient" />
/// </summary>
/// <param name="services">The <see cref="IServiceCollection" /> to add the service to</param>
/// <typeparam name="TClient">Type of JSON-RPC client</typeparam>
Expand All @@ -26,7 +26,7 @@ public static IHttpClientBuilder AddJsonRpcClient<TClient, TImplementation>(this
AddJsonRpcClient<TClient, TImplementation>(services, static (_, _) => { });

/// <summary>
/// Register JSON-RPC client as <typeparamref name="TClient"/> and configure internal <see cref="HttpClient" />
/// Register JSON-RPC client as <typeparamref name="TClient" /> and configure internal <see cref="HttpClient" />
/// </summary>
/// <param name="services">The <see cref="IServiceCollection" /> to add the service to</param>
/// <param name="configureClient">Delegate used to configure internal <see cref="HttpClient" /></param>
Expand Down Expand Up @@ -71,5 +71,7 @@ public static IHttpClientBuilder AddJsonRpcClient<TClient>(this IServiceCollecti
/// <summary>
/// Register handler to log outgoing requests
/// </summary>
public static IHttpClientBuilder WithJsonRpcRequestLogging(this IHttpClientBuilder httpClientBuilder) => httpClientBuilder.AddHttpMessageHandler<JsonRpcRequestLoggingHandler>();
[ExcludeFromCodeCoverage(Justification = "it's almost impossible to test AddHttpMessageHandler")]
public static IHttpClientBuilder WithJsonRpcRequestLogging(this IHttpClientBuilder httpClientBuilder) =>
httpClientBuilder.AddHttpMessageHandler<JsonRpcRequestLoggingHandler>();
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System.Diagnostics.CodeAnalysis;
using Asp.Versioning;
using Asp.Versioning.ApiExplorer;
using Asp.Versioning.ApplicationModels;
using JetBrains.Annotations;
using Microsoft.AspNetCore.Builder;
Expand Down Expand Up @@ -60,6 +61,10 @@ public static IServiceCollection AddJsonRpcServer(this IServiceCollection servic
options.FormatGroupName = static (name, version) => $"{name}_{version}";
});
services.TryAddEnumerable(ServiceDescriptor.Singleton<IApiControllerSpecification, JsonRpcControllerSpecification>());

// required for correct autodocs document names if ApiExplorerSettingsAttribute with custom GroupName is used
services.Replace(ServiceDescriptor.Singleton<IApiVersionDescriptionProvider, DefaultApiVersionDescriptionProvider>());

services.AddSingleton<JsonRpcMarkerService>();
return services;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,25 @@ public void OnProvidersExecuting_ValidDescriptor_UpdateDescriptionProperties()
description.Properties[ApiExplorerConstants.MethodNameProperty] = Method;
}

[Test]
public void OnProvidersExecuting_GroupNameAlreadySpecified_DontOverrideGroupName()
{
var groupName = "group-name";
var context = GetContext();
context.Results.First().ActionDescriptor.EndpointMetadata.Add(new JsonRpcMethodAttribute(Method));
context.Results.First().GroupName = groupName;
typeEmitterMock.Setup(static e => e.CreateRequestType(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<Type>(), It.IsAny<IReadOnlyDictionary<string, Type>>(), It.IsAny<Type?>()))
.Returns(Mock.Of<Type>);
typeEmitterMock.Setup(static e => e.CreateResponseType(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<Type>(), It.IsAny<Type?>()))
.Returns(Mock.Of<Type>);

descriptionProvider.OnProvidersExecuting(context);

context.Results.Should().HaveCount(1);
var description = context.Results.Single();
description.GroupName.Should().Be(groupName);
}

[Test]
public void OnProvidersExecuting_HasCustomSerializer_UseSerializer()
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,4 +44,16 @@ public async Task GetDocument_ReturnsAllMethods(string method)
var methods = responseJson.RootElement.GetProperty("methods").EnumerateArray().ToArray();
methods.Should().Contain(m => m.GetProperty("name").GetString() == method);
}

[Test]
public async Task GetDocument_AttributeWithCustomGroup_ReturnAllCustomGroupMethods()
{
var response = await ApiClient.GetAsync("/openrpc/custom_v1.json");

var responseContent = await response.Content.ReadAsStringAsync();
var responseJson = JsonDocument.Parse(responseContent);
response.StatusCode.Should().Be(HttpStatusCode.OK);
var methods = responseJson.RootElement.GetProperty("methods").EnumerateArray().ToArray();
methods.Should().OnlyContain(static m => m.GetProperty("name").GetString() == "custom_group");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -48,13 +48,14 @@ public void AddJsonRpcServer_RegisterServices()
result.Remove((typeof(IJsonRpcRequestValidator), typeof(JsonRpcRequestValidator), ServiceLifetime.Singleton)).Should().BeTrue();
result.Remove((typeof(IJsonRpcErrorFactory), typeof(JsonRpcErrorFactory), ServiceLifetime.Singleton)).Should().BeTrue();
result.Remove((typeof(IApiControllerSpecification), typeof(JsonRpcControllerSpecification), ServiceLifetime.Singleton)).Should().BeTrue();
result.Remove((typeof(IApiVersionDescriptionProvider), typeof(DefaultApiVersionDescriptionProvider), ServiceLifetime.Singleton)).Should().BeTrue();
result.Remove((typeof(JsonRpcMarkerService), typeof(JsonRpcMarkerService), ServiceLifetime.Singleton)).Should().BeTrue();
// one of services registered by calling AddApiVersioning
result.Remove((typeof(IApiVersionSetBuilderFactory), typeof(DefaultApiVersionSetBuilderFactory), ServiceLifetime.Singleton)).Should().BeTrue();
// one of services registered by calling AddApiVersioning.AddMvc
result.Remove((typeof(IControllerNameConvention), typeof(DefaultControllerNameConvention), ServiceLifetime.Singleton)).Should().BeTrue();
// one of services registered by calling AddApiVersioning.AddApiExplorer
result.Remove((typeof(IApiVersionDescriptionProvider), null, ServiceLifetime.Singleton)).Should().BeTrue();
result.Remove((typeof(IApiVersionDescriptionProviderFactory), null, ServiceLifetime.Transient)).Should().BeTrue();
}

[Test]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ internal class IntegrationTests : IntegrationTestsBase<Program>
[TestCase("jsonrpc_v1", "/api/jsonrpc#return_error_from_factory")]
[TestCase("jsonrpc_v1", "/api/jsonrpc#return_mvc_error")]
[TestCase("jsonrpc_v1", "/api/jsonrpc#error_throw_as_response_exception")]
[TestCase("custom_v1", "/api/jsonrpc#custom_group")]
public async Task GetDocument_ReturnsAllMethods(string document, string path)
{
var response = await ApiClient.GetAsync($"/swagger/{document}/swagger.json");
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
using Microsoft.AspNetCore.Mvc;
using Tochka.JsonRpc.Server;

namespace Tochka.JsonRpc.Tests.WebApplication.Controllers;

[ApiExplorerSettings(GroupName = "custom")]
public class CustomGroupNameJsonRpcController : JsonRpcControllerBase
{
public bool CustomGroup() => true;
}
9 changes: 8 additions & 1 deletion src/tests/Tochka.JsonRpc.Tests.WebApplication/Program.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
using System.Reflection;
using Asp.Versioning.ApiExplorer;
using Microsoft.OpenApi.Models;
using Tochka.JsonRpc.OpenRpc;
using Tochka.JsonRpc.OpenRpc.Models;
using Tochka.JsonRpc.Server.Extensions;
using Tochka.JsonRpc.Server.Serialization;
using Tochka.JsonRpc.Server.Settings;
Expand All @@ -23,25 +25,30 @@
builder.Services.AddSingleton<IJsonSerializerOptionsProvider, KebabCaseUpperJsonSerializerOptionsProvider>();

builder.Services.AddSwaggerWithJsonRpc(Assembly.GetExecutingAssembly()); // swagger for json-rpc
builder.Services.AddSwaggerGen(static c => // swagger for REST
builder.Services.ConfigureSwaggerGen(static c => // swagger for REST
{
c.SwaggerDoc("rest", new OpenApiInfo { Title = "RESTful API", Version = "v1" });
c.SwaggerDoc("custom_v1", new OpenApiInfo { Title = "Custom group", Version = "v1" });
});

builder.Services.AddOpenRpc(Assembly.GetExecutingAssembly()); // OpenRpc
builder.Services.Configure<OpenRpcOptions>(static o => o.OpenRpcDoc("custom_v1", new OpenRpcInfo("Custom group", "v1")));

// auth
builder.Services.AddAuthentication(AuthConstants.SchemeName)
.AddScheme<ApiAuthenticationOptions, ApiAuthenticationHandler>(AuthConstants.SchemeName, null);
builder.Services.AddAuthorization();

builder.Services.AddSingleton<IApiVersionDescriptionProvider, DefaultApiVersionDescriptionProvider>();

var app = builder.Build();

app.UseAuthentication();
app.UseSwaggerUI(c =>
{
c.JsonRpcSwaggerEndpoints(app.Services); // register json-rpc in swagger UI
c.SwaggerEndpoint("/swagger/rest/swagger.json", "RESTful"); // register REST in swagger UI
c.SwaggerEndpoint("/swagger/custom_v1/swagger.json", "Custom group");
});
app.UseJsonRpc();
app.UseRouting();
Expand Down

0 comments on commit 233f025

Please sign in to comment.