New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add simple sub routing system #74

bubulemaster opened this Issue May 8, 2017 · 4 comments


None yet
4 participants
Copy link

bubulemaster commented May 8, 2017

Hi all,

if you want use both createStaticHandler and createRpcHandler with shelf_io.serve(), you cannot do this natively.

I purpose to create a PR to add this method in shelf_io.dart to do this easly.

import 'package:shelf/shelf.dart';
import 'dart:core';

/// Creates a Shelf [Handler] that allow to register some Shelf [Handler] like
/// [createStaticHandler] or [createRpcHandler] on same listener.
/// Just give map [routing] to link [key] that represent path to [value] that
/// contain handler.
/// The path [key] is only static path.
Handler createSubHandler(Map<String, Handler> routing) {
  return (Request request) {
    // Selected path
    String selectedPath = '';

    routing.forEach((key, value) {
      String currentPath = '/' + request.url.path;

      if (currentPath.startsWith(key)
        && currentPath.length > selectedPath.length) {
        selectedPath = key;

    Handler h = routing[selectedPath];

    if (h == null) {
      return new Response.notFound('Not Found');
    } else {
      Uri requestUri = request.requestedUri;

      Uri newRequestedUri = new Uri(
        scheme: requestUri.scheme,
        userInfo: requestUri.userInfo,
        // Getter return empty string if host is null
        host: == 0 ? null :,
        port: requestUri.port,
        path: requestUri.path.substring(selectedPath.length - 1),
        query: requestUri.query,
        queryParameters: requestUri.queryParameters,
        fragment: requestUri.fragment);

      Uri url = request.url;

      Uri newUrl = new Uri(
        scheme: url.scheme,
        userInfo: url.userInfo,
        // Getter return empty string if host is null
        host: == 0 ? null :,
        port: url.port,
        path: url.path.substring(selectedPath.length - 1),
        query: url.query,
        queryParameters: url.queryParameters,
        fragment: url.fragment);

      Request newRequest = new Request(request.method, newRequestedUri,
        protocolVersion: request.protocolVersion,
        headers: request.headers,
        handlerPath: request.handlerPath,
        url: newUrl,
        body: request.readAsString().asStream(),
        encoding: request.encoding,
        context: request.context,
        onHijack: request.hijack);

      return h(newRequest);

Its use like:

// Create a Shelf handler for your RPC API.
var handlerApi = shelf_rpc.createRpcHandler(apiServer);
// Create a Shelf handler for static file
var handlerStatic = shelf_static.createStaticHandler('example/files', defaultDocument: 'index.html');

var handler = shelf_io.createSubHandler({
  '/': handlerStatic,
  '/api/': handlerApi,
  '/api/toto/': otherHandler

Do you think is good feature ?

Have you any suggestion about this ?



This comment has been minimized.

Copy link

nex3 commented May 16, 2017

I'd really like to keep routing out of shelf core. There's a lot of room for different, valid opinions about routing, which suggests to me that we shouldn't declare a "canonical" version in shelf itself—shelf is explicitly intended as a foundation on which other packages can be built, not a batteries-included server framework.

@nex3 nex3 closed this May 16, 2017


This comment has been minimized.

Copy link

bubulemaster commented May 17, 2017

Ok, thanks for your reply


This comment has been minimized.

Copy link

MarkOSullivan94 commented Feb 6, 2019

Curious if anyone has a recommendation for routing which is compatible with Dart 2.x?

I noticed there was both shelf_route and shelf_rest but both haven't been updated to support Dart 2.x


This comment has been minimized.

Copy link

kevmoo commented Feb 7, 2019

If you're keen @MarkOSullivan94 , I'd suggest taking the best of those options and create your own. Once you've validated it for your needs, consider publishing it for others!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment