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 space0x20
) after theAccept-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.
- Azure App Services (aka Azure Websites) already has this extension installed.
- Download version 2.1 from https://www.iis.net/downloads/microsoft/url-rewrite
Recommended reading:
- URL Rewriter 1.0 documentation: https://docs.microsoft.com/en-us/iis/extensions/url-rewrite-module/url-rewrite-module-configuration-reference
- URL Rewriter 2.0 documentation: https://docs.microsoft.com/en-us/iis/extensions/url-rewrite-module/url-rewrite-module-20-configuration-reference
- This article only covers new functionality in version 2.0; the documentation for version 1.0 still applies to 2.0: use the 1.0 documentation for the basic URL rewriter functionality, and the 2.0 documentation only for more advanced topics like ARR, etc.
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}
.- The underscores ("
_
") will match dashes ("-
") in the request header name (this does not introduce ambiguity as underscores will not normally appear in header names).
- The underscores ("
- Response headers are identified by strings of the form
RESPONSE_{HEADER_NAME}
. - For example:
- Match the
Content-Type
request header withHTTP_CONTENT_TYPE
. - Match the
Content-Type
response header withRESPONSE_Content-Type
.
- Match the
- In your case, to match
Accept-Charset :ISO-8859-1
I assume that IIS will either strip the space by itself and matchHTTP_ACCEPT_CHARSET
- or - IIS will allow and match a trailing literal space or XML entitized space ( 
) as"HTTP_ACCEPT_CHARSET "
or"HTTP_ACCEPT_CHARSET "
respectively.- I have not tested this, however.
- Request headers are identified and matched by strings of the form
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 atD:\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 " xdt:Transform="InsertIfMissing" xdt:Locator="Match(name)" /> </allowedServerVariables> </rewrite> </system.webServer> </configuration>
- In other hosting scenarios, consult your hosting provider.
- In Azure App Services (aka Azure Websites) you can do this with your
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).
- I assume
<?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 " 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 " value="" />
</serverVariables>
<action type="None" />
</rule>
<rule name="ClearAcceptCharset2" 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 " value="" />
</serverVariables>
<action type="None" />
</rule>
</rewrite>
</system.webServer>
</configuration>
- HTH, YMMV, etc.