| 287 | } |
| 288 | |
| 289 | func (s *Server) constructRedirectURL(r *http.Request) (string, error) { |
| 290 | proto := r.Header.Get("X-Forwarded-Proto") |
| 291 | host := r.Header.Get("X-Forwarded-Host") |
| 292 | uri := r.Header.Get("X-Forwarded-Uri") |
| 293 | |
| 294 | localizer := localization.GetLocalizer(r) |
| 295 | |
| 296 | if proto == "" || host == "" || uri == "" { |
| 297 | return "", errors.New(localizer.T("missing_required_forwarded_headers")) |
| 298 | } |
| 299 | |
| 300 | switch proto { |
| 301 | case "http", "https": |
| 302 | // allowed |
| 303 | default: |
| 304 | lg := internal.GetRequestLogger(s.logger, r) |
| 305 | lg.Warn("invalid protocol in X-Forwarded-Proto", "proto", proto) |
| 306 | return "", errors.New(localizer.T("invalid_redirect")) |
| 307 | } |
| 308 | |
| 309 | // Check if host is allowed in RedirectDomains (supports '*' via glob) |
| 310 | if len(s.opts.RedirectDomains) > 0 && !matchRedirectDomain(s.opts.RedirectDomains, host) { |
| 311 | lg := internal.GetRequestLogger(s.logger, r) |
| 312 | lg.Debug("domain not allowed", "domain", host) |
| 313 | return "", errors.New(localizer.T("redirect_domain_not_allowed")) |
| 314 | } |
| 315 | |
| 316 | redir := proto + "://" + host + uri |
| 317 | escapedURL := url.QueryEscape(redir) |
| 318 | return fmt.Sprintf("%s/.within.website/?redir=%s", s.opts.PublicUrl, escapedURL), nil |
| 319 | } |
| 320 | |
| 321 | func (s *Server) RenderBench(w http.ResponseWriter, r *http.Request) { |
| 322 | localizer := localization.GetLocalizer(r) |