/** * Get the content for the signature from the given request * * @param \TYPO3\Flow\Http\Request $httpRequest * @return string */ public function getSignatureContent(\TYPO3\Flow\Http\Request $httpRequest) { $date = $httpRequest->getHeader('Date'); $dateValue = $date instanceof \DateTime ? $date->format(DATE_RFC2822) : ''; $signData = $httpRequest->getMethod() . chr(10) . sha1($httpRequest->getContent()) . chr(10) . $httpRequest->getHeader('Content-Type') . chr(10) . $dateValue . chr(10) . $httpRequest->getUri(); return $signData; }
/** * */ public function __construct($message, $code, \TYPO3\Flow\Http\Response $response, \TYPO3\Flow\Http\Request $request = NULL, \Exception $previous = NULL) { $this->response = $response; $this->request = $request; if ($request !== NULL) { $message = sprintf("[%s %s]: %s\n\nRequest data: %s", $request->getMethod(), $request->getUri(), $message . '; Response body: ' . $response->getContent(), $request->getContent()); } parent::__construct($message, $code, $previous); }
/** * Creates a PSR-7 compatible request * * @param \TYPO3\Flow\Http\Request $nativeRequest Flow request object * @param array $files List of uploaded files like in $_FILES * @param array $query List of uploaded files like in $_GET * @param array $post List of uploaded files like in $_POST * @param array $cookies List of uploaded files like in $_COOKIES * @param array $server List of uploaded files like in $_SERVER * @return \Psr\Http\Message\ServerRequestInterface PSR-7 request object */ protected function createRequest(\TYPO3\Flow\Http\Request $nativeRequest, array $files, array $query, array $post, array $cookies, array $server) { $server = ServerRequestFactory::normalizeServer($server); $files = ServerRequestFactory::normalizeFiles($files); $headers = $nativeRequest->getHeaders()->getAll(); $uri = (string) $nativeRequest->getUri(); $method = $nativeRequest->getMethod(); $body = new Stream('php://temp', 'wb+'); $body->write($nativeRequest->getContent()); return new ServerRequest($server, $files, $uri, $method, $body, $headers, $cookies, $query, $post); }
/** * Sends the given HTTP request * * @param \TYPO3\Flow\Http\Request $request * @return \TYPO3\Flow\Http\Response The response or FALSE * @api * @throws \TYPO3\Flow\Http\Exception * @throws CurlEngineException */ public function sendRequest(Request $request) { if (!extension_loaded('curl')) { throw new \TYPO3\Flow\Http\Exception('CurlEngine requires the PHP CURL extension to be installed and loaded.', 1346319808); } $requestUri = $request->getUri(); $curlHandle = curl_init((string) $requestUri); curl_setopt_array($curlHandle, $this->options); // Send an empty Expect header in order to avoid chunked data transfer (which we can't handle yet). // If we don't set this, cURL will set "Expect: 100-continue" for requests larger than 1024 bytes. curl_setopt($curlHandle, CURLOPT_HTTPHEADER, array('Expect:')); // If the content is a stream resource, use cURL's INFILE feature to stream it $content = $request->getContent(); if (is_resource($content)) { curl_setopt_array($curlHandle, array(CURLOPT_INFILE => $content, CURLOPT_INFILESIZE => $request->getHeader('Content-Length'))); } switch ($request->getMethod()) { case 'GET': if ($request->getContent()) { // workaround because else the request would implicitly fall into POST: curl_setopt($curlHandle, CURLOPT_CUSTOMREQUEST, 'GET'); if (!is_resource($content)) { curl_setopt($curlHandle, CURLOPT_POSTFIELDS, $content); } } break; case 'POST': curl_setopt($curlHandle, CURLOPT_POST, TRUE); if (!is_resource($content)) { $body = $content !== '' ? $content : http_build_query($request->getArguments()); curl_setopt($curlHandle, CURLOPT_POSTFIELDS, $body); } break; case 'PUT': curl_setopt($curlHandle, CURLOPT_PUT, TRUE); if (!is_resource($content) && $content !== '') { $inFileHandler = fopen('php://temp', 'r+'); fwrite($inFileHandler, $request->getContent()); rewind($inFileHandler); curl_setopt_array($curlHandle, array(CURLOPT_INFILE => $inFileHandler, CURLOPT_INFILESIZE => strlen($request->getContent()))); } break; default: if (!is_resource($content)) { $body = $content !== '' ? $content : http_build_query($request->getArguments()); curl_setopt($curlHandle, CURLOPT_POSTFIELDS, $body); } curl_setopt($curlHandle, CURLOPT_CUSTOMREQUEST, $request->getMethod()); } $preparedHeaders = array(); foreach ($request->getHeaders()->getAll() as $fieldName => $values) { foreach ($values as $value) { $preparedHeaders[] = $fieldName . ': ' . $value; } } curl_setopt($curlHandle, CURLOPT_HTTPHEADER, $preparedHeaders); // curl_setopt($curlHandle, CURLOPT_PROTOCOLS, CURLPROTO_HTTP && CURLPROTO_HTTPS); // CURLOPT_UPLOAD if ($requestUri->getPort() !== NULL) { curl_setopt($curlHandle, CURLOPT_PORT, $requestUri->getPort()); } // CURLOPT_COOKIE $curlResult = curl_exec($curlHandle); if ($curlResult === FALSE) { throw new CurlEngineException(sprintf('cURL reported error code %s with message "%s". Last requested URL was "%s" (%s).', curl_errno($curlHandle), curl_error($curlHandle), curl_getinfo($curlHandle, CURLINFO_EFFECTIVE_URL), $request->getMethod()), 1338906040); } elseif (strlen($curlResult) === 0) { return FALSE; } curl_close($curlHandle); $response = Response::createFromRaw($curlResult); if ($response->getStatusCode() === 100) { $response = Response::createFromRaw($response->getContent(), $response); } return $response; }
/** * @param HttpRequest $httpRequest * @param array $routingMatchResults * @return array */ protected function mergeArguments(HttpRequest $httpRequest, array $routingMatchResults = NULL) { // HTTP body arguments $this->propertyMappingConfiguration->setTypeConverterOption(\TYPO3\Flow\Property\TypeConverter\MediaTypeConverterInterface::class, MediaTypeConverterInterface::CONFIGURATION_MEDIA_TYPE, $httpRequest->getHeader('Content-Type')); $arguments = $this->propertyMapper->convert($httpRequest->getContent(), 'array', $this->propertyMappingConfiguration); // HTTP arguments (e.g. GET parameters) $arguments = Arrays::arrayMergeRecursiveOverrule($httpRequest->getArguments(), $arguments); // Routing results if ($routingMatchResults !== NULL) { $arguments = Arrays::arrayMergeRecursiveOverrule($arguments, $routingMatchResults); } return $arguments; }
/** * Parses the request body according to the media type. * * @param HttpRequest $httpRequest * @return array */ protected function parseRequestBody(HttpRequest $httpRequest) { $requestBody = $httpRequest->getContent(); if ($requestBody === null || $requestBody === '') { return []; } $mediaTypeConverter = $this->objectManager->get(MediaTypeConverterInterface::class); $propertyMappingConfiguration = new PropertyMappingConfiguration(); $propertyMappingConfiguration->setTypeConverter($mediaTypeConverter); $propertyMappingConfiguration->setTypeConverterOption(MediaTypeConverterInterface::class, MediaTypeConverterInterface::CONFIGURATION_MEDIA_TYPE, $httpRequest->getHeader('Content-Type')); $arguments = $this->propertyMapper->convert($requestBody, 'array', $propertyMappingConfiguration); return $arguments; }
/** * Builds a Json ExtDirect request by reading the transaction data from * the HTTP request body. * * @param \TYPO3\Flow\Http\Request $httpRequest The HTTP request * @return \TYPO3\ExtJS\ExtDirect\Request The Ext Direct request object * @throws \TYPO3\ExtJS\ExtDirect\Exception\InvalidExtDirectRequestException */ protected function buildJsonRequest(\TYPO3\Flow\Http\Request $httpRequest) { $allTransactionData = json_decode($httpRequest->getContent()); if ($allTransactionData === NULL) { throw new \TYPO3\ExtJS\ExtDirect\Exception\InvalidExtDirectRequestException('The request is not a valid Ext Direct request', 1268490738); } if (!is_array($allTransactionData)) { $allTransactionData = array($allTransactionData); } $extDirectRequest = new Request($httpRequest); foreach ($allTransactionData as $singleTransactionData) { $extDirectRequest->createAndAddTransaction($singleTransactionData->action, $singleTransactionData->method, is_array($singleTransactionData->data) ? $singleTransactionData->data : array(), $singleTransactionData->tid); } return $extDirectRequest; }