Repository navigation
[OpenAPI] Avoid double PipeReader.AdvanceTo when reading @body #9961
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
28b9bd3
ad19ee6
53b0d0c
c7f855f
db942d5
b89f9ad
8f685a9
5aa4013
422f1ed
af25323
44d8bc4
c7dc2ee
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,127 @@ | ||
| using System.Net; | ||
| using System.Text; | ||
| using System.Text.Json; | ||
| using Microsoft.AspNetCore.Builder; | ||
| using Microsoft.AspNetCore.Hosting; | ||
| using Microsoft.AspNetCore.Hosting.Server.Features; | ||
| using Microsoft.Extensions.DependencyInjection; | ||
|
|
||
| namespace HotChocolate.Adapters.OpenApi; | ||
|
|
||
| // Regression tests for @body endpoints. They must run on a real Kestrel host: | ||
| // TestServer's in-memory body PipeReader tolerates the double AdvanceTo bug, | ||
| // only Kestrel enforces the contract and returns 500. | ||
| public sealed class KestrelHttpEndpointIntegrationTests : OpenApiTestBase | ||
| { | ||
| protected override void ConfigureStorage( | ||
| IServiceCollection services, | ||
| IOpenApiDefinitionStorage storage, | ||
| OpenApiDiagnosticEventListener? eventListener) | ||
| { | ||
| services.AddGraphQLServer() | ||
| .AddOpenApi() | ||
| .AddOpenApiDefinitionStorage(storage) | ||
| .AddBasicServer(); | ||
| } | ||
|
|
||
| [Fact] | ||
| public async Task Http_Post_Body_Succeeds_On_Kestrel() | ||
| { | ||
| var cancellationToken = TestContext.Current.CancellationToken; | ||
| var storage = CreateBasicTestDefinitionStorage(); | ||
| var host = await StartKestrelHostAsync(storage, cancellationToken); | ||
|
|
||
| try | ||
| { | ||
| using var client = new HttpClient { BaseAddress = GetBaseAddress(host) }; | ||
| var content = new StringContent( | ||
| """{ "id": "6", "name": "Test", "email": "test@example.com" }""", | ||
| Encoding.UTF8, | ||
| "application/json"); | ||
|
|
||
| var response = await client.PostAsync("/users", content, cancellationToken); | ||
|
|
||
| Assert.Equal(HttpStatusCode.OK, response.StatusCode); | ||
|
|
||
| var body = await response.Content.ReadAsStringAsync(cancellationToken); | ||
| using var json = JsonDocument.Parse(body); | ||
| Assert.Equal(JsonValueKind.Object, json.RootElement.ValueKind); | ||
| Assert.True(json.RootElement.TryGetProperty("name", out _)); | ||
| } | ||
| finally | ||
| { | ||
| await host.StopAsync(cancellationToken); | ||
| host.Dispose(); | ||
| } | ||
| } | ||
|
|
||
| [Fact] | ||
| public async Task Http_Put_Body_Succeeds_On_Kestrel() | ||
| { | ||
| var cancellationToken = TestContext.Current.CancellationToken; | ||
| var storage = CreateBasicTestDefinitionStorage(); | ||
| var host = await StartKestrelHostAsync(storage, cancellationToken); | ||
|
|
||
| try | ||
| { | ||
| using var client = new HttpClient { BaseAddress = GetBaseAddress(host) }; | ||
| // The PUT route is "/users/{userId:$user.id}", so "id" is supplied by the | ||
| // route segment and must not also appear in the body. | ||
| var content = new StringContent( | ||
| """{ "name": "Test", "email": "test@example.com" }""", | ||
| Encoding.UTF8, | ||
| "application/json"); | ||
|
|
||
| var response = await client.PutAsync("/users/6", content, cancellationToken); | ||
|
|
||
| Assert.Equal(HttpStatusCode.OK, response.StatusCode); | ||
| } | ||
| finally | ||
| { | ||
| await host.StopAsync(cancellationToken); | ||
| host.Dispose(); | ||
| } | ||
| } | ||
|
|
||
| private async Task<IWebHost> StartKestrelHostAsync( | ||
|
Check warning on line 86 in src/HotChocolate/Adapters/test/Adapters.OpenApi.Tests/Endpoints/KestrelHttpEndpointIntegrationTests.cs
|
||
| IOpenApiDefinitionStorage storage, | ||
| CancellationToken cancellationToken) | ||
| { | ||
| var host = new WebHostBuilder() | ||
|
Check warning on line 90 in src/HotChocolate/Adapters/test/Adapters.OpenApi.Tests/Endpoints/KestrelHttpEndpointIntegrationTests.cs
|
||
| .UseKestrel() | ||
| .UseUrls("http://127.0.0.1:0") | ||
| .ConfigureServices(services => | ||
| { | ||
| services.AddRouting(); | ||
|
|
||
| services.AddGraphQLServer() | ||
| .AddOpenApi() | ||
| .AddOpenApiDefinitionStorage(storage) | ||
| .AddBasicServer(); | ||
| }) | ||
| .Configure(app => | ||
| { | ||
| app.UseRouting(); | ||
| app.UseEndpoints(endpoints => | ||
| { | ||
| endpoints.MapOpenApiEndpoints(); | ||
| endpoints.MapGraphQL(); | ||
| }); | ||
| }) | ||
| .Build(); | ||
|
|
||
| await host.StartAsync(cancellationToken); | ||
| return host; | ||
| } | ||
|
|
||
| private static Uri GetBaseAddress(IWebHost host) | ||
|
Check warning on line 117 in src/HotChocolate/Adapters/test/Adapters.OpenApi.Tests/Endpoints/KestrelHttpEndpointIntegrationTests.cs
|
||
| { | ||
| var addresses = host.ServerFeatures.Get<IServerAddressesFeature>()?.Addresses | ||
| ?? throw new InvalidOperationException("Kestrel did not expose any server addresses."); | ||
|
|
||
| var address = addresses.FirstOrDefault() | ||
| ?? throw new InvalidOperationException("Kestrel did not bind to any address."); | ||
|
|
||
| return new Uri(address); | ||
| } | ||
| } | ||
Uh oh!
There was an error while loading. Please reload this page.