@@ -5,13 +5,74 @@ import (
5
5
"encoding/json"
6
6
"io"
7
7
"net/http"
8
+ "net/url"
8
9
10
+ "github.com/google/uuid"
9
11
"golang.org/x/xerrors"
10
12
13
+ "github.com/coder/coder/coderd/httpmw"
11
14
"github.com/coder/coder/coderd/workspaceapps"
12
15
"github.com/coder/coder/codersdk"
13
16
)
14
17
18
+ // Client is a HTTP client for a subset of Coder API routes that external
19
+ // proxies need.
20
+ type Client struct {
21
+ SDKClient * codersdk.Client
22
+ // HACK: the issue-signed-app-token requests may issue redirect responses
23
+ // (which need to be forwarded to the client), so the client we use to make
24
+ // those requests must ignore redirects.
25
+ sdkClientIgnoreRedirects * codersdk.Client
26
+ }
27
+
28
+ // New creates a external proxy client for the provided primary coder server
29
+ // URL.
30
+ func New (serverURL * url.URL ) * Client {
31
+ sdkClient := codersdk .New (serverURL )
32
+ sdkClient .SessionTokenHeader = httpmw .WorkspaceProxyAuthTokenHeader
33
+
34
+ sdkClientIgnoreRedirects := codersdk .New (serverURL )
35
+ sdkClientIgnoreRedirects .HTTPClient .CheckRedirect = func (req * http.Request , via []* http.Request ) error {
36
+ return http .ErrUseLastResponse
37
+ }
38
+ sdkClientIgnoreRedirects .SessionTokenHeader = httpmw .WorkspaceProxyAuthTokenHeader
39
+
40
+ return & Client {
41
+ SDKClient : sdkClient ,
42
+ sdkClientIgnoreRedirects : sdkClientIgnoreRedirects ,
43
+ }
44
+ }
45
+
46
+ // SetSessionToken sets the session token for the client. An error is returned
47
+ // if the session token is not in the correct format for external proxies.
48
+ func (c * Client ) SetSessionToken (token string ) error {
49
+ c .SDKClient .SetSessionToken (token )
50
+ c .sdkClientIgnoreRedirects .SetSessionToken (token )
51
+ return nil
52
+ }
53
+
54
+ // SessionToken returns the currently set token for the client.
55
+ func (c * Client ) SessionToken () string {
56
+ return c .SDKClient .SessionToken ()
57
+ }
58
+
59
+ // Request wraps the underlying codersdk.Client's Request method.
60
+ func (c * Client ) Request (ctx context.Context , method , path string , body interface {}, opts ... codersdk.RequestOption ) (* http.Response , error ) {
61
+ return c .SDKClient .Request (ctx , method , path , body , opts ... )
62
+ }
63
+
64
+ // RequestIgnoreRedirects wraps the underlying codersdk.Client's Request method
65
+ // on the client that ignores redirects.
66
+ func (c * Client ) RequestIgnoreRedirects (ctx context.Context , method , path string , body interface {}, opts ... codersdk.RequestOption ) (* http.Response , error ) {
67
+ return c .sdkClientIgnoreRedirects .Request (ctx , method , path , body , opts ... )
68
+ }
69
+
70
+ // DialWorkspaceAgent calls the underlying codersdk.Client's DialWorkspaceAgent
71
+ // method.
72
+ func (c * Client ) DialWorkspaceAgent (ctx context.Context , agentID uuid.UUID , options * codersdk.DialWorkspaceAgentOptions ) (agentConn * codersdk.WorkspaceAgentConn , err error ) {
73
+ return c .SDKClient .DialWorkspaceAgent (ctx , agentID , options )
74
+ }
75
+
15
76
type IssueSignedAppTokenResponse struct {
16
77
// SignedTokenStr should be set as a cookie on the response.
17
78
SignedTokenStr string `json:"signed_token_str"`
0 commit comments