Documentation
¶
Overview ¶
Package server — HTTP instrumentation chokepoint (Plan 04-02 D-03).
instrumentedMux is the SOLE observation site for HTTP requests per AGENTS.md §7 DRY (single chokepoint per subsystem). It wraps the existing *http.ServeMux at the http.Server.Handler mount site (server.go Start()), reading `r.Pattern` post-mux.ServeHTTP — the Go 1.22+ stdlib field populated AFTER pattern matching — to extract a closed-shape `path_template` label value (D-03 / KD-04: stdlib mux chosen, no router migration).
Design (CONTEXT D-03 + Plan 04-02 task 04-02-02):
- Observation runs in a `defer func()` so a panicking handler still emits an observation (with status 500) and the panic re-propagates to the outer http.Server panic handler. RESEARCH §Q1 risk addressed (T-04-08 mitigation).
- Empty `r.Pattern` (unmatched URL) bucketed as "_NOT_FOUND_" to bound 404-path cardinality.
- `r.PathValue("database")` extracted at the chokepoint per D-10; forwarded to BindRequestDuration which drops the arg when the bag was constructed with tenantLabelsEnabled=false (D-08 forward-compat).
- `statusRecorder` captures the status code written by the handler so status_class can be classified post-handler.
- InFlight gauge Inc'd before mux.ServeHTTP and Dec'd in defer pair (deferred path always fires, even on panic).
- Bound observer cache keyed by (method, template, status_class[, database]) tuple is hosted on the wrapper and amortized across requests (MET-25). Per-request lookup is a single sync.Map Load (no WithLabelValues alloc on hit) — Plan 04-07 cumulates the BenchmarkObserve_Hot evidence.
Forbidden-label discipline (Phase 3 D-03a / registration.go ForbiddenLabels): `r.URL.Path` is NEVER passed as a label value — only `r.Pattern` (the closed route-table template) reaches the path_template axis. The Phase-3 panic-at-registration guard catches any future regression that tries to slot raw `path` into the label set.
Package server provides a Neo4j-compatible HTTP REST API server for NornicDB.
This package implements the Neo4j HTTP API specification, making NornicDB compatible with existing Neo4j tools, drivers, and browsers while adding NornicDB-specific extensions for memory decay, vector search, and compliance features.
Neo4j Compatibility:
- Discovery endpoint (/) returns Neo4j-compatible service information
- Transaction API (/db/{name}/tx) supports implicit and explicit transactions
- Cypher query execution with Neo4j response format
- Basic Auth and Bearer token authentication
- Error codes follow Neo4j conventions (Neo.ClientError.*)
NornicDB Extensions:
- JWT authentication with RBAC
- Vector search endpoints (/nornicdb/search, /nornicdb/similar)
- Memory decay information (/nornicdb/decay)
- GDPR compliance endpoints (/gdpr/export, /gdpr/delete)
- Admin endpoints (/admin/stats, /admin/config)
- GPU acceleration control (/admin/gpu/*)
- HTTP/2 support (always enabled, backwards compatible with HTTP/1.1)
Example Usage:
// Create server
db, _ := nornicdb.Open("./data", nil)
auth, _ := auth.NewAuthenticator(auth.DefaultAuthConfig())
config := server.DefaultConfig()
server, err := server.New(db, auth, config)
if err != nil {
log.Fatal(err)
}
// Start server
if err := server.Start(); err != nil {
log.Fatal(err)
}
// Server listening on server.Addr()
// Use with Neo4j Browser
// Open: http://localhost:7474
// Connect URI: bolt://localhost:7687 (if Bolt server is running)
// Or use HTTP: http://localhost:7474/db/nornic/tx/commit
// Use with Neo4j drivers
driver := neo4j.NewDriver("http://localhost:7474", neo4j.BasicAuth("admin", "password"))
session := driver.NewSession(neo4j.SessionConfig{})
result, _ := session.Run("MATCH (n) RETURN count(n)", nil)
// Graceful shutdown
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()
server.Stop(ctx)
Authentication:
The server supports multiple authentication methods:
**Basic Auth** (Neo4j compatible): Authorization: Basic base64(username:password)
**Bearer Token** (JWT): Authorization: Bearer eyJhbGciOiJIUzI1NiIs...
**Cookie** (browser sessions): Cookie: token=eyJhbGciOiJIUzI1NiIs...
**Query Parameter** (for SSE/WebSocket): ?token=eyJhbGciOiJIUzI1NiIs...
Neo4j HTTP API Endpoints:
GET / - Discovery (service information)
GET /db/{name} - Database information
POST /db/{name}/tx/commit - Execute Cypher (implicit transaction)
POST /db/{name}/tx - Begin explicit transaction
POST /db/{name}/tx/{id} - Execute in transaction
POST /db/{name}/tx/{id}/commit - Commit transaction
DELETE /db/{name}/tx/{id} - Rollback transaction
NornicDB Extension Endpoints:
Authentication:
POST /auth/token - Get JWT token
POST /auth/logout - Logout
GET /auth/me - Current user info
POST /auth/api-token - Generate API token (admin)
GET /auth/oauth/redirect - OAuth redirect
GET /auth/oauth/callback - OAuth callback
GET /auth/users - List users (admin)
POST /auth/users - Create user (admin)
GET /auth/users/{username} - Get user (admin)
PUT /auth/users/{username} - Update user (admin)
DELETE /auth/users/{username} - Delete user (admin)
Search & Embeddings:
POST /nornicdb/search - Hybrid search (vector + BM25)
POST /nornicdb/similar - Vector similarity search
GET /nornicdb/decay - Memory decay statistics
POST /nornicdb/embed/trigger - Trigger embedding generation
GET /nornicdb/embed/stats - Embedding statistics
POST /nornicdb/embed/clear - Clear all embeddings (admin)
POST /nornicdb/search/rebuild - Rebuild search indexes
Admin & System:
GET /admin/stats - System statistics (admin)
GET /admin/config - Server configuration (admin)
POST /admin/backup - Create backup (admin)
GET /admin/gpu/status - GPU status (admin)
POST /admin/gpu/enable - Enable GPU (admin)
POST /admin/gpu/disable - Disable GPU (admin)
POST /admin/gpu/test - Test GPU (admin)
GDPR Compliance:
POST /gdpr/export - GDPR data export (requires user_id and format in body)
POST /gdpr/delete - GDPR erasure request
GraphQL & AI:
POST /graphql - GraphQL endpoint
GET /graphql/playground - GraphQL Playground
POST /mcp - MCP server endpoint
POST /api/bifrost/chat/completions - Heimdall AI chat
For complete API documentation, see: docs/api-reference/openapi.yaml
Security Features:
- CORS support with configurable origins
- Request size limits (default 10MB)
- IP-based rate limiting (configurable per-minute/per-hour limits)
- Audit logging integration
- Panic recovery middleware
- TLS/HTTPS support
Compliance:
- GDPR Art.15 (right of access) via /gdpr/export
- GDPR Art.17 (right to erasure) via /gdpr/delete
- HIPAA audit logging for all data access
- SOC2 access controls via RBAC
ELI12 (Explain Like I'm 12):
Think of this server like a restaurant:
**Neo4j compatibility**: We speak the same "language" as Neo4j, so existing customers (tools/drivers) can order from our menu without learning new words.
**Authentication**: Like checking IDs at the door - we make sure you're allowed to be here and what you're allowed to do.
**Endpoints**: Different "counters" for different services - one for regular food (Cypher queries), one for special orders (vector search), one for the manager's office (admin functions).
**Middleware**: Like security guards, cashiers, and cleaners who help every customer but do different jobs (logging, auth, error handling).
The server makes sure everyone gets served safely and efficiently!
Package server provides an HTTP REST API server for NornicDB.
Index ¶
- Variables
- func SetUIAssets(assets fs.FS)
- func SetUIBasePath(basePath string)
- type Config
- type GraphNode
- type GraphRelationship
- type GraphResult
- type IPRateLimiter
- type NotificationPos
- type QueryError
- type QueryResult
- type QueryStats
- type ResultRow
- type Server
- func (s *Server) Addr() string
- func (s *Server) GetDatabaseAccessMode() auth.DatabaseAccessMode
- func (s *Server) GetDatabaseAccessModeForRoles(roles []string) auth.DatabaseAccessMode
- func (s *Server) GetDatabaseManager() *multidb.DatabaseManager
- func (s *Server) GetEffectivePermissions(roles []string) []string
- func (s *Server) GetResolvedAccessForRoles(roles []string, dbName string) auth.ResolvedAccess
- func (s *Server) SetAuditLogger(logger *audit.Logger)
- func (s *Server) SetHTTPMetrics(m *observability.HTTPMetrics)
- func (s *Server) SetObsRegistry(reg *prometheus.Registry)
- func (s *Server) Start() error
- func (s *Server) Stats() ServerStats
- func (s *Server) Stop(ctx context.Context) error
- type ServerNotification
- type ServerStats
- type StatementRequest
- type TransactionInfo
- type TransactionRequest
- type TransactionResponse
Constants ¶
This section is empty.
Variables ¶
var ( ErrServerClosed = fmt.Errorf("server closed") ErrForbidden = fmt.Errorf("forbidden") ErrBadRequest = fmt.Errorf("bad request") ErrNotFound = fmt.Errorf("not found") ErrMethodNotAllowed = fmt.Errorf("method not allowed") ErrInternalError = fmt.Errorf("internal server error") )
Errors for HTTP operations.
var UIAssets fs.FS
UIAssets holds the UI files (set by main package or tests).
var UIBasePath string
UIBasePath is a trusted, server-configured UI base path used when rewriting static asset references in index.html for reverse-proxy deployments.
var UIEnabled bool
UIEnabled indicates if UI assets are available
Functions ¶
func SetUIBasePath ¶
func SetUIBasePath(basePath string)
SetUIBasePath configures the trusted base path used for UI asset rewriting.
Types ¶
type Config ¶
type Config struct {
// Address to bind to (default: "127.0.0.1" - localhost only for security)
// Set to "0.0.0.0" to listen on all interfaces (required for Docker/external access)
Address string
// PerDBYAMLOverrides carries the `databases:` map parsed from
// nornicdb.yaml. Server.New consumes it during system-DB load to seed
// dbconfig.Store on first boot via LoadWithYAMLDefaults — admin-API
// edits remain authoritative across restarts. Must be set BEFORE
// server.New runs; the post-construction setter is gone because the
// store load happens inside New and won't see late assignments.
PerDBYAMLOverrides map[string]map[string]string
// Port to listen on (default: 7474)
Port int
// BoltPort is the port the Bolt protocol server listens on. Surfaced
// in the discovery response so browser clients constructing
// neo4j-driver Bolt-over-WS sessions know where to connect.
// Default: 7687 when zero.
BoltPort int
// ReadTimeout for requests
ReadTimeout time.Duration
// WriteTimeout for responses
WriteTimeout time.Duration
// IdleTimeout for keep-alive connections
IdleTimeout time.Duration
// MaxRequestSize in bytes (default: 10MB)
MaxRequestSize int64
// EnableCORS for cross-origin requests (default: false for security)
EnableCORS bool
// CORSOrigins allowed origins (default: empty - must be explicitly configured)
// WARNING: Never use "*" with credentials - this is a CSRF vulnerability
CORSOrigins []string
// EnableCompression for responses
EnableCompression bool
// Rate Limiting Configuration (DoS protection)
// RateLimitEnabled enables IP-based rate limiting (default: true)
RateLimitEnabled bool
// RateLimitPerMinute max requests per IP per minute (default: 100)
RateLimitPerMinute int
// RateLimitPerHour max requests per IP per hour (default: 3000)
RateLimitPerHour int
// RateLimitBurst max burst size for short request spikes (default: 20)
RateLimitBurst int
// TLSCertFile for HTTPS
TLSCertFile string
// TLSKeyFile for HTTPS
TLSKeyFile string
// HTTP/2 Configuration
// HTTP/2 is always enabled (backwards compatible with HTTP/1.1)
// HTTP/2 provides multiplexing, header compression, and improved performance
// HTTP/1.1 clients continue to work normally
// HTTP2MaxConcurrentStreams limits the number of concurrent streams per connection (default: 250)
// - 250: Go's internal default, matches standard library behavior (default)
// - 100: Lower memory usage, good for resource-constrained environments
// - 500-1000: High concurrency scenarios, uses more memory per connection
// - Very high values (>1000) are not recommended due to DoS attack risk
HTTP2MaxConcurrentStreams uint32
// MCP Configuration (Model Context Protocol)
// MCPEnabled controls whether the MCP server is started (default: true)
// Set to false to disable MCP tools entirely
// Env: NORNICDB_MCP_ENABLED=true|false
MCPEnabled bool
// Embedding Configuration (for vector search)
// EmbeddingEnabled turns on automatic embedding generation
EmbeddingEnabled bool
// EmbeddingProvider: "ollama" or "openai" or "local"
EmbeddingProvider string
// EmbeddingAPIURL is the base URL (e.g., http://localhost:11434)
EmbeddingAPIURL string
// EmbeddingModel is the model name (e.g., bge-m3)
EmbeddingModel string
// EmbeddingDimensions is expected vector size (e.g., 1024)
EmbeddingDimensions int
// EmbeddingCacheSize is max embeddings to cache (0 = disabled, default: 10000)
// Each cached embedding uses ~4KB (1024 dims × 4 bytes)
EmbeddingCacheSize int
// EmbeddingAPIKey is the API key for authenticated embedding providers (OpenAI, Cloudflare Workers AI, etc.)
// Env: NORNICDB_EMBEDDING_API_KEY
EmbeddingAPIKey string
// ModelsDir is the directory containing local GGUF models
// Env: NORNICDB_MODELS_DIR (default: ./models)
ModelsDir string
// Embedding llama.cpp context features (passthrough for local GGUF models)
EmbeddingCtxType int // Env: NORNICDB_EMBEDDING_CTX_TYPE
EmbeddingPoolingType int // Env: NORNICDB_EMBEDDING_POOLING_TYPE
EmbeddingAttentionType int // Env: NORNICDB_EMBEDDING_ATTENTION_TYPE
EmbeddingFlashAttn int // Env: NORNICDB_EMBEDDING_FLASH_ATTN
// Slow Query Logging Configuration
// SlowQueryEnabled turns on slow query logging (default: true)
SlowQueryEnabled bool
// D-04d: SlowQueryThreshold and SlowQueryLogFile collapsed into
// pkg/config.LoggingConfig (the single source of truth). Threaded into
// the server via the Logging field below; readers go through
// s.config.Logging.SlowQueryThreshold / .SlowQueryLogFile.
//
// Logging carries the runtime LoggingConfig snapshot. Populated by
// cmd/nornicdb/main.go from cfg.Logging at server construction.
Logging nornicConfig.LoggingConfig
// Headless Mode Configuration
// Headless disables the web UI and browser-related endpoints
// Set to true for API-only deployments (e.g., embedded use, microservices)
// Env: NORNICDB_HEADLESS=true|false
Headless bool
// BasePath for deployment behind a reverse proxy with URL prefix
// Example: "/nornicdb" when deployed at https://example.com/nornicdb/
// Leave empty for root deployment (default)
// Env: NORNICDB_BASE_PATH
BasePath string
// Plugins Configuration
// PluginsDir is the directory for APOC/function plugins
// Env: NORNICDB_PLUGINS_DIR
PluginsDir string
// HeimdallPluginsDir is the directory for Heimdall plugins
// Env: NORNICDB_HEIMDALL_PLUGINS_DIR
HeimdallPluginsDir string
// Features configuration (passed from main config loading)
// This contains feature flags like HeimdallEnabled loaded from YAML/env
Features *nornicConfig.FeatureFlagsConfig
// Logger is the structured-logging entrypoint per Phase 2 D-01.
// If nil, a discard-handler fallback is installed at New() — graceful
// degrade for the transitional period; ctors will be tightened post-M1
// once all consumers are updated to pass an explicit logger via
// observability.Provider.Logger().
Logger *slog.Logger
}
Config holds HTTP server configuration options.
All settings have sensible defaults via DefaultConfig(). The server follows Neo4j conventions where applicable (default port 7474, timeouts, etc.).
Example:
// Production configuration
config := &server.Config{
Address: "0.0.0.0",
Port: 7474,
ReadTimeout: 30 * time.Second,
WriteTimeout: 60 * time.Second,
MaxRequestSize: 50 * 1024 * 1024, // 50MB for large imports
EnableCORS: true,
CORSOrigins: []string{"https://myapp.com"},
EnableCompression: true,
TLSCertFile: "/etc/ssl/server.crt",
TLSKeyFile: "/etc/ssl/server.key",
}
// Development configuration with CORS for local UI
config = server.DefaultConfig()
config.Port = 8080
config.EnableCORS = true
config.CORSOrigins = []string{"http://localhost:3000"} // Local dev UI only
func DefaultConfig ¶
func DefaultConfig() *Config
DefaultConfig returns Neo4j-compatible default server configuration.
Defaults match Neo4j HTTP server settings:
- Port 7474 (Neo4j HTTP default)
- 30s read timeout
- 60s write timeout
- 120s idle timeout
- 10MB max request size
- CORS enabled for browser compatibility
- Compression enabled
Embedding defaults (for MCP vector search):
- Enabled by default, connects to localhost:11434 (llama.cpp/Ollama)
- Model: bge-m3 (1024 dimensions)
- Falls back to text search if embeddings unavailable
Environment Variables to override embedding config:
NORNICDB_EMBEDDING_ENABLED=true|false - Enable/disable embeddings NORNICDB_EMBEDDING_PROVIDER=openai - API format: "openai" or "ollama" NORNICDB_EMBEDDING_URL=http://... - Embeddings API URL NORNICDB_EMBEDDING_MODEL=bge-m3 NORNICDB_EMBEDDING_DIM=1024 - Vector dimensions
Example:
config := server.DefaultConfig() server, err := server.New(db, auth, config) // Or customize config = server.DefaultConfig() config.Port = 8080 config.EnableCORS = false server, err = server.New(db, auth, config)
type GraphNode ¶
type GraphNode struct {
ID string `json:"id"`
ElementID string `json:"elementId"`
Labels []string `json:"labels"`
Properties map[string]interface{} `json:"properties"`
}
GraphNode is a node in graph format.
type GraphRelationship ¶
type GraphRelationship struct {
ID string `json:"id"`
ElementID string `json:"elementId"`
Type string `json:"type"`
StartNode string `json:"startNodeElementId"`
EndNode string `json:"endNodeElementId"`
Properties map[string]interface{} `json:"properties"`
}
GraphRelationship is a relationship in graph format.
type GraphResult ¶
type GraphResult struct {
Nodes []GraphNode `json:"nodes"`
Relationships []GraphRelationship `json:"relationships"`
}
GraphResult holds graph-format results.
type IPRateLimiter ¶
type IPRateLimiter struct {
// contains filtered or unexported fields
}
IPRateLimiter provides IP-based rate limiting to prevent DoS attacks.
func NewIPRateLimiter ¶
func NewIPRateLimiter(perMinute, perHour, burst int) *IPRateLimiter
NewIPRateLimiter creates a new IP-based rate limiter.
func (*IPRateLimiter) Allow ¶
func (rl *IPRateLimiter) Allow(ip string) bool
Allow checks if a request from the given IP is allowed.
type NotificationPos ¶
type NotificationPos struct {
Offset int `json:"offset"`
Line int `json:"line"`
Column int `json:"column"`
}
NotificationPos is the position of a notification in the query.
type QueryError ¶
QueryError is an error from a query (Neo4j format).
type QueryResult ¶
type QueryResult struct {
Columns []string `json:"columns"`
Data []ResultRow `json:"data"`
Stats *QueryStats `json:"stats,omitempty"`
}
QueryResult is a single query result.
type QueryStats ¶
type QueryStats struct {
NodesCreated int `json:"nodes_created,omitempty"`
NodesDeleted int `json:"nodes_deleted,omitempty"`
RelationshipsCreated int `json:"relationships_created,omitempty"`
RelationshipsDeleted int `json:"relationships_deleted,omitempty"`
PropertiesSet int `json:"properties_set,omitempty"`
LabelsAdded int `json:"labels_added,omitempty"`
LabelsRemoved int `json:"labels_removed,omitempty"`
IndexesAdded int `json:"indexes_added,omitempty"`
IndexesRemoved int `json:"indexes_removed,omitempty"`
ConstraintsAdded int `json:"constraints_added,omitempty"`
ConstraintsRemoved int `json:"constraints_removed,omitempty"`
ContainsUpdates bool `json:"contains_updates,omitempty"`
}
QueryStats holds query execution statistics.
type ResultRow ¶
type ResultRow struct {
Row []interface{} `json:"row"`
Meta []interface{} `json:"meta,omitempty"`
Graph *GraphResult `json:"graph,omitempty"`
}
ResultRow is a row of results with metadata.
type Server ¶
type Server struct {
// contains filtered or unexported fields
}
Server is the HTTP API server providing Neo4j-compatible endpoints.
The server is thread-safe and handles concurrent requests. It maintains metrics, supports graceful shutdown, and integrates with audit logging.
Lifecycle:
- Create with New()
- Optionally set audit logger with SetAuditLogger()
- Start with Start()
- Handle requests automatically
- Stop with Stop() for graceful shutdown
Example:
server := server.New(db, auth, config)
// Set up audit logging
auditLogger, _ := audit.NewLogger(audit.DefaultConfig())
server.SetAuditLogger(auditLogger)
// Start server
if err := server.Start(); err != nil {
log.Fatal(err)
}
// Server is now handling requests
// (Listening on server.Addr())
// Get metrics
stats := server.Stats()
// stats.RequestCount, stats.ErrorCount expose request/error counts
// Graceful shutdown
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()
server.Stop(ctx)
func New ¶
New creates a new HTTP server with the given database, authenticator, and configuration.
The server is created but not started. Call Start() to begin accepting connections.
Parameters:
- db: NornicDB database instance (required)
- authenticator: Authentication handler (can be nil to disable auth)
- config: Server configuration (uses DefaultConfig() if nil)
Returns:
- Server instance ready to start
- Error if database is nil or configuration is invalid
Example:
// With authentication
db, _ := nornicdb.Open("./data", nil)
auth, _ := auth.NewAuthenticator(auth.DefaultAuthConfig())
server, err := server.New(db, auth, nil) // Uses default config
// Without authentication (development)
server, err = server.New(db, nil, nil)
// Custom configuration
config := &server.Config{
Port: 8080,
EnableCORS: false,
}
server, err = server.New(db, auth, config)
func (*Server) GetDatabaseAccessMode ¶
func (s *Server) GetDatabaseAccessMode() auth.DatabaseAccessMode
GetDatabaseAccessMode returns the server's per-database access mode for a request with no principal (e.g. unauthenticated). Prefer getDatabaseAccessMode(claims) or GetDatabaseAccessModeForRoles(roles) when principal is known.
func (*Server) GetDatabaseAccessModeForRoles ¶
func (s *Server) GetDatabaseAccessModeForRoles(roles []string) auth.DatabaseAccessMode
GetDatabaseAccessModeForRoles returns the per-database access mode for the given principal roles. Used by Bolt when the principal is known (e.g. from HELLO auth). When auth disabled, Bolt should use Full.
func (*Server) GetDatabaseManager ¶
func (s *Server) GetDatabaseManager() *multidb.DatabaseManager
GetDatabaseManager returns the server's multi-database manager so external protocol frontends can route through the same database-resolution path.
func (*Server) GetEffectivePermissions ¶
GetEffectivePermissions returns the union of global entitlement IDs for the given roles. Used by Bolt auth adapter so BoltAuthResult.HasPermission uses stored role entitlements.
func (*Server) GetResolvedAccessForRoles ¶
func (s *Server) GetResolvedAccessForRoles(roles []string, dbName string) auth.ResolvedAccess
GetResolvedAccessForRoles returns per-DB read/write for (roles, dbName). Used by Bolt for mutation checks.
func (*Server) SetAuditLogger ¶
SetAuditLogger sets the audit logger for compliance logging.
func (*Server) SetHTTPMetrics ¶ added in v1.1.0
func (s *Server) SetHTTPMetrics(m *observability.HTTPMetrics)
SetHTTPMetrics injects the Plan-04-02 HTTP catalog bag (D-02 typed handle DI). MUST be called BEFORE Start() — once the http.Server's Handler is wired in Start(), the wrapper is fixed for the server lifetime. Callers (cmd/nornicdb/main.go) inject after observability.New returns the registry, then call Start().
Nil-safe: passing nil is equivalent to never calling — instrumentedMux is a pass-through. Test fixtures and pre-Phase-4 callers compile and run unchanged.
func (*Server) SetObsRegistry ¶ added in v1.1.0
func (s *Server) SetObsRegistry(reg *prometheus.Registry)
SetObsRegistry plumbs the unified prometheus registry from observability.New into the server so handleMetrics can call observability.RenderLegacy. Phase 5 / Plan 05-04. Mirrors the SetHTTPMetrics pattern (mu.Lock + assign + unlock).
Nil-safe: passing nil is equivalent to never calling — handleMetrics tolerates a nil registry by emitting empty body bytes (RenderLegacy contract). Test fixtures and pre-Phase-5 callers compile and run unchanged.
func (*Server) Start ¶
Start begins listening for HTTP connections on the configured address and port.
The server starts in a separate goroutine, so this method returns immediately after successfully binding to the port. Use Addr() to get the actual listening address after starting.
Returns:
- nil if server started successfully
- Error if failed to bind to port or server is already closed
Example:
server := server.New(db, auth, config)
if err := server.Start(); err != nil {
log.Fatalf("Failed to start server: %v", err)
}
// Server started on server.Addr()
// Server is now accepting connections
// Keep main goroutine alive
select {}
TLS Support:
If TLSCertFile and TLSKeyFile are configured, the server automatically starts with HTTPS. Otherwise, it uses HTTP.
func (*Server) Stats ¶
func (s *Server) Stats() ServerStats
Stats returns current server runtime statistics.
Statistics are updated in real-time by middleware and include:
- Uptime since server start
- Total request count
- Total error count
- Currently active requests
Example:
stats := server.Stats()
// stats.Uptime: server uptime
// stats.RequestCount: total requests
// stats.ErrorCount / stats.RequestCount: error rate
// stats.ActiveRequests: in-flight requests
// Use for monitoring/alerting
if stats.ErrorCount > 1000 {
alert("High error count detected")
}
Thread-safe: Can be called concurrently from multiple goroutines.
type ServerNotification ¶
type ServerNotification struct {
Code string `json:"code"`
Severity string `json:"severity"`
Title string `json:"title"`
Description string `json:"description"`
Position *NotificationPos `json:"position,omitempty"`
}
ServerNotification is a warning/info from the server.
type ServerStats ¶
type ServerStats struct {
Uptime time.Duration `json:"uptime"`
RequestCount int64 `json:"request_count"`
ErrorCount int64 `json:"error_count"`
ActiveRequests int64 `json:"active_requests"`
Version string `json:"version"`
Commit string `json:"commit"`
BuildTime string `json:"build_time"`
}
ServerStats holds server metrics.
type StatementRequest ¶
type StatementRequest struct {
Statement string `json:"statement"`
Parameters map[string]interface{} `json:"parameters,omitempty"`
ResultDataContents []string `json:"resultDataContents,omitempty"` // ["row", "graph"]
IncludeStats bool `json:"includeStats,omitempty"`
}
StatementRequest is a single Cypher statement.
type TransactionInfo ¶
type TransactionInfo struct {
Expires string `json:"expires"` // RFC1123 format
}
TransactionInfo holds transaction state.
type TransactionRequest ¶
type TransactionRequest struct {
Statements []StatementRequest `json:"statements"`
}
TransactionRequest follows Neo4j HTTP API format exactly.
type TransactionResponse ¶
type TransactionResponse struct {
Results []QueryResult `json:"results"`
Errors []QueryError `json:"errors"`
Commit string `json:"commit,omitempty"` // URL to commit (for open transactions)
Transaction *TransactionInfo `json:"transaction,omitempty"` // Transaction state
LastBookmarks []string `json:"lastBookmarks,omitempty"` // Bookmark for causal consistency
Notifications []ServerNotification `json:"notifications,omitempty"` // Server notifications
Receipt interface{} `json:"receipt,omitempty"` // Mutation receipt (tx_id, wal_seq_start, wal_seq_end, hash)
Optimistic interface{} `json:"optimistic,omitempty"` // Optimistic mutation metadata (e.g., created IDs)
}
TransactionResponse follows Neo4j HTTP API format exactly.