Retrieving UpstreamPathTemplate at runtime Ocelot Gateway - ocelot

I would like to retrieve the "UpstreamPathTemplate" parameter at run time, to use in my Logs. Does anyone know how to do this, please?

You can use some middleware in the OcelotPipelineConfiguration and access the route in the context.
Something like that:
{
//PreQueryStringBuilderMiddleware occurs after authorization
PreQueryStringBuilderMiddleware = async (ctx, next) =>
{
var upstreamRoute = ctx.DownstreamReRoute.UpstreamPathTemplate;
Log.Information($"{upstreamRoute}");
await next.Invoke();
}
};
Or implement your own ASP.NET middleware, catch all requests and log or whatever you want.

Related

ASP.NET Core URL rewriting with query parameters

I have a LitElement based SPA with an ASP.NET Core backend which hosts the static files and a REST API for loading data into the SPA.
The user starts with /index.html and the client-side router brings him to, f.e.,
/data-analysis or /dashboard.
When the user now presses the browser refresh button she gets 404 which is to be expected since the server does not know any of these subpaths.
I read elsewhere that I have to take care of this on the server side, so I came up with this middleware in my Startup.cs Configure method:
app.Use(async (c, next) =>
{
//Identify subpaths...
c.Request.Path = "/index.html";
await next();
});
For all subpaths it brings the user back to index.html which is nice. Better yet would be to let the client side know which subpath to restore. For this I added the following lines to the code above:
var url = c.Request.Path.Value;
c.Request.QueryString = c.Request.QueryString.Add("page", $"{url.Substring(1)}");
I expected the client to see a window.location of, f.e.
.../index.html?page=data-analysis
but the query string never arrives, window.location.search is always empty on the client side.
Is this possible at all or am I misunderstanding something here?
Nicolas
Studying Microsofts documentation about the URL rewriting middleware led me to the conclusion that I should redirect and not rewrite! The following code produces the desired result. Note that the 'return' statement is critical, because no further middleware should be called!
app.Use(async (c, next) =>
{
var url = c.Request.Path.Value;
//Identify subpaths...
if(... should redirect ...)
{
c.Response.Redirect($"/index.html?page={url.Substring(1)}");
return;
}
await next();
});

Get number of connections in ASP .NET Core 3.1 / Kestrel

