Skip to content

Commit dea6fdd

Browse files
committed
Forward HTTP requests in the LLM app
1 parent e25b3b0 commit dea6fdd

File tree

4 files changed

+83
-11
lines changed

4 files changed

+83
-11
lines changed

agent/apps/ztm/llm/api.js

Lines changed: 70 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,7 @@ export default function ({ app, mesh }) {
208208

209209
function getRoute(ep, path) {
210210
if (ep === app.endpoint.id) {
211+
if (!path.endsWith('/')) path += '/'
211212
var route = localRoutes.find(r => r.path === path)
212213
if (route) {
213214
return mesh.discover(route.service.endpoint.id).then(
@@ -237,8 +238,7 @@ export default function ({ app, mesh }) {
237238
if (ep === app.endpoint.id) {
238239
checkPath(path)
239240
checkRoute(info)
240-
var prefix = path
241-
if (!prefix.endsWith('/')) prefix += '/'
241+
if (!path.endsWith('/')) path += '/'
242242
var service = {
243243
name: info.service.name,
244244
kind: info.service.kind,
@@ -248,9 +248,9 @@ export default function ({ app, mesh }) {
248248
if (localRoutes[i]?.path === path) {
249249
localRoutes[i].service = service
250250
} else if (i < 0) {
251-
localRoutes.push({ path, prefix, service })
251+
localRoutes.push({ path, service })
252252
} else {
253-
localRoutes.splice(i, 0, { path, prefix, service })
253+
localRoutes.splice(i, 0, { path, service })
254254
}
255255
saveLocalConfig()
256256
return Promise.resolve()
@@ -267,6 +267,7 @@ export default function ({ app, mesh }) {
267267

268268
function deleteRoute(ep, path) {
269269
if (ep === app.endpoint.id) {
270+
if (!path.endsWith('/')) path += '/'
270271
var i = localRoutes.findIndex(r => r.path === path)
271272
if (i >= 0) {
272273
localRoutes.splice(i, 1)
@@ -283,9 +284,72 @@ export default function ({ app, mesh }) {
283284
}
284285
}
285286

286-
var forwardService = pipeline($=>$)
287+
var $route
287288

288-
var connectService = pipeline($=>$)
289+
var forwardService = pipeline($=>$
290+
.pipe(evt => {
291+
if (evt instanceof MessageStart) {
292+
var url = new URL(evt.head.path)
293+
var path = url.pathname
294+
if (path.startsWith('/svc/')) path = path.substring(4)
295+
if (!path.endsWith('/')) path += '/'
296+
if ($route = localRoutes.findLast(r => path.startsWith(r.path))) {
297+
var service = $route.service
298+
var basepath = `/api/forward/${service.kind}/${URL.encodeComponent(service.name)}`
299+
evt.head.path = os.path.join(basepath, path.substring($route.path.length)) + url.search
300+
return ($route.service.endpoint.id === app.endpoint.id ? 'local' : 'remote')
301+
} else {
302+
return '404'
303+
}
304+
}
305+
}, {
306+
'remote': ($=>$
307+
.muxHTTP(() => $route, { version: 2 }).to($=>$
308+
.pipe(() => mesh.connect($route.service.endpoint.id))
309+
)
310+
),
311+
'local': $=>$.pipe(connectService),
312+
'404': $=>$.replaceMessage(new Message({ status: 404 })),
313+
})
314+
)
315+
316+
var matchApiForwardKindName = new http.Match('/api/forward/{kind}/{name}')
317+
var matchApiForwardKindNameStar = new http.Match('/api/forward/{kind}/{name}/*')
318+
319+
var $service
320+
var $serviceURL
321+
322+
var connectService = pipeline($=>$
323+
.pipe(evt => {
324+
if (evt instanceof MessageStart) {
325+
var url = new URL(evt.head.path)
326+
var params = matchApiForwardKindNameStar(url.pathname) || matchApiForwardKindName(url.pathname)
327+
if (params) {
328+
var kind = params.kind
329+
var name = URL.decodeComponent(params.name)
330+
evt.head.path = '/' + (params['*'] || '') + url.search
331+
$service = localServices[kind]?.[name]
332+
}
333+
if (!$service) return '404'
334+
return $service.target.address.startsWith('/') ? 'stdio' : 'http'
335+
}
336+
}, {
337+
'http': ($=>$
338+
.handleMessageStart(msg => {
339+
$serviceURL = new URL($service.target.address)
340+
msg.head.path = os.path.join($serviceURL.pathname, msg.head.path)
341+
msg.head.headers.host = $serviceURL.hostname
342+
})
343+
.muxHTTP(() => $service).to($=>$
344+
.connect(() => `${$serviceURL.hostname}:${$serviceURL.port}`)
345+
)
346+
),
347+
'stdio': ($=>$
348+
.replaceMessage(new Message({ status: 404 }))
349+
),
350+
'404': $=>$.replaceMessage(new Message({ status: 404 })),
351+
})
352+
)
289353

290354
function getServiceFilePathname(username, ep, kind, name) {
291355
if (!username) {

agent/apps/ztm/llm/cli.js

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,6 @@ export default function ({ app, mesh, api, utils }) {
172172
'SERVICE': r => r.service.name,
173173
'KIND': r => r.service.kind,
174174
'ENDPOINT': r => {
175-
println(r)
176175
var ep = endpoints[r.service.endpoint.id]
177176
return ep.name || ep.id
178177
},

agent/apps/ztm/llm/main.js

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ export default function ({ app, mesh, utils }) {
3434
))
3535
},
3636

37-
'/api/services/*': {
37+
'/svc/*': {
3838
'GET': pipeline($=>$.pipe(api.forwardService, () => $ctx)),
3939
'POST': pipeline($=>$.pipe(api.forwardService, () => $ctx)),
4040
},
@@ -156,8 +156,6 @@ export default function ({ app, mesh, utils }) {
156156
'DELETE': responderOwnerOnly(({ kind, name }) => {
157157
return api.deleteService(app.endpoint.id, kind, URL.decodeComponent(name)).then(response(204))
158158
}),
159-
160-
'CONNECT': pipeline($=>$.pipe(api.connectService, () => $ctx)),
161159
},
162160

163161
'/api/routes': {
@@ -184,6 +182,16 @@ export default function ({ app, mesh, utils }) {
184182
return api.deleteRoute(app.endpoint.id, '/' + params['*']).then(response(204))
185183
}),
186184
},
185+
186+
'/api/forward/{kind}/{name}': {
187+
'GET': pipeline($=>$.pipe(api.connectService, () => $ctx)),
188+
'POST': pipeline($=>$.pipe(api.connectService, () => $ctx)),
189+
},
190+
191+
'/api/forward/{kind}/{name}/*': {
192+
'GET': pipeline($=>$.pipe(api.connectService, () => $ctx)),
193+
'POST': pipeline($=>$.pipe(api.connectService, () => $ctx)),
194+
},
187195
})
188196

189197
return pipeline($=>$

agent/main.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -611,7 +611,8 @@ function main(listen) {
611611
}
612612
),
613613
'app': ($=>$
614-
.onStart(() => api.connectApp(
614+
.onStart(
615+
() => api.connectApp(
615616
URL.decodeComponent($params.mesh),
616617
URL.decodeComponent($params.provider),
617618
URL.decodeComponent($params.app),

0 commit comments

Comments
 (0)