Add a basic tool for collecting web comments
This commit is contained in:
parent
c3cc608570
commit
486b58525f
|
@ -0,0 +1,101 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"log"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
"regexp"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
var (
|
||||
long = regexp.MustCompile(`(.{72}\S*)\s+`)
|
||||
file, requests *os.File
|
||||
m sync.Mutex
|
||||
)
|
||||
|
||||
func wrap(s string) string {
|
||||
return strings.ReplaceAll(long.ReplaceAllString(
|
||||
strings.ReplaceAll(s, "\r", ""), "$1\n"), "\n", "\n ")
|
||||
}
|
||||
|
||||
func handler(w http.ResponseWriter, r *http.Request) {
|
||||
defer r.Body.Close()
|
||||
if err := r.ParseForm(); err != nil {
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
text := r.FormValue("text")
|
||||
if len(text) > 64<<10 {
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
m.Lock()
|
||||
defer m.Unlock()
|
||||
|
||||
j, _ := json.Marshal(struct {
|
||||
URI string
|
||||
Headers http.Header
|
||||
Form url.Values
|
||||
}{
|
||||
URI: r.RequestURI,
|
||||
Headers: r.Header,
|
||||
Form: r.Form,
|
||||
})
|
||||
|
||||
if s, err := file.Stat(); err != nil {
|
||||
log.Fatalln(err)
|
||||
} else if s.Size()+int64(len(text)) > 64<<20 {
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
} else if r.Form.Has("submit") {
|
||||
// <input type="submit"> should not be named, and thus received.
|
||||
//
|
||||
// If this is not enough to filter out most spammers, consider also:
|
||||
// - Header: "Origin" should not be missing for POST.
|
||||
// - Header: "Accept" should not be "*/*".
|
||||
// - Header: "Accept-Language" and "Accept-Encoding" should be present.
|
||||
// - Form: _charset_ should not be kept verbatim,
|
||||
// seeing as Safari/Chromium/Firefox all pass UTF-8,
|
||||
// in accordance with HTML5.
|
||||
w.WriteHeader(http.StatusTeapot)
|
||||
} else {
|
||||
fmt.Fprintf(file, "%s %s\n %s\n",
|
||||
time.Now().Local().Format(time.RFC1123), r.RequestURI, wrap(text))
|
||||
if err := file.Sync(); err != nil {
|
||||
log.Fatalln(err)
|
||||
}
|
||||
|
||||
// To help filter out spammers.
|
||||
fmt.Fprintf(requests, "%s\n", j)
|
||||
if err := requests.Sync(); err != nil {
|
||||
log.Fatalln(err)
|
||||
}
|
||||
|
||||
fmt.Fprintln(w, "Saved.")
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
if len(os.Args) != 3 {
|
||||
log.Fatalf("Usage: %s BIND DB\n", os.Args[0])
|
||||
}
|
||||
|
||||
var err error
|
||||
if file, err = os.OpenFile(os.Args[2],
|
||||
os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0644); err != nil {
|
||||
log.Fatalln(err)
|
||||
}
|
||||
if requests, err = os.OpenFile(os.Args[2]+".requests",
|
||||
os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0644); err != nil {
|
||||
log.Fatalln(err)
|
||||
}
|
||||
|
||||
http.HandleFunc("/", handler)
|
||||
log.Fatalln(http.ListenAndServe(os.Args[1], nil))
|
||||
}
|
Loading…
Reference in New Issue