This document describes the internal architecture and design patterns of the Newgate framework.
Newgate is a lightweight, multi-format backend framework built on Node.js's native HTTP module. It provides:
- Express-like routing with parameter and wildcard support
- Automatic content-type detection and parsing
- Middleware system with global and route-level support
- Enhanced response helpers for multiple formats
- Error handling with custom middleware
- Graceful shutdown with cleanup hooks
The framework is designed to be minimal yet extensible, allowing developers to handle multiple data formats without external dependencies for routing or middleware.
The main application class that orchestrates the framework.
Responsibilities:
- Route registration (GET, POST, PUT, DELETE, PATCH)
- Global middleware management
- CORS configuration
- Shutdown hook management
- Server lifecycle (listen, shutdown)
Key Methods:
get/post/put/delete/patch(path, ...handlers)- Register routesuse(middleware)- Register middleware
The App class is the main entry point. It orchestrates:
- Server creation (
http.createServer) - Route registration
- Middleware execution
- Request/Response enhancement
- Error handling
The Router handles URL matching and handler dispatching.
- Stores routes in a structured format.
- Supports parameterized routes (
/users/:id). - Supports wildcard routes (
/files/*). - Handles HTTP methods (GET, POST, PUT, DELETE, etc.).
Newgate uses a middleware stack similar to Connect/Express.
- Global Middleware: Runs for every request.
- Path-Specific Middleware: Runs for requests matching a path prefix.
- Route-Specific Middleware: Runs for specific routes.
- Error Middleware: Handles errors propagated via
next(err).
The parsing system is modular. It inspects the Content-Type header and delegates to the appropriate parser.
json.js: Handlesapplication/json.csv.js: Handlestext/csv.xml.js: Handlesapplication/xml.yaml.js: Handlesapplication/x-yaml.formdata.js: Handlesmultipart/form-data.binary.js: Handlesapplication/octet-stream.
The enhanceResponse function adds helper methods to the native ServerResponse object.
res.json(data)res.csv(data)res.xml(data)res.status(code)res.send(data)
- Incoming Request: HTTP server receives a request.
- Enhancement:
reqandresobjects are enhanced with Newgate properties and methods. - Body Parsing: The body is parsed based on
Content-Type. - Middleware Execution: Global and path-specific middleware are executed in order.
- Route Matching: The router finds a matching route handler.
- Handler Execution: The route handler is executed.
- Response: The handler sends a response using one of the helper methods.
newgatejs/
├── bin/
│ └── newgatejs.js # CLI entry point
├── src/
│ ├── core/
│ │ ├── app.js # Main App class
│ │ ├── router.js # Routing logic
│ │ └── server.js # HTTP server wrapper
│ ├── middleware/
│ │ └── index.js # Built-in middleware
│ ├── parsers/
│ │ ├── index.js # Parser dispatcher
│ │ ├── json.js
│ │ ├── csv.js
│ │ └── ...
│ ├── response/
│ │ └── enhance.js # Response helpers
│ └── utils/
│ └── logger.js # Logger utility
├── tests/ # Unit and integration tests
├── docs/ # Documentation
└── package.json
Newgate is designed to be extensible.
- Custom Parsers: Can be added by modifying the parser dispatcher (future feature: plugin system).
- Custom Middleware: Standard middleware signature
(req, res, next)allows easy integration of custom logic. xml(data)- Send XMLyaml(data)- Send YAMLfile(buffer, mimetype)- Send binaryerror(options)- Send error responsestream(stream)- Pipe streamdownload(path, filename)- Send file download
Helper functions for common tasks.
Utilities:
detectContentType.js- Parse content-type headerstreamToBuffer.js- Convert stream to bufferurlParser.js- Parse URL componentsdeepMerge.js- Recursively merge objects
┌─────────────────────────────────────────────────────────────┐
│ Incoming HTTP Request │
└────────────────────────┬────────────────────────────────────┘
│
▼
┌────────────────────────────────┐
│ Parse Request Body │
│ (based on content-type) │
└────────────┬───────────────────┘
│
▼
┌────────────────────────────────┐
│ Enhance Response Object │
│ (add helper methods) │
└────────────┬───────────────────┘
│
▼
┌────────────────────────────────┐
│ Execute Global Middleware │
│ (in order) │
└────────────┬───────────────────┘
│
▼
┌────────────────────────────────┐
│ Match Route │
│ (method + path) │
└────────────┬───────────────────┘
│
┌────────┴────────┐
│ │
┌───▼──┐ ┌──▼────┐
│Found │ │ Not │
│ │ │ Found │
└───┬──┘ └──┬────┘
│ │
▼ ▼
┌──────────────┐ ┌─────────────┐
│Execute Route │ │Send 404 │
│Handlers │ │Response │
└──────┬───────┘ └─────────────┘
│
▼
┌──────────────┐
│Send Response │
└──────────────┘
newgatejs/
├── src/
│ ├── core/
│ │ ├── app.js # Main App class
│ │ ├── router.js # Route matching
│ │ ├── middleware.js # Middleware engine
│ │ └── server.js # HTTP server
│ ├── parsers/
│ │ ├── index.js # Parser dispatcher
│ │ ├── json.js # JSON parser
│ │ ├── csv.js # CSV parser
│ │ ├── xml.js # XML parser
│ │ ├── yaml.js # YAML parser
│ │ ├── formdata.js # Form-data parser
│ │ └── binary.js # Binary parser
│ ├── response/
│ │ └── enhance.js # Response helpers
│ └── utils/
│ ├── detectContentType.js
│ ├── streamToBuffer.js
│ ├── urlParser.js
│ └── deepMerge.js
├── tests/
├── docs/
├── examples/
├── index.js # Entry point
├── index.d.ts # TypeScript definitions
└── package.json
Middleware is executed sequentially with a next() callback:
app.use((req, res, next) => {
// Do something
next(); // Continue to next middleware
});Features:
- Error propagation via
next(err) - Async support with promises
- Error handler detection (4 parameters)
Routes accept multiple handlers (middleware + final handler):
app.get('/path',
(req, res, next) => { /* middleware */ next(); },
(req, res) => { /* handler */ }
);Automatic parsing based on Content-Type header:
Content-Type: application/json → parseJSON()
Content-Type: text/csv → parseCSV()
Content-Type: application/xml → parseXML()
Content-Type: application/x-yaml → parseYAML()
Content-Type: multipart/form-data → parseFormData()
Response object is enhanced with format-specific methods:
res.json(data) // JSON response
res.csv(data) // CSV response
res.xml(data) // XML response
res.yaml(data) // YAML response
res.download(path) // File downloadThree-level error handling:
- Parser errors - Caught during request parsing
- Middleware errors - Passed via
next(err) - Route errors - Caught by error handlers
Error handlers are identified by 4 parameters:
app.useError((err, req, res, next) => {
// Handle error
});Shutdown hooks allow cleanup:
app.onShutdown(async () => {
// Close connections
// Cleanup resources
});- Routes are stored in an array
- Linear search through routes (O(n))
- Regex compilation happens at registration time
- Consider route ordering for frequently accessed paths
- Middleware runs sequentially
- Async middleware is awaited
- Early termination possible via response send
- Streaming for large files (form-data)
- Buffer-based parsing for other formats
- Schema validation optional (CSV)
- Form-data has configurable limits
- Stream-based parsing for large uploads
- Automatic cleanup on server shutdown
app.use((req, res, next) => {
// Custom logic
next();
});app.useError((err, req, res, next) => {
// Custom error handling
});Extend the parser dispatcher in src/parsers/index.js:
if (contentType === 'custom/format') {
body = parseCustom(buffer);
bodyType = 'custom';
}Extend response in src/response/enhance.js:
res.custom = (data) => {
res.setHeader('Content-Type', 'custom/format');
res.end(data);
};XML parser runs in safe mode by default:
- External entities disabled
- DOCTYPE processing disabled
Form-data parser enforces:
- File size limits (10MB default)
- Total memory limits (50MB default)
- File count limits (10 default)
CORS headers are configurable:
- Origin validation
- Method restrictions
- Header filtering
Production mode hides error details:
- Development: Full error messages
- Production: Generic error messages
- Route Caching - Cache compiled route patterns
- Middleware Caching - Pre-compile middleware chains
- Request Pooling - Reuse request/response objects
- Plugin System - Load custom modules
- Rate Limiting - Built-in rate limiting middleware
- Compression - Gzip/brotli compression
- Clustering - Multi-process support
- Metrics - Built-in performance metrics
- Replace linear route search with trie-based matching
- Implement middleware pre-compilation
- Add request/response object pooling
- Optimize regex compilation
- Add caching layer for parsed requests