Przeglądaj źródła

Web UI: URLFromRoute now generates absolute URLs.

Frederic G. MARAND 5 lat temu
rodzic
commit
18c5213c69

+ 1 - 1
.idea/runConfigurations/Test_Web.xml

@@ -1,7 +1,7 @@
 <component name="ProjectRunConfigurationManager">
   <configuration default="false" name="Test Web" type="GoTestRunConfiguration" factoryName="Go Test">
     <module name="kurz" />
-    <working_directory value="$PROJECT_DIR$/" />
+    <working_directory value="$PROJECT_DIR$/web" />
     <framework value="gotest" />
     <kind value="PACKAGE" />
     <package value="code.osinet.fr/fgm/kurz/web" />

+ 1 - 1
.idea/runConfigurations/Test_all.xml

@@ -1,7 +1,7 @@
 <component name="ProjectRunConfigurationManager">
   <configuration default="false" name="Test all" type="GoTestRunConfiguration" factoryName="Go Test" singleton="true">
     <module name="kurz" />
-    <working_directory value="$PROJECT_DIR$/" />
+    <working_directory value="$PROJECT_DIR$" />
     <framework value="gotest" />
     <kind value="DIRECTORY" />
     <package value="code.osinet.fr/fgm/kurz" />

+ 15 - 0
web/gorilla_imported.go

@@ -0,0 +1,15 @@
+package web
+
+// mapToPairs converts a string map to a slice of string pairs
+// Part of the mux_test.go file in Gorilla Mux, used under its BSD-like license.
+func mapToPairs(m map[string]string) []string {
+	var i int
+	p := make([]string, len(m)*2)
+	for k, v := range m {
+		p[i] = k
+		p[i+1] = v
+		i += 2
+	}
+	return p
+}
+

+ 12 - 4
web/post_target.go

