Parse Accept Header

2019-03-17 09:50发布

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.

7条回答
老娘就宠你
2楼-- · 2019-03-17 10:11

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

查看更多
欢心
3楼-- · 2019-03-17 10:16

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

查看更多
你好瞎i
4楼-- · 2019-03-17 10:20

Found another implementation in php here

查看更多
小情绪 Triste *
5楼-- · 2019-03-17 10:23

Building on https://stackoverflow.com/a/49011308/275501 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" };

    }

}    
查看更多
戒情不戒烟
6楼-- · 2019-03-17 10:24

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.

查看更多
地球回转人心会变
7楼-- · 2019-03-17 10:28

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.

查看更多
登录 后发表回答