PhantomJS - onLoadFinished called twice without reason - javascript

Here is my code:
var system = require('system');
var page = require('webpage').create();
var server = require('webserver').create();
var system = require('system');
var someUrl = "http://sportfun.bg";
var port = 3000;
//Screen resolution
page.viewportSize = {
width: 1920,
height: 1080
};
//User agent
page.settings.userAgent = 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2062.120 Safari/537.36';
page.onConsoleMessage = function(msg) {
system.stderr.writeLine('Console: ' + msg);
};
var service = server.listen(port, function (request, response) {
//console.log('Request received at ' + new Date());
//console.log("Request" + JSON.stringify(request.post));
var POST = request.post;
//console.log("Bank:" + POST.bank);
// TODO: parse `request` and determine where to go
var step = 0;
page.open(someUrl, function (status) {
if (status !== 'success') {
console.log('Unable to post!');
} else {
console.log("Here0");
page.onLoadFinished = function(status) {
if(status === "success"){
console.log("Here 1");
response.statusCode = 200;
response.headers = {
'Cache': 'no-cache',
'Content-Type': 'text/plain;charset=utf-8'
};
// TODO: do something on the page and generate `result`
response.write("We good");
//console.log(page.content);
response.close();
}
};
}
});
});
console.log("Server started!");
I'm using PhantomJS 2.1.1.
When i launch the server and send a post request to it in the console i see strange thing:
Server started!
Here0
Here 1
Here 1
Why i see twice Here 1 when actually the page should be once loaded ?
Is there any reason about it and how can i fix it ?

Multiple callbacks of onLoadFinished happen if there are multiple widgets embedded via iframe — like Facebook widgets or Google Maps. You can get rid of them by blacklisting calls to those sites:
block_urls = ['gstatic.com', 'google-analytics.com', 'tawk.to', 'perdeta.net', 'facebook.net', 'facebook.com'];
page.onResourceRequested = function(requestData, request){
for(url in block_urls) {
if(requestData.url.indexOf(block_urls[url]) !== -1) {
request.abort();
console.log(requestData.url + " aborted");
return;
}
}
}
If you implement this solution you will notice that "Here 1" is not printed anymore. That is because the first onLoadFinished is actually fired even before page.open but you create it only after page.open is called.
If you want to make real use of page.onLoadFinished you should decalre it even before page.open.

Related

Querying the API via JavaScript / CORS (teamup.com calendar)

