Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/tsar-boomba/megalo
Deno HTTP server framework focused on speed
https://github.com/tsar-boomba/megalo
backend deno http openapi server typescript
Last synced: about 3 hours ago
JSON representation
Deno HTTP server framework focused on speed
- Host: GitHub
- URL: https://github.com/tsar-boomba/megalo
- Owner: tsar-boomba
- License: mit
- Created: 2022-09-08T20:25:12.000Z (about 2 years ago)
- Default Branch: main
- Last Pushed: 2022-10-06T14:08:19.000Z (about 2 years ago)
- Last Synced: 2024-10-17T18:13:34.270Z (29 days ago)
- Topics: backend, deno, http, openapi, server, typescript
- Language: TypeScript
- Homepage: https://deno.land/x/megalo
- Size: 56.6 KB
- Stars: 14
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# Megalo
Deno HTTP server framework aiming for maximum speed
## Example
```ts
// server.ts
import { Controller, Megalo } from 'https://deno.land/x/megalo/mod.ts';
import { cors } from 'https://deno.land/x/megalo/plugins/cors.ts';const megalo = new Megalo({
// optionally add a notFoundHandler
notFoundHandler: (req, res) => res.status(404).body(`${req.pathname} not found :(`),
// optionally add an errorHandler
errorHandler: (_err, _req, res, httpErr) => {
// if NotFoundError, etc. was thrown
if (httpErr) return res.status(httpErr.status).body(httpErr.message);
res.status(500).body('Internal Server Error');
},
plugins: [cors({ origin: 'http://127.0.0.1:9000' })],
});megalo
.get('/', { parseQuery: false }, (_req, res) => {
res.body('hello megalo!', {
status: 200,
headers: { ['Content-Type']: 'text/html' },
});
})
.post('/', (_req, res) => {
res.body('Secret handler', { status: 200 });
})
.get('/sus', (_req, res) => {
res.body('sus page', {
status: 200,
headers: { ['Content-Type']: 'text/html' },
});
})
.get(/^\/regex(\/.*)?$/, (_req, res) => res.body(undefined, { status: 200 }))
.get('/pattern/:id', ({ params }, res) => {
res.body(`id: ${params.id}`, {
status: 200,
headers: { ['Content-Type']: 'text/html' },
});
})
.post('/posted', (_req, res) => {
res.body('you posted it :)', { status: 200 });
})
.controller(
new Controller('/users')
.get('/', (_req, res) => res.body('user', { status: 200 }))
.get('/:id', (req, res) => res.body(`user id: ${req.params.id}`, { status: 200 }))
);console.log(`Startup time: ${performance.now()}ms`);
megalo.listen({ port: 9000, hostname: '127.0.0.1' });
```### Start Server
Use `--allow-hrtime` for more precise `performance.now()`
```bash
deno run --allow-net --allow-hrtime --unstable server.ts
```## Benchmarks
[HTTP server benchmarks](https://github.com/denosaurs/bench#readme)
## Route resolution
Routes are resolved in this order
- string literal ex. `"/sus"`
- controllers ex. `new Controller("/users")`
- patterns ex. `"/users/:id"`
- regex ex. `/^.*\/regex\/.*\/?$/`
- wildcard (You can only have one of these per method) `"*"`
- notFoundHandler## Hooks
You can use hooks to run functions when certain lifecycle events occur. Hooks
can be used on the Megalo instance or Controller instance.- preRoute: runs before pathname is evaluated and handler is chosen
- preHandle: runs directly before handler
- postHandle: runs directly after handler (may change in the future)The megalo instance has some exclusive hooks
- preParse: runs before anything is done, right when request is received
- preSend: run directly before response is sent to client, last chance to add
headers or whateverThis is an example on how to use hooks. If you return the res from the hook it
will be sent early.```ts
import { ForbiddenError, Megalo } from 'https://deno.land/x/megalo/mod.ts';const megalo = new Megalo();
megalo
.addHook('preRoute', (req, res) => {
// note that all pathname will never have trailing slash, even if url does
if (req.pathname === '/return-early') return res;
if (req.pathname === '/forbidden') throw new ForbiddenError('not okay >:(');
})
.get((req, res) => {
res.status(200);
});megalo.listen({ port: 9000, hostname: '127.0.0.1' });
```## Error Throwing
You can throw special exported errors to have the response status and body
automatically set.```ts
import { InternalServerError, Megalo } from 'https://deno.land/x/megalo/mod.ts';const megalo = new Megalo();
megalo.get((req) => {
throw new InternalServerError({ message: 'uh oh' });
res.status(200);
});megalo.listen({ port: 9000, hostname: '127.0.0.1' });
```## OpenAPI Support
Megalo now has support for defining OpenAPI Documentation in your code. check out `openApiExample.ts` for a small example of using it. You can check out the [example deployment](https://tsar-boomba-megalo.deno.dev/swagger).
## Notes
If using serve / flash instead of listen, until
https://github.com/denoland/deno/issues/15813 is resolved, in all POST, PUT, and
PATCH routes you MUST await the body or else deno will panic.