-
Notifications
You must be signed in to change notification settings - Fork 73
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(ur): add
redirect
strategy #539
- Loading branch information
1 parent
de0d709
commit b1fe54f
Showing
11 changed files
with
200 additions
and
156 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,4 @@ | ||
.DS_Store | ||
wallet.json | ||
dist | ||
.VSCodeCounter | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,3 +2,4 @@ NODE_CONFIG_ENV="development" | |
DEBUG=* | ||
HOSTS="https://foo.bar,https://fizz.buzz" | ||
AO_UNIT=cu | ||
STRATEGY=proxy |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,84 +1,43 @@ | ||
import { Readable } from 'node:stream' | ||
import express from 'express' | ||
import WarpArBundles from 'warp-arbundles' | ||
import { join } from 'node:path' | ||
|
||
import { router } from './router.js' | ||
import cors from 'cors' | ||
import express from 'express' | ||
import heapdump from 'heapdump' | ||
import { pipe } from 'ramda' | ||
|
||
const { DataItem } = WarpArBundles | ||
import { config } from './config.js' | ||
import { logger } from './logger.js' | ||
|
||
/** | ||
* The ONLY custom bits needed for the router. | ||
* | ||
* Mount any custom endpoints, optionally reverse-proxying to the set of | ||
* underyling hosts with automatic failover, by using the injected revProxy handler | ||
*/ | ||
import { proxyWith } from './proxy.js' | ||
import { redirectWith } from './redirect.js' | ||
|
||
/** | ||
* The Reverse Proxy Configuration for an ao Compute Unit Router | ||
*/ | ||
function aoComputeUnitMount ({ app, revProxy }) { | ||
app.get('/', revProxy({ processIdFromRequest: (req) => 'process' })) | ||
app.get('/result/:messageTxId', revProxy({ processIdFromRequest: (req) => req.query['process-id'] })) | ||
app.get('/results/:processId', revProxy({ processIdFromRequest: (req) => req.params.processId })) | ||
app.get('/state/:processId', revProxy({ processIdFromRequest: (req) => req.params.processId })) | ||
app.get('/cron/:processId', revProxy({ processIdFromRequest: (req) => req.params.processId })) | ||
app.post('/dry-run', revProxy({ processIdFromRequest: (req) => req.query['process-id'] })) | ||
const middlewareWithByStrategy = { | ||
proxy: proxyWith, | ||
redirect: redirectWith | ||
} | ||
|
||
/** | ||
* The Reverse Proxy Configuration for an ao Messenger Unit Router | ||
*/ | ||
function aoMessengerUnitMount ({ app, revProxy }) { | ||
class InvalidDataItemError extends Error { | ||
constructor (...args) { | ||
super(...args) | ||
this.status = 422 | ||
} | ||
const middlewareWith = middlewareWithByStrategy[config.strategy] | ||
|
||
pipe( | ||
(app) => app.use(cors()), | ||
(app) => app.use(express.static(config.DUMP_PATH)), | ||
middlewareWith({ ...config }), | ||
(app) => { | ||
const server = app.listen(config.port, () => { | ||
logger(`Server is running on http://localhost:${config.port}`) | ||
}) | ||
|
||
process.on('SIGTERM', () => { | ||
logger('Recevied SIGTERM. Gracefully shutting down server...') | ||
server.close(() => logger('Server Shut Down')) | ||
}) | ||
|
||
process.on('SIGUSR2', () => { | ||
const name = `${Date.now()}.heapsnapshot` | ||
heapdump.writeSnapshot(join(config.DUMP_PATH, name)) | ||
console.log(name) | ||
}) | ||
|
||
return server | ||
} | ||
|
||
const isTagEqualTo = ({ name, value }) => (tag) => tag.name === name && tag.value === value | ||
const isMessage = (dataItem) => !!dataItem.tags.find(isTagEqualTo({ name: 'Type', value: 'Message' })) | ||
const isProcess = (dataItem) => !!dataItem.tags.find(isTagEqualTo({ name: 'Type', value: 'Process' })) | ||
|
||
app.get('/', (req, res, next) => { | ||
if (req.query.debug) return res.status(501).send('MU Tracing not implemented on the Router') | ||
|
||
/** | ||
* Continue the request, rev proxying with a static value in order to get the roout info response from a MU | ||
*/ | ||
return revProxy({ processIdFromRequest: () => 'process' })(req, res, next) | ||
}) | ||
|
||
/** | ||
* Since the MU receives opaque data items, we have to unpack it, to know which MU | ||
* to route to | ||
*/ | ||
app.post('/', express.raw({ type: 'application/octet-stream', limit: '10mb' }), revProxy({ | ||
processIdFromRequest: async (req) => { | ||
const dataItem = new DataItem(Buffer.from(req.body)) | ||
|
||
if (!(await dataItem.isValid())) throw new InvalidDataItemError('A valid and signed data item must be provided as the body') | ||
/** | ||
* The processId is the target on a message data item | ||
*/ | ||
if (isMessage(dataItem)) return dataItem.target | ||
/** | ||
* The processId is the dataItem itseld on a process data item | ||
*/ | ||
if (isProcess(dataItem)) return dataItem.id | ||
|
||
throw new InvalidDataItemError('Could not determine ao type of DataItem based on tag \'Type\'') | ||
}, | ||
/** | ||
* Since we consumed the request stream in order to parse the data item and | ||
* determine the processId, we must provide a new request stream, to be sent | ||
* as the body on proxied request | ||
*/ | ||
restreamBody: (req) => Readable.from(req.body) | ||
})) | ||
|
||
app.post('/monitor/:processId', revProxy({ processIdFromRequest: (req) => req.params.processId })) | ||
app.delete('/monitor/:processId', revProxy({ processIdFromRequest: (req) => req.params.processId })) | ||
} | ||
|
||
router({ cu: aoComputeUnitMount, mu: aoMessengerUnitMount }) | ||
)(express()) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.