Permalink
Browse files

feat(app): Implement server side static file delivery with express.st…

…atic
  • Loading branch information...
zakhenry committed Aug 2, 2016
1 parent cae672a commit 98e880aba1242196aee9333b1a469dc4a2acbb57
View
@@ -77,4 +77,4 @@
"directories": {
"doc": "docs"
}
}
}
@@ -29,10 +29,14 @@ export class ServerMock extends Server {
return this;
}
public start(): Promise<this> {
public startEngine(): Promise<this> {
return Promise.resolve(this);
}
public registerStaticLoader(webroot?: string): this {
return this;
}
}
describe('Server', () => {
@@ -76,10 +76,26 @@ export abstract class Server {
*/
protected abstract initialize(): this;
/**
* Kicks off the server using the specific underlying engine
*/
public abstract startEngine(): Promise<this>;
/**
* Register loader with engine to handle static loading of frontend assets
* @param webroot
*/
public abstract registerStaticLoader(webroot:string):this;
/**
* Kicks off the server
*/
public abstract start(): Promise<this>;
public start(): Promise<this> {
this.registerStaticLoader(process.env.WEB_ROOT);
return this.startEngine();
};
/**
* Retrieves the underlying engine for custom calls
@@ -13,7 +13,7 @@ import { AuthService } from '../services/auth.service';
describe('Express Server', () => {
const expressConstructorSpy = jasmine.createSpy('expressConstructor');
const expressSpy = jasmine.createSpyObj('express', ['get']);
const expressSpy = jasmine.createSpyObj('express', ['get', 'use']);
expressConstructorSpy.and.returnValue(expressSpy);
@@ -47,6 +47,10 @@ describe('Express Server', () => {
addProviders(providers);
});
afterEach(() => {
delete process.env.WEB_ROOT;
});
it('initialized http server with new express instance', inject([Server], (server: Server) => {
expect(expressConstructorSpy)
@@ -175,6 +179,29 @@ describe('Express Server', () => {
})));
it('registers static file loader when started', async(inject([Server], (server: Server) => {
process.env.WEB_ROOT = '/tmp/example';
expressConstructorSpy['static'] = jasmine.createSpy('express_static');
const startPromise = server.start()
.then((res) => {
expect(res)
.toEqual(server);
expect(expressConstructorSpy['static'])
.toHaveBeenCalledWith('/tmp/example', {index: ['index.html']});
});
const startedCallback = httpServerSpy.listen.calls.mostRecent().args[2];
startedCallback(); //resolve the promise
return startPromise;
})));
});
@@ -12,10 +12,20 @@ import * as express from 'express';
import { Application, Request as ExpressRequest, Response as ExpressResponse } from 'express';
import * as http from 'http';
// import {
// expressEngine,
// BASE_URL,
// REQUEST_URL,
// ORIGIN_URL,
// NODE_LOCATION_PROVIDERS,
// NODE_HTTP_PROVIDERS,
// ExpressEngineConfig
// } from 'angular2-universal';
@Injectable()
export class ExpressServer extends Server {
protected engine: Application;
protected app: Application;
constructor(logger: Logger, remoteCli: RemoteCli) {
super(logger, remoteCli);
@@ -26,16 +36,16 @@ export class ExpressServer extends Server {
* @returns {Application}
*/
public getEngine(): Application {
return this.engine;
return this.app;
}
/**
* @inheritdoc
* @returns {Express}
*/
protected initialize() {
this.engine = express();
this.httpServer = http.createServer(<any>(this.engine));
this.app = express();
this.httpServer = http.createServer(<any>(this.app));
return this;
}
@@ -47,7 +57,7 @@ export class ExpressServer extends Server {
*/
protected registerRouteWithEngine(routeConfig: RouteConfig): this {
this.engine[routeConfig.method.toLowerCase()](routeConfig.path, (req: ExpressRequest, res: ExpressResponse) => {
this.app[routeConfig.method.toLowerCase()](routeConfig.path, (req: ExpressRequest, res: ExpressResponse) => {
let request = new Request(req,
Request.extractMapFromDictionary<string, string>(req.params),
@@ -59,18 +69,69 @@ export class ExpressServer extends Server {
.then((response: Response) => {
return this.send(response, res);
})
.catch((err:Error) => this.sendErr(err, res));
.catch((err: Error) => this.sendErr(err, res));
});
return this;
}
/**
* @inheritDoc
*/
public registerStaticLoader(webroot?: string): this {
if (webroot) {
this.app.use(express.static(webroot, {index: ['index.html']}));
}
//@todo resolve how to load webpacked modules with angular/universal
// const ngApp = (req:ExpressRequest, res:ExpressResponse) => {
// let baseUrl = '/';
// let url = req.originalUrl || '/';
//
// let config: ExpressEngineConfig = {
// directives: frontendComponents,//[ App ],
//
// // dependencies shared among all requests to server
// platformProviders: [
// {provide: ORIGIN_URL, useValue: this.getHost()},
// {provide: BASE_URL, useValue: baseUrl},
// ],
//
// // dependencies re-created for each request
// providers: [
// {provide: REQUEST_URL, useValue: url},
// // provideRouter(routes),
// NODE_LOCATION_PROVIDERS,
// NODE_HTTP_PROVIDERS,
// ],
//
// // if true, server will wait for all async to resolve before returning response
// async: true,
//
// // if you want preboot, you need to set selector for the app root
// // you can also include various preboot options here (explained in separate document)
// preboot: false // { appRoot: 'app' }
// };
//
// res.render('index', config);
// };
//
// this.app.engine('.html', expressEngine);
// this.app.set('views', process.env.WEB_ROOT);
// this.app.set('view engine', 'html');
// this.app.use(express.static(process.env.WEB_ROOT, {index: false}));
// this.app.get('/', ngApp);
return this;
}
/**
* @inheritdoc
* @returns {Promise<ExpressServer>}
*/
public start(): Promise<this> {
public startEngine(): Promise<this> {
return new Promise((resolve, reject) => {
this.httpServer.listen(this.port, this.host, resolve);
})
@@ -38,6 +38,10 @@ describe('Hapi Server', () => {
addProviders(providers);
});
afterEach(() => {
delete process.env.WEB_ROOT;
});
it('initialized http server with new hapi instance', inject([Server], (server: Server) => {
expect(hapiConstructorSpy)
@@ -50,6 +54,15 @@ describe('Hapi Server', () => {
}));
it('throws error when webroot is defined as static file listing is not yet implemented', inject([Server], (server: Server) => {
process.env.WEB_ROOT = '/tmp/example';
const fixture = () => server.start();
expect(fixture).toThrowError('Static file listing is not implemented for hapi');
}));
it('kicks off an http server when started', async(inject([Server], (server: Server) => {
const startPromise = server.start()
@@ -9,6 +9,7 @@ import { RemoteCli } from '../services/remoteCli.service';
import { Logger } from '../../common/services/logger.service';
import { Response } from '../controllers/response';
import { Request } from '../controllers/request';
import { NotImplementedException } from '../../common/exeptions/exceptions';
@Injectable()
export class HapiServer extends Server {
@@ -110,11 +111,21 @@ export class HapiServer extends Server {
return res;
}
/**
* @inheritdoc
*/
public registerStaticLoader(webroot?: string): this {
if (webroot) {
throw new NotImplementedException('Static file listing is not implemented for hapi');
}
return this;
}
/**
* @inheritdoc
* @returns {Promise<HapiServer>}
*/
public start(): Promise<this> {
public startEngine(): Promise<this> {
return new Promise((resolve, reject) => {
this.engine.start((err) => {

0 comments on commit 98e880a

Please sign in to comment.