Friday, February 24, 2017

How to create simple local web server for APEX static files

Today I've run into a problem that happens to me quite often. I've started a new project at the new client and one of the first things that I've had to do is to modify Universal Theme to meet their corporate design. They had simple APEX architecture with the EPG and without any custom CSS or JS in their apps.

At first, I thought that I would have to do some minor changes in CSS so I've started to use Custom CSS property in Theme Roller. It's great tool, but as I had to do more and more changes it was just too slow.

So I've asked them to provide me with some Web repository where I can easily put and change my files. Because this is a quite big company (actually a bank) with very strict security policies I knew that this would take a too looooong time. So I've started to look for an alternative.

Off course, my first thought was a great tool named APEX Front End Boost (if you don't know it, check it out), but again, because strict security policies, I wasn't been able to install it on the PC that I was working on. The good thing was that I had Node.js already installed there.

So I've googled around for other solutions, but almost every solution was starting like this:
npm install ...
and it was a bummer because I couldn't install anything from npm.

So I've decided to build my own solution. I thought, I'm not a Node.js developer but I know JavaScript so it shouldn't be too hard...and it wasn't.

I've found one simple server script and added some additional stuff like Access-Control-Allow-Origin and Content-Type headers:
var fs = require('fs');  
var path = require('path');  
var http = require('http');
var staticBasePath = '.';

var staticServe = function(req, res) {  
    var fileLoc = path.resolve(staticBasePath);
    fileLoc = path.join(fileLoc, req.url);

    fs.readFile(fileLoc, function(err, data) {
        if (err) {
            res.writeHead(404, 'Not Found');
            res.write('404: File Not Found!');
            return res.end();
        }
  
  var vExt = req.url.split('.').pop(), vContType;
  switch(vExt) {
   case 'css':
    vContType = 'text/css';
    break;
   case 'js':
    vContType = 'text/javascript';
    break;
   case 'png':
    vContType = 'image/png';
    break;    
   default:
    vContType = 'text/plain';
  } 

  res.setHeader('Content-Type', vContType);
  // Chrome Fix
  res.setHeader('Access-Control-Allow-Origin', '*');
        res.statusCode = 200;
        res.write(data);
        return res.end();
    });
};

var httpServer = http.createServer(staticServe);

httpServer.listen(8085); 
...started it:
node node_server.js
..and voila! I had my static file server running on localhost:8085 (change the port number if you already have something running on 8085) and I could access files through URL like this http://localhost:8085/custom_theme/custom.css (where custom_theme is directory where node_server.js is located).

The next goal was that other developers don't have any problems with the application runtime while I'm doing my CSS changes. So at first, I've created one application item F_THEME_PATH



and application computation (after authentication) to populate it in developement environment (with build option included for developement only)


and the other application computation to populate it on production and test environments which always returns path to workspace images (also defined by build option):

return '&WORKSPACE_IMAGES.custom_theme/';

The idea is - if I'm logged in take files from my local server and for other users take files from APEX workspace files. On test and production evnironments always take files from APEX workspace files.

Because there's a great feature to upload zip file with directory structure to APEX workspace files it was really easy to refresh new version of my files when I was sattisfied with my modifications.  

The last thing was to add reference to my files. You can do this in several places in APEX. I've decided to do it in user interface properties:





Enjoy!

Tested on APEX 5.1.0.00.45 and Node 5.2.0