Skip to content

Commit

Permalink
first files
Browse files Browse the repository at this point in the history
  • Loading branch information
hvoss49 committed Dec 16, 2020
1 parent 230016c commit c7ccd63
Show file tree
Hide file tree
Showing 32 changed files with 5,120 additions and 0 deletions.
18 changes: 18 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#####################################################################################
# Compile this dockerfile with
# time sudo docker build -t hvoss49/pyonline:latest -f Dockerfile .
# Run docker image
# sudo docker run -d -p 3000:3000 --rm --name pyonline hvoss49/pyonline:latest
#####################################################################################
# Latex-Online container

MAINTAINER Herbert Voss [email protected]

# Install git & Node.JS
RUN apt-get clean && apt-get update && apt-get install -y git-core nodejs npm && rm -rf /var/lib/apt/lists/*

COPY ./util/docker-entrypoint.sh /

EXPOSE 2701
CMD ["./docker-entrypoint.sh"]

171 changes: 171 additions & 0 deletions app.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
var path = require('path');
var PythonOnline = require('./lib/PythonOnline');
var Janitor = require('./lib/Janitor');
var HealthMonitor = require('./lib/HealthMonitor');
var utils = require('./lib/utilities');

var logger = utils.logger('app.js');

var VERSION = process.env.VERSION || "master";
VERSION = VERSION.substr(0, 9);

// Will be initialized later.
var pythonOnline;
var healthMonitor;

// Initialize service dependencies.
PythonOnline.create('/tmp/downloads/', '/tmp/storage/')
.then(onInitialized)

function onInitialized(python) {
pythonOnline = python;
if (!pythonOnline) {
logger.error('ERROR: failed to initialize pythonOnline');
return;
}

// Initialize janitor to clean up stale storage.
var expiry = utils.hours(24);
var cleanupTimeout = utils.minutes(5);
var janitor = new Janitor(pythonOnline, expiry, cleanupTimeout);

// Initialize health monitor
healthMonitor = new HealthMonitor(pythonOnline);

// Launch server.
var port = process.env.PORT || 3000;
var listener = app.listen(port, () => {
logger.info("Express server started", {
port: listener.address().port,
env: app.settings.env,
sha: VERSION
});
});
}

// Initialize server.
var express = require('express');
var compression = require('compression');
var useragent = require('express-useragent');

var app = express();
app.use(compression());
app.use(useragent.express());
app.use(express.static(__dirname + '/public'));

function sendError(res, userError) {
res.set('Content-Type', 'text/plain');
var statusCode = userError ? 400 : 500;
var error = userError || 'Internal Server Error';
res.status(statusCode).send(error)
}

async function handleResult(res, preparation, force, downloadName) {
var {request, downloader, userError} = preparation;
if (!request) {
sendError(res, userError);
return;
}
var compilation = pythonOnline.compilationWithFingerprint(request.fingerprint);
if (force && compilation)
pythonOnline.removeCompilation(compilation);
compilation = pythonOnline.getOrCreateCompilation(request, downloader);
await compilation.run();

// In case of URL compilation and cached compilation object, the downlaoder
// has to be cleaned up.
downloader.dispose();

if (compilation.userError) {
sendError(res, compilation.userError);
} else if (compilation.success) {
if (downloadName)
res.set('content-disposition', `attachment; filename="${downloadName}"`);
res.status(200).sendFile(compilation.outputPath(), {acceptRanges: false});
} else {
res.status(400).sendFile(compilation.logPath(), {acceptRanges: false});
}
}

app.get('/version', (req, res) => {
res.json({
version: VERSION,
link: `http://github.com/aslushnikov/python-online/commit/${VERSION}`
});
});

app.get('/health.json', (req, res) => {
if (!healthMonitor) {
sendError(res, 'ERROR: health monitor is not initialized.');
return;
}
var result = {
uptime: healthMonitor.uptime(),
health: healthMonitor.healthPoints()
};
res.json(result);
});

app.get('/health', (req, res) => {
res.sendFile(path.join(__dirname, 'public', 'health.html'));
});

app.get('/pending', (req, res) => {
res.sendFile(path.join(__dirname, 'public', 'pending.html'));
});

var pendingTrackIds = new Set();
app.get('/compile', async (req, res) => {
// Do not leak too much memory if clients drop connections on redirect.
if (pendingTrackIds.size > 10000)
pendingTrackIds.clear();
var trackId = req.query.trackId;
var isBrowser = !req.useragent.isBot;
// Redirect browser to the page with analytics code.
if (isBrowser && (!trackId || !pendingTrackIds.has(trackId))) {
trackId = Date.now() + '';
pendingTrackIds.add(trackId);
var query = Object.assign({}, req.query);
query.trackId = trackId;

var search = Object.keys(query).map(key => `${key}=${encodeURIComponent(query[key])}`).join('&');
res.redirect(307, `/pending?${search}`);
return;
}
pendingTrackIds.delete(trackId);

var forceCompilation = req.query && !!req.query.force;
var command = req.query && req.query.command ? req.query.command : 'python';
command = command.trim().toLowerCase();
var preparation;
if (req.query.text) {
preparation = await pythonOnline.prepareTextCompilation(req.query.text, command);
} else if (req.query.url) {
preparation = await pythonOnline.prepareURLCompilation(req.query.url, command);
} else if (req.query.git) {
var workdir = req.query.workdir || '';
preparation = await pythonOnline.prepareGitCompilation(req.query.git, req.query.target, 'master', command, workdir);
}
if (preparation)
handleResult(res, preparation, forceCompilation, req.query.download);
else
sendError(res, 'ERROR: failed to parse request: ' + JSON.stringify(req.query));
});

var multer = require('multer')
var upload = multer({ dest: '/tmp/file-uploads/' })
app.post('/data', upload.any(), async (req, res) => {
if (!req.files || req.files.length !== 1) {
sendError(res, 'ERROR: files are not uploaded to server.');
return;
}
var command = req.query && req.query.command ? req.query.command : 'python';
command = command.trim().toLowerCase();
var file = req.files[0];
var preparation = await pythonOnline.prepareTarballCompilation(file.path, req.query.target, command);
if (preparation)
await handleResult(res, preparation, true /* force */, null /* downloadName */);
else
sendError(res, 'ERROR: failed to process file upload!');
utils.unlink(file.path);
});
38 changes: 38 additions & 0 deletions examples/pdfgenerator.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<script>
document.addEventListener('DOMContentLoaded', function onDOMContentLoaded() {
document.querySelector('#update').addEventListener('click', updatePreview);

function updatePreview() {
var text = document.querySelector('textarea').value;
var py = [
text
].join('\n');
var iframe = document.querySelector('iframe');
iframe.src = 'https://pyonline.hvoss.org/compile?text=' + encodeURIComponent(tex);
}
});
</script>
<style>
body {
display: flex;
flex-direction: column;
align-items: center;
}
iframe {
width: 800px;
height: 800px;
}
textarea {
width: 400px;
}
</style>
<h1>PDF Generator</h1>
<textarea>foo="Hello Python"
print (foo)</textarea>
<div>
<button id='update'>preview PDF</button>
</div>
<h4>PDF preview</h4>
<iframe>
</iframe>

Loading

0 comments on commit c7ccd63

Please sign in to comment.