shelf_plus 0.0.1 copy "shelf_plus: ^0.0.1" to clipboard
shelf_plus: ^0.0.1 copied to clipboard

outdated

Shelf Plus is a quality of life addon for your server-side development within the Shelf platform.

Shelf Plus #

Shelf Plus is a quality of life addon for your server-side development within the Shelf platform. It's a great base to start off your apps fast, while maintaining full compatibility with the Shelf ecosystem.

import 'package:shelf_plus/shelf_plus.dart';

void main() => shelfRun(init);

Handler init() {
  var app = Router().plus;

  app.get('/', () => 'Hello World!');

  return app;
}

It comes with a lot of awesome features, like zero-configuration initializer, build-in hot-reload and a super powerful and intuitive router upgrade. Continue reading and get to know why you can't ever code without Shelf Plus.

Router Plus #

Router Plus is a high-level abstraction layer sitting directly on shelf_router. It shares the same routing logic but allows you to handle responses in a very simple way.

var app = Router().plus;

app.use(middleware());

app.get('/text', () => 'I am a text');

app.get(
    '/html/<name>', (Request request, String name) => '<h1>Hello $name</h1>',
    use: typeByExtension('html'));

app.get('/file', () => File('path/to/file.zip'));

app.get('/person', () => Person(name: 'John', age: 42));

The core mechanic is called ResponseHandler which continuously refines a data structure, until it resolves in a Shelf Response. This extensible system comes with support for text, json, binaries, files, json serialization and Shelf Handler.

You can access the Router Plus by calling the .plus getter on a regular Shelf Router.

var app = Router().plus;

Routes API #

The API mimics the Shelf Router methods. You basically use an HTTP verb, define a route to match and specify a handler, that generates the response.

app.get('/path/to/match', () => 'a response');

You can return any type, as long the ResponseHandler mechanism has a capable resolver to handle that type.

If you need the Shelf Request object, specify it as the first parameter. Any other parameter will match the route parameters, if defined.

app.get('/minimalistic', () => 'response');

app.get('/with/request', (Request request) => 'response');

app.get('/clients/<id>', (Request request, String id) => 'response: $id');

app.get('/customer/<id>', (Request request) {
  // alternative access to route parameters
  return 'response: ${request.routeParameter('id')}';
});

Middleware #

Router Plus provides several options to place your middleware (Shelf Middleware).

var app = Router().plus;

app.use(middlewareA); // apply to all routes

// apply to a single route
app.get('/request1', () => 'response', use: middlewareB);

// combine middleware with + operator
app.get('/request2', () => 'response', use: middlewareB + middlewareC);

You can also apply middleware dynamically inside a route handler, using the >> operator.

app.get('/request/<value>', (Request request, String value) {
  return middleware(value) >> 'response';
});

ResponseHandler #

ResponseHandler process the return value of a route handler, until it matches a Shelf Response.

Build-in ResponseHandler

Source Result Use case
String Shelf Response Respond with a text (text/plain)
Uint8List, Stream<List<int>> Shelf Response Respond with binary (application/octet-stream)
Map<String, dynamic>, List<dynamic>> Shelf Response Respond with JSON (application/json)
Any Type having a toJson() method Map<String, dynamic>, List<dynamic>> (expected) Provide serialization support for classes
Shelf Handler Shelf Response Processing Shelf-based Middleware or Handler
File (dart:io) Shelf Response Respond with file contents (using shelf_static)

Example:

import 'dart:io';

import 'package:shelf_plus/shelf_plus.dart';

void main() => shelfRun(init);

Handler init() {
  var app = Router().plus;

  app.get('/text', () => 'a text');

  app.get('/binary', () => File('data.zip').openRead());

  app.get('/json', () => {'name': 'John', 'age': 42});

  app.get('/class', () => Person('Theo'));

  app.get('/handler', () => typeByExtension('html') >> '<h1>Hello</h1>');

  app.get('/file', () => File('thesis.pdf'));

  return app;
}

class Person {
  final String name;

  Person(this.name);

  // can be generated by tools (i.e. json_serializable package)
  Map<String, dynamic> toJson() => {'name': name};
}

Custom ResponseHandler

You can add your own ResponseHandler by using a Shelf Middleware created with the .middleware getter on a ResponseHandler function.

// define custom ResponseHandler
ResponseHandler catResponseHandler = (Request request, dynamic maybeCat) =>
    maybeCat is Cat ? maybeCat.interact() : null;

// register custom ResponseHandler as middleware
app.use(catResponseHandler.middleware);

app.get('/cat', () => Cat());
class Cat {
  String interact() => 'Purrrrr!';
}

Cascading multiple routers #

Router Plus is compatible to a Shelf Handler. So, you can also use it in a Shelf Cascade. This package provides a cascade() function, to quickly set up a cascade.

import 'package:shelf_plus/shelf_plus.dart';

void main() => shelfRun(init);

Handler init() {
  var app1 = Router().plus;
  var app2 = Router().plus;

  app1.get('/maybe', () => Response.notFound('no idea'));

  app2.get('/maybe', () => 'got it!');

  return cascade([app1, app2]);
}

Middleware collection #

This package comes with additional Shelf Middleware to simplify common tasks.

setContentType #

Sets the content-type header of a Response to the specified mime-type.

app.get('/one', () => setContentType('application/json') >> '1');

app.get('/two', () => '2', use: setContentType('application/json'));

typeByExtension #

Sets the content-type header of a Response to the mime-type of the specified file extension.

app.get('/', () => '<h1>Hi!</h1>', use: typeByExtension('html'));

download #

Sets the content-disposition header of a Response, so browsers will download the server response instead of displaying it. Optionally you can define a specific file name.

app.get('/wallpaper/download', () => File('image.jpg'), use: download());

app.get('/invoice/<id>', (Request request, String id) {
  File document = pdfService.generateInvoice(id);
  return download(filename: 'invoid_$id') >> document;
});

Shelf Run #

Shelf Run is zero-configuration web-server initializer with hot-reload support.

import 'package:shelf_plus/shelf_plus.dart';

void main() => shelfRun(init);

Handler init() {
  return (Request request) => Response.ok('Hello!');
}

It's important to use a dedicated init function, returning a Shelf Handler, for hot-reload to work properly.

Shelf Run uses a default configuration, that can be modified via environment variables:

Environment variable Default value Description
SHELF_PORT 8080 Port to bind the shelf application to
SHELF_ADDRESS localhost Address to bind the shelf application to
SHELF_HOTRELOAD true Enable hot-reload
92
likes
0
pub points
89%
popularity

Publisher

verified publisherfelix-blaschke.de

Shelf Plus is a quality of life addon for your server-side development within the Shelf platform.

Repository (GitHub)
View/report issues

License

unknown (LICENSE)

Dependencies

mime_type, shelf, shelf_hotreload, shelf_router, shelf_static, supercharged_dart

More

Packages that depend on shelf_plus