This repository has been archived by the owner on Feb 5, 2020. It is now read-only.
/
ldf-client-http
executable file
·121 lines (107 loc) · 4.31 KB
/
ldf-client-http
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
#!/usr/bin/env node
/*! @license ©2013 Ruben Verborgh - Multimedia Lab / iMinds / Ghent University */
/* HTTP server that executes SPARQL queries over triple pattern fragments. */
var path = require('path'),
http = require('http'),
url = require('url'),
querystring = require('querystring'),
exec = require('child_process').exec,
spawn = require('child_process').spawn,
Negotiator = require('negotiator');
var clientPath = path.join(__dirname, 'ldf-client');
var availableMimeTypes = getAvailableMimeTypes();
var MIME_PLAIN = 'text/plain',
MIME_TURTLE = 'text/turtle',
MIME_JSON = 'application/json';
// Retrieve and check arguments
var args = require('minimist')(process.argv.slice(2));
if (args._.length > 1 || args.h || args.help) {
console.error('usage: ldf-client-http [startFragment] [-c config.json] [-p port] [--help]');
return process.exit(1);
}
var node = process.argv[0],
startFragment = args._[0],
port = parseInt(args.p, 10) || 3000,
configFile = args.c || path.join(__dirname, '../config-default.json'),
clientArgs = [clientPath, '-c', configFile],
ioSettings = { stdio: ['ignore', 'pipe', 'pipe'] };
startFragment && clientArgs.push(startFragment);
// Start the server
var server = http.createServer(handleRequest);
server.listen(port);
console.error('Server running on http://localhost:' + port + '/');
// Handles an HTTP request
function handleRequest(request, response) {
// Verify the path
var requestUrl = url.parse(request.url, true);
if (requestUrl.pathname !== '/sparql') {
response.writeHead(404, { 'content-type': MIME_JSON });
response.end(JSON.stringify({ message: 'Resource not found' }));
return;
}
// Parse the query, depending on the HTTP method
switch (request.method) {
case 'POST':
return parseBody(request, function (query) { writeQueryResult(request, response, query); });
case 'GET':
return writeQueryResult(request, response, requestUrl.query.query || '');
default:
response.writeHead(405, { 'content-type': MIME_JSON });
response.end(JSON.stringify({ message: 'Incorrect HTTP method' }));
}
}
// Writes the result of the given SPARQL query
function writeQueryResult(request, response, query) {
// Get the results of the query from the client
var hasTriplesResult = /\s*(?:CONSTRUCT|DESCRIBE)/i.test(query),
mimeType = hasTriplesResult ? MIME_TURTLE : new Negotiator(request).mediaType(availableMimeTypes),
client = spawn(node, clientArgs.concat(['-t', mimeType, '-q', query]), ioSettings);
// Write a successful data response
client.stdout.setEncoding('utf8');
client.stdout.once('data', function (data) {
if (!response.headersSent) {
response.writeHead(200, { 'content-type': mimeType });
response.write(data);
client.stdout.pipe(response);
}
});
// Write an error response
client.stderr.setEncoding('utf8');
client.stderr.once('data', function (data) {
if (!response.headersSent) {
response.writeHead(400, { 'content-type': MIME_PLAIN });
response.write(data);
client.stderr.pipe(response);
}
});
// End the response if all streams have ended
var ended = false;
client.stdout.on('end', function () { ended ? response.end() : ended = true; });
client.stderr.on('end', function () { ended ? response.end() : ended = true; });
// Stop the client if the connection is terminated
response.on('close', function () { client.kill('SIGKILL'); });
}
// Parses the body of a SPARQL POST request
function parseBody(request, callback) {
var body = '';
request.setEncoding('utf8');
request.on('data', function (chunk) { body += chunk; });
request.on('end', function () {
switch (request.headers['content-type']) {
case 'application/sparql-query':
return callback(body);
case 'application/x-www-form-urlencoded':
return callback(querystring.parse(body).query || '');
default:
return callback('');
}
});
}
// Retrieves the MIME types supported by the client
function getAvailableMimeTypes() {
var client = spawn(process.argv[0], [clientPath, '--listformats']), data = '', mimeTypes = [];
client.stdout.setEncoding('utf8');
client.stdout.on('data', function (chunk) { data += chunk; });
client.stdout.on('end', function () { mimeTypes.push.apply(mimeTypes, data.trim().split('\n')); });
return mimeTypes;
}