среда, 6 февраля 2019 г.

Веб-приложение на Go: готовое приложение

Вот окончательный код всего нашего вики веб-приложения. Приложение состоит из трех файлов: wiki.go, edit.html. view.html.

Файл wiki.go

package main

import (
  "html/template"
  "io/ioutil"
  "log"
  "net/http"
  "regexp"
)

type Page struct {
  Title string
  Body  []byte
}

func (p *Page) save() error {
  filename := p.Title + ".txt"
  return ioutil.WriteFile(filename, p.Body, 0600)
}

func loadPage(title string) (*Page, error) {
  filename := title + ".txt"
  body, err := ioutil.ReadFile(filename)
  if err != nil {
    return nil, err
  }
  return &Page{Title: title, Body: body}, nil
}

func viewHandler(w http.ResponseWriter, 
                 r *http.Request, title string) {
  p, err := loadPage(title)
  if err != nil {
    http.Redirect(w, r, "/edit/"+title, http.StatusFound)
    return
  }
  renderTemplate(w, "view", p)
}

func editHandler(w http.ResponseWriter, 
                 r *http.Request, title string) {
  p, err := loadPage(title)
  if err != nil {
    p = &Page{Title: title}
  }
  renderTemplate(w, "edit", p)
}

func saveHandler(w http.ResponseWriter, 
                 r *http.Request, title string) {
  body := r.FormValue("body")
  p := &Page{Title: title, Body: []byte(body)}
  err := p.save()
  if err != nil {
    http.Error(w, err.Error(), 
               http.StatusInternalServerError)
    return
  }
  http.Redirect(w, r, "/view/"+title, http.StatusFound)
}

var templates = template.Must(
                   template.ParseFiles("edit.html", 
                                       "view.html"))

func renderTemplate(w http.ResponseWriter, 
                    tmpl string, p *Page) {
  err := templates.ExecuteTemplate(w, tmpl+".html", p)
  if err != nil {
    http.Error(w, err.Error(), 
               http.StatusInternalServerError)
  }
}

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) {
    m := validPath.FindStringSubmatch(r.URL.Path)
    if m == nil {
      http.NotFound(w, r)
      return
    }
    fn(w, r, m[2])
  }
}

func main() {
  http.HandleFunc("/view/", makeHandler(viewHandler))
  http.HandleFunc("/edit/", makeHandler(editHandler))
  http.HandleFunc("/save/", makeHandler(saveHandler))

  log.Fatal(http.ListenAndServe(":8080", nil))
}

Файл edit.html

<h1>Editing {{.Title}}</h1>

<form action="/save/{{.Title}}" method="POST">
<div><textarea name="body" rows="20" cols="80">
{{printf "%s" .Body}}
</textarea></div>
<div><input type="submit" value="Save"></div>
</form>

Файл view.html

<h1>{{.Title}}</h1>

<p>[<a href="/edit/{{.Title}}">edit</a>]</p>
<div>{{printf "%s" .Body}}</div>

Скомпилируйте код и запустите приложение:

$ go build wiki.go
$ ./wiki

При открытии http://localhost:8080/view/ANewPage должна быть показана форма редактирования страницы.

Далее вводим текст, после нажатия «Сохранить» должно быть выполнено перенаправление на вновь созданную страницу.

Код приложения также доступен на Github https://github.com/A1esandr/golang-blog/tree/master/src/wiki


Читайте также:


Комментариев нет:

Отправить комментарий