Step 4: Web routing handling edit/view dari txt file
// 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.
//go:build ignore
package main
import (
"html/template"
"log"
"net/http"
"os"
"regexp"
)
type Page struct {
Title string
Body []byte
}
func (p *Page) save() error {
filename := p.Title + ".txt"
return os.WriteFile(filename, p.Body, 0600)
}
func loadPage(title string) (*Page, error) {
filename := title + ".txt"
body, err := os.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))
}
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
<h1></h1>
<div>
<pre></pre>
</div>
<p>
<a href="/edit/">Edit this page</a>
</p>
</body>
</html>
<!DOCTYPE html>
<html>
<head>
<title>Edit </title>
</head>
<body>
<h1>Editing </h1>
<form action="/save/" method="POST">
<div>
<textarea name="body" rows="20" cols="80"></textarea>
</div>
<div>
<input type="submit" value="Save">
</div>
</form>
<p>
<a href="/view/">Back to view</a>
</p>
</body>
</html>
Buat file test.txt pada folder yang sama dengan step4.go, isi bebas
Compile and run step4.go
go build step4.go
step4
Atau langsung compile dan run
go run step4.go
Perhantikan hasil pada url http://localhost:8080/view/test
Coba apabila ke url yang file txt yang belum ada http://localhost:8080/edit/belumadafile
Perhatikan apa yang terjadi.
Ini adalah suatu proses routing handling, ketika ke url yang belum ada suatu file-nya, maka path akan pindah ke path localhost/edit, dan bisa membuat file txt baru disana. Sedangkan ketika file txt sudah ada maka bisa mengakses url seperti localhost/view/test bisa mengakses endpoint test karena sudah ada file test.txt