- Introduced a comprehensive data model for route definitions, parameters, and validation rules. - Established component interfaces for route parsing, comment parsing, import resolution, route building, validation, and rendering. - Developed a detailed implementation plan outlining execution flow, user requirements, and compliance with design principles. - Created a quickstart guide to assist users in utilizing the refactored system effectively. - Conducted thorough research on existing architecture, identifying key improvements and establishing a refactoring strategy. - Specified functional requirements and user scenarios to ensure clarity and testability. - Generated a task list for implementation, emphasizing test-driven development and parallel execution where applicable.
7.4 KiB
7.4 KiB
Phase 1: Quickstart Guide
Overview
This quickstart guide demonstrates how to use the refactored AST route generation system. It covers the basic workflow for defining routes and generating route handler code.
Prerequisites
- Go 1.21 or higher
- Existing atomctl project structure
- Basic understanding of Go annotations
Basic Route Definition
1. Simple Route
Create a controller with basic route annotation:
// app/http/user_controller.go
package http
// @Router /users [get]
type UserController struct {}
Generate routes:
atomctl gen route
2. Route with Parameters
Add parameter bindings using @Bind annotations:
// app/http/user_controller.go
package http
// @Router /users/:id [get]
// @Bind id (path) model()
// @Bind limit (query) model(limit:int)
type UserController struct {}
Parameter Binding Types
Path Parameters
// @Bind id (path) model()
// @Bind name (path) model(name:string)
Query Parameters
// @Bind limit (query) model(limit:int)
// @Bind offset (query) model(offset:int)
// @Bind filter (query)
Body Parameters
// @Bind user (body) model(User)
// @Bind data (body) model(CreateUserRequest)
Header Parameters
// @Bind authorization (header)
// @Bind x-api-key (header) model(APIKey)
Generated Code Structure
The route generation will create a routes.gen.go file:
// app/http/routes.gen.go
package http
import (
"context"
"net/http"
"go.ipao.vip/atom/contracts"
"go.ipao.vip/atom/http"
"go.ipao.vip/gen/model"
)
type RouteProvider struct {
userController *UserController
}
func (p *RouteProvider) Provide(opts ...contracts.Option) error {
// Route registration logic here
p.userController = &UserController{}
// Register /users route
http.Handle("/users", p.userController.GetUsers)
return nil
}
// UserController method stubs
func (c *UserController) GetUsers(ctx context.Context, w http.ResponseWriter, r *http.Request) {
// Generated method implementation
}
Testing Your Routes
1. Unit Test
// app/http/user_controller_test.go
package http
import (
"net/http"
"net/http/httptest"
"testing"
"github.com/stretchr/testify/assert"
)
func TestUserController_GetUsers(t *testing.T) {
controller := &UserController{}
req := httptest.NewRequest("GET", "/users", nil)
w := httptest.NewRecorder()
controller.GetUsers(context.Background(), w, req)
assert.Equal(t, http.StatusOK, w.Code)
}
2. Integration Test
// integration/user_routes_test.go
package integration
import (
"net/http"
"net/http/httptest"
"testing"
"github.com/stretchr/testify/assert"
)
func TestUserRoutes(t *testing.T) {
// Setup router with generated routes
router := setupRouter()
tests := []struct {
name string
path string
method string
wantStatus int
}{
{"Get Users", "/users", "GET", http.StatusOK},
{"Get User by ID", "/users/123", "GET", http.StatusOK},
{"Create User", "/users", "POST", http.StatusCreated},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
req := httptest.NewRequest(tt.method, tt.path, nil)
w := httptest.NewRecorder()
router.ServeHTTP(w, req)
assert.Equal(t, tt.wantStatus, w.Code)
})
}
}
Advanced Features
1. Route Groups
// @Router /api/v1/users [get]
// @Router /api/v1/users/:id [get,put,delete]
type UserController struct {}
2. Middleware Integration
// @Router /admin [get]
// @Middleware auth,admin
type AdminController struct {}
3. Custom Return Types
// @Router /users [post]
// @ReturnType UserResponse
type UserController struct {}
Configuration Options
Parser Configuration
config := &route.RouteParserConfig{
StrictMode: true,
ParseComments: true,
SourceLocations: true,
EnableValidation: true,
}
Builder Configuration
config := &route.BuilderConfig{
EnableValidation: true,
StrictMode: true,
DefaultParamPosition: route.ParamPositionQuery,
AutoGenerateReturnTypes: true,
ResolveImportDependencies: true,
}
Error Handling
1. Validation Errors
The refactored system provides detailed error messages:
$ atomctl gen route
Error: invalid route syntax in user_controller.go:15
Expected: @Router /path [method]
Found: @Router /users
Fix: Add HTTP methods in brackets
2. Parameter Binding Errors
$ atomctl gen route
Error: invalid parameter binding in user_controller.go:16
Parameter 'id' has invalid position 'invalid'
Valid positions: path, query, body, header, cookie, local, file
Migration from Legacy System
1. Existing Code Compatibility
The refactored system maintains full backward compatibility:
// This still works
// @Router /users [get]
// @Bind id (path) model()
type UserController struct {}
2. Gradual Migration
You can migrate files incrementally:
# Generate routes for specific files
atomctl gen route app/http/user_controller.go
# Or generate for entire directory
atomctl gen route app/http/
Performance Considerations
1. Caching
The refactored system includes caching for improved performance:
config := &route.RouteParserConfig{
CacheEnabled: true,
}
2. Parallel Processing
Enable parallel processing for large projects:
config := &route.RouteParserConfig{
ParallelProcessing: true,
}
Debugging and Diagnostics
1. Enable Detailed Logging
config := &route.RouteParserConfig{
SourceLocations: true,
}
2. Access Diagnostics
parser := route.NewRouteParser()
routes, err := parser.ParseFile("controller.go")
// Get detailed diagnostics
diagnostics := parser.GetDiagnostics()
for _, diag := range diagnostics {
fmt.Printf("%s: %s (%s:%d)\n", diag.Level, diag.Message, diag.File, diag.Location.Line)
}
Best Practices
1. Route Definition
- Use descriptive route names
- Group related routes together
- Follow REST conventions where applicable
2. Parameter Binding
- Use appropriate parameter positions
- Provide clear parameter names
- Add validation for complex parameters
3. Error Handling
- Implement proper error handling in controllers
- Use appropriate HTTP status codes
- Provide meaningful error messages
4. Testing
- Write comprehensive tests for all routes
- Test both success and error scenarios
- Use contract tests for consistency
Troubleshooting
Common Issues
- Routes not generated: Check file naming and location
- Parameters not parsed: Verify annotation syntax
- Import errors: Ensure all dependencies are available
- Compilation errors: Check generated code syntax
Getting Help
- Review the contract tests in
contracts/directory - Check the diagnostic output for detailed error information
- Run tests to verify implementation correctness
Next Steps
- Define your routes using
@Routerand@Bindannotations - Run
atomctl gen routeto generate route code - Implement the generated controller methods
- Write tests to verify functionality
- Configure options as needed for your project
The refactored system provides a solid foundation for route generation with improved maintainability, testability, and extensibility.