返回 DeepSeek-Reasonix
remote_serve_url.go
根目录 / internal / cli / remote_serve_url.go
1 package cli
2
3 import (
4 "context"
5 "net/http"
6 "net/url"
7 "strings"
8 "time"
9 )
10
11 const remoteServeCapabilityTimeout = 2 * time.Second
12
13 // remoteServeBrowserURL keeps fragments for current Serve versions while
14 // preserving reconnects to already-running legacy processes that only accept
15 // the query-token bootstrap. Probe failures fall back to the compatible path.
16 func remoteServeBrowserURL(ctx context.Context, bound, token string) string {
17 base := "http://" + bound + "/"
18 escapedToken := url.QueryEscape(token)
19 if remoteServeSupportsFragmentToken(ctx, base) {
20 return base + "#token=" + escapedToken
21 }
22 return base + "?token=" + escapedToken
23 }
24
25 // remoteServeSupportsFragmentToken probes without sending the secret. Current
26 // Serve versions expose /auth/token and reject GET with 405; legacy token auth
27 // rejects the unauthenticated request with 401 before routing the endpoint.
28 func remoteServeSupportsFragmentToken(ctx context.Context, base string) bool {
29 probeCtx, cancel := context.WithTimeout(ctx, remoteServeCapabilityTimeout)
30 defer cancel()
31 req, err := http.NewRequestWithContext(probeCtx, http.MethodGet, strings.TrimRight(base, "/")+"/auth/token", nil)
32 if err != nil {
33 return false
34 }
35 req.Close = true
36 client := &http.Client{
37 Transport: &http.Transport{DisableKeepAlives: true},
38 CheckRedirect: func(*http.Request, []*http.Request) error { return http.ErrUseLastResponse },
39 }
40 resp, err := client.Do(req)
41 if err != nil {
42 return false
43 }
44 _ = resp.Body.Close()
45 return resp.StatusCode == http.StatusMethodNotAllowed
46 }
47
47 lines GO