Parse Accept Header
-
05-07-2019 - |
Question
Quelqu'un a-t-il des suggestions (ou une expression régulière) à analyser l'en-tête HTTP Accept?
J'essaie de négocier un type de contenu dans ASP.NET MVC. Il ne semble pas y avoir de chemin construit (ce qui est bien, car il y a beaucoup d'écoles de pensée ici), mais l'analyse n'est pas entièrement triviale et je préférerais ne pas réinventer la roue si quelqu'un l'a déjà fait. bien et est prêt à partager.
La solution
Avez-vous vu cet article ? Cela donne une implémentation assez complète pour analyser l’en-tête Accept et ensuite lui faire quelque chose d’utile.
Autres conseils
À partir de .NET 4.5 (& # 8212; Microsoft a créé des informations sur les versions du framework < 4.5 plutôt obscur), vous pouvez utiliser l'un des analyseurs syntaxiques intégrés à partir de System.Net.Http.Headers
:
public IOrderedEnumerable<MediaTypeWithQualityHeaderValue> GetMediaTypes(string headerValue) =>
headerValue?.Split(',')
.Select(MediaTypeWithQualityHeaderValue.Parse)
.OrderByDescending(mt => mt.Quality.GetValueOrDefault(1));
Ensuite, vous pouvez faire quelque chose comme ceci:
var headerValue = "application/json, text/javascript, */*; q=0.01";
var mediaTypes = GetMediaTypes(headerValue);
En vous donnant une belle liste de tous les types de média, l'option préférée étant le premier élément. Voici un LINQPad Dump
du mediaTypes
résultat de l'exemple:
Pourboire à cette réponse , pour m'avoir mis sur la bonne voie.
J'ai écrit un analyseur en PHP. Ce n'est pas complexe, mais cela vous donnera un tableau de types de mime par ordre de préférence.
Une autre implémentation dans le php a été ici
.Après avoir lu l'article sur xml.com, j'ai décidé de ne pas écrire de fonction pour l'en-tête Accept moi-même;)
Heureusement, l'article pointe vers une bonne bibliothèque: https://code.google.com/p/ mimeparse / - dans mon cas, j'en ai besoin en tant que module Node.js: https://github.com / kriskowal / mimeparse
La RFC est assez complexe. Si la regex suivait ces règles à la lettre, elle aurait plusieurs lignes.
Si vous avez déjà l'en-tête Accept et que vous ignorez les guillemets et les paramètres, vous pouvez faire quelque chose comme ceci pour faire correspondre chaque paire:
/([^()<>@,;:\\"\/[\]?={} \t]+)\/([^()<>@,;:\\"\/[\]?={} \t]+)/
*
est inclus dans la classe de caractères, il n'a donc besoin d'aucun cas spécial dans l'expression régulière.
Mise à profit du https://stackoverflow.com/a/49011308/275501 à partir de https://stackoverflow.com/users/43140/mark-bell ci-dessus:
public class MyController : Controller
{
[HttpGet]
[Route("/test")]
public ActionResult Index() {
// does this request accept HTML?
var acceptsHTML = IsAcceptable("text/html");
var model = FetchViewModel();
return acceptsHTML ? (ActionResult) View(model) : Ok(model);
}
private bool IsAcceptable(string mediaType) =>
Request.Headers["Accept"].Any(headerValue =>
!string.IsNullOrWhiteSpace(headerValue) &&
headerValue.Split(",").Any(segment => MediaTypeHeaderValue.Parse(segment).MediaType == mediaType));
private object FetchViewModel() {
return new { Description = "To be completed" };
}
}