I implemented a health check endpoint following this doc. My ASP.NET application is dockerized and runs using docker-compose, with the port mapped/exposed.
Question: I am not sure how to query the health check endpoint from clients such as postman.
When I send a GET request to the /healthz endpoint as the following, postman throws the following error.
http://host.docker.internal:1200/healthz
Error: Client network socket disconnected before secure TLS connection was established
while I can see the following in the logs of the docker container.
[05:01:03 DBG] Connection id "0HMLSHSV1HRD2" accepted.
[05:01:03 DBG] Connection id "0HMLSHSV1HRD2" started.
[05:01:03 INF] Request starting HTTP/1.1 GET http://host.docker.internal:1200/healthz - -
[05:01:03 DBG] Wildcard detected, all requests with hosts will be allowed.
[05:01:03 VRB] All hosts are allowed.
[05:01:03 DBG] 1 candidate(s) found for the request path '/healthz'
[05:01:03 DBG] Request matched endpoint 'Health checks'
[05:01:03 DBG] Static files was skipped as the request already matched an endpoint.
[05:01:03 DBG] Https port '1200' loaded from configuration.
[05:01:03 DBG] Redirecting to 'https://host.docker.internal:1200/healthz'.
[05:01:03 DBG] Connection id "0HMLSHSV1HRD2" completed keep alive response.
[05:01:03 INF] Request finished HTTP/1.1 GET http://host.docker.internal:1200/healthz - - - 307 0 - 89.5220ms
Related
I'm trying to config a web api with SignalR enabled, so I can push real-time information to the clients via websockets. In front of the api I have a nginx reverse ssl proxy running in a docker container.
Clients can connect just fine via the reverse proxy when ssl is disabled in the nginx configuration:
server {
listen 55555;
# listen 55555 ssl;
ssl_certificate /config/keys/cert.crt;
ssl_certificate_key /config/keys/cert.key;
location / {
proxy_pass http://192.168.1.175:50000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
But when I configure the proxy to listen for ssl the clients can't seem to connect, or at least the client gets a "The server disconnected before the handshake could be started" IOException after what appears to be a time out.
WebAPI log:
info: Microsoft.AspNetCore.Hosting.Diagnostics[1]
Request starting HTTP/1.1 POST http://192.168.1.150/chatHub/negotiate?negotiateVersion=1 - 0
info: Microsoft.AspNetCore.Routing.EndpointMiddleware[0]
Executing endpoint '/chatHub/negotiate'
dbug: Microsoft.AspNetCore.Http.Connections.Internal.HttpConnectionManager[1]
New connection i-HjjQP9EsA_rBTX7vFs2Q created.
dbug: Microsoft.AspNetCore.Http.Connections.Internal.HttpConnectionDispatcher[10]
Sending negotiation response.
info: Microsoft.AspNetCore.Routing.EndpointMiddleware[1]
Executed endpoint '/chatHub/negotiate'
info: Microsoft.AspNetCore.Hosting.Diagnostics[2]
Request finished HTTP/1.1 POST http://192.168.1.150/chatHub/negotiate?negotiateVersion=1 - 0 - 200 316 application/json 117.3988ms
info: Microsoft.AspNetCore.Hosting.Diagnostics[1]
Request starting HTTP/1.1 POST http://192.168.1.150/chatHub/negotiate?negotiateVersion=1 - 0
info: Microsoft.AspNetCore.Routing.EndpointMiddleware[0]
Executing endpoint '/chatHub/negotiate'
dbug: Microsoft.AspNetCore.Http.Connections.Internal.HttpConnectionManager[1]
New connection K0y7OI3-3KvPIXWV92HEkA created.
dbug: Microsoft.AspNetCore.Http.Connections.Internal.HttpConnectionDispatcher[10]
Sending negotiation response.
info: Microsoft.AspNetCore.Routing.EndpointMiddleware[1]
Executed endpoint '/chatHub/negotiate'
info: Microsoft.AspNetCore.Hosting.Diagnostics[2]
Request finished HTTP/1.1 POST http://192.168.1.150/chatHub/negotiate?negotiateVersion=1 - 0 - 200 316 application/json 11.6330ms
info: Microsoft.AspNetCore.Hosting.Diagnostics[1]
Request starting HTTP/1.1 GET http://192.168.1.150/chatHub?id=zdDUpBZ-RsnQgEZsJ9Sctg - -
info: Microsoft.AspNetCore.Routing.EndpointMiddleware[0]
Executing endpoint '/chatHub'
dbug: Microsoft.AspNetCore.Http.Connections.Internal.HttpConnectionDispatcher[4]
Establishing new connection.
dbug: Microsoft.AspNetCore.SignalR.HubConnectionHandler[5]
OnConnectedAsync started.
dbug: Microsoft.AspNetCore.SignalR.HubConnectionContext[2]
Handshake was canceled.
dbug: Microsoft.AspNetCore.Http.Connections.Internal.HttpConnectionManager[2]
Removing connection zdDUpBZ-RsnQgEZsJ9Sctg from the list of connections.
info: Microsoft.AspNetCore.Routing.EndpointMiddleware[1]
Executed endpoint '/chatHub'
info: Microsoft.AspNetCore.Hosting.Diagnostics[2]
Request finished HTTP/1.1 GET http://192.168.1.150/chatHub?id=zdDUpBZ-RsnQgEZsJ9Sctg - - - 200 - text/event-stream 60079.4344ms
I've tried including the following in the WebApplication settings:
builder.Services.Configure<ForwardedHeadersOptions>(options =>
{
options.KnownProxies.Add(IPAddress.Parse("192.168.1.150")); // Proxy Server IP
});
app.UseForwardedHeaders(new ForwardedHeadersOptions
{
ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto | ForwardedHeaders.XForwardedHost
});
But as far as I can tell, it doesn't really make a difference.
I'm unsure whether this is a nginx reverse proxy/sll or a Webpi/SignalR issue. Any ideas? :)
I want to use Serilog for my .Net 5 Web Api project. I installed the packages
Serilog.AspNetCore v4.1.0
Serilog.Sinks.Console v4.0.0
and changed the Program.cs file to
public sealed class Program
{
public static void Main(string[] args)
{
Log.Logger = new LoggerConfiguration()
.WriteTo.Console()
.CreateLogger();
CreateHostBuilder(args)
.Build()
.Run();
}
private static IHostBuilder CreateHostBuilder(string[] args)
=> Host
.CreateDefaultBuilder(args)
.UseSerilog()
.ConfigureWebHostDefaults(webBuilder => { webBuilder.UseStartup<Startup>(); });
}
I created a single controller for testing purposes
[ApiController]
[Route("[controller]")]
public sealed class TodosController : ControllerBase
{
[HttpGet("{todoId:Guid}")]
public IActionResult GetTodoById(Guid todoId) => Ok(todoId);
}
After consuming this endpoint I can see the following in the console
[22:30:11 INF] Now listening on: https://localhost:5001
[22:30:11 INF] Now listening on: http://localhost:5000
[22:30:11 INF] Application started. Press Ctrl+C to shut down.
[22:30:11 INF] Hosting environment: Development
[22:30:11 INF] Content root path: /home/.../Server
[22:30:12 INF] Request starting HTTP/2 GET https://localhost:5001/swagger - -
[22:30:12 INF] Request finished HTTP/2 GET https://localhost:5001/swagger - - - 301 0 - 78.0119ms
[22:30:12 INF] Request starting HTTP/2 GET https://localhost:5001/swagger/index.html - -
[22:30:12 INF] Request finished HTTP/2 GET https://localhost:5001/swagger/index.html - - - 200 - text/html;charset=utf-8 64.9042ms
[22:30:12 INF] Request starting HTTP/2 GET https://localhost:5001/swagger/swagger-ui.css - -
[22:30:12 INF] Request starting HTTP/2 GET https://localhost:5001/swagger/swagger-ui-bundle.js - -
[22:30:12 INF] Request starting HTTP/2 GET https://localhost:5001/swagger/swagger-ui-standalone-preset.js - -
[22:30:12 INF] Sending file. Request path: '/swagger-ui-standalone-preset.js'. Physical path: 'N/A'
[22:30:12 INF] Sending file. Request path: '/swagger-ui.css'. Physical path: 'N/A'
[22:30:12 INF] Sending file. Request path: '/swagger-ui-bundle.js'. Physical path: 'N/A'
[22:30:12 INF] Request finished HTTP/2 GET https://localhost:5001/swagger/swagger-ui-bundle.js - - - 200 986342 application/javascript 191.4506ms
[22:30:12 INF] Request finished HTTP/2 GET https://localhost:5001/swagger/swagger-ui-standalone-preset.js - - - 200 311804 application/javascript 191.4478ms
[22:30:12 INF] Request finished HTTP/2 GET https://localhost:5001/swagger/swagger-ui.css - - - 200 142933 text/css 192.6142ms
[22:30:13 INF] Request starting HTTP/2 GET https://localhost:5001/swagger/v1/swagger.json - -
[22:30:13 INF] Request finished HTTP/2 GET https://localhost:5001/swagger/v1/swagger.json - - - 200 - application/json;charset=utf-8 83.3874ms
[22:30:41 INF] Request starting HTTP/2 GET https://localhost:5001/Todos/00119201-3fed-4741-8295-48d697790729 - -
[22:30:41 INF] Executing endpoint 'Server.Controllers.TodosController.GetTodoById (Server)'
[22:30:41 INF] Route matched with {action = "GetTodoById", controller = "Todos"}. Executing controller action with signature System.Threading.Tasks.Task`1[Microsoft.AspNetCore.Mvc.IActionResult] GetTodoById(System.Guid) on controller Server.Controllers.TodosController (Server).
[22:30:41 INF] Executing OkObjectResult, writing value of type 'System.Guid'.
[22:30:41 INF] Executed action Server.Controllers.TodosController.GetTodoById (Server) in 34.6663ms
[22:30:41 INF] Executed endpoint 'Server.Controllers.TodosController.GetTodoById (Server)'
[22:30:41 INF] Request finished HTTP/2 GET https://localhost:5001/Todos/00119201-3fed-4741-8295-48d697790729 - - - 200 - application/json;+charset=utf-8 121.1434ms
I don't think this is a desired behaviour (if the log level is information instead of trace). Did I miss something? How to prevent Serilog from logging without being asked for it?
I already checked this question Serilog - MinimumLoggingLevel Information shows every request in log - is that normal? but that didn't help. The Serilog.Web.Classic package is not installed.
These logs are being written by the ASP .NET host with the level Information and thus Serilog receives them as Information as well.
What you can do, is override the MinimumLevel for different sources, so that you can continue to receive Information-level logs written by some sources, whilst ignoring Information-level logs written by the host.
Here's an example that:
Sets the overall MinimumLevel to Information
Overrides the MinimumLevel to Warning only for logs coming from the Microsoft source
Overrides the MinimumLevel to Information only for logs coming from the Microsoft.Hosting.Lifetime source
e.g.
Log.Logger = new LoggerConfiguration()
.MinimumLevel.Information()
.MinimumLevel.Override("Microsoft", LogEventLevel.Warning)
.MinimumLevel.Override("Microsoft.Hosting.Lifetime", LogEventLevel.Information)
.WriteTo.Console()
.CreateLogger();
You can also configure these source overrides via appSettings.json:
{
"Serilog": {
"MinimumLevel": {
"Default": "Information",
"Override": {
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
}
},
"AllowedHosts": "*"
}
You need to set up log level for "Microsoft.Hosting.Lifetime" and "Microsoft". Personally I use Serilog.Settings.Configuration package, adding .ReadFrom.Configuration(configuration) to the set up and copying values provided by default template to Serilog.MinimumLevel.Override json property in config:
"Serilog": {
"MinimumLevel": {
"Default": "Information",
"Override": {
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
}
},
I have an ASP.NET core 1.0 app running on ubuntu 16.04 behind nginx/1.10.0. However, I notice that intermittently nginx throws the following error (in nginx error-log)
2017/06/08 05:19:19 [error] 11572#11572: *119049 upstream prematurely closed connection while reading response header from upstream, client: <ipaddress>, server: <servername>, request: "POST /<uri> HTTP/1.1", upstream: "http://127.0.0.1:5000/<uri>", host: "<servername>"
which results in a 502 Bad Gateway to the client although the request completes successfully in the application
2017-06-08 05:19:14.399 [DBG] Executed action method "<Controller.Action>", returned result "Microsoft.AspNetCore.Mvc.CreatedAtRouteResult
Could this be an nginx configuration issue or ASP.NET/Kestrel issue? Can someone give me hints to debug this?
Further notes:
I also see the following in the application log just after request completion
2017-06-08 05:19:14.399 [DBG] Executed action method "<Controller.Action>", returned result "Microsoft.AspNetCore.Mvc.CreatedAtRouteResult
2017-06-08 05:19:18.632 [DBG] Some connections failed to close gracefully during server shutdown.
2017-06-08 05:19:22.402 [DBG] Hosting starting
2017-06-08 05:19:22.689 [DBG] Hosting started
and the nginx error is just around the same time 2017/06/08 05:19:19
Also, normally in the logs I see messages around Executing ObjectResult and Executed time etc. which I don't see with the above request
2017-06-08 00:10:14.391 [DBG] Selected output formatter '"Microsoft.AspNetCore.Mvc.Formatters.JsonOutputFormatter"' and content type '"application/json"' to write the response.
2017-06-08 00:10:14.391 [INF] Executing ObjectResult, writing value "Microsoft.AspNetCore.Mvc.ControllerContext".
2017-06-08 00:10:14.504 [INF] Executed action "<Controller.Action>" in 1875.3845ms
I have a client-server application that works using a https connection with a self signed certificate and a Nancy Selfhost server.
After installing the application i run the following scripts to prepeare the server.
Add SSL Certificate to store
Check witch ip:ports are configured with netsh http show sslcert
Remove all registrations with port number 4443 (only if they are found with previous step):
netsh http del sslcert ipport=0.0.0.0:4443
netsh http del sslcert ipport=[::]:4443
netsh http del urlacl url=https://+:4443/
And then add url reservation with: netsh http add urlacl url=https://+:4443/ user=everyone
Add SSL Certicates with:
netsh http add sslcert ipport=0.0.0.0:4443 certhash=XXX appid={XXX}
netsh http add sslcert ipport=[::]:4443 certhash=XXX appid={XXX}
Then I start the server. The code for starting the self host server is:
public void Start(string baseUrl) {
string url = baseUrl;
Uri uri = new Uri(url);
var uris = new[]
{
new Uri($"{uri.Scheme}://localhost:{uri.Port}"),
};
server = new NancyHost(new CustomBootstrapper(url, Api1, Api2, applicationConfiguration), uris);
server.Start();
}
In this code is the baseURL the Hostname of the machine.
The client server connection works in most cases, but one situation it doesn't. This is when i try to run the the server on a specific computer. It has the following differences from other servers:
Windows 8
Pinging the hostname of this returns a IPv6 adress.
When starting the client application, it gives the following error:
The underlying connection was closed: Could not establsh trust relationship for the ssl/tls secure channel
Now i'm stuck, because I am not sure why it would not work.
Apparently I had some old certification registrations and url reservations still active. After clearing them all, the issue was resolved.
When I open a web socket to my server - it looks like the client is automatically sending an HTTP request as part of the first payload. How can I prevent this?
That is the nature of the web socket protocol. It starts with a handshake done over simple HTTP
GET /mychat HTTP/1.1
Host: server.example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==
Sec-WebSocket-Protocol: chat
Sec-WebSocket-Version: 13
Origin: http://example.com
More: http://en.wikipedia.org/wiki/WebSocket#WebSocket_protocol_handshake
You cannot create a websocket without this handshake.