Checkpoint
This commit is contained in:
164
server/README.md
Normal file
164
server/README.md
Normal file
@@ -0,0 +1,164 @@
|
||||
# Server Package
|
||||
|
||||
This package contains the restructured HTTP server implementation for HAMView.
|
||||
|
||||
## Structure
|
||||
|
||||
```
|
||||
server/
|
||||
├── server.go # Main server setup and configuration
|
||||
├── router.go # Route configuration with nested routers
|
||||
├── handlers_radios.go # Radio endpoint handlers
|
||||
├── handlers_meshcore.go # MeshCore endpoint handlers
|
||||
├── error.go # Error handling utilities
|
||||
└── server_test.go # Test infrastructure and test cases
|
||||
```
|
||||
|
||||
## Design Principles
|
||||
|
||||
### Clean Separation of Concerns
|
||||
|
||||
- **server.go**: Server initialization, configuration, and lifecycle management
|
||||
- **router.go**: Centralized route definition using Echo's Group feature for nested routing
|
||||
- **handlers_*.go**: Domain-specific handler functions grouped by feature
|
||||
- **error.go**: Consistent error handling across all endpoints
|
||||
|
||||
### Nested Routers
|
||||
|
||||
The routing structure uses Echo's Group feature to create a clean hierarchy:
|
||||
|
||||
```
|
||||
/api/v1
|
||||
├── /radios
|
||||
│ ├── GET / -> handleGetRadios
|
||||
│ └── GET /:protocol -> handleGetRadios
|
||||
└── /meshcore
|
||||
├── GET / -> handleGetMeshCore
|
||||
├── GET /groups -> handleGetMeshCoreGroups
|
||||
├── GET /packets -> handleGetMeshCorePackets
|
||||
└── /nodes
|
||||
├── GET / -> handleGetMeshCoreNodes
|
||||
└── GET /close-to/:publickey -> handleGetMeshCoreNodesCloseTo
|
||||
```
|
||||
|
||||
### Testing Infrastructure
|
||||
|
||||
The test suite uses an in-memory SQLite3 database for fast, isolated unit tests:
|
||||
|
||||
- **setupTestServer()**: Creates a test Echo instance with routes and in-memory DB
|
||||
- **teardownTestServer()**: Cleans up test resources
|
||||
- Test cases cover all endpoints with various query parameters
|
||||
- Benchmarks for performance testing
|
||||
- Example showing how to populate test data
|
||||
|
||||
## Usage
|
||||
|
||||
### Creating a Server
|
||||
|
||||
```go
|
||||
import (
|
||||
"github.com/sirupsen/logrus"
|
||||
"git.maze.io/ham/hamview/server"
|
||||
)
|
||||
|
||||
logger := logrus.New()
|
||||
|
||||
serverConfig := &server.Config{
|
||||
Listen: ":8073",
|
||||
}
|
||||
|
||||
dbConfig := &server.DatabaseConfig{
|
||||
Type: "postgres",
|
||||
Conf: "host=localhost user=ham dbname=hamview",
|
||||
}
|
||||
|
||||
srv, err := server.New(serverConfig, dbConfig, logger)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
if err := srv.Run(); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
```
|
||||
|
||||
### Running Tests
|
||||
|
||||
```bash
|
||||
# Run all tests
|
||||
go test -v ./server/
|
||||
|
||||
# Run specific test
|
||||
go test -v ./server/ -run TestRadiosEndpoints
|
||||
|
||||
# Run with coverage
|
||||
go test -v -cover ./server/
|
||||
|
||||
# Run benchmarks
|
||||
go test -v -bench=. ./server/
|
||||
```
|
||||
|
||||
### Adding New Endpoints
|
||||
|
||||
1. **Add handler function** in the appropriate `handlers_*.go` file:
|
||||
```go
|
||||
func (s *Server) handleNewEndpoint(c echo.Context) error {
|
||||
// Implementation
|
||||
return c.JSON(http.StatusOK, result)
|
||||
}
|
||||
```
|
||||
|
||||
2. **Register route** in `router.go`:
|
||||
```go
|
||||
func setupSomethingRoutes(s *Server, api *echo.Group) {
|
||||
group := api.Group("/something")
|
||||
group.GET("/new", s.handleNewEndpoint)
|
||||
}
|
||||
```
|
||||
|
||||
3. **Add test** in `server_test.go`:
|
||||
```go
|
||||
func TestNewEndpoint(t *testing.T) {
|
||||
e, _ := setupTestServer(t)
|
||||
defer teardownTestServer(t)
|
||||
|
||||
req := httptest.NewRequest(http.MethodGet, "/api/v1/something/new", nil)
|
||||
rec := httptest.NewRecorder()
|
||||
|
||||
e.ServeHTTP(rec, req)
|
||||
|
||||
// Assertions
|
||||
}
|
||||
```
|
||||
|
||||
## Backward Compatibility
|
||||
|
||||
The root `server.go` file maintains backward compatibility by re-exporting types and providing a compatibility wrapper for `NewServer()`. Existing code continues to work without changes.
|
||||
|
||||
## Best Practices
|
||||
|
||||
1. **Handler naming**: Use `handle` prefix (e.g., `handleGetRadios`)
|
||||
2. **Context parameter**: Use short name `c` for `echo.Context`
|
||||
3. **Error handling**: Always use `s.apiError()` for consistent error responses
|
||||
4. **Query parameters**: Use helper functions like `getQueryInt()` for parsing
|
||||
5. **Testing**: Write tests for both success and error cases
|
||||
6. **Documentation**: Add godoc comments for exported functions
|
||||
|
||||
## Performance Considerations
|
||||
|
||||
- Use in-memory SQLite for tests (fast and isolated)
|
||||
- Benchmark critical endpoints
|
||||
- Use Echo's built-in middleware for CORS, logging, etc.
|
||||
- Consider adding route-specific middleware for caching or rate limiting
|
||||
|
||||
## Future Enhancements
|
||||
|
||||
Potential improvements to consider:
|
||||
|
||||
- [ ] Add middleware for authentication/authorization
|
||||
- [ ] Implement request validation using a schema library
|
||||
- [ ] Add structured logging with trace IDs
|
||||
- [ ] Implement health check and metrics endpoints
|
||||
- [ ] Add integration tests with a real PostgreSQL instance
|
||||
- [ ] Consider adding OpenAPI/Swagger documentation
|
||||
- [ ] Add graceful shutdown handling
|
||||
Reference in New Issue
Block a user