diff options
author | Andrew Gerrand <adg@golang.org> | 2013-10-08 11:14:35 +1100 |
---|---|---|
committer | Andrew Gerrand <adg@golang.org> | 2013-10-08 11:14:35 +1100 |
commit | fe9861ee213c456e935e9d1b36817a5de4235f90 (patch) | |
tree | 5fa9d16eea464109ac69c56bc03800539f7821e8 /doc | |
parent | 63cb24068229b07d6286c8a0fa9358c9c9be4783 (diff) | |
download | go-fe9861ee213c456e935e9d1b36817a5de4235f90.tar.gz |
doc/articles/wiki: fix path handling and clean up test process
Fixes issue 6525.
R=r
CC=golang-dev
https://codereview.appspot.com/14383043
Diffstat (limited to 'doc')
-rw-r--r-- | doc/articles/wiki/Makefile | 12 | ||||
-rw-r--r-- | doc/articles/wiki/final-noclosure.go | 14 | ||||
-rw-r--r-- | doc/articles/wiki/final-noerror.go | 6 | ||||
-rw-r--r-- | doc/articles/wiki/final-parsetemplate.go | 10 | ||||
-rw-r--r-- | doc/articles/wiki/final-template.go | 8 | ||||
-rw-r--r-- | doc/articles/wiki/final.go | 10 | ||||
-rw-r--r-- | doc/articles/wiki/htmlify.go | 16 | ||||
-rw-r--r-- | doc/articles/wiki/index.html | 28 | ||||
-rw-r--r-- | doc/articles/wiki/notemplate.go | 6 | ||||
-rw-r--r-- | doc/articles/wiki/part2.go | 4 | ||||
-rw-r--r-- | doc/articles/wiki/part3-errorhandling.go | 8 | ||||
-rw-r--r-- | doc/articles/wiki/part3.go | 6 | ||||
-rw-r--r-- | doc/articles/wiki/srcextract.go | 76 | ||||
-rwxr-xr-x | doc/articles/wiki/test.bash | 9 |
14 files changed, 51 insertions, 162 deletions
diff --git a/doc/articles/wiki/Makefile b/doc/articles/wiki/Makefile index 0cb907185..e40b1311e 100644 --- a/doc/articles/wiki/Makefile +++ b/doc/articles/wiki/Makefile @@ -4,17 +4,7 @@ all: index.html -CLEANFILES:=srcextract.bin htmlify.bin get.bin - -index.html: wiki.html srcextract.bin htmlify.bin - PATH=.:$$PATH awk '/^!/{system(substr($$0,2)); next} {print}' < wiki.html | tr -d '\r' > index.html - -test: get.bin - bash ./test.sh - rm -f get.6 get.bin - -%.bin: %.go - go build -o $@ $^ +CLEANFILES:=get.bin final-test.bin a.out clean: rm -f $(CLEANFILES) diff --git a/doc/articles/wiki/final-noclosure.go b/doc/articles/wiki/final-noclosure.go index a23cf7a27..d72ca805b 100644 --- a/doc/articles/wiki/final-noclosure.go +++ b/doc/articles/wiki/final-noclosure.go @@ -83,17 +83,15 @@ func renderTemplate(w http.ResponseWriter, tmpl string, p *Page) { } } -const lenPath = len("/view/") +var validPath = regexp.MustCompile("^/(edit|save|view)/([a-zA-Z0-9]+)$") -var titleValidator = regexp.MustCompile("^[a-zA-Z0-9]+$") - -func getTitle(w http.ResponseWriter, r *http.Request) (title string, err error) { - title = r.URL.Path[lenPath:] - if !titleValidator.MatchString(title) { +func getTitle(w http.ResponseWriter, r *http.Request) (string, error) { + m := validPath.FindStringSubmatch(r.URL.Path) + if m == nil { http.NotFound(w, r) - err = errors.New("Invalid Page Title") + return "", errors.New("Invalid Page Title") } - return + return m[2], nil // The title is the second subexpression. } func main() { diff --git a/doc/articles/wiki/final-noerror.go b/doc/articles/wiki/final-noerror.go index e11d268e2..86d8da751 100644 --- a/doc/articles/wiki/final-noerror.go +++ b/doc/articles/wiki/final-noerror.go @@ -29,10 +29,8 @@ func loadPage(title string) (*Page, error) { return &Page{Title: title, Body: body}, nil } -const lenPath = len("/view/") - func editHandler(w http.ResponseWriter, r *http.Request) { - title := r.URL.Path[lenPath:] + title := r.URL.Path[len("/edit/"):] p, err := loadPage(title) if err != nil { p = &Page{Title: title} @@ -42,7 +40,7 @@ func editHandler(w http.ResponseWriter, r *http.Request) { } func viewHandler(w http.ResponseWriter, r *http.Request) { - title := r.URL.Path[lenPath:] + title := r.URL.Path[len("/view/"):] p, _ := loadPage(title) t, _ := template.ParseFiles("view.html") t.Execute(w, p) diff --git a/doc/articles/wiki/final-parsetemplate.go b/doc/articles/wiki/final-parsetemplate.go index 6234c08f2..5ff8bf60c 100644 --- a/doc/articles/wiki/final-parsetemplate.go +++ b/doc/articles/wiki/final-parsetemplate.go @@ -70,18 +70,16 @@ func renderTemplate(w http.ResponseWriter, tmpl string, p *Page) { } } -const lenPath = len("/view/") - -var titleValidator = regexp.MustCompile("^[a-zA-Z0-9]+$") +var validPath = regexp.MustCompile("^/(edit|save|view)/([a-zA-Z0-9]+)$") func makeHandler(fn func(http.ResponseWriter, *http.Request, string)) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { - title := r.URL.Path[lenPath:] - if !titleValidator.MatchString(title) { + m := validPath.FindStringSubmatch(r.URL.Path) + if m == nil { http.NotFound(w, r) return } - fn(w, r, title) + fn(w, r, m[2]) } } diff --git a/doc/articles/wiki/final-template.go b/doc/articles/wiki/final-template.go index f295b9d60..719157da9 100644 --- a/doc/articles/wiki/final-template.go +++ b/doc/articles/wiki/final-template.go @@ -29,10 +29,8 @@ func loadPage(title string) (*Page, error) { return &Page{Title: title, Body: body}, nil } -const lenPath = len("/view/") - func editHandler(w http.ResponseWriter, r *http.Request) { - title := r.URL.Path[lenPath:] + title := r.URL.Path[len("/edit/"):] p, err := loadPage(title) if err != nil { p = &Page{Title: title} @@ -41,13 +39,13 @@ func editHandler(w http.ResponseWriter, r *http.Request) { } func viewHandler(w http.ResponseWriter, r *http.Request) { - title := r.URL.Path[lenPath:] + title := r.URL.Path[len("/view/"):] p, _ := loadPage(title) renderTemplate(w, "view", p) } func saveHandler(w http.ResponseWriter, r *http.Request) { - title := r.URL.Path[lenPath:] + title := r.URL.Path[len("/save/"):] body := r.FormValue("body") p := &Page{Title: title, Body: []byte(body)} p.save() diff --git a/doc/articles/wiki/final.go b/doc/articles/wiki/final.go index e93cdee47..f15794d66 100644 --- a/doc/articles/wiki/final.go +++ b/doc/articles/wiki/final.go @@ -67,18 +67,16 @@ func renderTemplate(w http.ResponseWriter, tmpl string, p *Page) { } } -const lenPath = len("/view/") - -var titleValidator = regexp.MustCompile("^[a-zA-Z0-9]+$") +var validPath = regexp.MustCompile("^/(edit|save|view)/([a-zA-Z0-9]+)$") func makeHandler(fn func(http.ResponseWriter, *http.Request, string)) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { - title := r.URL.Path[lenPath:] - if !titleValidator.MatchString(title) { + m := validPath.FindStringSubmatch(r.URL.Path) + if m == nil { http.NotFound(w, r) return } - fn(w, r, title) + fn(w, r, m[2]) } } diff --git a/doc/articles/wiki/htmlify.go b/doc/articles/wiki/htmlify.go deleted file mode 100644 index 2a845a174..000000000 --- a/doc/articles/wiki/htmlify.go +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright 2010 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package main - -import ( - "io/ioutil" - "os" - "text/template" -) - -func main() { - b, _ := ioutil.ReadAll(os.Stdin) - template.HTMLEscape(os.Stdout, b) -} diff --git a/doc/articles/wiki/index.html b/doc/articles/wiki/index.html index f57857a7f..7bf7213e8 100644 --- a/doc/articles/wiki/index.html +++ b/doc/articles/wiki/index.html @@ -260,18 +260,15 @@ Let's create a handler, <code>viewHandler</code> that will allow users to view a wiki page. It will handle URLs prefixed with "/view/". </p> -{{code "doc/articles/wiki/part2.go" `/^const lenPath/`}} - {{code "doc/articles/wiki/part2.go" `/^func viewHandler/` `/^}/`}} <p> First, this function extracts the page title from <code>r.URL.Path</code>, -the path component of the request URL. The global constant -<code>lenPath</code> is the length of the leading <code>"/view/"</code> -component of the request path. -The <code>Path</code> is re-sliced with <code>[lenPath:]</code> to drop the -first 6 characters of the string. This is because the path will invariably -begin with <code>"/view/"</code>, which is not part of the page's title. +the path component of the request URL. +The <code>Path</code> is re-sliced with <code>[len("/view/"):]</code> to drop +the leading <code>"/view/"</code> component of the request path. +This is because the path will invariably begin with <code>"/view/"</code>, +which is not part of the page's title. </p> <p> @@ -431,6 +428,11 @@ to its own function: </p> {{code "doc/articles/wiki/final-template.go" `/^func renderTemplate/` `/^}/`}} + +<p> +And modify the handlers to use that function: +</p> + {{code "doc/articles/wiki/final-template.go" `/^func viewHandler/` `/^}/`}} {{code "doc/articles/wiki/final-template.go" `/^func editHandler/` `/^}/`}} @@ -573,10 +575,11 @@ this, we can write a function to validate the title with a regular expression. <p> First, add <code>"regexp"</code> to the <code>import</code> list. -Then we can create a global variable to store our validation regexp: +Then we can create a global variable to store our validation +expression: </p> -{{code "doc/articles/wiki/final-noclosure.go" `/^var titleValidator/`}} +{{code "doc/articles/wiki/final-noclosure.go" `/^var validPath/`}} <p> The function <code>regexp.MustCompile</code> will parse and compile the @@ -587,9 +590,8 @@ an <code>error</code> as a second parameter. </p> <p> -Now, let's write a function, <code>getTitle</code>, that extracts the title -string from the request URL, and tests it against our -<code>TitleValidator</code> expression: +Now, let's write a function that uses the <code>validPath</code> +expression to validate path and extract the page title: </p> {{code "doc/articles/wiki/final-noclosure.go" `/func getTitle/` `/^}/`}} diff --git a/doc/articles/wiki/notemplate.go b/doc/articles/wiki/notemplate.go index 33006ac95..be214d111 100644 --- a/doc/articles/wiki/notemplate.go +++ b/doc/articles/wiki/notemplate.go @@ -29,16 +29,14 @@ func loadPage(title string) (*Page, error) { return &Page{Title: title, Body: body}, nil } -const lenPath = len("/view/") - func viewHandler(w http.ResponseWriter, r *http.Request) { - title := r.URL.Path[lenPath:] + title := r.URL.Path[len("/view/"):] p, _ := loadPage(title) fmt.Fprintf(w, "<h1>%s</h1><div>%s</div>", p.Title, p.Body) } func editHandler(w http.ResponseWriter, r *http.Request) { - title := r.URL.Path[lenPath:] + title := r.URL.Path[len("/edit/"):] p, err := loadPage(title) if err != nil { p = &Page{Title: title} diff --git a/doc/articles/wiki/part2.go b/doc/articles/wiki/part2.go index dd4365c82..c0231693e 100644 --- a/doc/articles/wiki/part2.go +++ b/doc/articles/wiki/part2.go @@ -29,10 +29,8 @@ func loadPage(title string) (*Page, error) { return &Page{Title: title, Body: body}, nil } -const lenPath = len("/view/") - func viewHandler(w http.ResponseWriter, r *http.Request) { - title := r.URL.Path[lenPath:] + title := r.URL.Path[len("/view/"):] p, _ := loadPage(title) fmt.Fprintf(w, "<h1>%s</h1><div>%s</div>", p.Title, p.Body) } diff --git a/doc/articles/wiki/part3-errorhandling.go b/doc/articles/wiki/part3-errorhandling.go index 945aa1e39..bb4ecda84 100644 --- a/doc/articles/wiki/part3-errorhandling.go +++ b/doc/articles/wiki/part3-errorhandling.go @@ -29,15 +29,13 @@ func loadPage(title string) (*Page, error) { return &Page{Title: title, Body: body}, nil } -const lenPath = len("/view/") - func renderTemplate(w http.ResponseWriter, tmpl string, p *Page) { t, _ := template.ParseFiles(tmpl + ".html") t.Execute(w, p) } func viewHandler(w http.ResponseWriter, r *http.Request) { - title := r.URL.Path[lenPath:] + title := r.URL.Path[len("/view/"):] p, err := loadPage(title) if err != nil { http.Redirect(w, r, "/edit/"+title, http.StatusFound) @@ -47,7 +45,7 @@ func viewHandler(w http.ResponseWriter, r *http.Request) { } func editHandler(w http.ResponseWriter, r *http.Request) { - title := r.URL.Path[lenPath:] + title := r.URL.Path[len("/edit/"):] p, err := loadPage(title) if err != nil { p = &Page{Title: title} @@ -56,7 +54,7 @@ func editHandler(w http.ResponseWriter, r *http.Request) { } func saveHandler(w http.ResponseWriter, r *http.Request) { - title := r.URL.Path[lenPath:] + title := r.URL.Path[len("/save/"):] body := r.FormValue("body") p := &Page{Title: title, Body: []byte(body)} err := p.save() diff --git a/doc/articles/wiki/part3.go b/doc/articles/wiki/part3.go index 7fe4351af..174f3abcd 100644 --- a/doc/articles/wiki/part3.go +++ b/doc/articles/wiki/part3.go @@ -29,21 +29,19 @@ func loadPage(title string) (*Page, error) { return &Page{Title: title, Body: body}, nil } -const lenPath = len("/view/") - func renderTemplate(w http.ResponseWriter, tmpl string, p *Page) { t, _ := template.ParseFiles(tmpl + ".html") t.Execute(w, p) } func viewHandler(w http.ResponseWriter, r *http.Request) { - title := r.URL.Path[lenPath:] + title := r.URL.Path[len("/view/"):] p, _ := loadPage(title) renderTemplate(w, "view", p) } func editHandler(w http.ResponseWriter, r *http.Request) { - title := r.URL.Path[lenPath:] + title := r.URL.Path[len("/edit/"):] p, err := loadPage(title) if err != nil { p = &Page{Title: title} diff --git a/doc/articles/wiki/srcextract.go b/doc/articles/wiki/srcextract.go deleted file mode 100644 index 813e25283..000000000 --- a/doc/articles/wiki/srcextract.go +++ /dev/null @@ -1,76 +0,0 @@ -// Copyright 2010 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package main - -import ( - "bytes" - "flag" - "go/ast" - "go/parser" - "go/printer" - "go/token" - "log" - "os" - "text/template" -) - -var ( - srcFn = flag.String("src", "", "source filename") - getName = flag.String("name", "", "func/type name to output") - html = flag.Bool("html", true, "output HTML") - showPkg = flag.Bool("pkg", false, "show package in output") -) - -func main() { - // handle input - flag.Parse() - if *srcFn == "" || *getName == "" { - flag.Usage() - os.Exit(2) - } - // load file - fs := token.NewFileSet() - file, err := parser.ParseFile(fs, *srcFn, nil, 0) - if err != nil { - log.Fatal(err) - } - // create filter - filter := func(name string) bool { - return name == *getName - } - // filter - if !ast.FilterFile(file, filter) { - os.Exit(1) - } - // print the AST - var b bytes.Buffer - printer.Fprint(&b, fs, file) - // drop package declaration - if !*showPkg { - for { - c, err := b.ReadByte() - if c == '\n' || err != nil { - break - } - } - } - // drop leading newlines - for { - b, err := b.ReadByte() - if err != nil { - break - } - if b != '\n' { - os.Stdout.Write([]byte{b}) - break - } - } - // output - if *html { - template.HTMLEscape(os.Stdout, b.Bytes()) - } else { - b.WriteTo(os.Stdout) - } -} diff --git a/doc/articles/wiki/test.bash b/doc/articles/wiki/test.bash index 02ed1894a..54a632c30 100755 --- a/doc/articles/wiki/test.bash +++ b/doc/articles/wiki/test.bash @@ -7,10 +7,17 @@ set -e wiki_pid= cleanup() { kill $wiki_pid - rm -f test_*.out Test.txt final-test.bin final-test.go + rm -f test_*.out Test.txt final-test.bin final-test.go a.out get.bin } trap cleanup 0 INT +# If called with -all, check that all code snippets compile. +if [ "$1" == "-all" ]; then + for fn in *.go; do + go build -o a.out $fn + done +fi + go build -o get.bin get.go addr=$(./get.bin -addr) sed s/:8080/$addr/ < final.go > final-test.go |