I need to start a webserver without a specific IP and Port with HTTP 1.1 and HTTP 2.
After start, i need to provide the webservers IP, Port and HTTP version of each url.
var builder = WebApplication.CreateBuilder();
...
builder_.WebHost.UseKestrel(options =>
{
options.ListenAnyIP(0, (listenOptions) =>
{
listenOptions.Protocols = HttpProtocols.Http1;
});
options.ListenAnyIP(0, (listenOptions) =>
{
listenOptions.Protocols = HttpProtocols.Http2;
});
});
...
var app = builder.Build();
// Start application
_ = app.RunAsync();
// Does only provide IP and Port but not HTTP version
var urls = app.Urls;
ASP.NET Core .net6.0
So far i was unable to retrieve the HTTP Version of the webservers endpoints from the "WebApplication" class.
Related
I have a C# / ASP.NET Core Web API project running on https://localhost:7001 and a next js app running on http://localhost:3000.
I can run the C# API from swagger and directly in the browser (https://localhost:7001/api/SourceSystems), but when I try to call it from the next js page using GetStaticProps, I get a 500 error.
Next.js code:
export default function Sourcesystem({systems}) {
return (
<ul>
{systems.map((system) => (
<li key={system.systemName}>{system.systemName} </li>
))}
</ul>
)
};
// This function gets called at build time
export async function getStaticProps() {
// Call an external API endpoint to get posts
const res = await fetch(
'https://localhost:7001/api/Schedules',
{
method:'GET',
}
)
const systems = await res.json()
console.log(systems);
return {
props: {
systems
},
}
}
I have added CORS to the c# code (I think) in
program.cs
var MyAllowSpecificOrigins = "_myAllowSpecificOrigins";
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddCors(options =>
{
options.AddPolicy(name: MyAllowSpecificOrigins,
builder =>
{
builder.WithOrigins(
"http://example.com",
"http://www.contoso.com",
"http://localhost:3000"
);
});
});
// services.AddResponseCaching();
builder.Services.AddControllers();
// add dbContext
builder.Services.AddDbContext<GdqcDevContext>(options => options.UseSqlServer("Data Source = RAZERPRO17; Initial Catalog = GDQC_dev; Integrated Security = True; Connect Timeout = 30; Encrypt = False; TrustServerCertificate = False; ApplicationIntent = ReadWrite; MultiSubnetFailover = False"));
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
var app = builder.Build();
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseCors(MyAllowSpecificOrigins);
app.UseAuthorization();
app.MapControllers();
app.Run();
Next is saying the the fetch failed:
I am suspecting something still not set correctly for CORS but I have copied the CORS configuration and the middleware assignment order from documentation and other stackoverflow answers. NOTE: I am running the c# API code using the debug browser rather than directly from IIS. I have read somewhere about the OPTIONS but this is only for the full blown IIS
I have also added a CORS guard annotation to the c# controller with no success
namespace Overwatch_API.Controllers
{
[EnableCors("MyAllowSpecificOrigins")]
[Route("api/[controller]")]
[ApiController]
public class SourceSystemsController : ControllerBase
{
private readonly GdqcDevContext _context;
public SourceSystemsController(GdqcDevContext context)
{
_context = context;
}
// GET: api/SourceSystems
[HttpGet]
public async Task<ActionResult<IEnumerable<SourceSystem>>> GetSourceSystems()
...
UPDATE: It looks like Next is returning the following error message in the logging:
cause: Error: self-signed certificate
at TLSSocket.onConnectSecure (node:_tls_wrap:1538:34)
at TLSSocket.emit (node:events:513:28)
at TLSSocket._finishInit (node:_tls_wrap:952:8)
at ssl.onhandshakedone (node:_tls_wrap:733:12) {
code: 'DEPTH_ZERO_SELF_SIGNED_CERT'
I presume this is related to the SSL cert on the .net core 6 api code, as this is being called with https. How do I get next to accept a self signed cert, or build a propertly signed cert for the dev environment
This issue is common in nextjs.
I found two ways to fixed it.
1. If the issue occurs in dev environment. we can use NODE_TLS_REJECT_UNAUTHORIZED=0 to solve it.
① Overcome the DEPTH_ZERO_SELF_SIGNED_CERT on Node.js
② Self Signed SSL Certificate in NextJS
2. We also can use NODE_EXTRA_CA_CERTS to solve it. It can be used in Dev or Prod Environment.
Node TLS socket : DEPTH_ZERO_SELF_SIGNED_CERT error
I have an ASP.NET Core Web API running in a Linux Docker container orchestrated using Docker compose. When I try to access the Swagger endpoint of the Web API on HTTPS, the browser cannot reach the endpoint, and I see the following error in the Web API logs.
Detected a TLS handshake to an endpoint that does not have TLS enabled
After reading this topic, I "fixed" the issue by adding the following to my configuration. However, I am not sure why this is needed. It seems overkill and has too much complexity to enable HTTPS, so I am wondering if I am missing something.
builder.WebHost.ConfigureKestrel(options =>
{
options.Listen(
address: IPAddress.Any,
port: 443,
configure: listenOptions =>
{
listenOptions.Protocols = HttpProtocols.Http1AndHttp2;
listenOptions.UseHttps(new TlsHandshakeCallbackOptions
{
OnConnection = context =>
{
if (string.Equals(context.ClientHelloInfo.ServerName, "localhost", StringComparison.OrdinalIgnoreCase) ||
string.Equals(context.ClientHelloInfo.ServerName, "host.docker.internal", StringComparison.OrdinalIgnoreCase))
{
// Different TLS requirements for this host
context.AllowDelayedClientCertificateNegotation = true;
return new ValueTask<SslServerAuthenticationOptions>(
new SslServerAuthenticationOptions
{
ServerCertificate = new X509Certificate2("/root/.aspnet/https/webapi.pfx", "password")
});
}
return new ValueTask<SslServerAuthenticationOptions>(
new SslServerAuthenticationOptions
{
ServerCertificate = new X509Certificate2("/root/.aspnet/https/webapi.pfx", "password")
});
}
});
});
});
I have tried every other ways to set Access-Control-Allow-Origin : * in my Blazor Static Web App.
I follow this documentation Configure Azure Static Web Apps first to set globalHeaders. It isn't working.
And I try to add Cors in builder services. It isn't working too.
builder.Services.AddScoped (sp => new HttpClient
{ BaseAddress = new Uri(builder.Configuration["API_Prefix"] ??
builder.HostEnvironment.BaseAddress) });
builder.Services.AddCors(options =>
{ options.AddPolicy(name: policyName,
builder =>
{ builder.WithOrigins("https://localhost:5000") // specifying the allowed origin
.WithMethods("GET") // defining the allowed HTTP method
.AllowAnyHeader(); // allowing any header to be sent
});
});
await builder.Build().RunAsync();
And I tried it also in individual HttpClient request in the following.
// create request object
var request = new HttpRequestMessage(HttpMethod.Get, uri);
// add custom http header
request.Headers.Add("Access-Control-Allow-Origin", "*");
request.Headers.Add("Access-Control-Allow-Methods", "GET");
// send request
var httpResponse = await Http.SendAsync(request);
I had used this tutorial to create [Blazor Static Web App].2
This is the error I got in the browser's console. ].3
What am I missing to set the correct configuration?
Restrict Domain consumption of services by CORS browser restriction. But when you hit the service service will get executed but the response wont captured in browser side. By adding following code in API program.cs will allow specific Domains
builder.Services.AddCors(options =>
{
options.AddDefaultPolicy(policy =>
{
policy.WithOrigins("http://192.168.10.127",
"https://localhost:5000",
"https://localhost:5001")
.AllowAnyHeader()
.AllowAnyMethod();
});
});
app.UseCors();
To allow from any Domain follow below code
app.UseCors(options => options.SetIsOriginAllowed(x => _ = true).AllowAnyMethod().AllowAnyHeader().AllowCredentials());
I have created a Blazor WebAssembly application with ASP Hosted, on the server I preload the blazor application following the microsoft tutorials.
There is a point in the documentation where it tells me that I have to create a new method to map the Blazor services to the server.
Here is my method:
namespace Test.Client
{
public class CommonServices
{
public static void ConfigureCommonServices(IServiceCollection services, Uri uri)
{
services.AddScoped(sp => new HttpClient { BaseAddress = uri });
services.AddBlazoredLocalStorage();
services.AddScoped<IAuthService, AuthService>();
services.AddScoped<IAdvertiserService, AdvertiserService>();
services.AddScoped<ICategoryService, CategoryService>();
services.AddScoped<IItemService, ItemService>();
services.AddScoped<IItemVariantService, ItemVariantService>();
services.AddScoped<IPriceMonitorService, PriceMonitorService>();
services.AddFileReaderService(o => o.UseWasmSharedBuffer = true);
services.AddOptions();
services.AddAuthorizationCore();
services.AddScoped<AuthenticationStateProvider, CustomAuthStateProvider>();
}
}
}
And I load it on the client like this in Program.cs:
var builder = WebAssemblyHostBuilder.CreateDefault(args);
var uri = new Uri(builder.HostEnvironment.BaseAddress);
CommonServices.ConfigureCommonServices(builder.Services, uri);
await builder.Build().RunAsync();
The problem I have in the server Program.cs, I don't know how I can get the base address in this one, if I map it fixed it works, but when I take it to production logically this configuration stops working...
var uri = new Uri("https://localhost:7278/");
Test.Client.CommonServices.ConfigureCommonServices(builder.Services, uri);
var app = builder.Build();
My question is how can I get the correct url on the server? and if there is a better way to do this?
Using aspnetcore 3.1 and the Grpc.AspNetCore nuget package, I have managed to get gRPC services running successfully alongside standard asp.net controllers as described in this tutorial.
However I would like to bind the gRPC services to a specific port (e.g. 5001), preferably through configuration instead of code if possible. This is because I would like to limit how my gRPC services are exposed.
The closest I have come has been using RequireHost when mapping the endpoints:
// Startup.cs
public void Configure(IApplicationBuilder app)
{
// ...
app.useEndpoints(endpoints =>
{
endpoints.MapGrpcService<MyService>()
.RequireHost("0.0.0.0:5001");
});
}
This seems to do what I want but I can't find any documentation about it, and it requires configuration in code per service. Perhaps there is a better way?
This works (server side) with Kestrel:
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.ConfigureKestrel(options =>
{
options.Listen(IPAddress.Loopback, 5000);
options.Listen(IPAddress.Loopback, 5005, configure => configure.UseHttps());
});
webBuilder.UseStartup<Startup>();
});
client side:
var httpHandler = new HttpClientHandler
{
ServerCertificateCustomValidationCallback =
HttpClientHandler.DangerousAcceptAnyServerCertificateValidator
};
AppContext.SetSwitch("System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport", true);
using var channel = GrpcChannel.ForAddress("https://localhost:5005", new GrpcChannelOptions { HttpHandler = httpHandler } );
var client = new Greeter.GreeterClient(channel);
Note:
var httpHandler = new HttpClientHandler
{
ServerCertificateCustomValidationCallback =
HttpClientHandler.DangerousAcceptAnyServerCertificateValidator
};
when you have a self-signed certificate without a trust chain (mostly when developing).
AppContext.SetSwitch("System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport", true);
Is for support of http.
You need to configure the middleware
app.UseRouting();
app.MapWhen(context => {
return context.Connection.LocalPort == 1000
}, newApp => {
newApp.UseRouting();
newApp.UseEndpoints(endpoints =>
{
endpoints.MapGrpcService<Service1>();
}
});
app.MapWhen(context => {
return context.Connection.LocalPort == 2000
}, newApp => {
newApp.UseRouting();
newApp.UseEndpoints(endpoints =>
{
endpoints.MapGrpcService<Service2>();
}
});
In the ASP.NET Core 6.0 ports can be changed in the Properties > launchSettings.json file. But this file is considered only if you run the server from the Visual Studio or VS Code.
I was trying to run the server directly using the .exe file for testing. The server was running with the default ports: "http://localhost:5000;https://localhost:5001".
Finally, I changed it from the appsettings.json for the .exe file:
"AllowedHosts": "*",
"Kestrel": {
"Endpoints": {
"Http": {
"Url": "https://localhost:7005",
"Protocols": "Http1AndHttp2"
},
"gRPC": {
"Url": "http://localhost:5005",
"Protocols": "Http2"
}
}
As far as I know, there is no other way to set a specific port for the GRPC service.
The grpc service is also running on the asp.net core kestrel server, the server will listen the port not the service.
If your asp.net core application just has GRPC service, you could just set the kestrel server's listen port to 5001.
If you have multiple service like MVC web api or else, RequireHost is the best workaround to allow only specific port access the grpc service.
If you want to prompt the routing system for GRPC service to require the specified port, you could use below port:
routes.MapGrpcService<MyService>().RequireHost("*:5001");
You can try to use the UseWhen method to use the MapGrpcService endpoints only when the request uses the port you defined.
var grpcPort = 5001;
app.UseWhen(context => context.Connection.LocalPort == grpcPort,
builder =>
{
builder.UseRouting();
builder.UseEndpoints(endpoints =>
{
endpoints.MapGrpcService<MyService>();
});
});
This has the benefit of not repeating .RequireHost("*:5001"); for every single service, although repeating UseRouting twice may induce weird behaviour: for instance, authentication may not be working unless you put in builder.UseAuthentication() after builder.UseRouting().
However, this behaviour be useful if you want to have a distinct request pipeline for REST and gRPC.