server

package
v1.1.6 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 12, 2026 License: MIT Imports: 60 Imported by: 0

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:

  1. **Basic Auth** (Neo4j compatible): Authorization: Basic base64(username:password)

  2. **Bearer Token** (JWT): Authorization: Bearer eyJhbGciOiJIUzI1NiIs...

  3. **Cookie** (browser sessions): Cookie: token=eyJhbGciOiJIUzI1NiIs...

  4. **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:

  1. **Neo4j compatibility**: We speak the same "language" as Neo4j, so existing customers (tools/drivers) can order from our menu without learning new words.

  2. **Authentication**: Like checking IDs at the door - we make sure you're allowed to be here and what you're allowed to do.

  3. **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).

  4. **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

Constants

This section is empty.

Variables

View Source
var (
	ErrServerClosed       = fmt.Errorf("server closed")
	ErrUnauthorized       = fmt.Errorf("unauthorized")
	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")
	ErrServiceUnavailable = fmt.Errorf("service unavailable")
)

Errors for HTTP operations.

View Source
var UIAssets fs.FS

UIAssets holds the UI files (set by main package or tests).

View Source
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.

View Source
var UIEnabled bool

UIEnabled indicates if UI assets are available

Functions

func SetUIAssets

func SetUIAssets(assets fs.FS)

SetUIAssets configures the UI assets.

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

	// Debug/Profiling Configuration
	// EnablePprof enables /debug/pprof endpoints for performance profiling
	// WARNING: Only enable in development/testing environments
	// Env: NORNICDB_ENABLE_PPROF=true|false
	EnablePprof bool

	// 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.

func (*IPRateLimiter) Stop

func (rl *IPRateLimiter) Stop()

Stop stops the cleanup goroutine.

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

type QueryError struct {
	Code    string `json:"code"`
	Message string `json:"message"`
}

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:

  1. Create with New()
  2. Optionally set audit logger with SetAuditLogger()
  3. Start with Start()
  4. Handle requests automatically
  5. 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

func New(db *nornicdb.DB, authenticator *auth.Authenticator, config *Config) (*Server, error)

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) Addr

func (s *Server) Addr() string

Addr returns the server's listen address.

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

func (s *Server) GetEffectivePermissions(roles []string) []string

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

func (s *Server) SetAuditLogger(logger *audit.Logger)

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

func (s *Server) Start() error

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.

func (*Server) Stop

func (s *Server) Stop(ctx context.Context) error

Stop gracefully shuts down the server.

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.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL