fix: 아키텍처 리뷰 이슈 3건 수정
- 명령줄 토큰 노출 제거 — exec.Command에서 -token 인자 제거, 환경변수(A301_TOKEN)만 사용 - redeemTicket 재시도 추가 — 3회 exponential backoff, 4xx는 즉시 실패 - 임시 추출 디렉토리 defer os.RemoveAll 추가 — 중복 정리 코드 제거 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -191,17 +191,15 @@ func doDownload(downloadURL, destDir string) error {
|
||||
if err != nil {
|
||||
return fmt.Errorf("임시 추출 디렉토리 생성 실패: %w", err)
|
||||
}
|
||||
defer os.RemoveAll(tmpExtractDir)
|
||||
|
||||
if err := extractZip(tmpPath, tmpExtractDir); err != nil {
|
||||
os.RemoveAll(tmpExtractDir)
|
||||
return err
|
||||
}
|
||||
|
||||
if err := moveContents(tmpExtractDir, destDir); err != nil {
|
||||
os.RemoveAll(tmpExtractDir)
|
||||
return fmt.Errorf("파일 이동 실패: %w", err)
|
||||
}
|
||||
os.RemoveAll(tmpExtractDir)
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
4
main.go
4
main.go
@@ -58,7 +58,7 @@ func handleURI(rawURI string) error {
|
||||
if _, statErr := os.Stat(gamePath); statErr == nil {
|
||||
ret := msgBox("One of the plans", "서버에 연결할 수 없습니다.\n설치된 게임을 실행하시겠습니까?\n(업데이트 확인 불가)", mbYesNo|mbQ)
|
||||
if ret == idYes {
|
||||
cmd := exec.Command(gamePath, "-token", token)
|
||||
cmd := exec.Command(gamePath)
|
||||
cmd.Dir = gameDir
|
||||
cmd.Env = append(os.Environ(), "A301_TOKEN="+token)
|
||||
if err := cmd.Start(); err != nil {
|
||||
@@ -86,7 +86,7 @@ func handleURI(rawURI string) error {
|
||||
return err
|
||||
}
|
||||
|
||||
cmd := exec.Command(gamePath, "-token", token)
|
||||
cmd := exec.Command(gamePath)
|
||||
cmd.Dir = gameDir
|
||||
cmd.Env = append(os.Environ(), "A301_TOKEN="+token)
|
||||
if err := cmd.Start(); err != nil {
|
||||
|
||||
21
protocol.go
21
protocol.go
@@ -156,8 +156,24 @@ func fetchServerInfo() (*downloadInfo, error) {
|
||||
}
|
||||
|
||||
// redeemTicket exchanges a one-time launch ticket for a fresh JWT access token.
|
||||
// Retries up to 3 times with exponential backoff on transient errors.
|
||||
func redeemTicket(ticket string) (string, error) {
|
||||
return redeemTicketFrom(redeemTicketURL, ticket)
|
||||
const maxRetries = 3
|
||||
var lastErr error
|
||||
for i := range maxRetries {
|
||||
token, err := redeemTicketFrom(redeemTicketURL, ticket)
|
||||
if err == nil {
|
||||
return token, nil
|
||||
}
|
||||
lastErr = err
|
||||
// HTTP 4xx errors should not be retried
|
||||
var noRetry *errNoRetry
|
||||
if errors.As(err, &noRetry) {
|
||||
return "", err
|
||||
}
|
||||
time.Sleep(time.Duration(1<<i) * time.Second)
|
||||
}
|
||||
return "", fmt.Errorf("인증 실패 (%d회 재시도): %w", maxRetries, lastErr)
|
||||
}
|
||||
|
||||
func redeemTicketFrom(url, ticket string) (string, error) {
|
||||
@@ -173,6 +189,9 @@ func redeemTicketFrom(url, ticket string) (string, error) {
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
if resp.StatusCode >= 400 && resp.StatusCode < 500 {
|
||||
return "", &errNoRetry{fmt.Errorf("런처 인증에 실패했습니다 (HTTP %d)", resp.StatusCode)}
|
||||
}
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
return "", fmt.Errorf("런처 인증에 실패했습니다 (HTTP %d)", resp.StatusCode)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user