ultimate-express 2.0.9 → 2.0.10

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/README.md CHANGED
@@ -1,350 +1,350 @@
1
- # µExpress / Ultimate Express
2
-
3
- The *Ultimate* Express. Fastest http server with **full** Express compatibility, based on µWebSockets.
4
-
5
- This library is a very fast re-implementation of Express.js 4.
6
- It is designed to be a drop-in replacement for Express.js, with the same API and functionality, while being much faster. It is not a fork of Express.js.
7
- To make sure µExpress matches behavior of Express in all cases, we run all tests with Express first, and then with µExpress and compare results to make sure they match.
8
-
9
- `npm install ultimate-express` -> replace `express` with `ultimate-express` -> done[*](https://github.com/dimdenGD/ultimate-express?tab=readme-ov-file#differences-from-express)
10
-
11
- [![Node.js >= 20.0.0](https://img.shields.io/badge/Node.js-%3E=20.0.0-green)](https://nodejs.org)
12
- [![npm](https://img.shields.io/npm/v/ultimate-express?label=last+version)](https://npmjs.com/package/ultimate-express)
13
- [![Patreon](https://img.shields.io/badge/donate-Patreon-orange)](https://patreon.com/dimdendev)
14
-
15
- > Use `npm install ultimate-express@node-v18` to install last version that supported Node.js v18.
16
-
17
- ## Difference from similar projects
18
-
19
- Similar projects based on uWebSockets:
20
-
21
- - `express` on Bun - since Bun uses uWS for its HTTP module, Express is about 2-3 times faster than on Node.js, but still almost 2 times slower than µExpress because it doesn't do uWS-specific optimizations.
22
- - `hyper-express` - while having a similar API to Express, it's very far from being a drop-in replacement, and implements most of the functionality differently. This creates a lot of random quirks and issues, making the switch quite difficult. Built in middlewares are also very different, middlewares for Express are mostly not supported.
23
- - `uwebsockets-express` - this library is closer to being a drop-in replacement, but misses a lot of APIs, depends on Express by calling it's methods under the hood and doesn't try to optimize routing by using native uWS router.
24
-
25
- ## Performance
26
-
27
- ### Test results
28
-
29
- Tested using [wrk](https://github.com/wg/wrk) (`-d 60 -t 1 -c 200`). Tested on Ubuntu 22.04, Node.js 20.17.0, AMD Ryzen 5 3600, 64GB RAM.
30
-
31
- | Test | Express req/sec | µExpress req/sec | Express throughput | µExpress throughput | µExpress speedup |
32
- | --------------------------------------------- | --------------- | ---------------- | ------------------ | ------------------- | ---------------- |
33
- | routing/simple-routes (/) | 11.16k | 75.14k | 2.08 MB/sec | 14.46 MB/sec | **6.73X** |
34
- | routing/lot-of-routes (/999) | 4.63k | 54.57k | 0.84 MB/sec | 10.03 MB/sec | **11.78X** |
35
- | routing/some-middlewares (/90) | 10.12k | 61.92k | 1.79 MB/sec | 11.32 MB/sec | **6.12X** |
36
- | routers/nested-routers (/abccc/nested/ddd) | 10.18k | 51.15k | 1.82 MB/sec | 9.40 MB/sec | **5.02X** |
37
- | middlewares/express-static (/static/index.js) | 6.58k | 32.45k | 10.15 MB/sec | 49.43 MB/sec | **4.87X** |
38
- | engines/ejs (/test) | 5.50k | 40.82k | 2.45 MB/sec | 18.38 MB/sec | **7.42X** |
39
- | middlewares/body-urlencoded (/abc) | 8.07k | 50.52k | 1.68 MB/sec | 10.78 MB/sec | **6.26X** |
40
- | middlewares/compression-file (/small-file) | 4.81k | 14.92k | 386 MB/sec | 1.17 GB/sec | **3.10X** |
41
-
42
- ### Performance against other frameworks
43
-
44
- Tested using [bun-http-framework-benchmark](https://github.com/dimdenGD/bun-http-framework-benchmark). This table only includes Node.js results.
45
- For full table with other runtimes, check [here](https://github.com/dimdenGD/bun-http-framework-benchmark?tab=readme-ov-file#results).
46
-
47
- | Framework | Average | Ping | Query | Body |
48
- | -------------------- | -------------- | ------------- | ------------- | ------------- |
49
- | uws | 95,531.277 | 109,960.35 | 105,601.47 | 71,032.01 |
50
- | **ultimate-express (declarative)** | **86,794.997** | **108,546.44** | **105,869.75** | **45,968.8** |
51
- | hyper-express | 68,959.92 | 82,547.21 | 71,685.51 | 52,647.04 |
52
- | **ultimate-express** | **60,839.75** | **68,938.53** | **66,173.86** | **47,406.86** |
53
- | h3 | 35,423.263 | 41,243.68 | 34,429.26 | 30,596.85 |
54
- | fastify | 33,094.62 | 40,147.67 | 40,076.35 | 19,059.84 |
55
- | hono | 26,576.02 | 36,215.35 | 34,656.12 | 8,856.59 |
56
- | koa | 24,045.08 | 28,202.12 | 24,590.84 | 19,342.28 |
57
- | express | 10,411.313 | 11,245.57 | 10,598.74 | 9,389.63 |
58
-
59
- Other benchmarks:
60
- - [TechEmpower / FrameworkBenchmarks](https://www.techempower.com/benchmarks/#section=data-r23&test=plaintext&l=zik0sf-pa7)
61
- - [the-benchmarker / web-frameworks](https://web-frameworks-benchmark.netlify.app/result?l=javascript)
62
-
63
- ### Performance on real-world application
64
-
65
- Also tested on a [real-world application](https://nekoweb.org) with templates, static files and dynamic pages with data from database, and showed 1.5-4X speedup in requests per second depending on the page.
66
-
67
- ## Differences from Express
68
-
69
- In a lot of cases, you can just replace `require("express")` with `require("ultimate-express")` and everything works the same. But there are some differences:
70
-
71
- - `case sensitive routing` is enabled by default.
72
- - a new option `catch async errors` is added. If it's enabled, you don't need to use `express-async-errors` module.
73
- - request body is only read for POST, PUT and PATCH requests by default. You can add additional methods by setting `body methods` to array with uppercased methods.
74
- - For HTTPS, instead of doing this:
75
- ```js
76
- const https = require("https");
77
- const express = require("express");
78
-
79
- const app = express();
80
-
81
- https.createServer({
82
- key: fs.readFileSync('path/to/key.pem'),
83
- cert: fs.readFileSync('path/to/cert.pem')
84
- }, app).listen(3000, () => {
85
- console.log('Server is running on port 3000');
86
- });
87
- ```
88
-
89
- You have to pass `uwsOptions` to the `express()` constructor:
90
- ```js
91
- const express = require("ultimate-express");
92
-
93
- const app = express({
94
- uwsOptions: {
95
- // https://unetworking.github.io/uWebSockets.js/generated/interfaces/AppOptions.html
96
- key_file_name: 'path/to/key.pem',
97
- cert_file_name: 'path/to/cert.pem'
98
- }
99
- });
100
-
101
- app.listen(3000, () => {
102
- console.log('Server is running on port 3000');
103
- });
104
- ```
105
-
106
- - This also applies to non-SSL HTTP too. Do not create http server manually, use `app.listen()` instead.
107
- - Node.JS max header size is 16384 bytes, while uWebSockets by default is 4096 bytes, so if you need longer headers set the env variable `UWS_HTTP_MAX_HEADERS_SIZE` to max byte count you need.
108
-
109
- ## Performance tips
110
-
111
- 1. µExpress tries to optimize routing as much as possible, but it's only possible if:
112
- - `case sensitive routing` is enabled (it is by default, unlike in normal Express).
113
- - only string paths without regex characters like *, +, (), {}, etc. can be optimized.
114
- - only 1-level deep routers can be optimized.
115
-
116
- Optimized routes can be up to 10 times faster than normal routes, as they're using native uWS router and have pre-calculated path.
117
-
118
- 2. Do not use external `serve-static` module. Instead use built-in `express.static()` middleware, which is optimized for uExpress.
119
-
120
- 3. Do not use `body-parser` module. Instead use built-in `express.text()`, `express.json()` etc.
121
-
122
- 4. Do not set `body methods` to read body of requests with GET method or other methods that don't need a body. Reading body makes endpoint about 15% slower.
123
-
124
- 5. By default, µExpress creates 1 (or 0 if your CPU has only 1 core) child thread to improve performance of reading files. You can change this number by setting `threads` to a different number in `express()`, or set to 0 to disable thread pool (`express({ threads: 0 })`). Threads are shared between all express() instances, with largest `threads` number being used. Using more threads will not necessarily improve performance. Sometimes not using threads at all is faster, please [test](https://github.com/wg/wrk/) both options.
125
-
126
- ## WebSockets
127
-
128
- Since you don't create http server manually, you can't properly use http.on("upgrade") to handle WebSockets. To solve this, there's currently 2 options:
129
-
130
- - There's a sister library that implements `ws` compatible API: [Ultimate WS](https://github.com/dimdenGD/ultimate-ws). It's same concept as this library, but for WebSockets: fast drop-in replacement for `ws` module with support for Ultimate Express upgrades. There's a guide for how to upgrade http requests in the documentation.
131
- - You can simply use `app.uwsApp` to access uWebSockets.js `App` instance and call its `ws()` method directly.
132
-
133
- ## HTTP/3
134
-
135
- HTTP/3 is supported. To use:
136
-
137
- ```js
138
- const app = express({
139
- http3: true,
140
- uwsOptions: {
141
- key_file_name: '/path/to/example.key',
142
- cert_file_name: '/path/to/example.crt'
143
- }
144
- });
145
- ```
146
-
147
- ## Compatibility
148
-
149
- In general, basically all features and options are supported. Use [Express 4.x documentation](https://expressjs.com/en/4x/api.html) for API reference.
150
-
151
- ✅ - Full support (all features and options are supported)
152
- 🚧 - Partial support (some options are not supported)
153
- ❌ - Not supported
154
-
155
- ### express
156
-
157
- - ✅ express()
158
- - ✅ express.Router()
159
- - ✅ express.json()
160
- - ✅ express.urlencoded()
161
- - ✅ express.static()
162
- - ✅ express.text()
163
- - ✅ express.raw()
164
- - 🚧 express.request (this is not a constructor but a prototype for replacing methods)
165
- - 🚧 express.response (this is not a constructor but a prototype for replacing methods)
166
-
167
- ### Application
168
-
169
- - ✅ app.listen(port[, host][, callback])
170
- - ✅ app.listen(unix_socket[, callback])
171
- - ✅ app.METHOD() (app.get, app.post, etc.)
172
- - ✅ app.route()
173
- - ✅ app.all()
174
- - ✅ app.use()
175
- - ✅ app.mountpath
176
- - ✅ app.set()
177
- - ✅ app.get()
178
- - ✅ app.enable()
179
- - ✅ app.disable()
180
- - ✅ app.enabled()
181
- - ✅ app.disabled()
182
- - ✅ app.path()
183
- - ✅ app.param(name, callback)
184
- - ✅ app.param(callback)
185
- - ✅ app.engine()
186
- - ✅ app.render()
187
- - ✅ app.locals
188
- - ✅ app.settings
189
- - ✅ app.engines
190
- - ✅ app.on("mount")
191
- - ✅ HEAD method
192
- - ✅ OPTIONS method
193
-
194
- ### Application settings
195
-
196
- - ✅ case sensitive routing
197
- - ✅ env
198
- - ✅ etag
199
- - ✅ jsonp callback name
200
- - ✅ json escape
201
- - ✅ json replacer
202
- - ✅ json spaces
203
- - ✅ query parser
204
- - ✅ strict routing
205
- - ✅ subdomain offset
206
- - ✅ trust proxy
207
- - ✅ views
208
- - ✅ view cache
209
- - ✅ view engine
210
- - ✅ x-powered-by
211
-
212
- ### Request
213
- - ✅ implements Readable stream
214
- - ✅ req.app
215
- - ✅ req.baseUrl
216
- - ✅ req.body
217
- - ✅ req.cookies
218
- - ✅ req.fresh
219
- - ✅ req.hostname
220
- - ✅ req.header
221
- - ✅ req.headers
222
- - ✅ req.headersDistinct
223
- - ✅ req.rawHeaders
224
- - ✅ req.ip
225
- - ✅ req.ips
226
- - ✅ req.method
227
- - ✅ req.url
228
- - ✅ req.originalUrl
229
- - ✅ req.params
230
- - ✅ req.path
231
- - ✅ req.protocol
232
- - ✅ req.query
233
- - ✅ req.res
234
- - ✅ req.secure
235
- - ✅ req.signedCookies
236
- - ✅ req.stale
237
- - ✅ req.subdomains
238
- - ✅ req.xhr
239
- - 🚧 req.route (route implementation is different from Express)
240
- - 🚧 req.connection, req.socket (only `end()`, `encrypted`, `remoteAddress` and `localPort` are supported)
241
- - ✅ req.accepts()
242
- - ✅ req.acceptsCharsets()
243
- - ✅ req.acceptsEncodings()
244
- - ✅ req.acceptsLanguages()
245
- - ✅ req.get()
246
- - ✅ req.is()
247
- - ✅ req.param()
248
- - ✅ req.range()
249
-
250
- ### Response
251
-
252
- - ✅ implements Writable stream
253
- - ✅ res.app
254
- - ✅ res.headersSent
255
- - ✅ res.req
256
- - ✅ res.locals
257
- - ✅ res.append()
258
- - ✅ res.attachment()
259
- - ✅ res.cookie()
260
- - ✅ res.clearCookie()
261
- - ✅ res.download()
262
- - ✅ res.end()
263
- - ✅ res.format()
264
- - ✅ res.getHeader(), res.get()
265
- - ✅ res.json()
266
- - ✅ res.jsonp()
267
- - ✅ res.links()
268
- - ✅ res.location()
269
- - ✅ res.redirect()
270
- - ✅ res.render()
271
- - ✅ res.send()
272
- - ✅ res.sendFile()
273
- - - ✅ options.maxAge
274
- - - ✅ options.root
275
- - - ✅ options.lastModified
276
- - - ✅ options.headers
277
- - - ✅ options.dotfiles
278
- - - ✅ options.acceptRanges
279
- - - ✅ options.cacheControl
280
- - - ✅ options.immutable
281
- - - ✅ Range header
282
- - - ✅ Setting ETag header
283
- - - ✅ If-Match header
284
- - - ✅ If-Modified-Since header
285
- - - ✅ If-Unmodified-Since header
286
- - - ✅ If-Range header
287
- - ✅ res.sendStatus()
288
- - ✅ res.header(), res.setHeader(), res.set()
289
- - ✅ res.status()
290
- - ✅ res.type()
291
- - ✅ res.vary()
292
- - ✅ res.removeHeader()
293
- - ✅ res.write()
294
- - ✅ res.writeHead()
295
-
296
- ### Router
297
-
298
- - ✅ router.all()
299
- - ✅ router.METHOD() (router.get, router.post, etc.)
300
- - ✅ router.route()
301
- - ✅ router.use()
302
- - ✅ router.param(name, callback)
303
- - ✅ router.param(callback)
304
- - ✅ options.caseSensitive
305
- - ✅ options.strict
306
- - ✅ options.mergeParams
307
-
308
- ## Tested middlewares
309
-
310
- Almost all middlewares that are compatible with Express are compatible with µExpress. Here's list of middlewares that we test for compatibility:
311
-
312
- - ✅ [body-parser](https://npmjs.com/package/body-parser) (use `express.text()` etc instead for better performance)
313
- - ✅ [cookie-parser](https://npmjs.com/package/cookie-parser)
314
- - ✅ [cookie-session](https://npmjs.com/package/cookie-session)
315
- - ✅ [compression](https://npmjs.com/package/compression)
316
- - ✅ [serve-static](https://npmjs.com/package/serve-static) (use `express.static()` instead for better performance)
317
- - ✅ [serve-index](https://npmjs.com/package/serve-index)
318
- - ✅ [cors](https://npmjs.com/package/cors)
319
- - ✅ [errorhandler](https://npmjs.com/package/errorhandler)
320
- - ✅ [method-override](https://npmjs.com/package/method-override)
321
- - ✅ [multer](https://npmjs.com/package/multer)
322
- - ✅ [response-time](https://npmjs.com/package/response-time)
323
- - ✅ [express-fileupload](https://npmjs.com/package/express-fileupload)
324
- - ✅ [express-session](https://npmjs.com/package/express-session)
325
- - ✅ [express-rate-limit](https://npmjs.com/package/express-rate-limit)
326
- - ✅ [express-subdomain](https://npmjs.com/package/express-subdomain)
327
- - ✅ [vhost](https://npmjs.com/package/vhost)
328
- - ✅ [tsoa](https://github.com/lukeautry/tsoa)
329
- - ✅ [express-mongo-sanitize](https://www.npmjs.com/package/express-mongo-sanitize)
330
- - ✅ [helmet](https://www.npmjs.com/package/helmet)
331
- - ✅ [passport](https://www.npmjs.com/package/passport)
332
- - ✅ [morgan](https://www.npmjs.com/package/morgan)
333
- - ✅ [swagger-ui-express](https://www.npmjs.com/package/swagger-ui-express)
334
- - ✅ [graphql-http](https://www.npmjs.com/package/graphql-http)
335
- - ✅ [better-sse](https://www.npmjs.com/package/better-sse)
336
-
337
- Middlewares and modules that are confirmed to not work:
338
-
339
- - ❌ [express-async-errors](https://npmjs.com/package/express-async-errors) - doesn't work, use `app.set('catch async errors', true)` instead.
340
-
341
- ## Tested view engines
342
-
343
- Any Express view engine should work. Here's list of engines we include in our test suite:
344
-
345
- - ✅ [ejs](https://npmjs.com/package/ejs)
346
- - ✅ [pug](https://npmjs.com/package/pug)
347
- - ✅ [express-dot-engine](https://npmjs.com/package/express-dot-engine)
348
- - ✅ [express-art-template](https://npmjs.com/package/express-art-template)
349
- - ✅ [express-handlebars](https://npmjs.com/package/express-handlebars)
350
- - ✅ [swig](https://npmjs.com/package/swig)
1
+ # µExpress / Ultimate Express
2
+
3
+ The *Ultimate* Express. Fastest http server with **full** Express compatibility, based on µWebSockets.
4
+
5
+ This library is a very fast re-implementation of Express.js 4.
6
+ It is designed to be a drop-in replacement for Express.js, with the same API and functionality, while being much faster. It is not a fork of Express.js.
7
+ To make sure µExpress matches behavior of Express in all cases, we run all tests with Express first, and then with µExpress and compare results to make sure they match.
8
+
9
+ `npm install ultimate-express` -> replace `express` with `ultimate-express` -> done[*](https://github.com/dimdenGD/ultimate-express?tab=readme-ov-file#differences-from-express)
10
+
11
+ [![Node.js >= 20.0.0](https://img.shields.io/badge/Node.js-%3E=20.0.0-green)](https://nodejs.org)
12
+ [![npm](https://img.shields.io/npm/v/ultimate-express?label=last+version)](https://npmjs.com/package/ultimate-express)
13
+ [![Patreon](https://img.shields.io/badge/donate-Patreon-orange)](https://patreon.com/dimdendev)
14
+
15
+ > Use `npm install ultimate-express@node-v18` to install last version that supported Node.js v18.
16
+
17
+ ## Difference from similar projects
18
+
19
+ Similar projects based on uWebSockets:
20
+
21
+ - `express` on Bun - since Bun uses uWS for its HTTP module, Express is about 2-3 times faster than on Node.js, but still almost 2 times slower than µExpress because it doesn't do uWS-specific optimizations.
22
+ - `hyper-express` - while having a similar API to Express, it's very far from being a drop-in replacement, and implements most of the functionality differently. This creates a lot of random quirks and issues, making the switch quite difficult. Built in middlewares are also very different, middlewares for Express are mostly not supported.
23
+ - `uwebsockets-express` - this library is closer to being a drop-in replacement, but misses a lot of APIs, depends on Express by calling it's methods under the hood and doesn't try to optimize routing by using native uWS router.
24
+
25
+ ## Performance
26
+
27
+ ### Test results
28
+
29
+ Tested using [wrk](https://github.com/wg/wrk) (`-d 60 -t 1 -c 200`). Tested on Ubuntu 22.04, Node.js 20.17.0, AMD Ryzen 5 3600, 64GB RAM.
30
+
31
+ | Test | Express req/sec | µExpress req/sec | Express throughput | µExpress throughput | µExpress speedup |
32
+ | --------------------------------------------- | --------------- | ---------------- | ------------------ | ------------------- | ---------------- |
33
+ | routing/simple-routes (/) | 11.16k | 75.14k | 2.08 MB/sec | 14.46 MB/sec | **6.73X** |
34
+ | routing/lot-of-routes (/999) | 4.63k | 54.57k | 0.84 MB/sec | 10.03 MB/sec | **11.78X** |
35
+ | routing/some-middlewares (/90) | 10.12k | 61.92k | 1.79 MB/sec | 11.32 MB/sec | **6.12X** |
36
+ | routers/nested-routers (/abccc/nested/ddd) | 10.18k | 51.15k | 1.82 MB/sec | 9.40 MB/sec | **5.02X** |
37
+ | middlewares/express-static (/static/index.js) | 6.58k | 32.45k | 10.15 MB/sec | 49.43 MB/sec | **4.87X** |
38
+ | engines/ejs (/test) | 5.50k | 40.82k | 2.45 MB/sec | 18.38 MB/sec | **7.42X** |
39
+ | middlewares/body-urlencoded (/abc) | 8.07k | 50.52k | 1.68 MB/sec | 10.78 MB/sec | **6.26X** |
40
+ | middlewares/compression-file (/small-file) | 4.81k | 14.92k | 386 MB/sec | 1.17 GB/sec | **3.10X** |
41
+
42
+ ### Performance against other frameworks
43
+
44
+ Tested using [bun-http-framework-benchmark](https://github.com/dimdenGD/bun-http-framework-benchmark). This table only includes Node.js results.
45
+ For full table with other runtimes, check [here](https://github.com/dimdenGD/bun-http-framework-benchmark?tab=readme-ov-file#results).
46
+
47
+ | Framework | Average | Ping | Query | Body |
48
+ | -------------------- | -------------- | ------------- | ------------- | ------------- |
49
+ | uws | 95,531.277 | 109,960.35 | 105,601.47 | 71,032.01 |
50
+ | **ultimate-express (declarative)** | **86,794.997** | **108,546.44** | **105,869.75** | **45,968.8** |
51
+ | hyper-express | 68,959.92 | 82,547.21 | 71,685.51 | 52,647.04 |
52
+ | **ultimate-express** | **60,839.75** | **68,938.53** | **66,173.86** | **47,406.86** |
53
+ | h3 | 35,423.263 | 41,243.68 | 34,429.26 | 30,596.85 |
54
+ | fastify | 33,094.62 | 40,147.67 | 40,076.35 | 19,059.84 |
55
+ | hono | 26,576.02 | 36,215.35 | 34,656.12 | 8,856.59 |
56
+ | koa | 24,045.08 | 28,202.12 | 24,590.84 | 19,342.28 |
57
+ | express | 10,411.313 | 11,245.57 | 10,598.74 | 9,389.63 |
58
+
59
+ Other benchmarks:
60
+ - [TechEmpower / FrameworkBenchmarks](https://www.techempower.com/benchmarks/#section=data-r23&test=plaintext&l=zik0sf-pa7)
61
+ - [the-benchmarker / web-frameworks](https://web-frameworks-benchmark.netlify.app/result?l=javascript)
62
+
63
+ ### Performance on real-world application
64
+
65
+ Also tested on a [real-world application](https://nekoweb.org) with templates, static files and dynamic pages with data from database, and showed 1.5-4X speedup in requests per second depending on the page.
66
+
67
+ ## Differences from Express
68
+
69
+ In a lot of cases, you can just replace `require("express")` with `require("ultimate-express")` and everything works the same. But there are some differences:
70
+
71
+ - `case sensitive routing` is enabled by default.
72
+ - a new option `catch async errors` is added. If it's enabled, you don't need to use `express-async-errors` module.
73
+ - request body is only read for POST, PUT and PATCH requests by default. You can add additional methods by setting `body methods` to array with uppercased methods.
74
+ - For HTTPS, instead of doing this:
75
+ ```js
76
+ const https = require("https");
77
+ const express = require("express");
78
+
79
+ const app = express();
80
+
81
+ https.createServer({
82
+ key: fs.readFileSync('path/to/key.pem'),
83
+ cert: fs.readFileSync('path/to/cert.pem')
84
+ }, app).listen(3000, () => {
85
+ console.log('Server is running on port 3000');
86
+ });
87
+ ```
88
+
89
+ You have to pass `uwsOptions` to the `express()` constructor:
90
+ ```js
91
+ const express = require("ultimate-express");
92
+
93
+ const app = express({
94
+ uwsOptions: {
95
+ // https://unetworking.github.io/uWebSockets.js/generated/interfaces/AppOptions.html
96
+ key_file_name: 'path/to/key.pem',
97
+ cert_file_name: 'path/to/cert.pem'
98
+ }
99
+ });
100
+
101
+ app.listen(3000, () => {
102
+ console.log('Server is running on port 3000');
103
+ });
104
+ ```
105
+
106
+ - This also applies to non-SSL HTTP too. Do not create http server manually, use `app.listen()` instead.
107
+ - Node.JS max header size is 16384 bytes, while uWebSockets by default is 4096 bytes, so if you need longer headers set the env variable `UWS_HTTP_MAX_HEADERS_SIZE` to max byte count you need.
108
+
109
+ ## Performance tips
110
+
111
+ 1. µExpress tries to optimize routing as much as possible, but it's only possible if:
112
+ - `case sensitive routing` is enabled (it is by default, unlike in normal Express).
113
+ - only string paths without regex characters like *, +, (), {}, etc. can be optimized.
114
+ - only 1-level deep routers can be optimized.
115
+
116
+ Optimized routes can be up to 10 times faster than normal routes, as they're using native uWS router and have pre-calculated path.
117
+
118
+ 2. Do not use external `serve-static` module. Instead use built-in `express.static()` middleware, which is optimized for uExpress.
119
+
120
+ 3. Do not use `body-parser` module. Instead use built-in `express.text()`, `express.json()` etc.
121
+
122
+ 4. Do not set `body methods` to read body of requests with GET method or other methods that don't need a body. Reading body makes endpoint about 15% slower.
123
+
124
+ 5. By default, µExpress creates 1 (or 0 if your CPU has only 1 core) child thread to improve performance of reading files. You can change this number by setting `threads` to a different number in `express()`, or set to 0 to disable thread pool (`express({ threads: 0 })`). Threads are shared between all express() instances, with largest `threads` number being used. Using more threads will not necessarily improve performance. Sometimes not using threads at all is faster, please [test](https://github.com/wg/wrk/) both options.
125
+
126
+ ## WebSockets
127
+
128
+ Since you don't create http server manually, you can't properly use http.on("upgrade") to handle WebSockets. To solve this, there's currently 2 options:
129
+
130
+ - There's a sister library that implements `ws` compatible API: [Ultimate WS](https://github.com/dimdenGD/ultimate-ws). It's same concept as this library, but for WebSockets: fast drop-in replacement for `ws` module with support for Ultimate Express upgrades. There's a guide for how to upgrade http requests in the documentation.
131
+ - You can simply use `app.uwsApp` to access uWebSockets.js `App` instance and call its `ws()` method directly.
132
+
133
+ ## HTTP/3
134
+
135
+ HTTP/3 is supported. To use:
136
+
137
+ ```js
138
+ const app = express({
139
+ http3: true,
140
+ uwsOptions: {
141
+ key_file_name: '/path/to/example.key',
142
+ cert_file_name: '/path/to/example.crt'
143
+ }
144
+ });
145
+ ```
146
+
147
+ ## Compatibility
148
+
149
+ In general, basically all features and options are supported. Use [Express 4.x documentation](https://expressjs.com/en/4x/api.html) for API reference.
150
+
151
+ ✅ - Full support (all features and options are supported)
152
+ 🚧 - Partial support (some options are not supported)
153
+ ❌ - Not supported
154
+
155
+ ### express
156
+
157
+ - ✅ express()
158
+ - ✅ express.Router()
159
+ - ✅ express.json()
160
+ - ✅ express.urlencoded()
161
+ - ✅ express.static()
162
+ - ✅ express.text()
163
+ - ✅ express.raw()
164
+ - 🚧 express.request (this is not a constructor but a prototype for replacing methods)
165
+ - 🚧 express.response (this is not a constructor but a prototype for replacing methods)
166
+
167
+ ### Application
168
+
169
+ - ✅ app.listen(port[, host][, callback])
170
+ - ✅ app.listen(unix_socket[, callback])
171
+ - ✅ app.METHOD() (app.get, app.post, etc.)
172
+ - ✅ app.route()
173
+ - ✅ app.all()
174
+ - ✅ app.use()
175
+ - ✅ app.mountpath
176
+ - ✅ app.set()
177
+ - ✅ app.get()
178
+ - ✅ app.enable()
179
+ - ✅ app.disable()
180
+ - ✅ app.enabled()
181
+ - ✅ app.disabled()
182
+ - ✅ app.path()
183
+ - ✅ app.param(name, callback)
184
+ - ✅ app.param(callback)
185
+ - ✅ app.engine()
186
+ - ✅ app.render()
187
+ - ✅ app.locals
188
+ - ✅ app.settings
189
+ - ✅ app.engines
190
+ - ✅ app.on("mount")
191
+ - ✅ HEAD method
192
+ - ✅ OPTIONS method
193
+
194
+ ### Application settings
195
+
196
+ - ✅ case sensitive routing
197
+ - ✅ env
198
+ - ✅ etag
199
+ - ✅ jsonp callback name
200
+ - ✅ json escape
201
+ - ✅ json replacer
202
+ - ✅ json spaces
203
+ - ✅ query parser
204
+ - ✅ strict routing
205
+ - ✅ subdomain offset
206
+ - ✅ trust proxy
207
+ - ✅ views
208
+ - ✅ view cache
209
+ - ✅ view engine
210
+ - ✅ x-powered-by
211
+
212
+ ### Request
213
+ - ✅ implements Readable stream
214
+ - ✅ req.app
215
+ - ✅ req.baseUrl
216
+ - ✅ req.body
217
+ - ✅ req.cookies
218
+ - ✅ req.fresh
219
+ - ✅ req.hostname
220
+ - ✅ req.header
221
+ - ✅ req.headers
222
+ - ✅ req.headersDistinct
223
+ - ✅ req.rawHeaders
224
+ - ✅ req.ip
225
+ - ✅ req.ips
226
+ - ✅ req.method
227
+ - ✅ req.url
228
+ - ✅ req.originalUrl
229
+ - ✅ req.params
230
+ - ✅ req.path
231
+ - ✅ req.protocol
232
+ - ✅ req.query
233
+ - ✅ req.res
234
+ - ✅ req.secure
235
+ - ✅ req.signedCookies
236
+ - ✅ req.stale
237
+ - ✅ req.subdomains
238
+ - ✅ req.xhr
239
+ - 🚧 req.route (route implementation is different from Express)
240
+ - 🚧 req.connection, req.socket (only `end()`, `encrypted`, `remoteAddress` and `localPort` are supported)
241
+ - ✅ req.accepts()
242
+ - ✅ req.acceptsCharsets()
243
+ - ✅ req.acceptsEncodings()
244
+ - ✅ req.acceptsLanguages()
245
+ - ✅ req.get()
246
+ - ✅ req.is()
247
+ - ✅ req.param()
248
+ - ✅ req.range()
249
+
250
+ ### Response
251
+
252
+ - ✅ implements Writable stream
253
+ - ✅ res.app
254
+ - ✅ res.headersSent
255
+ - ✅ res.req
256
+ - ✅ res.locals
257
+ - ✅ res.append()
258
+ - ✅ res.attachment()
259
+ - ✅ res.cookie()
260
+ - ✅ res.clearCookie()
261
+ - ✅ res.download()
262
+ - ✅ res.end()
263
+ - ✅ res.format()
264
+ - ✅ res.getHeader(), res.get()
265
+ - ✅ res.json()
266
+ - ✅ res.jsonp()
267
+ - ✅ res.links()
268
+ - ✅ res.location()
269
+ - ✅ res.redirect()
270
+ - ✅ res.render()
271
+ - ✅ res.send()
272
+ - ✅ res.sendFile()
273
+ - - ✅ options.maxAge
274
+ - - ✅ options.root
275
+ - - ✅ options.lastModified
276
+ - - ✅ options.headers
277
+ - - ✅ options.dotfiles
278
+ - - ✅ options.acceptRanges
279
+ - - ✅ options.cacheControl
280
+ - - ✅ options.immutable
281
+ - - ✅ Range header
282
+ - - ✅ Setting ETag header
283
+ - - ✅ If-Match header
284
+ - - ✅ If-Modified-Since header
285
+ - - ✅ If-Unmodified-Since header
286
+ - - ✅ If-Range header
287
+ - ✅ res.sendStatus()
288
+ - ✅ res.header(), res.setHeader(), res.set()
289
+ - ✅ res.status()
290
+ - ✅ res.type()
291
+ - ✅ res.vary()
292
+ - ✅ res.removeHeader()
293
+ - ✅ res.write()
294
+ - ✅ res.writeHead()
295
+
296
+ ### Router
297
+
298
+ - ✅ router.all()
299
+ - ✅ router.METHOD() (router.get, router.post, etc.)
300
+ - ✅ router.route()
301
+ - ✅ router.use()
302
+ - ✅ router.param(name, callback)
303
+ - ✅ router.param(callback)
304
+ - ✅ options.caseSensitive
305
+ - ✅ options.strict
306
+ - ✅ options.mergeParams
307
+
308
+ ## Tested middlewares
309
+
310
+ Almost all middlewares that are compatible with Express are compatible with µExpress. Here's list of middlewares that we test for compatibility:
311
+
312
+ - ✅ [body-parser](https://npmjs.com/package/body-parser) (use `express.text()` etc instead for better performance)
313
+ - ✅ [cookie-parser](https://npmjs.com/package/cookie-parser)
314
+ - ✅ [cookie-session](https://npmjs.com/package/cookie-session)
315
+ - ✅ [compression](https://npmjs.com/package/compression)
316
+ - ✅ [serve-static](https://npmjs.com/package/serve-static) (use `express.static()` instead for better performance)
317
+ - ✅ [serve-index](https://npmjs.com/package/serve-index)
318
+ - ✅ [cors](https://npmjs.com/package/cors)
319
+ - ✅ [errorhandler](https://npmjs.com/package/errorhandler)
320
+ - ✅ [method-override](https://npmjs.com/package/method-override)
321
+ - ✅ [multer](https://npmjs.com/package/multer)
322
+ - ✅ [response-time](https://npmjs.com/package/response-time)
323
+ - ✅ [express-fileupload](https://npmjs.com/package/express-fileupload)
324
+ - ✅ [express-session](https://npmjs.com/package/express-session)
325
+ - ✅ [express-rate-limit](https://npmjs.com/package/express-rate-limit)
326
+ - ✅ [express-subdomain](https://npmjs.com/package/express-subdomain)
327
+ - ✅ [vhost](https://npmjs.com/package/vhost)
328
+ - ✅ [tsoa](https://github.com/lukeautry/tsoa)
329
+ - ✅ [express-mongo-sanitize](https://www.npmjs.com/package/express-mongo-sanitize)
330
+ - ✅ [helmet](https://www.npmjs.com/package/helmet)
331
+ - ✅ [passport](https://www.npmjs.com/package/passport)
332
+ - ✅ [morgan](https://www.npmjs.com/package/morgan)
333
+ - ✅ [swagger-ui-express](https://www.npmjs.com/package/swagger-ui-express)
334
+ - ✅ [graphql-http](https://www.npmjs.com/package/graphql-http)
335
+ - ✅ [better-sse](https://www.npmjs.com/package/better-sse)
336
+
337
+ Middlewares and modules that are confirmed to not work:
338
+
339
+ - ❌ [express-async-errors](https://npmjs.com/package/express-async-errors) - doesn't work, use `app.set('catch async errors', true)` instead.
340
+
341
+ ## Tested view engines
342
+
343
+ Any Express view engine should work. Here's list of engines we include in our test suite:
344
+
345
+ - ✅ [ejs](https://npmjs.com/package/ejs)
346
+ - ✅ [pug](https://npmjs.com/package/pug)
347
+ - ✅ [express-dot-engine](https://npmjs.com/package/express-dot-engine)
348
+ - ✅ [express-art-template](https://npmjs.com/package/express-art-template)
349
+ - ✅ [express-handlebars](https://npmjs.com/package/express-handlebars)
350
+ - ✅ [swig](https://npmjs.com/package/swig)