Parse Accept Header
Asked Answered
U

8

28

Does anyone have any suggestions (or a regular expression) for parsing the HTTP Accept header?

I am trying to do some content-type negotiation in ASP.NET MVC. There doesn't seem to be a built in way (which is fine, because there are a lot of schools of thought here), but the parsing is not entirely trivial and I would rather not re-invent the wheel if someone has already done it well and is willing to share.

Urinal answered 1/11, 2008 at 2:43 Comment(1)
Good question - I'm looking for this in another project, as well!Gigi
F
9

Have you seen this article? It gives a pretty comprehensive implementation for parsing the Accept header and subsequently doing something useful with it.

Fingering answered 1/11, 2008 at 16:50 Comment(1)
There is now a builtin method to retrieve common headers from HttpRequest: GetTypeHeaders(), like stated above: https://mcmap.net/q/493993/-parse-accept-headerChretien
S
8

As of .NET 4.5 (I think—Microsoft have made info on framework versions < 4.5 rather obscure these days), you can use one of the the built in parsers from System.Net.Http.Headers:

public IOrderedEnumerable<MediaTypeWithQualityHeaderValue> GetMediaTypes(string headerValue) =>
    headerValue?.Split(',')
        .Select(MediaTypeWithQualityHeaderValue.Parse)
        .OrderByDescending(mt => mt.Quality.GetValueOrDefault(1));

Then you can do something like this:

var headerValue = "application/json, text/javascript, */*; q=0.01";
var mediaTypes = GetMediaTypes(headerValue);

Giving you a nice list of all the media types, where the preferred option is the first item. Here's a LINQPad Dump of the mediaTypes result from the example:

LINQPad dump of results

Hat tip to this answer, for getting me on the right track.

Succor answered 27/2, 2018 at 14:42 Comment(0)
K
3

I've written a parser in PHP. It's not complex, but it will give you an array of mime types in order of preference.

Kreindler answered 24/4, 2009 at 8:16 Comment(1)
the linked site is "disabled"Celtuce
S
2

ASP.NET Core solution:

I know this is an old question but for anyone using ASP.NET Core who might stumble into it like me, note that you can use the GetTypedHeaders extension method on the Request (or Response) object to get strongly-typed header information, including for Accept:

using Microsoft.AspNetCore.Http;

var accept = Request.GetTypedHeaders().Accept; // `Request` must be an `HttpRequest` instance
accept[0].MediaType
accept[0].Quality
// And so on...
Stratocumulus answered 27/3, 2023 at 14:28 Comment(0)
S
1

Found another implementation in php here

Selectman answered 15/2, 2011 at 10:4 Comment(0)
A
1

After reading the xml.com article I decided to not write a function for the Accept header myself ;)

Fortunately the article points to a good library: https://code.google.com/p/mimeparse/ - in my case I need it as a Node.js module: https://github.com/kriskowal/mimeparse

Amorist answered 30/1, 2013 at 13:15 Comment(0)
C
1

Building on https://mcmap.net/q/493993/-parse-accept-header from https://stackoverflow.com/users/43140/mark-bell above:

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" };

    }

}    
Craunch answered 15/10, 2018 at 9:13 Comment(0)
M
0

The RFC is quite complex. If the regex where to follow these rules to the letter, it would become several lines long.

If you already have the Accept-header, and ignore the quotes and the parameters, you could do something like this to match each pair:

/([^()<>@,;:\\"\/[\]?={} \t]+)\/([^()<>@,;:\\"\/[\]?={} \t]+)/

* is included in the character class, so it does not need any special case in the regex.

Mazzard answered 1/11, 2008 at 4:48 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.