So we are supposed to set up an WebServer with Fuseki and Nodejs.
I defined the classes with the following OWL Ontology and loaded it up to the Fuseki server.
<?xml version="1.0" encoding="utf-8" ?>
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:owl="http://www.w3.org/2002/07/owl#"
xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#"
xmlns:ns0="http://localhost:3000/data#">
<owl:DatatypeProperty rdf:about="http://localhost:3000/data#message">
</owl:DatatypeProperty>
<owl:DatatypeProperty rdf:about="http://localhost:3000/data#firstname">
<rdf:type rdf:resource="http://www.w3.org/2002/07/owl#ObjectProperty"/>
</owl:DatatypeProperty>
<owl:DatatypeProperty rdf:about="http://localhost:3000/data#lastname">
<rdf:type rdf:resource="http://www.w3.org/2002/07/owl#ObjectProperty"/>
</owl:DatatypeProperty>
<owl:Class rdf:about="http://localhost:3000/data#linkeddata">
<rdfs:comment>The class of all data types.</rdfs:comment>
<rdfs:label>The data type</rdfs:label>
</owl:Class>
<owl:Class rdf:about="http://localhost:3000/data#users">
<rdfs:comment>Users that post Tweets.</rdfs:comment>
<rdfs:label>Users</rdfs:label>
<rdfs:subClassOf rdf:resource="http://localhost:3000/data#linkeddata"/>
</owl:Class>
<owl:Class rdf:about="http://localhost:3000/data#tweets">
<rdfs:comment>Tweets contain messages of Users.</rdfs:comment>
<rdfs:label>Tweets</rdfs:label>
<rdfs:subClassOf rdf:resource="http://localhost:3000/data#linkeddata"/>
</owl:Class>
<owl:ObjectProperty rdf:about="http://localhost:3000/data#tweetedby">
</owl:ObjectProperty>
<rdf:Description rdf:about="http://localhost:3000/data#1234">
<rdf:type rdf:resource="http://localhost:3000/data#tweets"/>
<ns0:message>blablubbtweet</ns0:message>
<ns0:tweetedby>
<ns0:users rdf:about="http://localhost:3000/data#2345">
<ns0:firstname>Manuel</ns0:firstname>
<ns0:lastname>Neuer</ns0:lastname>
</ns0:users>
</ns0:tweetedby>
</rdf:Description>
</rdf:RDF>
I hope you can read it. It works however. I can then view the classes directly by typing this into Fuseki web interface. With "'2345" for example being the User Manuel Neuer.
SELECT * WHERE { GRAPH ?g { <http://localhost:3000/data#2345> ?p ?o}}
However, in my Node.js application, I somehow am only able to get the whole graph, and I dont know why.
The following is the Nodejs code :
I think the error must be at
function sparql_GET_Data_Element (URIhash) {
postData =
` describe <http://localhost:3030/data#` + URIhash + `>`
Its like he would always describe http:/localhost:3030/data# and never take the urihash. I would be delighted about every tip. Thanks alot. I test it by sending GET requests with Insomnia Rest Api.
http://localhost:3030/data#2345 this get request generates the same whole graph as http://localhost:3030/data#users.
const express = require('express')
const app = express()
const app_port = 3000
const apache_fuseki_persistence_url = 'http://localhost:3030'
const http = require('http');
const rdf_url_prefix_tag = 'PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>'
const rdff_url_prefix_tag = 'PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>'
const SPARQL_GET_ALL_CLASSES = function (){
postData =
`
prefix owl: <http://www.w3.org/2002/07/owl#>
prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#>
SELECT DISTINCT ?class ?label ?description
WHERE {
?class a owl:Class.
OPTIONAL { ?class rdfs:label ?label}
OPTIONAL { ?class rdfs:comment ?description}
}
`
const options = {
hostname: 'localhost',
port: 3030,
path: '/data/query',
method: 'POST',
headers: {
'Accept': 'application/sparql-results+json',
'Content-Type': 'application/sparql-query'
}
}
return new Promise(function(resolve, reject) {
var req = http.request( options, function(res) {
// reject on bad status
if (res.statusCode < 200 || res.statusCode >= 300) {
return reject(new Error('statusCode=' + res.statusCode));
}
var data = {};
res.on('data', function(chunk) {
data = chunk;
});
// resolve on end
res.on('end', function() {
resolve(JSON.parse(data));
});
});
// reject on request error
req.on('error', function(err) {
// This is not a "Second reject", just a different sort of failure
reject(err);
});
if (postData) {
req.write(postData);
}
// IMPORTANT
req.end();
});
}
function sparql_GET_Data_Element (URIhash) {
postData =
` describe <http://localhost:3030/data#` + URIhash + `>`
const options = {
hostname: 'localhost',
port: 3030,
path: '/data/query',
method: 'POST',
headers: {
'Accept': 'application/ld+json',
'Content-Type': 'application/sparql-query'
}
}
return new Promise(function(resolve, reject) {
var req = http.request( options, function(res) {
// reject on bad status
if (res.statusCode < 200 || res.statusCode >= 300) {
reject(new Error('statusCode=' + res.statusCode));
}
var data = [];
res.on('data', function(chunk) {
data.push(chunk);
});
// resolve on end
res.on('end', function() {
resolve(JSON.parse(data[0]));
});
});
// reject on request error
req.on('error', function(err) {
// This is not a "Second reject", just a different sort of failure
reject(err);
});
if (postData) {
req.write(postData);
}
// IMPORTANT
req.end();
});
}
function sparql_CREATE_NEW_CLASS(new_rdfs_class){
}
// var promiseB = promiseA.then(function(result) {
// // do something with result
// });
function rdfs_class_exists (requested_class){
return SPARQL_GET_ALL_CLASSES().then(result => {
let found_class = false;
result.results.bindings.forEach(element => {
if (element.class.value == 'http://localhost:3000/data#'+requested_class) {
found_class = true;
}
})
return found_class;
});
}
app.get('*', function(req, res, next){
path_elements = req.path.split('#');
var requested_class = path_elements[1];
rdfs_class_exists(requested_class).then((RDFS_Class_found) => {
if (RDFS_Class_found){
if(path_elements.length > 3){
sparql_GET_Data_Element(path_elements[3]).then(result => {
console.log('result: ' + result);
res.send(result);
}).catch(error => {
console.log(error);
res.send(error);
})
} else {
sparql_GET_Data_Element(path_elements[1]).then(result => {
console.log('result: ' + result);
var ele = sparql_GET_Data_element(path_elements[1]);
res.send(ele);
// res.send(result);
}).catch(error => {
console.log(error);
res.send(error);
})
}
} else res.status(400).send("RDFS Class not Found");
});
})
app.post('*', function(req, res, next){
next();
})
app.delete('*', function(req, res, next){
next();
})
app.put('*', function(req, res, next){
next();
})
app.all('*', function (req, res, next){
res.status(400).send('No Elements found');
})
/**
* Die API wartet auf Requests am Port 3000.
* Wird sie per Node gitlokal gestartet läuft sie unter http://localhost:3000/
*/
app.listen(app_port, function () {
console.log('Example app listening on port 3000!');
});
Related
I am trying to make a HTTP get request, but nothing is being returned as text. Here is my code
const http = require('http');
const ws = require('ws');
const wss = new ws.Server({noServer: true});
var XMLHttpRequest = require('xhr2');
function accept(req, res) {
console.log("got request")
wss.handleUpgrade(req, req.socket, Buffer.alloc(0), function(ws) {
//party name, sockets on party, limit 2
ws.on('message', function (msg) {
var message = JSON.parse(msg.toString())
if(message.type==='add') {
//do later
} else if(message.type==='start') {
httpGetAsync('192.168.26.23', "/startRelay")
} else if(message.type==='stop') {
httpGetAsync('92.168.26.23', "/stopRelay")
} else if(message.type==='status') {
httpGetAsync('92.168.26.23', "/")
}
});
ws.on('close', function () {
console.log('closed')
});
ws.on('error', function(error){
console.log('error - ' + JSON.stringify(error));
});
})
}
function httpGetAsync(theUrl, path) {
var options = {
host: theUrl,
path: path,
method: "GET",
}
callback = async function(response) {
var str = ''
response.on('data', function (chunk) {
str += chunk;
});
response.on('end', function () {
console.log(JSON.parse(str));
});
};
http.request(options, callback).end();
}
http.createServer(accept).listen(3000);
Here is what 192.168.26.23 has in it (if you type it up from my wifi onto google, this is what shows - and this data is what I need to get in a string)
{"success":true,"ms_left":0,"relayStarted":false}
Ok, i'm done. Please someone help me :(
I don't know how js and lambda works
What i have to do:
Send GET request and get response.
Write data from response to DynamoDb
I can do it 1by1 but can't do everything by 1 lambda call.
My code:
const https = require('https');
const crypto = require("crypto");
const AWS = require('aws-sdk');
const DynamoDb = new AWS.DynamoDB({region: 'eu-central-1'});
exports.handler = async (event) => {
let response;
console.log("Start");
let steamTicket;
let steamId;
if(event.body){
const body = JSON.parse(event.body);
if(body.steamticket && body.steamid){
steamTicket = body.steamticket;
steamId = body.steamid;
}
else{
response = {
statusCode: 400,
body: JSON.stringify({
authenticated: false,
reason: 'cant find steamid or steamticket in your request'
})
};
return response;
}
}
else{
response = {
statusCode: 400,
body: JSON.stringify({
authenticated: false,
reason: 'cant find request body'
})
};
return response;
}
await httprequest(steamTicket).then((data) =>{
if(data.response && data.response.params){
if(data.response.params.result == 'OK' && data.response.params.steamid == steamId){
console.log(JSON.stringify(data));
const sessionId = crypto.randomBytes(16).toString("hex");
console.log('Generated session id: ' + sessionId);
PutToDB(sessionId, steamId);
}
else{
response = {
statusCode: 400,
body: JSON.stringify({
authenticated: false,
reason: 'steam response is not OK or session != steamId'
})
};
return response;
}
}
else{
response = {
statusCode: 400,
body: JSON.stringify({
authenticated: false,
reason: 'invalid response from steam: ' + JSON.stringify(data)
})
};
return response;
}
});
};
async function PutToDB(sessionId, steamId){
var WriteParams = {
RequestItems:{
SteamSessions: []
}
};
WriteParams.RequestItems.SteamSessions.push({
PutRequest:{
Item: {
SteamId: {S: steamId},
SessionId: {S: sessionId},
ttl: {N: (Math.floor(Date.now() / 1000) + 600).toString()}
}
}
});
console.log('SessionIdToWrite: ' + sessionId);
return new Promise((resolve, reject) =>{
DynamoDb.batchWriteItem(WriteParams, function(err, data){
if(err){
console.log("Error", err);
}
else{
console.log("Success write", JSON.stringify(data));
}
})
})
}
async function httprequest(steamTicket) {
return new Promise((resolve, reject) => {
const options = {
host: 'partner.steam-api.com',
path: '/ISteamUserAuth/AuthenticateUserTicket/v1/?key=somekey&appid=someid&ticket=' + steamTicket,
port: 443,
method: 'GET'
};
const req = https.request(options, (res) => {
if (res.statusCode < 200 || res.statusCode >= 300) {
return reject(new Error('statusCode=' + res.statusCode));
}
var body = [];
res.on('data', function(chunk) {
body.push(chunk);
});
res.on('end', function() {
try {
body = JSON.parse(Buffer.concat(body).toString());
} catch(e) {
reject(e);
}
resolve(body);
});
});
req.on('error', (e) => {
reject(e.message);
});
// send the request
req.end();
});
}
I lost way already, i'm not even sure it should work like that.
And most confusing thing! This b give me this test results:
Run 1:
2021-03-05T13:28:47.741Z INFO Start
2021-03-05T13:28:48.612Z INFO {"response":{"params":{"result":"OK","steamid":"mysteamid","ownersteamid":"mysteamid","vacbanned":false,"publisherbanned":false}}}
2021-03-05T13:28:48.650Z INFO Generated session id: 6a5633a5f862d8663d0fe546a9c89feb
2021-03-05T13:28:48.650Z INFO SessionIdToWrite: 6a5633a5f862d8663d0fe546a9c89feb
DynamoDb is empty, here we can't see log from DynamoDb.batchWriteItem result.
Run 2:
2021-03-05T13:29:53.308Z INFO Start
2021-03-05T13:29:53.674Z INFO Success write {"UnprocessedItems":{}}
2021-03-05T13:29:54.048Z INFO {"response":{"params":{"result":"OK","steamid":"mysteamid","ownersteamid":"mysteamid","vacbanned":false,"publisherbanned":false}}}
2021-03-05T13:29:54.048Z INFO Generated session id: 05c62de782202fc100cea9d47e38242c
2021-03-05T13:29:54.048Z INFO SessionIdToWrite: 05c62de782202fc100cea9d47e38242c
And after second run i can see in DynamoDb sessionId from FIRST RUN (6a5633a5f862d8663d0fe546a9c89feb)
If i run it again, there will be id from 2nd run
I think it continues to run previous tasks on new run? Or what? I'm lost
Thank you for any help with it
You need to call reject / resolve in the DynamoDb.batchWriteItem call.
return new Promise((resolve, reject) =>{
DynamoDb.batchWriteItem(WriteParams, function(err, data){
if(err){
console.log("Error", err);
reject(err);
}
else{
console.log("Success write", JSON.stringify(data));
resolve();
}
})
})
this is my test file for upload and i explain it step by step:
I wrote a test to upload the file. the uploader method written with busboy module and it working true
but i have problem in test.
when result of uploader is error, this error never returned in .catch and go in .then.
more explain in code:
const http = require('http');
// const request = require('request');
const rp = require('request-promise');
const fs = require('fs');
const assert = require('chai').assert;
const port = process.env.PORT || 80;
const Q = require('q');
let server;
const options = {
method: 'POST',
uri: 'http://127.0.0.1/upload',
formData: {
name: 'test',
file: {
value: fs.createReadStream('./test/test.jpg'),
options: {
filename: 'test.jpg',
contentType: 'image/jpg'
}
}
},
headers: {
'Connection': 'Keep-Alive',
'content-type': 'multipart/form-data' // Is set automatically
},
json: true,
};
function startServer(port, cb) {
server = http.createServer(function (req, res) {
if (req.method === 'POST') {
if (req.url === '/upload') {
serveRequest(req, res);
}
}
});
server.listen(port, () => {
cb(function stopServer(done) {
setTimeout(function () {
server.close();
done();
}, 20);
});
console.log(`listening on port ${port} ...`);
});
}
function serveRequest(request, response) {
if (request.headers.hasOwnProperty('content-type')
&& request.headers['content-type'].split(';')[0] === 'multipart/form-data') {
serveUpload(request, response);
}
}
function serveUpload(request, response) {
uploader.upload(request, function (error, res) {
if (error) {
response.end();
}
else {
response.write(JSON.stringify(res));
response.end();
}
});
}
// -----------------------
describe('upload', function () {
let stopServer = null;
before('start server', function (done) {
startServer(port, function (stop) {
stopServer = stop;
done();
});
});
it('upload a file - options is true', function (done) {
rp(options)
.then(function (r) {
console.log(r);
})
.catch(function (error) {
console.log(error);
});
});
after('stop server', function (done) {
stopServer(done);
});
});
I make a request to the uploader and the result of my request is returned in the serveUpload() method. The result of serveUpload() is error and error is object like this :
error =
meta: {
code: '',
sourceType: 'module',
sourceName: '',
version: '2.0.4'
},
data: {
message: {
en: 'uploaded data size is out of limit'
}
}
}
this error must returned .catch(e) in the rp(options), but in fact it must go to .then(r) in rp(options)
log r in .then is undefined.
rp(options)
.then(function (r) {
console.log(r); // error always come here But in fact it must go to catch and r is undefined
})
.catch(function (error) {
console.log(error);
});
I don't understand why this is happening, I would be very grateful if anyone could help me.
In my function "reqHandler" I collect form data and pass it into my http.request. To chain requests, I declared a Promise and .then handler. Problem is that:
1. This is written into console "Unhandled promise rejection (rejection id: 2): TypeError: Cannot read property 'url' of undefined"
2. It seems like .then is not invoked, so no API calls are made.
Code:
"use strict";
const http = require("http");
const qs = require("querystring");
const fs = require("fs");
const PORT = 3000;
let resObject = {};
let hash = "";
const options = {
hostname: "netology.tomilomark.ru",
path: "/api/v1/hash",
method: "post"
};
const reqHandler = (req, res) => {
return new Promise((resolve, reject) => {
if (req.url === "/") {
switch (req.method.toLowerCase()) {
case "get":
// Browse my form with "Name" and "Surname" inputs
fs.readFile("./logs/form.html", (err, file) => {
if (err) {
reject("Promise rejected");
return
}
res.writeHead(200, {'Content-Type': 'text/html','Content-Length':file.length});
res.write(file);
res.end();
});
break;
case "post":
// Collect form data and parse it using querystring
let body = "";
req.setEncoding("utf8");
req.on("data", (data) => {
body += data;
if (body.length > 1e6)
req.connection.destroy();
});
req.on("end", () => {
let post = qs.parse(body);
console.log(post);
options.headers = {
"Content-Type": "application/json",
"firstname": `${post.firstName}`
};
options.body = {
"lastname": `${post.lastName}`
};
// Resolve with "options" object that has headers and body
resolve(options);
});
break;
default:
badRequest(res);
}
} else {
notFound(res);
}
});
};
reqHandler()
.then((options) => {
http.request(options, (res) => {
let resString = "";
res.on("data", (data) => {
resString += data;
});
res.on("end", () => {
console.log(resString);
});
res.end();
});
})
.catch(err => {throw err});
let badRequest = (res) => {
res.statusCode = 400;
res.setHeader('Content-Type', 'text/plain');
res.end('Bad Request');
};
let notFound = (res) => {
res.statusCode = 404;
res.setHeader('Content-Type', 'text/plain');
res.end('Not Found');
};
const server = http.createServer();
server.on("error", (err) => console.error(err));
server.on("request", reqHandler);
server.on("listening", () => console.log(`Start HTTP on port ${PORT}`));
server.listen(PORT);
Ultimately, what´s wrong with my promise and .then? Any help will be appreciated!
Ok I have create a test environment and here you have an abstract version of your source.
Your mistakes was to wrap your promise in a function which pass the req and res parameters and you have to call resolve or reject inside your promise, what have been forgotten on several places.
This source is tested!
const http = require('http');
const reqHandler = (req, res) => {
return new Promise((resolve, reject) => {
if (req.url === "/") {
switch (req.method.toLowerCase()) {
case "get":
console.log('get');
return resolve('get');
case "post":
console.log('post');
return resolve('post');
default:
return resolve('default');
}
} else {
return resolve('some thing else');
}
});
};
const myReqHandler = (req, res) => {
reqHandler(req, res).then(()=> {
console.log('then reached')
});
}
const PORT = 8089;
const server = http.createServer();
server.on("error", (err) => console.error(err));
server.on("request", myReqHandler);
server.on("listening", () => console.log(`Start HTTP on port ${PORT}`));
server.listen(PORT);
I want to test a asynchronous javascript function that runs in node.js and makes a simple request to a http api:
const HOST = 'localhost';
const PORT = 80;
http = require('http');
var options = {
host: HOST,
port: PORT,
path: '/api/getUser/?userCookieId=26cf7a34c0b91335fbb701f35d118c4c32566bce',
method: 'GET'
};
doRequest(options, myCallback);
function doRequest(options, callback) {
var protocol = options.port == 443 ? https : http;
var req = protocol.request(options, function(res) {
var output = '';
res.setEncoding('utf8');
res.on('data', function(chunk) {
console.log(chunk);
output += chunk;
});
res.on('error', function(err) {
throw err;
});
res.on('end', function() {
var dataRes = JSON.parse(output);
if(res.statusCode != 200) {
throw new Error('error: ' + res.statusCode);
} else {
try {
callback(dataRes);
} catch(err) {
throw err;
}
}
});
});
req.on('error', function(err) {
throw err;
});
req.end();
}
function myCallback(dataRes) {
console.log(dataRes);
}
Executed this code works and the response will be displayed as expected.
If I execute this in a mocha test the request is not executed:
describe('api', function() {
it('should load a user', function() {
assert.doesNotThrow(function() {
doRequest(options, myCallback, function(err) {
if (err) throw err;
done();
});
});
assert.equal(res, '{Object ... }');
});
});
The Problem is, that no code after:
var req = protocol.request(options, function(res) {
is executed not even a simple console.log.
Can anybody help?
You have to specify the callback done as the argument to the function which is provided to mocha - in this case the it() function. Like so:
describe('api', function() {
it('should load a user', function(done) { // added "done" as parameter
assert.doesNotThrow(function() {
doRequest(options, function(res) {
assert.equal(res, '{Object ... }'); // will not fail assert.doesNotThrow
done(); // call "done()" the parameter
}, function(err) {
if (err) throw err; // will fail the assert.doesNotThrow
done(); // call "done()" the parameter
});
});
});
});
Also, the signature of doRequest(options, callback) specifies two arguments though when you call it in the test you provide three.
Mocha probably couldn't find the method doRequest(arg1,arg2,arg3).
Did it not provide some error output? Maybe you can change the mocha options to get more information.
EDIT :
andho is right, the second assert would be called in parallel to assert.doesNotThrow while it should only be called in the success callback.
I have fixed the example code.
EDIT 2:
Or, to simplify the error handling (see Dan M.'s comment):
describe('api', function() {
it('should load a user', function(done) { // added "done" as parameter
assert.doesNotThrow(function() {
doRequest(options, function(res) {
assert.equal(res, '{Object ... }'); // will not fail assert.doesNotThrow
done(); // call "done()" the parameter
}, done);
});
});
});
If you have an asynchronous function that does not support callbacks, or if you think using unnecessary callbacks is... unnecessary, then you can also just turn the test into an async test.
instead of:
it('should be able to do something', function () {});
simply do:
it('should be able to do something', async function () {});
^^^^^
Now you can await async functions:
it('should be able to do something', async function () {
this.timeout(40000);
var result = await someComplexFunction();
assert.isBelow(result, 3);
});
I've done a very similar test in my project for an http client. I paste the code here and hope is useful.
Here is the client (my nodejs server use express and I use promise for error handling):
var http = require('http');
var querystring = require('querystring');
module.exports = {
get: function(action, params, res, callback) {
doPromiseRequest(action, querystring.stringify(params), callback, 'GET', 'application/json')
.then((response) => callback(response))
.catch((error) => {
res.status(500);
res.render('error', {layout: false, message: error.message, code: 500});
});
},
}
function doPromiseRequest(action, params, callback, method, contentType) {
var options = {
hostname: 'localhost',
port: 3000,
path: '/api/v1/' + action.toString(),
method: method,
headers: {
'Content-Type': contentType,
'Content-Length': Buffer.byteLength(params)
}
};
return new Promise( (resolve, reject) => {
var req = http.request(options,
function(response) {
response.setEncoding('utf8');
var data = '';
response.on('data', function(chunk) {
data += chunk;
});
response.on('end', function() {
var parsedResponse;
try {
parsedResponse = JSON.parse(data);
} catch(err) {
reject({message: `Invalid response from hurricane for ${action}`});
return;
}
if (parsedResponse.error)
reject(parsedResponse.error);
else
resolve(parsedResponse);
});
response.on('error', function(err){
console.log(err.message);
reject(err);
});
});
req.on('error', function(err) {
console.log(err);
reject({message: err.message});
});
req.write(params);
req.end();
});
}
And here is the test:
var http = require('http');
var expect = require('chai').expect;
var sinon = require('sinon');
var PassThrough = require('stream').PassThrough;
describe('Hurricane Client tests', function() {
before(function() {
this.request = sinon.stub(http, 'request');
});
after(function() {
http.request.restore();
});
it('should convert get result to object', function(done) {
var expected = { hello: 'world' };
var response = new PassThrough();
response.statusCode = 200;
response.headers = {}
response.write(JSON.stringify(expected));
response.end();
var request = new PassThrough();
this.request.callsArgWith(1, response).returns(request);
client.get('any', {}, null, function(result) {
expect(result).to.eql(expected);
done();
});
});
});