Pistos
Pistos

Reputation: 23792

Rack: mapping more complex routes

Consider the following subsection of config.ru:

run Rack::URLMap.new(                                                                                                                      
  "/" => Ramaze,                                                                                                                           
  "/apixxx" => MyGrapeAPI.new                                                                                                                            
)

This works. (Notice the xxx suffix). Every request going to /apixxx/* goes to the Grape API endpoints, and everything else is served by the Ramaze app. (Ramaze is built on Rack.)

However, what I really want to do is map /api not /apixxx. BUT, the Ramaze app happens to have endpoints under /api/v1/*. What I want is to have every request under /api that is NOT under /api/v1 to go the Grape API (e.g. /api/somethingelse), and every /api/v1/* request to go to Ramaze.

I have tried using Regexps instead of Strings in the URLMap, but that doesn't work. I've tried combinations of URLMap and Rack::Cascade, and have had no success.

Optimally, if I could use Regexps to map, or if I could use a block of code to map, I'd be off to the races.

Upvotes: 0

Views: 437

Answers (2)

Pistos
Pistos

Reputation: 23792

Here is what I ended up using, thanks to the tip from @rekado .

# config.ru

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

  def call(env)
    request = Rack::Request.new(env)
    # Version 1 of the API was served from Ramaze, but the API has since been
    # moved out of Ramaze.
    if request.path =~ %r{/api/(?!v1)}
      # Have the Grape API handle the request
      env_without_api_prefix = env.dup
      ['REQUEST_PATH', 'PATH_INFO', 'REQUEST_URI'].each do |key|
        env_without_api_prefix[key] = env_without_api_prefix[key].gsub(%r{^/api}, '')
      end

      TheGrapeAPI.new.call(env_without_api_prefix)
    else
      # Let Ramaze handle the request
      @app.call(env)
    end
  end
end

use APIRoutingAdapter

run Ramaze

Upvotes: 0

user519736
user519736

Reputation:

It might work to use middleware that performs the check against a regular expression, as outlined here: https://stackoverflow.com/a/3070083/519736

Upvotes: 1

Related Questions