ParseSubdomainAppURL parses an ApplicationURL from the given subdomain. If the subdomain is not a valid application URL hostname, returns a non-nil error. If the hostname is not a subdomain of the given base hostname, returns a non-nil error. Subdomains should be in the form: ({PREFIX}---)?{PORT{
(subdomain string)
| 170 | // Prefix requires three hyphens at the end to separate it from the rest of the |
| 171 | // URL so we can add/remove segments in the future from the parsing logic. |
| 172 | func ParseSubdomainAppURL(subdomain string) (ApplicationURL, error) { |
| 173 | var ( |
| 174 | prefixSegments = strings.Split(subdomain, "---") |
| 175 | prefix = "" |
| 176 | ) |
| 177 | if len(prefixSegments) > 1 { |
| 178 | prefix = strings.Join(prefixSegments[:len(prefixSegments)-1], "---") + "---" |
| 179 | subdomain = prefixSegments[len(prefixSegments)-1] |
| 180 | } |
| 181 | |
| 182 | matches := appURL.FindStringSubmatch(subdomain) |
| 183 | if matches == nil { |
| 184 | return ApplicationURL{}, xerrors.Errorf("invalid application url format: %q", subdomain) |
| 185 | } |
| 186 | |
| 187 | appSlug := matches[appURL.SubexpIndex("AppSlug")] |
| 188 | agentName := matches[appURL.SubexpIndex("AgentName")] |
| 189 | |
| 190 | // Agent name is optional for app slugs but required for ports |
| 191 | if PortRegex.MatchString(appSlug) { |
| 192 | if agentName == "" { |
| 193 | return ApplicationURL{}, xerrors.Errorf("agent name is required for port-based URLs: %q", subdomain) |
| 194 | } |
| 195 | } else { |
| 196 | agentName = "" |
| 197 | } |
| 198 | |
| 199 | return ApplicationURL{ |
| 200 | Prefix: prefix, |
| 201 | AppSlugOrPort: appSlug, |
| 202 | AgentName: agentName, |
| 203 | WorkspaceName: matches[appURL.SubexpIndex("WorkspaceName")], |
| 204 | Username: matches[appURL.SubexpIndex("Username")], |
| 205 | }, nil |
| 206 | } |
| 207 | |
| 208 | // HostnamesMatch returns true if the hostnames are equal, disregarding |
| 209 | // capitalization, extra leading or trailing periods, and ports. |