go/svc/{invoice,speedtest} -> bgpwtf/
Continued from https://gerrit.hackerspace.pl/c/hscloud/+/71 .
Change-Id: I5aef587c7e9a4cec301e3c95530c33914851ad44
diff --git a/bgpwtf/speedtest/backend/main.go b/bgpwtf/speedtest/backend/main.go
new file mode 100644
index 0000000..7d4aece
--- /dev/null
+++ b/bgpwtf/speedtest/backend/main.go
@@ -0,0 +1,148 @@
+package main
+
+// Copyright 2019 Serge Bazanski
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+// SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+// OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+// CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+import (
+ "crypto/rand"
+ "encoding/json"
+ "flag"
+ "io"
+ "io/ioutil"
+ "net"
+ "net/http"
+ "strconv"
+ "strings"
+
+ "github.com/golang/glog"
+
+ "code.hackerspace.pl/hscloud/bgpwtf/speedtest/static"
+)
+
+var (
+ flagBind string
+ flagUseForwardedFor bool
+)
+
+func cors(w http.ResponseWriter) {
+ w.Header().Add("Access-Control-Allow-Origin", "*")
+ w.Header().Add("Access-Control-Allow-Methods", "GET, POST")
+}
+
+func noCache(w http.ResponseWriter) {
+ w.Header().Add("Cache-Control", "no-store, no-cache, must-revalidate, max-age=0, s-maxage=0")
+ w.Header().Add("Cache-Control", " post-check=0, pre-check=0")
+ w.Header().Add("Pragma", "no-cache")
+}
+
+func remoteIP(r *http.Request) net.IP {
+ remote := strings.TrimSpace(r.RemoteAddr)
+ if flagUseForwardedFor {
+ remote = strings.TrimSpace(r.Header.Get("X-Forwarded-For"))
+ }
+
+ if remote == "" {
+ return nil
+ }
+
+ if strings.HasPrefix(remote, "[") {
+ // Looks like a [::1] v6 address
+ inner := strings.Split(strings.Split(remote, "[")[1], "]")[0]
+ return net.ParseIP(inner)
+ }
+
+ if strings.Count(remote, ":") == 1 {
+ // Looks like a :4321 port suffix
+ inner := strings.Split(remote, ":")[0]
+ return net.ParseIP(inner)
+ }
+
+ return net.ParseIP(remote)
+}
+
+func init() {
+ flag.Set("logtostderr", "true")
+}
+
+func main() {
+ flag.StringVar(&flagBind, "bind", "0.0.0.0:8080", "Address at which to serve HTTP requests")
+ flag.BoolVar(&flagUseForwardedFor, "use_forwarded_for", false, "Honor X-Forwarded-For headers to detect user IP")
+ flag.Parse()
+ http.HandleFunc("/empty", func(w http.ResponseWriter, r *http.Request) {
+ cors(w)
+ noCache(w)
+ w.Header().Add("Connection", "keep-alive")
+ w.WriteHeader(http.StatusOK)
+ io.Copy(ioutil.Discard, r.Body)
+ })
+ http.HandleFunc("/garbage", func(w http.ResponseWriter, r *http.Request) {
+ cors(w)
+ w.Header().Add("Content-Description", "File Tranfer")
+ w.Header().Add("Content-Type", "application/octet-stream")
+ w.Header().Add("Content-Disposition", "attachment; filename=random.dat")
+ w.Header().Add("Content-Transfer-Encoding", "binary")
+ noCache(w)
+ w.WriteHeader(http.StatusOK)
+
+ chunks := 4
+ if val, err := strconv.Atoi(r.Header.Get("ckSize")); err == nil {
+ if val > 0 && val <= 1024 {
+ chunks = val
+ }
+ }
+
+ chunk := make([]byte, 1024*1024)
+ rand.Read(chunk)
+
+ for i := 0; i < chunks; i += 1 {
+ w.Write(chunk)
+ }
+ })
+ http.HandleFunc("/ip", func(w http.ResponseWriter, r *http.Request) {
+ cors(w)
+ noCache(w)
+
+ res := struct {
+ ProcessedString string `json:processedString`
+ RawISPInfo string `json:rawIspInfo`
+ }{
+ ProcessedString: "",
+ RawISPInfo: "",
+ }
+
+ ip := remoteIP(r)
+ if ip != nil {
+ res.ProcessedString = ip.String()
+ }
+
+ w.Header().Set("Content-Type", "application/json")
+
+ json.NewEncoder(w).Encode(res)
+ })
+ http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
+ w.Write(static.Data["bgpwtf/speedtest/index.html"])
+ })
+ http.HandleFunc("/speedtest.js", func(w http.ResponseWriter, r *http.Request) {
+ w.Write(static.Data["bgpwtf/speedtest/speedtest.js"])
+ })
+ http.HandleFunc("/speedtest_worker.js", func(w http.ResponseWriter, r *http.Request) {
+ w.Write(static.Data["bgpwtf/speedtest/speedtest_worker.js"])
+ })
+
+ glog.Infof("Starting up at %v", flagBind)
+ err := http.ListenAndServe(flagBind, nil)
+ if err != nil {
+ glog.Exit(err)
+ }
+}