Respecting q-values during content negotiation.

Just wrote this in the course of playing around and thought some others might find it useful. Returns the UA's preferred option for any of the HTTP headers which potentially have q-values. Supply it with the HTTP header you want evaluated, a list of what things your program can serve in the order it would like to serve them (in lowercase — in_array is case-sensitive), and whether or not failing to match one will cause the request to fail.

function getPreference($string,$pref_order,$fatal=true) {
	$acceptArray = explode(',',strtolower(str_replace(' ','',$_SERVER[$string])));
	$use = array();
	foreach($acceptArray as &$key) {
		$newkey = explode(';',$key);
		$newkey[1] = (count($newkey) < 2) ? '1.0' : substr($newkey[1],2);
		$use[$newkey[1]][] = $newkey[0];
	foreach($use as $qval) {
		foreach ($pref_order as $pref) {
			if (strpos($pref,'/')) {
				if (in_array($pref,$qval) || in_array('*/*',$qval) || in_array(substr($pref,0,strpos($pref,'/')).'/*',$qval))
					return $pref;
			else {
				if (in_array($pref,$qval) || in_array('*',$qval))
					return $pref;
	if($fatal) {
		header('HTTP/1.1 406 Not Acceptable');
	return false;
header('Content-Type: text/plain');
echo getPreference('HTTP_ACCEPT',array('application/xhtml+xml','text/html','text/vnd.wap.wml','text/plain','application/atom+xml','text/xml'))."\n";
echo getPreference('HTTP_ACCEPT_CHARSET',array('utf-8','utf-16','iso-8859-1'),false)."\n";
echo getPreference('HTTP_ACCEPT_LANGUAGE',array('en'),false)."\n";

An interesting thing I happened upon while doing this: my browser's preferred charset was ISO-8859-1 and not UTF-8. Oops :)


Post a Comment

<< Home