-
Notifications
You must be signed in to change notification settings - Fork 20
[duplicate-code] Duplicate Code Pattern: Random Hex-Encoded Byte Generation #3110
Description
Part of duplicate code analysis: #3108
Summary
Two package-private functions in different packages implement the same logic: create N random bytes with crypto/rand, hex-encode them, and return the result. The functions differ only in byte count and error-handling strategy, making them candidates for a shared utility.
Duplication Details
Pattern: make([]byte, N) → rand.Read → hex.EncodeToString
- Severity: Medium
- Occurrences: 2 instances across 2 files
- Locations:
internal/cmd/root.go(lines 593–599, functiongenerateRandomAPIKey)internal/middleware/jqschema.go(lines 116–123, functiongenerateRandomID)
Instance 1 — internal/cmd/root.go lines 593–599:
// generateRandomAPIKey generates a cryptographically random API key.
// Per spec §7.3, the gateway SHOULD generate a random API key on startup
// if none is provided. Returns a 32-byte hex-encoded string (64 chars).
func generateRandomAPIKey() (string, error) {
bytes := make([]byte, 32)
if _, err := rand.Read(bytes); err != nil {
return "", fmt.Errorf("failed to generate random API key: %w", err)
}
return hex.EncodeToString(bytes), nil
}Instance 2 — internal/middleware/jqschema.go lines 116–123:
// generateRandomID generates a random ID for payload storage
func generateRandomID() string {
bytes := make([]byte, 16)
if _, err := rand.Read(bytes); err != nil {
// Fallback to timestamp-based ID if random fails
return fmt.Sprintf("fallback-%d", os.Getpid())
}
return hex.EncodeToString(bytes)
}The core 3-line pattern (make → rand.Read → hex.EncodeToString) is identical; the differences are byte count (32 vs 16) and error strategy (propagate error vs PID fallback).
Impact Analysis
- Maintainability: Minor — both functions are private and simple. Risk is low unless crypto/rand usage policy changes (e.g., switching to
rand.Readdeprecation in Go 1.20+) - Bug Risk: Low — both functions are independently correct
- Code Bloat: Minor (~10 lines duplicated), but the pattern could recur if more random IDs are needed elsewhere
Refactoring Recommendations
-
Add a
RandomHex(n int) (string, error)helper tointernal/strutil(the existing home for string utilities likeTruncateandDeduplicate):// RandomHex returns a hex-encoded string of n cryptographically random bytes. // The returned string has length 2*n. func RandomHex(n int) (string, error) { b := make([]byte, n) if _, err := rand.Read(b); err != nil { return "", fmt.Errorf("failed to generate %d random bytes: %w", n, err) } return hex.EncodeToString(b), nil }
-
Update callers:
generateRandomAPIKey()ininternal/cmd/root.go: replace body withreturn strutil.RandomHex(32)generateRandomID()ininternal/middleware/jqschema.go: replace withid, err := strutil.RandomHex(16)and apply the PID fallback on error
-
Alternative: Keep functions as-is if the different error strategies are intentional design choices and the duplication is considered acceptable for the small size. Document the decision with a comment.
Implementation Checklist
- Add
RandomHex(or equivalent) tointernal/strutil - Update
generateRandomAPIKeyininternal/cmd/root.go - Update
generateRandomIDininternal/middleware/jqschema.go - Add unit tests for
RandomHexininternal/strutil - Verify no behavioral regression in API key generation or payload ID generation
Parent Issue
See parent analysis report: #3108
Related to #3108
Generated by Duplicate Code Detector · ◷
- expires on Apr 10, 2026, 6:01 AM UTC