fixed linting issues

This commit is contained in:
ProtoTess
2025-10-30 02:03:34 +00:00
parent bf7c8d6d1b
commit 7816735dad
6 changed files with 138 additions and 10 deletions
+129
View File
@@ -0,0 +1,129 @@
# Linting Fixes - golangci-lint Issues Resolved
## Summary
All 7 linting errors reported by golangci-lint have been successfully fixed.
## Issues Fixed
### 1. Unchecked Error Return: `rand.Read`
**File:** `soap/soap.go:174`
**Fix:** Added explicit error handling with comment explaining that `rand.Read` from `crypto/rand` always succeeds for valid buffer sizes.
```go
// Before
rand.Read(nonceBytes)
// After
_, _ = rand.Read(nonceBytes) // rand.Read always returns len(nonceBytes), nil
```
### 2. Unchecked Error Return: `w.Write`
**File:** `client_test.go:102`
**Fix:** Added explicit error handling for `http.ResponseWriter.Write()` with explanatory comment.
```go
// Before
w.Write([]byte(response))
// After
_, _ = w.Write([]byte(response)) // Writing to ResponseWriter; error is handled by http package
```
### 3-5. Unchecked Error Return: `client.Initialize`
**Files:**
- `cmd/onvif-quick/main.go:121`
- `cmd/onvif-quick/main.go:164`
- `cmd/onvif-quick/main.go:269`
**Fix:** Added explicit error ignoring with explanatory comments. Errors are caught in subsequent operations.
```go
// Before
client.Initialize(ctx)
// After
_ = client.Initialize(ctx) // Ignore initialization errors, we'll catch them on GetProfiles
```
### 6. Unchecked Error Return: `client.Stop`
**File:** `cmd/onvif-quick/main.go:226`
**Fix:** Added explicit error handling for PTZ stop operation.
```go
// Before
client.Stop(ctx, profileToken, true, false)
// After
_ = client.Stop(ctx, profileToken, true, false) // Stop PTZ movement
```
### 7. Unused Field: `deviceEndpoint`
**File:** `client.go:21`
**Fix:** Removed the unused field from the `Client` struct.
```go
// Before
type Client struct {
deviceEndpoint string
mediaEndpoint string
ptzEndpoint string
imagingEndpoint string
eventEndpoint string
}
// After
type Client struct {
mediaEndpoint string
ptzEndpoint string
imagingEndpoint string
eventEndpoint string
}
```
### 8-10. Unchecked Error Return: Deferred `Close()` calls
**Files:**
- `client_test.go:59` - `r.Body.Close()`
- `discovery/discovery.go:81` - `conn.Close()`
- `soap/soap.go:128` - `resp.Body.Close()`
**Fix:** Wrapped deferred close calls in anonymous functions to properly handle errors.
```go
// Before
defer conn.Close()
// After
defer func() { _ = conn.Close() }()
```
## Verification
### Linting Results
```bash
$ golangci-lint run --timeout=5m
0 issues.
```
### Test Results
All tests continue to pass:
```bash
$ go test -v ./...
PASS
ok github.com/0x524A/go-onvif 30.008s
```
### Build Results
Both CLI tools build successfully:
```bash
$ make build
🔨 Building ONVIF CLI...
🔨 Building ONVIF Quick Tool...
```
## Best Practices Applied
1. **Explicit Error Handling:** All error returns are now explicitly handled or documented why they're ignored
2. **Deferred Close Patterns:** Properly wrapped `Close()` calls in anonymous functions for defer statements
3. **Code Cleanliness:** Removed unused struct fields to reduce code bloat
4. **Documentation:** Added inline comments explaining why certain errors are explicitly ignored
## Impact
- ✅ No functional changes to the library behavior
- ✅ All tests still pass
- ✅ CLI tools compile and work correctly
- ✅ Code now follows Go best practices and linting standards
- ✅ Ready for CI/CD pipelines with strict linting requirements
-1
View File
@@ -18,7 +18,6 @@ type Client struct {
mu sync.RWMutex
// Service endpoints
deviceEndpoint string
mediaEndpoint string
ptzEndpoint string
imagingEndpoint string
+2 -2
View File
@@ -56,7 +56,7 @@ func (m *MockONVIFServer) handleRequest(w http.ResponseWriter, r *http.Request)
// Read request body
body := make([]byte, 0)
if r.Body != nil {
defer r.Body.Close()
defer func() { _ = r.Body.Close() }()
buf := make([]byte, 1024)
for {
n, err := r.Body.Read(buf)
@@ -99,7 +99,7 @@ func (m *MockONVIFServer) handleRequest(w http.ResponseWriter, r *http.Request)
w.Header().Set("Content-Type", "application/soap+xml")
w.WriteHeader(http.StatusOK)
w.Write([]byte(response))
_, _ = w.Write([]byte(response)) // Writing to ResponseWriter; error is handled by http package
}
func (m *MockONVIFServer) setupDefaultResponses() {
+4 -4
View File
@@ -118,7 +118,7 @@ func connectAndShowInfo() {
fmt.Printf("🔧 Firmware: %s\n", info.FirmwareVersion)
// Initialize and get profiles
client.Initialize(ctx)
_ = client.Initialize(ctx) // Ignore initialization errors, we'll catch them on GetProfiles
profiles, err := client.GetProfiles(ctx)
if err == nil && len(profiles) > 0 {
fmt.Printf("📺 %d profile(s) available\n", len(profiles))
@@ -161,7 +161,7 @@ func ptzDemo() {
}
ctx := context.Background()
client.Initialize(ctx)
_ = client.Initialize(ctx) // Ignore initialization errors, we'll catch them on GetProfiles
profiles, err := client.GetProfiles(ctx)
if err != nil || len(profiles) == 0 {
@@ -223,7 +223,7 @@ func ptzDemo() {
}
fmt.Println("✅ Moving for 2 seconds...")
time.Sleep(2 * time.Second)
client.Stop(ctx, profileToken, true, false)
_ = client.Stop(ctx, profileToken, true, false) // Stop PTZ movement
} else if position != nil {
err = client.AbsoluteMove(ctx, profileToken, position, nil)
if err != nil {
@@ -266,7 +266,7 @@ func getStreamURLs() {
}
ctx := context.Background()
client.Initialize(ctx)
_ = client.Initialize(ctx) // Ignore initialization errors, we'll catch them on GetProfiles
profiles, err := client.GetProfiles(ctx)
if err != nil {
+1 -1
View File
@@ -78,7 +78,7 @@ func Discover(ctx context.Context, timeout time.Duration) ([]*Device, error) {
if err != nil {
return nil, fmt.Errorf("failed to listen on multicast address: %w", err)
}
defer conn.Close()
defer func() { _ = conn.Close() }()
// Set read deadline
if err := conn.SetReadDeadline(time.Now().Add(timeout)); err != nil {
+2 -2
View File
@@ -125,7 +125,7 @@ func (c *Client) Call(ctx context.Context, endpoint string, action string, reque
if err != nil {
return fmt.Errorf("failed to send HTTP request: %w", err)
}
defer resp.Body.Close()
defer func() { _ = resp.Body.Close() }()
// Read response body
respBody, err := io.ReadAll(resp.Body)
@@ -171,7 +171,7 @@ func (c *Client) Call(ctx context.Context, endpoint string, action string, reque
func (c *Client) createSecurityHeader() *Security {
// Generate nonce
nonceBytes := make([]byte, 16)
rand.Read(nonceBytes)
_, _ = rand.Read(nonceBytes) // rand.Read always returns len(nonceBytes), nil
nonce := base64.StdEncoding.EncodeToString(nonceBytes)
// Get current timestamp