dotnet / aspnetcore

ASP.NET Core is a cross-platform .NET framework for building modern cloud-based web applications on Windows, Mac, or Linux.
https://asp.net
MIT License
35.37k stars 9.99k forks source link

UsePathBase regex #40959

Closed Alerinos closed 2 years ago

Alerinos commented 2 years ago

Is there an existing issue for this?

Is your feature request related to a problem? Please describe the problem.

I need to add a regex in UsePathBase, I want to culture the entire URL

Describe the solution you'd like

I am using blazor server side.

I currently have something like this:

            app.UsePathBase("/pl");
            app.UsePathBase("/pl-pl");
            app.UsePathBase("/en");
            app.UsePathBase("/en-us");
            app.UsePathBase("/de");
            app.UsePathBase("/it");

Need:

app.UsePathBase("/{culture:regex(^[a-zA-Z]{{2}}(-[a-zA-Z+]{{2}})?$)}");

This creates many problems but solves the one I care about. Thanks to this, we can have a culture in each URL. e.g: domain.com/en-us/register


                endpoints.MapGet("/{culture:regex(^[a-zA-Z]{{2}}(-[a-zA-Z+]{{2}})?$)=pl}/{**rest}", async context =>
                {
                    var culture = context.Request.RouteValues["culture"] ?? _website.Culture;
                    var rest = context.Request.RouteValues["rest"];

                    var option = new CookieOptions
                    {
                        Expires = DateTime.Now.AddYears(1)
                    };
                    context.Response.Cookies.Append("Culture", culture.ToString() ?? "", option);
                    await Task.CompletedTask;
                });

Unfortunately, when we use PathBase, this request will not be performed and it will not save the cookie culture. Do you have an idea how to do it?

The effect I want to get is written here: https://github.com/dotnet/aspnetcore/issues/38584#issuecomment-976637332

The problem of using app.UsePathBase is that a value is added to <base href = "~ /" />, so we need to change to <base href = "/" />

Additional context

Let me know what you think, in short I need to be able to prefix in the url. I need to support the culture as in the example in the link above.

adityamandaleeka commented 2 years ago

@Alerinos we won't implement a feature for this (as you described, it creates many problems :) ) but you can implement this behavior yourself in middleware.

You'll want to do something like this: https://source.dot.net/#Microsoft.AspNetCore.Http.Abstractions/Extensions/UsePathBaseMiddleware.cs,49

Alerinos commented 2 years ago

@adityamandaleeka https://gyazo.com/9769db6352bbb42d03c64c40391f96ae I found an error, after adding this code the server side generates the content well, but after connecting to "_blazor" it extracts the information about the missing page.

app.Use((context, next) =>
{
    if (context.Request.Path == "/en-us/counter")
    {
        context.Request.Path = "/counter";
    }
    return next();
});

Program.cs:

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.
builder.Services.AddRazorPages();
builder.Services.AddServerSideBlazor();
builder.Services.AddSingleton<WeatherForecastService>();

var app = builder.Build();

// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error");
    // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
    app.UseHsts();
}

app.Use((context, next) =>
{
    if (context.Request.Path == "/en-us/counter")
    {
        context.Request.Path = "/counter";
    }
    return next();
});

app.UseHttpsRedirection();

app.UseStaticFiles();

app.UseRouting();

app.MapBlazorHub();
app.MapFallbackToPage("/_Host");

app.Run();
ghost commented 2 years ago

This issue has been resolved and has not had any activity for 1 day. It will be closed for housekeeping purposes.

See our Issue Management Policies for more information.

rjgotten commented 2 years ago

@Alerinos FWIW; keep in mind that using PathBase when you also need to support generating links to switch between different cultures/locales/languages is a bit of a pain. You need to use the signatures for link generator where you explicitly pass the pathBase parameter; can't pass it as a route value. And that also means pain when you have an application using e.g. asp-* tag helpers.

Moreover; consider that PathBase is added to each and every generated link. You may not want that when generating links to resources that are not localized at all, e.g. CSS or JavaScript assets.

The proper solution would be to wrangle the endpoint routing system to add the culture to the route. But, because of how the system for merging ambient and current route values works, it will still delete the ambient culture even though it would be 'more to the left' - i.e. higher up the path hierarchy - than action/controller or other route values. Meaning you need to pass the culture to use on all your link generation. ... Or you hack the system and author and register into the IServiceCollection an implementation of LinkGenerator which decorates DefaultLinkGenerator and which forcibly reintroduces the ambient culture routeValue as a current culture routeValue before passing on to the default generator's GetPathByAddress and GetUriByAddress methods.

That gives you your cake and allows you to eat it.


Situation would be a whoooo----le lot better if the merging of ambient and current route values could use information about the hierarchical order of the tokens in the routes. But afaik it currently can't; mainly because the routes aren't tried one by one anymore with endpoint routing. They're pre-assembled into one big directed graph and it all is evaluated together in one go.

...

Wonder if the DFA building could be extended to support that somehow though.

blowdart commented 2 years ago

As an aside if you're going to do this yourself please put a timeout on the regex, otherwise you may end up with catastrophic backtracking DoS attacks depending on your expression.

ghost commented 2 years ago

This issue has been resolved and has not had any activity for 1 day. It will be closed for housekeeping purposes.

See our Issue Management Policies for more information.