дȫÏîĿÉó²éÎÊÌⲢ·¢²¼ v1.1.9
¸ÄÓñ¾»ú¶ÀÁ¢ CA£¬»ָ´ CLI TLS УÑ飬±£»¤ƾ¾ÝÓëÅäÖò¢·¢±£´档 д Cursor Êý¾ݡ¢»Ự·¾¶¡¢´úÀíÉúÃüÖÜÆڡ¢ģÐÍÇëÇóÓë Skills Îļþ²Ù×÷¡£ Ϊ¶ÀÁ¢ Tab ·þÎñÔö¼ӿͻ§¶˼øȨ£¬Éý¼¶ÒÀÀµÓ빤¾ßÁ´£¬ÍêÉƷ¢²¼ԪÐÅϢͬ²½¡£ Ñé֤£ºÁ½¸ö Go ģ¿éµIJâÊÔ/vet¡¢¹ؼüģ¿é race¡¢ǰ¶˲âÊÔ/Éú²ú¹¹½¨/Éó¼ơ¢ Go ¿ɴï©¶´ɨÃèÓë macOS/Linux ¿ÉÐÐģ¿齻²æ±àÒë¾ùͨ¹ý¡£ Windows ¸ôÀëÆô¶¯ͨ¹ý£»δÍê³ɵĵã»÷ðÑ̺ÍԭÉúƽ̨Ñé֤¼ûÉó²鱨¸档
This commit is contained in:
@@ -58,8 +58,34 @@ type ProxyState struct {
|
||||
|
||||
// StartProxy 用于处理与 StartProxy 相关的逻辑。
|
||||
func (s *ProxyService) StartProxy() (ProxyState, error) {
|
||||
if s == nil {
|
||||
return ProxyState{}, fmt.Errorf("服务未初始化")
|
||||
}
|
||||
s.lifecycleMu.Lock()
|
||||
defer s.lifecycleMu.Unlock()
|
||||
if s.backend() != nil && s.backend().IsRunning() && s.proxyServer() != nil && s.proxyServer().IsRunning() {
|
||||
return s.GetState(), nil
|
||||
}
|
||||
startedBackend, startedProxy, settingsAttempted := false, false, false
|
||||
rollback := func() {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
||||
defer cancel()
|
||||
if startedProxy && s.proxyServer() != nil {
|
||||
_ = s.proxyServer().Stop(ctx)
|
||||
}
|
||||
if settingsAttempted {
|
||||
if err := s.ClearCursorSettings(); err != nil {
|
||||
logger.Error("startup rollback failed", "error", err)
|
||||
}
|
||||
}
|
||||
if startedBackend && s.backend() != nil {
|
||||
_ = s.backend().Stop(ctx)
|
||||
}
|
||||
}
|
||||
|
||||
logger.Infof("start service requested config_path=%s logs_root=%s", s.configPath, s.logsRoot)
|
||||
fail := func(step string, err error) (ProxyState, error) {
|
||||
rollback()
|
||||
logger.Errorf("start service failed step=%s err=%v", step, err)
|
||||
s.setLastError(err)
|
||||
s.emitState()
|
||||
@@ -72,51 +98,43 @@ func (s *ProxyService) StartProxy() (ProxyState, error) {
|
||||
if err := s.ensureBackendHost(); err != nil {
|
||||
return fail("ensure_backend_host", err)
|
||||
}
|
||||
if !s.backendHost.IsRunning() {
|
||||
logger.Infof("starting embedded backend listen_addr=%s", s.backendHost.ListenAddr())
|
||||
if err := s.backendHost.Start(); err != nil {
|
||||
if !s.backend().IsRunning() {
|
||||
logger.Infof("starting embedded backend listen_addr=%s", s.backend().ListenAddr())
|
||||
if err := s.backend().Start(); err != nil {
|
||||
return fail("start_backend", err)
|
||||
}
|
||||
startedBackend = true
|
||||
} else {
|
||||
logger.Infof("embedded backend already running listen_addr=%s", s.backendHost.ListenAddr())
|
||||
logger.Infof("embedded backend already running listen_addr=%s", s.backend().ListenAddr())
|
||||
}
|
||||
healthCtx, healthCancel := context.WithTimeout(context.Background(), backendReadyTimeout)
|
||||
defer healthCancel()
|
||||
if err := s.waitForBackend(healthCtx); err != nil {
|
||||
return fail("wait_backend_ready", err)
|
||||
}
|
||||
logger.Infof("embedded backend ready listen_addr=%s", s.backendHost.ListenAddr())
|
||||
logger.Infof("embedded backend ready listen_addr=%s", s.backend().ListenAddr())
|
||||
if err := s.ensureProxy(cfg); err != nil {
|
||||
return fail("ensure_proxy", err)
|
||||
}
|
||||
|
||||
if s.proxyServer() != nil && !s.proxyServer().IsRunning() {
|
||||
logger.Infof("starting mitm proxy listen_addr=%s", s.proxyServer().Snapshot().ListenAddr)
|
||||
if err := s.proxyServer().Start(); err != nil {
|
||||
return fail("start_mitm_proxy", err)
|
||||
}
|
||||
startedProxy = true
|
||||
}
|
||||
|
||||
settingsAttempted = true
|
||||
if err := s.ApplyCursorSettings(); err != nil {
|
||||
return fail("apply_cursor_settings", err)
|
||||
}
|
||||
// 启动时注入账号信息
|
||||
if err := cursor.InjectCursorUserInfo(localruntime.InjectAccountEmail, localruntime.InjectAuthToken); err != nil {
|
||||
logger.Errorf("injectCursorUserInfo failed: %v", err)
|
||||
// 不阻断启动,仅记录日志
|
||||
}
|
||||
|
||||
if s.proxy != nil && !s.proxy.IsRunning() {
|
||||
logger.Infof("starting mitm proxy listen_addr=%s", s.proxy.Snapshot().ListenAddr)
|
||||
if err := s.proxy.Start(); err != nil {
|
||||
return fail("start_mitm_proxy", err)
|
||||
}
|
||||
}
|
||||
|
||||
if err := s.ApplyCursorSettings(); err != nil {
|
||||
stopCtx, stopCancel := context.WithTimeout(context.Background(), 5*time.Second)
|
||||
defer stopCancel()
|
||||
if s.proxy != nil {
|
||||
_ = s.proxy.Stop(stopCtx)
|
||||
}
|
||||
_ = s.backendHost.Stop(stopCtx)
|
||||
startErr := fmt.Errorf("服务已启动,但注入 Cursor 配置失败: %w", err)
|
||||
logger.Errorf("start service failed step=apply_cursor_settings err=%v", startErr)
|
||||
s.setLastError(startErr)
|
||||
s.emitState()
|
||||
return s.GetState(), startErr
|
||||
}
|
||||
|
||||
s.setLastError(nil)
|
||||
s.emitState()
|
||||
state := s.GetState()
|
||||
@@ -133,6 +151,11 @@ func (s *ProxyService) StartProxy() (ProxyState, error) {
|
||||
// 各清理步骤失败时记录错误但继续执行后续步骤,保证 backend 最终被停止,
|
||||
// 避免"Cursor 配置已清理但 backend 仍在运行"的不一致状态。
|
||||
func (s *ProxyService) StopProxy() (ProxyState, error) {
|
||||
if s == nil {
|
||||
return ProxyState{}, nil
|
||||
}
|
||||
s.lifecycleMu.Lock()
|
||||
defer s.lifecycleMu.Unlock()
|
||||
logger.Infof("stop service requested")
|
||||
var stopErrors []error
|
||||
fail := func(step string, err error) {
|
||||
@@ -144,15 +167,15 @@ func (s *ProxyService) StopProxy() (ProxyState, error) {
|
||||
}
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
||||
defer cancel()
|
||||
if s.proxy != nil && s.proxy.IsRunning() {
|
||||
logger.Infof("stopping mitm proxy listen_addr=%s", s.proxy.Snapshot().ListenAddr)
|
||||
fail("stop_mitm_proxy", s.proxy.Stop(ctx))
|
||||
if s.proxyServer() != nil && s.proxyServer().IsRunning() {
|
||||
logger.Infof("stopping mitm proxy listen_addr=%s", s.proxyServer().Snapshot().ListenAddr)
|
||||
fail("stop_mitm_proxy", s.proxyServer().Stop(ctx))
|
||||
}
|
||||
|
||||
fail("clear_cursor_settings", s.ClearCursorSettings())
|
||||
if s.backendHost != nil {
|
||||
logger.Infof("stopping embedded backend listen_addr=%s", s.backendHost.ListenAddr())
|
||||
fail("stop_backend", s.backendHost.Stop(ctx))
|
||||
if s.backend() != nil {
|
||||
logger.Infof("stopping embedded backend listen_addr=%s", s.backend().ListenAddr())
|
||||
fail("stop_backend", s.backend().Stop(ctx))
|
||||
}
|
||||
|
||||
if len(stopErrors) > 0 {
|
||||
@@ -177,8 +200,8 @@ func (s *ProxyService) StopProxy() (ProxyState, error) {
|
||||
// GetState 用于处理与 GetState 相关的逻辑。
|
||||
func (s *ProxyService) GetState() ProxyState {
|
||||
var proxySnap mitm.Snapshot
|
||||
if s.proxy != nil {
|
||||
proxySnap = s.proxy.Snapshot()
|
||||
if s.proxyServer() != nil {
|
||||
proxySnap = s.proxyServer().Snapshot()
|
||||
}
|
||||
s.mu.RLock()
|
||||
lastError := s.lastError
|
||||
@@ -188,11 +211,11 @@ func (s *ProxyService) GetState() ProxyState {
|
||||
backendRunning := false
|
||||
cliHTTPSListenAddr := ""
|
||||
cliHTTPSRunning := false
|
||||
if s.backendHost != nil {
|
||||
backendListenAddr = s.backendHost.ListenAddr()
|
||||
backendRunning = s.backendHost.IsRunning()
|
||||
cliHTTPSListenAddr = s.backendHost.CLIHTTPSListenAddr()
|
||||
cliHTTPSRunning = s.backendHost.CLIHTTPSRunning()
|
||||
if s.backend() != nil {
|
||||
backendListenAddr = s.backend().ListenAddr()
|
||||
backendRunning = s.backend().IsRunning()
|
||||
cliHTTPSListenAddr = s.backend().CLIHTTPSListenAddr()
|
||||
cliHTTPSRunning = s.backend().CLIHTTPSRunning()
|
||||
}
|
||||
netProxy := netproxy.CurrentStatus()
|
||||
return ProxyState{
|
||||
@@ -263,20 +286,27 @@ func (s *ProxyService) emitState() {
|
||||
|
||||
// ShutdownForQuit 用于处理与 ShutdownForQuit 相关的逻辑。
|
||||
func (s *ProxyService) ShutdownForQuit() {
|
||||
s.lifecycleMu.Lock()
|
||||
defer s.lifecycleMu.Unlock()
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
||||
defer cancel()
|
||||
var finalErr error
|
||||
|
||||
if s.proxy != nil {
|
||||
if err := s.proxy.Stop(ctx); err != nil && !errors.Is(err, context.Canceled) {
|
||||
if s.proxyServer() != nil {
|
||||
if err := s.proxyServer().Stop(ctx); err != nil && !errors.Is(err, context.Canceled) {
|
||||
finalErr = err
|
||||
}
|
||||
}
|
||||
if err := s.ClearCursorSettings(); err != nil {
|
||||
finalErr = errors.Join(finalErr, err)
|
||||
s.mu.RLock()
|
||||
applied := s.cursorSettingsApplied
|
||||
s.mu.RUnlock()
|
||||
if applied {
|
||||
if err := s.ClearCursorSettings(); err != nil {
|
||||
finalErr = errors.Join(finalErr, err)
|
||||
}
|
||||
}
|
||||
if s.backendHost != nil {
|
||||
if err := s.backendHost.Stop(ctx); err != nil && !errors.Is(err, context.Canceled) {
|
||||
if s.backend() != nil {
|
||||
if err := s.backend().Stop(ctx); err != nil && !errors.Is(err, context.Canceled) {
|
||||
finalErr = errors.Join(finalErr, err)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user