1 var url
= require('url'),
3 node_static
= require('node-static'),
4 Negotiator
= require('negotiator'),
6 config
= require('./configuration.js'),
7 SettingsGenerator
= require('./settingsgenerator.js');
12 var HttpHandler = function (config
) {
13 var public_http
= config
.public_http
|| 'client/';
14 this.file_server
= new node_static
.Server(public_http
);
17 module
.exports
.HttpHandler
= HttpHandler
;
21 HttpHandler
.prototype.serve = function (request
, response
) {
22 // The incoming requests base path (ie. /kiwiclient)
23 var base_path
= global
.config
.http_base_path
|| '/kiwi',
26 // Trim of any trailing slashes
27 if (base_path
.substr(base_path
.length
- 1) === '/') {
28 base_path
= base_path
.substr(0, base_path
.length
- 1);
31 // Build the regex to match the base_path
32 base_path_regex
= base_path
.replace(/[-/\\^$*+?.()|[\]{}]/g
, '\\$&');
34 // Any asset request to head into the asset dir
35 request
.url
= request
.url
.replace(base_path
+ '/assets/', '/assets/');
37 // Any src request to head into the src dir
38 request
.url
= request
.url
.replace(base_path
+ '/src/', '/src/');
40 // Any requests for /client to load the index file
41 if (request
.url
.match(new RegExp('^' + base_path_regex
+ '([/$]|$)', 'i'))) {
42 request
.url
= '/index.html';
45 // If the 'magic' translation is requested, figure out the best language to use from
46 // the Accept-Language HTTP header. If nothing is suitible, fallback to our en-gb default translation
47 if (request
.url
.substr(0, 16) === '/assets/locales/') {
48 if (request
.url
=== '/assets/locales/magic.json') {
49 return serveMagicLocale
.call(this, request
, response
);
51 response
.setHeader('Content-Language', request
.url
.substr(16, request
.url
.indexOf('.') - 16));
53 } else if (request
.url
.substr(0, 21) === '/assets/settings.json') {
54 return serveSettings
.call(this, request
, response
);
57 this.file_server
.serve(request
, response
, function (err
) {
59 response
.writeHead(err
.status
, err
.headers
);
66 // Cached list of available translations
67 var cached_available_locales
= [];
69 // Get a list of the available translations we have
70 fs
.readdir('client/assets/locales', function (err
, files
) {
71 files
.forEach(function (file
) {
72 if (file
.substr(-5) === '.json') {
73 cached_available_locales
.push(file
.slice(0, -5));
81 * Handle the /assets/locales/magic.json request
82 * Find the closest translation we have for the language
85 var serveMagicLocale = function (request
, response
) {
86 var default_locale_id
= 'en-gb',
87 found_locale
, negotiator
;
89 if (!request
.headers
['accept-language']) {
90 // No accept-language specified in the request so send the default
91 found_locale
= default_locale_id
;
94 negotiator
= new Negotiator(request
);
95 found_locale
= negotiator
.language(cached_available_locales
);
98 // Send a locale to the browser
99 this.file_server
.serveFile('/assets/locales/' + found_locale
+ '.json', 200, {
100 Vary
: 'Accept-Language',
101 'Content-Language': found_locale
102 }, request
, response
);
108 * Handle the settings.json request
110 var serveSettings = function(request
, response
) {
115 // Check the referrer for a debug option
116 if (request
.headers
['referer']) {
117 referrer_url
= url
.parse(request
.headers
['referer'], true);
118 if (referrer_url
.query
&& referrer_url
.query
.debug
) {
123 SettingsGenerator
.get(debug
, function(settings
) {
124 if (request
.headers
['if-none-match'] && request
.headers
['if-none-match'] === settings
.hash
) {
125 response
.writeHead(304, 'Not Modified');
126 return response
.end();
129 response
.writeHead(200, {
130 'ETag': settings
.hash
,
131 'Content-Type': 'application/json'
133 response
.end(settings
.settings
);