hanami/router

Per-slice middleware not being applied correctly?

pat opened this issue · 3 comments

pat commented

This is kinda two issues in one - I'm trying to reproduce the one I'm seeing in my app, but I've found another while doing that, so…

The reproducible error first:

  • I have an app with slices
  • Slices have their own routes
  • I configure HTTP Auth in the slice's config (see below), it has no impact at all (a bug?).
  • But if I configure HTTP Auth within the slice's routes file, it does work (as expected)
# config/slices/closed.rb
module Closed
  class Slice < Hanami::Slice
    config.middleware.use Rack::Auth::Basic do |username, password|
      username == "admin" && password == "secret"
    end
  end
end

# slices/closed/config/routes.rb
module Closed
  class Routes < Hanami::Routes
    root { "Super-secret" }
  end
end

# config/routes.rb
module MyApp
  class Routes < Hanami::Routes
    root { "Hello from Default Hanami" }

    slice :closed, at: "/closed"
  end
end

And when requesting with no auth credentials:

$ curl -i http://127.0.0.1:9292/closed

HTTP/1.1 200 OK
Content-Length: 12

Super-secret

The error in my own app is a touch more complex - I've been using Roda, and so have been migrating slices over to hanami-router/hanami-controller one at a time. The first slice was a single endpoint, public-facing, easy. The second is an API, has HTTP auth… and setting that HTTP auth up in the slice config (rather than routes file), had the undesired side-effect of enforced HTTP auth for the first slice as well. 😓

Within the Roda app, I'm routing those as follows (in case the context is useful for figuring out what might be the cause):

route do |r|
  # ...
  
  r.on "second" do
    r.run Second::Slice.rack_app.tap(&:freeze)
  end

  r.on "first" do
    r.run First::Slice.rack_app.tap(&:freeze)
  end

  # ...
end

Not sure I'll have further time to debug this in the near future, but figure it's worth reporting nonetheless!

@pat Why not:

# config/routes.rb
module MyApp
  class Routes < Hanami::Routes
    root { "Hello from Default Hanami" }

    slice :closed, at: "/closed" do
      use Rack::Auth::Basic do |username, password|
        username == "admin" && password == "secret"
      end
    end
  end
end
pat commented

@jodosha thanks for the response :) I haven't yet have time to test that approach, but it'd be nice if each slice could maintain its own middleware concerns, rather than having them all sit in the app's routes.

@pat Roger that.

I manually tested the following approach. It works successfully:

config/routes.rb

module MyApp
  class Routes < Hanami::Routes
    root { "Hello from Default Hanami" }

    slice :closed, at: "/closed"
  end
end

slices/closed/config/routes.rb

# frozen_string_literal: true

require "rack/auth/basic"

module Closed
  class Routes < Hanami::Routes
    use Rack::Auth::Basic do |username, password|
      username == "admin" && password == "secret"
    end

    root { "Super-secret" }
  end
end

The slice file can be removed.