dox_http_native

Native HTTP/1.1 server for Dart. It is the default HTTP server of Dox.

pub package license: MIT

Part of Dox, a web backend framework for Dart, like Laravel. Source code: github.com/dartondox/dox.

Install

You usually do not add this package. dox_core depends on it and uses it by default. Add it only to use the server without Dox:

dart pub add dox_http_native

Dox 3.x is in alpha (3.0.0-alpha.4). The API can still change before the stable release.

How it works

  • Rust (hyper) owns the sockets and parses HTTP/1.1.
  • Your handlers stay in Dart.
  • It implements the dart:io HttpServer, HttpRequest and HttpResponse API. Code written for dart:io works unchanged.

The native library

A build hook (hook/build.dart) gets the Rust library. It tries these in order:

  1. A path you set in your app pubspec.yaml (hooks: user_defines: dox_http_native: lib_path: ...).
  2. A ready-built library from the GitHub release, checked with sha256. There are builds for macOS (arm64, x64), Linux (x64, arm64) and Windows (x64).
  3. A build from source with cargo, when Rust is installed.

So on these systems you do not need Rust. Use dart run, dart test or dart build cli. dart compile exe does not run build hooks.

Use it

import 'dart:io';

import 'package:dox_http_native/dox_http_native.dart';

void main() async {
  NativeHttpServer server = await NativeHttpServer.bind(3000);
  server.listen((HttpRequest req) {
    req.response.write('Hello World');
    req.response.close();
  });
}

Turn it off in Dox

  • Set server: ServerBackend.dartIo in AppConfig.
  • Or set the env var DOX_SERVER=dartio. The env var wins over the config.

Dox also uses dart:io by itself when the native library does not load, and when the app has WebSocket or Socket.IO routes.

Features

  • Each isolate can bind the same port (SO_REUSEPORT on Linux, one shared socket on macOS).
  • Each isolate has its own Rust network thread. DOX_HTTP_THREAD=shared puts them on one thread.
  • 400 for bad requests, 431 for headers over 16 KB, 413 for bodies over maxBodySize.
  • bind(port, address: '127.0.0.1') listens on one host. With no address it listens on all interfaces.
  • close() is graceful: no new connections, open requests get their answer, then it completes. close(force: true) closes every connection at once.
  • Not yet: WebSocket upgrade (detachSocket).
  • Not yet: streaming a response while it is written. The body is sent on close.

Documentation

License

MIT. See LICENSE.

Libraries

dox_http_native
Native HTTP/1.1 server for Dart. Rust (hyper) owns the sockets and parses HTTP. Your handlers stay in Dart and use the dart:io API.