1616module Rackup
1717 module Handler
1818 class WEBrick < ::WEBrick ::HTTPServlet ::AbstractServlet
19+ # A WEBrick HTTPServer subclass that invokes the Rack app directly,
20+ # bypassing the mount table and default OPTIONS * handling.
21+ class Server < ::WEBrick ::HTTPServer
22+ def initialize ( app , config )
23+ super ( config )
24+ @handler = Handler ::WEBrick . new ( self , app )
25+ end
26+
27+ def service ( req , res )
28+ @handler . service ( req , res )
29+ end
30+ end
31+
1932 def self . run ( app , **options )
2033 environment = ENV [ 'RACK_ENV' ] || 'development'
2134 default_host = environment == 'development' ? 'localhost' : nil
@@ -28,8 +41,7 @@ def self.run(app, **options)
2841 require 'webrick/https'
2942 end
3043
31- @server = ::WEBrick ::HTTPServer . new ( options )
32- @server . mount "/" , Rackup ::Handler ::WEBrick , app
44+ @server = Server . new ( app , options )
3345 yield @server if block_given?
3446 @server . start
3547 end
@@ -102,11 +114,25 @@ def service(req, res)
102114 )
103115
104116 env [ ::Rack ::QUERY_STRING ] ||= ""
105- unless env [ ::Rack ::PATH_INFO ] == ""
106- path , n = req . request_uri . path , env [ ::Rack ::SCRIPT_NAME ] . length
107- env [ ::Rack ::PATH_INFO ] = path [ n , path . length - n ]
117+
118+ # Handle OPTIONS * requests which have no path
119+ if req . unparsed_uri == "*"
120+ env [ ::Rack ::PATH_INFO ] = "*"
121+ env [ ::Rack ::REQUEST_PATH ] = "*"
122+
123+ # Ensure SERVER_NAME and SERVER_PORT are set from server config
124+ # (WEBrick allows these to be nil for OPTIONS * requests)
125+ # See https://github.com/ruby/webrick/pull/182 for a proper fix.
126+ env [ ::Rack ::SERVER_NAME ] ||= @server [ :ServerName ] || @server [ :BindAddress ] || "localhost"
127+ env [ ::Rack ::SERVER_PORT ] ||= ( @server [ :Port ] || 80 ) . to_s
128+ else
129+ unless env [ ::Rack ::PATH_INFO ] == ""
130+ # Strip the script name prefix from the path to get path info
131+ script_name_length = env [ ::Rack ::SCRIPT_NAME ] . length
132+ env [ ::Rack ::PATH_INFO ] = req . request_uri . path [ script_name_length ..-1 ] || ""
133+ end
134+ env [ ::Rack ::REQUEST_PATH ] ||= env [ ::Rack ::SCRIPT_NAME ] + env [ ::Rack ::PATH_INFO ]
108135 end
109- env [ ::Rack ::REQUEST_PATH ] ||= [ env [ ::Rack ::SCRIPT_NAME ] , env [ ::Rack ::PATH_INFO ] ] . join
110136
111137 status , headers , body = @app . call ( env )
112138 begin
0 commit comments