// 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(cg config.GetterPubSuber) 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. // <todo check logic!> cgDefaultScope := cg.NewScoped(0, 0, 0) configRedirectCode := backend.Backend.WebURLRedirectToBase.Get(cgDefaultScope) redirectCode := http.StatusMovedPermanently if configRedirectCode != redirectCode { redirectCode = http.StatusFound } // </todo check logic> return func(hf ctxhttp.HandlerFunc) ctxhttp.HandlerFunc { return func(ctx context.Context, w http.ResponseWriter, r *http.Request) error { if configRedirectCode > 0 && 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 := httputil.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 hf(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/"), httputil.ErrBaseURLDoNotMatch}, {nr("http://corestore.io/"), pu("https://corestore.io/"), httputil.ErrBaseURLDoNotMatch}, {nr("http://corestore.io/"), pu("http://corestore.io/subpath"), httputil.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 := httputil.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) } } }