cwserver
The aim of the project is to create an easy to use, lightweight, Complete Web Server Framework
with default NodeJs HTTP Server
.
- The framework also provides default
-
Secure User Session
, -
Cookie Parser
, -
Flexible Router
, -
Multiple Views
, -
Virtual Directory
, -
Hidden Directory
, -
Template Engine
, -
Nested Master Template Engine
, -
Post Data Handler (with multipart form data and large file)
, -
Mimetype Handler
, -
WebStream Handler
, -
JS/CSS Bundler
, -
socket.io Interface
, Easy way to bind with IIS/NGINX
-
Install cwserver
by this command npm i cwserver
How to use cwserver
core IApplication
?
const { App } = require('cwserver');
const app = App();
const port = 8080;
app.on("request-begain", (req) => {
console.log(`${req.method} ${req.path}`);
});
app.on("response-end", (req, res) => {
console.log(`Send ${res.statusCode} ${req.path}`);
});
app.use((req, res, next) => {
res.status(200).send("Hello World...");
});
app.listen(port, () => {
console.log(`Listing port => ${port}`);
});
Or you may use full application by following:
Create createProjectTemplate.js
as following
const { createProjectTemplate } = require( 'cwserver' );
createProjectTemplate( {
appRoot: __dirname,
projectRoot: "www" /** Your project root folder name*/,
allExample: false
} );
Then run this commmand node createProjectTemplate
It will create default project template for cwserver
in your application root.
Now your appRoot look like this
appRoot
├─┬ wwww ( projectRoot )
│ └─┬ config
│ ├ lib
│ ├ template (this contains master template file)
│ ├ web (this contains temp and cache files)
│ └ index.html
├─ node_modules
├─ server.js
├─ package.json
└─ README.md
After, run this command node server www /**your project root*/
How to setup middleware
First process app.prerequisites
every request and then run app.use
global.cw.server.on( "register-view", ( app, controller, server ) => {
app.prerequisites( ( req, res, next ): void => {
res.setHeader( 'x-frame-options', 'sameorigin' );
return next();
} );
app.use( ( req, res, next ): void => {
res.setHeader( 'x-frame-options', 'sameorigin' );
return next();
} );
} );
How to setup router ?
global.cw.server.on( "register-view", ( app, controller, server ) => {
controller
.any( '/test-any/*', ( ctx, match ) => {
return ctx.res.json( { reqPath: ctx.path, servedFrom: "/test-any/*", q: match } );
} )
.get( '/task/:id/*', ( ctx, match ) => {
return ctx.res.json( { reqPath: ctx.path, servedFrom: "/task/:id/*", q: match } );
} )
.get( '/dist/*', ( ctx, match ) => {
return ctx.res.json( { reqPath: ctx.path, servedFrom: "/dist/*", q: match } );
} )
.get( '/user/:id/settings', ( ctx, match ) => {
return ctx.res.json( { reqPath: ctx.path, servedFrom: "/user/:id/settings", q: match } );
} );
} );
How to add Virtual Directory ?
global.cw.server.on( "register-view", ( app, controller, server ) => {
const vDir = path.join( path.resolve( server.getRoot(), '..' ), "/project_template/test/" );
server.addVirtualDir( "/vtest", vDir, ( ctx ) => {
return mimeHandler.render( ctx, vDir, true );
} );
server.addVirtualDir( "/test-virtual", vDir );
server.addVirtualDir( "/vtest/virtual/", vDir );
} );
Authetication
Session cookie name use from app.config.json => session.cookie
and session encryption use app.config.json => session.key
global.cw.server.on( "register-view", ( app, controller, server ) => {
controller.get( '/authenticate/:loginId/:roleid', ( ctx, requestParam ) => {
if ( ctx.req.session.isAuthenticated ) {
ctx.res.status( 200 ).type( "html" ).send( `Hello ${ctx.req.session.loginId}` );
} else {
ctx.setSession(/*loginId*/requestParam.query.loginId,/*roleId*/requestParam.query.roleId, /*userData*/{ token: ctx.req.query.token } );
ctx.res.status( 200 ).type( "html" ).send( `Authentication success ${ctx.req.query.loginId}` );
}
return ctx.next( 200 );
} );
} );
SignOut From Application
global.cw.server.on( "register-view", ( app, controller, server ) => {
controller.get( '/signout', ( ctx, requestParam ) => {
if ( ctx.session.isAuthenticated ) {
ctx.signOut();
}
ctx.redirect( "/" ).next( 302, true );
} );
} );
Handle post data
const { getBodyParser, fsw } = require( 'cwserver' );
global.cw.server.on( "register-view", ( app, controller, server ) => {
const downloadDir = server.mapPath( "/upload/data/" );
if ( !fs.existsSync( downloadDir ) ) {
fsw.mkdirSync( server.mapPath( "/" ), "/upload/data/" );
}
const tempDir = server.mapPath( "/upload/temp/" );
controller.post( '/post-async', async ( ctx ) => {
const parser = getBodyParser( ctx.req, tempDir );
await parser.parseSync();
if ( parser.isUrlEncoded() || parser.isAppJson() ) {
ctx.res.status( 200, { 'Content-Type': 'application/json' } );
ctx.res.end( JSON.stringify( parser.getJson() ) );
parser.dispose();
return ctx.next( 200 );
}
parser.saveAsSync( downloadDir ); parser.dispose();
return ctx.res.status( 200 ).send( "<h1>success</h1>" );
// or
// return ctx.res.asHTML( 200 ).end( "<h1>success</h1>" );
// or
/*const data = [];
parser.getFilesSync( ( file ) => {
data.push( {
content_type: file.getContentType(),
name: file.getName(),
file_name: file.getFileName(),
content_disposition: file.getContentDisposition(),
temp_path: file.getTempPath()
} );
file.saveAsSync( `${downloadDir}/${Util.guid()}_${file.getFileName()}` );
} );
return ctx.res.status( 200 ).json( data );*/
} )
} );
Template Engine
Template can run config.defaultExt
file extension or ctx.res.render( ctx, to_file_path )
Example of server-side script in config.defaultExt
or app.config.json => template.ext
ctx.res.render( ctx, server.mapPath( `/index${server.config.defaultExt || ".html"}` ) );
Code block:
{%
if( !ctx.session.isAuthenticated ){
return ctx.next( 401, true );
} else {
ctx.write( JSON.stringify( ctx.session ) );
}
%}
<ul>
{% users.forEach(function(user){ %}
{= user =}
{% }); %}
</ul>
<ul>
<!--{%--> users.forEach(function(user){ <!--%}-->
{= user =}
<!--{%--> }); <!--%}-->
</ul>
<script>
var userLength = 0;
/*{%*/ if ( users.length > 0 ) {/*%}*/
userLength = {= users.length =};
/*{%*/ } /*%}*/
</script>
<script>
var userLength = 0;
{% if ( users.length > 0 ) { %}
userLength = {= users.length =};
{% } %}
</script>
Response write: {= myVar =}
or ctx.write(myVar)
{%
const result = await ctx.server.db.pgsql.executeIoAsync( "my_shcema.__get_dataset", JSON.stringify( {
login_id: ctx.req.session.loginId
} ), JSON.stringify( {
trade_date: "2020-02-03"
} ) );
%}
{% if ( result.ret_val < 0) { %}
<span style="color:red">No Data Found...</span>
{% } else { %}
<table style="width:100%">
<thead>
<tr>
<th>Firstname</th>
<th>Lastname</th>
<th>Age</th>
</tr>
</thead>
<tbody>
{% for( const row of result.ret_data_table ){ %}
<tr>
<td>{= row.first_name =}</td>
<td>{= row.last_name =}</td>
<td>{= row.age_name =}</td>
</tr>
{% } %}
</tbody>
</table>
{% } %}
Nested Master Template
#extends
keyword define my master template
You can add multiple file by #attach
keyword
www
├─┬ template
│ └─┬ master.html
│ ├ footer.html
│ ├ header.html
│ └ readme.html
├─ index.html
index.html ==> #extends /template/readme.html
==> index.html impliment placeholder id of readme.html (parent master)
-------------------------------------------
#extends /template/readme.html
<impl-placeholder id="container">
container here
</impl-placeholder>
-------------------------------------------
readme.html ==> #extends /template/master.html (parent master)
==> readme.html like as master template and its contains own placeholder and impliment placeholder id of master.html
-------------------------------------------
#extends /template/master.html
<impl-placeholder id="body">
<!--Here create new placeholder-->
<placeholder id="container">
</placeholder>
</impl-placeholder>
<impl-placeholder id="header">
#attach /template/header.html
</impl-placeholder>
-------------------------------------------
master.html ==> root master template
--------------------------------------------
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<placeholder id="header">
</placeholder>
<body>
<placeholder id="body">
</placeholder>
#attach /template/footer.html
</body>
</html>
--------------------------------------------
see more about template /dist/project_template/www
server.js
You may create server.js file by you:
const { ConsoleColor, initilizeServer } = require( 'cwserver' );
let wwwName = void 0;
if ( process.argv.length > 2 ) {
wwwName = process.argv[2];
} else {
if ( process.env.APP_POOL_ID ) {
wwwName = process.env[process.env.APP_POOL_ID];
}
}
const server = initilizeServer( __dirname, wwwName );
const app = server.init();
process.on( 'exit', () => {
console.log( "Exited..." );
} );
process.on( 'SIGINT', () => {
server.log.error( "Caught interrupt signal" );
server.log.error( "Application Exited..." );
server.log.reset(); server.log.dispose();
setTimeout( () => {
process.exit( 0 );
}, 200 );
} );
app.listen( server.port, () => server.log.write( `
[+] Maintance : https://www.fsys.tech
[+] Server : http://localhost:${server.port}
[+] Socket : ws://localhost:${server.port}${server.socketPath}
[~] Running Server...
`, ConsoleColor.FgMagenta ) );
Read more about app.config.json
run node server your_app_dir_name
or npm start your_app_dir_name