instaserve 1.1.4 → 1.1.6
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 +65 -1
- package/instaserve +9 -0
- package/module.mjs +48 -4
- package/package.json +1 -1
- package/test.js +28 -0
package/README.md
CHANGED
|
@@ -107,6 +107,39 @@ export default {
|
|
|
107
107
|
}
|
|
108
108
|
```
|
|
109
109
|
|
|
110
|
+
### Method-Specific Routes
|
|
111
|
+
|
|
112
|
+
Routes can be defined with HTTP method prefixes to handle different methods on the same path. Supported methods: `GET`, `POST`, `PUT`, `DELETE`.
|
|
113
|
+
|
|
114
|
+
```javascript
|
|
115
|
+
export default {
|
|
116
|
+
// Method-specific routes
|
|
117
|
+
'POST /users': (req, res, data) => {
|
|
118
|
+
return { message: 'Create user', data }
|
|
119
|
+
},
|
|
120
|
+
|
|
121
|
+
'GET /users': (req, res, data) => {
|
|
122
|
+
return { message: 'Get users' }
|
|
123
|
+
},
|
|
124
|
+
|
|
125
|
+
'PUT /users': (req, res, data) => {
|
|
126
|
+
return { message: 'Update user', data }
|
|
127
|
+
},
|
|
128
|
+
|
|
129
|
+
'DELETE /users': (req, res, data) => {
|
|
130
|
+
return { message: 'Delete user', data }
|
|
131
|
+
},
|
|
132
|
+
|
|
133
|
+
// Path-only routes still work (backward compatible)
|
|
134
|
+
// These match any HTTP method
|
|
135
|
+
hello: (req, res, data) => {
|
|
136
|
+
return { message: 'Hello World' }
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
Method-specific routes take precedence over path-only routes. If no method-specific route matches, the server falls back to path-only route matching.
|
|
142
|
+
|
|
110
143
|
### Special Routes (Middleware)
|
|
111
144
|
|
|
112
145
|
Routes starting with `_` are middleware functions that run on **every request** before the main route handler. They are useful for:
|
|
@@ -152,6 +185,25 @@ Each route function receives:
|
|
|
152
185
|
- URL query parameters
|
|
153
186
|
- Form data
|
|
154
187
|
|
|
188
|
+
### Returning Status Codes
|
|
189
|
+
|
|
190
|
+
Routes can return a 3-digit number (100-999) to set the HTTP status code with an empty response body:
|
|
191
|
+
|
|
192
|
+
```javascript
|
|
193
|
+
export default {
|
|
194
|
+
'GET /notfound': () => 404,
|
|
195
|
+
'GET /unauthorized': () => 401,
|
|
196
|
+
'GET /forbidden': () => 403,
|
|
197
|
+
'GET /teapot': () => 418, // I'm a teapot
|
|
198
|
+
'GET /created': () => 201
|
|
199
|
+
}
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
Routes can also return:
|
|
203
|
+
- **Strings** - Sent as plain text response
|
|
204
|
+
- **Objects** - Automatically serialized as JSON
|
|
205
|
+
- **Status codes** - 3-digit numbers (100-999) set HTTP status with empty body
|
|
206
|
+
|
|
155
207
|
### Example Routes File
|
|
156
208
|
|
|
157
209
|
```javascript
|
|
@@ -163,7 +215,19 @@ export default {
|
|
|
163
215
|
return false // Continue to next route
|
|
164
216
|
},
|
|
165
217
|
|
|
166
|
-
//
|
|
218
|
+
// Method-specific routes
|
|
219
|
+
'POST /api/users': (req, res, data) => {
|
|
220
|
+
return { status: 'created', data }
|
|
221
|
+
},
|
|
222
|
+
|
|
223
|
+
'GET /api/users': (req, res, data) => {
|
|
224
|
+
return { status: 'ok', users: [] }
|
|
225
|
+
},
|
|
226
|
+
|
|
227
|
+
'GET /api/notfound': () => 404,
|
|
228
|
+
'GET /api/unauthorized': () => 401,
|
|
229
|
+
|
|
230
|
+
// Path-only route (matches any method)
|
|
167
231
|
api: (req, res, data) => {
|
|
168
232
|
return { status: 'ok', data }
|
|
169
233
|
},
|
package/instaserve
CHANGED
|
@@ -59,6 +59,15 @@ if (args[0] === 'generate-routes') {
|
|
|
59
59
|
|
|
60
60
|
api: (req, res, data) => {
|
|
61
61
|
return { message: 'API endpoint', data }
|
|
62
|
+
},
|
|
63
|
+
|
|
64
|
+
// Method-specific routes (POST, GET, PUT, DELETE)
|
|
65
|
+
'POST /users': (req, res, data) => {
|
|
66
|
+
return { message: 'Create user', data }
|
|
67
|
+
},
|
|
68
|
+
|
|
69
|
+
'GET /users': (req, res, data) => {
|
|
70
|
+
return { message: 'Get users' }
|
|
62
71
|
}
|
|
63
72
|
}
|
|
64
73
|
`
|
package/module.mjs
CHANGED
|
@@ -51,6 +51,21 @@ export default async function (routes, port = params.port || 3000, ip = params.i
|
|
|
51
51
|
let sdata = '', rrurl = r.url || ''
|
|
52
52
|
let responseSent = false
|
|
53
53
|
|
|
54
|
+
// Helper to check if value is a 3-digit HTTP status code
|
|
55
|
+
const isStatusCode = (val) => {
|
|
56
|
+
return typeof val === 'number' && val >= 100 && val <= 999 && Math.floor(val) === val
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// Helper to send response, handling status codes
|
|
60
|
+
const sendResponse = (result) => {
|
|
61
|
+
if (isStatusCode(result)) {
|
|
62
|
+
s.writeHead(result)
|
|
63
|
+
s.end()
|
|
64
|
+
} else {
|
|
65
|
+
s.end(typeof result === 'string' ? result : JSON.stringify(result))
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
54
69
|
r.on('data', (s) => sdata += s.toString().trim())
|
|
55
70
|
r.on('end', (x) => {
|
|
56
71
|
try {
|
|
@@ -68,7 +83,7 @@ export default async function (routes, port = params.port || 3000, ip = params.i
|
|
|
68
83
|
const result = routes[k](r, s, data)
|
|
69
84
|
if (result && !responseSent) {
|
|
70
85
|
responseSent = true
|
|
71
|
-
|
|
86
|
+
sendResponse(result)
|
|
72
87
|
}
|
|
73
88
|
return result
|
|
74
89
|
})
|
|
@@ -84,11 +99,40 @@ export default async function (routes, port = params.port || 3000, ip = params.i
|
|
|
84
99
|
|
|
85
100
|
const urlParts = rrurl.split('/')
|
|
86
101
|
const url = urlParts.length > 1 ? urlParts[1].split('?')[0] : ''
|
|
87
|
-
|
|
88
|
-
|
|
102
|
+
const method = (r.method || 'GET').toUpperCase()
|
|
103
|
+
|
|
104
|
+
// Try method-specific route first (e.g., "POST /endp", "GET /")
|
|
105
|
+
const methodRoute = url ? `${method} /${url}` : `${method} /`
|
|
106
|
+
let routeHandler = routes[methodRoute]
|
|
107
|
+
|
|
108
|
+
// If no exact match, check if any method-specific route exists for this path
|
|
109
|
+
if (!routeHandler) {
|
|
110
|
+
const methods = ['GET', 'POST', 'PUT', 'DELETE']
|
|
111
|
+
const pathRoute = url ? `/${url}` : `/`
|
|
112
|
+
const hasMethodSpecificRoute = methods.some(m => {
|
|
113
|
+
const checkRoute = url ? `${m} /${url}` : `${m} /`
|
|
114
|
+
return routes[checkRoute] !== undefined
|
|
115
|
+
})
|
|
116
|
+
|
|
117
|
+
// If method-specific route exists but for different method, return 405
|
|
118
|
+
if (hasMethodSpecificRoute) {
|
|
119
|
+
if (!responseSent && !s.writableEnded) {
|
|
120
|
+
responseSent = true
|
|
121
|
+
s.writeHead(405)
|
|
122
|
+
s.end()
|
|
123
|
+
}
|
|
124
|
+
return
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// Fall back to path-only route (backward compatible)
|
|
128
|
+
routeHandler = routes[url]
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
if (routeHandler) {
|
|
132
|
+
const resp = routeHandler(r, s, data)
|
|
89
133
|
if (!responseSent && !s.writableEnded) {
|
|
90
134
|
responseSent = true
|
|
91
|
-
|
|
135
|
+
sendResponse(resp)
|
|
92
136
|
}
|
|
93
137
|
return
|
|
94
138
|
}
|
package/package.json
CHANGED
package/test.js
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
export default {
|
|
2
|
+
// Middleware functions (prefixed with _) run on every request
|
|
3
|
+
// Return false to continue processing, or a value to use as response
|
|
4
|
+
|
|
5
|
+
// Example: Log all requests
|
|
6
|
+
_log: (req, res, data) => {
|
|
7
|
+
console.log(`${req.method} ${req.url}`)
|
|
8
|
+
return false // Continue to next middleware or route
|
|
9
|
+
},
|
|
10
|
+
|
|
11
|
+
// Example: Basic authentication (commented out)
|
|
12
|
+
// _auth: (req, res, data) => {
|
|
13
|
+
// if (!data.token) {
|
|
14
|
+
// res.writeHead(401)
|
|
15
|
+
// return 'Unauthorized'
|
|
16
|
+
// }
|
|
17
|
+
// return false // Continue if authorized
|
|
18
|
+
// },
|
|
19
|
+
|
|
20
|
+
// Regular route handlers
|
|
21
|
+
hello: (req, res, data) => {
|
|
22
|
+
return { message: 'Hello World' }
|
|
23
|
+
},
|
|
24
|
+
|
|
25
|
+
api: (req, res, data) => {
|
|
26
|
+
return { message: 'API endpoint', data }
|
|
27
|
+
}
|
|
28
|
+
}
|