I'm putting a limit on the number of concurrent connections to a webapp hosted by Kestrel using an approach like:
webBuilder.UseKestrel((context, options) =>
{
options.Configure(context.Configuration.GetSection("Kestrel"));
options.AddServerHeader = false;
// get limits
var maxConnections = context.Configuration.GetValue<int>("Kestrel:Limits:MaxConcurrentConnections");
var maxUpgradedConnections = context.Configuration.GetValue<int>("Kestrel:Limits:MaxConcurrentUpgradedConnections");
options.Limits.MaxConcurrentConnections = maxConnections;
options.Limits.MaxConcurrentUpgradedConnections = maxUpgradedConnections;
...
}
When receiving new requests I would like to check the servers current number of connections and perform a graceful deny by showing an error message about the connection limit have been reached. One approach I've tried has been adding middleware for checking, something like this:
public void Configure(IApplicationBuilder app)
{
app.Use(async (context, next) =>
{
// Insert limit check here
// Call the next delegate/middleware in the pipeline
await next();
});
}
The problem is that I have not found a way of getting the number of connections in Kestrel. Anyone knows how to get it? Or if this even is a viable approach?

Protecting static files with Authorization Middleware using IdentityServer4

I have a IS4 set up and most of the clients that use it get their pictures from a simple ASP.NET Core API. There is one method for adding pictures that go to wwwroot. I noticed that, while unauthorized users can't add new pictures, anyone can access the pictures if they know the URL. After a quick search, i found out that i need a middleware to protect static files, so i shamelessly used sir Alan's code from here. After modifying it for ASP.NET Core (unsure if i did it correctly), i couldn't get authorized from any of the clients (I would get a 401 response, so at least that works correctly).
Here are the services added:
services.AddAuthentication(
IdentityServerAuthenticationDefaults.AuthenticationScheme)
.AddIdentityServerAuthentication(options =>
{
options.Authority = "http://some.url";
options.ApiName = "SomeAPI";
options.RequireHttpsMetadata = false;
});
services.AddAuthorization(options =>
{
options.AddPolicy("Authenticated", policy => policy.RequireAuthenticatedUser());
});
And the Invoke method from ProtectFolder, that i modifyied:
public async Task Invoke(HttpContext httpContext,
IAuthorizationService authorizationService,
IAuthenticationService authenticationService)
{
if (httpContext.Request.Path.StartsWithSegments(_path))
{
var authenticated = await authenticationService.AuthenticateAsync(httpContext,
IdentityServerAuthenticationDefaults.AuthenticationScheme);
var authorized = await authorizationService.AuthorizeAsync(httpContext.User, null, _policyName);
if (!authorized.Succeeded)
{
await authenticationService.ChallengeAsync(httpContext,
IdentityServerAuthenticationDefaults.AuthenticationScheme, authenticated.Properties);
return;
}
}
await _next(httpContext);
}
So i managed to protect the files, but now I can't access them either. Since I'm using IS4 I'm pretty sure I need to use the token for authorization, but I'm unsure how.
I checked this answer and put UseAuthentication above UseProtectFolder and UseStaticFiles, but I still get a 401 response. I also checked this answer, but I'm unsure if it will help, since I'm not using the controller to get the files.

Passing Controller Action output as SupplyData in UseSpaPrerendering of .Net Core

In .Net Core application, I have below code in Configure method of Startup.cs file.
app.UseSpa(spa =>
{
spa.Options.SourcePath = "ClientApp";
spa.UseSpaPrerendering(options =>
{
options.BootModulePath = $"{spa.Options.SourcePath}/dist-server/main.js";
options.BootModuleBuilder = env.IsDevelopment() ? new AngularCliBuilder(npmScript: "build:ssr") : null;
options.ExcludeUrls = new[] { "/sockjs-node" };
});
if (env.IsDevelopment())
{
spa.UseAngularCliServer(npmScript: "start");
}
});
UseSpaPrerendering has an option to provide SupplyData callback which lets you pass arbitrary, per-request, JSON-serializable data.
In my case there are pages in my Angular application which makes http requests to fetch data. Since these requests are made to the same application. I see a potential of optimization i.e. if we could just call the corresponding Controller Action method and supply its data to Angular, so that we dont have to make an http request for SSR.
Can anyone please guide how to achieve this.
I know that below is how we pass data using SupplyData
options.SupplyData = (context, data) =>
{
// Creates a new value called isHttpsRequest that's passed to TypeScript code
data["isHttpsRequest"] = context.Request.IsHttps;
};
But how to we pass the results/output of a Controller Actions (which returns json).
I wrote a package to determine the currently activated SPA route from the supplydata delegate.
https://github.com/MusicDemons/AspNetSpaPrerendering
You have to define all your SPA routes using the SpaRouteBuilder and then you can check which route was activated and get the route data (like an id). Based on that you get data from your database through your repositories and add this data to the array. A complete example is included.

Parse-Server capture bad session token requests

Is there any way to capture bad session token requests on a remote parse-server app?
Unfortunately, verbose logs for bad session tokens only display a very not verbose error message that an invalid session token was used, whereas all other requests will display the full headers used to make a request. I need to get to those headers so I can identify the x-parse-session-token being sent.
I've discovered I can add some middleware doing something like this:
var myMiddleware = function (req, res, next) {
// extract request headers
next()
}
app.use(myMiddleware)
But I wouldn't yet know if the session token was valid or not at that point, and I don't think it'd be efficient to set up a whole extra middleware checking the validity of every session token that gets passed in.
Any tips on how I could get access to these x-parse-session-token headers for requests that are failing due to bad session tokens would be greatly appreciated.
One hacky way would be to override in your middleware the req.json call.
const myMiddleware = function (req, res, next) {
const json = res.json;
res.json = function(object) {
if (object.code == Parse.Error.INVALID_SESSION_TOKEN) {
// get the session token
const token = req.headers['x-parse-session-token'];
// Invalid token, do something
}
// Forward the response
json.call(res, object);
}
next()
}
server = new ParseServer({
applicationId: YOUR_APP_ID,
/* more options */
middleware: myMiddleware
});
// continue initialization here
This should do the trick what do you think?