@idio/core is a Koa2-based web server with some pre-installed middleware which facilitates quick creation of a web server with the essential functionality, such as serving static files, compression, body parsing, etc. It also provides full JSDoc documentation of all options for completion in IDEs. Other components such as @idio/database, @idio/route and @idio/jsx allow to build more complex websites (to come).
The @idio/core accepts 2 arguments which are the middleware configuration object and server configuration object. It is possible to start the server without any configuration, however it will do nothing, therefore it is important to add some middleware configuration.
MiddlewareConfig: Middleware configuration for the idiocore server.
The map of configured middleware functions which could then be set up to be used on a certain route.
-
To start the server, the async method needs to be called and passed the middleware and server configuration objects. For example, the following code will start a server which serves static files with enabled compression.
File available at: http://localhost:8080/static/test.txt
Middleware Configuration
The middleware can be configured according to the MiddlewareConfig. @idio/core comes with some installed middleware as dependencies to speed up the process of creating a web server. Moreover, any custom middleware which is not part of the bundle can also be specified here (see Custom Middleware).
Each middleware accepts the following properties:
Property
Description
Default
use
Whether to use this middleware for every request. If not set to true, the configured middleware function will be included in the middleware property of the returned object, which can then be passed to a router configuration (not part of the @idio/core).
false
config
Configuration object expected by the middleware constructor.
{}
...props
Any additional specific properties (see individual middleware configuration).
maxAge in ms with default of 1 day. session will result in a cookie that expires when session/browser is closed. Warning: If a session cookie is stolen, this cookie will never expire.
86400000
overwrite
boolean
Can overwrite or not.
true
httpOnly
boolean
httpOnly or not.
true
signed
boolean
Signed or not.
true
rolling
boolean
Force a session identifier cookie to be set on every response. The expiration is reset to the original maxAge, resetting the expiration countdown.
false
renew
boolean
Renew session when session is nearly expired, so we can always keep user logged in.
Param str is output string with ANSI Color, and you can get pure text with other modules like strip-ansi. Param args is a array by [format, method, url, status, time, length].
If true, serves after return next(), allowing any downstream middleware to respond first.
false
gzip
boolean
Try to serve the gzipped version of a file automatically when gzip is supported by a client and if the requested file with .gz extension exists.
true
br
boolean
Try to serve the brotli version of a file automatically when brotli is supported by a client and if the requested file with .br extension exists (note, that brotli is only accepted over https).
Try to match extensions from passed array to search for file when no extension is sufficed in URL. First found is served.
false
For example, the below configuration will serve files from both the static directory of the project, and the React.js dependency. When NODE_ENV environment variable is set to production, files will be cached for 10 days.
The pragma function to import. This enables to skip writing h at the beginning of each file. JSX will be transpiled to have h pragma, therefore to use React it's possible to do import { createElement: h } from 'react'.
import { h } from 'preact'
Custom Middleware
When required to add any other middleware in the application not included in the @idio/core bundle, it can be done in several ways.
Passing the middleware function as part of the MiddlewareConfig. It will be automatically installed to be used by the Application. All middleware will be installed in order it is found in the MiddlewareConfig.
Started API server at: http://localhost:5005
--> API: GET / 403
--> API: GET /?key=app-secret 200
Passing a configuration object as part of the MiddlewareConfig that includes the middlewareConstructor property which will receive the reference to the app. Other properties such as conf and use will be used in the same way as when setting up bundled middleware: setting use to true will result in the middleware being used for every request, and the config will be passed to the constructor.
importrqtfrom'rqt'importidioCorefrom'@idio/core'importAPIServerfrom'./api-server'constProxyServer=async(port)=>{// 1. Start the API server.constAPI=awaitAPIServer(5001)console.log('API server started at %s',API)// 2. Start a proxy server to the API.const{ url }=awaitidioCore({/** @type {import('koa').Middleware} */asynclog(ctx,next){awaitnext()console.log(' --> Proxy: %s %s %s',ctx.method,ctx.url,ctx.status)},api: {use: true,asyncmiddlewareConstructor(app,config){// e.g., read from a virtual networkapp.context.SECRET=awaitPromise.resolve('app-secret')/** @type {import('koa').Middleware} */constfn=async(ctx,next)=>{const{ path }=ctxconstres=awaitrqt(`${config.API}${path}?key=${ctx.SECRET}`)ctx.body=resawaitnext()}returnfn},config: {API,},},},{ port })returnurl}
API server started at http://localhost:5001
Proxy started at http://localhost:5002
--> API: GET /?key=app-secret 200
--> Proxy: GET / 200
Router Set-up
After the Application and Router instances are obtained after starting the server as the app and router properties of the returned object, the router can be configured to respond to custom paths. This can be done by assigning configured middleware from the map and standalone middleware, and calling the use method on the Application instance.
importidioCorefrom'@idio/core'asyncfunctionpre(ctx,next){console.log(' <-- %s %s',ctx.request.method,ctx.request.path,)awaitnext()}asyncfunctionpost(ctx,next){console.log(' --> %s %s %s',ctx.request.method,ctx.request.path,ctx.response.status,)awaitnext()}constServer=async()=>{constpath='/test'const{
url, router, app,middleware: { bodyparser },}=awaitidioCore({// 1. Configure the bodyparser without using it for each request.bodyparser: {config: {enableTypes: ['json'],},},},{port: 5003})// 2. Setup router with the bodyparser and path-specific middleware.router.post(path,pre,bodyparser,async(ctx,next)=>{ctx.body={ok: true,request: ctx.request.body,}awaitnext()},post,)app.use(router.routes())return`${url}${path}`}
Page available at: http://localhost:5003/test
<-- POST /test
--> POST /test 200