Skip to content

Shelf dynamic routes without the need to use mounts #485

@guibbv2011

Description

@guibbv2011

davidmartos96
jonasfj

If this separation of routes and dynamic routes is possible to do with vanilla shelf and router (no codegen) I would love to see it in action.

I build a package to "solve" this issue (https://pub.dev/packages/shelf_dynamic_forwarder)
https://github.com/guibbv2011/shelf_dynamic_forwarder

I don't use the mount function instead I call directly:

  return await handler!(subReq);

This will link the child router defined in map dynamicRoutes.

Here a example usage:

import 'dart:io';
import 'package:shelf/shelf.dart';
import 'package:shelf/shelf_io.dart';
import 'package:shelf_dynamic_forwarder/shelf_dynamic_forwarder.dart';
import 'package:shelf_router/shelf_router.dart';

Router get filenamesRequest {
  final handler = Router();
  handler.get('/filenames', (Request req) async {
    // Your logic code here..
    return Response.ok('');
  });
  return handler;
}

Router get fileRequest {
  final handler = Router();
  handler.get('/file', (Request req) async {
    // Your logic code here..
    return Response.ok('');
  });
  return handler;
}

final Map<String, Handler> dynamicRoutes = {
  'filenames': filenamesRequest,
  '.*': fileRequest,
};

Handler get router {
  final dynamicRouter = createDynamicRouter(
    routePattern: '/api/<adminId>/<index>/<path|.*>',
    routes: dynamicRoutes,
  );
  return dynamicRouter;
}

void main() async {
  final handler = 
    const Pipeline().addMiddleware(logRequests()).addHandler(router);
  await serve(handler, 'localhost', 8080);
}

And how I implemented it:

    // Create a new ABSOLUTE URI for the child router.
    // This isolates the child from the parent's base path and ensures the URI is absolute.
    final originalUri = request.requestedUri;

    final newUri = originalUri.replace(
      // Explicitly retain scheme, host, and port for absolute URI
      // Reset the path to only what the child router expects (e.g., /filenames)
      // pathSegments must be an Iterable<String>
      pathSegments: [pathSegment],
    );

    // 4. Create a brand new Request object using the new absolute URI.
    final subReq = Request(
      request.method,
      newUri,
      headers: newHeaders,
      body: await request.read(),
      context: request.context,
    );
}

Originally posted by @guibbv2011 in #288 (comment)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions