Webcounter with cookies
This commit is contained in:
parent
b9344dcf82
commit
4dc2e681c4
1
.gitignore
vendored
1
.gitignore
vendored
@ -59,3 +59,4 @@ tpl-ex2/tpl-ex2
|
|||||||
tpl-ex3/tpl-ex3
|
tpl-ex3/tpl-ex3
|
||||||
form-ex1/form-ex1
|
form-ex1/form-ex1
|
||||||
form-ex2/form-ex2
|
form-ex2/form-ex2
|
||||||
|
webcounter/webcounter
|
||||||
|
83
webcounter/main.go
Normal file
83
webcounter/main.go
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/hmac"
|
||||||
|
"crypto/sha256"
|
||||||
|
"fmt"
|
||||||
|
"hash"
|
||||||
|
"html/template"
|
||||||
|
"log"
|
||||||
|
"net/http"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
var TPL *template.Template
|
||||||
|
|
||||||
|
const (
|
||||||
|
SECRET = "QDFuO2FyRHhGKEg5QlI4XDMlM2sK"
|
||||||
|
COUNTER_COOKIE string = "counter"
|
||||||
|
)
|
||||||
|
|
||||||
|
func displayPage(res http.ResponseWriter, req *http.Request) {
|
||||||
|
count, cookie := updateCounter(req)
|
||||||
|
http.SetCookie(res, cookie)
|
||||||
|
TPL.Execute(res, count)
|
||||||
|
}
|
||||||
|
|
||||||
|
func updateCounter(req *http.Request) (uint64, *http.Cookie) {
|
||||||
|
count := fromCookie(req)
|
||||||
|
count++
|
||||||
|
val := toCookieVal(count)
|
||||||
|
cookie := &http.Cookie{
|
||||||
|
Name: COUNTER_COOKIE,
|
||||||
|
Value: val,
|
||||||
|
}
|
||||||
|
return count, cookie
|
||||||
|
}
|
||||||
|
|
||||||
|
func fromCookie(req *http.Request) uint64 {
|
||||||
|
cookie, err := req.Cookie(COUNTER_COOKIE)
|
||||||
|
if err != nil {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
sp := strings.Split(cookie.Value, "|")
|
||||||
|
if len(sp) != 2 {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
c, err := strconv.Atoi(sp[0])
|
||||||
|
if err != nil {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
if !checkMac(sp[0], sp[1]) {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
return uint64(c)
|
||||||
|
}
|
||||||
|
|
||||||
|
func checkMac(val string, macStr string) bool {
|
||||||
|
var mac []byte
|
||||||
|
fmt.Sscanf(macStr, "%x", &mac)
|
||||||
|
return hmac.Equal(mac, cookieHash(val).Sum(nil))
|
||||||
|
}
|
||||||
|
|
||||||
|
func cookieHash(val string) hash.Hash {
|
||||||
|
mac := hmac.New(sha256.New, []byte(SECRET))
|
||||||
|
mac.Write([]byte(val))
|
||||||
|
return mac
|
||||||
|
}
|
||||||
|
|
||||||
|
func toCookieVal(count uint64) string {
|
||||||
|
val := strconv.FormatUint(count, 10)
|
||||||
|
return val + "|" + fmt.Sprintf("%x", cookieHash(val).Sum(nil))
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
var err error
|
||||||
|
TPL, err = template.ParseFiles("tpl.html")
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalln(err)
|
||||||
|
}
|
||||||
|
http.HandleFunc("/", displayPage)
|
||||||
|
http.ListenAndServe(":9000", nil)
|
||||||
|
}
|
8
webcounter/tpl.html
Normal file
8
webcounter/tpl.html
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head><title>Webcounter</title></head>
|
||||||
|
<body>
|
||||||
|
<p>Number of visits: {{ . }}</p>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
Loading…
Reference in New Issue
Block a user