/** * Gets the appropriate MIME type for the request, throwing if there is none. * * @param string $acceptTypesText Text as it appears in an HTTP * Accepts header. * @param array(String) $exactContentTypes Preferred content type to match * if an exact media type is given * - this is in descending order * of preference. * @param string $inexactContentType Preferred fallback content type * for inexact matches. * * @return string One of exactContentType or inexactContentType. */ public static function selectRequiredMimeType($acceptTypesText, $exactContentTypes, $inexactContentType) { $selectedContentType = null; $selectedMatchingParts = -1; $selectedQualityValue = 0; $acceptable = false; $acceptTypesEmpty = true; $foundExactMatch = false; if (!is_null($acceptTypesText)) { $acceptTypes = self::mimeTypesFromAcceptHeaders($acceptTypesText); foreach ($acceptTypes as $acceptType) { $acceptTypesEmpty = false; foreach ($exactContentTypes as $exactContentType) { if (strcasecmp($acceptType->getMimeType(), $exactContentType) == 0) { $selectedContentType = $exactContentType; $selectedQualityValue = $acceptType->getQualityValue(); $acceptable = $selectedQualityValue != 0; $foundExactMatch = true; break; } } if ($foundExactMatch) { break; } $matchingParts = $acceptType->getMatchingParts($inexactContentType); if ($matchingParts < 0) { continue; } if ($matchingParts > $selectedMatchingParts) { // A more specific type wins. $selectedContentType = $inexactContentType; $selectedMatchingParts = $matchingParts; $selectedQualityValue = $acceptType->getQualityValue(); $acceptable = $selectedQualityValue != 0; } else { if ($matchingParts == $selectedMatchingParts) { // A type with a higher q-value wins. $candidateQualityValue = $acceptType->getQualityValue(); if ($candidateQualityValue > $selectedQualityValue) { $selectedContentType = $inexactContentType; $selectedQualityValue = $candidateQualityValue; $acceptable = $selectedQualityValue != 0; } } } } } if (!$acceptable && !$acceptTypesEmpty) { throw new HttpHeaderFailure(Messages::dataServiceExceptionUnsupportedMediaType(), 415); } if ($acceptTypesEmpty) { $selectedContentType = $inexactContentType; } return $selectedContentType; }
/** * Gets the response format for the requested resource. * * @param RequestDescription &$requestDescription The request submitted by * client and it's execution * result. * @param UriProcessor &$uriProcessor The reference to the * UriProcessor. * @param DataService &$dataService Reference to the data * service instance * @param string &$responseContentType On Return, this will hold * the response content-type, a null value means the requested resource * is named stream and IDSSP2::getStreamContentType returned null. * * @return ResponseFormat The format in which response needs to be serialized. * * @throws ODataException, HttpHeaderFailure */ public static function getResponseFormat(RequestDescription &$requestDescription, UriProcessor &$uriProcessor, DataService &$dataService, &$responseContentType) { // The Accept request-header field specifies media types which are // acceptable for the response $requestAcceptText = $dataService->getHost()->getRequestAccept(); $responseFormat = ResponseFormat::UNSUPPORTED; $requestTargetKind = $requestDescription->getTargetKind(); if ($requestDescription->isLinkUri()) { $requestTargetKind = RequestTargetKind::LINK; } if ($requestTargetKind == RequestTargetKind::METADATA) { $responseContentType = HttpProcessUtility::selectMimeType($requestAcceptText, array(ODataConstants::MIME_APPLICATION_XML)); if (!is_null($responseContentType)) { $responseFormat = ResponseFormat::METADATA_DOCUMENT; } } else { if ($requestTargetKind == RequestTargetKind::SERVICE_DIRECTORY) { $responseContentType = HttpProcessUtility::selectMimeType($requestAcceptText, array(ODataConstants::MIME_APPLICATION_XML, ODataConstants::MIME_APPLICATION_ATOMSERVICE, ODataConstants::MIME_APPLICATION_JSON)); if (!is_null($responseContentType)) { $responseFormat = self::_getContentFormat($responseContentType); } } else { if ($requestTargetKind == RequestTargetKind::PRIMITIVE_VALUE) { $supportedResponseMimeTypes = array(ODataConstants::MIME_TEXTPLAIN); $responseFormat = ResponseFormat::TEXT; if ($requestDescription->getIdentifier() != '$count') { $projectedProperty = $requestDescription->getProjectedProperty(); self::assert(!is_null($projectedProperty), '!is_null($projectedProperty)'); $type = $projectedProperty->getInstanceType(); self::assert(!is_null($type) && array_search('ODataProducer\\Providers\\Metadata\\Type\\IType', class_implements($type)) !== false, '!is_null($type) && array_search(\'ODataProducer\\Providers\\Metadata\\Type\\IType\', class_implements($type)) !== false'); if ($type instanceof Binary) { $supportedResponseMimeTypes = array(ODataConstants::MIME_APPLICATION_OCTETSTREAM); $responseFormat = ResponseFormat::BINARY; } } $responseContentType = HttpProcessUtility::selectMimeType($requestAcceptText, $supportedResponseMimeTypes); if (is_null($responseContentType)) { $responseFormat = ResponseFormat::UNSUPPORTED; } } else { if ($requestTargetKind == RequestTargetKind::PRIMITIVE || $requestTargetKind == RequestTargetKind::COMPLEX_OBJECT || $requestTargetKind == RequestTargetKind::BAG || $requestTargetKind == RequestTargetKind::LINK) { $responseContentType = HttpProcessUtility::selectMimeType($requestAcceptText, array(ODataConstants::MIME_APPLICATION_XML, ODataConstants::MIME_TEXTXML, ODataConstants::MIME_APPLICATION_JSON)); if (!is_null($responseContentType)) { $responseFormat = self::_getContentFormat($responseContentType); } } else { if ($requestTargetKind == RequestTargetKind::RESOURCE) { $responseContentType = HttpProcessUtility::selectMimeType($requestAcceptText, array(ODataConstants::MIME_APPLICATION_ATOM, ODataConstants::MIME_APPLICATION_JSON)); if (!is_null($responseContentType)) { $responseFormat = self::_getContentFormat($responseContentType); } } else { if ($requestTargetKind == RequestTargetKind::MEDIA_RESOURCE) { $responseFormat = ResponseFormat::BINARY; if ($requestDescription->isNamedStream() || $requestDescription->getTargetResourceType()->isMediaLinkEntry()) { $streamInfo = $requestDescription->getResourceStreamInfo(); //Execute the query as we need media resource instance for //further processing $uriProcessor->execute(); $requestDescription->setExecuted(); // DSSW::getStreamContentType can throw error in 2 cases // 1. If the required stream implementation not found // 2. If IDSSP::getStreamContentType returns NULL for MLE $contentType = $dataService->getStreamProvider()->getStreamContentType($requestDescription->getTargetResult(), $streamInfo); if (!is_null($contentType)) { $responseContentType = HttpProcessUtility::selectMimeType($requestAcceptText, array($contentType)); if (is_null($responseContentType)) { $responseFormat = ResponseFormat::UNSUPPORTED; } } else { // For NamedStream StreamWrapper::getStreamContentType // can return NULL if the requested named stream has not // yet been uploaded. But for an MLE if // IDSSP::getStreamContentType // returns NULL then StreamWrapper will throw error $responseContentType = null; } } else { ODataException::createBadRequestError(Messages::badRequestInvalidUriForMediaResource($dataService->getHost()->getAbsoluteRequestUri()->getUrlAsString())); } } } } } } } if ($responseFormat == ResponseFormat::UNSUPPORTED) { throw new ODataException(Messages::dataServiceExceptionUnsupportedMediaType(), 415); } return $responseFormat; }