Skip to content

Commit

Permalink
Codespaces: Use the host name from the logged in server for commands (c…
Browse files Browse the repository at this point in the history
…li#7795)

* Use the host name from the logged in server for codespace commands

* Fix existing tests

* Add tests for server url configuration

* Rename defaultApiUrl to defaultAPIURL and comment cleanup

* Switch to t.Setenv in codespaces api tests

* Switch to t.Setenv in other tests

* Support custom server in web flows for list and create

* Rename GetServerURL() to ServerURL()
  • Loading branch information
jkeech authored Aug 8, 2023
1 parent e0d2fc8 commit 93e1511
Show file tree
Hide file tree
Showing 26 changed files with 409 additions and 194 deletions.
64 changes: 42 additions & 22 deletions internal/codespaces/api/api.go
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
package api

// For descriptions of service interfaces, see:
// - https://online.visualstudio.com/api/swagger (for visualstudio.com)
// - https://docs.github.com/en/rest/reference/repos (for api.github.com)
// - https://github.com/github/github/blob/master/app/api/codespaces.rb (for vscs_internal)
// TODO(adonovan): replace the last link with a public doc URL when available.

// TODO(adonovan): a possible reorganization would be to split this
// file into three internal packages, one per backend service, and to
// file into two internal packages, one per backend service, and to
// rename api.API to github.Client:
//
// - github.GetUser(github.Client)
Expand All @@ -20,7 +19,6 @@ package api
// - codespaces.GetToken(Client, login, name)
// - codespaces.List(Client, user)
// - codespaces.Start(Client, token, codespace)
// - visualstudio.GetRegionLocation(http.Client) // no dependency on github
//
// This would make the meaning of each operation clearer.

Expand All @@ -34,6 +32,7 @@ import (
"io"
"net/http"
"net/url"
"os"
"reflect"
"regexp"
"strconv"
Expand All @@ -42,13 +41,14 @@ import (

"github.com/cenkalti/backoff/v4"
"github.com/cli/cli/v2/api"
"github.com/cli/cli/v2/internal/ghinstance"
"github.com/cli/cli/v2/pkg/cmdutil"
"github.com/opentracing/opentracing-go"
)

const (
githubServer = "https://github.com"
githubAPI = "https://api.github.com"
vscsAPI = "https://online.visualstudio.com"
defaultAPIURL = "https://api.github.com"
defaultServerURL = "https://github.com"
)

const (
Expand All @@ -60,31 +60,40 @@ const (

// API is the interface to the codespace service.
type API struct {
client httpClient
vscsAPI string
client func() (*http.Client, error)
githubAPI string
githubServer string
retryBackoff time.Duration
}

type httpClient interface {
Do(req *http.Request) (*http.Response, error)
}

// New creates a new API client connecting to the configured endpoints with the HTTP client.
func New(serverURL, apiURL, vscsURL string, httpClient httpClient) *API {
if serverURL == "" {
serverURL = githubServer
}
func New(f *cmdutil.Factory) *API {
apiURL := os.Getenv("GITHUB_API_URL")
if apiURL == "" {
apiURL = githubAPI
cfg, err := f.Config()
if err != nil {
// fallback to the default api endpoint
apiURL = defaultAPIURL
} else {
host, _ := cfg.Authentication().DefaultHost()
apiURL = ghinstance.RESTPrefix(host)
}
}
if vscsURL == "" {
vscsURL = vscsAPI

serverURL := os.Getenv("GITHUB_SERVER_URL")
if serverURL == "" {
cfg, err := f.Config()
if err != nil {
// fallback to the default server endpoint
serverURL = defaultServerURL
} else {
host, _ := cfg.Authentication().DefaultHost()
serverURL = ghinstance.HostPrefix(host)
}
}

return &API{
client: httpClient,
vscsAPI: strings.TrimSuffix(vscsURL, "/"),
client: f.HttpClient,
githubAPI: strings.TrimSuffix(apiURL, "/"),
githubServer: strings.TrimSuffix(serverURL, "/"),
retryBackoff: 100 * time.Millisecond,
Expand All @@ -97,6 +106,11 @@ type User struct {
Type string `json:"type"`
}

// ServerURL returns the server url (not the API url), such as https://github.com
func (a *API) ServerURL() string {
return a.githubServer
}

// GetUser returns the user associated with the given token.
func (a *API) GetUser(ctx context.Context) (*User, error) {
req, err := http.NewRequest(http.MethodGet, a.githubAPI+"/user", nil)
Expand Down Expand Up @@ -1119,7 +1133,13 @@ func (a *API) do(ctx context.Context, req *http.Request, spanName string) (*http
span, ctx := opentracing.StartSpanFromContext(ctx, spanName)
defer span.Finish()
req = req.WithContext(ctx)
return a.client.Do(req)

httpClient, err := a.client()
if err != nil {
return nil, err
}

return httpClient.Do(req)
}

// setHeaders sets the required headers for the API.
Expand Down
Loading

0 comments on commit 93e1511

Please sign in to comment.