ruby-grape / ruby-grape/grape

Broken middleware behaviour for reused endpoints

Open
#1,613 5 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

bug?
Dominant language
Ruby
Stars
10k
Forks
1.2k
Avg merge
14h 38m
Merged PRs (30d)
92

Description

require 'grape'

class Endpoint < Grape::API
  format :txt

  get(:e) { 'Endpoint was called' }
end

class Middleware
  def initialize(app)
    @app = app
  end

  def call(env)
    @app.call(env).tap do |r|
      r.write(' and middleware too')
    end
  end
end

class Protected < Grape::API
  use Middleware

  mount Endpoint
end

class Routes
  def initialize
    @app = Rack::Builder.app do
      map('/n') { run Class.new(Grape::API) { mount Endpoint } }
      map('/o') { run Endpoint }
      map('/p') { run Protected }
    end.freeze
  end

  def call(env)
    @app.call(env)
  end
end

run Routes.new
$  curl localhost:9292/p/e  
Endpoint was called  

$  curl localhost:9292/o/e    
Endpoint was called     

$  curl localhost:9292/n/e    
Endpoint was called

Expected behaviour:
Middleware would run in endpoint mounted to /p/e.
Actual behaviour:
Middleware don't get executed at all.

If I comment out /n/e mapping:

require 'grape'

class Endpoint < Grape::API
  format :txt

  get(:e) { 'Endpoint was called' }
end

class Middleware
  def initialize(app)
    @app = app
  end

  def call(env)
    @app.call(env).tap do |r|
      r.write(' and middleware too')
    end
  end
end

class Protected < Grape::API
  use Middleware

  mount Endpoint
end

class Routes
  def initialize
    @app = Rack::Builder.app do
#     map('/n') { run Class.new(Grape::API) { mount Endpoint } }
      map('/o') { run Endpoint }
      map('/p') { run Protected }
    end.freeze
  end

  def call(env)
    @app.call(env)
  end
end

run Routes.new
$  curl localhost:9292/o/e
Endpoint was called and middleware too
$  curl localhost:9292/p/e
Endpoint was called and middleware too

Expected behaviour:
Middleware would run in endpoint mounted to /p/e.
Actual behaviour:
Middleware is affecting mapping where it should not get executed.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by running the provided Ruby reproduction with the three Rack::Builder mappings and compare middleware behavior for /n/e, /o/e, and /p/e. Trace how mounted Grape endpoints and middleware are assembled, then verify that middleware runs for /p/e without affecting the other mappings.

Written by the indexing model from the issue text.

Assessment

Tech stack
ruby
Domain
api, backend
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Clearly specified
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.