Skip to content

Commit 1212cdd

Browse files
feat: add structured error responses for handler errors (#57)
* feat(errors): add Error proto message for structured handler errors - Add Error message with string message field - Provides structured error responses for handler failures - Consistent with existing ValidationError pattern * build(proto): regenerate Go code with new Error message - Update errors.pb.go with Error type and methods - Regenerate annotations.pb.go and headers.pb.go with latest protoc - Generated code includes proper protobuf bindings for Error message * feat(httpgen): replace plain string errors with structured Error responses - Add generateWriteErrorResponseFunc to create error response helper - Replace http.Error calls with structured sebufhttp.Error messages - Apply consistent error handling for handler, marshal, and write errors - Maintain HTTP 500 status code for internal server errors - Serialize errors as JSON/protobuf based on request Content-Type * chore(dev): update coverage reports and development settings - Update coverage badge and reports after test execution - Update local Claude settings for development workflow * docs: update documentation for structured error handling - Add comprehensive error handling section to http-generation.md - Document Error proto message and handler error responses - Update key features to include structured error responses - Modernize CLAUDE.md examples to use structured error functions - Add error hierarchy and response format examples - Include JSON and protobuf serialization details Reflects new Error message implementation and writeErrorResponse function. * refactor(httpgen): eliminate code duplication in error response functions - Extract common logic into shared writeProtoMessageResponse helper - Replace duplicated marshaling logic in validation and handler error functions - Fix golangci-lint duplication warnings (dupl) - Maintain identical functionality while reducing code repetition - Fix line length formatting issues
1 parent 9c38676 commit 1212cdd

File tree

11 files changed

+1821
-50
lines changed

11 files changed

+1821
-50
lines changed

.claude/settings.local.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,8 @@
3939
"Bash(./generate_golden.sh:*)",
4040
"Bash(UPDATE_GOLDEN=1 go test -run TestExhaustiveGoldenFiles)",
4141
"Bash(git restore:*)",
42-
"Bash(git checkout:*)"
42+
"Bash(git checkout:*)",
43+
"Bash(./scripts/run_tests.sh:*)"
4344
],
4445
"deny": [],
4546
"ask": [],

CLAUDE.md

Lines changed: 10 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ func BindingMiddleware[Req any](next http.Handler) http.Handler {
7272
// Automatic body validation happens here
7373
if msg, ok := any(toBind).(proto.Message); ok {
7474
if err := ValidateMessage(msg); err != nil {
75-
http.Error(w, err.Error(), http.StatusBadRequest)
75+
writeValidationError(w, r, err)
7676
return
7777
}
7878
}
@@ -86,17 +86,9 @@ func HeaderValidationMiddleware(requiredHeaders []HeaderConfig) func(http.Handle
8686
return func(next http.Handler) http.Handler {
8787
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
8888
// Validate required headers
89-
for _, header := range requiredHeaders {
90-
value := r.Header.Get(header.Name)
91-
if header.Required && value == "" {
92-
http.Error(w, fmt.Sprintf("Missing required header: %s", header.Name), http.StatusBadRequest)
93-
return
94-
}
95-
// Type and format validation
96-
if err := validateHeaderValue(value, header.Type, header.Format); err != nil {
97-
http.Error(w, err.Error(), http.StatusBadRequest)
98-
return
99-
}
89+
if validationErr := validateHeaders(r, serviceHeaders, methodHeaders); validationErr != nil {
90+
writeValidationErrorResponse(w, r, validationErr)
91+
return
10092
}
10193
next.ServeHTTP(w, r)
10294
})
@@ -265,9 +257,12 @@ service UserService {
265257
```
266258

267259
### Error Handling
268-
- **HTTP 400 responses**: Validation errors return Bad Request with error message for both body and header validation failures
269-
- **Detailed errors**: Full validation error details from protovalidate for body validation
270-
- **Header errors**: Clear messages indicating which header failed validation and why
260+
- **Structured Error Responses**: All errors use protobuf messages for consistent API responses
261+
- **Validation Errors (HTTP 400)**: ValidationError with field-level violations for body and header validation failures
262+
- **Handler Errors (HTTP 500)**: Error messages for service implementation failures with custom messages
263+
- **Content-Type Aware**: Error responses serialized as JSON or protobuf based on request Content-Type
264+
- **Detailed validation errors**: Full validation error details from protovalidate for body validation
265+
- **Header validation errors**: Clear messages indicating which header failed validation and why
271266
- **Fail-fast**: Validation stops request processing immediately on failure (headers validated before body)
272267

273268
## Type System

coverage/coverage-badge.svg

Lines changed: 1 addition & 1 deletion
Loading

0 commit comments

Comments
 (0)