Skip to content
This repository has been archived by the owner on May 8, 2020. It is now read-only.

Commit

Permalink
feat(app): Implement server side static file delivery with express.st…
Browse files Browse the repository at this point in the history
…atic
  • Loading branch information
zakhenry committed Aug 2, 2016
1 parent cae672a commit 98e880a
Show file tree
Hide file tree
Showing 7 changed files with 144 additions and 12 deletions.
2 changes: 1 addition & 1 deletion package.json
Expand Up @@ -77,4 +77,4 @@
"directories": {
"doc": "docs"
}
}
}
6 changes: 5 additions & 1 deletion src/server/servers/abstract.server.spec.ts
Expand Up @@ -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', () => {
Expand Down
18 changes: 17 additions & 1 deletion src/server/servers/abstract.server.ts
Expand Up @@ -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
Expand Down
29 changes: 28 additions & 1 deletion src/server/servers/express.server.spec.ts
Expand Up @@ -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);

Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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;

})));

});


75 changes: 68 additions & 7 deletions src/server/servers/express.server.ts
Expand Up @@ -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);
Expand All @@ -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;
}
Expand All @@ -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),
Expand All @@ -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);
})
Expand Down
13 changes: 13 additions & 0 deletions src/server/servers/hapi.server.spec.ts
Expand Up @@ -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)
Expand All @@ -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()
Expand Down
13 changes: 12 additions & 1 deletion src/server/servers/hapi.server.ts
Expand Up @@ -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 {
Expand Down Expand Up @@ -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) => {
Expand Down

0 comments on commit 98e880a

Please sign in to comment.