Skip to content
Snippets Groups Projects
Select Git revision
  • acd59b65608989d4996a2f275cb1e91e3c65df2d
  • master default protected
  • rednatco-v2
  • rednatco
  • test
  • ntc-tube-uniform-color
  • ntc-tube-missing-atoms
  • restore-vertex-array-per-program
  • watlas2
  • dnatco_new
  • cleanup-old-nodejs
  • webmmb
  • fix_auth_seq_id
  • update_deps
  • ext_dev
  • ntc_balls
  • nci-2
  • plugin
  • bugfix-0.4.5
  • nci
  • servers
  • v0.5.0-dev.1
  • v0.4.5
  • v0.4.4
  • v0.4.3
  • v0.4.2
  • v0.4.1
  • v0.4.0
  • v0.3.12
  • v0.3.11
  • v0.3.10
  • v0.3.9
  • v0.3.8
  • v0.3.7
  • v0.3.6
  • v0.3.5
  • v0.3.4
  • v0.3.3
  • v0.3.2
  • v0.3.1
  • v0.3.0
41 results

binary-cif.ts

Blame
  • web-api.ts 3.25 KiB
    /**
     * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
     *
     * @author David Sehnal <david.sehnal@gmail.com>
     */
    
    import * as express from 'express';
    import Config from '../config';
    import { QueryDefinition, QueryList } from './api';
    import { ConsoleLogger } from 'mol-util/console-logger';
    import { resolveJob } from './query';
    import { JobManager } from './jobs';
    import { UUID } from 'mol-util';
    
    function makePath(p: string) {
        return Config.appPrefix + '/' + p;
    }
    
    function wrapResponse(fn: string, res: express.Response) {
        const w = {
            doError(this: any, code = 404) {
                if (!this.headerWritten) {
                    res.writeHead(code);
                    this.headerWritten = true;
                }
                this.end();
            },
            writeHeader(this: any, binary: boolean) {
                if (this.headerWritten) return;
                res.writeHead(200, {
                    'Content-Type': binary ? 'application/octet-stream' : 'text/plain; charset=utf-8',
                    'Access-Control-Allow-Origin': '*',
                    'Access-Control-Allow-Headers': 'X-Requested-With',
                    'Content-Disposition': `inline; filename="${fn}"`
                });
                this.headerWritten = true;
            },
            writeBinary(this: any, data: Uint8Array) {
                if (!this.headerWritten) this.writeHeader(true);
                return res.write(new Buffer(data.buffer));
            },
            writeString(this: any, data: string) {
                if (!this.headerWritten) this.writeHeader(false);
                return res.write(data);
            },
            end(this: any) {
                if (this.ended) return;
                res.end();
                this.ended = true;
            },
            ended: false,
            headerWritten: false
        };
    
        return w;
    }
    
    const responseMap = new Map<UUID, express.Response>();
    
    async function processNextJob() {
        if (!JobManager.hasNext()) return;
    
        const job = JobManager.getNext();
        const response = responseMap.get(job.id)!;
        responseMap.delete(job.id);
    
        const filenameBase = `${job.entryId}_${job.queryDefinition.name.replace(/\s/g, '_')}`
        const writer = wrapResponse(job.responseFormat.isBinary ? `${filenameBase}.bcif` : `${filenameBase}.cif`, response);
        try {
            writer.writeHeader(job.responseFormat.isBinary);
            await resolveJob(job, writer);
        } catch (e) {
            ConsoleLogger.errorId(job.id, '' + e);
            // TODO: add some error?
            writer.doError(404);
        } finally {
            writer.end();
            setImmediate(processNextJob);
        }
    }
    
    function mapQuery(app: express.Express, queryName: string, queryDefinition: QueryDefinition) {
        app.get(makePath(':entryId/' + queryName), async (req, res) => {
            ConsoleLogger.log('Server', `Query '${req.params.entryId}/${queryName}'...`);
    
            if (JobManager.size >= Config.maxQueueLength) {
                // TODO use proper code: server busy
                res.writeHead(404);
                res.end();
                return;
            }
    
            const jobId = JobManager.add('pdb', req.params.entryId, queryName, req.query);
            responseMap.set(jobId, res);
            processNextJob();
        });
    }
    
    export function initWebApi(app: express.Express) {
        for (const q of QueryList) {
            mapQuery(app, q.name, q.definition);
        }
    }