@@ -31,7 +31,12 @@ func handlePostTarget(w http.ResponseWriter, r *http.Request, router *mux.Router
 	if err != nil {
 		sess.AddFlash(err.Error())
 		sess.Save(r, w)
-		w.Header().Set("Location", URLFromRoute(router, RouteGetRoot, nil))
+		location, err := URLFromRoute(router, RouteGetRoot, nil)
+		if err != nil {
+			w.WriteHeader(http.StatusInternalServerError)
+			return
+		}
+		w.Header().Set("Location", location)
 		w.WriteHeader(http.StatusSeeOther)
 		return
 	}
@@ -41,13 +46,16 @@ func handlePostTarget(w http.ResponseWriter, r *http.Request, router *mux.Router
 		w.WriteHeader(http.StatusInternalServerError)
 		return
 	}
+	fqsu, err := URLFromRoute(router, RouteGetShort, map[string]string{"short": short})
+	if err != nil {
+		w.WriteHeader(http.StatusInternalServerError)
+		return
+	}
 	sw := &strings.Builder{}
 	var templateName string
 	if isNew {
-		sess.AddFlash("New short URL created")
 		templateName = "201"
 	} else {
-		sess.AddFlash("Existing short URL reused")
 		templateName = "409"
 	}
 	defer sess.Save(r, w)
@@ -59,7 +67,7 @@ func handlePostTarget(w http.ResponseWriter, r *http.Request, router *mux.Router
 		Globals
 	}{
 		sess.Flashes(),
-		short,
+		fqsu,
 		target,
 		globals,
 	}

+ 20 - 6
web/web.go

@@ -9,6 +9,7 @@ package web
 
 import (
 	"errors"
+	"fmt"
 	"html/template"
 	"log"
 	"net/http"
@@ -16,6 +17,7 @@ import (
 	"path"
 	"path/filepath"
 	"strconv"
+	"strings"
 
 	"github.com/gorilla/mux"
 	"github.com/gorilla/sessions"
@@ -117,13 +119,13 @@ func setupTemplates(configAssetsPath string) {
 func SetupGlobals(c map[string]interface{}) {
 	// Note: keys in viper are lower-cased.
 	globals = Globals{
-		AssetsBaseURL: c["assetsbaseurl"].(string),
+		AssetsBaseURL: strings.Trim(c["assetsbaseurl"].(string), "/"),
 		AssetsPath:    c["assetspath"].(string),
 		AssetsVersion: c["assetsversion"].(int),
 		RefreshDelay:  c["refreshdelay"].(int),
 		SessionKey:    []byte(c["sessionkey"].(string)),
 		SessionName:   c["sessionname"].(string),
-		SiteBaseURL:   c["sitebaseurl"].(string),
+		SiteBaseURL:   strings.Trim(c["sitebaseurl"].(string), "/"),
 		SiteName:      c["sitename"].(string),
 	}
 
@@ -138,10 +140,22 @@ To build URLs for assets, use URLForAsset().
   - ns: the assets namespace. One of "js", "css', "images".
   - path: the asset path relative to the project root
 */
-func URLFromRoute(router *mux.Router, name string, params map[string]string) string {
-	log.Println("Generating route:", name, params)
-	//url, err := router.Get(name).URL(params
-	return "/"
+func URLFromRoute(router *mux.Router, name string, params map[string]string) (string, error) {
+	route := router.Get(name)
+	if route == nil {
+		err := errors.New(fmt.Sprintf("Error building unregistered route %s\n", name))
+		return "", err
+	}
+	pairs := mapToPairs(params)
+	url, err := route.URL(pairs...)
+	if err != nil {
+		err = errors.New(fmt.Sprintf("Error building route %s: %s\n", name, err))
+		return "", err
+	}
+	// Don't use path.Join, it would clobber the scheme://domain format.
+	// SiteBaseURL is "/"-trimmed on setup.
+	fqsu := globals.SiteBaseURL + url.String()
+	return fqsu, nil
 }
 
 /*

+ 39 - 2
web/web_test.go

@@ -3,14 +3,20 @@ package web
 import (
 	"fmt"
 	"testing"
+
+	"github.com/gorilla/mux"
 )
 
-// Not a Test function, a test helper.
+/* Not a Test function, a test helper.
+
+AssetsPath is "public" instead of "web/public" because tests normaly run from the
+package directory, not the project directory.
+*/
 func testSetupGlobals() {
 	globals = Globals{
 		AssetsBaseURL: "https://cdn.osinet.fr",
 		AssetsVersion: 1,
-		AssetsPath:    "web/public",
+		AssetsPath:    "public",
 		SiteBaseURL:   "http://sut.kurz.osinet.fr",
 		RefreshDelay:  1,
 		SiteName:      "Kurz test site",
@@ -65,3 +71,34 @@ func TestURLForAssetSad(t *testing.T) {
 	}()
 	URLForAsset("", "")
 }
+
+func TestURLFromRoute(t *testing.T) {
+	testSetupGlobals()
+	router := mux.NewRouter()
+	SetupUI(router, globals.AssetsPath)
+
+	type strings map[string]string
+	type check struct {
+		Expected string
+		OK       bool
+		Params   strings
+		Route    string
+	}
+	checks := []check{
+		{globals.SiteBaseURL + "/", true, nil, RouteGetRoot},
+		{globals.SiteBaseURL + "/foo", true, strings{"short": "foo"}, RouteGetShort},
+		{"", false, nil, "NoSuchRoute"},
+		{"", false, nil, RouteGetShort},
+	}
+
+	for _, check := range checks {
+		actual, err := URLFromRoute(router, check.Route, check.Params)
+		if check.OK && err != nil {
+			t.Errorf("Error building route %s: %v\n", check.Route, err)
+			t.FailNow()
+		} else if actual != check.Expected {
+			t.Errorf("Route %s failure. Expected %s, got %s\n", RouteGetRoot, check.Expected, actual)
+			t.Fail()
+		}
+	}
+}