|
@@ -1,25 +1,28 @@
|
|
/**
|
|
/**
|
|
- * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
|
|
|
|
|
|
+ * Copyright (c) 2018-2019 mol* contributors, licensed under MIT, See LICENSE file for more info.
|
|
*
|
|
*
|
|
* Taken/adapted from DensityServer (https://github.com/dsehnal/DensityServer)
|
|
* Taken/adapted from DensityServer (https://github.com/dsehnal/DensityServer)
|
|
*
|
|
*
|
|
* @author David Sehnal <david.sehnal@gmail.com>
|
|
* @author David Sehnal <david.sehnal@gmail.com>
|
|
|
|
+ * @author Alexander Rose <alexander.rose@weirdbyte.de>
|
|
*/
|
|
*/
|
|
|
|
|
|
import * as express from 'express'
|
|
import * as express from 'express'
|
|
|
|
|
|
import * as Api from './api'
|
|
import * as Api from './api'
|
|
-
|
|
|
|
import * as Data from './query/data-model'
|
|
import * as Data from './query/data-model'
|
|
import * as Coords from './algebra/coordinate'
|
|
import * as Coords from './algebra/coordinate'
|
|
-import Docs from './documentation'
|
|
|
|
-import ServerConfig from '../server-config'
|
|
|
|
import { ConsoleLogger } from 'mol-util/console-logger'
|
|
import { ConsoleLogger } from 'mol-util/console-logger'
|
|
import { State } from './state'
|
|
import { State } from './state'
|
|
|
|
+import { LimitsConfig, ServerConfig } from '../config';
|
|
|
|
+import { interpolate } from 'mol-util/string';
|
|
|
|
+import { getSchema, shortcutIconLink } from './web-schema';
|
|
|
|
+import { swaggerUiIndexHandler, swaggerUiAssetsHandler } from 'servers/common/swagger-ui';
|
|
|
|
|
|
export default function init(app: express.Express) {
|
|
export default function init(app: express.Express) {
|
|
|
|
+ app.locals.mapFile = getMapFileFn()
|
|
function makePath(p: string) {
|
|
function makePath(p: string) {
|
|
- return ServerConfig.apiPrefix + '/' + p;
|
|
|
|
|
|
+ return `${ServerConfig.apiPrefix}/${p}`;
|
|
}
|
|
}
|
|
|
|
|
|
// Header
|
|
// Header
|
|
@@ -29,18 +32,40 @@ export default function init(app: express.Express) {
|
|
// Cell /:src/:id/cell/?text=0|1&space=cartesian|fractional
|
|
// Cell /:src/:id/cell/?text=0|1&space=cartesian|fractional
|
|
app.get(makePath(':source/:id/cell/?'), (req, res) => queryBox(req, res, getQueryParams(req, true)));
|
|
app.get(makePath(':source/:id/cell/?'), (req, res) => queryBox(req, res, getQueryParams(req, true)));
|
|
|
|
|
|
- app.get('*', (req, res) => {
|
|
|
|
- res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });
|
|
|
|
- res.end(Docs);
|
|
|
|
|
|
+ app.get(makePath('openapi.json'), (req, res) => {
|
|
|
|
+ res.writeHead(200, {
|
|
|
|
+ 'Content-Type': 'application/json; charset=utf-8',
|
|
|
|
+ 'Access-Control-Allow-Origin': '*',
|
|
|
|
+ 'Access-Control-Allow-Headers': 'X-Requested-With'
|
|
|
|
+ });
|
|
|
|
+ res.end(JSON.stringify(getSchema()));
|
|
});
|
|
});
|
|
|
|
+
|
|
|
|
+ app.use(makePath(''), swaggerUiAssetsHandler());
|
|
|
|
+ app.get(makePath(''), swaggerUiIndexHandler({
|
|
|
|
+ openapiJsonUrl: makePath('openapi.json'),
|
|
|
|
+ apiPrefix: ServerConfig.apiPrefix,
|
|
|
|
+ title: 'VolumeServer API',
|
|
|
|
+ shortcutIconLink
|
|
|
|
+ }));
|
|
}
|
|
}
|
|
|
|
|
|
-function mapFile(type: string, id: string) {
|
|
|
|
- return ServerConfig.mapFile(type || '', id || '');
|
|
|
|
|
|
+function getMapFileFn() {
|
|
|
|
+ const map = new Function('type', 'id', 'interpolate', [
|
|
|
|
+ 'id = id.toLowerCase()',
|
|
|
|
+ 'switch (type.toLowerCase()) {',
|
|
|
|
+ ...ServerConfig.idMap.map(mapping => {
|
|
|
|
+ const [type, path] = mapping
|
|
|
|
+ return ` case '${type}': return interpolate('${path}', { id });`
|
|
|
|
+ }),
|
|
|
|
+ ' default: return void 0;',
|
|
|
|
+ '}'
|
|
|
|
+ ].join('\n'))
|
|
|
|
+ return (type: string, id: string) => map(type, id, interpolate)
|
|
}
|
|
}
|
|
|
|
|
|
function wrapResponse(fn: string, res: express.Response) {
|
|
function wrapResponse(fn: string, res: express.Response) {
|
|
- const w = {
|
|
|
|
|
|
+ return {
|
|
do404(this: any) {
|
|
do404(this: any) {
|
|
if (!this.headerWritten) {
|
|
if (!this.headerWritten) {
|
|
res.writeHead(404);
|
|
res.writeHead(404);
|
|
@@ -74,13 +99,11 @@ function wrapResponse(fn: string, res: express.Response) {
|
|
ended: false,
|
|
ended: false,
|
|
headerWritten: false
|
|
headerWritten: false
|
|
};
|
|
};
|
|
-
|
|
|
|
- return w;
|
|
|
|
}
|
|
}
|
|
|
|
|
|
function getSourceInfo(req: express.Request) {
|
|
function getSourceInfo(req: express.Request) {
|
|
return {
|
|
return {
|
|
- filename: mapFile(req.params.source, req.params.id),
|
|
|
|
|
|
+ filename: req.app.locals.mapFile(req.params.source, req.params.id),
|
|
id: `${req.params.source}/${req.params.id}`
|
|
id: `${req.params.source}/${req.params.id}`
|
|
};
|
|
};
|
|
}
|
|
}
|
|
@@ -104,7 +127,7 @@ async function getHeader(req: express.Request, res: express.Response) {
|
|
|
|
|
|
try {
|
|
try {
|
|
const { filename, id } = getSourceInfo(req);
|
|
const { filename, id } = getSourceInfo(req);
|
|
- const header = await Api.getHeaderJson(filename, id);
|
|
|
|
|
|
+ const header = await Api.getExtendedHeaderJson(filename, id);
|
|
if (!header) {
|
|
if (!header) {
|
|
res.writeHead(404);
|
|
res.writeHead(404);
|
|
return;
|
|
return;
|
|
@@ -130,7 +153,7 @@ function getQueryParams(req: express.Request, isCell: boolean): Data.QueryParams
|
|
const a = [+req.params.a1, +req.params.a2, +req.params.a3];
|
|
const a = [+req.params.a1, +req.params.a2, +req.params.a3];
|
|
const b = [+req.params.b1, +req.params.b2, +req.params.b3];
|
|
const b = [+req.params.b1, +req.params.b2, +req.params.b3];
|
|
|
|
|
|
- const detail = Math.min(Math.max(0, (+req.query.detail) | 0), ServerConfig.limits.maxOutputSizeInVoxelCountByPrecisionLevel.length - 1)
|
|
|
|
|
|
+ const detail = Math.min(Math.max(0, (+req.query.detail) | 0), LimitsConfig.maxOutputSizeInVoxelCountByPrecisionLevel.length - 1)
|
|
const isCartesian = (req.query.space || '').toLowerCase() !== 'fractional';
|
|
const isCartesian = (req.query.space || '').toLowerCase() !== 'fractional';
|
|
|
|
|
|
const box: Data.QueryParamsBox = isCell
|
|
const box: Data.QueryParamsBox = isCell
|
|
@@ -140,7 +163,7 @@ function getQueryParams(req: express.Request, isCell: boolean): Data.QueryParams
|
|
: { kind: 'Fractional', a: Coords.fractional(a[0], a[1], a[2]), b: Coords.fractional(b[0], b[1], b[2]) });
|
|
: { kind: 'Fractional', a: Coords.fractional(a[0], a[1], a[2]), b: Coords.fractional(b[0], b[1], b[2]) });
|
|
|
|
|
|
const asBinary = (req.query.encoding || '').toLowerCase() !== 'cif';
|
|
const asBinary = (req.query.encoding || '').toLowerCase() !== 'cif';
|
|
- const sourceFilename = mapFile(req.params.source, req.params.id)!;
|
|
|
|
|
|
+ const sourceFilename = req.app.locals.mapFile(req.params.source, req.params.id)!;
|
|
|
|
|
|
return {
|
|
return {
|
|
sourceFilename,
|
|
sourceFilename,
|