Core Boxx – Route Module

TABLE OF CONTENTS

 

FILES CONFIG NOTES

Files and config list for this module, and some notes (if any).

 

FILES LIST

  • LIB/LIB-Route.php The one that resolves “URL to PHP file”.
  • LIB/HOOK-Routes.php Manual overrides for “URL to PHP file”.
  • LIB/HOOK-API-CORS.php Manual overrides for “which domains can access the API”.

 

RELATED CONFIG

In CORE-Config.php, the “important URL settings” are:

  • HOST_BASE Your base URL.
    • If the project is deployed at the root – http://site.com/
    • Include the path and trailing slash if not – http://site.com/myproject/
  • HOST_API This defaults to api/. That is, the API endpoints will be deployed at http://site.com/api/.
  • API_CORS Cross-origins permissions for API.
    • false No cross-origins allowed. Use this if you are not planning to develop mobile apps and open up to 3rd parties.
    • true All cross-origins are allowed. NOT RECOMMENDED. Huge security risk.
    • string Only calls from this domain are allowed.
    • array Only calls from this list of domains are allowed.

 

 

URL ROUTE ENGINE CONCEPTS

The “pretty URL” engine in Core Boxx covers 2 parts – Serving HTML pages and responding to API calls.

 

A QUICK TRACE OF WHAT HAPPENS

HTACCESS

.htaccess
RewriteEngine On
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]

To drive the pretty URL, Apache mod_rewrite must be enabled to work properly. As for this .htaccess file, I “borrowed” it from WordPress. In simple English:

  • Route all URLs to index.php.
  • Do not rewrite HTTP auth requests.
  • Do not rewrite existing files and folders.

Simply put, we will write our own PHP to resolve the URL.

P.S. If you are using IIS or NGINX, you can translate this on your own.

 

ROUTE ENGINE TAKEOVER

index.php
require __DIR__ . DIRECTORY_SEPARATOR . "lib" . DIRECTORY_SEPARATOR . "CORE-Go.php";
$_CORE->load("Route");
$_CORE->Route->run();

Now that http://site.com/EVERYTHING will point to index.php, we can build our own “URL resolve engine”. Not going to explain line-by-line, a quick summary:

  • $_CORE->Route->run() Determines if it is a request for an HTML page or an API call.
  • $_CORE->Route->resolve() Will handle “URL to HTML page”, then $_CORE->Route->load() will load the file itself.
  • $_CORE->Route->api() Will handle API calls.

 

 

RESOLVING HTML PAGES

DEFAULT “URL TO HTML PAGE”

  • http://site.com/ will resolve to pages/PAGE-home.php.
  • http://site.com/foo will resolve to pages/PAGE-foo.php.
  • http://site.com/foo/bar will resolve to pages/PAGE-foo-bar.php.
  • If pages/PAGE-foo.php is not found, it will load pages/PAGE-404.php.

So at the bare minimum, your project needs to have:

  • pages/PAGE-home.php The home page.
  • pages/PAGE-404.php Not found.

 

OVERRIDE URL RESOLVE

You can override the “URL to HTML page” in lib/HOOK-Routes.php.

  • $override A function to modify the URL path.
  • $routes Map URL path to file.
  • $wild Wildcard path routing.

The precedence order as above – Path override, exact route, wildcard route, default route. See “override examples” below for more.

 

RESOLVING API CALLS

DEFAULT “URL TO API HANDLER”

  • API URLs have the following structure – http://site.com/api/MODULE/ACTION. Examples:
    • Access http://site.com/api/items/get to get all items.
    • Send $_POST["name"] = "NEW" to http://site.com/api/items/save to add a new item.
    • Send $_POST["id"] = 123 to http://site.com/api/items/del to delete an item.
  • http://site.com/api/items will resolve to lib/API-items.php. If this script is not found, it will output an “invalid request”.

 

 

DUMMY API EXAMPLE

lib/API-items.php
// AUTOMATIC RESOLVE
// API/ITEMS/GET WILL CALL $_CORE->ITEMS->GET()
// API/ITEMS/SAVE WILL CALL $_CORE->ITEMS->SAVE()
// API/ITEMS/DEL WILL CALL $_CORE->ITEMS->DEL()
$_CORE->autoAPI([
  "get" => ["Items", "get"],
  "save" => ["Items", "save"],
  "del" => ["Items", "del"]
]);
 
// OR MANUALLY RESOLVE IF YOU WANT...
switch ($_CORE->Route->act) {
  case "get":
    $_CORE->load("Items");
    $items = $_CORE->Items->get($_POST["search"]);
    $_CORE->respond(1, null, null, $items);
    break;
}

 

OVERRIDE EXAMPLES

Need to deal with pagination? Categories? Restrict access to registered users only? Here are a few common examples.

 

URL PATH OVERRIDE

