-
Notifications
You must be signed in to change notification settings - Fork 928
feat: Add serving applications on subdomains and port-based proxying #3753
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
29 commits
Select commit
Hold shift + click to select a range
35ee5d6
chore: Add subdomain parser for applications
Emyrk a7e5bd6
Add basic router for applications using same codepath
Emyrk 03c697d
Merge remote-tracking branch 'origin/main' into stevenmasley/unnamed-…
Emyrk 3e30cdd
Handle ports as app names
Emyrk 8397306
Add comments
Emyrk f994ec3
Cleanup
Emyrk fda80b8
Linting
Emyrk 6b09a0f
Push cookies to subdomains on the access url as well
Emyrk 634cd2e
Fix unit test
Emyrk 82df6f1
Fix comment
Emyrk 49084e2
Reuse regex from validation
Emyrk 4696bf9
Export valid name regex
Emyrk b5d1f6a
Move to workspaceapps.go
Emyrk 0578588
Change app url name order
Emyrk 77d3452
Import order
Emyrk 931ecb2
Merge remote-tracking branch 'origin/main' into stevenmasley/unnamed-…
Emyrk 54f2bdd
Deleted duplicate code
Emyrk f1d7670
Rename subdomain handler
Emyrk 46e0900
Merge branch 'main' into stevenmasley/unnamed-apps
deansheather 56c1d00
Change the devurl syntax to app--agent--workspace--user
deansheather 25d776a
more devurls support stuff, everything should work now
deansheather f3c6645
devurls working + tests
deansheather 75c4713
Merge branch 'main' into stevenmasley/unnamed-apps
deansheather 1f8a1f0
Move stuff to httpapi
deansheather 2c7bcc1
fixup! Move stuff to httpapi
deansheather dc0d348
Merge branch 'main' into stevenmasley/unnamed-apps
deansheather 58653d4
kyle comments
deansheather 5321bef
fixup! kyle comments
deansheather ad53b42
fixup! kyle comments
deansheather File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,100 @@ | ||
package httpapi | ||
|
||
import ( | ||
"fmt" | ||
"regexp" | ||
"strconv" | ||
"strings" | ||
|
||
"golang.org/x/xerrors" | ||
) | ||
|
||
var ( | ||
// Remove the "starts with" and "ends with" regex components. | ||
nameRegex = strings.Trim(UsernameValidRegex.String(), "^$") | ||
appURL = regexp.MustCompile(fmt.Sprintf( | ||
// {PORT/APP_NAME}--{AGENT_NAME}--{WORKSPACE_NAME}--{USERNAME} | ||
`^(?P<AppName>%[1]s)--(?P<AgentName>%[1]s)--(?P<WorkspaceName>%[1]s)--(?P<Username>%[1]s)$`, | ||
nameRegex)) | ||
) | ||
|
||
// SplitSubdomain splits a subdomain from the rest of the hostname. E.g.: | ||
// - "foo.bar.com" becomes "foo", "bar.com" | ||
// - "foo.bar.baz.com" becomes "foo", "bar.baz.com" | ||
// | ||
// An error is returned if the string doesn't contain a period. | ||
func SplitSubdomain(hostname string) (subdomain string, rest string, err error) { | ||
toks := strings.SplitN(hostname, ".", 2) | ||
if len(toks) < 2 { | ||
return "", "", xerrors.New("no subdomain") | ||
} | ||
|
||
return toks[0], toks[1], nil | ||
} | ||
|
||
// ApplicationURL is a parsed application URL hostname. | ||
type ApplicationURL struct { | ||
// Only one of AppName or Port will be set. | ||
AppName string | ||
Port uint16 | ||
AgentName string | ||
WorkspaceName string | ||
Username string | ||
// BaseHostname is the rest of the hostname minus the application URL part | ||
// and the first dot. | ||
BaseHostname string | ||
} | ||
|
||
// String returns the application URL hostname without scheme. | ||
func (a ApplicationURL) String() string { | ||
appNameOrPort := a.AppName | ||
if a.Port != 0 { | ||
appNameOrPort = strconv.Itoa(int(a.Port)) | ||
} | ||
|
||
return fmt.Sprintf("%s--%s--%s--%s.%s", appNameOrPort, a.AgentName, a.WorkspaceName, a.Username, a.BaseHostname) | ||
} | ||
|
||
// ParseSubdomainAppURL parses an ApplicationURL from the given hostname. If | ||
// the subdomain is not a valid application URL hostname, returns a non-nil | ||
// error. | ||
// | ||
// Subdomains should be in the form: | ||
// | ||
// {PORT/APP_NAME}--{AGENT_NAME}--{WORKSPACE_NAME}--{USERNAME} | ||
// (eg. http://8080--main--dev--dean.hi.c8s.io) | ||
func ParseSubdomainAppURL(hostname string) (ApplicationURL, error) { | ||
subdomain, rest, err := SplitSubdomain(hostname) | ||
if err != nil { | ||
return ApplicationURL{}, xerrors.Errorf("split host domain %q: %w", hostname, err) | ||
} | ||
|
||
matches := appURL.FindAllStringSubmatch(subdomain, -1) | ||
if len(matches) == 0 { | ||
return ApplicationURL{}, xerrors.Errorf("invalid application url format: %q", subdomain) | ||
} | ||
matchGroup := matches[0] | ||
|
||
appName, port := AppNameOrPort(matchGroup[appURL.SubexpIndex("AppName")]) | ||
return ApplicationURL{ | ||
AppName: appName, | ||
Port: port, | ||
AgentName: matchGroup[appURL.SubexpIndex("AgentName")], | ||
WorkspaceName: matchGroup[appURL.SubexpIndex("WorkspaceName")], | ||
Username: matchGroup[appURL.SubexpIndex("Username")], | ||
BaseHostname: rest, | ||
}, nil | ||
} | ||
|
||
// AppNameOrPort takes a string and returns either the input string or a port | ||
// number. | ||
func AppNameOrPort(val string) (string, uint16) { | ||
port, err := strconv.ParseUint(val, 10, 16) | ||
if err != nil || port == 0 { | ||
port = 0 | ||
} else { | ||
val = "" | ||
} | ||
|
||
return val, uint16(port) | ||
} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.