I am currently trying to figure out how to query the API of a calendar on teamup.com and retrieve data (events in the calendar) from it.
There's a code example on their website: Querying the API via JavaScript / CORS
I tried to make it work in Visual Studio, so I had to install XMLHttpRequest via npm and add a require code line:
var XMLHttpRequest = require("xmlhttprequest").XMLHttpRequest;
// Creates a CORS request in a cross-browser manner
function createCORSRequest(method, url) {
var apiKey = 'API_KEY'; //placeholder for api key
var xhr = new XMLHttpRequest();
if ("withCredentials" in xhr) {
// XHR for Chrome/Firefox/Opera/Safari/IE10+.
xhr.open(method, url, true);
xhr.setRequestHeader('Teamup-Token', apiKey);
} else if (typeof XDomainRequest != "undefined") {
// XDomainRequest for IE8/IE9.
xhr = new XDomainRequest();
// XDomainRequest does not support querying HTTPS from HTTP pages
if (window.location.protocol === 'http:') {
url = url.replace('https://', 'http://');
}
if (-1 === ['GET', 'POST'].indexOf(method)) {
alert('XDomainRequest only supports GET and POST methods');
return;
}
if (-1 === url.indexOf('?')) {
url += '?_teamup_token=' + apiKey;
} else {
url += '&_teamup_token=' + apiKey;
}
xhr.open(method, url);
} else {
// CORS not supported.
xhr = null;
}
return xhr;
}
// Sends the actual CORS request.
function makeCorsRequest(url, successCallback, errorCallback) {
var xhr = createCORSRequest('GET', url);
if (!xhr) {
alert('CORS not supported');
return;
}
// Response handlers.
xhr.onload = function (xhr) {
if (xhr.target.status < 400) {
if (successCallback) successCallback(xhr.target);
} else if (errorCallback) {
errorCallback(xhr.target);
}
};
xhr.onerror = function (xhr) {
if (errorCallback) {
errorCallback(xhr.target);
}
};
xhr.send();
}
// Send a GET request for all events in a date range
makeCorsRequest(
'https://api.teamup.com/ks73ad7816e7a61b3a/events?startDate=2015-06-01&endDate=2015-06-05',
function(xhr) {
var data = JSON.parse(xhr.responseText);
alert('Successfully Received: ' + JSON.stringify(data));
},
function(xhr) {
var data = JSON.parse(xhr.responseText);
alert('Request failed with code '+ xhr.status +': ' + JSON.stringify(data));
}
);
When I try to run the program per node I get this terminal output:
PS C:\Users\...\Documents\GitHub\teamup-test> node team-up-test.js
C:\Users\...\Documents\GitHub\teamup-test\team-up-test.js:45
if (xhr.target.status < 400) {
^
TypeError: Cannot read properties of undefined (reading 'target')
at exports.XMLHttpRequest.xhr.onload (C:\Users\...\Documents\GitHub\teamup-test\team-up-test.js:45:17)
at exports.XMLHttpRequest.dispatchEvent (C:\Users\...\Documents\GitHub\teamup-test\node_modules\xmlhttprequest\lib\XMLHttpRequest.js:591:25)
at setState (C:\Users\...\Documents\GitHub\teamup-test\node_modules\xmlhttprequest\lib\XMLHttpRequest.js:614:14)
at IncomingMessage.<anonymous> (C:\Users\...\Documents\GitHub\teamup-test\node_modules\xmlhttprequest\lib\XMLHttpRequest.js:447:13)
at IncomingMessage.emit (node:events:539:35)
at endReadableNT (node:internal/streams/readable:1345:12)
at processTicksAndRejections (node:internal/process/task_queues:83:21)
So it seems like the program cannot read xhr.target.status, but why?
Summarized: I want to fetch calendar event data from my calendar on team-up per JS and display that data on a discord bot.
I am wondering if I even do need CORS since it's only for browsers. Hoping someone could guide me into the right direction please.
The code tutorial here: https://apidocs.teamup.com/#querying-the-api-via-javascript--cors is to be executed in the browser, in the client. I don't think it can be used in the server. Remember, Node.js is a back-end language, it runs on the server, not on the browser.
You can make an API call in Node.js with the code below, but you should study Axios later
const https = require('https');
const options = {
hostname: 'api.teamup.com',
path: '/ks73ad7816e7a61b3a/events?startDate=2015-06-01&endDate=2015-06-05',
headers: {
"Teamup-Token" : "API_KEY"
},
};
https.get(options, (resp) => {
let data = '';
resp.on('data', (receivedDataBuffer) => {
data += receivedDataBuffer;
});
resp.on('end', () => {
let receivedDataAsJSON = JSON.parse(data);
//do what you need with the json
});
}).on("error", (err) => {
console.log("Error: " + err.message);
});

How to initiate websocket Server correctly?

I've set up a websocket server via php on a local MAMP PRO environment using Ratchet.
$server = IoServer::factory(
new Control(),
81,
'0.0.0.0'
);
Starting the server with root privileges (because I'm unable to get him up with other than root privileges (permission denied) )
php server.php
Establish a connection
telnet 192.168.2.106 81
Trying 192.168.2.106...
Connected to mmm.mrmedia.private.
Answers correctly
php server.php
New connection! (37)
But if I'm trying to connect to the server via JavaScript it's not going through the Handshake (ERR_CONNECTION_REFUSED after a couple of time).
New connection! (48)
Connection 48 sending message "GET / HTTP/1.1
Host: 192.168.2.106:81
Connection: Upgrade
Pragma: no-cache
Cache-Control: no-cache
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36
Upgrade: websocket
Origin: http://192.168.2.106
Sec-WebSocket-Version: 13
Accept-Encoding: gzip, deflate
Accept-Language: de,de-DE;q=0.9,en;q=0.8,en-US;q=0.7,es;q=0.6,fr;q=0.5,it;q=0.4
Sec-WebSocket-Key: RH25+2UD8PQI+0A+VQWn4Q==
Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits
The console outputs the following informations:
TIC TCP Conn Start [24126:0x7fdcc6f47c20]
TIC TCP Conn Event [24126:0x7fdcc6f47c20]: 3
TIC TCP Conn Failed [24126:0x7fdcc6f47c20]: 12:8 Err(-65554)
TIC TCP Conn Cancel [24126:0x7fdcc6f47c20]
Source server.php
use Ratchet\Server\IoServer;
use FluvalEdge\Control;
require dirname(__DIR__) . '/websocket-php-ratchet/vendor/autoload.php';
$server = IoServer::factory(
new Control(),
81,
'0.0.0.0'
);
$server->run();
Source Namespacing FluvalEdge
namespace FluvalEdge;
use Ratchet\MessageComponentInterface;
use Ratchet\ConnectionInterface;
class Control implements MessageComponentInterface {
protected $clients;
public function __construct() {
$this->clients = new \SplObjectStorage;
}
public function onOpen(ConnectionInterface $conn) {
// Store the new connection to send messages to later
$this->clients->attach($conn);
echo "New connection! ({$conn->resourceId})\n";
}
public function onMessage(ConnectionInterface $from, $msg) {
$numRecv = count($this->clients) - 1;
echo sprintf('Connection %d sending message "%s" to %d other connection%s' . "\n"
, $from->resourceId, $msg, $numRecv, $numRecv == 1 ? '' : 's');
foreach ($this->clients as $client) {
if ($from !== $client) {
// The sender is not the receiver, send to each client connected
$client->send($msg);
}
}
}
public function onClose(ConnectionInterface $conn) {
// The connection is closed, remove it, as we can no longer send it messages
$this->clients->detach($conn);
echo "Connection {$conn->resourceId} has disconnected\n";
}
public function onError(ConnectionInterface $conn, \Exception $e) {
echo "An error has occurred: {$e->getMessage()}\n";
$conn->close();
}
}
Calling the Client-Connection via
initWebsocket('ws://192.168.2.106:81', false, 5000, 5);
Source websocket.js
/**
* inits a websocket by a given url, returned promise resolves with initialized websocket, rejects after failure/timeout.
*
* #param url the websocket url to init
* #param existingWebsocket if passed and this passed websocket is already open, this existingWebsocket is resolved, no additional websocket is opened
* #param timeoutMs the timeout in milliseconds for opening the websocket
* #param numberOfRetries the number of times initializing the socket should be retried, if not specified or 0, no retries are made
* and a failure/timeout causes rejection of the returned promise
* #return {Promise}
*/
function initWebsocket(url, existingWebsocket, timeoutMs, numberOfRetries) {
timeoutMs = timeoutMs ? timeoutMs : 1500;
numberOfRetries = numberOfRetries ? numberOfRetries : 0;
var hasReturned = false;
var promise = new Promise((resolve, reject) => {
setTimeout(function () {
if(!hasReturned) {
console.info('opening websocket timed out: ' + url);
rejectInternal();
}
}, timeoutMs);
if (!existingWebsocket || existingWebsocket.readyState != existingWebsocket.OPEN) {
if (existingWebsocket) {
existingWebsocket.close();
}
var websocket = new WebSocket(url);
websocket.onopen = function () {
if(hasReturned) {
websocket.close();
} else {
console.info('websocket to opened! url: ' + url);
resolve(websocket);
}
};
websocket.onclose = function () {
console.info('websocket closed! url: ' + url);
rejectInternal();
};
websocket.onerror = function () {
console.info('websocket error! url: ' + url);
rejectInternal();
};
} else {
resolve(existingWebsocket);
}
function rejectInternal() {
if(numberOfRetries <= 0) {
reject();
} else if(!hasReturned) {
hasReturned = true;
console.info('retrying connection to websocket! url: ' + url + ', remaining retries: ' + (numberOfRetries-1));
initWebsocket(url, null, timeoutMs, numberOfRetries-1).then(resolve, reject);
}
}
});
promise.then(function () {hasReturned = true;}, function () {hasReturned = true;});
return promise;
};
/*
var ws_host_fluval = "fluvaledge.local";
var ws_port_fluval = "81";
var ws_server_fluval = "";
var ws_url_fluval = "ws://" + ws_host_fluval + ":" + ws_port_fluval + "/" + ws_server_fluval;
try
{
var socket_fluval = new WebSocket(ws_url_fluval);
// Handlerfunktionen definieren
socket_fluval.onopen = function()
{
// Willkommensnachricht an den Server senden
socket_fluval.send("Client hat Verbindung mit fluvaledge hergestellt");
};
socket_fluval.onmessage = function(msg)
{
console.log("Websocket: " + msg.data);
};
socket_fluval.onclose = function(msg)
{
console.log("Verbindung wurde getrennt");
};
}
catch(ex)
{
alert("Exception: " + ex);
}
*/
I think you are confusing plain sockets with WebSockets. Looking at the documentation it looks like you should not use IoServer but WsServer. The first seems to implement plain sockets while the second implements the WebSockets protocol which you are trying to access from Javascript.

How To Reuse Token From FireBase

I am implementing Firebase Web Notification using Firebase.
The whole process is:
There are two files: a) generate-token.js b) firebase-messaging.sw.js
Permission to get access token( By calling requestPermission).
After clicking Allow, token is generated.
An Ajax call is made to backend service to save the token correspond to that browser.
We have separate module for Notification-sender and Notification-Manager to schedule and send notification.
firebase-messaging.sw.js is at root. It is called when notification is called.
There are 2 main methods for this:
initMessaging.setBackgroundMessageHandler(function (payload) {
)}; ( For background handling of message)
and
messaging.onMessage(function(payload) {}); : This method is in generate-token.js for receiving foreground message.
When notification is received, an ajax call is made to api to track notification with actionId=1 and for clicking notification actionId=3.
My questions:
In step 1, once I make an ajax call to save the token, I have to reuse that token in my methods of firebase-messaging.sw.js to hit track api (Track api require token and deviceId)
Currently, I am making device_id using userAgent, which may clash with some other machine. Is there a better way?
How can I reuse my token, as service-worker dont have access to local storage, DOM, cookies,etc.?
My code:
generate-token.js:
firebase.initializeApp(config);
const messaging=firebase.messaging();
var postURL=null;
var gcmId=null;
var id=getUniqueId();
var id1=id.split('.').join("");
if ('serviceWorker' in navigator) {
// Register service worker
navigator.serviceWorker.register('/firebase-messaging-sw.js').then(function (reg) {
console.log("SW registration succeeded. Scope is " + reg.scope);
console.log("Updating service worker" +reg.update());
}).catch(function (err) {
console.error("SW registration failed with error " + err);
});
}
messaging.onMessage(function(payload) {
console.log("OnMessage called app is in foreground");
//tracking notification with actionid=1;
trackNotification(payload.data,1,postURL,gcmId);
});
function requestPermission(url) {
console.log('Requesting permission...');
postURL=url;
var firebaseRefUrl=firebase.database().ref().child(location.host.split('.').join("")+"/" + "url");
firebaseRefUrl.set(url);
messaging.requestPermission()
.then(function () {
console.log('Notification permission granted.');
return messaging.getToken();
})
.then(function(token){
userAction(token,url);
var firebaseRefToken=firebase.database().ref().child(location.host.split('.').join("") + "/" + id1);
firebaseRefToken.set(token);
gcmId=token;
})
.catch(function (err) {
console.log('Unable to get permission for notification.', err);
});
}
function getUniqueId(){
var Sys = {};
var ua = navigator.userAgent.toLowerCase();
return ua;
}
function userAction(token,url) {
try{
console.log("Calling wrapper interface to save gcm_id");
var obj = new Object();
obj.deviceId =getUniqueId();
obj.token=token;
var jsonString= JSON.stringify(obj);
var xhttp = new XMLHttpRequest();
xhttp.open("POST", url+ "/registerGCM", true);
xhttp.setRequestHeader("Content-type", "application/json");
xhttp.send(jsonString);
xhttp.onreadystatechange = function() {
if(xhttp.readyState == XMLHttpRequest.DONE && xhttp.status == 200) {
var jsonDeviceId=JSON.parse(xhttp.responseText);
localStorage.setItem("deviceId",jsonDeviceId.deviceId);
}
}
}catch(error) {
console.log('Error while calling apis.', error);
}}
firebase-messaging.sw.js:
firebase.initializeApp(config);
var click=null;
var url;
var token;
var obj=new Object();
//Initialise firebase messaging
const initMessaging = firebase.messaging();
var id=getUniqueId();
var id1=id.split('.').join("");
var firebaseRefToken=firebase.database().ref().child(location.host.split('.').join("") + "/" + id1);
firebaseRefToken.on('value',function(data){
token=data.val();
});
var firebaseRefUrl=firebase.database().ref().child(location.host.split('.').join("") +"/" + "url");
firebaseRefUrl.on('value',function(data){
url=data.val();
});
//Background push notification handler. It fires up when the browser or web page in which push notification is activated are closed.
initMessaging.setBackgroundMessageHandler(function (payload) {
//console.log("In background");
console.log("Tracking notification when the app is in background");
var gcmId;
var tokenRefCheck=firebase.database().ref().child(location.host.split('.').join("") + "/" + id1);
tokenRefCheck.on('value',function(data){
gcmId=data.val();
});
trackNotification(obj.data,1,url,null);
});
//Displays incoming push notification
self.addEventListener('push', function (event) {
console.log('Push Notification Received.');
var eventData = event.data.text();
obj = JSON.parse(eventData); //Parse the received JSON object.
//printing payload
console.log("PAyload is " + JSON.stringify(obj,2,null));
const title = obj.data.title;
click=obj.data.targetActionData;
const options = {
body: obj.data.body,
icon: obj.data.icon,
click_action:obj.data.targetActionData
};
event.preventDefault();
event.waitUntil(self.registration.showNotification(title, options));
});
//Take action when a user clicks on the received notification.
self.addEventListener('notificationclick', function (event) {
console.log("Notification clicked");
event.notification.close();
event.preventDefault(); // prevent the browser from focusing the Notification's tab
trackNotification(obj.data,3,url,null);
event.waitUntil(
clients.openWindow(click)
);
});
self.addEventListener('notificationclose', function (event) {
console.log("Notification closed");
event.notification.close();
event.preventDefault(); // prevent the browser from focusing the Notification's tab
trackNotification(obj.data,2,url,null);
});
function trackNotification(data,actionId,url,gcmId) {
try{
var obj=new Object();
console.log("Calling track notification api to save the data");
if(actionId===1){
console.log("Tracking for receving notification");
}
if(actionId===2){
console.log("Tracking for closing notification");
}
if(actionId===3){
console.log("Tracking for clicking notification");
}
obj.deviceId =getUniqueId();
obj.campaignId=data.campaignId;
obj.actionTime=new Date();
if(gcmId!=null)
obj.token=gcmId;
else
obj.token=token;
obj.actionId=actionId;
obj.scheduleId=data.scheduleId;
var jsonString= JSON.stringify(obj,2,null);
/*xhttp.open("POST", postURL+ "/trackNotification", true);
xhttp.setRequestHeader("Content-type", "application/json");
xhttp.send(jsonString);*/
console.log("Payload" + jsonString);
fetch(url + "/trackNotification", {
method: 'post',
headers: {
"Content-type": "application/json; charset=UTF-8"
},
body: jsonString
})
.then(function (data) {
})
.catch(function (error) {
console.log('Request failed', error);
});
}catch(error) {
console.log('Error while calling apis.', error);
}}
function getUniqueId(){
var Sys = {};
var ua = navigator.userAgent.toLowerCase();
return ua;
}
I am using Firebase Database, and save the token with useragent as a key, but it will sure collide with some other device.
You can save the data in the service worker cache.
The Service Worker API comes with a Cache interface, that lets you
create stores of responses keyed by request. While this interface was
intended for service workers it is actually exposed on the window, and
can be accessed from anywhere in your scripts. The entry point is
caches.
https://developers.google.com/web/ilt/pwa/caching-files-with-service-worker

