1
1
package coderd
2
2
3
3
import (
4
+ "database/sql"
4
5
"fmt"
5
6
"net/http"
6
7
"regexp"
7
8
"strings"
8
9
10
+ "github.com/coder/coder/coderd/httpapi"
11
+ "github.com/coder/coder/codersdk"
12
+
13
+ "github.com/coder/coder/coderd/database"
14
+
9
15
"golang.org/x/xerrors"
10
16
)
11
17
@@ -17,20 +23,66 @@ const (
17
23
)
18
24
19
25
type Application struct {
20
- AppURL string
21
- AppName string
22
- Workspace string
23
- Agent string
24
- User string
25
- Path string
26
+ AppURL string
27
+ AppName string
28
+ WorkspaceName string
29
+ Agent string
30
+ Username string
31
+ Path string
26
32
27
33
// Domain is used to output the url to reach the app.
28
34
Domain string
29
35
}
30
36
31
37
func (api * API ) handleSubdomain (next http.Handler ) http.Handler {
32
- return http .HandlerFunc (func (w http.ResponseWriter , r * http.Request ) {
33
-
38
+ return http .HandlerFunc (func (rw http.ResponseWriter , r * http.Request ) {
39
+ ctx := r .Context ()
40
+ app , err := ParseSubdomainAppURL (r )
41
+ if err != nil {
42
+ // Not a Dev URL, proceed as usual.
43
+ // TODO: @emyrk we should probably catch invalid subdomains. Meaning
44
+ // an invalid devurl should not route to the coderd.
45
+ next .ServeHTTP (rw , r )
46
+ return
47
+ }
48
+
49
+ user , err := api .Database .GetUserByEmailOrUsername (ctx , database.GetUserByEmailOrUsernameParams {
50
+ Username : app .Username ,
51
+ })
52
+ if err != nil {
53
+ if xerrors .Is (err , sql .ErrNoRows ) {
54
+ httpapi .ResourceNotFound (rw )
55
+ return
56
+ }
57
+ httpapi .Write (rw , http .StatusInternalServerError , codersdk.Response {
58
+ Message : "Internal error fetching user." ,
59
+ Detail : err .Error (),
60
+ })
61
+ return
62
+ }
63
+
64
+ workspace , err := api .Database .GetWorkspaceByOwnerIDAndName (ctx , database.GetWorkspaceByOwnerIDAndNameParams {
65
+ OwnerID : user .ID ,
66
+ Name : app .WorkspaceName ,
67
+ })
68
+ if err != nil {
69
+ if xerrors .Is (err , sql .ErrNoRows ) {
70
+ httpapi .ResourceNotFound (rw )
71
+ return
72
+ }
73
+ httpapi .Write (rw , http .StatusInternalServerError , codersdk.Response {
74
+ Message : "Internal error fetching workspace." ,
75
+ Detail : err .Error (),
76
+ })
77
+ return
78
+ }
79
+
80
+ api .proxyWorkspaceApplication (proxyApplication {
81
+ Workspace : workspace ,
82
+ // TODO: Fetch workspace agent
83
+ Agent : database.WorkspaceAgent {},
84
+ AppName : app .AppName ,
85
+ }, rw , r )
34
86
})
35
87
}
36
88
@@ -64,13 +116,13 @@ func ParseSubdomainAppURL(r *http.Request) (Application, error) {
64
116
matchGroup := matches [0 ]
65
117
66
118
return Application {
67
- AppURL : "" ,
68
- AppName : matchGroup [appURL .SubexpIndex ("AppName" )],
69
- Workspace : matchGroup [appURL .SubexpIndex ("WorkspaceName" )],
70
- Agent : matchGroup [appURL .SubexpIndex ("AgentName" )],
71
- User : matchGroup [appURL .SubexpIndex ("UserName" )],
72
- Path : r .URL .Path ,
73
- Domain : domain ,
119
+ AppURL : "" ,
120
+ AppName : matchGroup [appURL .SubexpIndex ("AppName" )],
121
+ WorkspaceName : matchGroup [appURL .SubexpIndex ("WorkspaceName" )],
122
+ Agent : matchGroup [appURL .SubexpIndex ("AgentName" )],
123
+ Username : matchGroup [appURL .SubexpIndex ("UserName" )],
124
+ Path : r .URL .Path ,
125
+ Domain : domain ,
74
126
}, nil
75
127
}
76
128
0 commit comments