J'ai un comportement étrange lorsque j'essaie de modifier mes en-têtes avec un gestionnaire d'événements EndRequest
dans un HttpModule
imbriqué sur MVC 5.2.2 et .NET 4.6.2. Si je ne modifie pas EndRequest
dans mon niveau supérieur HttpModule
, il semble que le gestionnaire d'événements dans le HttpModule
imbriqué ne se déclenche jamais, même si je sais Init
a été appelé sur le HttpModule
imbriqué.
Ma question est, que se passe-t-il dans mon code ci-dessous pour empêcher l'en-tête "TestNested" d'apparaître dans les en-têtes de réponse, sauf si j'inclus le code commenté qui ajoute un gestionnaire d'événements EndRequest
qui ne fait rien?
Enregistrer dynamiquement mon niveau supérieur HttpModule
[Assembly: PreApplicationStartMethod(typeof(PreApplicationStartClass), "Start")]
namespace MyNamespace
{
public class PreApplicationStartClass
{
public static void Start()
{
DynamicModuleUtility.RegisterModule(typeof(TopHttpModule));
}
}
}
Appelez Init
sur tous mes autres HttpModules
à partir d'un seul module de niveau supérieur
namespace MyNamespace
{
public class TopHttpModule: IHttpModule
{
private readonly Lazy<IEnumerable<IHttpModule>> _modules =
new Lazy<IEnumerable<IHttpModule>>(RetrieveModules);
private static IEnumerable<IHttpModule> RetrieveModules()
{
return DependencyResolver.Current.GetServices<IHttpModule>();
}
public void Init(HttpApplication context)
{
var modules = _modules.Value;
foreach (var module in modules
.Where(module => module.GetType() != typeof(TopHttpModule)))
{
module.Init(context);
}
context.BeginRequest += (sender, e) =>
{
var app = sender as HttpApplication;
if (app != null)
{
//This shows that NestedHttpModule was found
app.Context.Response.Headers.Add(
"TestModules",
string.Join(",", modules.Select(_ => _.GetType().ToString())));
}
};
//Add this and the NestedHttpModule EndRequest handler works
//context.EndRequest += (sender, e) =>
//{
// //Do Nothing
//};
}
public void Dispose()
{
var modules = _modules.Value;
foreach (var disposable in modules
.Where(disposable => disposable.GetType() != typeof(TopHttpModule)))
{
disposable.Dispose();
}
}
}
}
Modifier certaines informations d'en-tête dans un gestionnaire d'événements EndRequest
namespace MyNamespace
{
public class NestedHttpModule: IHttpModule
{
public void Init(HttpApplication context)
{
//This gets called whether or not the TopHttpModule modifies context.EndRequest
MvcHandler.DisableMvcResponseHeader = true;
context.EndRequest += Application_EndRequest;
}
public void Application_EndRequest(object sender, EventArgs e)
{
var app = sender as HttpApplication;
if (app != null && app.Context != null)
{
//This doesn't appear to be called unless TopHttpModule modifies context.EndRequest
app.Context.Response.Headers.Add("TestNested", "Found");
}
}
public void Dispose()
{
//Do Nothing
}
}
}
Je voulais également modifier mes en-têtes, mais je devais cacher autant que possible. C'est la même chose pour Ajouter ou Supprimer ou les deux, ce ne sont que des en-têtes.
1) Vous pouvez définir MvcHandler.DisableMvcResponseHeader = true;
dans le global.asax
protected void Application_Start()
{
MvcHandler.DisableMvcResponseHeader = true;
}
and
protected void Application_PreSendRequestHeaders()
{
Response.Headers.Remove("Server");
Response.Headers.Remove("X-AspNet-Version");
}
2) Vous ne devriez pas vraiment utiliser le module diff pour presque le même travail, créez plutôt un HeadersModule
qui ne gère que la modification des en-têtes, et utilisez le PreSendRequestHeaders
pour ajouter ou supprimer les en-têtes souhaités. Vous pouvez toujours injecter un service avec une liste d'en-têtes à ajouter ou à supprimer.
public class HeadersModule : IHttpModule
{
public void Init(HttpApplication context)
{
context.PreSendRequestHeaders += OnPreSendRequestHeaders;
}
public void Dispose() {
}
void OnPreSendRequestHeaders(object sender, EventArgs e)
{
var r = sender as HttpApplication;
r.Response.Headers.Remove("Server");
r.Response.Headers.Remove("X-AspNetMvc-Version");
r.Response.Headers.Remove("X-AspNet-Version");
r.Response.Headers.Remove("X-Powered-By");
}
}
3) Pour être encore plus sûr, que certains en-têtes s'affichent ou "ne s'affichent pas", vous pouvez l'ajouter à votre fichier de configuration
<system.webServer>
<modules>
<add name="HeadersModule " type="MyNamespace.Modules.HeadersModule " />
</modules>
<httpProtocol>
<customHeaders>
<remove name="X-Powered-By" />
<remove name="Server" />
<remove name="X-AspNet-Version" />
<remove name="X-AspNetMvc-Version" />
</customHeaders>
<redirectHeaders>
<clear />
</redirectHeaders>
</httpProtocol>
</system.webServer>
4) Testez toutes les pages, alias 404, les pages d'erreur, les noms de chemin étranges, car ils peuvent fuir certains en-têtes ou afficher des en-têtes auxquels vous ne vous attendiez pas.