Home > Software design >  Parse and modify a request before it's routed in .net core 6 mvc
Parse and modify a request before it's routed in .net core 6 mvc

Time:08-14

So an old program (windows exe) does a request to our site with this header:

"Accept-Charset[space]:ISO-8859-1"

And this throws a 400 Bad Request error. We cannot change that and remove the space (which would solve the nightmare) because that exe is already installed in a ton of computers.

This was not causing any issue when the web was a 20 year old ASP Web Forms, but now, the new NET 6 MVC doesn't like it.

The IAsyncActionFilter filter is not a solution as the BAD Request is returned before the query can even be routed.

Do you have any clue on how to parse that request removing the space or any other magic that can solve this?

Thank you!

CodePudding user response:

I guess you are looking for something called Middleware (msdn).

In short, it gives you access to the request/response pipeline - so you can perform some actions with request before it reaches your controller and with response before it is passed to a client.

Implementation

In your Startup.cs:

public class Startup
{
    public Startup(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public IConfiguration Configuration { get; }

    public void ConfigureServices(IServiceCollection services)
    {
        ///           ///
        /// Your code ///
        ///           ///
    }

    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        ///           ///
        /// Your code ///
        ///           ///

        app.UseMiddleware<HttpHeadersAligner>();
    }
}

HttpHeadersAligner.cs

public class HttpHeadersAligner
{
    private readonly RequestDelegate _next;
    public HttpHeadersAligner(RequestDelegate next)
    {
        _next = next;
    }

    public async Task Invoke(HttpContext httpContext)
    {
        ///
        /// Your code
        /// 
    }
}

CodePudding user response:

Using IIS' URL Rewrite 2.0:

  • NOTE: The OP said their problem is that old client software is sending HTTP requests with a malformed Accept-Charset header (it has a space 0x20) after the Accept-Charset header name but before the colon (and no space after the colon), i.e. "Accept-Charset :ISO-8859-1".

    • I do not know if IIS' URL Rewrite extension will correctly match this header. My answer is written in the assumption that it does. YMMV.
  • You will need version 2.0 (or later) of the IIS URL Rewrite extension to manipulate request and response headers (amongst other things) before ASP.NET Core sees the request.

  • Recommended reading:

  • IIS URL Rewrite 2.0 can edit (add, set, edit, and remove) request and response headers via their HTTP Server Variable representations.

    • Request headers are identified and matched by strings of the form HTTP_{UPPER_SNAKE_CASE_HEADER_NAME}.
    • Response headers are identified by strings of the form RESPONSE_{HEADER_NAME}.
    • For example:
      • Match the Content-Type request header with HTTP_CONTENT_TYPE.
      • Match the Content-Type response header with RESPONSE_Content-Type.
    • In your case, to match Accept-Charset :ISO-8859-1 I assume that IIS will either strip the space by itself and match HTTP_ACCEPT_CHARSET - or - IIS will allow and match a trailing literal space or XML entitized space (&#x20;) as "HTTP_ACCEPT_CHARSET " or "HTTP_ACCEPT_CHARSET&#x20;" respectively.
      • I have not tested this, however.
  • NOTE: In order to allow a <rewrite> configuration to edit HTTP headers, you need to edit IIS' applicationHost.config file (which defines server-level settings and Website configuration) to add the HTTP server variable representation of those request/response header names to the <allowedServerVariables> list.

    • In Azure App Services (aka Azure Websites) you can do this with your applicationHost.xdt file, placed at D:\home\site\applicationHost.xdt - and the file should look like this:
      <configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
          <system.webServer>
              <rewrite>
                  <allowedServerVariables>
                       <!-- I'm trying different patterns so that the trailing space will hopefully be matched. -->
                       <add name="HTTP_ACCEPT_CHARSET" xdt:Transform="InsertIfMissing" xdt:Locator="Match(name)" />
                       <add name="HTTP_ACCEPT_CHARSET " xdt:Transform="InsertIfMissing" xdt:Locator="Match(name)" />
                       <add name="HTTP_ACCEPT_CHARSET&#x20;" xdt:Transform="InsertIfMissing" xdt:Locator="Match(name)" />
                   </allowedServerVariables>
               </rewrite>
           </system.webServer>
      </configuration>
      
    • In other hosting scenarios, consult your hosting provider.
  • Here's something that I feel should work...

    • I assume <action type="None" /> will still edit the HTTP request headers, but if not, try <action type="Rewrite" url="{R:0}" /> (which will rewrite the request URL to itself, a NOOP, basically).
<?xml version="1.0" encoding="utf-8"?>
<configuration>
    
    <system.webServer>
        <rewrite>
            <rule name="ClearAcceptCharset0" stopProcessing="true">
                <match url=".*" />
                <conditions>
                    <add input="{HTTP_ACCEPT_CHARSET}" pattern="(. )" />
                </conditions>
                <serverVariables>
                    <set name="HTTP_ACCEPT_CHARSET" value="" />
                    <set name="HTTP_ACCEPT_CHARSET " value="" />
                    <set name="HTTP_ACCEPT_CHARSET&#x20;" value="" />
                </serverVariables>
                <action type="None" />
            </rule>
            <rule name="ClearAcceptCharset1" stopProcessing="true">
                <match url=".*" />
                <conditions>
                    <add input="{HTTP_ACCEPT_CHARSET }" pattern="(. )" />
                </conditions>
                <serverVariables>
                    <set name="HTTP_ACCEPT_CHARSET" value="" />
                    <set name="HTTP_ACCEPT_CHARSET " value="" />
                    <set name="HTTP_ACCEPT_CHARSET&#x20;" value="" />
                </serverVariables>
                <action type="None" />
            </rule>
            <rule name="ClearAcceptCharset2" stopProcessing="true">
                <match url=".*" />
                <conditions>
                    <add input="{HTTP_ACCEPT_CHARSET&#x20;}" pattern="(. )" />
                </conditions>
                <serverVariables>
                    <set name="HTTP_ACCEPT_CHARSET" value="" />
                    <set name="HTTP_ACCEPT_CHARSET " value="" />
                    <set name="HTTP_ACCEPT_CHARSET&#x20;" value="" />
                </serverVariables>
                <action type="None" />
            </rule>
        </rewrite>
    </system.webServer>

</configuration>
  • HTH, YMMV, etc.
  • Related