Class: Mongrel::DirHandler
- Inherits:
-
HttpHandler
- Object
- HttpHandler
- Mongrel::DirHandler
- Defined in:
- lib/mongrel.rb
Overview
Serves the contents of a directory. You give it the path to the root where the files are located, and it tries to find the files based on the PATH_INFO inside the directory. If the requested path is a directory then it returns a simple directory listing.
It does a simple protection against going outside it’s root path by converting all paths to an absolute expanded path, and then making sure that the final expanded path includes the root path. If it doesn’t than it simply gives a 404.
Constant Summary collapse
- MIME_TYPES =
{ ".css" => "text/css", ".gif" => "image/gif", ".htm" => "text/html", ".html" => "text/html", ".jpeg" => "image/jpeg", ".jpg" => "image/jpeg", ".js" => "text/javascript", ".png" => "image/png", ".swf" => "application/x-shockwave-flash", ".txt" => "text/plain" }
Instance Attribute Summary collapse
-
#path ⇒ Object
readonly
Returns the value of attribute path.
Class Method Summary collapse
-
.add_mime_type(extension, type) ⇒ Object
There is a small number of default mime types for extensions, but this lets you add any others you’ll need when serving content.
Instance Method Summary collapse
-
#can_serve(path_info) ⇒ Object
Checks if the given path can be served and returns the full path (or nil if not).
-
#initialize(path, listing_allowed = true, index_html = "index.html") ⇒ DirHandler
constructor
You give it the path to the directory root and an (optional).
-
#process(request, response) ⇒ Object
Process the request to either serve a file or a directory listing if allowed (based on the listing_allowed paramter to the constructor).
-
#send_dir_listing(base, dir, response) ⇒ Object
Returns a simplistic directory listing if they’re enabled, otherwise a 403.
-
#send_file(req, response) ⇒ Object
Sends the contents of a file back to the user.
Constructor Details
#initialize(path, listing_allowed = true, index_html = "index.html") ⇒ DirHandler
You give it the path to the directory root and an (optional)
470 471 472 473 474 |
# File 'lib/mongrel.rb', line 470 def initialize(path, listing_allowed=true, index_html="index.html") @path = File.(path) @listing_allowed=listing_allowed @index_html = index_html end |
Instance Attribute Details
#path ⇒ Object (readonly)
Returns the value of attribute path.
467 468 469 |
# File 'lib/mongrel.rb', line 467 def path @path end |
Class Method Details
.add_mime_type(extension, type) ⇒ Object
There is a small number of default mime types for extensions, but this lets you add any others you’ll need when serving content.
585 586 587 |
# File 'lib/mongrel.rb', line 585 def DirHandler::add_mime_type(extension, type) MIME_TYPES[extension] = type end |
Instance Method Details
#can_serve(path_info) ⇒ Object
Checks if the given path can be served and returns the full path (or nil if not).
477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 |
# File 'lib/mongrel.rb', line 477 def can_serve(path_info) req = File.(File.join(@path,path_info), @path) if req.index(@path) == 0 and File.exist? req # it exists and it's in the right location if File.directory? req # the request is for a directory index = File.join(req, @index_html) if File.exist? index # serve the index return index elsif @listing_allows # serve the directory req else # do not serve anything return nil end else # it's a file and it's there return req end else # does not exist or isn't in the right spot return nil end end |
#process(request, response) ⇒ Object
Process the request to either serve a file or a directory listing if allowed (based on the listing_allowed paramter to the constructor).
559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 |
# File 'lib/mongrel.rb', line 559 def process(request, response) req = can_serve request.params['PATH_INFO'] if not req # not found, return a 404 response.start(404) do |head,out| out << "File not found" end else begin if File.directory? req send_dir_listing(request.params["REQUEST_URI"],req, response) else send_file(req, response) end rescue => details response.reset response.start(403) do |head,out| out << "Error accessing file: #{details}" out << details.backtrace.join("\n") end end end end |
#send_dir_listing(base, dir, response) ⇒ Object
Returns a simplistic directory listing if they’re enabled, otherwise a 403. Base is the base URI from the REQUEST_URI, dir is the directory to serve on the file system (comes from can_serve()), and response is the HttpResponse object to send the results on.
510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 |
# File 'lib/mongrel.rb', line 510 def send_dir_listing(base, dir, response) # take off any trailing / so the links come out right base.chop! if base[-1] == "/"[-1] if @listing_allowed response.start(200) do |head,out| head['Content-Type'] = "text/html" out << "<html><head><title>Directory Listing</title></head><body>" Dir.entries(dir).each do |child| next if child == "." if child == ".." out << "<a href=\"#{base}/#{child}\">Up to parent..</a><br/>" else out << "<a href=\"#{base}/#{child}\">#{child}</a><br/>" end end out << "</body></html>" end else response.start(403) do |head,out| out.write("Directory listings not allowed") end end end |
#send_file(req, response) ⇒ Object
Sends the contents of a file back to the user. Not terribly efficient since it’s opening and closing the file for each read.
539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 |
# File 'lib/mongrel.rb', line 539 def send_file(req, response) response.start(200) do |head,out| # set the mime type from our map based on the ending dot_at = req.rindex(".") if dot_at ext = req[dot_at .. -1] if MIME_TYPES[ext] head['Content-Type'] = MIME_TYPES[ext] end end open(req, "rb") do |f| out.write(f.read) end end end |