LoginSignup
0
0

More than 3 years have passed since last update.

go修行18日目 構造化されたWebサーバ

Last updated at Posted at 2020-07-09

構造化されたWebサーバ

メイン

main.go

package main

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

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
}

// htmlファイルのテンプレートを指定できる
// 直接書いてもいいけれどソースがわかりにくくなる
func renderTemplate(w http.ResponseWriter, tmpl string, p *Page) {
    // ローカルのhtmlファイルを指定
    t, _ := template.ParseFiles(tmpl + ".html")
    t.Execute(w, p)
}

func viewHandler(w http.ResponseWriter, r *http.Request) {
    title := r.URL.Path[len("/view/"):]
    p, err := loadPage(title)

    // もしエラー(ページがなかったら)editページへリダイレクトされる
    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 := r.URL.Path[len("/edit/"):]
    p, err := loadPage(title)
    if err != nil {
        p = &Page{Title: title}
    }
    renderTemplate(w, "edit", p)
}

func saveHandler(w http.ResponseWriter, r *http.Request) {
    title := r.URL.Path[len("/save/"):]
    body := r.FormValue("body")
    p := &Page{Title: title, Body: []byte(body)}
    err := p.save()
    // saveに失敗したら、500エラー
    if err != nil {
        http.Error(w, err.Error(), http.StatusInternalServerError)
        return
    }
    http.Redirect(w, r, "/view/"+title, http.StatusFound)
}

func main() {
    http.HandleFunc("/view/", viewHandler)
    http.HandleFunc("/edit/", editHandler)
    http.HandleFunc("/save/", saveHandler)
    // /にアクセスしたり/view以外にアクセスすると404NOTFOUND
    log.Fatal(http.ListenAndServe(":8080", nil))
}


/editとなるhtmlファイル

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となるhmtlファイル

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

<p>[<a href="/edit/{{.Title}}">Edit</a>]</p>

<div>{{printf "%s" .Body}}</div>

動作確認

editページでhtmlファイル生成

image.png

/viewが一覧ページ

image.png

/view/test1などでアクセス

image.png

教材

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0