Repository: getpelican/pelican

Issue:
Allow nice URLs on devserver
When you publish the website is quite easy to implement nice URLs. For example an nginx configuraiton like this would provide you with nice URLs for your website:

```
index index.php index.html index.htm index.shtml;
root /var/www/example.com/public_html;
try_files $uri $uri.html $uri/index.html index.html;
```

Now the problem is tha the devserver does not have the save behaviour, and so far I am now aware of any way to configure it to do this.

```
/output/index.html              http://localhost:8000
/output/contact.html              http://localhost:8000/contact
/output/sales/index.html              http://localhost:8000/sales
/output/sales/index.html              http://localhost:8000/sales/    (yes the same) 
```



Discussion:
The "devserver" is just a wrapper around `python -m SimpleHTTPServer`, which as the name suggests is a very simple web server that does not have all the rewriting features of `nginx`. The best solution here is to install and configure `nginx` locally to match the server-side configuration.

You can do something similar in Pelican itself, instead of using your webserver to deal with redirects. Instead on my sites I have saved everything to index.html and use the "url" to point to the pretty urls. That way the server doesn't need to be modified.

``` python
# Pages

PAGE_URL = '{slug}'
PAGE_SAVE_AS = '{slug}/index.html'

# Blog

BLOG_URL = 'blog/'
BLOG_INDEX_SAVE_AS = 'blog/index.html'

ARTICLE_DIR = 'blog'
ARTICLE_URL = 'blog/{slug}/'
ARTICLE_SAVE_AS = 'blog/{slug}/index.html'

TAGS_SAVE_AS = 'blog/tags/index.html'

TAG_URL = 'blog/tags/{slug}/'
TAG_SAVE_AS = 'blog/tags/{slug}/index.html'

CATEGORY_URL = 'blog/category/{slug}/'
CATEGORY_SAVE_AS = 'blog/category/{slug}/index.html'

AUTHOR_URL = 'blog/authors/{slug}/'
AUTHOR_SAVE_AS = 'blog/authors/{slug}/index.html'

ARCHIVES_SAVE_AS = 'blog/archvives/index.html'
```

I was considering this alternative bug I didn't like the idea of having a new directory for each page, just to trick the server to use the URLs.

BTW, I investigated the SimpleHTTPServer server a little bit and now I know that I can easily implement what I want. It seems that in few hours we will have a new feature: ability to serve nice URLs. That's much better than nginx, running nginx on my dev machine si not so easy as you may think.


Resolving patch:
diff --git a/pelican/server.py b/pelican/server.py
--- a/pelican/server.py
+++ b/pelican/server.py
@@ -1,5 +1,7 @@
 from __future__ import print_function
+import os
 import sys
+import logging
 try:
     import SimpleHTTPServer as srvmod
 except ImportError:
@@ -11,19 +13,36 @@
     import socketserver  # NOQA
 
 PORT = len(sys.argv) == 2 and int(sys.argv[1]) or 8000
+SUFFIXES = ['','.html','/index.html']
 
-Handler = srvmod.SimpleHTTPRequestHandler
+class ComplexHTTPRequestHandler(srvmod.SimpleHTTPRequestHandler):
+    def do_GET(self):
+        # we are trying to detect the file by having a fallback mechanism
+        r = None
+        for suffix in SUFFIXES:
+            if not hasattr(self,'original_path'):
+                self.original_path = self.path
+            self.path = self.original_path + suffix
+            path = self.translate_path(self.path)
+            if os.path.exists(path):
+                r = srvmod.SimpleHTTPRequestHandler.do_GET(self)
+            if r is not None:
+                break
+            logging.warning("Unable to find %s file." % self.path)
+        return r
+
+Handler = ComplexHTTPRequestHandler
 
 try:
     httpd = socketserver.TCPServer(("", PORT), Handler)
 except OSError as e:
-    print("Could not listen on port", PORT)
+    logging.error("Could not listen on port %s" % PORT)
     sys.exit(getattr(e, 'exitcode', 1))
 
 
-print("serving at port", PORT)
+logging.info("serving at port %s" % PORT)
 try:
     httpd.serve_forever()
 except KeyboardInterrupt as e:
-    print("shutting down server")
-    httpd.socket.close()
+    logging.info("shutting down server")
+    httpd.socket.close()
\ No newline at end of file


Test patch: