yinzerflow 0.1.18 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +0 -296
- package/YinzerFlow.d.ts +565 -0
- package/YinzerFlow.js +24 -0
- package/YinzerFlow.js.map +42 -0
- package/docs/advanced-configuration-options.md +175 -0
- package/docs/body-parsing.md +294 -0
- package/docs/cors.md +187 -0
- package/docs/ip-security.md +232 -0
- package/docs/request.md +145 -0
- package/docs/response.md +251 -0
- package/docs/start-here.MD +116 -0
- package/example/index.ts +109 -53
- package/package.json +15 -17
- package/constants/index.d.ts +0 -86
- package/constants/index.js +0 -3
- package/constants/index.js.map +0 -13
- package/docs/README.md +0 -327
- package/docs/content-types.md +0 -390
- package/docs/error-handling.md +0 -266
- package/docs/file-parsers.md +0 -276
- package/docs/hooks.md +0 -289
- package/docs/routing.md +0 -204
- package/example/bun.lock +0 -866
- package/example/hooks/authentication.middleware.ts +0 -77
- package/example/package.json +0 -61
- package/example/routes/authentication.routes.ts +0 -243
- package/example/routes/content-types.ts +0 -116
- package/example/tsconfig.json +0 -32
- package/index.d.ts +0 -395
- package/index.js +0 -23
- package/index.js.map +0 -33
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
# IP Address Security
|
|
2
|
+
|
|
3
|
+
YinzerFlow provides comprehensive IP address validation and security protection against IP spoofing attacks, supporting multiple header formats with trusted proxy validation.
|
|
4
|
+
|
|
5
|
+
## Configuration
|
|
6
|
+
|
|
7
|
+
Configure IP security settings in your YinzerFlow application:
|
|
8
|
+
|
|
9
|
+
```typescript
|
|
10
|
+
const app = new YinzerFlow({
|
|
11
|
+
port: 3000,
|
|
12
|
+
ipSecurity: {
|
|
13
|
+
trustedProxies: ['127.0.0.1', '::1', '192.168.1.10'],
|
|
14
|
+
allowPrivateIps: true,
|
|
15
|
+
headerPreference: ['x-forwarded-for', 'x-real-ip', 'cf-connecting-ip'],
|
|
16
|
+
maxChainLength: 10,
|
|
17
|
+
detectSpoofing: true
|
|
18
|
+
}
|
|
19
|
+
});
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
### Configuration Options
|
|
23
|
+
|
|
24
|
+
| Option | Type | Default | Description |
|
|
25
|
+
|-----|---|---|---|
|
|
26
|
+
| `trustedProxies` | `string[]` | `['127.0.0.1', '::1']` | List of trusted proxy IP addresses |
|
|
27
|
+
| `allowPrivateIps` | `boolean` | `true` | Allow private IP addresses (RFC 1918, etc.) |
|
|
28
|
+
| `headerPreference` | `string[]` | `['x-forwarded-for', 'x-real-ip', 'cf-connecting-ip', 'x-client-ip', 'true-client-ip']` | Header preference order |
|
|
29
|
+
| `maxChainLength` | `number` | `10` | Maximum IP chain length |
|
|
30
|
+
| `detectSpoofing` | `boolean` | `true` | Enable spoofing pattern detection |
|
|
31
|
+
|
|
32
|
+
## Examples
|
|
33
|
+
|
|
34
|
+
### Basic Example
|
|
35
|
+
|
|
36
|
+
Access client IP address with automatic security validation:
|
|
37
|
+
|
|
38
|
+
```typescript
|
|
39
|
+
app.get('/api/user-info', ({ request }) => {
|
|
40
|
+
const clientIp = request.ipAddress;
|
|
41
|
+
|
|
42
|
+
return {
|
|
43
|
+
message: `Hello from ${clientIp}`,
|
|
44
|
+
userAgent: request.headers['user-agent']
|
|
45
|
+
};
|
|
46
|
+
});
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
### Advanced Example
|
|
50
|
+
|
|
51
|
+
Configure IP security for your application:
|
|
52
|
+
|
|
53
|
+
```typescript
|
|
54
|
+
app.post('/api/secure-endpoint', ({ request }) => {
|
|
55
|
+
// YinzerFlow automatically applies IP security configuration
|
|
56
|
+
const clientIp = request.ipAddress; // Uses configured IP security rules
|
|
57
|
+
|
|
58
|
+
if (!clientIp) {
|
|
59
|
+
return {
|
|
60
|
+
error: 'Unable to determine client IP address',
|
|
61
|
+
message: 'Request may be from untrusted proxy or invalid source'
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
return {
|
|
66
|
+
clientIp,
|
|
67
|
+
message: 'Secure endpoint accessed successfully'
|
|
68
|
+
};
|
|
69
|
+
});
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
## Common Use Cases
|
|
73
|
+
|
|
74
|
+
- **Load Balancer Integration**: Configure trusted proxies to get real client IPs behind Nginx, HAProxy, or cloud load balancers
|
|
75
|
+
- **CDN Support**: Handle Cloudflare and other CDN headers like `CF-Connecting-IP` with proper validation
|
|
76
|
+
- **Reverse Proxy Security**: Validate proxy chains to prevent IP spoofing in complex network topologies
|
|
77
|
+
- **Complex Infrastructure**: Use wildcard (`'*'`) for Kubernetes ingress, unknown CDN configurations, or dynamic proxy setups
|
|
78
|
+
- **Rate Limiting**: Get accurate client IPs for rate limiting and abuse prevention systems
|
|
79
|
+
- **Geolocation Services**: Ensure IP addresses are valid before passing to geolocation APIs
|
|
80
|
+
- **Security Logging**: Log real client IPs for security monitoring and incident response
|
|
81
|
+
|
|
82
|
+
### Load Balancer Behind Nginx
|
|
83
|
+
|
|
84
|
+
```typescript
|
|
85
|
+
const app = new YinzerFlow({
|
|
86
|
+
port: 3000,
|
|
87
|
+
ipSecurity: {
|
|
88
|
+
trustedProxies: ['192.168.1.10'], // Your Nginx server
|
|
89
|
+
headerPreference: ['x-forwarded-for'],
|
|
90
|
+
detectSpoofing: true
|
|
91
|
+
}
|
|
92
|
+
});
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
### Cloudflare CDN Integration
|
|
96
|
+
|
|
97
|
+
```typescript
|
|
98
|
+
const app = new YinzerFlow({
|
|
99
|
+
port: 3000,
|
|
100
|
+
ipSecurity: {
|
|
101
|
+
trustedProxies: [
|
|
102
|
+
// Cloudflare IP ranges
|
|
103
|
+
'173.245.48.0/20', '103.21.244.0/22', '103.22.200.0/22'
|
|
104
|
+
],
|
|
105
|
+
headerPreference: ['cf-connecting-ip', 'x-forwarded-for'],
|
|
106
|
+
allowPrivateIps: false // Only real client IPs
|
|
107
|
+
}
|
|
108
|
+
});
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
### High-Security Environment
|
|
112
|
+
|
|
113
|
+
```typescript
|
|
114
|
+
const app = new YinzerFlow({
|
|
115
|
+
port: 3000,
|
|
116
|
+
ipSecurity: {
|
|
117
|
+
trustedProxies: ['10.0.1.100'], // Only specific proxy
|
|
118
|
+
maxChainLength: 2, // Short chains only
|
|
119
|
+
detectSpoofing: true,
|
|
120
|
+
allowPrivateIps: false
|
|
121
|
+
}
|
|
122
|
+
});
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
### Complex Infrastructure (Unknown Proxies)
|
|
126
|
+
|
|
127
|
+
```typescript
|
|
128
|
+
const app = new YinzerFlow({
|
|
129
|
+
port: 3000,
|
|
130
|
+
ipSecurity: {
|
|
131
|
+
trustedProxies: ['*'], // Trust any proxy - useful for Kubernetes, unknown CDNs
|
|
132
|
+
detectSpoofing: true, // Still detect attack patterns
|
|
133
|
+
maxChainLength: 10,
|
|
134
|
+
allowPrivateIps: false
|
|
135
|
+
}
|
|
136
|
+
});
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
## Error Handling
|
|
140
|
+
|
|
141
|
+
YinzerFlow handles IP parsing errors gracefully and applies security validation automatically:
|
|
142
|
+
|
|
143
|
+
**Common behaviors:**
|
|
144
|
+
- Invalid IP formats result in empty `request.ipAddress`
|
|
145
|
+
- Untrusted proxy chains are rejected when strict validation is enabled
|
|
146
|
+
- Spoofing patterns are detected and suspicious headers are ignored automatically
|
|
147
|
+
- Private IPs are filtered when `allowPrivateIps: false` is configured
|
|
148
|
+
|
|
149
|
+
```typescript
|
|
150
|
+
app.get('/api/user-location', ({ request }) => {
|
|
151
|
+
const clientIp = request.ipAddress;
|
|
152
|
+
|
|
153
|
+
if (!clientIp) {
|
|
154
|
+
// YinzerFlow couldn't determine a valid, trusted IP
|
|
155
|
+
return {
|
|
156
|
+
error: 'Unable to determine client location',
|
|
157
|
+
message: 'IP address validation failed'
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
// Safe to use clientIp - YinzerFlow has validated it
|
|
162
|
+
return await getLocationForIp(clientIp);
|
|
163
|
+
});
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
## Security Considerations
|
|
167
|
+
|
|
168
|
+
YinzerFlow implements several security measures to prevent IP spoofing attacks and ensure accurate client identification:
|
|
169
|
+
|
|
170
|
+
### 🛡️ Trusted Proxy Validation
|
|
171
|
+
- **Problem**: Attackers can spoof `X-Forwarded-For` headers to hide their real IP address or impersonate other clients
|
|
172
|
+
- **YinzerFlow Solution**: Only accepts forwarded headers from explicitly configured trusted proxy IPs, preventing spoofing from untrusted sources
|
|
173
|
+
|
|
174
|
+
#### How Trusted Proxies Work
|
|
175
|
+
|
|
176
|
+
When using `X-Forwarded-For` headers, YinzerFlow validates proxy chains by checking if the **rightmost IP** (the proxy that sent the request) is in your trusted proxies list:
|
|
177
|
+
|
|
178
|
+
```
|
|
179
|
+
X-Forwarded-For: 203.0.113.1, 198.51.100.1, 127.0.0.1
|
|
180
|
+
^client IP ^proxy 1 ^proxy 2 (rightmost - must be trusted)
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
**Key Points:**
|
|
184
|
+
- **Only the rightmost IP needs to be trusted** - this is the proxy that directly sent the request to your server
|
|
185
|
+
- **Client IP is extracted** - YinzerFlow extracts the leftmost IP (203.0.113.1) as the real client
|
|
186
|
+
- **Chain validation** - If the rightmost IP isn't in your `trustedProxies` list, the entire header is rejected
|
|
187
|
+
- **Wildcard support** - Use `['*']` to trust any proxy (useful for Kubernetes/unknown infrastructure)
|
|
188
|
+
|
|
189
|
+
**Examples:**
|
|
190
|
+
```typescript
|
|
191
|
+
// ✅ Valid: 127.0.0.1 is trusted, extracts 203.0.113.1 as client
|
|
192
|
+
trustedProxies: ['127.0.0.1']
|
|
193
|
+
X-Forwarded-For: 203.0.113.1, 127.0.0.1
|
|
194
|
+
|
|
195
|
+
// ❌ Invalid: 192.168.1.1 is not trusted, header rejected
|
|
196
|
+
trustedProxies: ['127.0.0.1']
|
|
197
|
+
X-Forwarded-For: 203.0.113.1, 192.168.1.1
|
|
198
|
+
|
|
199
|
+
// ✅ Valid: Wildcard trusts any proxy
|
|
200
|
+
trustedProxies: ['*']
|
|
201
|
+
X-Forwarded-For: 203.0.113.1, any.proxy.ip
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
### 🛡️ Multiple Header Support
|
|
205
|
+
- **Problem**: Different proxies and CDNs use different headers (X-Real-IP, CF-Connecting-IP, etc.), making it hard to get consistent client IPs
|
|
206
|
+
- **YinzerFlow Solution**: Configurable header preference order with validation for each header type based on its expected format and source
|
|
207
|
+
|
|
208
|
+
### 🛡️ IP Format Validation
|
|
209
|
+
- **Problem**: Malformed IP addresses can cause application errors or bypass security controls
|
|
210
|
+
- **YinzerFlow Solution**: Comprehensive IPv4 and IPv6 validation with named capture groups for precise format checking
|
|
211
|
+
|
|
212
|
+
### 🛡️ Spoofing Pattern Detection
|
|
213
|
+
- **Problem**: Sophisticated attacks use patterns like duplicate IPs, overly long chains, or mixed valid/invalid IPs to confuse parsing
|
|
214
|
+
- **YinzerFlow Solution**: Advanced pattern detection identifies suspicious IP chains and automatically rejects them
|
|
215
|
+
|
|
216
|
+
### 🛡️ Private IP Filtering
|
|
217
|
+
- **Problem**: Internal network IPs might leak information about network topology or be used in certain attacks
|
|
218
|
+
- **YinzerFlow Solution**: Configurable private IP filtering with RFC 1918, RFC 4193, and RFC 3927 range detection
|
|
219
|
+
|
|
220
|
+
### 🛡️ Chain Length Limits
|
|
221
|
+
- **Problem**: Extremely long IP chains can cause DoS attacks through memory exhaustion or processing delays
|
|
222
|
+
- **YinzerFlow Solution**: Configurable maximum chain length prevents amplification attacks while allowing legitimate proxy chains
|
|
223
|
+
|
|
224
|
+
### 🛡️ Fallback Protection
|
|
225
|
+
- **Problem**: When strict validation fails, applications might fall back to unsafe IP extraction methods
|
|
226
|
+
- **YinzerFlow Solution**: Controlled fallback behavior that maintains security when trusted proxies are configured
|
|
227
|
+
|
|
228
|
+
### 🛡️ IPv6 Security
|
|
229
|
+
- **Problem**: IPv6 addresses have complex formats that can be exploited for parsing attacks or validation bypasses
|
|
230
|
+
- **YinzerFlow Solution**: Robust IPv6 validation including compression rules, zone identifiers, and IPv4-mapped addresses
|
|
231
|
+
|
|
232
|
+
These security measures ensure YinzerFlow's IP parsing implementation follows security best practices and prevents common attack vectors while maintaining compatibility with standard proxy configurations.
|
package/docs/request.md
ADDED
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
# Request Object
|
|
2
|
+
|
|
3
|
+
YinzerFlow provides a comprehensive request object containing parsed headers, body, query parameters, route parameters, and metadata with built-in security protections and validation.
|
|
4
|
+
|
|
5
|
+
## Configuration
|
|
6
|
+
|
|
7
|
+
Request parsing is automatically enabled and requires no configuration for basic usage:
|
|
8
|
+
|
|
9
|
+
```typescript
|
|
10
|
+
import { YinzerFlow } from 'yinzerflow';
|
|
11
|
+
|
|
12
|
+
const app = new YinzerFlow({ port: 3000 });
|
|
13
|
+
|
|
14
|
+
// Request object is automatically parsed and available in handlers
|
|
15
|
+
app.get('/api/data', ({ request }) => {
|
|
16
|
+
const userAgent = request.headers['user-agent'];
|
|
17
|
+
const queryParam = request.query.search;
|
|
18
|
+
|
|
19
|
+
return {
|
|
20
|
+
message: 'Request parsed successfully',
|
|
21
|
+
userAgent,
|
|
22
|
+
queryParam
|
|
23
|
+
};
|
|
24
|
+
});
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
### Configuration Options
|
|
28
|
+
|
|
29
|
+
YinzerFlow's request parsing includes built-in security limits that are automatically applied:
|
|
30
|
+
|
|
31
|
+
| Security Limit | Default Value | Description |
|
|
32
|
+
|-----|---|---|
|
|
33
|
+
| `MAX_HEADERS` | `100` | Maximum number of headers per request |
|
|
34
|
+
| `MAX_HEADER_NAME_LENGTH` | `200` | Maximum length of header names |
|
|
35
|
+
| `MAX_HEADER_VALUE_LENGTH` | `8192` | Maximum length of header values |
|
|
36
|
+
|
|
37
|
+
These limits are built into the framework and cannot be disabled, ensuring consistent security across all YinzerFlow applications.
|
|
38
|
+
|
|
39
|
+
## Basic Example
|
|
40
|
+
|
|
41
|
+
```typescript
|
|
42
|
+
import { YinzerFlow } from 'yinzerflow';
|
|
43
|
+
|
|
44
|
+
const app = new YinzerFlow({ port: 3000 });
|
|
45
|
+
|
|
46
|
+
app.post('/api/users/:id', ({ request }) => {
|
|
47
|
+
// Access route parameters
|
|
48
|
+
const userId = request.params.id;
|
|
49
|
+
|
|
50
|
+
// Access query parameters
|
|
51
|
+
const includeProfile = request.query.include_profile;
|
|
52
|
+
|
|
53
|
+
// Access headers
|
|
54
|
+
const contentType = request.headers['content-type'];
|
|
55
|
+
const authorization = request.headers['authorization'];
|
|
56
|
+
|
|
57
|
+
// Access request body
|
|
58
|
+
const userData = request.body;
|
|
59
|
+
|
|
60
|
+
const clientIp = request.ipAddress
|
|
61
|
+
|
|
62
|
+
return {
|
|
63
|
+
message: 'Request processed successfully',
|
|
64
|
+
userId,
|
|
65
|
+
includeProfile,
|
|
66
|
+
contentType,
|
|
67
|
+
hasAuth: !!authorization,
|
|
68
|
+
receivedData: userData
|
|
69
|
+
};
|
|
70
|
+
});
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
## Common Use Cases
|
|
74
|
+
|
|
75
|
+
- **Authentication**: Extract and validate Bearer tokens, API keys, and session headers
|
|
76
|
+
- **Content Negotiation**: Handle Accept, Accept-Encoding, and Content-Type headers for proper response formatting
|
|
77
|
+
- **File Uploads**: Process multipart form data with automatic parsing and validation
|
|
78
|
+
- **API Filtering**: Use query parameters for pagination, sorting, and filtering
|
|
79
|
+
- **Route Parameters**: Extract dynamic URL segments with automatic parsing
|
|
80
|
+
- **Request Logging**: Access client IP, user agent, and request metadata for logging
|
|
81
|
+
|
|
82
|
+
## Error Handling
|
|
83
|
+
|
|
84
|
+
YinzerFlow automatically handles request parsing errors and provides clear error messages:
|
|
85
|
+
|
|
86
|
+
**Header-related errors:**
|
|
87
|
+
- `Too many headers: maximum 100 allowed`
|
|
88
|
+
- `Invalid header name: Invalid@Header`
|
|
89
|
+
- `Header name too long: maximum 200 characters allowed`
|
|
90
|
+
- `Header value too long: maximum 8192 characters allowed`
|
|
91
|
+
- `Header value contains invalid control characters`
|
|
92
|
+
|
|
93
|
+
**Body parsing errors:** See [Body Parsing Documentation](./body-parsing.md) for detailed error handling
|
|
94
|
+
|
|
95
|
+
These errors automatically result in appropriate HTTP status codes (400 Bad Request) and prevent malformed requests from reaching your application handlers.
|
|
96
|
+
|
|
97
|
+
## Security Considerations
|
|
98
|
+
|
|
99
|
+
YinzerFlow implements several security measures to prevent common request-based vulnerabilities:
|
|
100
|
+
|
|
101
|
+
### 🛡️ RFC 7230 Header Compliance
|
|
102
|
+
- **Problem**: Invalid header names can bypass security filters and cause parsing inconsistencies
|
|
103
|
+
- **YinzerFlow Solution**: Strict validation against RFC 7230 specification - only valid header characters are allowed (letters, digits, hyphens, and specific symbols)
|
|
104
|
+
|
|
105
|
+
### 🛡️ DoS Protection Through Limits
|
|
106
|
+
- **Problem**: Unlimited headers, names, or values can cause memory exhaustion and server crashes
|
|
107
|
+
- **YinzerFlow Solution**: Built-in limits prevent abuse: maximum 100 headers, 200-character names, and 8KB values
|
|
108
|
+
|
|
109
|
+
### 🛡️ Control Character Sanitization
|
|
110
|
+
- **Problem**: Control characters in headers can cause parsing errors and bypass security filters
|
|
111
|
+
- **YinzerFlow Solution**: Automatic removal of dangerous control characters while preserving legitimate characters like horizontal tabs
|
|
112
|
+
|
|
113
|
+
### 🛡️ Body Parsing Protection
|
|
114
|
+
- **Problem**: Malformed request bodies can cause parsing errors, memory exhaustion, or security vulnerabilities
|
|
115
|
+
- **YinzerFlow Solution**: Comprehensive body parsing security with size limits, validation, and protection against common attacks - see [Body Parsing Documentation](./body-parsing.md)
|
|
116
|
+
|
|
117
|
+
### 🛡️ Parameter Pollution Prevention
|
|
118
|
+
- **Problem**: Duplicate query parameters can bypass validation or cause unexpected behavior
|
|
119
|
+
- **YinzerFlow Solution**: Consistent parameter handling - last value wins for duplicates, preventing pollution attacks
|
|
120
|
+
|
|
121
|
+
### 🛡️ Path Traversal Protection
|
|
122
|
+
- **Problem**: Directory traversal attacks through URL paths can access unauthorized files
|
|
123
|
+
- **YinzerFlow Solution**: Comprehensive path normalization and validation prevents traversal attempts while maintaining route functionality
|
|
124
|
+
|
|
125
|
+
### 🛡️ IP Address Validation
|
|
126
|
+
- **Problem**: Spoofed proxy headers can bypass IP-based security controls
|
|
127
|
+
- **YinzerFlow Solution**: Secure IP address extraction with proxy header validation prevents spoofing attacks
|
|
128
|
+
|
|
129
|
+
## Body Parsing
|
|
130
|
+
|
|
131
|
+
YinzerFlow automatically parses request bodies (JSON, file uploads, forms) with built-in security protections. Parsed data is available on `request.body` - see [Body Parsing Documentation](./body-parsing.md) for detailed configuration options, examples, and security considerations.
|
|
132
|
+
|
|
133
|
+
```typescript
|
|
134
|
+
app.post('/api/users', ({ request, response }) => {
|
|
135
|
+
// Body is automatically parsed based on Content-Type
|
|
136
|
+
const userData = request.body;
|
|
137
|
+
|
|
138
|
+
return {
|
|
139
|
+
message: 'User created successfully',
|
|
140
|
+
data: userData
|
|
141
|
+
};
|
|
142
|
+
});
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
These security measures ensure YinzerFlow's request implementation follows security best practices and prevents common attack vectors while maintaining RFC compliance and performance.
|
package/docs/response.md
ADDED
|
@@ -0,0 +1,251 @@
|
|
|
1
|
+
# Response Object
|
|
2
|
+
|
|
3
|
+
YinzerFlow provides a powerful response object for sending HTTP responses with automatic content type detection, header validation, and built-in security protections.
|
|
4
|
+
|
|
5
|
+
## Configuration
|
|
6
|
+
|
|
7
|
+
Response handling is automatically enabled and requires no configuration for basic usage:
|
|
8
|
+
|
|
9
|
+
```typescript
|
|
10
|
+
import { YinzerFlow } from 'yinzerflow';
|
|
11
|
+
|
|
12
|
+
const app = new YinzerFlow({ port: 3000 });
|
|
13
|
+
|
|
14
|
+
// Response object is automatically available in handlers
|
|
15
|
+
app.get('/api/data', ({ response }) => {
|
|
16
|
+
// Set status code
|
|
17
|
+
response.setStatusCode(200);
|
|
18
|
+
|
|
19
|
+
// Add headers
|
|
20
|
+
response.addHeaders({
|
|
21
|
+
'Content-Type': 'application/json',
|
|
22
|
+
'Cache-Control': 'no-cache'
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
return { message: 'Response sent successfully' };
|
|
26
|
+
});
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
YinzerFlow's response handling includes built-in security protections that are automatically applied to prevent common vulnerabilities, including automatic security headers on all responses.
|
|
30
|
+
|
|
31
|
+
## Basic Example
|
|
32
|
+
|
|
33
|
+
```typescript
|
|
34
|
+
import { YinzerFlow } from 'yinzerflow';
|
|
35
|
+
|
|
36
|
+
const app = new YinzerFlow({ port: 3000 });
|
|
37
|
+
|
|
38
|
+
app.get('/api/users/:id', ({ request, response }) => {
|
|
39
|
+
const userId = request.params.id;
|
|
40
|
+
|
|
41
|
+
// Set successful status code
|
|
42
|
+
response.setStatusCode(200);
|
|
43
|
+
|
|
44
|
+
// Add custom headers
|
|
45
|
+
response.addHeaders({
|
|
46
|
+
'X-User-ID': userId,
|
|
47
|
+
'Cache-Control': 'max-age=3600',
|
|
48
|
+
'X-API-Version': '1.0'
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
// Return JSON response body (Content-Type automatically set)
|
|
52
|
+
return {
|
|
53
|
+
id: userId,
|
|
54
|
+
name: 'John Doe',
|
|
55
|
+
email: 'john@example.com',
|
|
56
|
+
timestamp: new Date().toISOString()
|
|
57
|
+
};
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
app.post('/api/files', ({ request, response }) => {
|
|
61
|
+
// Set created status
|
|
62
|
+
response.setStatusCode(201);
|
|
63
|
+
|
|
64
|
+
// Add location header for created resource
|
|
65
|
+
response.addHeaders({
|
|
66
|
+
'Location': '/api/files/12345',
|
|
67
|
+
'X-Upload-Size': request.headers['content-length'] || '0'
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
return { fileId: '12345', status: 'uploaded' };
|
|
71
|
+
});
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
## Response Body Handling
|
|
75
|
+
|
|
76
|
+
YinzerFlow automatically processes response bodies based on their type:
|
|
77
|
+
|
|
78
|
+
### JSON Objects and Arrays
|
|
79
|
+
|
|
80
|
+
Objects and arrays are automatically JSON stringified with `Content-Type: application/json`:
|
|
81
|
+
|
|
82
|
+
```typescript
|
|
83
|
+
// Automatically becomes JSON
|
|
84
|
+
return { message: 'Hello', data: [1, 2, 3] };
|
|
85
|
+
// Content-Type: application/json
|
|
86
|
+
// Body: {"message":"Hello","data":[1,2,3]}
|
|
87
|
+
|
|
88
|
+
return [{ id: 1 }, { id: 2 }];
|
|
89
|
+
// Content-Type: application/json
|
|
90
|
+
// Body: [{"id":1},{"id":2}]
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
### Strings
|
|
94
|
+
|
|
95
|
+
String responses get intelligent content type detection:
|
|
96
|
+
|
|
97
|
+
```typescript
|
|
98
|
+
// JSON string
|
|
99
|
+
return '{"message": "Hello"}';
|
|
100
|
+
// Content-Type: application/json
|
|
101
|
+
|
|
102
|
+
// Form data
|
|
103
|
+
return 'name=John&email=john@example.com';
|
|
104
|
+
// Content-Type: application/x-www-form-urlencoded
|
|
105
|
+
|
|
106
|
+
// Plain text
|
|
107
|
+
return 'Hello, world!';
|
|
108
|
+
// Content-Type: text/plain
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
### Binary Data
|
|
112
|
+
|
|
113
|
+
Binary data is handled with appropriate encoding:
|
|
114
|
+
|
|
115
|
+
```typescript
|
|
116
|
+
// Buffer/Uint8Array/ArrayBuffer
|
|
117
|
+
const imageBuffer = Buffer.from(imageData);
|
|
118
|
+
return imageBuffer;
|
|
119
|
+
// Content-Type: application/octet-stream (for binary)
|
|
120
|
+
// Content-Type: text/plain (for text-like content)
|
|
121
|
+
|
|
122
|
+
// Base64 encoding for true binary
|
|
123
|
+
response.addHeaders({ 'Content-Transfer-Encoding': 'base64' });
|
|
124
|
+
return imageBuffer; // Automatically encoded as base64
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
### Primitives
|
|
128
|
+
|
|
129
|
+
Numbers, booleans, and other primitives are converted to strings:
|
|
130
|
+
|
|
131
|
+
```typescript
|
|
132
|
+
return 42; // "42", Content-Type: text/plain
|
|
133
|
+
return true; // "true", Content-Type: text/plain
|
|
134
|
+
return new Date(); // ISO string, Content-Type: text/plain
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
## API Reference
|
|
138
|
+
|
|
139
|
+
### setStatusCode(statusCode)
|
|
140
|
+
|
|
141
|
+
Sets the HTTP status code for the response.
|
|
142
|
+
|
|
143
|
+
```typescript
|
|
144
|
+
response.setStatusCode(200); // OK
|
|
145
|
+
response.setStatusCode(201); // Created
|
|
146
|
+
response.setStatusCode(400); // Bad Request
|
|
147
|
+
response.setStatusCode(404); // Not Found
|
|
148
|
+
response.setStatusCode(500); // Internal Server Error
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
### addHeaders(headers)
|
|
152
|
+
|
|
153
|
+
Adds or updates response headers. Headers are validated for security before being set.
|
|
154
|
+
|
|
155
|
+
```typescript
|
|
156
|
+
// Single header
|
|
157
|
+
response.addHeaders({ 'X-Custom-Header': 'value' });
|
|
158
|
+
|
|
159
|
+
// Multiple headers
|
|
160
|
+
response.addHeaders({
|
|
161
|
+
'Cache-Control': 'max-age=3600',
|
|
162
|
+
'X-API-Version': '2.0',
|
|
163
|
+
'Access-Control-Allow-Origin': '*'
|
|
164
|
+
});
|
|
165
|
+
|
|
166
|
+
// Security headers
|
|
167
|
+
response.addHeaders({
|
|
168
|
+
'X-Content-Type-Options': 'nosniff',
|
|
169
|
+
'X-Frame-Options': 'DENY',
|
|
170
|
+
'X-XSS-Protection': '1; mode=block'
|
|
171
|
+
});
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
### removeHeaders(headerNames)
|
|
175
|
+
|
|
176
|
+
Removes headers from the response.
|
|
177
|
+
|
|
178
|
+
```typescript
|
|
179
|
+
// Remove single header
|
|
180
|
+
response.removeHeaders(['X-Powered-By']);
|
|
181
|
+
|
|
182
|
+
// Remove multiple headers
|
|
183
|
+
response.removeHeaders(['Server', 'X-Debug-Info', 'X-Internal-ID']);
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
## Common Use Cases
|
|
187
|
+
|
|
188
|
+
- **Set Status Codes**: Configure HTTP status codes (200, 404, 500, etc.) to communicate request results to clients
|
|
189
|
+
- **Add Custom Headers**: Include metadata, caching directives, and API versioning information in responses
|
|
190
|
+
- **Handle File Downloads**: Stream binary data with proper Content-Type and Content-Disposition headers for file downloads
|
|
191
|
+
- **Configure CORS**: Enable cross-origin requests by adding Access-Control headers for browser security
|
|
192
|
+
- **Implement Redirects**: Send location headers with 301/302 status codes to redirect clients to new resources
|
|
193
|
+
- **Process Error Responses**: Return appropriate error status codes and structured error messages for client debugging
|
|
194
|
+
|
|
195
|
+
## Error Handling
|
|
196
|
+
|
|
197
|
+
YinzerFlow automatically handles response processing errors and provides clear error messages:
|
|
198
|
+
|
|
199
|
+
**Header-related errors:**
|
|
200
|
+
- `Invalid header value: contains CRLF characters`
|
|
201
|
+
- `Suspicious header pattern detected: potential injection attempt`
|
|
202
|
+
- `Header validation failed: invalid characters in header name`
|
|
203
|
+
|
|
204
|
+
**Body processing errors:**
|
|
205
|
+
- `Failed to stringify response body: circular reference detected`
|
|
206
|
+
- `Binary data encoding error: invalid buffer format`
|
|
207
|
+
- `Response body too large: exceeds maximum size limit`
|
|
208
|
+
|
|
209
|
+
These errors are automatically logged and result in appropriate HTTP status codes (500 Internal Server Error) to prevent malformed responses from being sent to clients.
|
|
210
|
+
|
|
211
|
+
## Security Considerations
|
|
212
|
+
|
|
213
|
+
YinzerFlow implements several security measures to prevent common response-based vulnerabilities:
|
|
214
|
+
|
|
215
|
+
### 🛡️ CRLF Injection Prevention
|
|
216
|
+
- **Problem**: Injecting carriage return (`\r`) or line feed (`\n`) characters in header values can allow attackers to inject additional headers or even HTTP response splitting attacks
|
|
217
|
+
- **YinzerFlow Solution**: Comprehensive validation detects and blocks CRLF characters in header values before they are set, preventing header injection attacks
|
|
218
|
+
|
|
219
|
+
### 🛡️ Response Header Validation
|
|
220
|
+
- **Problem**: Invalid header names or values can cause parsing errors in clients or bypass security controls
|
|
221
|
+
- **YinzerFlow Solution**: All response headers are validated against HTTP specifications and security patterns before being sent
|
|
222
|
+
|
|
223
|
+
### 🛡️ Suspicious Pattern Detection
|
|
224
|
+
- **Problem**: Attackers may try to inject malicious headers like `Set-Cookie` or create HTTP response splitting attacks
|
|
225
|
+
- **YinzerFlow Solution**: Advanced pattern detection identifies and blocks suspicious header values that could indicate injection attempts
|
|
226
|
+
|
|
227
|
+
### 🛡️ Safe Header Filtering
|
|
228
|
+
- **Problem**: Undefined or null header values can cause unexpected behavior or security bypasses
|
|
229
|
+
- **YinzerFlow Solution**: Automatic filtering removes undefined values and validates all headers before they reach the response
|
|
230
|
+
|
|
231
|
+
### 🛡️ Content-Type Security
|
|
232
|
+
- **Problem**: Missing or incorrect Content-Type headers can lead to MIME sniffing attacks or content confusion
|
|
233
|
+
- **YinzerFlow Solution**: Intelligent content type detection ensures appropriate Content-Type headers are set based on response body content
|
|
234
|
+
|
|
235
|
+
### 🛡️ JSON Stringification Safety
|
|
236
|
+
- **Problem**: Circular references or non-serializable objects can crash the server or leak sensitive information
|
|
237
|
+
- **YinzerFlow Solution**: Safe JSON stringification with error handling prevents crashes and provides fallback string conversion
|
|
238
|
+
|
|
239
|
+
### 🛡️ Binary Data Handling
|
|
240
|
+
- **Problem**: Improper binary data encoding can corrupt files or expose server internals
|
|
241
|
+
- **YinzerFlow Solution**: Proper binary data detection and encoding ensures files are transmitted correctly and securely
|
|
242
|
+
|
|
243
|
+
### 🛡️ Status Code Validation
|
|
244
|
+
- **Problem**: Invalid HTTP status codes can confuse clients or indicate server errors
|
|
245
|
+
- **YinzerFlow Solution**: Automatic mapping of status codes to standard HTTP status messages ensures consistent and valid responses
|
|
246
|
+
|
|
247
|
+
### 🛡️ Automatic Security Headers
|
|
248
|
+
- **Problem**: Missing security headers leave applications vulnerable to clickjacking, MIME sniffing, and XSS attacks
|
|
249
|
+
- **YinzerFlow Solution**: Automatically adds essential security headers to every response unless explicitly overridden by the application
|
|
250
|
+
|
|
251
|
+
These security measures ensure YinzerFlow's response implementation follows security best practices and prevents common attack vectors while maintaining HTTP compliance and performance.
|