# Protevus Shelf ![Pub Version (including pre-releases)](https://img.shields.io/pub/v/protevus_shelf?include_prereleases) [![Null Safety](https://img.shields.io/badge/null-safety-brightgreen)](https://dart.dev/null-safety) [![Discord](https://img.shields.io/discord/1060322353214660698)](https://discord.gg/3X6bxTUdCM) [![License](https://img.shields.io/github/license/dart-backend/belatuk-common-utilities)](https://github.com/dart-backend/protevus/tree/master/packages/shelf/LICENSE) **Replacement of `package:angel_shelf` with breaking changes to support NNBD.** Shelf interop with Protevus. This package lets you run `package:shelf` handlers via a custom adapter. Use the code in this repo to embed existing Protevus/shelf apps into other Protevus/shelf applications. This way, you can migrate legacy applications without having to rewrite your business logic. This will make it easy to layer your API over a production application, rather than having to port code. - [Protevus Shelf](#protevus-shelf) - [Usage](#usage) - [embedShelf](#embedshelf) - [Communicating with Protevus with embedShelf](#communicating-with-protevus-with-embedshelf) - [ProtevusShelf](#angelshelf) ## Usage ### embedShelf This is a compliant `shelf` adapter that acts as an Protevus request handler. You can use it as a middleware, or attach it to individual routes. ```dart import 'dart:io'; import 'package:protevus_framework/protevus_framework.dart'; import 'package:protevus_shelf/protevus_shelf.dart'; import 'package:shelf/shelf.dart' as shelf; import 'api/api.dart'; void main() async { var app = Protevus(); var http = ProtevusHttp(app); // Protevus routes on top await app.mountController(); // Re-route all other traffic to an // existing application. app.fallback(embedShelf( shelf.Pipeline() .addMiddleware(shelf.logRequests()) .addHandler(_echoRequest) )); // Or, only on a specific route: app.get('/shelf', wrappedShelfHandler); await http.startServer(InternetAddress.loopbackIPV4, 3000); print(http.uri); } ``` ### Communicating with Protevus with embedShelf You can communicate with Protevus: ```dart handleRequest(shelf.Request request) { // Access original Protevus request... var req = request.context['angel_shelf.request'] as RequestContext; // ... And then interact with it. req.container.registerNamedSingleton('from_shelf', Foo()); // `req.container` is also available. var container = request.context['angel_shelf.container'] as Container; container.make().drive(); } ``` ### ProtevusShelf Protevus brought about the generic `Driver` class, which is implemented by `ProtevusHttp`, `ProtevusHttp2`, `ProtevusGopher`, etc., and provides the core infrastructure for request handling in Protevus. `ProtevusShelf` is an implementation that wraps shelf requests and responses in their Protevus equivalents. Using it is as simple using as using `ProtevusHttp`, or any other driver: ```dart // Create an ProtevusShelf driver. // If we have startup hooks we want to run, we need to call // `startServer`. Otherwise, it can be omitted. // Of course, if you call `startServer`, know that to run // shutdown/cleanup logic, you need to call `close` eventually, // too. var angelShelf = ProtevusShelf(app); await angelShelf.startServer(); await shelf_io.serve(angelShelf.handler, InternetAddress.loopbackIPv4, 8081); ``` You can also use the `ProtevusShelf` driver as a shelf middleware - just use `angelShelf.middleware` instead of `angelShelf.handler`. When used as a middleware, if the Protevus response context is still open after all handlers run (i.e. no routes were matched), the next shelf handler will be called. ```dart var handler = shelf.Pipeline() .addMiddleware(angelShelf.middleware) .addHandler(createStaticHandler(...)); ```