Monday, November 30, 2015

CSE 321 Project - Part 1 - Install Lubuntu on VirtualBox

This is one post in a series of posts related to CSE 321 - Software Engineering project for ASU CSE 2017 students. The series starts from setting up the environment, to planning the work on the website project, to implementation

In this tutorial, we will start a virtual machine and install Lubuntu or Ubuntu.

Install VirtualBox

The first thing is downloading and installing VirtualBox:
https://www.virtualbox.org/wiki/Downloads

And assuming that you are working on Linux, then you'll go for the first link. The download link is for both 32-bit and 64-bit computers.
(note: x86 means 32-bit, amd64 means 64-bit)

Create a New Lubuntu Machine

Let's create a new machine by clicking the New icon.

Enter a suitable name for your machine. Any name to remind you what this machine does.

Select the amount of memory this machine is allowed to use. If you have plenty of RAM, give it 2GB. No worries, this value can be changed later.

Leave the default option to create a new virtual hard disk.

Leave the VDI option as it is.

Leave the dynamic size as it is. This option allows the virtual hard disk (the file created) to start small then expand later to a max limit. The other option will create the full sized file from the beginning.

Choose a different name for the virtual hard disk or leave it with the same name as the virtual machine name. And you can leave the size at it is for now. Actually 8GB is more than enough.

Now the VM is ready.

Install Lubuntu

Before starting, let's mount the Lubuntu iso image as a CD to use it for installation.

Select the machine and click Settings.


Go to Storage, and select the empty CD.

Click on the small CD icon on the far right. And choose Choose Virtual Optical Disk file.
Then browse your folders and select the iso file you downloaded (Ubuntu iso , Lubuntu iso) then click Open.

Click OK. When done.

Now we are ready to start the machine. Select the machine and click Start or double-click it.

Choose English.


Choose Install Lubuntu.

Wait for a few seconds until it boots the installer.

Choose English.

Click Continue.

Now for the critical part of formatting if it was a real installation. Leave the first option as it is. After all, this is a virtual disk created for Lubuntu. Not your actual disk. Click Install Now. Then click Continue.

Choose the city of Cairo or any other city you prefer, and click Continue.

Leave the keyboard layout as it is and press Continue.

Enter your name and choose the username and password. Click Continue.

Now leave it for a few minutes to install and pull only some basic data from the Internet.

When finished, press Restart Now.

The machine will eject the virtual CD it used for installation and asks you to press Enter. Do it.

The fresh Lubuntu OS will boot.

The login dialog will appear. Enter your password.

Welcome to your new machine. Now you can shut it down and start it again whenever you want.

That's all folk! :)

In the next tutorial, we will work on installing:
  • Ruby
  • Rails
  • Node.js
  • PostgresSQL
  • Atom Editor
  • Git
  • Gitg (a graphical tool to use with Git)
  • Enable copy and paste between the VM and the computer, and enable flexible display resolution.
Take your time and try and fail without worries. Virtual machines are created and deleted all the time. If you mess it up, delete it and try again.

[update: Part 2 is available now]

Friday, October 16, 2015

Custom 404 Page in Slim Framework 3

In the past month, I've been learning Slim 3 PHP framework through a website as a real experiment of how powerful Slim Framework is. In this post, I'm sharing a code snippet for rendering 404 page.

Between creating a Slim Container and creating the Slim App, I override the default notFoundHandler.
$container = new Slim\Container;

...

// Override the default Slim Not Found Handler
$container['notFoundHandler'] = function ($c) {
    return function ($request, $response) use ($c) {
        return $c['view']->render($response, '404.html', [])->withStatus(404);
    };
};

...

// Initialize the app
$app = new Slim\App($container);

In my case, I use Twig template engine for views. If your case is different, change the render line.

File System Caching in Slim Framework 3

In the past month, I've been learning Slim 3 PHP framework through a website as a real experiment of how powerful Slim Framework is. In this post, I'm sharing a code snippet of how I implemented the Filesystem caching.

The summary is:
- Add a middleware for caching successful responses (200 OK) by saving the response in a file. To avoid long file names or deep paths, I hash the response URL.
- When receiving a request, check its hashed path in the cached files. If found, return the content. Else, continue with initializing the app, routes, and everything else. This way, there is no initialization overhead for cached requests.

Here is the beginning of my index.php:
require './lib/initializer.php';

function getCachePath($uri) {
    $webpage_handle = md5($uri);
    return ROOT."/public/cache/".$webpage_handle;
}

/* Check for cached file here before loading anything or opening DB */
if(CACHING_ENABLED) {
    $requestedURI = "http://$_SERVER[HTTP_HOST]$_SERVER[REQUEST_URI]";
    $cachedFilePath = getCachePath($requestedURI);
    if (file_exists($cachedFilePath) && (filemtime($cachedFilePath) > (time() - CACHE_SECONDS ))) {
        $cacheFile = file_get_contents($cachedFilePath);
        die($cacheFile);
    }
}

$cacheMiddleware = function ($request, $response, $next) {
    /* process the request */
    $response = $next($request, $response);

    /* cache response */
    if(CACHING_ENABLED && ($response->getStatusCode()==200) && ($request->getMethod() == 'GET')) {
        $cachedFilePath = getCachePath($request->getUri());
        $file = fopen($cachedFilePath,"w");
        fwrite($file, $response->getBody());
        fclose($file);
    }

    return $response;
};


First, I require a file where I initialize some configs and constants, like CACHE_SECONDS.

Then, I create a function for deciding the cache path for requests. To use it in both reads and writes.

Then, -if caching is enabled- I check for the existence of the requested file and the creation date. This way I override the file if it was older. (*check the end of the post for another better way for expiry)

Next, you can see the caching middleware I use with some routes I wish to cache. Here is an example:
$app->get('/', function ($request, $response, $args) {
    // some app-related code
})->setName('home')->add($cacheMiddleware);

And that's it. The file system is now implemented with minimal code. Of course there are many changes and upgrades depending on your case.

----------------------------------
Notes:
*Better than just checking for file creation date (and leaving the files to increase), you can remove the date-check part and add a cron job for removing files older than a specific duration. Here is how my cron job script looks like:
CACHE_DIR=$1;
cd $CACHE_DIR && find * -type f -cmin +5 -exec rm {} \;

It takes the path to clean in the cron job command. And removes any file older than 5 minutes.

The cron job looks like:
*/5 * * * * bash ~/path/to/cache/expiry/script.sh ~/path/to/cache/folder/