Explorar o código

Add 'host' flag for URL display (#26)

* add host flag, which allows one to specify the host that provided as the source in API output, and use this for UI rendering

* move to forked go-bindata

Co-authored-by: Adam Allred <aallred@rsglab.com>
adamallred %!s(int64=5) %!d(string=hai) anos
pai
achega
043936a950
Modificáronse 10 ficheiros con 123 adicións e 52 borrados
  1. 2 2
      Makefile
  2. 1 1
      cmd/go/main.go
  3. 21 15
      web/api.go
  4. 57 15
      web/api_test.go
  5. 13 6
      web/assets/edit.ts
  6. 10 3
      web/assets/index.js
  7. 1 0
      web/assets/lib/types.ts
  8. 1 1
      web/bindata.go
  9. 14 7
      web/json.go
  10. 3 2
      web/web.go

+ 2 - 2
Makefile

@@ -6,13 +6,13 @@ DST = $(patsubst %.scss,%.css,$(patsubst %.ts,%.js,$(subst web/assets,.build/ass
 ALL: web/bindata.go
 
 .build/bin/go-bindata:
-	GOPATH=$(shell pwd)/.build go get github.com/jteeuwen/go-bindata/...
+	GOPATH=$(shell pwd)/.build go get github.com/a-urth/go-bindata/...
 
 .build/assets:
 	mkdir -p $@
 
 .build/assets/%.css: web/assets/%.scss
-	sass --no-cache --sourcemap=none --style=compressed $< $@
+	sass --no-source-map --style=compressed $< $@
 
 .build/assets/%.js: web/assets/%.ts
 	$(eval TMP := $(shell mktemp))

+ 1 - 1
cmd/go/main.go

@@ -22,7 +22,7 @@ func main() {
 	pflag.String("backend", "leveldb", "backing store to use. 'leveldb' and 'firestore' currently supported.")
 	pflag.String("data", "data", "The location of the leveldb data directory")
 	pflag.String("project", "", "The GCP project to use for the firestore backend. Will attempt to use application default creds if not defined.")
-
+	pflag.String("host", "", "The host field to use when gnerating the source URL of a link. Defaults to the Host header of the generate request")
 	pflag.Parse()
 
 	if err := viper.BindPFlags(pflag.CommandLine); err != nil {

+ 21 - 15
web/api.go

@@ -75,7 +75,7 @@ func validateURL(r *http.Request, s string) error {
 	return nil
 }
 
-func apiURLPost(backend backend.Backend, w http.ResponseWriter, r *http.Request) {
+func apiURLPost(backend backend.Backend, host string, w http.ResponseWriter, r *http.Request) {
 	p := parseName("/api/url/", r.URL.Path)
 
 	var req struct {
@@ -125,10 +125,10 @@ func apiURLPost(backend backend.Backend, w http.ResponseWriter, r *http.Request)
 		return
 	}
 
-	writeJSONRoute(w, p, &rt)
+	writeJSONRoute(w, p, &rt, host)
 }
 
-func apiURLGet(backend backend.Backend, w http.ResponseWriter, r *http.Request) {
+func apiURLGet(backend backend.Backend, host string, w http.ResponseWriter, r *http.Request) {
 	p := parseName("/api/url/", r.URL.Path)
 
 	if p == "" {
@@ -148,7 +148,7 @@ func apiURLGet(backend backend.Backend, w http.ResponseWriter, r *http.Request)
 		return
 	}
 
-	writeJSONRoute(w, p, rt)
+	writeJSONRoute(w, p, rt, host)
 }
 
 func apiURLDelete(backend backend.Backend, w http.ResponseWriter, r *http.Request) {
@@ -208,7 +208,7 @@ func parseBool(v string, def bool) (bool, error) {
 	return false, errors.New("invalid boolean value")
 }
 
-func apiURLsGet(backend backend.Backend, w http.ResponseWriter, r *http.Request) {
+func apiURLsGet(backend backend.Backend, host string, w http.ResponseWriter, r *http.Request) {
 	c, err := parseCursor(r.FormValue("cursor"))
 	if err != nil {
 		writeJSONError(w, "invalid cursor value", http.StatusBadRequest)
@@ -250,10 +250,16 @@ func apiURLsGet(backend backend.Backend, w http.ResponseWriter, r *http.Request)
 			}
 		}
 
-		res.Routes = append(res.Routes, &routeWithName{
+		r := routeWithName{
 			Name:  iter.Name(),
 			Route: iter.Route(),
-		})
+		}
+
+		if host != "" {
+			r.SourceHost = host
+		}
+
+		res.Routes = append(res.Routes, &r)
 
 		if len(res.Routes) == lim {
 			break
@@ -272,12 +278,12 @@ func apiURLsGet(backend backend.Backend, w http.ResponseWriter, r *http.Request)
 	writeJSON(w, &res, http.StatusOK)
 }
 
-func apiURL(backend backend.Backend, w http.ResponseWriter, r *http.Request) {
+func apiURL(backend backend.Backend, host string, w http.ResponseWriter, r *http.Request) {
 	switch r.Method {
 	case "POST":
-		apiURLPost(backend, w, r)
+		apiURLPost(backend, host, w, r)
 	case "GET":
-		apiURLGet(backend, w, r)
+		apiURLGet(backend, host, w, r)
 	case "DELETE":
 		apiURLDelete(backend, w, r)
 	default:
@@ -285,22 +291,22 @@ func apiURL(backend backend.Backend, w http.ResponseWriter, r *http.Request) {
 	}
 }
 
-func apiURLs(backend backend.Backend, w http.ResponseWriter, r *http.Request) {
+func apiURLs(backend backend.Backend, host string, w http.ResponseWriter, r *http.Request) {
 	switch r.Method {
 	case "GET":
-		apiURLsGet(backend, w, r)
+		apiURLsGet(backend, host, w, r)
 	default:
 		writeJSONError(w, http.StatusText(http.StatusMethodNotAllowed), http.StatusOK) // fix
 	}
 }
 
 // Setup ...
-func Setup(m *http.ServeMux, backend backend.Backend) {
+func Setup(m *http.ServeMux, backend backend.Backend, host string) {
 	m.HandleFunc("/api/url/", func(w http.ResponseWriter, r *http.Request) {
-		apiURL(backend, w, r)
+		apiURL(backend, host, w, r)
 	})
 
 	m.HandleFunc("/api/urls/", func(w http.ResponseWriter, r *http.Request) {
-		apiURLs(backend, w, r)
+		apiURLs(backend, host, w, r)
 	})
 }

+ 57 - 15
web/api_test.go

@@ -72,7 +72,7 @@ func (e *env) call(method, path string, body io.Reader) (*mockResponse, error) {
 	return res, nil
 }
 
-func newEnv() (*env, error) {
+func newEnv(host string) (*env, error) {
 	dir, err := ioutil.TempDir("", "")
 	if err != nil {
 		return nil, err
@@ -86,7 +86,7 @@ func newEnv() (*env, error) {
 
 	mux := http.NewServeMux()
 
-	Setup(mux, backend)
+	Setup(mux, backend, host)
 
 	return &env{
 		mux:     mux,
@@ -95,8 +95,8 @@ func newEnv() (*env, error) {
 	}, nil
 }
 
-func needEnv(t *testing.T) *env {
-	e, err := newEnv()
+func needEnv(t *testing.T, host string) *env {
+	e, err := newEnv(host)
 	if err != nil {
 		t.Fatal(err)
 	}
@@ -137,11 +137,15 @@ func mustBeRouteOf(t *testing.T, rt *internal.Route, url string) {
 	}
 }
 
-func mustBeNamedRouteOf(t *testing.T, rt *routeWithName, name, url string) {
+func mustBeNamedRouteOf(t *testing.T, rt *routeWithName, name, url string, host string) {
 	mustBeRouteOf(t, rt.Route, url)
 	if rt.Name != name {
 		t.Fatalf("expected name of %s, got %s", name, rt.Name)
 	}
+
+	if host != "" && rt.SourceHost != host {
+		t.Fatalf("expected source of %s, got %s", host, rt.SourceHost)
+	}
 }
 
 func mustBeOk(t *testing.T, ok bool) {
@@ -167,7 +171,7 @@ func mustHaveStatus(t *testing.T, res *mockResponse, status int) {
 }
 
 func TestAPIGetNotFound(t *testing.T) {
-	e := needEnv(t)
+	e := needEnv(t, "")
 	defer e.destroy()
 
 	names := map[string]int{
@@ -194,7 +198,45 @@ func TestAPIGetNotFound(t *testing.T) {
 }
 
 func TestAPIPutThenGet(t *testing.T) {
-	e := needEnv(t)
+	e := needEnv(t, "")
+	defer e.destroy()
+
+	res, err := e.post("/api/url/xxx", &urlReq{
+		URL: "http://ex.com/",
+	})
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	mustHaveStatus(t, res, http.StatusOK)
+
+	var pm msgRoute
+	if err := json.NewDecoder(res).Decode(&pm); err != nil {
+		t.Fatal(err)
+	}
+
+	mustBeOk(t, pm.Ok)
+	mustBeNamedRouteOf(t, pm.Route, "xxx", "http://ex.com/", "")
+
+	res, err = e.get("/api/url/xxx")
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	mustHaveStatus(t, res, http.StatusOK)
+
+	var gm msgRoute
+	if err := json.NewDecoder(res).Decode(&gm); err != nil {
+		t.Fatal(err)
+	}
+
+	mustBeOk(t, gm.Ok)
+	mustBeNamedRouteOf(t, pm.Route, "xxx", "http://ex.com/", "")
+}
+
+func TestAPIPutThenGetWithHost(t *testing.T) {
+	host := "http://test.com"
+	e := needEnv(t, host)
 	defer e.destroy()
 
 	res, err := e.post("/api/url/xxx", &urlReq{
@@ -212,7 +254,7 @@ func TestAPIPutThenGet(t *testing.T) {
 	}
 
 	mustBeOk(t, pm.Ok)
-	mustBeNamedRouteOf(t, pm.Route, "xxx", "http://ex.com/")
+	mustBeNamedRouteOf(t, pm.Route, "xxx", "http://ex.com/", host)
 
 	res, err = e.get("/api/url/xxx")
 	if err != nil {
@@ -227,11 +269,11 @@ func TestAPIPutThenGet(t *testing.T) {
 	}
 
 	mustBeOk(t, gm.Ok)
-	mustBeNamedRouteOf(t, pm.Route, "xxx", "http://ex.com/")
+	mustBeNamedRouteOf(t, pm.Route, "xxx", "http://ex.com/", host)
 }
 
 func TestBadPuts(t *testing.T) {
-	e := needEnv(t)
+	e := needEnv(t, "")
 	defer e.destroy()
 
 	var m msgErr
@@ -271,7 +313,7 @@ func TestBadPuts(t *testing.T) {
 }
 
 func TestAPIDel(t *testing.T) {
-	e := needEnv(t)
+	e := needEnv(t, "")
 	defer e.destroy()
 
 	ctx, cancel := context.WithTimeout(context.Background(), time.Minute)
@@ -306,7 +348,7 @@ func TestAPIDel(t *testing.T) {
 }
 
 func TestAPIPutThenGetAuto(t *testing.T) {
-	e := needEnv(t)
+	e := needEnv(t, "")
 	defer e.destroy()
 
 	res, err := e.post("/api/url/", &urlReq{URL: "http://b.com/"})
@@ -335,7 +377,7 @@ func TestAPIPutThenGetAuto(t *testing.T) {
 		t.Fatal(err)
 	}
 	mustBeOk(t, bm.Ok)
-	mustBeNamedRouteOf(t, bm.Route, am.Route.Name, "http://b.com/")
+	mustBeNamedRouteOf(t, bm.Route, am.Route.Name, "http://b.com/", "")
 }
 
 func getInPages(e *env, params url.Values) ([][]*routeWithName, error) {
@@ -376,7 +418,7 @@ type listTest struct {
 }
 
 func TestAPIList(t *testing.T) {
-	e := needEnv(t)
+	e := needEnv(t, "")
 	defer e.destroy()
 
 	rts := []*routeWithName{
@@ -545,7 +587,7 @@ func TestAPIList(t *testing.T) {
 }
 
 func TestBadList(t *testing.T) {
-	e := needEnv(t)
+	e := needEnv(t, "")
 	defer e.destroy()
 
 	tests := map[string]int{

+ 13 - 6
web/assets/edit.ts

@@ -17,7 +17,7 @@ namespace go {
     // Called with the window resizes.
     var windowDidResize = () => {
         var rect = $frm.getBoundingClientRect();
-        dom.css($frm, 'margin-top', (window.innerHeight/3 - rect.height/2) + 'px');
+        dom.css($frm, 'margin-top', (window.innerHeight / 3 - rect.height / 2) + 'px');
     };
 
     // Called when the URL changes.
@@ -44,7 +44,7 @@ namespace go {
             url = ($url.value || '').trim();
 
         xhr.post('/api/url/' + name)
-            .sendJSON({url: url})
+            .sendJSON({ url: url })
             .onDone((data: string, status: number) => {
                 var msg = <MsgRoute>JSON.parse(data);
                 if (!msg.ok) {
@@ -59,10 +59,11 @@ namespace go {
                 }
 
                 var url = route.url || '',
-                    name = route.name || '';
+                    name = route.name || '',
+                    host = route.source_host || '';
                 if (url) {
                     history.replaceState({}, null, '/edit/' + name);
-                    showLink(name);
+                    showLink(name, host);
                 }
             });
     };
@@ -104,8 +105,14 @@ namespace go {
         dom.css($cmp, 'transform', 'scaleY(1)');
     };
 
-    var showLink = (name: string) => {
-        var lnk = location.origin + '/' + name;
+    var showLink = (name: string, src: string) => {
+        var lnk = '/' + name;
+
+        if (src != '') {
+            lnk = src + lnk;
+        } else {
+            lnk = location.origin + lnk;
+        }
 
         $cmp.textContent = '';
         $cmp.classList.remove('fuck');

+ 10 - 3
web/assets/index.js

@@ -39,8 +39,14 @@ var load = function() {
   });
 }
 
-var showLink = function(name) {
-  var lnk = location.origin + '/' + name;
+var showLink = function(name, src) {
+  var lnk = '/' + name;
+
+  if (src != '') {
+    lnk = src + lnk;
+  } else {
+    lnk = location.origin + lnk;
+  }
 
   $cmp.text('')
     .removeClass('fuck')
@@ -116,9 +122,10 @@ $frm.on('submit', function(e) {
 
     var url = route.url || '',
         name = route.name || '';
+        src = route.source_host || '';
     if (url) {
       history.replaceState({}, null, '/edit/' + name);
-      showLink(name);
+      showLink(name, src);
     }
   });
 });

+ 1 - 0
web/assets/lib/types.ts

@@ -2,6 +2,7 @@ interface Route {
 	name: string;
 	url: string;
 	time: string;
+	source_host: string;
 }
 
 interface Msg {

A diferenza do arquivo foi suprimida porque é demasiado grande
+ 1 - 1
web/bindata.go


+ 14 - 7
web/json.go

@@ -10,7 +10,8 @@ import (
 
 // Used as an API response, this is a route with its associated shortcut name.
 type routeWithName struct {
-	Name string `json:"name"`
+	Name       string `json:"name"`
+	SourceHost string `json:"source_host"`
 	*internal.Route
 }
 
@@ -66,12 +67,18 @@ func writeJSONBackendError(w http.ResponseWriter, err error) {
 }
 
 // Encode the given named route as a msg and send it to the client.
-func writeJSONRoute(w http.ResponseWriter, name string, rt *internal.Route) {
+func writeJSONRoute(w http.ResponseWriter, name string, rt *internal.Route, host string) {
+	r := routeWithName{
+		Name:  name,
+		Route: rt,
+	}
+
+	if host != "" {
+		r.SourceHost = host
+	}
+
 	writeJSON(w, &msgRoute{
-		Ok: true,
-		Route: &routeWithName{
-			Name:  name,
-			Route: rt,
-		},
+		Ok:    true,
+		Route: &r,
 	}, http.StatusOK)
 }

+ 3 - 2
web/web.go

@@ -96,14 +96,15 @@ func ListenAndServe(backend backend.Backend) error {
 	addr := viper.GetString("addr")
 	admin := viper.GetBool("admin")
 	version := viper.GetString("version")
+	host := viper.GetString("host")
 
 	mux := http.NewServeMux()
 
 	mux.HandleFunc("/api/url/", func(w http.ResponseWriter, r *http.Request) {
-		apiURL(backend, w, r)
+		apiURL(backend, host, w, r)
 	})
 	mux.HandleFunc("/api/urls/", func(w http.ResponseWriter, r *http.Request) {
-		apiURLs(backend, w, r)
+		apiURLs(backend, host, w, r)
 	})
 	mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
 		getDefault(backend, w, r)

Algúns arquivos non se mostraron porque demasiados arquivos cambiaron neste cambio