How to select content type from HTTP Accept header in PHP

后端 未结 7 1055
[愿得一人]
[愿得一人] 2020-12-16 13:10

I\'m trying to build a standard compliant website framework which serves XHTML 1.1 as application/xhtml+xml or HTML 4.01 as text/html depending on the browser support. Curre

7条回答
  •  被撕碎了的回忆
    2020-12-16 13:20

    Merged @maciej-Łebkowski and @chacham15 solutions with my issues fixes and improvements. If you pass $desiredTypes = 'text/*' and Accept contains text/html;q=1 then text/html will be returned.

    /**
     * Parse, sort and select best Content-type, supported by a user browser.
     *
     * @param string|string[] $desiredTypes The filter of desired types. If &null then the all supported types will returned.
     * @param string $acceptRules Supported types in the HTTP Accept header format. $_SERVER['HTTP_ACCEPT'] by default.
     * @return string|string[]|null Matched by $desiredTypes type or all accepted types.
     * @link Inspired by http://stackoverflow.com/a/1087498/3155344
     */
    function resolveContentNegotiation($desiredTypes = null, $acceptRules = null)
    {
        if (!$acceptRules) {
            $acceptRules = @$_SERVER['HTTP_ACCEPT'];
        }
        // Accept header is case insensitive, and whitespace isn't important.
        $acceptRules = strtolower(str_replace(' ', '', $acceptRules));
    
        $sortedAcceptTypes = array();
        foreach (explode(',', $acceptRules) as $acceptRule) {
            $q = 1; // the default accept quality (rating).
            // Check if there is a different quality.
            if (strpos($acceptRule, ';q=') !== false) {
                // Divide "type;q=X" into two parts: "type" and "X"
                list($acceptRule, $q) = explode(';q=', $acceptRule, 2);
            }
            $sortedAcceptTypes[$acceptRule] = $q;
        }
        // WARNING: zero quality is means, that type isn't supported! Thus remove them.
        $sortedAcceptTypes = array_filter($sortedAcceptTypes);
        arsort($sortedAcceptTypes, SORT_NUMERIC);
    
        // If no parameter was passed, just return parsed data.
        if (!$desiredTypes) {
            return $sortedAcceptTypes;
        }
    
        $desiredTypes = array_map('strtolower', (array) $desiredTypes);
    
        // Let's check our supported types.
        foreach (array_keys($sortedAcceptTypes) as $type) {
            foreach ($desiredTypes as $desired) {
                if (fnmatch($desired, $type)) {
                    return $type;
                }
            }
        }
    
        // No matched type.
        return null;
    }
    

提交回复
热议问题