/** * Validate request * * @throws AuthorizationException * @throws \Magento\Framework\Webapi\Exception * @return void */ public function validate() { $this->checkPermissions(); $route = $this->router->match($this->request); if ($route->isSecure() && !$this->request->isSecure()) { throw new \Magento\Framework\Webapi\Exception(__('Operation allowed only in HTTPS')); } }
/** * Test insecure request for a secure route * * @expectedException \Magento\Framework\Webapi\Exception * @expectedExceptionMessage Operation allowed only in HTTPS */ public function testInSecureRequestOverSecureRoute() { $this->routeMock->expects($this->any())->method('isSecure')->will($this->returnValue(true)); $this->routeMock->expects($this->any())->method('getAclResources')->will($this->returnValue(['1'])); $this->requestMock->expects($this->any())->method('isSecure')->will($this->returnValue(false)); $this->authorizationMock->expects($this->once())->method('isAllowed')->will($this->returnValue(true)); $this->requestValidator->validate(); }
/** * 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 ($filterArray === null) { return []; } $partialResponse = $this->applyFilter($response, $filterArray); return $partialResponse; }
/** * Generate the list of available REST routes. Current HTTP method is taken into account. * * @param \Magento\Framework\Webapi\Rest\Request $request * @return Route[] matched routes * @throws \Magento\Framework\Webapi\Exception */ public function getRestRoutes(\Magento\Framework\Webapi\Rest\Request $request) { $requestHttpMethod = $request->getHttpMethod(); $servicesRoutes = $this->_config->getServices()[Converter::KEY_ROUTES]; $routes = []; // Return the route on exact match if (isset($servicesRoutes[$request->getPathInfo()][$requestHttpMethod])) { $methodInfo = $servicesRoutes[$request->getPathInfo()][$requestHttpMethod]; $routes[] = $this->_createRoute([self::KEY_ROUTE_PATH => $request->getPathInfo(), self::KEY_CLASS => $methodInfo[Converter::KEY_SERVICE][Converter::KEY_SERVICE_CLASS], self::KEY_METHOD => $methodInfo[Converter::KEY_SERVICE][Converter::KEY_SERVICE_METHOD], self::KEY_IS_SECURE => $methodInfo[Converter::KEY_SECURE], self::KEY_ACL_RESOURCES => array_keys($methodInfo[Converter::KEY_ACL_RESOURCES]), self::KEY_PARAMETERS => $methodInfo[Converter::KEY_DATA_PARAMETERS]]); return $routes; } $serviceBaseUrl = $this->_getServiceBaseUrl($request); ksort($servicesRoutes, SORT_STRING); foreach ($servicesRoutes as $url => $httpMethods) { // skip if baseurl is not null and does not match if (!$serviceBaseUrl || strpos(trim($url, '/'), trim($serviceBaseUrl, '/')) !== 0) { // base url does not match, just skip this service continue; } foreach ($httpMethods as $httpMethod => $methodInfo) { if (strtoupper($httpMethod) == strtoupper($requestHttpMethod)) { $aclResources = array_keys($methodInfo[Converter::KEY_ACL_RESOURCES]); $routes[] = $this->_createRoute([self::KEY_ROUTE_PATH => $url, self::KEY_CLASS => $methodInfo[Converter::KEY_SERVICE][Converter::KEY_SERVICE_CLASS], self::KEY_METHOD => $methodInfo[Converter::KEY_SERVICE][Converter::KEY_SERVICE_METHOD], self::KEY_IS_SECURE => $methodInfo[Converter::KEY_SECURE], self::KEY_ACL_RESOURCES => $aclResources, self::KEY_PARAMETERS => $methodInfo[Converter::KEY_DATA_PARAMETERS]]); } } } return $routes; }
/** * 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\Framework\Webapi\Exception(__('Operation allowed only in HTTPS')); } /** @var array $inputData */ $inputData = $this->_request->getRequestData(); $serviceMethodName = $route->getServiceMethod(); $serviceClassName = $route->getServiceClass(); $inputData = $this->paramsOverrider->override($inputData, $route->getParameters()); $inputParams = $this->serviceInputProcessor->process($serviceClassName, $serviceMethodName, $inputData); $service = $this->_objectManager->get($serviceClassName); /** @var \Magento\Framework\Api\AbstractExtensibleObject $outputData */ $outputData = call_user_func_array([$service, $serviceMethodName], $inputParams); $outputData = $this->serviceOutputProcessor->process($outputData, $serviceClassName, $serviceMethodName); if ($this->_request->getParam(FieldsFilter::FILTER_PARAMETER) && is_array($outputData)) { $outputData = $this->fieldsFilter->filter($outputData); } $this->_response->prepareResponse($outputData); } catch (\Exception $e) { $maskedException = $this->_errorProcessor->maskException($e); $this->_response->setException($maskedException); } return $this->_response; }
/** * Find renderer which can render response in requested format. * * @return string * @throws \Magento\Framework\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\Framework\Webapi\Exception(new Phrase('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.', $acceptTypes), 0, \Magento\Framework\Webapi\Exception::HTTP_NOT_ACCEPTABLE); }
public function testGetMethodAllStoresInvalid() { $this->_routeMock->expects($this->any())->method('getAclResources')->will($this->returnValue(['1'])); $this->_authorizationMock->expects($this->any())->method('isAllowed')->will($this->returnValue(true)); $this->storeMock->expects($this->once())->method('getCode')->willReturn('admin'); $this->_requestMock->expects($this->once())->method('getMethod')->willReturn('get'); $this->_restController->dispatch($this->_requestMock); $this->assertTrue($this->_responseMock->isException()); $this->assertSame("Cannot perform GET operation with store code 'all'", $this->_responseMock->getException()[0]->getMessage()); }
/** * Validate request * * @throws AuthorizationException * @throws \Magento\Framework\Webapi\Exception * @return void */ protected function validateRequest() { $this->checkPermissions(); if ($this->getCurrentRoute()->isSecure() && !$this->_request->isSecure()) { throw new \Magento\Framework\Webapi\Exception(__('Operation allowed only in HTTPS')); } if ($this->storeManager->getStore()->getCode() === Store::ADMIN_CODE && strtoupper($this->_request->getMethod()) === RestRequest::HTTP_METHOD_GET) { throw new \Magento\Framework\Webapi\Exception(__('Cannot perform GET operation with store code \'all\'')); } }
public function testDispatchAllSchemaRequest() { $params = [\Magento\Framework\Webapi\Request::REQUEST_PARAM_SERVICES => 'all']; $this->_requestMock->expects($this->any())->method('getPathInfo')->willReturn(\Magento\Webapi\Controller\Rest::SCHEMA_PATH); $this->_requestMock->expects($this->any())->method('getParam')->will($this->returnValueMap([[\Magento\Framework\Webapi\Request::REQUEST_PARAM_SERVICES, null, 'all']])); $this->_requestMock->expects($this->any())->method('getParams')->will($this->returnValue($params)); $this->_requestMock->expects($this->any())->method('getRequestedServices')->will($this->returnValue('all')); $schema = 'Some REST schema content'; $this->swaggerGeneratorMock->expects($this->any())->method('generate')->willReturn($schema); $this->swaggerGeneratorMock->expects($this->once())->method('getListOfServices')->willReturn(['listOfServices']); $this->_restController->dispatch($this->_requestMock); $this->assertEquals($schema, $this->_responseMock->getBody()); }
/** * Test insecure request for a secure route */ public function testInSecureRequestOverSecureRoute() { $this->_serviceMock->expects($this->any())->method(self::SERVICE_METHOD)->will($this->returnValue([])); $this->_routeMock->expects($this->any())->method('isSecure')->will($this->returnValue(true)); $this->_routeMock->expects($this->any())->method('getAclResources')->will($this->returnValue(['1'])); $this->_requestMock->expects($this->any())->method('isSecure')->will($this->returnValue(false)); $this->_authorizationMock->expects($this->once())->method('isAllowed')->will($this->returnValue(true)); // Override default prepareResponse. It should never be called in this case $this->_responseMock->expects($this->never())->method('prepareResponse'); $this->_restController->dispatch($this->_requestMock); $this->assertTrue($this->_responseMock->isException()); $exceptionArray = $this->_responseMock->getException(); $this->assertEquals('Operation allowed only in HTTPS', $exceptionArray[0]->getMessage()); $this->assertEquals(\Magento\Framework\Webapi\Exception::HTTP_BAD_REQUEST, $exceptionArray[0]->getHttpCode()); }
/** * 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\Framework\Exception\InputException $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.'); } }
/** * Process and resolve input parameters * * @return array * @throws \Magento\Framework\Webapi\Exception */ public function resolve() { $this->requestValidator->validate(); $route = $this->getRoute(); $serviceMethodName = $route->getServiceMethod(); $serviceClassName = $route->getServiceClass(); /* * Valid only for updates using PUT when passing id value both in URL and body */ if ($this->request->getHttpMethod() == RestRequest::HTTP_METHOD_PUT) { $inputData = $this->paramsOverrider->overrideRequestBodyIdWithPathParam($this->request->getParams(), $this->request->getBodyParams(), $serviceClassName, $serviceMethodName); $inputData = array_merge($inputData, $this->request->getParams()); } else { $inputData = $this->request->getRequestData(); } $inputData = $this->paramsOverrider->override($inputData, $route->getParameters()); $inputParams = $this->serviceInputProcessor->process($serviceClassName, $serviceMethodName, $inputData); return $inputParams; }
/** * @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); }