blob: d84c1ffb264663a279a76554c3e22d07009b22b9 [file] [log] [blame]
Brent Austinba3052e2015-04-21 16:08:23 -07001// Copyright 2010 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5package main
6
7import (
8 "flag"
9 "html/template"
10 "io/ioutil"
11 "log"
12 "net"
13 "net/http"
14 "regexp"
15)
16
17var (
18 addr = flag.Bool("addr", false, "find open address and print to final-port.txt")
19)
20
21type Page struct {
22 Title string
23 Body []byte
24}
25
26func (p *Page) save() error {
27 filename := p.Title + ".txt"
28 return ioutil.WriteFile(filename, p.Body, 0600)
29}
30
31func loadPage(title string) (*Page, error) {
32 filename := title + ".txt"
33 body, err := ioutil.ReadFile(filename)
34 if err != nil {
35 return nil, err
36 }
37 return &Page{Title: title, Body: body}, nil
38}
39
40func viewHandler(w http.ResponseWriter, r *http.Request, title string) {
41 p, err := loadPage(title)
42 if err != nil {
43 http.Redirect(w, r, "/edit/"+title, http.StatusFound)
44 return
45 }
46 renderTemplate(w, "view", p)
47}
48
49func editHandler(w http.ResponseWriter, r *http.Request, title string) {
50 p, err := loadPage(title)
51 if err != nil {
52 p = &Page{Title: title}
53 }
54 renderTemplate(w, "edit", p)
55}
56
57func saveHandler(w http.ResponseWriter, r *http.Request, title string) {
58 body := r.FormValue("body")
59 p := &Page{Title: title, Body: []byte(body)}
60 err := p.save()
61 if err != nil {
62 http.Error(w, err.Error(), http.StatusInternalServerError)
63 return
64 }
65 http.Redirect(w, r, "/view/"+title, http.StatusFound)
66}
67
68var templates = template.Must(template.ParseFiles("edit.html", "view.html"))
69
70func renderTemplate(w http.ResponseWriter, tmpl string, p *Page) {
71 err := templates.ExecuteTemplate(w, tmpl+".html", p)
72 if err != nil {
73 http.Error(w, err.Error(), http.StatusInternalServerError)
74 }
75}
76
77var validPath = regexp.MustCompile("^/(edit|save|view)/([a-zA-Z0-9]+)$")
78
79func makeHandler(fn func(http.ResponseWriter, *http.Request, string)) http.HandlerFunc {
80 return func(w http.ResponseWriter, r *http.Request) {
81 m := validPath.FindStringSubmatch(r.URL.Path)
82 if m == nil {
83 http.NotFound(w, r)
84 return
85 }
86 fn(w, r, m[2])
87 }
88}
89
90func main() {
91 flag.Parse()
92 http.HandleFunc("/view/", makeHandler(viewHandler))
93 http.HandleFunc("/edit/", makeHandler(editHandler))
94 http.HandleFunc("/save/", makeHandler(saveHandler))
95
96 if *addr {
97 l, err := net.Listen("tcp", "127.0.0.1:0")
98 if err != nil {
99 log.Fatal(err)
100 }
101 err = ioutil.WriteFile("final-port.txt", []byte(l.Addr().String()), 0644)
102 if err != nil {
103 log.Fatal(err)
104 }
105 s := &http.Server{}
106 s.Serve(l)
107 return
108 }
109
110 http.ListenAndServe(":8080", nil)
111}