From 737461c59443e0bc423bc59e793215f06377607c Mon Sep 17 00:00:00 2001 From: Matt Sturgeon Date: Wed, 19 Jul 2017 00:31:31 +0100 Subject: [PATCH] Fix serving files that clash with directories Jekyll extends WEBrick to serve file.html if file is requested but doesn't exist (see #3452). This doesn't work if file exists as a directory though. This commit extends WEBrick further so that if file exists as a directory, we first try and serve file/index.html (as normal), but fallback to file.html if no index can be found within the file directory (reported as #6222). It is slightly hacky, to avoid having to re-implement the entire set_filename method, we instead extend search_index_file and mutate res.filename, reverting the change if it isn't needed. See base class search_index_file implementation: https://github.com/ruby/webrick/blob/3fb6a011/lib/webrick/httpservlet/filehandler.rb#L356-L363 --- lib/jekyll/commands/serve/servlet.rb | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/lib/jekyll/commands/serve/servlet.rb b/lib/jekyll/commands/serve/servlet.rb index 3ae5cf32367..d53ee0f0060 100644 --- a/lib/jekyll/commands/serve/servlet.rb +++ b/lib/jekyll/commands/serve/servlet.rb @@ -21,10 +21,36 @@ def initialize(server, root, callbacks) # up with a different preference on which comes first. def search_file(req, res, basename) - # /file.* > /file/index.html > /file.html + # /file.* -> /file.html super || super(req, res, "#{basename}.html") end + def search_index_file(req, res) + # /file/index.html -> /file.html + + # First, let's see if the our super method can figure it out. + # (i.e Check for index.html files in the res.filename directory) + file = super + + unless file + # Ok, I guess that didn't work, I guess there's no basename/index.html + # Let's look for basename.html instead... + + # Split the basename from the path (res.filename) + i = res.filename.rindex "\/" + basename = res.filename[i..-1] + res.filename = res.filename[0, i] + + # Try and find a file named dirname.html in the parent directory. + file = search_file(req, res, basename + ".html") + + # If we didn't find a file, revert our changes to res.filename. + res.filename << basename unless file + end + + return file + end + # rubocop:disable Style/MethodName def do_GET(req, res) rtn = super