lib/HOOK-Routes.php
$override = function ($path) {
  // EXAMPLE - REDIRECT TO LOGIN PAGE IF NOT SIGNED IN
  if (!isset($_SESSION["user"]) && $path!="login/") {
    header("Location: " . HOST_BASE . "login/");
    exit();
  }

  // EXAMPLE - TWEAK PATH BASED ON USER ROLE
  if ($path=="products/" && $_SESSION["user"]["user_level"]=="A") {
    $path = "admin/products/";
  }
 
  // MUST RETURN OVERIDDEN PATH
  return $path;
);

$_CORE->Route->run() will parse the current URL path into $_CORE->Route->path. Use this override to change the parsed path, very useful for things like access control or “load a different page for certain user roles”.

 

 

EXACT PATH OVERRIDE

lib/HOOK-Routes.php
// EXACT PATH ROUTING
$routes = [
  "/" => "myhome.php", // http://site.com/ > pages/myhome.php
  "foo/" => "bar.php"  // http://site.com/foo/ > pages/bar.php
];

Pretty self-explanatory, if you want to load a specific file for a particular URL.

 

WILDCARD PATH OVERRIDE

lib/HOOK-Routes.php
// WILDCARD PATH ROUTING
$wild = [
  "category/" => "category.php" // http://site.com/category/* > pages/category.php
];

Use this to cover a range of URL paths. Good for things like pagination and categories. See the example below.

 

CATEGORY & PAGINATION

WILDCARD MAP ALL PRODUCTS

lib/HOOK-Routes.php
$wild = [
  "products/" => "PDT-list.php"
];

For this example, we will be working with a dummy products page. This will map http://site.com/products/* to pages/PDT-list.php

 

 

PRODUCTS HANDLER SCRIPT

pages/PDT-list.php
// (A) EXPLODE CURRENT PATH INTO AN ARRAY FIRST
// $REQ[0] = "PRODUCTS"
// $REQ[1] = CATEGORY
// $REQ[2] = PAGE NUMBER
$req = explode("/", rtrim($_CORE->Route->path, "/"));

// (B) INVALID
if (count($req) != 3) {
  $_CORE->Route->load("PAGE-404.php", 404); exit();
}
 
// (C) GET PRODUCTS
$_CORE->load("Products");
$products = $_CORE->Products->get($req[1], $req[2]);
 
// (D) DRAW HTML
foreach ($products as $p) { ... }

Parse the current URL path, and use them to load the products/pagination accordingly.

 

CONTROL ACCESS TO ADMIN PAGES

MAP ALL ADMIN PAGES TO A “CHECK PAGE”

lib/HOOK-Routes.php
$wild = [
  "admin/" => "ADM-check.php"
];

Want to restrict some pages to administrators only? Start by doing a wildcard map to an “access check script”.

 

ADMIN PERMISSION CHECK

pages/ADM-check.php
// (A) ADMIN ONLY
$_CORE->ucheck("A");
 
// (B) STRIP "ADMIN/" FROM PATH
$_CORE->Route->path = substr($_CORE->Route->path, 6);
 
// (C) OK - LOAD PAGE
$_CORE->Route->load($_CORE->Route->path==""
  ? "ADM-home.php"
  : "ADM-" . str_replace("/", "-", rtrim($_CORE->Route->path, "/\\")) . ".php"
);

Do a check against the session or cookie – Whichever you are using to track user login. Then, use $_CORE->Route->load() to load the requested page.

 

 

API-CORS CONTROL

HOOK-API-CORS.php
// (A) EXAMPLE - ALLOW "FOO.COM" TO ACCESS "TEST" MODULE
if ($this->orihost=="foo.com" && $this->mod=="test") {
  $access = true;
}

// (B) EXAMPLE - ALLOW "BAR.COM" TO ACCESS SOME ACTIONS IN "TEST" MODULE
$allowed = ["get", "getAll"];
if ($this->orihost=="bar.com" && $this->mod=="test" && in_array($this->act, $allowed)) {
  $access = true;
}

If you want to give API access to a certain domain, but not open all modules – This is a good place to do your checks.

 

URL ROUTE LIBRARY REFERENCES

Don’t think this is necessary, but just for the “official documentation”.

 

PRETTY URL

function run ()

Reads the current URL and determines if it is an API call or request for an HTML page.

function init ()

Regenerates .htaccess and CB-manifest.json.

 

HTML PAGE RESOLVE

function resolve ()

Resolve URL path to HTML page.

function load ($file, $http)

A “helper function” for resolve(). You can also use this in your pages to load the given HTML page.

  • $file – String, file to load.
  • $http – Integer, optional HTTP response code.
$_CORE->Route->load("NO-ACCESS.PHP", 403);

 

API RESOLVE

function api ()

Reads the current URL path http://site.com/api/MODULE/ACTION and maps it to lib/API-MODULE.php.

Leave a Comment

Your email address will not be published. Required fields are marked *