Skip to content

iyifr/h4

Repository files navigation

H4.

og

A HTTP framework for productive and fun API development with dart.

Inspired by unjs H3.

This is a new project under active development, production use is not advised.

The docs site is still in construction🚧🚧 - link

Features

  • Lightweight: H4 ships with a small core and a set of composable utilities.
  • Middleware: H4 comes with onRequest and onError middleware.
  • Generic Handlers: Specify the return type of your handler functions.

Getting Started

Add H4 to your pubspec.yaml:

dependencies:
  h4: ^1.0.0

Or install with dart pub get

dart pub add h4

Import the library and start building your server:

import 'package:h4/create.dart';

void main() {
 var app = createApp();
 var router = createRouter();

 app.use(router);

 router.get("/", (event) => "Hello world!");
}

Examples

Hello world

void main() {
  var app = createApp(port: 4000);
  var router = createRouter();

  app.use(router);

  router.get("/", (event) => "Hello world")
}

Generic handlers

Specify the return type of your handlers

router.get<bool>("/25/**", (event) => true);

Global Hooks

You can register global hooks:

  • onRequest
  • onError
  • afterResponse

These hooks are called for every request and can be used to add global logic to your app such as logging, error handling, etc.

 var app = createApp(
   port: 5173,
   onRequest: (event) => {},
   onError: (error, stacktrace, event) => {},
   afterResponse: (event) => {},
 );
 var router = createRouter();
 app.use(router);

Error Handling

You can throw a create error Exception that will terminate the request and send a 400 - Bad Request response

router.get('/error', (event) async {
 try {
  // Code that could fail.
 }
 catch(e) {
   throw CreateError(message: 'Womp Womp', errorCode: 400);
 }
});

The client recieves this json payload -

{
 "status": 400,
 "message": "Womp Womp"
}

Param Routing

You can define parameters in your routes using : prefix:

router.get('/users/:id', (event) {
 final userId = event.params['id'];
 return 'User $userId'
});

Wildcard Routing

// Matches 'articles/page' and '/articles/otherPage' but not 'articles/page/otherPage'
router.get('/articles/*', (event) {
 final path = event.path;
 return 'The tea is teaing!!'
});
// Matches 'articles/foo/bar' and 'articles/rice/eba/beans'
router.get('/articles/**', (event) {
 final path = event.path;
 return 'The tea is teaing!!'
});

Utilities

A set of composable utilities that help you add functionality to your server

readRequestBody

Reads the request body as json or text depending on the contentType of the request body.

router.post("/vamos", (event) async {
 var body = await readRequestBody(event);
 return body;
});

getHeader

Get the value of any of the incoming request headers. For convenience you can use the HTTPHeaders utility to get header strings.

router.post("/vamos", (event) async {
 var header = getHeader(event, HttpHeaders.userAgentHeader);
 return body;
});

Contributing

A good first PR would be helping me improve the test coverage of this library, or adding one of the utilities listed here.

Running tests

In the root directory run

dart test

Code of Conduct.

Show respect and consideration for others when creating issues and contributing to the library. Only good vibes!