liefern
Version:
Node Webserver without dependencies
278 lines (236 loc) • 6.49 kB
Markdown
# liefern.io
Simple, fast and no-dependency web server for nodejs.
# Table of Contents
1. [Installation](#installation)
2. [Quick Start](#quick-start)
3. [Examples](#examples)
- [Hello World](#hello-world)
- [Static files](#static-files)
- [Testing with supertest](#testing-with-supertest)
4. [Features](#features)
4. [Requirements](#requirements)
4. [Documentation](#documentation)
- [Liefern](#liefern)
- [Constructor](#constructor)
- [.start](#start)
- [.stop](#stop)
- [.use](#use)
- [.cors](#cors)
- [.get](#get)
- [.head](#head)
- [.post](#post)
- [.put](#put)
- [.delete](#delete)
- [.patch](#patch)
- [.connect](#connect)
- [.trace](#trace)
- [.options](#options)
- [.all](#all)
- [Controller](#controller)
- [ControllerParams](#controllerparams)
- [UrlMatcherType](#urlmatchertype)
- [UrlParams](#urlparams)
- [SharedObject](#sharedobject)
- [Request](#request)
- [Response](#response)
## Installation
```console
$ npm install liefern
```
## Quick Start
```console
$ mkdir myapp
$ cd myapp
$ npm init
$ npm install liefern
```
## Examples
### Hello World
import { Liefern } from 'liefern'
const server = Liefern()
server.use(({ request, sharedData }) => {
sharedData.requestIp = request.socket.remoteAddress
})
server.get('/', ({ send: { text }, sharedData }) => {
text(`Hello World! (${sharedData.requestIp})`)
})
server.post('/', async ({ send: { text }, body }) => {
console.log(await body())
text('Hello World!')
})
server.start(1337)
### Static files
import { Liefern } from 'liefern'
const server = Liefern()
server.static('/', `/absolutPath/to/publicHtml`)
server.start(1337)
### Testing with supertest
import { Liefern } from 'liefern'
const server = Liefern({ name: 'TestServer' })
server.get('/', ({ send: { ok }}) => {
ok()
})
await supertest(server.httpServer)
.get('/')
.expect(200)
## Features
- [x] routing
- [x] regex url-pattern
- [x] url-pattern-matching customizable
- [x] all-helper for html-verb independed routes
- [x] logging
- [x] customizable
- [x] full async
- [x] exitable by signal
- [x] appendable with middlewares
- [x] shared data (middleware -> controller)
- [x] serving static files
- [x] even with middleware handling
- [x] typescript
- [x] ESM & CJS
- [x] CORS
- [x] helper for incomming request-body (json, text)
- [x] plain node testrunner
## Requirements
- node
- we using "node:" protocol imports (https://nodejs.org/api/esm.html#node-imports) so we need a node-version supporting this
- 14.13.1 (if you using "import")
- 16.0.0 (if you use "require")
## Documentation
### Liefern
#### Constructor
new Liefern({
name?: string
logger?: Logger
urlMatcher?: UrlMatcherType
})
#### .start
const server = new Liefern()
async server.start(8080)
#### .stop
const server = new Liefern()
async server.start(8080)
async server.stop()
#### .use
const server = new Liefern()
server.use(({ request, sharedData }) => {
sharedData.requestIp = request.socket.remoteAddress
})
#### .cors
server.cors({
origin?: string[] | '*',
allowMethods?: string[] | '*',
exposeHeaders?: string[],
allowHeaders?: string[] | '*',
maxAge?: number,
credentials?: boolean,
secureContext?: boolean,
privateNetworkAccess?: boolean
})
#### .get
server.get('/api/user/(\\d+)', ({ send: { json }, urlParams }) => {
const [userId] = urlParams
json({ testData: true, id: userId })
})
#### .head
server.head('/', ({ send: { ok }}) => {
ok()
})
#### .post
server.post('/', ({ send: { ok }}) => {
ok()
})
#### .put
server.put('/', ({ send: { ok }}) => {
ok()
})
#### .delete
server.delete('/', ({ send: { ok }}) => {
ok()
})
#### .patch
server.patch('/', ({ send: { ok }}) => {
ok()
})
#### .connect
server.connect('/', ({ send: { forbidden }}) => {
forbidden()
})
#### .trace
server.trace('/', ({ send: { notFound }}) => {
notFound()
})
#### .options
server.options('/', ({ send: { ok }}) => {
ok()
})
#### .all
server.all('/', ({ send: { ok }}) => {
ok()
})
### Controller
type Controller = (params: ControllerParams) => void | Promise<void>
#### ControllerParams
type ControllerParams = {
sharedData: SharedObject
request: Request
response: Response
urlParams: UrlParams
statusCode: (statusCode: number) => void
body: undefined | string | JsonType
contentType: {
textHtml: () => void
textPlain: () => void
applicationJson: () => void
}
setHeader: (name: string, value: string | number | readonly string[]) => void
statusCodes: {
ok: () => void
created: () => void
noContent: () => void
movedPermanently: () => void
notModified: () => void
badRequest: () => void
unauthorized: () => void
paymentRequired: () => void
forbidden: () => void
notFound: () => void
internalServerError: () => void
notImplemented: () => void
}
send: {
json: (data: JsonType) => void
text: (data: string) => void
html: (data: string) => void
ok: () => void
created: () => void
noContent: () => void
movedPermanently: (url: string) => void
notModified: () => void
badRequest: () => void
unauthorized: () => void
paymentRequired: () => void
forbidden: () => void
notFound: () => void
methodNotAllow: () => void
internalServerError: () => void
notImplemented: () => void
}
}
### UrlMatcherType
type UrlMatcherType = (
url: string,
pattern: string | RegExp,
) => false | UrlParams | Promise<false | UrlParams>
### UrlParams
type UrlParams = string[]
### SharedObject
type SharedObject = Record<string, unknown> & {
body: undefined | string | JsonType
}
### Request
type Request = http.IncomingMessage
### Response
type Response = http.ServerResponse<http.IncomingMessage> & {
req: http.IncomingMessage
}