Skip to content

Commit 6774d85

Browse files
authored
Glauber/region (#970)
This code is necessary to make local regions work.
2 parents 2b9aad7 + eefc9c8 commit 6774d85

6 files changed

Lines changed: 55 additions & 41 deletions

File tree

internal/cmd/db.go

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,13 @@ func closestLocation(client *turso.Client) (string, error) {
182182
return closest, nil
183183
}
184184

185-
closest, err := client.Locations.Closest()
185+
settings, err := settings.ReadSettings()
186+
if err != nil {
187+
return "", fmt.Errorf("could not read settings file to probe for locations: %w", err)
188+
}
189+
190+
regionUrl := settings.GetRegionURL()
191+
closest, err := client.Locations.Closest(regionUrl)
186192
if err != nil {
187193
// We fallback to ams if we are unable to probe the closest location.
188194
return "ams", err

internal/cmd/db_shell.go

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -20,16 +20,10 @@ import (
2020
"github.com/tursodatabase/turso-cli/internal/turso"
2121
)
2222

23-
var proxy string
24-
2523
func init() {
2624
dbCmd.AddCommand(shellCmd)
2725
addInstanceFlag(shellCmd, "Connect to the database at the specified instance.")
2826
addLocationFlag(shellCmd, "Connect to the database at the specified location.")
29-
shellCmd.Flags().StringVar(&proxy, "proxy", "", "Proxy to use for the connection.")
30-
shellCmd.RegisterFlagCompletionFunc("proxy", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
31-
return []string{}, cobra.ShellCompDirectiveNoFileComp
32-
})
3327
flags.AddAttachClaims(shellCmd)
3428
}
3529

@@ -222,7 +216,7 @@ var shellCmd = &cobra.Command{
222216

223217
shellConfig := shell.ShellConfig{
224218
DbUri: dbUrl,
225-
Proxy: proxy,
219+
Proxy: getTursoProxyUrl(),
226220
AuthToken: authToken,
227221
InF: cmd.InOrStdin(),
228222
OutF: cmd.OutOrStdout(),

internal/cmd/utils.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -261,6 +261,11 @@ func getTursoUrl() string {
261261
return url
262262
}
263263

264+
func getTursoProxyUrl() string {
265+
config, _ := settings.ReadSettings() // ok to ignore, we'll fallback to default
266+
return config.GetProxyURL()
267+
}
268+
264269
func promptConfirmation(prompt string) (bool, error) {
265270
reader := bufio.NewReader(os.Stdin)
266271

internal/settings/settings.go

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package settings
22

33
import (
44
"fmt"
5+
"net/url"
56
"os"
67
"path"
78
"path/filepath"
@@ -34,6 +35,7 @@ func ReadSettings() (*Settings, error) {
3435
configPath := configdir.LocalConfig("turso")
3536
viper.BindEnv("config-path", "TURSO_CONFIG_FOLDER")
3637
viper.BindEnv("baseURL", "TURSO_API_BASEURL")
38+
viper.BindEnv("proxyURL", "TURSO_PROXY_URL")
3739

3840
configPathFlag := viper.GetString("config-path")
3941
if len(configPathFlag) > 0 {
@@ -143,6 +145,21 @@ func (s *Settings) GetBaseURL() string {
143145
return viper.GetString("baseURL")
144146
}
145147

148+
func (s *Settings) GetProxyURL() string {
149+
return viper.GetString("proxyURL")
150+
}
151+
152+
func (s *Settings) GetRegionURL() string {
153+
baseURL := s.GetProxyURL()
154+
parsedURL, err := url.Parse(baseURL)
155+
if err != nil {
156+
return "https://region.turso.io"
157+
}
158+
159+
parsedURL.Host = "region." + parsedURL.Host
160+
return parsedURL.String()
161+
}
162+
146163
func (s *Settings) SetAutoupdate(autoupdate string) {
147164
config := viper.GetStringMap("config")
148165
if config == nil {

internal/turso/locations.go

Lines changed: 2 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import (
44
"fmt"
55
"net/http"
66
"regexp"
7-
"time"
87
"unicode/utf8"
98

109
"github.com/rodaine/table"
@@ -53,8 +52,8 @@ type ClosestLocationResponse struct {
5352
Server string
5453
}
5554

56-
func (c *LocationsClient) Closest() (string, error) {
57-
r, err := c.client.Get("https://region.turso.io", nil)
55+
func (c *LocationsClient) Closest(regionUrl string) (string, error) {
56+
r, err := c.client.Get(regionUrl, nil)
5857
if err != nil {
5958
return "", fmt.Errorf("failed to request closest: %s", err)
6059
}
@@ -73,35 +72,6 @@ func (c *LocationsClient) Closest() (string, error) {
7372
return data.Server, nil
7473
}
7574

76-
func ProbeLocation(location string) *time.Duration {
77-
client := &http.Client{Timeout: 2 * time.Second}
78-
req, err := http.NewRequest("GET", "http://region.turso.io:8080/", nil)
79-
if err != nil {
80-
return nil
81-
}
82-
req.Header.Add("fly-prefer-region", location)
83-
84-
start := time.Now()
85-
r, err := client.Do(req)
86-
if err != nil {
87-
return nil
88-
}
89-
defer r.Body.Close()
90-
91-
dur := time.Since(start)
92-
if r.StatusCode != http.StatusOK {
93-
return nil
94-
}
95-
data, err := unmarshal[ClosestLocationResponse](r)
96-
if err != nil {
97-
return nil
98-
}
99-
if data.Server != location {
100-
return nil
101-
}
102-
return &dur
103-
}
104-
10575
func LocationsTable(columns []interface{}) table.Table {
10676
regex := regexp.MustCompile(`\x1b\[[0-9;]*m`)
10777
return table.New(columns...).WithWidthFunc(func(s string) int {

internal/turso/turso.go

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,17 @@
11
package turso
22

33
import (
4+
"context"
45
"fmt"
56
"io"
67
"mime/multipart"
8+
"net"
79
"net/http"
810
"net/http/httputil"
911
"net/url"
1012
"os"
1113
"runtime"
14+
"strings"
1215

1316
"github.com/tursodatabase/turso-cli/internal/flags"
1417
)
@@ -101,7 +104,26 @@ func (t *Client) do(method, path string, body io.Reader, extraHeaders map[string
101104
if err != nil {
102105
return nil, err
103106
}
104-
resp, err := http.DefaultClient.Do(req)
107+
108+
var client = &http.Client{
109+
// go seems to have issues resolving things like region.localhost:9090, while curl works fine.
110+
// Make sure we can get it to work in those cases by resolving it manually.
111+
Transport: &http.Transport{
112+
DialContext: func(ctx context.Context, network, addr string) (net.Conn, error) {
113+
host, port, err := net.SplitHostPort(addr)
114+
if err != nil {
115+
return nil, err
116+
}
117+
118+
if strings.HasSuffix(host, ".localhost") {
119+
return (&net.Dialer{}).DialContext(ctx, network, net.JoinHostPort("127.0.0.1", port))
120+
}
121+
122+
return (&net.Dialer{}).DialContext(ctx, network, addr)
123+
},
124+
},
125+
}
126+
resp, err := client.Do(req)
105127
if err != nil {
106128
return nil, err
107129
}

0 commit comments

Comments
 (0)