| package middleware | |
| import ( | |
| "strings" | |
| "github.com/labstack/echo/v4" | |
| ) | |
| // BaseURL returns the base URL for the given HTTP request context. | |
| // It takes into account that the app may be exposed by a reverse-proxy under a different protocol, host and path. | |
| // The returned URL is guaranteed to end with `/`. | |
| // The method should be used in conjunction with the StripPathPrefix middleware. | |
| func BaseURL(c echo.Context) string { | |
| path := c.Path() | |
| origPath := c.Request().URL.Path | |
| // Check if StripPathPrefix middleware stored the original path | |
| if storedPath, ok := c.Get("_original_path").(string); ok && storedPath != "" { | |
| origPath = storedPath | |
| } | |
| // Check X-Forwarded-Proto for scheme | |
| scheme := "http" | |
| if c.Request().Header.Get("X-Forwarded-Proto") == "https" { | |
| scheme = "https" | |
| } else if c.Request().TLS != nil { | |
| scheme = "https" | |
| } | |
| // Check X-Forwarded-Host for host | |
| host := c.Request().Host | |
| if forwardedHost := c.Request().Header.Get("X-Forwarded-Host"); forwardedHost != "" { | |
| host = forwardedHost | |
| } | |
| if path != origPath && strings.HasSuffix(origPath, path) && len(path) > 0 { | |
| prefixLen := len(origPath) - len(path) | |
| if prefixLen > 0 && prefixLen <= len(origPath) { | |
| pathPrefix := origPath[:prefixLen] | |
| if !strings.HasSuffix(pathPrefix, "/") { | |
| pathPrefix += "/" | |
| } | |
| return scheme + "://" + host + pathPrefix | |
| } | |
| } | |
| return scheme + "://" + host + "/" | |
| } | |