Phantomjs interprocess communication

I am trying to implement a solution where by using PhantomJS a web location is open evaluated and the output is saved to a file for processing. Specifically the scanning for malicious scripts. I have been able to implement the solution using PhantomJS running once. For example this works perfectly...
var system = require('system');
var page = require('webpage').create();
var lastReceived = new Date().getTime();
var requestCount = 0;
var responseCount = 0;
var requestIds = [];
var fileSystem = require('fs');
var startTime = new Date().getTime();
page.onResourceReceived = function (response) {
if(requestIds.indexOf(response.id) !== -1) {
lastReceived = new Date().getTime();
responseCount++;
requestIds[requestIds.indexOf(response.id)] = null;
}
};
page.onResourceRequested = function (request) {
if(requestIds.indexOf(request.id) === -1) {
requestIds.push(request.id);
requestCount++;
}
};
page.open('http://adserver.example.com/adserve/;ID=164857;size=300x250;setID=162909;type=iframe', function () {});
var checkComplete = function () {
// We don't allow it to take longer than 5 seconds but
// don't return until all requests are finished
if((new Date().getTime() - lastReceived > 300 && requestCount === responseCount) || new Date().getTime() - startTime > 5000) {
clearInterval(checkCompleteInterval);
console.log(page.content);
phantom.exit();
}
}
var checkCompleteInterval = setInterval(checkComplete, 1);
However, I have had immense difficulty trying to create and automated system that doesn't require PhantomJS to continually be restarted which has a fair bit of overhead.
I tried using a named pipe to read from and then attempt to open the passed url, but for some reason it will not open properly. I would love and deeply appreciate any guidance on this.
One thing to mention is that PhantomJS excels in HTTP communications. That's why for advanced features & better performance, I always use resource pooling pattern + webserver module. This module is still tagged EXPERIMENTAL, but I have always found it quite stable until now.
So, I think the best in your case it's better to communicate via HTTP than via files IO.
Here is a very basic example :
var page = require('webpage').create();
var server = require('webserver').create();
var system = require('system');
var host, port;
if (system.args.length !== 2) {
console.log('Usage: server.js <some port>');
phantom.exit(1);
} else {
port = system.args[1];
var listening = server.listen(port, function (request, response) {
var page=require('webpage').create();
page.open(request.post.target, function(status){
response.write("Hello "+page.title);
response.close();
});
});
if (!listening) {
console.log("could not create web server listening on port " + port);
phantom.exit();
}
//test only
var url = "http://localhost:" + port + "/";
console.log("SENDING REQUEST TO:");
console.log(url);
var data='target=http://stackoverflow.com/';
page.open(url,'post', data, function (status) {
if (status !== 'success') {
console.log('FAIL to load the address');
} else {
console.log("GOT REPLY FROM SERVER:");
console.log(page.content);
}
phantom.exit();
});
}

