diff --git a/ContentNegotiator.php b/ContentNegotiator.php new file mode 100644 index 0000000..90a5183 --- /dev/null +++ b/ContentNegotiator.php @@ -0,0 +1,60 @@ + 'JsonConverter' /*, 'text/x-yaml' => 'YamlConverter'*/); + + public static function SupportedMimeTypes() { + $mimes = array(); + $instances = array(); + + foreach (self::$output_handlers AS $mime => $handler) { + if (!isset($instances[$handler])) { + if (!class_exists($handler)) { + continue; + } + $instances[$handler] = new $handler(); + if (!($instances[$handler] instanceof OutputConverter)) { + throw new HttpException(500, NULL, 'Unsupported converter for mime type "' . $mime . '"!'); + } + } + + if ($instances[$handler]->canRun()) { + $mimes[] = $mime; + } + } + + return $mimes; + } + + public static function MimeType() { + $additional = func_get_args(); + $mimes = array_unique(array_merge(self::SupportedMimeTypes(), $additional)); + + if (isset($_SERVER['HTTP_ACCEPT'])) { + foreach(explode(',', $_SERVER['HTTP_ACCEPT']) as $value) { + list($suggested_mime) = explode(';', $value); + if (in_array($suggested_mime, $mimes)) { + return $suggested_mime; + } + } + throw new HttpException(406, array('Content-Type' => implode($mimes, ','))); + } + return DEFAULT_MIME_TYPE; + } + + public static function Output(array $data, $namespace) { + $mime = self::MimeType(); + $conv = new self::$output_handlers[$mime](); + $content = $conv->convert($data, $namespace); # canRun() is checked by already + + header('Content-Type: ' . $mime); + echo $content; + exit; + } +} +?> \ No newline at end of file diff --git a/JsonConverter.php b/JsonConverter.php new file mode 100644 index 0000000..96b7370 --- /dev/null +++ b/JsonConverter.php @@ -0,0 +1,13 @@ + \ No newline at end of file diff --git a/OutputConverter.php b/OutputConverter.php new file mode 100644 index 0000000..49b152a --- /dev/null +++ b/OutputConverter.php @@ -0,0 +1,6 @@ + \ No newline at end of file diff --git a/YamlConverter.php b/YamlConverter.php new file mode 100644 index 0000000..9cecb2c --- /dev/null +++ b/YamlConverter.php @@ -0,0 +1,13 @@ + \ No newline at end of file diff --git a/config/content-negotiation.php b/config/content-negotiation.php new file mode 100644 index 0000000..0fb742a --- /dev/null +++ b/config/content-negotiation.php @@ -0,0 +1,10 @@ + \ No newline at end of file diff --git a/items/describe.php b/items/describe.php index e161668..77fea37 100644 --- a/items/describe.php +++ b/items/describe.php @@ -2,6 +2,7 @@ require_once("../modules/HttpException/HttpException.php"); require_once("../db.php"); require_once("../util.php"); + require_once('../ContentNegotiator.php'); require_once("../Assert.php"); require_once("../modules/semver/semver.php"); require_once('../Item.php'); @@ -15,7 +16,7 @@ Assert::GetParameters("id", array("name", "version")); # validate accept header of request - $content_type = get_preferred_mimetype(array("application/json", "text/xml", "application/xml", "application/x-ald-package"), "application/json"); + $content_type = ContentNegotiator::MimeType('application/x-ald-package'); # connect to database server $db_connection = db_ensure_connection(); diff --git a/items/list.php b/items/list.php index cea6afd..11a776a 100644 --- a/items/list.php +++ b/items/list.php @@ -2,6 +2,7 @@ require_once("../modules/HttpException/HttpException.php"); require_once("../db.php"); require_once("../util.php"); + require_once('../ContentNegotiator.php'); require_once('../SortHelper.php'); require_once('../FilterHelper.php'); require_once("../User.php"); @@ -18,7 +19,7 @@ Assert::RequestMethod(Assert::REQUEST_METHOD_GET); # only allow GET requests # validate accept header of request - $content_type = get_preferred_mimetype(array("application/json", "text/xml", "application/xml"), "application/json"); + $content_type = ContentNegotiator::MimeType(); # connect to database server $db_connection = db_ensure_connection(); diff --git a/items/rating.php b/items/rating.php index be5a708..ea06255 100644 --- a/items/rating.php +++ b/items/rating.php @@ -3,6 +3,7 @@ require_once("../Item.php"); require_once("../Assert.php"); require_once("../util.php"); + require_once('../ContentNegotiator.php'); require_once("../db.php"); require_once('../sql2array.php'); require_once("../config/rating.php"); # import config settings @@ -60,7 +61,7 @@ } else if ($request_method == Assert::REQUEST_METHOD_GET) { # validate accept header of request - $content_type = get_preferred_mimetype(array("application/json", "text/xml", "application/xml", "application/x-ald-package"), "application/json"); + $content_type = ContentNegotiator::MimeType(); $db_query = 'SELECT name AS user, rating FROM ' . DB_TABLE_RATINGS . ', ' . DB_TABLE_USERS . ' WHERE item = UNHEX("' . $id . '") AND `user` = `id`'; $db_result = $db_connection->query($db_query); diff --git a/items/tags.php b/items/tags.php index f529b35..de6e510 100644 --- a/items/tags.php +++ b/items/tags.php @@ -2,13 +2,14 @@ require_once('../modules/HttpException/HttpException.php'); require_once('../db.php'); require_once('../util.php'); +require_once('../ContentNegotiator.php'); require_once('../Assert.php'); try { Assert::RequestMethod(Assert::REQUEST_METHOD_GET); # only allow GET requests # validate accept header of request - $content_type = get_preferred_mimetype(array('application/json', 'text/xml', 'application/xml'), 'application/json'); + $content_type = ContentNegotiator::MimeType(); # connect to database server $db_connection = db_ensure_connection(); diff --git a/items/types.php b/items/types.php index 110be47..ff68b8d 100644 --- a/items/types.php +++ b/items/types.php @@ -1,10 +1,10 @@ implode($available, ","))); - } - return $default; - } - function handleHttpException($e) { header("HTTP/1.1 " . $e->getCode() . " " . HttpException::getStatusMessage($e->getCode())); diff --git a/version.php b/version.php index df6b7b0..3b45ac4 100644 --- a/version.php +++ b/version.php @@ -1,11 +1,11 @@