Skip to content
Open
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 @@ -5,6 +5,8 @@
{{/nrt}}
using System;
using System.Net.Http;
using System.Net.Security;
using Microsoft.Extensions.Http;
using Microsoft.Extensions.DependencyInjection;{{#supportsRetry}}
using Polly.Timeout;
using Polly.Extensions.Http;
Expand All @@ -17,6 +19,59 @@ namespace {{packageName}}.Extensions
/// </summary>
{{>visibility}} static class IHttpClientBuilderExtensions
{
/// <summary>
/// Configures remote certificate validation for requests made by this client.
/// </summary>
public static IHttpClientBuilder ConfigureRemoteCertificateValidationCallback(
this IHttpClientBuilder client,
RemoteCertificateValidationCallback callback)
{
if (callback == null)
throw new ArgumentNullException(nameof(callback));

client.Services.Configure<HttpClientFactoryOptions>(client.Name, (HttpClientFactoryOptions options) =>
{
options.HttpMessageHandlerBuilderActions.Add(builder =>
{
if (builder.PrimaryHandler is HttpClientHandler httpClientHandler)
httpClientHandler.ServerCertificateCustomValidationCallback = (request, certificate, chain, errors) =>
callback(request, certificate, chain, errors);
#if NETCOREAPP || NETSTANDARD2_1_OR_GREATER
else if (builder.PrimaryHandler is SocketsHttpHandler socketsHttpHandler)
socketsHttpHandler.SslOptions.RemoteCertificateValidationCallback = callback;
#endif
else
throw new InvalidOperationException("Certificate validation requires HttpClientHandler or SocketsHttpHandler.");
});
});

return client;
}

/// <summary>
/// Disables TLS certificate validation for requests made by this client.
/// Use only for development or testing.
/// </summary>
public static IHttpClientBuilder SkipCertificateCheck(this IHttpClientBuilder client)
{
client.Services.Configure<HttpClientFactoryOptions>(client.Name, (HttpClientFactoryOptions options) =>
{
options.HttpMessageHandlerBuilderActions.Add(builder =>
{
if (builder.PrimaryHandler is HttpClientHandler httpClientHandler)
httpClientHandler.ServerCertificateCustomValidationCallback = (request, certificate, chain, errors) => true;
#if NETCOREAPP || NETSTANDARD2_1_OR_GREATER
else if (builder.PrimaryHandler is SocketsHttpHandler socketsHttpHandler)
socketsHttpHandler.SslOptions.RemoteCertificateValidationCallback = (sender, certificate, chain, errors) => true;
#endif
else
throw new InvalidOperationException("Certificate validation requires HttpClientHandler or SocketsHttpHandler.");
});
});

return client;
}
Comment on lines +55 to +73

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P3: SkipCertificateCheck duplicates the full handler-configuration block from ConfigureRemoteCertificateValidationCallback. Delegate to it with an always-true callback so the handler-type logic lives in one place.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At modules/openapi-generator/src/main/resources/csharp/libraries/generichost/IHttpClientBuilderExtensions.mustache, line 55:

<comment>`SkipCertificateCheck` duplicates the full handler-configuration block from `ConfigureRemoteCertificateValidationCallback`. Delegate to it with an always-true callback so the handler-type logic lives in one place.</comment>

<file context>
@@ -17,6 +19,59 @@ namespace {{packageName}}.Extensions
+        /// Disables TLS certificate validation for requests made by this client.
+        /// Use only for development or testing.
+        /// </summary>
+        public static IHttpClientBuilder SkipCertificateCheck(this IHttpClientBuilder client)
+        {
+            client.Services.Configure<HttpClientFactoryOptions>(client.Name, (HttpClientFactoryOptions options) =>
</file context>
Suggested change
public static IHttpClientBuilder SkipCertificateCheck(this IHttpClientBuilder client)
{
client.Services.Configure<HttpClientFactoryOptions>(client.Name, (HttpClientFactoryOptions options) =>
{
options.HttpMessageHandlerBuilderActions.Add(builder =>
{
if (builder.PrimaryHandler is HttpClientHandler httpClientHandler)
httpClientHandler.ServerCertificateCustomValidationCallback = (request, certificate, chain, errors) => true;
#if NETCOREAPP || NETSTANDARD2_1_OR_GREATER
else if (builder.PrimaryHandler is SocketsHttpHandler socketsHttpHandler)
socketsHttpHandler.SslOptions.RemoteCertificateValidationCallback = (sender, certificate, chain, errors) => true;
#endif
else
throw new InvalidOperationException("Certificate validation requires HttpClientHandler or SocketsHttpHandler.");
});
});
return client;
}
public static IHttpClientBuilder SkipCertificateCheck(this IHttpClientBuilder client)
=> client.ConfigureRemoteCertificateValidationCallback((sender, certificate, chain, errors) => true);


{{#supportsRetry}}
/// <summary>
/// Adds a Polly retry policy to your clients.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,17 @@ namespace YourProject
}
}
```

## Certificate validation

To skip certificate validation for local development or testing, configure the generated HTTP clients as follows:

```cs
options.Add{{apiName}}HttpClients(client => { }, builder => builder.SkipCertificateCheck());
```

Do not disable certificate validation in production.

<a id="questions"></a>
## Questions

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -380,6 +380,44 @@ public void testJsonContentHeaderUsesJsonSerializationGenericHost() throws IOExc
"ClientUtils.ParameterToString(xPlainArg)");
}

@Test
public void testGenericHostSupportsSkipCertificateCheck() throws IOException {
File output = Files.createTempDirectory("test").toFile().getCanonicalFile();
output.deleteOnExit();
final OpenAPI openAPI = TestUtils.parseFlattenSpec("src/test/resources/3_0/petstore.yaml");
final DefaultGenerator defaultGenerator = new DefaultGenerator();
final ClientOptInput clientOptInput = new ClientOptInput();
clientOptInput.openAPI(openAPI);
CSharpClientCodegen cSharpClientCodegen = new CSharpClientCodegen();
cSharpClientCodegen.setLibrary("generichost");
cSharpClientCodegen.setOutputDir(output.getAbsolutePath());
clientOptInput.config(cSharpClientCodegen);
defaultGenerator.opts(clientOptInput);

Map<String, File> files = defaultGenerator.generate().stream()
.collect(Collectors.toMap(File::getPath, Function.identity()));

File extensions = files.values().stream()
.filter(file -> file.getName().equals("IHttpClientBuilderExtensions.cs"))
.findFirst()
.orElse(null);
assertNotNull(extensions);
assertFileContains(extensions.toPath(), "ConfigureRemoteCertificateValidationCallback(");
assertFileContains(extensions.toPath(), "callback(request, certificate, chain, errors)");
assertFileContains(extensions.toPath(), "SkipCertificateCheck(this IHttpClientBuilder client)");
assertFileContains(extensions.toPath(), "ServerCertificateCustomValidationCallback = (request, certificate, chain, errors) => true;");
assertFileContains(extensions.toPath(),
"client.Services.Configure<HttpClientFactoryOptions>(client.Name, (HttpClientFactoryOptions options) =>",
"builder.PrimaryHandler is HttpClientHandler httpClientHandler",
"builder.PrimaryHandler is SocketsHttpHandler socketsHttpHandler",
"socketsHttpHandler.SslOptions.RemoteCertificateValidationCallback = callback;",
"socketsHttpHandler.SslOptions.RemoteCertificateValidationCallback = (sender, certificate, chain, errors) => true;");
assertFileNotContains(extensions.toPath(), "new HttpClientHandler");
assertFileContains(Paths.get(output.getAbsolutePath(), "src", "Org.OpenAPITools", "README.md"),
"builder => builder.SkipCertificateCheck()",
"Do not disable certificate validation in production.");
}

@Test
public void testUserAgentIsNotUrlEncoded() throws IOException {
// both restsharp Configuration templates: the default one and the useIntForTimeout v7.9.0 fallback
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@

using System;
using System.Net.Http;
using System.Net.Security;
using Microsoft.Extensions.Http;
using Microsoft.Extensions.DependencyInjection;
using Polly.Timeout;
using Polly.Extensions.Http;
Expand All @@ -23,6 +25,59 @@ namespace Org.OpenAPITools.Extensions
/// </summary>
public static class IHttpClientBuilderExtensions
{
/// <summary>
/// Configures remote certificate validation for requests made by this client.
/// </summary>
public static IHttpClientBuilder ConfigureRemoteCertificateValidationCallback(
this IHttpClientBuilder client,
RemoteCertificateValidationCallback callback)
{
if (callback == null)
throw new ArgumentNullException(nameof(callback));

client.Services.Configure<HttpClientFactoryOptions>(client.Name, (HttpClientFactoryOptions options) =>
{
options.HttpMessageHandlerBuilderActions.Add(builder =>
{
if (builder.PrimaryHandler is HttpClientHandler httpClientHandler)
httpClientHandler.ServerCertificateCustomValidationCallback = (request, certificate, chain, errors) =>
callback(request, certificate, chain, errors);
#if NETCOREAPP || NETSTANDARD2_1_OR_GREATER
else if (builder.PrimaryHandler is SocketsHttpHandler socketsHttpHandler)
socketsHttpHandler.SslOptions.RemoteCertificateValidationCallback = callback;
#endif
else
throw new InvalidOperationException("Certificate validation requires HttpClientHandler or SocketsHttpHandler.");
});
});

return client;
}

/// <summary>
/// Disables TLS certificate validation for requests made by this client.
/// Use only for development or testing.
/// </summary>
public static IHttpClientBuilder SkipCertificateCheck(this IHttpClientBuilder client)
{
client.Services.Configure<HttpClientFactoryOptions>(client.Name, (HttpClientFactoryOptions options) =>
{
options.HttpMessageHandlerBuilderActions.Add(builder =>
{
if (builder.PrimaryHandler is HttpClientHandler httpClientHandler)
httpClientHandler.ServerCertificateCustomValidationCallback = (request, certificate, chain, errors) => true;
#if NETCOREAPP || NETSTANDARD2_1_OR_GREATER
else if (builder.PrimaryHandler is SocketsHttpHandler socketsHttpHandler)
socketsHttpHandler.SslOptions.RemoteCertificateValidationCallback = (sender, certificate, chain, errors) => true;
#endif
else
throw new InvalidOperationException("Certificate validation requires HttpClientHandler or SocketsHttpHandler.");
});
});

return client;
}

/// <summary>
/// Adds a Polly retry policy to your clients.
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,17 @@ namespace YourProject
}
}
```

## Certificate validation

To skip certificate validation for local development or testing, configure the generated HTTP clients as follows:

```cs
options.AddApiHttpClients(client => { }, builder => builder.SkipCertificateCheck());

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1: This example leaves HttpClient.BaseAddress unset, so the first API call throws a NullReferenceException. The default base address is only applied when no client action is passed. Use the single-argument overload with a named parameter so the default configuration still runs.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At samples/client/petstore/csharp/generichost/latest/AnnotatedEnum/src/Org.OpenAPITools/README.md, line 92:

<comment>This example leaves `HttpClient.BaseAddress` unset, so the first API call throws a NullReferenceException. The default base address is only applied when no client action is passed. Use the single-argument overload with a named parameter so the default configuration still runs.</comment>

<file context>
@@ -83,6 +83,17 @@ namespace YourProject
+To skip certificate validation for local development or testing, configure the generated HTTP clients as follows:
+
+```cs
+options.AddApiHttpClients(client => { }, builder => builder.SkipCertificateCheck());
+```
+
</file context>
Suggested change
options.AddApiHttpClients(client => { }, builder => builder.SkipCertificateCheck());
options.AddApiHttpClients(builder: builder => builder.SkipCertificateCheck());

```

Do not disable certificate validation in production.

<a id="questions"></a>
## Questions

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@

using System;
using System.Net.Http;
using System.Net.Security;
using Microsoft.Extensions.Http;
using Microsoft.Extensions.DependencyInjection;
using Polly.Timeout;
using Polly.Extensions.Http;
Expand All @@ -23,6 +25,59 @@ namespace Org.OpenAPITools.Extensions
/// </summary>
public static class IHttpClientBuilderExtensions
{
/// <summary>
/// Configures remote certificate validation for requests made by this client.
/// </summary>
public static IHttpClientBuilder ConfigureRemoteCertificateValidationCallback(
this IHttpClientBuilder client,
RemoteCertificateValidationCallback callback)
{
if (callback == null)
throw new ArgumentNullException(nameof(callback));

client.Services.Configure<HttpClientFactoryOptions>(client.Name, (HttpClientFactoryOptions options) =>
{
options.HttpMessageHandlerBuilderActions.Add(builder =>
{
if (builder.PrimaryHandler is HttpClientHandler httpClientHandler)
httpClientHandler.ServerCertificateCustomValidationCallback = (request, certificate, chain, errors) =>
callback(request, certificate, chain, errors);
#if NETCOREAPP || NETSTANDARD2_1_OR_GREATER
else if (builder.PrimaryHandler is SocketsHttpHandler socketsHttpHandler)
socketsHttpHandler.SslOptions.RemoteCertificateValidationCallback = callback;
#endif
else
throw new InvalidOperationException("Certificate validation requires HttpClientHandler or SocketsHttpHandler.");
});
});

return client;
}

/// <summary>
/// Disables TLS certificate validation for requests made by this client.
/// Use only for development or testing.
/// </summary>
public static IHttpClientBuilder SkipCertificateCheck(this IHttpClientBuilder client)
{
client.Services.Configure<HttpClientFactoryOptions>(client.Name, (HttpClientFactoryOptions options) =>
{
options.HttpMessageHandlerBuilderActions.Add(builder =>
{
if (builder.PrimaryHandler is HttpClientHandler httpClientHandler)
httpClientHandler.ServerCertificateCustomValidationCallback = (request, certificate, chain, errors) => true;
#if NETCOREAPP || NETSTANDARD2_1_OR_GREATER
else if (builder.PrimaryHandler is SocketsHttpHandler socketsHttpHandler)
socketsHttpHandler.SslOptions.RemoteCertificateValidationCallback = (sender, certificate, chain, errors) => true;
#endif
else
throw new InvalidOperationException("Certificate validation requires HttpClientHandler or SocketsHttpHandler.");
});
});

return client;
}
Comment on lines +61 to +79

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P3: SkipCertificateCheck duplicates the handler-configuration block from ConfigureRemoteCertificateValidationCallback and only swaps the delegate. Implement it by delegating to ConfigureRemoteCertificateValidationCallback so the handler logic lives in one place. This file is generated, so make the change in the generator template.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At samples/client/petstore/csharp/generichost/latest/ComposedEnum/src/Org.OpenAPITools/Extensions/IHttpClientBuilderExtensions.cs, line 61:

<comment>`SkipCertificateCheck` duplicates the handler-configuration block from `ConfigureRemoteCertificateValidationCallback` and only swaps the delegate. Implement it by delegating to `ConfigureRemoteCertificateValidationCallback` so the handler logic lives in one place. This file is generated, so make the change in the generator template.</comment>

<file context>
@@ -23,6 +25,59 @@ namespace Org.OpenAPITools.Extensions
+        /// Disables TLS certificate validation for requests made by this client.
+        /// Use only for development or testing.
+        /// </summary>
+        public static IHttpClientBuilder SkipCertificateCheck(this IHttpClientBuilder client)
+        {
+            client.Services.Configure<HttpClientFactoryOptions>(client.Name, (HttpClientFactoryOptions options) =>
</file context>
Suggested change
public static IHttpClientBuilder SkipCertificateCheck(this IHttpClientBuilder client)
{
client.Services.Configure<HttpClientFactoryOptions>(client.Name, (HttpClientFactoryOptions options) =>
{
options.HttpMessageHandlerBuilderActions.Add(builder =>
{
if (builder.PrimaryHandler is HttpClientHandler httpClientHandler)
httpClientHandler.ServerCertificateCustomValidationCallback = (request, certificate, chain, errors) => true;
#if NETCOREAPP || NETSTANDARD2_1_OR_GREATER
else if (builder.PrimaryHandler is SocketsHttpHandler socketsHttpHandler)
socketsHttpHandler.SslOptions.RemoteCertificateValidationCallback = (sender, certificate, chain, errors) => true;
#endif
else
throw new InvalidOperationException("Certificate validation requires HttpClientHandler or SocketsHttpHandler.");
});
});
return client;
}
public static IHttpClientBuilder SkipCertificateCheck(this IHttpClientBuilder client)
{
return client.ConfigureRemoteCertificateValidationCallback((sender, certificate, chain, errors) => true);
}


/// <summary>
/// Adds a Polly retry policy to your clients.
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,17 @@ namespace YourProject
}
}
```

## Certificate validation

To skip certificate validation for local development or testing, configure the generated HTTP clients as follows:

```cs
options.AddApiHttpClients(client => { }, builder => builder.SkipCertificateCheck());

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: The empty client => { } callback suppresses the default BaseAddress (http://localhost) set in HostConfiguration, so copying this snippet can leave the generated clients without a base address. Use the single-argument overload so the default is kept: options.AddApiHttpClients(builder => builder.SkipCertificateCheck());. Apply the same change to the README.client.mustache template.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At samples/client/petstore/csharp/generichost/latest/ComposedEnum/src/Org.OpenAPITools/README.md, line 89:

<comment>The empty `client => { }` callback suppresses the default `BaseAddress` (`http://localhost`) set in `HostConfiguration`, so copying this snippet can leave the generated clients without a base address. Use the single-argument overload so the default is kept: `options.AddApiHttpClients(builder => builder.SkipCertificateCheck());`. Apply the same change to the `README.client.mustache` template.</comment>

<file context>
@@ -80,6 +80,17 @@ namespace YourProject
+To skip certificate validation for local development or testing, configure the generated HTTP clients as follows:
+
+```cs
+options.AddApiHttpClients(client => { }, builder => builder.SkipCertificateCheck());
+```
+
</file context>
Suggested change
options.AddApiHttpClients(client => { }, builder => builder.SkipCertificateCheck());
options.AddApiHttpClients(builder => builder.SkipCertificateCheck());

```

Do not disable certificate validation in production.

<a id="questions"></a>
## Questions

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@

using System;
using System.Net.Http;
using System.Net.Security;
using Microsoft.Extensions.Http;
using Microsoft.Extensions.DependencyInjection;
using Polly.Timeout;
using Polly.Extensions.Http;
Expand All @@ -23,6 +25,59 @@ namespace Org.OpenAPITools.Extensions
/// </summary>
public static class IHttpClientBuilderExtensions
{
/// <summary>
/// Configures remote certificate validation for requests made by this client.
/// </summary>
public static IHttpClientBuilder ConfigureRemoteCertificateValidationCallback(
this IHttpClientBuilder client,
RemoteCertificateValidationCallback callback)
{
if (callback == null)
throw new ArgumentNullException(nameof(callback));

client.Services.Configure<HttpClientFactoryOptions>(client.Name, (HttpClientFactoryOptions options) =>
{
options.HttpMessageHandlerBuilderActions.Add(builder =>
{
if (builder.PrimaryHandler is HttpClientHandler httpClientHandler)
httpClientHandler.ServerCertificateCustomValidationCallback = (request, certificate, chain, errors) =>
callback(request, certificate, chain, errors);
#if NETCOREAPP || NETSTANDARD2_1_OR_GREATER
else if (builder.PrimaryHandler is SocketsHttpHandler socketsHttpHandler)
socketsHttpHandler.SslOptions.RemoteCertificateValidationCallback = callback;
#endif
else
throw new InvalidOperationException("Certificate validation requires HttpClientHandler or SocketsHttpHandler.");
});
});

return client;
}

/// <summary>
/// Disables TLS certificate validation for requests made by this client.
/// Use only for development or testing.
/// </summary>
public static IHttpClientBuilder SkipCertificateCheck(this IHttpClientBuilder client)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P3: SkipCertificateCheck duplicates the whole body of ConfigureRemoteCertificateValidationCallback, differing only in the callback. Delegate to the shared method so the handler dispatch lives in one place.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At samples/client/petstore/csharp/generichost/latest/HelloWorld/src/Org.OpenAPITools/Extensions/IHttpClientBuilderExtensions.cs, line 61:

<comment>`SkipCertificateCheck` duplicates the whole body of `ConfigureRemoteCertificateValidationCallback`, differing only in the callback. Delegate to the shared method so the handler dispatch lives in one place.</comment>

<file context>
@@ -23,6 +25,59 @@ namespace Org.OpenAPITools.Extensions
+        /// Disables TLS certificate validation for requests made by this client.
+        /// Use only for development or testing.
+        /// </summary>
+        public static IHttpClientBuilder SkipCertificateCheck(this IHttpClientBuilder client)
+        {
+            client.Services.Configure<HttpClientFactoryOptions>(client.Name, (HttpClientFactoryOptions options) =>
</file context>

{
client.Services.Configure<HttpClientFactoryOptions>(client.Name, (HttpClientFactoryOptions options) =>
{
options.HttpMessageHandlerBuilderActions.Add(builder =>
{
if (builder.PrimaryHandler is HttpClientHandler httpClientHandler)
httpClientHandler.ServerCertificateCustomValidationCallback = (request, certificate, chain, errors) => true;
#if NETCOREAPP || NETSTANDARD2_1_OR_GREATER
else if (builder.PrimaryHandler is SocketsHttpHandler socketsHttpHandler)
socketsHttpHandler.SslOptions.RemoteCertificateValidationCallback = (sender, certificate, chain, errors) => true;
#endif
else
throw new InvalidOperationException("Certificate validation requires HttpClientHandler or SocketsHttpHandler.");
});
});

return client;
}

/// <summary>
/// Adds a Polly retry policy to your clients.
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,17 @@ namespace YourProject
}
}
```

## Certificate validation

To skip certificate validation for local development or testing, configure the generated HTTP clients as follows:

```cs
options.AddApiHttpClients(client => { }, builder => builder.SkipCertificateCheck());
```

Do not disable certificate validation in production.

<a id="questions"></a>
## Questions

Expand Down
Loading
Loading