shelf_essentials

license dart

Essential utilities for building HTTP servers with shelf.

shelf_essentials provides commonly needed extensions and helpers for:

  • Reading request bodies
  • Parsing JSON requests
  • Handling multipart form data
  • Working with HTTP methods safely

Designed to be lightweight, idiomatic, and shelf-native.


Features

  • 🔌 Request extensions for body, JSON, and form data
  • 📦 Multipart form parsing with fields & files
  • 🧭 Type-safe HTTP method enum
  • 🧱 Zero framework lock-in
  • ⚡ Minimal dependencies

Installation

Add this to your pubspec.yaml:

dependencies:
  shelf_essentials: ^1.0.0

Then run:

dart pub get

Usage

Import

import 'package:shelf_essentials/shelf_essentials.dart';

Request Extensions

Read Request Body

final body = await request.body();

Parse JSON Body

final data = await request.json();

print(data['email']);

The returned value can be a Map, List, String, num, or bool.


Access HTTP Method Safely

switch (request.httpMethod) {
  case HttpMethod.get:
    return Response.ok('GET request');
  case HttpMethod.post:
    return Response.ok('POST request');
  default:
    return Response.notFound('Unsupported method');
}

Form Data Handling

Parse Multipart Form Data

final form = await request.formData();

Access Fields

final username = form.fields['username'];
final email = form.fields['email'];

Access Uploaded Files

final avatar = form.files['avatar'];

if (avatar != null) {
  final bytes = await avatar.readAsBytes();
  print('Uploaded file: ${avatar.name}');
}

UploadedFile

Each uploaded file provides:

final name = file.name;
final contentType = file.contentType;
final bytes = await file.readAsBytes();

⚠️ Note:
File streams are single-use. Call either readAsBytes() or openRead() once.


API Overview

RequestExtension

Method Description
body() Reads request body as String
json() Parses body as JSON
formData() Parses multipart form data
httpMethod Type-safe HTTP method
connectionInfo Socket connection info

HttpMethod

enum HttpMethod {
  get,
  post,
  put,
  patch,
  delete,
  options,
  head,
}

FormData

form.fields   // Map<String, String>
form.files    // Map<String, UploadedFile>

FormData is immutable by design.


Example Shelf Server

import 'package:shelf/shelf.dart';
import 'package:shelf/shelf_io.dart';
import 'package:shelf_essentials/shelf_essentials.dart';

void main() async {
  final handler = (Request request) async {
    if (request.httpMethod == HttpMethod.post) {
      final data = await request.json();
      return Response.ok('Hello ${data['name']}');
    }
    return Response.ok('Send a POST request');
  };

  await serve(handler, 'localhost', 8080);
  print('Server running on http://localhost:8080');
}

Design Goals

  • ✅ Minimal surface area
  • ✅ Idiomatic Dart
  • ✅ Shelf-first
  • ✅ No hidden magic
  • ✅ Easy to extend

Roadmap

  • Content-Type validation helpers
  • Typed JSON parsing utilities
  • Streaming file size helpers
  • Improved error handling
  • Middleware utilities

Contributing

Contributions are welcome!

  • Open an issue for bugs or feature requests
  • Submit a PR with clear description and tests
  • Keep APIs simple and shelf-compatible

License

MIT License © 2025
Use it freely in open-source and commercial projects.


Acknowledgements

  • Inspired by the simplicity of the shelf package
  • Special thanks to dart-frog

Libraries

shelf_essentials