blog: fix local mode to serve css and js correctly

Clearly the main server had run ahead of the local one.
The local one was expecting requests to say /static/,
which they do not, and there are also requests from
two different static file locations, not just one.

Now when you run the local blog server you see all
the styling of the blog site instead of unstyled HTML.

Also update README.md.

Change-Id: Ia662419339cd7546f0611f1b896c343902a018d5
Reviewed-on: https://go-review.googlesource.com/c/155019
Run-TryBot: Russ Cox <rsc@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
diff --git a/README.md b/README.md
index 3305877..363f6db 100644
--- a/README.md
+++ b/README.md
@@ -11,8 +11,8 @@
 
 To run the blog server locally:
 
-```sh
-dev_appserver.py app.yaml
+```
+go build && ./blog -reload
 ```
 
 and then visit [http://localhost:8080/](http://localhost:8080) in your browser.
diff --git a/local.go b/local.go
index 676acb5..e95dfea 100644
--- a/local.go
+++ b/local.go
@@ -13,6 +13,10 @@
 	"log"
 	"net"
 	"net/http"
+	"os"
+	"os/exec"
+	"path/filepath"
+	"strings"
 
 	"golang.org/x/tools/blog"
 )
@@ -22,22 +26,56 @@
 	contentPath  = flag.String("content", "content/", "path to content files")
 	templatePath = flag.String("template", "template/", "path to template files")
 	staticPath   = flag.String("static", "static/", "path to static files")
+	godocPath    = flag.String("godoc", defaultGodocPath(), "path to lib/godoc static files")
 	reload       = flag.Bool("reload", false, "reload content on each page load")
 )
 
+func defaultGodocPath() string {
+	out, err := exec.Command("go", "list", "-f", "{{.Dir}}", "golang.org/x/tools/godoc").CombinedOutput()
+	if err != nil {
+		log.Printf("warning: locating -godoc directory: %v", err)
+		return ""
+	}
+	dir := strings.TrimSpace(string(out))
+	return filepath.Join(dir, "static")
+}
+
+// maybeStatic serves from one of the two static directories
+// (-static and -godoc) if possible, or else defers to the fallback handler.
+func maybeStatic(fallback http.Handler) http.HandlerFunc {
+	return func(w http.ResponseWriter, r *http.Request) {
+		p := r.URL.Path
+		if strings.Contains(p, ".") && !strings.HasSuffix(p, "/") {
+			f := filepath.Join(*staticPath, p)
+			if _, err := os.Stat(f); err == nil {
+				http.ServeFile(w, r, f)
+				return
+			}
+		}
+		if strings.HasPrefix(p, "/lib/godoc/") {
+			f := filepath.Join(*godocPath, p[len("/lib/godoc/"):])
+			if _, err := os.Stat(f); err == nil {
+				http.ServeFile(w, r, f)
+				return
+			}
+		}
+		fallback.ServeHTTP(w, r)
+	}
+}
+
 func newServer(reload bool, staticPath string, config blog.Config) (http.Handler, error) {
 	mux := http.NewServeMux()
+	var h http.Handler
 	if reload {
-		mux.HandleFunc("/", reloadingBlogServer)
+		h = http.HandlerFunc(reloadingBlogServer)
 	} else {
 		s, err := blog.NewServer(config)
 		if err != nil {
 			return nil, err
 		}
-		mux.Handle("/", s)
+		h = s
 	}
-	fs := http.FileServer(http.Dir(staticPath))
-	mux.Handle("/static/", http.StripPrefix("/static/", fs))
+	mux.Handle("/", maybeStatic(h))
 	return mux, nil
 }