dicomweb-proxy
Version:
A proxy to translate between dicomweb and dimse
99 lines (88 loc) • 3.26 kB
text/typescript
import { ConfParams, config } from './utils/config';
import { io } from 'socket.io-client';
import { doFind } from './dimse/findData';
import { stringToQueryLevel } from './dimse/querLevel';
import { doWadoUri } from './dimse/wadoUri';
import { LoggerSingleton } from './utils/logger';
import { doWadoRs, DataFormat } from './dimse/wadoRs';
import socketIOStream from '@wearemothership/socket.io-stream';
import combineMerge from './utils/combineMerge';
import deepmerge from 'deepmerge';
const options = { arrayMerge: combineMerge };
const websocketUrl = config.get(ConfParams.WEBSOCKET_URL) as string;
const logger = LoggerSingleton.Instance;
export const socket = io(websocketUrl, {
reconnection: true,
reconnectionDelayMax: 10000,
autoConnect: false,
auth: {
token: config.get(ConfParams.WEBSOCKET_TOKEN),
},
});
socket.on('connect', () => {
logger.info('websocket connection established');
});
socket.on('qido-request', async (data) => {
const { level, query }: { level: string; query: Record<string, string> } = data;
if (data) {
const lvl = stringToQueryLevel(level);
logger.info('websocket QIDO request received, fetching metadata now...', level, data);
const json = deepmerge.all(await doFind(lvl, query), options);
logger.info('sending websocket response');
socket.emit(data.uuid, json);
}
});
type WadoRequest = {
studyInstanceUid: string;
seriesInstanceUid?: string;
sopInstanceUid?: string;
dataFormat?: DataFormat;
};
socket.on('wado-request', async (data) => {
const { query }: { query: WadoRequest } = data;
const { studyInstanceUid, seriesInstanceUid, sopInstanceUid, dataFormat } = query;
if (data) {
logger.info('websocket WADO request received, fetching metadata now...');
const { contentType, buffer } = await doWadoRs({ studyInstanceUid, seriesInstanceUid, sopInstanceUid, dataFormat });
logger.info('sending websocket response stream');
const stream = socketIOStream.createStream();
socketIOStream(socket).emit(data.uuid, stream, { contentType: contentType });
let offset = 0;
const chunkSize = 512 * 1024; // 512kb
const writeBuffer = () => {
let ok = true;
do {
const b = Buffer.alloc(chunkSize);
buffer.copy(b, 0, offset, offset + chunkSize);
ok = stream.write(b);
offset += chunkSize;
} while (offset < buffer.length && ok);
if (offset < buffer.length) {
stream.once('drain', writeBuffer);
} else {
stream.end();
}
};
writeBuffer();
}
});
socket.on('wadouri-request', async (data) => {
if (data) {
const { studyUID, seriesUID, objectUID, studyInstanceUid, seriesInstanceUid, sopInstanceUid } = data.query;
try {
logger.info('websocket wadouri request received, fetching metadata now...');
const rsp = await doWadoUri({
studyInstanceUid: studyInstanceUid ?? studyUID,
seriesInstanceUid: seriesInstanceUid ?? seriesUID,
sopInstanceUid: sopInstanceUid ?? objectUID,
});
socket.emit(data.uuid, rsp);
} catch (error) {
logger.error(error);
socket.emit(data.uuid, error);
}
}
});
socket.on('disconnect', () => {
logger.info('websocket connection disconnected');
});