/** * Führt das Modul entsprechend der Commands.json und Component.json Definitionen aus */ public function run() { // runs the CConfig $com = new CConfig($this->_prefix, $this->_path, $this->_noInfo, $this->_noHelp); // lädt die Konfiguration des Moduls if ($com->used()) { return; } $conf = $com->loadConfig(); $this->_conf = $conf; $this->_com = $com; $commands = $com->commands(array(), true, true); // multi Requests werden noch nicht unterstützt, das Model soll automatisch die Möglichkeit bieten, // mehrere Anfragen mit einmal zu beantworten ////$commands[] = array('name' => 'postMultiGetRequest','method' => 'POST', 'path' => '/multiGetRequest', 'inputType' => 'Link', 'outputType' => ''); // Erstellt für jeden angebotenen Befehl einen Router // Ein Router stellt einen erlaubten Aufruf dar (mit Methode und URI), sodass geprüft werden kann, // welcher für die Beantwortung zuständig ist $router = new \Slim\Router(); foreach ($commands as &$command) { if (!isset($command['name'])) { continue; } if (!isset($command['method'])) { $command['method'] = 'GET'; } if (!isset($command['callback'])) { $command['callback'] = $command['name']; } if (!isset($command['seqInput'])) { $command['seqInput'] = 'TRUE'; } if (!isset($command['singleOutput'])) { $command['singleOutput'] = 'FALSE'; } if (!isset($command['placeholder'])) { $command['placeholder'] = array(); } // Methoden können durch Komma getrennt aufgelistet sein $methods = explode(',', $command['method']); foreach ($methods as $method) { $route = new \Slim\Route($command['path'], array($this->_class, $command['callback']), false); $route->via(strtoupper($method)); $route->setName($command['name']); $router->map($route); // wenn es ein GET Befehl ist, wird automatisch HEAD unterstützt if (strtoupper($method) == 'GET') { // erzeugt einen HEAD Router $route = new \Slim\Route($command['path'], array($this->_class, $command['callback']), false); $route->via('HEAD'); $route->setName($command['name']); $router->map($route); } } } // hier wird die eingehende URI erzeugt // Bsp.: /user/1 $scriptName = $_SERVER['SCRIPT_NAME']; $requestUri = $_SERVER['REQUEST_URI']; $path = str_replace('?' . (isset($_SERVER['QUERY_STRING']) ? $_SERVER['QUERY_STRING'] : ''), '', substr_replace($requestUri, '', 0, strlen(strpos($requestUri, $scriptName) !== false ? $scriptName : str_replace('\\', '', dirname($scriptName))))); // ermittelt den zuständigen Befehl $matches = $router->getMatchedRoutes(strtoupper($_SERVER['REQUEST_METHOD']), $path); if (count($matches) > 0) { // mindestens ein zutreffender Befehl wurde gefunden (nimm den Ersten) $matches = $matches[0]; // suche den zugehörigen $commands Eintrag $selectedCommand = null; foreach ($commands as $command) { if ($command['name'] === $matches->getName()) { $selectedCommand = $command; break; } } if ($selectedCommand == null) { http_response_code(500); return; } // lies die eingehenden PHP Daten $rawInput = \Slim\Environment::getInstance()->offsetGet('slim.input'); if (!$rawInput) { $rawInput = @file_get_contents('php://input'); } // wir wollen wissen, ob die Eingabedaten als Liste rein kommen $arr = true; // wenn zu diesem Befehl ein inputType angegeben wurde, wird eine Type::decodeType() aufgerufen if (isset($selectedCommand['inputType']) && trim($selectedCommand['inputType']) != '') { $inputType = $selectedCommand['inputType']; $rawInput = call_user_func_array('\\' . $inputType . '::decode' . $inputType, array($rawInput)); if (!is_array($rawInput)) { // es ist keine Liste, also mach eine daraus (damit man sie einheitlich behandeln kann) $rawInput = array($rawInput); $arr = false; } } if (strtoupper($selectedCommand['seqInput']) != 'TRUE') { $arr = false; } $params = $matches->getParams(); $placeholder = array(); // prüfe die Bedingungen für die Platzhalter foreach ($selectedCommand['placeholder'] as $holder) { if (!isset($holder['name'])) { continue; } if (!isset($holder['regex'])) { continue; } $placeholder[$holder['name']] = $holder['regex']; } /*foreach ($params as $key => $value){ if (isset($placeholder[$key])){ if (is_array($value)){ // wenn es ein Array ist, wurde ein :Element+ verwendet (Slim) // daher wird der Ausdruck auf jedes Element angewendet foreach($value as $val){ $pregRes = @preg_match($placeholder[$key], $val); if ($pregRes === false){ error_log(__FILE__.':'.__LINE__.' '.$placeholder[$key].' konnte nicht interpretiert werden'); $this->finishRequest(self::isError()); return; } else if ($pregRes === 0){ error_log(__FILE__.':'.__LINE__.' '.$val.' passt nicht zu '.$placeholder[$key]); $this->finishRequest(self::isPreconditionError()); return; } } } else { // einzelnes Element für Slim verwendet :Element $pregRes = @preg_match($placeholder[$key], $value); if ($pregRes === false){ error_log(__FILE__.':'.__LINE__.' '.$placeholder[$key].' konnte nicht interpretiert werden'); $this->finishRequest(self::isError()); return; } else if ($pregRes === 0){ error_log(__FILE__.':'.__LINE__.' '.$value.' passt nicht zu '.$placeholder[$key]); $this->finishRequest(self::isPreconditionError()); return; } } } }*/ // nun soll die zugehörige Funktion im Modul aufgerufen werden if (isset($selectedCommand['inputType']) && trim($selectedCommand['inputType']) != '' && isset($rawInput)) { // initialisiert die Ausgabe positiv $result = array("status" => 201, "content" => array()); if (strtoupper($selectedCommand['seqInput']) == 'TRUE') { try { // für jede Eingabe wird die Funktion ausgeführt foreach ($rawInput as $input) { // Aufruf der Modulfunktion $res = call_user_func_array($matches->getCallable(), array($selectedCommand['name'], "input" => $input, $params)); // wenn es ein Ausgabeobjekt gibt, wird versucht dort einen Status zu setzen if (is_callable(array($res['content'], 'setStatus'))) { $res['content']->setStatus($res['status']); } // setze Status und Ausgabe $result["content"][] = $res['content']; if (isset($res['status'])) { $result["status"] = $res['status']; } } } catch (Exception $e) { header_remove(); error_log($e->getMessage()); $this->finishRequest(self::isError()); return; } } else { try { // Aufruf der Modulfunktion $res = call_user_func_array($matches->getCallable(), array($selectedCommand['name'], "input" => $rawInput, $params)); // wenn es ein Ausgabeobjekt gibt, wird versucht dort einen Status zu setzen if (is_callable(array($res['content'], 'setStatus'))) { $res['content']->setStatus($res['status']); } // setze Status und Ausgabe $result["content"] = $res['content']; if (isset($res['status'])) { $result["status"] = $res['status']; } } catch (Exception $e) { header_remove(); error_log($e->getMessage()); $this->finishRequest(self::isError()); return; } } } else { // wenn keinen vorgegebenen Eingabetyp gibt, wird die Eingabe direkt an die Modulfunktion weitergegeben $result = call_user_func_array($matches->getCallable(), array($selectedCommand['name'], "input" => $rawInput, $params)); } if ($selectedCommand['method'] == 'HEAD') { // Bei einer HEAD Funktion (die eventuell im Modul als GET bearbeitet wird), // kann die Ausgabe verworfen werden $result['content'] = ''; } elseif (isset($selectedCommand['outputType']) && trim($selectedCommand['outputType']) != '' && trim($selectedCommand['outputType']) != 'binary') { // wenn ein Ausgabetyp angegeben ist, wird eine Typ::encodeTyp() ausgeführt $outputType = $selectedCommand['outputType']; if (isset($result['content'])) { if (!is_array($result['content'])) { $result['content'] = array($result['content']); } if ($command['singleOutput'] !== 'FALSE' && count($result['content']) >= 1) { $result['content'] = $result['content'][0]; } elseif (!$arr && count($result['content']) == 1) { $result['content'] = $result['content'][0]; } $result['content'] = call_user_func_array('\\' . $outputType . '::encode' . $outputType, array($result['content'])); } header('Content-Type: application/json'); } elseif (isset($selectedCommand['outputType']) && trim($selectedCommand['outputType']) == 'binary') { // wenn der Ausgabetyp "binär" ist, erfolgt keine Anpassung } else { // selbst wenn nichts zutrifft, wird json kodiert if (isset($result['content'])) { $result['content'] = json_encode($result['content']); } header('Content-Type: application/json'); } } else { // es wurde kein zutreffender Befehl gefunden, also gibt es eine leere Antwort $this->finishRequest(self::isError()); return; } // ab hier werden die Ergebnisse ausgegeben $this->finishRequest($result); }
/** * Test that router returns matched routes based on URI only, not * based on the HTTP method. */ public function testRouterMatchesRoutesByUriOnly() { \Slim\Environment::mock(array('REQUEST_METHOD' => 'GET', 'REMOTE_ADDR' => '127.0.0.1', 'SCRIPT_NAME' => '', 'PATH_INFO' => '/foo', 'QUERY_STRING' => 'one=1&two=2&three=3', 'SERVER_NAME' => 'slim', 'SERVER_PORT' => 80, 'slim.url_scheme' => 'http', 'slim.input' => '', 'slim.errors' => fopen('php://stderr', 'w'), 'HTTP_HOST' => 'slim')); $this->env = \Slim\Environment::getInstance(); $this->req = new \Slim\Http\Request($this->env); $this->res = new \Slim\Http\Response(); $router = new \Slim\Router(); $router->setResourceUri($this->req->getResourceUri()); $router->map('/foo', function () { })->via('GET'); $router->map('/foo', function () { })->via('POST'); $router->map('/foo', function () { })->via('PUT'); $router->map('/foo/bar/xyz', function () { })->via('DELETE'); $this->assertEquals(3, count($router->getMatchedRoutes())); }
/** * the getl function uses a list of links to find a * relevant component for the $data request * * @param $data a slim generated array of URI segments (String[]) */ public function getl($data) { Logger::Log('starts Controller routing', LogLevel::DEBUG); // if no URI is received, abort process if (count($data) == 0) { Logger::Log('Controller nothing to route', LogLevel::DEBUG); $this->_app->response->setStatus(409); $this->_app->stop(); return; } $URI = '/' . implode('/', $data); // get possible links $list = CConfig::getLinks($this->_conf->getLinks(), 'out'); foreach ($list as $links) { $componentURL = $links->getAddress(); $similar = Controller2::UrlAnd($componentURL, $URI); if ($similar != null) { $URI2 = substr($URI, Controller2::UrlAnd($componentURL, $URI)); $relevanz = explode(' ', $links->getRelevanz()); $found = false; foreach ($relevanz as $rel) { if ($rel == 'ALL') { $found = true; break; } $sub = strpos($rel, '_'); if ($sub !== false) { $method = substr($rel, 0, $sub); $path = substr($rel, $sub + 1); if (strtoupper($method) == strtoupper($this->_app->request->getMethod())) { $router = new \Slim\Router(); $route = new \Slim\Route($path, 'is_array'); $route->via(strtoupper($method)); $router->map($route); $routes = count($router->getMatchedRoutes(strtoupper($method), $URI2), true); if ($routes === 0) { continue; } $found = true; break; } } } if (!$found) { continue; } // create a custom request $ch = Request::custom($this->_app->request->getMethod(), $componentURL . substr($URI, $similar), array(), $this->_app->request->getBody()); // checks the answered status code if ($ch['status'] >= 200 && $ch['status'] <= 299) { // finished $this->_app->response->setStatus($ch['status']); $this->_app->response->setBody($ch['content']); if (isset($ch['headers']['Content-Type'])) { $this->_app->response->headers->set('Content-Type', $ch['headers']['Content-Type']); } if (isset($ch['headers']['Content-Disposition'])) { $this->_app->response->headers->set('Content-Disposition', $ch['headers']['Content-Disposition']); } Logger::Log('Controller2 search done', LogLevel::DEBUG); $this->_app->stop(); } } } // no positive response or no operative link $this->_app->response->setStatus(409); $this->_app->response->setBody(''); }