// WithValidateBaseURL is a middleware which checks if the request base URL // is equal to the one store in the configuration, if not // i.e. redirect from http://example.com/store/ to http://www.example.com/store/ // @see app/code/Magento/Store/App/FrontController/Plugin/RequestPreprocessor.php func WithValidateBaseURL(cr config.ReaderPubSuber) ctxhttp.Middleware { // Having the GetBool command here, means you must restart the app to take // changes in effect. @todo refactor and use pub/sub to automatically change // the isRedirectToBase value. checkBaseURL, err := cr.GetBool(config.Path(PathRedirectToBase)) // scope default if config.NotKeyNotFoundError(err) && PkgLog.IsDebug() { PkgLog.Debug("ctxhttp.WithValidateBaseUrl.GetBool", "err", err, "path", PathRedirectToBase) } redirectCode := http.StatusMovedPermanently if rc, err := cr.GetInt(config.Path(PathRedirectToBase)); rc != redirectCode && false == config.NotKeyNotFoundError(err) { redirectCode = http.StatusFound } return func(h ctxhttp.Handler) ctxhttp.Handler { return ctxhttp.HandlerFunc(func(ctx context.Context, w http.ResponseWriter, r *http.Request) error { if checkBaseURL && r.Method != "POST" { _, requestedStore, err := FromContextReader(ctx) if err != nil { if PkgLog.IsDebug() { PkgLog.Debug("ctxhttp.WithValidateBaseUrl.FromContextServiceReader", "err", err, "ctx", ctx) } return errgo.Mask(err) } baseURL, err := requestedStore.BaseURL(config.URLTypeWeb, requestedStore.IsCurrentlySecure(r)) if err != nil { if PkgLog.IsDebug() { PkgLog.Debug("ctxhttp.WithValidateBaseUrl.requestedStore.BaseURL", "err", err, "ctx", ctx) } return errgo.Mask(err) } if err := httputils.IsBaseURLCorrect(r, &baseURL); err != nil { if PkgLog.IsDebug() { PkgLog.Debug("store.WithValidateBaseUrl.IsBaseUrlCorrect.error", "err", err, "baseURL", baseURL, "request", r) } baseURL.Path = r.URL.Path baseURL.RawPath = r.URL.RawPath baseURL.RawQuery = r.URL.RawQuery baseURL.Fragment = r.URL.Fragment http.Redirect(w, r, (&baseURL).String(), redirectCode) return nil } } return h.ServeHTTPContext(ctx, w, r) }) } }
func TestIsBaseUrlCorrect(t *testing.T) { var nr = func(urlStr string) *http.Request { r, err := http.NewRequest("GET", urlStr, nil) if err != nil { t.Fatal(err) } return r } var pu = func(rawURL string) *url.URL { u, err := url.Parse(rawURL) if err != nil { t.Fatal(err) } return u } tests := []struct { req *http.Request haveBaseURL *url.URL wantErr error }{ {nr("http://corestore.io/"), pu("http://corestore.io/"), nil}, {nr("http://www.corestore.io/"), pu("http://corestore.io/"), httputils.ErrBaseURLDoNotMatch}, {nr("http://corestore.io/"), pu("https://corestore.io/"), httputils.ErrBaseURLDoNotMatch}, {nr("http://corestore.io/"), pu("http://corestore.io/subpath"), httputils.ErrBaseURLDoNotMatch}, {nr("http://corestore.io/subpath"), pu("http://corestore.io/subpath"), nil}, {nr("http://corestore.io/"), pu("http://corestore.io/"), nil}, {nr("http://corestore.io/subpath/catalog/product/list"), pu("http://corestore.io/subpath"), nil}, } for i, test := range tests { haveErr := httputils.IsBaseURLCorrect(test.req, test.haveBaseURL) if test.wantErr != nil { assert.EqualError(t, haveErr, test.wantErr.Error(), "Index %d", i) } else { assert.NoError(t, haveErr, "Index %d", i) } } }