/** * Process filter from the request and apply over response to get the partial results * * @param array $response * @return array partial response array or empty array if invalid filter criteria is provided */ public function filter($response) { $filter = $this->_request->getParam(self::FILTER_PARAMETER); if (!is_string($filter)) { return []; } $filterArray = $this->parse($filter); if (is_null($filterArray)) { return []; } $partialResponse = $this->applyFilter($response, $filterArray); return $partialResponse; }
/** * Handle REST request * * @param \Magento\Framework\App\RequestInterface $request * @return \Magento\Framework\App\ResponseInterface */ public function dispatch(\Magento\Framework\App\RequestInterface $request) { $path = $this->_pathProcessor->process($request->getPathInfo()); $this->_request->setPathInfo($path); $this->areaList->getArea($this->_appState->getAreaCode())->load(\Magento\Framework\App\Area::PART_TRANSLATE); try { $this->checkPermissions(); $route = $this->getCurrentRoute(); if ($route->isSecure() && !$this->_request->isSecure()) { throw new \Magento\Webapi\Exception(__('Operation allowed only in HTTPS')); } /** @var array $inputData */ $inputData = $this->_request->getRequestData(); $serviceMethodName = $route->getServiceMethod(); $serviceClassName = $route->getServiceClass(); $inputData = $this->overrideParams($inputData, $route->getParameters()); $inputParams = $this->_serializer->getInputData($serviceClassName, $serviceMethodName, $inputData); $service = $this->_objectManager->get($serviceClassName); /** @var \Magento\Framework\Service\Data\AbstractExtensibleObject $outputData */ $outputData = call_user_func_array([$service, $serviceMethodName], $inputParams); $outputData = $this->dataObjectConverter->processServiceOutput($outputData); if ($this->_request->getParam(PartialResponseProcessor::FILTER_PARAMETER) && is_array($outputData)) { $outputData = $this->partialResponseProcessor->filter($outputData); } $this->_response->prepareResponse($outputData); } catch (\Exception $e) { $maskedException = $this->_errorProcessor->maskException($e); $this->_response->setException($maskedException); } return $this->_response; }
/** * Perform authentication and authorization. * * Authentication can be based on active customer/guest session or it can be based on OAuth headers. * * @throws \Magento\Framework\Exception\AuthorizationException * @return void */ protected function _checkPermissions() { /** * All mobile clients are expected to pass session cookie along with the request which will allow * to start session automatically. User ID and user type are initialized when session is created * during login call. */ $userId = $this->session->getUserId(); $userType = $this->session->getUserType(); $userIdentifier = null; $consumerId = null; if ($userType) { /** @var \Magento\Authz\Model\UserIdentifier $userIdentifier */ $userIdentifier = $this->_objectManager->create('Magento\\Authz\\Model\\UserIdentifier', ['userType' => $userType, 'userId' => $userId]); } else { $oauthRequest = $this->_oauthHelper->prepareRequest($this->_request); $consumerId = $this->_oauthService->validateAccessTokenRequest($oauthRequest, $this->_oauthHelper->getRequestUrl($this->_request), $this->_request->getMethod()); $this->_request->setConsumerId($consumerId); } $route = $this->_getCurrentRoute(); if (!$this->_authorizationService->isAllowed($route->getAclResources(), $userIdentifier)) { $params = ['resources' => implode(', ', $route->getAclResources())]; throw new AuthorizationException(AuthorizationException::NOT_AUTHORIZED, $params); } }
/** * Find renderer which can render response in requested format. * * @return string * @throws \Magento\Webapi\Exception */ protected function _getRendererClass() { $acceptTypes = $this->_request->getAcceptTypes(); if (!is_array($acceptTypes)) { $acceptTypes = array($acceptTypes); } foreach ($acceptTypes as $acceptType) { foreach ($this->_renders as $rendererConfig) { $rendererType = $rendererConfig['type']; if ($acceptType == $rendererType || $acceptType == current(explode('/', $rendererType)) . '/*' || $acceptType == '*/*') { return $rendererConfig['model']; } } } /** If server does not have renderer for any of the accepted types it SHOULD send 406 (not acceptable). */ throw new \Magento\Webapi\Exception(__('Server cannot understand Accept HTTP header media type.'), 0, \Magento\Webapi\Exception::HTTP_NOT_ACCEPTABLE); }
/** * Find renderer which can render response in requested format. * * @return string * @throws \Magento\Webapi\Exception */ protected function _getRendererClass() { $acceptTypes = $this->_request->getAcceptTypes(); if (!is_array($acceptTypes)) { $acceptTypes = [$acceptTypes]; } foreach ($acceptTypes as $acceptType) { foreach ($this->_renders as $rendererConfig) { $rendererType = $rendererConfig['type']; if ($acceptType == $rendererType || $acceptType == current(explode('/', $rendererType)) . '/*' || $acceptType == '*/*') { return $rendererConfig['model']; } } } /** If server does not have renderer for any of the accepted types it SHOULD send 406 (not acceptable). */ throw new \Magento\Webapi\Exception(__('Server cannot match any of the given Accept HTTP header media type(s) from the request: "%1" ' . 'with media types from the config of response renderer.', implode(',', $acceptTypes)), 0, \Magento\Webapi\Exception::HTTP_NOT_ACCEPTABLE); }
/** * @param array $requestData Data from the request * @param array $parameters Data from config about which parameters to override * @param array $expectedOverriddenParams Result of overriding $requestData when applying rules from $parameters * * @dataProvider overrideParmasDataProvider */ public function testOverrideParams($requestData, $parameters, $expectedOverriddenParams) { $this->_routeMock->expects($this->once())->method('getParameters')->will($this->returnValue($parameters)); $this->_appStateMock->expects($this->any())->method('isInstalled')->will($this->returnValue(true)); $this->_authzServiceMock->expects($this->once())->method('isAllowed')->will($this->returnValue(true)); $this->_requestMock->expects($this->any())->method('getRequestData')->will($this->returnValue($requestData)); // serializer should expect overridden params $this->serializerMock->expects($this->once())->method('getInputData')->with($this->equalTo('Magento\\Webapi\\Controller\\TestService'), $this->equalTo('testMethod'), $this->equalTo($expectedOverriddenParams)); $this->_restController->dispatch($this->_requestMock); }
/** * @param array $requestData Data from the request * @param array $parameters Data from config about which parameters to override * @param array $expectedOverriddenParams Result of overriding $requestData when applying rules from $parameters * @param int $userId The id of the user invoking the request * @param int $userType The type of user invoking the request * * @dataProvider overrideParmasDataProvider */ public function testOverrideParams($requestData, $parameters, $expectedOverriddenParams, $userId, $userType) { $this->_routeMock->expects($this->once())->method('getParameters')->will($this->returnValue($parameters)); $this->_routeMock->expects($this->any())->method('getAclResources')->will($this->returnValue(['1'])); $this->_authorizationMock->expects($this->once())->method('isAllowed')->will($this->returnValue(true)); $this->_requestMock->expects($this->any())->method('getRequestData')->will($this->returnValue($requestData)); $this->userContextMock->expects($this->any())->method('getUserId')->will($this->returnValue($userId)); $this->userContextMock->expects($this->any())->method('getUserType')->will($this->returnValue($userType)); // serializer should expect overridden params $this->serializerMock->expects($this->once())->method('getInputData')->with($this->equalTo('Magento\\Webapi\\Controller\\TestService'), $this->equalTo('testMethod'), $this->equalTo($expectedOverriddenParams)); $this->_restController->dispatch($this->_requestMock); }
/** * Test for getContentType() method. * * @dataProvider providerContentType * @param string $contentTypeHeader 'Content-Type' header value * @param string $contentType Appropriate content type for header value * @param string|boolean $exceptionMessage \Exception message (boolean FALSE if exception is not expected) */ public function testGetContentType($contentTypeHeader, $contentType, $exceptionMessage = false) { $this->_request->expects($this->once())->method('getHeader')->with('Content-Type')->will($this->returnValue($contentTypeHeader)); try { $this->assertEquals($contentType, $this->_request->getContentType()); } catch (\Magento\Webapi\Exception $e) { if ($exceptionMessage) { $this->assertEquals($exceptionMessage, $e->getMessage(), 'Exception message does not match the expected one.'); return; } else { $this->fail('Exception is thrown on valid header: ' . $e->getMessage()); } } if ($exceptionMessage) { $this->fail('Expected exception was not raised.'); } }
/** * Get service base URL * * @param \Magento\Webapi\Controller\Rest\Request $request * @return string|null */ protected function _getServiceBaseUrl($request) { $baseUrlRegExp = '#^/?\\w+/\\w+#'; $serviceBaseUrl = preg_match($baseUrlRegExp, $request->getPathInfo(), $matches) ? $matches[0] : null; return $serviceBaseUrl; }
/** * @dataProvider invalidFilterDataProvider */ public function testInvalidFilters($invalidFilter) { $this->requestMock->expects($this->any())->method('getParam')->will($this->returnValue($invalidFilter)); $filteredResponse = $this->processor->filter($this->sampleResponseValue); $this->assertEmpty($filteredResponse); }