Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • Home
  • SEARCH
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 3318510
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 17, 20262026-05-17T22:42:51+00:00 2026-05-17T22:42:51+00:00

1 The following is more to point out to the code devs an issue

  • 0

1 The following is more to point out to the code devs an issue of rails that can be percieved as a flaw.
2 And also me asking some oppinions from people who know better.

I want to add WebDAV to my Rails 3 App with Warden authentication. My warden middleware is injected via Devise.

http://github.com/chrisroberts/dav4rack
http://github.com/hassox/warden
http://github.com/plataformatec/devise

I cannot mount DAV4Rack handlers from inside rails app (routes), like this:

# in config/routes.rb
mount DAV4Rack::Handler.new(
  :root => Rails.root.to_s, # <= it's just an example
  :root_uri_path => '/webdav',
  :resource_class => Dav::DocumentResource # <= my custom resource, you could use FileResource from dav4rack
), :at => "/webdav"

because rails validates HTTP verbs (GET POST PUT ..), and webdav uses HTTP extensions like PROPFIND that do not validate, throwing the following exception:

ActionController::UnknownHttpMethod (PROPFIND, accepted HTTP methods are get, head, put, post, delete, and options)

This validation takes place in ActionDispatch:

/usr/local/lib/ruby/gems/1.9.1/gems/actionpack-3.0.0/lib/action_dispatch/http/request.rb +56 +72
in (56) "def request_method" and (72) "def method"

Sample code from ActionDispatch that does the validation, to make things clear:

def method
  @method ||= begin
    method = env["rack.methodoverride.original_method"] || env['REQUEST_METHOD']
    HTTP_METHOD_LOOKUP[method] || raise(ActionController::UnknownHttpMethod, "#{method}, accepted HTTP methods are #{HTTP_METHODS.to_sentence(:locale => :en)}")
    method
  end
end

In theory, we could monkey-patch this validation to comply with webdav verbs like the railsdav project used to do (note that is rails 2 there, in rails 3 one needs to monkey-patch action_dispatch/http/request).

To add DAV4Rack handlers to the rails app I have to mount the handler outside of ActionDispatch, at rack level, like this:

# config.ru
require ::File.expand_path('../config/environment',  __FILE__)
require 'dav4rack/interceptor'
require 'dav/document_resource'

app = Rack::Builder.new{
  map '/webdav/' do
    run DAV4Rack::Handler.new(
      :root => Rails.root.to_s,
      :root_uri_path => '/webdav',
      :resource_class => Dav::DocumentResource
    )
  end

  map '/' do
    use DAV4Rack::Interceptor, :mappings => {
      '/webdav/' => {
        :resource_class => Dav::DocumentResource
      },
    }
    run Pmp::Application
  end
}.to_app
run app

Now I have Webdav support in my application. But It still needs authentication, and for that I’d like to use warden.

# in document_resource.rb
def check_authentication
  puts request.env['warden'] # nil :(
end

Warden is nil because my DAV4Rack::Handler is mounted above the session and warden middleware.
Using “rake middleware” to inspect my stack I can see the following:

> rake middleware 
use ActionDispatch::Static
use Rack::Lock
use ActiveSupport::Cache::Strategy::LocalCache
use Rack::Runtime
use Rails::Rack::Logger
use ActionDispatch::ShowExceptions
use ActionDispatch::RemoteIp
use Rack::Sendfile
use ActionDispatch::Callbacks
use ActiveRecord::ConnectionAdapters::ConnectionManagement
use ActiveRecord::QueryCache
use ActionDispatch::Cookies
use ActionDispatch::Session::CookieStore
use ActionDispatch::Flash
use ActionDispatch::ParamsParser
use Rack::MethodOverride
use ActionDispatch::Head
use ActionDispatch::BestStandardsSupport
use Warden::Manager
run Pmp::Application.routes

I believe that by wrapping “Pmp::Application.routes” with DAV handler (just like I do above for “Pmp::Application” in config.ru) will inject my webdav handler in the stack at the right place to satisfy the two conditions:

  1. Be above ActionDispatch method validation code, to avoid ActionController::UnknownHttpMethod
  2. Be below session and Warden::Manager so I can use warden authentication.

How to do that? Looking at “rake middleware” otput it seems obvious to override the “Pmp::Application.routes” method:

# in my app at APP_ROOT/config/application.rb
# override the routes method inherited from Rails::Application#routes
def routes
  routes_app = super
  app = Rack::Builder.new {
    map '/webdav/' do
      run DAV4Rack::Handler.new(
        :root => Rails.root.to_s,
        :root_uri_path => '/webdav',
        :resource_class => Dav::DocumentResource
      )
    end

    map '/' do
      use DAV4Rack::Interceptor, :mappings => {
        '/webdav/' => {
          :resource_class => Dav::DocumentResource
        },
      }
      run routes_app
    end
  }.to_app

  class << app; self end.class_eval do
    attr_accessor :routes_app
    def method_missing(sym, *args, &block)
      routes_app.send sym, *args, &block
    end
  end
  app.routes_app = routes_app

  app
end

Because our new rack application “app” will be asked a few methods down the chain, that the old rack application “routes_app” used to resopnd to, we delegate theese to the old original application “routes_app” with a little method_missing magic.

And voila: everything is working!
Great success.

Only one problem: I don’t like it. There must be a better way to do all this enveloping, other than overriding routes method.

Note that this doesn’t work with passenger. The best way seems to be monkey patching rails.
See: dav4rack wiki

THE BIG QUESTION:

IS THERE A BETTER WAY TO ADD A RACK APP JUST ABOVE THE “Pmp::Application#routes” APP BY MEANS OF RACK MOUNT OR OTHER ???

THE BIG CONCLUSION

  1. The “mount” semantics in routes.rb should be rack-level (not rails/railtie/whatever), to allow, in this way, handeling of HTTP extensions, or at least have a method for this case “mount_rack”
  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-05-17T22:42:52+00:00Added an answer on May 17, 2026 at 10:42 pm

    And we have a winner.
    https://rails.lighthouseapp.com/projects/8994/tickets/5895-allow-mounting-of-rack-apps-that-deal-with-http-extensions

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

I like that in PHP I can do the following $myInteger++; $myString += 'more
I have roughly the following code. Could this be made nicer or more efficient?
Myself and a colleague have a dispute about which of the following is more
Would there a more elegant way of writing the following syntax? Thread t0 =
I have the following tables in MySQL: team: id, name, [more stuff] person: id,
I need to solve the following question which i can't get to work by
I'm doing some changes on my routes, and suddenly the following is appearing in
Following on from my recent question on Large, Complex Objects as a Web Service
Following my question regarding a .NET YAML Library ... as there doesn't seem to
Following this question: Good crash reporting library in c# Is there any library like

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.