Routing http requests through Node.js

I'm trying to make a cucumber test setup with Node.js that can test any website by using an iframe.
Normally the iframe is a no go because of cross script security limitations.
However if it was possible (I'm sure it is. And i trust you to come up with a solution)
to fetch the website being target for the test via the requested url when a specific url name is being requested, so that the iframe would be loaded with a copy of the test target.
Basically just a standard node.js server that fetches specific pages based on the req.url
Akin to an Address Request Router.
Here is my blatant attempt to do exactly that.
Fetching the test page via. the url works.
But i'm having a problem switching from the http server to the connection object.
Is there a way to "feed" the connection with the http server response?
PS. i also created a solution with two node.js servers.
Node 1 fetched the test target and mixing it with cucumber test page.
Node 2 hosting the cucumber test.
This solution is working. But it creates problems on websites where javascript naming conflicts occur. Which is why the iframe solution, that solves this problem by encapsulation is more appealing.
var http = require('http');
var connect = require('connect');
var port = process.env.PORT || 8788;
var server = http.createServer(function(req, webres)
{
var url = req.url;
console.log(url);
if(url == '/myWebsiteToBeTestedWithCucumberJS')
{
// Load the web site to be tested "myWebsiteToBeTestedWithCucumberJS"
// And update the references
// Finaly write the page with the webres
// The page will appear to be hosted locally
console.log('Loading myWebsiteToBeTestedWithCucumberJS');
webres.writeHead(200, {'content-type': 'text/html, level=1'});
var options =
{
host: 'www.myWebsiteToBeTestedWithCucumberJS.com,
port: 80,
path: '/'
};
var page = '';
var req = http.get(options, function(res)
{
console.log("Got response: " + res.statusCode);
res.on('data', function(chunk)
{
page = page + chunk;
});
res.on('end', function()
{
// Change relative paths to absolute (actual web location where images, javascript and stylesheets is placed)
page = page.replace(/ href="\/\//g , ' href="/');
page = page.replace(/ src="\//g , ' src="www.myWebsiteToBeTestedWithCucumberJS.com');
page = page.replace(/ data-src="\//g , ' data-src="www.myWebsiteToBeTestedWithCucumberJS.com');
page = page.replace(/ href="\//g , ' href="www.myWebsiteToBeTestedWithCucumberJS.com');
webres.write(page);
webres.end('');
});
});
}
else
{
// Load any file from localhost:8788
// This is where the cucumber.js project files are hosted
var dirserver = connect.createServer();
var browserify = require('browserify');
var cukeBundle = browserify({
mount: '/cucumber.js',
require: ['cucumber-html', './lib/cucumber', 'gherkin/lib/gherkin/lexer/en'],
ignore: ['./cucumber/cli', 'connect']
});
dirserver.use(connect.static(__dirname));
dirserver.use(cukeBundle);
dirserver.listen(port);
}
}).on('error', function(e)
{
console.log("Got error: " + e.message);
});
server.listen(port);
console.log('Accepting connections on port ' + port + '...');
Well it wasn't so difficult after all.
Being new to node.js i had to realize the possibilties of using multiple listeners.
Reading on nodejitsu's features helped me solve the problem.
Below example loads www.myWebsiteToBeTestedWithCucumberJS.com
when specifying the url as follows: http://localhost:9788/myWebsiteToBeTestedWithCucumberJS
where all other requests is handled as cucumber.js website requests.
Hope this make sense to other node.js newcucumbers.
var http = require('http');
var connect = require('connect');
var port = process.env.PORT || 9788;
var server = http.createServer(function(req, webres)
{
var url = req.url;
console.log(url);
if(url == '/myWebsiteToBeTestedWithCucumberJS')
{
loadMyWebsiteToBeTestedWithCucumberJS(req, webres);
}
else
{
loadLocal(req, webres, url);
}
}).on('error', function(e)
{
console.log("Got error: " + e.message);
});
server.listen(port);
console.log('Accepting connections on port ' + port + '...');
function loadMyWebsiteToBeTestedWithCucumberJS(req, webres)
{
console.log('Loading myWebsiteToBeTestedWithCucumberJS');
webres.writeHead(200, {'content-type': 'text/html, level=1'});
var options =
{
host: 'www.myWebsiteToBeTestedWithCucumberJS.com',
port: 80,
path: '/'
};
var page = '';
var req = http.get(options, function(res)
{
console.log("Got response: " + res.statusCode);
res.on('data', function(chunk)
{
page = page + chunk;
});
res.on('end', function()
{
page = page.replace(/ href="\/\//g , ' href="/');
page = page.replace(/ src="\//g , ' src="http://www.myWebsiteToBeTestedWithCucumberJS.com/');
page = page.replace(/ data-src="\//g , ' data-src="http://www.myWebsiteToBeTestedWithCucumberJS.com/');
page = page.replace(/ href="\//g , ' href="http://www.myWebsiteToBeTestedWithCucumberJS.com/');
webres.write(page);
webres.end('');
});
});
}
function loadLocal(req, webres, path)
{
console.log('Loading localhost');
webres.writeHead(200, {'content-type': 'text/html, level=1'});
var options =
{
host: 'localhost',
port: 9787,
path: path
};
var page = '';
var req = http.get(options, function(res)
{
console.log("Got response: " + res.statusCode);
res.on('data', function(chunk)
{
page = page + chunk;
});
res.on('end', function()
{
webres.write(page);
webres.end('');
});
});
}
// Cucumber site listening on port 9787
var dirserver = connect.createServer();
var browserify = require('browserify');
var cukeBundle = browserify(
{
mount: '/cucumber.js',
require: ['cucumber-html', './lib/cucumber', 'gherkin/lib/gherkin/lexer/en'],
ignore: ['./cucumber/cli', 'connect']
});
dirserver.use(connect.static(__dirname));
dirserver.use(cukeBundle);
dirserver.listen(9787);
var http = require('http');
// Create a server object
http.createServer(function (req, res) {
// http header
res.writeHead(200, {'Content-Type': 'text/html'});
var url = req.url;
if(url ==='/about') {
res.write(' Welcome to about us page');
res.end();
}
else if(url ==='/contact') {
res.write(' Welcome to contact us page');
res.end();
}
else {
res.write('Hello World!');
res.end();
}
}).listen(3000, function() {
// The server object listens on port 3000
console.log("server start at port 3000");
});

Categories