openreplay/backend/pkg/url/assets/url.go

98 lines
2.3 KiB
Go

package assets
import (
"net/url"
"path/filepath"
"strconv"
)
func getSessionKey(sessionID uint64) string {
// Based on timestamp, changes once per week. Check out utils/flacker for understanding sessionID
return strconv.FormatUint(sessionID>>50, 10)
}
func ResolveURL(baseurl string, rawurl string) string {
base, _ := url.ParseRequestURI(baseurl) // fn Only for base urls
u, _ := url.Parse(rawurl) // TODO: handle errors ?
if base == nil || u == nil {
return rawurl
}
return base.ResolveReference(u).String() // ResolveReference same as base.Parse(rawurl)
}
func isRelativeCachable(relativeURL string) bool {
if len(relativeURL) == 0 || relativeURL[0] == '#' {
return false
}
return true
}
func isCachable(rawurl string) bool {
u, _ := url.Parse(rawurl)
if u == nil || u.User != nil {
return false
}
if u.Scheme != "http" && u.Scheme != "https" {
return false
}
ext := filepath.Ext(u.Path)
return ext == ".css" ||
ext == ".woff" ||
ext == ".woff2" ||
ext == ".ttf" ||
ext == ".otf"
}
func GetFullCachableURL(baseURL string, relativeURL string) (string, bool) {
if !isRelativeCachable(relativeURL) {
return "", false
}
return ResolveURL(baseURL, relativeURL), true
}
const OPENREPLAY_QUERY_START = "OPENREPLAY_QUERY"
func getCachePath(rawurl string) string {
u, _ := url.Parse(rawurl)
s := "/" + u.Scheme + "/" + u.Hostname() + u.Path
if u.RawQuery != "" {
if (s[len(s) - 1] != '/') {
s += "/"
}
s += OPENREPLAY_QUERY_START + url.PathEscape(u.RawQuery)
}
return s
}
func getCachePathWithKey(sessionID uint64, rawurl string) string {
return getCachePath(rawurl) + "." + getSessionKey(sessionID) // Be carefull with slashes
}
func GetCachePathForJS(rawurl string) string {
return getCachePath(rawurl)
}
func GetCachePathForAssets(sessionID uint64, rawurl string) string {
return getCachePathWithKey(sessionID, rawurl)
}
func (r *Rewriter) RewriteURL(sessionID uint64, baseURL string, relativeURL string) string {
// TODO: put it in one check within GetFullCachableURL
if !isRelativeCachable(relativeURL) {
return relativeURL
}
fullURL := ResolveURL(baseURL, relativeURL)
if !isCachable(fullURL) {
return relativeURL
}
u := url.URL{
Path: r.assetsURL.Path + getCachePathWithKey(sessionID, fullURL),
Host: r.assetsURL.Host,
Scheme: r.assetsURL.Scheme,
}
return u.String()
}