165 lines
4.6 KiB
Markdown
165 lines
4.6 KiB
Markdown
# 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
|