ReXUWS
ReXUWS - Replace Express by uWS - A simple express-like framework built on top of uWebsockets.js
Usage
npm i rexuws
Create the server
import rex from 'rexuws';
import { IRequest, IResponse } from './lib/utils/types';
const app = rex();
app.get('/hi', (req: IRequest, res: IResponse) => {
res.send('hi');
});
app.listen(3000);
Configuration rex(options: TReXAppOptions)
-
forceAsync
: Attach abort handler to all routes. Should beTRUE
when compiling to ES5 (which lacks of Promise/Async/Await), default:FALSE
-
name
: Set up application's name in ReX container, default: 0, 1, 2, ... -
logging
: Control how the message gets printed over console's method such as log, error, info, warn, trace. -
useDefaultParser
: Apply some bultin parsers (bodyParser, multipartParser) on POST/PATCH/PUT routes and cookieParser on all endpoints. When configured over application's instanciation, these middlewares will be executed before all user's defined middlewares. IfTRUE
(default) enable bodyParser (to parse application/json, application/x-www-form-urlencoded, text/*) and cookieParser. To enable multipartParser on all POST/PUT/PATCH routes, you have to specify in useDefaultParser setting. ex:
const app = rex({
useDefaultParser: {
bodyParser: true,
cookieParser: true,
multipartParser: true,
},
});
uWSConfigurations
: uWebsockets Templated App options (see: https://github.com/uNetworking/uWebSockets.js/). Can be used to create a SSL App, ex:
const app = rex({
uWSConfigurations: {
key_file_name: 'misc/key.pem',
cert_file_name: 'misc/cert.pem',
passphrase: '1234',
},
});
preferJSON
: ifTRUE
return application/json in default errorMiddleware and notFoundMiddleware else return text/html. DefaultFALSE
Supported HTTP methods
GET
POST
PATCH
PUT
DELETE
HEAD
TRACE
OPTIONS
CONNECT
ANY
ALL
(alias ofANY
)
Examples
Basic routing
import rex from 'rexuws';
const app = rex({
useDefaultParser: true,
});
app.get('/', (req, res) => {
res.end('ok');
});
app.post('/', (req, res) => {
res.end('post ok');
});
app.get('/user/:id', (req, res) => {
res.end(`Your id is ${req.params.id}`);
});
// chaining
app
.get('/async', async (req, res) => {
res.json({
message: 'ok',
});
})
.post('/signIn', (req, res) => {
res.json(req.body);
})
.listen('0.0.0.0', 3001);
Router
import rex, { Router } from '../../index';
const router = Router()
.get('/helloworld', (req, res) => {
res.end('ok');
})
.get(
'/users/:id',
(req, res, next) => {
next();
},
(req, res) => {
res.end('ok');
}
);
app.use('/api', router);
Prefix Router
import rex, { Router } from '../../index';
const app = rex();
const prefixRouter = Router()
.route('/user')
.get((req, res) => {
res.end('ok');
})
.post(
(req, res, next) => {
next();
},
(req, res) => {
res.end('ok');
}
);
app.use('/api', preFixRouter);
Global middlewares
app.use((req, res, next) => {
next();
});
Global Error middlewares
app.use((err, req, res, next) => {
next();
});
Route middlewares
app.get(
'/user',
(req, res, next) => {
next();
},
(req, res) => {
res.end();
}
);
// Send to ErrorMiddleware
app.get('/error', (req, res, next) => {
next('Something went wrong');
});
Native Routing
This library only aims at providing a wrapper around Http Routes. If you want to use uWebsockets WebSocket feature, or would like to access raw uWebSockets.js usage, you can use app.useNativeHandlers((uws: TemplatedApp) => void)
There is a implementation of ReXUWS with NestJS which has a compatible Websocket Adapter, scroll down to the bottom of the page for detail.
app.useNativeHandlers((uws: TemplatedApp) => {
uws
.ws('/somepath', {
// ws handlers
})
.get('/hello', (res: uws.HttpResponse, req: uws.HttpRequest) => {
res.end();
});
});
Start the server
app.listen(port: number);
app.listen(port: number, callback: () => void)
app.listen(host: string, port: number)
app.listen(host: string, port: number, callback: () => void)
// example
app.listen('localhost', 3030, () => {
console.log('Listening on 3030');
})
Stop the server
app.close();
app.close(cb: () => void);
// example
app.close(() => {
console.log('Bye!');
})
Request Object
Interface:
import { IRequest } from 'rexuws/build/lib/utils/types';
Methods:
accepts()
acceptsCharsets()
acceptsEncodings()
acceptLanguages()
get()
: get spefic header value, ex:
app.get('/users', (req, res) => {
res.send(req.get('content-type'));
});
header()
: alias ofget()
is()
Properties:
body
: request body, if there is no posted body,req.body
isundefined
. Without any related parser,req.body
is aBuffer
cookies
: Without any related parsers, cookies is astring
headers
: an object of all request's headershostname
: parse the "Host" header field hostname.ip
: return the remote addressips
: parse the "X-Forwarded-For" ip address list.method
: request method (useful when usingapp.any()
,app.all()
)params
: parse the request params, ex:
// GET /users/alice/friends/bob
app.get('/users/:username/friends/:friendName', (req, res) => {
console.log(req.params.username); // alice
console.log(req.params.friendName); // bob
res.end();
});
query
: parse the request query
// GET /feeds?limit=5&skip=10
app.get('/users/:username/friends/:friendName', (req, res) => {
console.log(req.query); // { limit: '5', skip: '10' }
res.end();
});
raw
: posted body asBuffer
originalReq
: Original uWebsockets HttpRequest Object
Response Object
Interface:
import { IResponse } from 'rexuws/build/lib/utils/types';
Methods:
contentType()
: set response content typecookie()
: set reponse cookie (same as Express)end()
: send string data.get()
: get value for header's fieldgetHeader()
: alias ofget()
header()
: set reponse's headers (same as Express)json()
: send JSON.location()
: set location headerredirect()
: set location header and status code 302render()
render view (same as Express)send()
: send body and recognize its content-typeset()
: alias ofheader()
status()
: set status codetype()
: alias ofcontentType()
render()
: render view, (see: examples)
// render view
import ejs from 'ejs';
// config view engine
app.setView('path/to/view/directory', {
compileMethod: ejs.compile,
extName: 'ejs',
});
app.get('/home', (req, res) => {
res.render('Home', {
user: {
username: 'Adam',
email: 'adam@mail.com',
},
today: new Date(),
});
});
app.post('/users', (req: IRequest, res: IResponse) => {
res
.status(200)
.type('application/json')
.cookie('sid', '12345', {
path: '/',
httpOnly: true,
})
.set('X-Custom', '12345')
.send('ok');
});
Warning: Unstable methods:
download()
: Transfer the file at the givenpath
as an attachment.
app.get('/download', (req: IRequest, res: IResponse) => {
res.download('/path/to/file');
});
sendFile()
: send file at the given path
app.get('/send-file', (req, res) => {
res.sendFile('/path/to/file', options?:IResponseSendFileOption, callback?: (err: any) => void );
});
Bultin-middlewares
Usage
import { middlewares } from 'rexuws';
Middleware | Descripton | Default |
---|---|---|
bodyParser | Parse application/json, text/*, application/x-www-form-urlencoded | enabled |
errorMiddleware | Simple handler for next(err) |
enabled |
notFoundMiddleware | Return text/html; application/json 404 for unregistered path | enabled (*) |
httpLogger | Simple HTTP logger | disabled |
StaticServer | Serve static contents | disabled |
(*) notFoundMiddleware is enabled by default if ANY /*
hasn't been registered
Serve static files
import path from 'path';
import rex, { getLoggerInstance, middlewares } from 'rexuws';
async function bootstrap() {
const app = rex({
logging: {
level: true,
},
});
middlewares.StaticServer.Config({ watcher: true }, getLoggerInstance());
/**
* Init a StaticStore for selected directory
*/
await new middlewares.StaticServer(path.join(__dirname, './public')).init();
const router = middlewares.StaticServer.GetRouter();
app.use('/docs', router);
app.listen(3000);
}
bootstrap();
NestJS Integration (experimental)
Usage
Create a new NestJS Project (see: NestJS) then install these packages
npm i rexuws @rexuws/nestjs @nestjs/websockets
TODO
- Update docs
- Full tests