Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What's the difference between HttpRequest.Path and HttpRequest.PathBase in ASP.NET Core?

As detailed here: https://docs.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.http.httprequest?view=aspnetcore-3.0, ASP.NET Core's HttpRequest class includes both Path and PathBase properties.

What's the difference between these two properties? What's each one used for? What's the meaning of PathBase? What's the significance of having both a Path and a PathBase?

I can't find any documentation detailing why it is as it is - any ideas?

like image 391
James Law Avatar asked Oct 29 '19 20:10

James Law


1 Answers

In ASP.NET core there is this concept known as the path base. The basic idea is quite easy to understand: the path base is considered to be a fixed prefix for the path of all the incoming requests to your web application. By default the path base is considered to be the empty string.

This means that, by default, when a request enters your application, all the path portion of the request's URL will be mapped to the Path property of the HttpRequest object and the PathBase property will be set to string.empty.

As an example consider an asp.net core application running in your local machine and listening to port 3000. Suppose that you are running the application by using the raw kestrel web server (so there is no reverse proxy involved, requests arrive directly to kestrel).

When you request the URL http://localhost:3000/foo/bar then the HttpRequest object will have the following properties:

  • HttpRequest.Path will be set to /foo/bar
  • HttpRequest.PathBase will be set to string.empty

You will get the same situation when you decide to host your application on Azure, by using a windows app service.

In this hosting scenario the default for an ASP.NET core web application is being executed inside the same process as the IIS worker process. This basically means that there is only one process involved; again there is no reverse proxy and the kestrel web server is not used at all: the request is handled by IIS directly (you can find some details here if you are interested).

In that case the public URL for your application will be something like https://my-application.azurewebsites.net. When you browse to the URL https://my-application.azurewebsites.net/foo/bar, the situation for the incoming http request will be the following:

  • HttpRequest.Path will be set to /foo/bar
  • HttpRequest.PathBase will be set to string.empty

Again, as before, the path base is the empty string.

There are different hosting scenarios where you may decide to expose your application by using a virtual directory.

For instance, you may decide to host the asp.net core web application in your own datacenter by using a windows virtual machine having IIS installed. In that case you may have an existing web site in IIS and you want to create a virtual application having a proper alias under that web site. Again in this scenario, as explained above for the azure windows app service, there is no reverse proxy involved and the kestrel web server is not used at all: the request is handled directly by the IIS worker process (in process hosting model).

Suppose that the public URL of your web site is https://sample-application.contoso.net and that you have chosen the sample-alias as the alias for the virtual application. This implies that all the requests to your asp.net core web application will have a path portion starting by sample-alias. For instance, when you want to require the home page of your application you will browse to https://sample-application.contoso.net/sample-alias.

In this case when you request the URL https://sample-application.contoso.net/sample-alias/foo/bar, the HttpRequest object in your application will be done in the following manner:

  • HttpRequest.Path will be set to /foo/bar
  • HttpRequest.PathBase will be set to sample-alias

Due to the way the default web host for an ASP.NET core application is built, this scenario involving IIS virtual applications works out of the box and the middleware pipeline is aware of the common prefix to all the incoming HTTP requests and it is able to set the path base to sample-alias and the path property to the remaining part of the incoming request's path (/foo/bar in my example above).

As a rule of thumb, you can consider that an ASP.NET core web application works fine without any additional configurations when you want to host it by using IIS. This is true for the path base property too (check here to verify that the request base path is set automatically inside your application at the stratup).

As a last example consider hosting your application on a Linux machine, by using nginx as a reverse proxy. In this case your application will be executed inside the kestrel web server, but it won't be directly exposed to the public internet. The thing being exposed to the public internet is the nginx web server which routes the incoming HTTP requests to the kestrel web server (where your application is executed). You may decide to configure your nginx so that all requests starting by the prefix /awesome-application will be routed to your asp.net core web application.

As an example, suppose to expose nginx to the public internet at the URL https://ingress.contoso.net: in this case if you want to request the home page of your application you need to browse to https://ingress.contoso.net/awesome-application/.

In this case you can't get the awesome-application request path base for free (by default, kestrel is not aware of it and it considers the request path base to be string.empty).

In order to make kestrel aware of the request path base you need to use the UsePathBaseMiddleware as the first item in your middleware pipeline.

If you need more details for this case, follow this documentation and see also this stackoverflow question.

like image 108
Enrico Massone Avatar answered Sep 20 '22 12:09

Enrico Massone