0http-bun 0.0.1 → 0.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/0http-benchmarks.png +0 -0
- package/README.md +60 -7
- package/demos/basic.js +1 -4
- package/demos/minimal.js +10 -0
- package/lib/next.js +3 -18
- package/lib/router/sequential.js +8 -47
- package/package.json +4 -5
|
Binary file
|
package/README.md
CHANGED
|
@@ -1,11 +1,16 @@
|
|
|
1
1
|
# Introduction
|
|
2
|
-
Experimental, bun-based HTTP framework inspired by 0http
|
|
2
|
+
Experimental, bun-based HTTP framework inspired by [0http](https://0http.21no.de/#/)
|
|
3
|
+
|
|
4
|
+

|
|
5
|
+
> MacBook Pro (13-inch, 2020)
|
|
3
6
|
|
|
4
7
|
## Usage
|
|
5
8
|
```js
|
|
6
9
|
const http = require('0http-bun')
|
|
7
10
|
|
|
8
|
-
const { router } = http({
|
|
11
|
+
const { router } = http({
|
|
12
|
+
port: 3000
|
|
13
|
+
})
|
|
9
14
|
router.use((req, next) => {
|
|
10
15
|
req.ctx = {
|
|
11
16
|
engine: 'bun'
|
|
@@ -25,12 +30,60 @@ router.delete('/:id', async (req) => {
|
|
|
25
30
|
})
|
|
26
31
|
})
|
|
27
32
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
33
|
+
export default router
|
|
34
|
+
```
|
|
35
|
+
# Benchmarks
|
|
36
|
+
## 0http-bun (bun v0.2.2)
|
|
37
|
+
```
|
|
38
|
+
% wrk -t4 -c50 -d10s --latency http://127.0.0.1:3000/hi
|
|
39
|
+
Running 10s test @ http://127.0.0.1:3000/hi
|
|
40
|
+
4 threads and 50 connections
|
|
41
|
+
Thread Stats Avg Stdev Max +/- Stdev
|
|
42
|
+
Latency 463.26us 99.23us 4.28ms 96.62%
|
|
43
|
+
Req/Sec 25.98k 1.10k 27.48k 76.73%
|
|
44
|
+
Latency Distribution
|
|
45
|
+
50% 442.00us
|
|
46
|
+
75% 466.00us
|
|
47
|
+
90% 485.00us
|
|
48
|
+
99% 0.91ms
|
|
49
|
+
1044377 requests in 10.10s, 127.49MB read
|
|
50
|
+
Requests/sec: 103397.66
|
|
51
|
+
Transfer/sec: 12.62MB
|
|
52
|
+
```
|
|
53
|
+
## 0http (node v18.2.0)
|
|
54
|
+
```
|
|
55
|
+
% wrk -t4 -c50 -d10s --latency http://127.0.0.1:3000/hi
|
|
56
|
+
Running 10s test @ http://127.0.0.1:3000/hi
|
|
57
|
+
4 threads and 50 connections
|
|
58
|
+
Thread Stats Avg Stdev Max +/- Stdev
|
|
59
|
+
Latency 0.98ms 251.77us 13.04ms 95.09%
|
|
60
|
+
Req/Sec 12.31k 771.37 16.96k 95.29%
|
|
61
|
+
Latency Distribution
|
|
62
|
+
50% 0.95ms
|
|
63
|
+
75% 0.96ms
|
|
64
|
+
90% 0.98ms
|
|
65
|
+
99% 1.88ms
|
|
66
|
+
493899 requests in 10.10s, 63.59MB read
|
|
67
|
+
Requests/sec: 48893.32
|
|
68
|
+
Transfer/sec: 6.29MB
|
|
69
|
+
```
|
|
70
|
+
## express (node v18.2.0)
|
|
71
|
+
```
|
|
72
|
+
% wrk -t4 -c50 -d10s --latency http://127.0.0.1:3000/hi
|
|
73
|
+
Running 10s test @ http://127.0.0.1:3000/hi
|
|
74
|
+
4 threads and 50 connections
|
|
75
|
+
Thread Stats Avg Stdev Max +/- Stdev
|
|
76
|
+
Latency 4.99ms 0.90ms 20.31ms 89.52%
|
|
77
|
+
Req/Sec 2.42k 154.52 2.66k 82.25%
|
|
78
|
+
Latency Distribution
|
|
79
|
+
50% 4.67ms
|
|
80
|
+
75% 4.83ms
|
|
81
|
+
90% 6.03ms
|
|
82
|
+
99% 8.43ms
|
|
83
|
+
96296 requests in 10.01s, 21.95MB read
|
|
84
|
+
Requests/sec: 9622.74
|
|
85
|
+
Transfer/sec: 2.19MB
|
|
32
86
|
```
|
|
33
|
-
|
|
34
87
|
# Support / Donate 💚
|
|
35
88
|
You can support the maintenance of this project:
|
|
36
89
|
- PayPal: https://www.paypal.me/kyberneees
|
package/demos/basic.js
CHANGED
package/demos/minimal.js
ADDED
package/lib/next.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
module.exports = function next (middlewares, req, index,
|
|
1
|
+
module.exports = function next (middlewares, req, index, defaultRoute, errorHandler) {
|
|
2
2
|
const middleware = middlewares[index]
|
|
3
3
|
if (!middleware) {
|
|
4
4
|
return defaultRoute(req)
|
|
@@ -8,27 +8,12 @@ module.exports = function next (middlewares, req, index, routers = {}, defaultRo
|
|
|
8
8
|
if (err) {
|
|
9
9
|
return errorHandler(err, req)
|
|
10
10
|
} else {
|
|
11
|
-
return next(middlewares, req, index + 1,
|
|
11
|
+
return next(middlewares, req, index + 1, defaultRoute, errorHandler)
|
|
12
12
|
}
|
|
13
13
|
}
|
|
14
14
|
|
|
15
15
|
try {
|
|
16
|
-
|
|
17
|
-
// nested routes support
|
|
18
|
-
const pattern = routers[middleware.id]
|
|
19
|
-
if (pattern) {
|
|
20
|
-
req.preRouterPath = req.path
|
|
21
|
-
|
|
22
|
-
req.path = req.path.replace(pattern, '')
|
|
23
|
-
if (!req.path.startsWith('/')) {
|
|
24
|
-
req.path = '/' + req.path
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
return middleware.lookup(req, step)
|
|
29
|
-
} else {
|
|
30
|
-
return middleware(req, step)
|
|
31
|
-
}
|
|
16
|
+
return middleware(req, step)
|
|
32
17
|
} catch (err) {
|
|
33
18
|
return errorHandler(err, req)
|
|
34
19
|
}
|
package/lib/router/sequential.js
CHANGED
|
@@ -2,11 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
const Trouter = require('trouter')
|
|
4
4
|
const next = require('./../next')
|
|
5
|
-
const LRU = require('lru-cache')
|
|
6
|
-
const { parse } = require('regexparam')
|
|
7
5
|
|
|
8
6
|
module.exports = (config = {}) => {
|
|
9
|
-
if (config.defaultRoute
|
|
7
|
+
if (!config.defaultRoute) {
|
|
10
8
|
config.defaultRoute = (req) => {
|
|
11
9
|
const res = new Response(null, {
|
|
12
10
|
status: 404
|
|
@@ -15,7 +13,7 @@ module.exports = (config = {}) => {
|
|
|
15
13
|
return res
|
|
16
14
|
}
|
|
17
15
|
}
|
|
18
|
-
if (config.errorHandler
|
|
16
|
+
if (!config.errorHandler) {
|
|
19
17
|
config.errorHandler = (err, req) => {
|
|
20
18
|
const res = new Response(err.message, {
|
|
21
19
|
status: 500
|
|
@@ -24,18 +22,9 @@ module.exports = (config = {}) => {
|
|
|
24
22
|
return res
|
|
25
23
|
}
|
|
26
24
|
}
|
|
27
|
-
if (config.cacheSize === undefined) {
|
|
28
|
-
config.cacheSize = 1000
|
|
29
|
-
}
|
|
30
|
-
if (config.id === undefined) {
|
|
31
|
-
config.id = (Date.now().toString(36) + Math.random().toString(36).substring(2, 5)).toUpperCase()
|
|
32
|
-
}
|
|
33
25
|
|
|
34
|
-
const routers = {}
|
|
35
|
-
const isCacheEnabled = config.cacheSize > 0
|
|
36
|
-
const cache = isCacheEnabled ? new LRU({ max: config.cacheSize }) : null
|
|
37
26
|
const router = new Trouter()
|
|
38
|
-
router.
|
|
27
|
+
router.port = config.port || 3000
|
|
39
28
|
|
|
40
29
|
const _use = router.use
|
|
41
30
|
|
|
@@ -46,53 +35,25 @@ module.exports = (config = {}) => {
|
|
|
46
35
|
}
|
|
47
36
|
_use.call(router, prefix, middlewares)
|
|
48
37
|
|
|
49
|
-
if (middlewares[0].id) {
|
|
50
|
-
// caching router -> pattern relation for urls pattern replacement
|
|
51
|
-
const { pattern } = parse(prefix, true)
|
|
52
|
-
routers[middlewares[0].id] = pattern
|
|
53
|
-
}
|
|
54
|
-
|
|
55
38
|
return this
|
|
56
39
|
}
|
|
57
40
|
|
|
58
|
-
router.
|
|
41
|
+
router.fetch = (req, step) => {
|
|
59
42
|
const url = new URL(req.url)
|
|
43
|
+
|
|
60
44
|
req.path = url.pathname || '/'
|
|
61
45
|
req.query = url.queryparams
|
|
62
46
|
req.search = url.search
|
|
63
47
|
req.hostname = url.hostname
|
|
64
48
|
|
|
65
|
-
|
|
66
|
-
if (
|
|
67
|
-
const reqCacheKey = req.method + req.path
|
|
68
|
-
match = cache.get(reqCacheKey)
|
|
69
|
-
if (!match) {
|
|
70
|
-
match = router.find(req.method, req.path)
|
|
71
|
-
cache.set(reqCacheKey, match)
|
|
72
|
-
}
|
|
73
|
-
} else {
|
|
74
|
-
match = router.find(req.method, req.path)
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
if (match.handlers.length !== 0) {
|
|
78
|
-
const middlewares = [...match.handlers]
|
|
79
|
-
if (step !== undefined) {
|
|
80
|
-
// router is being used as a nested router
|
|
81
|
-
middlewares.push((req, next) => {
|
|
82
|
-
req.path = req.preRouterPath
|
|
83
|
-
|
|
84
|
-
delete req.preRouterPath
|
|
85
|
-
|
|
86
|
-
return step()
|
|
87
|
-
})
|
|
88
|
-
}
|
|
89
|
-
|
|
49
|
+
const match = router.find(req.method, req.path)
|
|
50
|
+
if (match.handlers.length > 0) {
|
|
90
51
|
if (!req.params) {
|
|
91
52
|
req.params = {}
|
|
92
53
|
}
|
|
93
54
|
Object.assign(req.params, match.params)
|
|
94
55
|
|
|
95
|
-
return next(
|
|
56
|
+
return next(match.handlers, req, 0, config.defaultRoute, config.errorHandler)
|
|
96
57
|
} else {
|
|
97
58
|
return config.defaultRoute(req)
|
|
98
59
|
}
|
package/package.json
CHANGED
|
@@ -1,15 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "0http-bun",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.3",
|
|
4
4
|
"description": "0http alternative for Bun",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"scripts": {
|
|
7
|
-
"
|
|
7
|
+
"lint": "bun x standard",
|
|
8
|
+
"format": "bun x standard --fix"
|
|
8
9
|
},
|
|
9
10
|
"dependencies": {
|
|
10
|
-
"
|
|
11
|
-
"regexparam": "^2.0.0",
|
|
12
|
-
"trouter": "^3.2.0"
|
|
11
|
+
"trouter": "^3.2.1"
|
|
13
12
|
},
|
|
14
13
|
"repository": {
|
|
15
14
|
"type": "git",
|