public function testFragmentsOverride() { $negotiator = new PjaxResponseNegotiator(array('alpha' => function () { return 'alpha response'; }, 'beta' => function () { return 'beta response'; })); $request = new SS_HTTPRequest('GET', '/'); $request->addHeader('X-Pjax', 'alpha'); $request->addHeader('Accept', 'text/json'); $response = $negotiator->setFragmentOverride(array('beta'))->respond($request); $json = json_decode($response->getBody()); $this->assertFalse(isset($json->alpha)); $this->assertObjectHasAttribute('beta', $json); }
protected function genRequest($accept = null, $method = 'GET') { $req = new SS_HTTPRequest($method, '/'); if ($accept) { $req->addHeader('Accept', $accept); } return $req; }
function testSelectsFragmentByHeader() { $negotiator = new PjaxResponseNegotiator(array( 'default' => function() {return 'default response';}, 'myfragment' => function() {return 'myfragment response';}, )); $request = new SS_HTTPRequest('GET', '/'); $request->addHeader('X-Pjax', 'myfragment'); $this->assertEquals('myfragment response', $negotiator->respond($request)); }
public function testIsAjax() { $req = new SS_HTTPRequest('GET', '/', array('ajax' => 0)); $this->assertFalse($req->isAjax()); $req = new SS_HTTPRequest('GET', '/', array('ajax' => 1)); $this->assertTrue($req->isAjax()); $req = new SS_HTTPRequest('GET', '/'); $req->addHeader('X-Requested-With', 'XMLHttpRequest'); $this->assertTrue($req->isAjax()); }
protected function genRequest($accept = null, $body = '') { $req = new SS_HTTPRequest('POST', '/'); if ($accept) { $req->addHeader('Content-Type', $accept); } if ($body) { $req->setBody($body); } return $req; }
/** * Test a URL request, returning a response object. This method is the counterpart of * Director::direct() that is used in functional testing. It will execute the URL given, and * return the result as an SS_HTTPResponse object. * * @uses getControllerForURL() The rule-lookup logic is handled by this. * @uses Controller::run() Handles the page logic for a Director::direct() call. * * @param string $url The URL to visit. * @param array $postVars The $_POST & $_FILES variables. * @param array|Session $session The {@link Session} object representing the current session. * By passing the same object to multiple calls of Director::test(), you can simulate a persisted * session. * @param string $httpMethod The HTTP method, such as GET or POST. It will default to POST if * postVars is set, GET otherwise. Overwritten by $postVars['_method'] if present. * @param string $body The HTTP body. * @param array $headers HTTP headers with key-value pairs. * @param array|Cookie_Backend $cookies to populate $_COOKIE. * @param HTTP_Request $request The {@see HTTP_Request} object generated as a part of this request. * * @return SS_HTTPResponse * * @throws SS_HTTPResponse_Exception */ public static function test($url, $postVars = null, $session = array(), $httpMethod = null, $body = null, $headers = array(), $cookies = array(), &$request = null) { Config::nest(); Injector::nest(); // These are needed so that calling Director::test() does not muck with whoever is calling it. // Really, it's some inappropriate coupling and should be resolved by making less use of statics. $oldReadingMode = Versioned::get_reading_mode(); $getVars = array(); if (!$httpMethod) { $httpMethod = $postVars || is_array($postVars) ? "POST" : "GET"; } if (!$session) { $session = Injector::inst()->create('Session', array()); } $cookieJar = $cookies instanceof Cookie_Backend ? $cookies : Injector::inst()->createWithArgs('Cookie_Backend', array($cookies ?: array())); // Back up the current values of the superglobals $existingRequestVars = isset($_REQUEST) ? $_REQUEST : array(); $existingGetVars = isset($_GET) ? $_GET : array(); $existingPostVars = isset($_POST) ? $_POST : array(); $existingSessionVars = isset($_SESSION) ? $_SESSION : array(); $existingCookies = isset($_COOKIE) ? $_COOKIE : array(); $existingServer = isset($_SERVER) ? $_SERVER : array(); $existingRequirementsBackend = Requirements::backend(); Config::inst()->update('Cookie', 'report_errors', false); Requirements::set_backend(Injector::inst()->create('Requirements_Backend')); // Set callback to invoke prior to return $onCleanup = function () use($existingRequestVars, $existingGetVars, $existingPostVars, $existingSessionVars, $existingCookies, $existingServer, $existingRequirementsBackend, $oldReadingMode) { // Restore the super globals $_REQUEST = $existingRequestVars; $_GET = $existingGetVars; $_POST = $existingPostVars; $_SESSION = $existingSessionVars; $_COOKIE = $existingCookies; $_SERVER = $existingServer; Requirements::set_backend($existingRequirementsBackend); // These are needed so that calling Director::test() does not muck with whoever is calling it. // Really, it's some inappropriate coupling and should be resolved by making less use of statics Versioned::set_reading_mode($oldReadingMode); Injector::unnest(); // Restore old CookieJar, etc Config::unnest(); }; if (strpos($url, '#') !== false) { $url = substr($url, 0, strpos($url, '#')); } // Handle absolute URLs if (parse_url($url, PHP_URL_HOST)) { $bits = parse_url($url); // If a port is mentioned in the absolute URL, be sure to add that into the HTTP host if (isset($bits['port'])) { $_SERVER['HTTP_HOST'] = $bits['host'] . ':' . $bits['port']; } else { $_SERVER['HTTP_HOST'] = $bits['host']; } } // Ensure URL is properly made relative. // Example: url passed is "/ss31/my-page" (prefixed with BASE_URL), this should be changed to "my-page" $url = self::makeRelative($url); $urlWithQuerystring = $url; if (strpos($url, '?') !== false) { list($url, $getVarsEncoded) = explode('?', $url, 2); parse_str($getVarsEncoded, $getVars); } // Replace the super globals with appropriate test values $_REQUEST = ArrayLib::array_merge_recursive((array) $getVars, (array) $postVars); $_GET = (array) $getVars; $_POST = (array) $postVars; $_SESSION = $session ? $session->inst_getAll() : array(); $_COOKIE = $cookieJar->getAll(false); Injector::inst()->registerService($cookieJar, 'Cookie_Backend'); $_SERVER['REQUEST_URI'] = Director::baseURL() . $urlWithQuerystring; $request = new SS_HTTPRequest($httpMethod, $url, $getVars, $postVars, $body); if ($headers) { foreach ($headers as $k => $v) { $request->addHeader($k, $v); } } // Pre-request filtering // @see issue #2517 $model = DataModel::inst(); $output = Injector::inst()->get('RequestProcessor')->preRequest($request, $session, $model); if ($output === false) { $onCleanup(); throw new SS_HTTPResponse_Exception(_t('Director.INVALID_REQUEST', 'Invalid request'), 400); } // TODO: Pass in the DataModel $result = Director::handleRequest($request, $session, $model); // Ensure that the result is an SS_HTTPResponse object if (is_string($result)) { if (substr($result, 0, 9) == 'redirect:') { $response = new SS_HTTPResponse(); $response->redirect(substr($result, 9)); $result = $response; } else { $result = new SS_HTTPResponse($result); } } $output = Injector::inst()->get('RequestProcessor')->postRequest($request, $result, $model); if ($output === false) { $onCleanup(); throw new SS_HTTPResponse_Exception("Invalid response"); } // Return valid response $onCleanup(); return $result; }
/** * Test a URL request, returning a response object. * * This method is the counterpart of Director::direct() that is used in functional testing. It will execute the URL given, * * @param string $url The URL to visit * @param array $postVars The $_POST & $_FILES variables * @param Session $session The {@link Session} object representing the current session. By passing the same object to multiple * calls of Director::test(), you can simulate a persisted session. * @param string $httpMethod The HTTP method, such as GET or POST. It will default to POST if postVars is set, GET otherwise. * Overwritten by $postVars['_method'] if present. * @param string $body The HTTP body * @param array $headers HTTP headers with key-value pairs * @param array $cookies to populate $_COOKIE * @return SS_HTTPResponse * * @uses getControllerForURL() The rule-lookup logic is handled by this. * @uses Controller::run() Controller::run() handles the page logic for a Director::direct() call. */ static function test($url, $postVars = null, $session = null, $httpMethod = null, $body = null, $headers = null, $cookies = null) { // These are needed so that calling Director::test() doesnt muck with whoever is calling it. // Really, it's some inappropriate coupling and should be resolved by making less use of statics $oldStage = Versioned::current_stage(); $getVars = array(); if (!$httpMethod) { $httpMethod = $postVars || is_array($postVars) ? "POST" : "GET"; } if (!$session) { $session = new Session(null); } // Back up the current values of the superglobals $existingRequestVars = isset($_REQUEST) ? $_REQUEST : array(); $existingGetVars = isset($_GET) ? $_GET : array(); $existingPostVars = isset($_POST) ? $_POST : array(); $existingSessionVars = isset($_SESSION) ? $_SESSION : array(); $existingCookies = isset($_COOKIE) ? $_COOKIE : array(); $existingServer = isset($_SERVER) ? $_SERVER : array(); $existingCookieReportErrors = Cookie::report_errors(); $existingRequirementsBackend = Requirements::backend(); Cookie::set_report_errors(false); Requirements::set_backend(new Requirements_Backend()); // Handle absolute URLs if (@parse_url($url, PHP_URL_HOST) != '') { $bits = parse_url($url); $_SERVER['HTTP_HOST'] = $bits['host']; $url = Director::makeRelative($url); } $urlWithQuerystring = $url; if (strpos($url, '?') !== false) { list($url, $getVarsEncoded) = explode('?', $url, 2); parse_str($getVarsEncoded, $getVars); } // Replace the superglobals with appropriate test values $_REQUEST = array_merge((array) $getVars, (array) $postVars); $_GET = (array) $getVars; $_POST = (array) $postVars; $_SESSION = $session ? $session->inst_getAll() : array(); $_COOKIE = (array) $cookies; $_SERVER['REQUEST_URI'] = Director::baseURL() . $urlWithQuerystring; $req = new SS_HTTPRequest($httpMethod, $url, $getVars, $postVars, $body); if ($headers) { foreach ($headers as $k => $v) { $req->addHeader($k, $v); } } $result = Director::handleRequest($req, $session); // Restore the superglobals $_REQUEST = $existingRequestVars; $_GET = $existingGetVars; $_POST = $existingPostVars; $_SESSION = $existingSessionVars; $_COOKIE = $existingCookies; $_SERVER = $existingServer; Cookie::set_report_errors($existingCookieReportErrors); Requirements::set_backend($existingRequirementsBackend); // These are needed so that calling Director::test() doesnt muck with whoever is calling it. // Really, it's some inappropriate coupling and should be resolved by making less use of statics Versioned::reading_stage($oldStage); return $result; }
public function testCheckRequest() { $t = new SecurityToken(); $n = $t->getName(); $t->setValue(null); $r = new SS_HTTPRequest('GET', 'dummy', array($n => 'invalidtoken')); $this->assertFalse($t->checkRequest($r), 'Any token is invalid if no token is stored'); $t->setValue(null); $r = new SS_HTTPRequest('GET', 'dummy', array($n => null)); $this->assertFalse($t->checkRequest($r), 'NULL token is invalid if no token is stored'); $t->setValue('mytoken'); $r = new SS_HTTPRequest('GET', 'dummy', array($n => 'invalidtoken')); $this->assertFalse($t->checkRequest($r), 'Invalid token returns false'); $t->setValue('mytoken'); $r = new SS_HTTPRequest('GET', 'dummy', array($n => 'mytoken')); $this->assertTrue($t->checkRequest($r), 'Valid token returns true'); $t->setValue('mytoken'); $r = new SS_HTTPRequest('GET', 'dummy'); $r->addHeader('X-Securityid', 'mytoken'); $this->assertTrue($t->checkRequest($r), 'Valid token returns true'); $t->setValue('mytoken'); $r = new SS_HTTPRequest('GET', 'dummy'); $r->addHeader('X-Securityid', 'wrongtoken'); $this->assertFalse($t->checkRequest($r), 'Valid token returns true'); }
<?php require_once __DIR__ . '/../framework/core/Core.php'; $request = new SS_HTTPRequest($_SERVER['REQUEST_METHOD'], isset($_GET['url']) ? $_GET['url'] : '', $_GET); $headers = Director::extract_request_headers($_SERVER); foreach ($headers as $header => $value) { $request->addHeader($header, $value); } $container = Injector::inst(); $session = $container->create('Session', array()); if (Session::request_contains_session_id()) { $session->inst_start(); } $container->get('RequestProcessor')->preRequest($request, $session, DataModel::inst()); require_once __DIR__ . '/../framework/main.php';
/** * Checks authentication works with a generated token */ public function testAuthenticate() { $member = Member::get()->filter(array('Email' => '*****@*****.**'))->first(); $auth = $this->getAuthenticator(); $request = new SS_HTTPRequest('GET', 'api/ApiTest_Book/1'); $auth->resetToken($member->ID); $token = $auth->getToken($member->ID); $request->addHeader('X-Silverstripe-Apitoken', $token); $result = $auth->authenticate($request); $this->assertTrue($result, "TokenAuth authentication success should return true"); $auth->resetToken($member->ID); $result = $auth->authenticate($request); $this->assertContainsOnlyInstancesOf('RESTfulAPI_Error', array($result), "TokenAuth authentication failure should return a RESTfulAPI_Error"); }
/** * Test a URL request, returning a response object. * * This method is the counterpart of Director::direct() that is used in functional testing. It will execute the * URL given, and return the result as an SS_HTTPResponse object. * * @param string $url The URL to visit * @param array $postVars The $_POST & $_FILES variables * @param Session $session The {@link Session} object representing the current session. By passing the same * object to multiple calls of Director::test(), you can simulate a persisted session. * @param string $httpMethod The HTTP method, such as GET or POST. It will default to POST if postVars is set, * GET otherwise. Overwritten by $postVars['_method'] if present. * @param string $body The HTTP body * @param array $headers HTTP headers with key-value pairs * @param array $cookies to populate $_COOKIE * @param HTTP_Request $request The {@see HTTP_Request} object generated as a part of this request * @return SS_HTTPResponse * * @uses getControllerForURL() The rule-lookup logic is handled by this. * @uses Controller::run() Controller::run() handles the page logic for a Director::direct() call. */ public static function test($url, $postVars = null, $session = null, $httpMethod = null, $body = null, $headers = null, $cookies = null, &$request = null) { Config::nest(); // These are needed so that calling Director::test() doesnt muck with whoever is calling it. // Really, it's some inappropriate coupling and should be resolved by making less use of statics $oldStage = Versioned::current_stage(); $getVars = array(); if (!$httpMethod) { $httpMethod = $postVars || is_array($postVars) ? "POST" : "GET"; } if (!$session) { $session = new Session(null); } // Back up the current values of the superglobals $existingRequestVars = isset($_REQUEST) ? $_REQUEST : array(); $existingGetVars = isset($_GET) ? $_GET : array(); $existingPostVars = isset($_POST) ? $_POST : array(); $existingSessionVars = isset($_SESSION) ? $_SESSION : array(); $existingCookies = isset($_COOKIE) ? $_COOKIE : array(); $existingServer = isset($_SERVER) ? $_SERVER : array(); $existingRequirementsBackend = Requirements::backend(); Config::inst()->update('Cookie', 'report_errors', false); Requirements::set_backend(new Requirements_Backend()); // Handle absolute URLs if (@parse_url($url, PHP_URL_HOST) != '') { $bits = parse_url($url); $_SERVER['HTTP_HOST'] = $bits['host']; $url = Director::makeRelative($url); } $urlWithQuerystring = $url; if (strpos($url, '?') !== false) { list($url, $getVarsEncoded) = explode('?', $url, 2); parse_str($getVarsEncoded, $getVars); } // Replace the superglobals with appropriate test values $_REQUEST = ArrayLib::array_merge_recursive((array) $getVars, (array) $postVars); $_GET = (array) $getVars; $_POST = (array) $postVars; $_SESSION = $session ? $session->inst_getAll() : array(); $_COOKIE = (array) $cookies; $_SERVER['REQUEST_URI'] = Director::baseURL() . $urlWithQuerystring; $request = new SS_HTTPRequest($httpMethod, $url, $getVars, $postVars, $body); if ($headers) { foreach ($headers as $k => $v) { $request->addHeader($k, $v); } } // Pre-request filtering // @see issue #2517 $model = DataModel::inst(); $output = Injector::inst()->get('RequestProcessor')->preRequest($request, $session, $model); if ($output === false) { // @TODO Need to NOT proceed with the request in an elegant manner throw new SS_HTTPResponse_Exception(_t('Director.INVALID_REQUEST', 'Invalid request'), 400); } // TODO: Pass in the DataModel $result = Director::handleRequest($request, $session, $model); // Ensure that the result is an SS_HTTPResponse object if (is_string($result)) { if (substr($result, 0, 9) == 'redirect:') { $response = new SS_HTTPResponse(); $response->redirect(substr($result, 9)); $result = $response; } else { $result = new SS_HTTPResponse($result); } } $output = Injector::inst()->get('RequestProcessor')->postRequest($request, $result, $model); if ($output === false) { throw new SS_HTTPResponse_Exception("Invalid response"); } // Restore the superglobals $_REQUEST = $existingRequestVars; $_GET = $existingGetVars; $_POST = $existingPostVars; $_SESSION = $existingSessionVars; $_COOKIE = $existingCookies; $_SERVER = $existingServer; Requirements::set_backend($existingRequirementsBackend); // These are needed so that calling Director::test() doesnt muck with whoever is calling it. // Really, it's some inappropriate coupling and should be resolved by making less use of statics Versioned::reading_stage($oldStage); Config::unnest(); return $result; }
function testPullRegionWithRenderContext() { // this is a dirty dirty mess. sorry. $req = new SS_HTTPRequest('GET', '/test1'); $req->addHeader(AjaxHTTPResponse::PULL_HEADER, 'TestProductGroupItem:BUYABLE'); $req->addHeader('X-Requested-With', 'XMLHttpRequest'); $ctrl = new Controller(); $ctrl->pushCurrent(); $ctrl->setRequest($req); $ctrl->setDataModel(DataModel::inst()); $ctrl->setURLParams(array()); $ctrl->init(); $response = $ctrl->getAjaxResponse(); $response->addRenderContext('BUYABLE', new ArrayData(array('Title' => 'Test Product', 'Link' => '/test-product', 'Price' => 29.99))); $data = json_decode($response->getBody(), true); $ctrl->popCurrent(); $this->assertNotEmpty($data[AjaxHTTPResponse::REGIONS_KEY]['TestProductGroupItem']); }
/** * Generates a fake request for the field * @param {SS_HTTPRequest} $request Source Request to base the fake request off of * @param {Widget} $sourceWidget Source widget * @param {string} $baseLink Base URL to be truncated off of the form * @return {SS_HTTPRequest} Fake HTTP Request used to fool the form field into thinking the request was made to it directly */ protected function getFakeRequest(SS_HTTPRequest $request, Widget $sourceWidget, $baseLink) { $fieldName = rawurldecode($request->param('FieldName')); $objID = preg_replace('/Widget\\[(.*?)\\]\\[(.*?)\\]\\[(.*?)\\]$/', '$2', $fieldName); $finalPostVars = array(); if ($request->isPOST()) { $postVars = $request->postVars(); //Pull the post data for the widget if (isset($postVars['Widget'][$this->getName()][$objID])) { $finalPostVars = $postVars['Widget'][$this->getName()][$objID]; } else { $finalPostVars = array(); } $finalPostVars = array_merge($finalPostVars, $postVars); unset($finalPostVars['Widget']); //Workaround for UploadField's and GridFields confusing the request $fields = $sourceWidget->getCMSFields(); $uploadFields = array(); $gridFields = array(); foreach ($fields as $field) { if ($field instanceof UploadField) { $uploadFields[] = $field->getName(); } else { if ($field instanceof GridField) { $gridFields[] = $field->getName(); } } } //Re-orgazine the upload field data if (count($uploadFields)) { foreach ($uploadFields as $field) { $formFieldName = 'Widget[' . $this->getName() . '][' . $objID . '][' . $field . ']'; $fieldData = array($formFieldName => array('name' => array('Uploads' => array()), 'type' => array('Uploads' => array()), 'tmp_name' => array('Uploads' => array()), 'error' => array('Uploads' => array()), 'size' => array('Uploads' => array()))); if (isset($postVars['Widget']['name'][$this->getName()][$objID][$field]['Uploads'])) { for ($i = 0; $i < count($postVars['Widget']['name'][$this->getName()][$objID][$field]['Uploads']); $i++) { $fieldData[$formFieldName]['name']['Uploads'][] = $postVars['Widget']['name'][$this->getName()][$objID][$field]['Uploads'][$i]; $fieldData[$formFieldName]['type']['Uploads'][] = $postVars['Widget']['type'][$this->getName()][$objID][$field]['Uploads'][$i]; $fieldData[$formFieldName]['tmp_name']['Uploads'][] = $postVars['Widget']['tmp_name'][$this->getName()][$objID][$field]['Uploads'][$i]; $fieldData[$formFieldName]['error']['Uploads'][] = $postVars['Widget']['error'][$this->getName()][$objID][$field]['Uploads'][$i]; $fieldData[$formFieldName]['size']['Uploads'][] = $postVars['Widget']['size'][$this->getName()][$objID][$field]['Uploads'][$i]; } } $finalPostVars = array_merge_recursive($finalPostVars, $fieldData); } } //Reorganize the gridfield data if (count($gridFields) && isset($postVars['Widget'][$this->getName()][$objID])) { foreach ($gridFields as $field) { $formFieldName = 'Widget[' . $this->getName() . '][' . $objID . '][' . $field . ']'; $fieldData = array($formFieldName => $postVars['Widget'][$this->getName()][$objID][$field]); } $finalPostVars = array_merge_recursive($finalPostVars, $fieldData); } } $headers = $request->getHeaders(); $request = new SS_HTTPRequest($_SERVER['REQUEST_METHOD'], str_replace(rtrim($baseLink, '/'), '', rtrim($request->getURL(), '/')) . '/', $request->getVars(), $finalPostVars, $request->getBody()); $request->match('$Action/$ID/$OtherID'); //Merge in the headers foreach ($headers as $header => $value) { $request->addHeader($header, $value); } return $request; }