dart-archive / shelf_static

archived repo
https://github.com/dart-lang/shelf/tree/master/pkgs/shelf_static
BSD 3-Clause "New" or "Revised" License
24 stars 24 forks source link

Default document for directory does not work when using shelf_route #9

Closed jonaskello closed 9 years ago

jonaskello commented 9 years ago
import 'package:shelf/shelf.dart' as shelf;
import 'package:shelf/shelf_io.dart' as io;
import 'package:shelf_route/shelf_route.dart' as route;
import 'package:shelf_static/shelf_static.dart' as static;

void main() {

  var staticHandler = static.createStaticHandler('static_content', defaultDocument: 'index.html');
  final routerHandler = (
      route.router()
        ..get('/foo', staticHandler)
        ..get('/', _echoRequest)
  ).handler;

  io.serve(routerHandler, '0.0.0.0', 8080).then((server) {
    print('Serving at http://${server.address.host}:${server.port}');
  });

}

shelf.Response _echoRequest(shelf.Request request) {
  return new shelf.Response.ok('Request for "${request.url}"');
}

Run this and goto:

http://localhost:8080/foo/

Produces:

Internal Server Error

In console:

ERROR - 2014-11-17 09:58:22.921
Error thrown by handler.
'package:shelf_static/src/static_handler.dart': Failed assertion: line 73 pos 14: '!uri.path.endsWith('/')' is not true.
package:shelf_static/src/static_handler.dart 73:14  createStaticHandler.<fn>
package:shelf_route/shelf_route.dart 136:19         _Route.handle
package:shelf_route/shelf_route.dart 100:24         _handleRequest
dart:isolate                                        _RawReceivePortImpl._handleMessage

Expected to return "index.html" for /foo and run _echoRequest for other URLS.

kevmoo commented 9 years ago

First, I'm not seeing the error any more. I am seeing a redirect loop, though.

This actually looks like a bug in shelf_route.

shelf_static redirects requests to '/foo' to '/foo/' which is by design.

But shelf_route should be sending that trailing slash in its routing logic.

Redirected to https://bitbucket.org/andersmholmgren/shelf_route/issue/18/fix-routing-of-paths-ending-in

Andersmholmgren commented 9 years ago

This fails because, by default, terminal routes like get must match the entire remaining path.

Currently, methods like get do not expose the exactMatch named parameter, so you need to use the slightly more verbose add method

import 'package:shelf/shelf.dart' as shelf;
import 'package:shelf/shelf_io.dart' as io;
import 'package:shelf_route/shelf_route.dart' as route;
import 'package:shelf_static/shelf_static.dart' as static;

void main() {

  var staticHandler = static.createStaticHandler('static_content', defaultDocument: 'index.html');
  final routerHandler = (
      route.router()
        ..add('/foo', ['GET'], staticHandler, exactMatch: false)
        ..get('/', _echoRequest)
  ).handler;

  io.serve(routerHandler, '0.0.0.0', 8080).then((server) {
    print('Serving at http://${server.address.host}:${server.port}');
  });

}

shelf.Response _echoRequest(shelf.Request request) {
  return new shelf.Response.ok('Request for "${request.url}"');
}

Note: this is even simpler to set up in mojito

import 'package:mojito/mojito.dart';

main() {
  final app = init();

  app.router.addStaticAssetHandler('foo', fileSystemPath: 'static_content');

  app.start(port: 8080);
}

with the added benefit that it will by default use pub serve in dev mode

kevmoo commented 9 years ago

@Andersmholmgren help me here. Do you still want something fixed?

Andersmholmgren commented 9 years ago

No I was just leaving an explanation for why the original example didn't work in case others stumble on this in the future. The problem was with how the static route was defined. My comment showed how to define it correctly