Strange question, but currently I have a script that I run from the terminal which requires a parameter. Normally I will run this by doing node script.js param, but now I want to run this script with the parameter from inside a JS file when the Express server loads.
The parameter is taken in and defined in the file like this:
var param = process.argv[process.argv.length - 1];
What is the best practice for making this file accessible elsewhere in my Node app and running it?
If I understand you correctly following should work.
script.js
module.exports = function (params) {
console.log(params);
}
main.js
var param = process.argv[process.argv.length - 1];
require('./script')(param);
If you need to get param from another source when the script is required you can make a verification if the script is running directly from command line or it was required:
if (require.main === module) {
var param = process.argv[process.argv.length - 1];
} else {
var param = // get from other source.
}
Related
I am trying to take the value of am input, use AJax to submit these variables into a php function, call PhantomJS from said PHP function WITH these arguments passed from AJax, and return the result back to the HTML page. I am passing the variables to the PHP file perfectly fine, the problem arises from calling PhantomJS with my script followed by the three arguments.
This is the script on my PHP page to call PhantomJS
echo json_encode(array("abc" => shell_exec('/Applications/XAMPP/htdocs/scripts/phantom/bin/phantomjs /Applications/XAMPP/htdocs/scripts/phantom/examples/test.js 2>&1',$website)));
This is the script referenced in the shell script:
var args = require('system').args;
args.forEach(function(arg, i) {
console.log(i+'::'+arg);
});
var page = require('webpage').create();
var address = args[1];
page.open(address, function () {
console.log("Done")
});
As you can see it should be a relatively simple process, except nothing at all is being echo'd. Permissions for each file are more than adequate, and I am sure these files are executing because if I change the shell script to run hello.jsEverything echo's and logs perfectly.
ALSO NOTE This script is executing on my web server, so I am not 100% certain there IS a system variable.
Any ideas?
First issue, shell_exec() takes a single argument (Documentation). However your example is passing the shell argument ($website) as a second argument on shell_exec().
Corrected Example:
$shellReturn = shell_exec("/Applications/XAMPP/htdocs/scripts/phantom/bin/phantomjs /Applications/XAMPP/htdocs/scripts/phantom/examples/test.js " . $website);
echo json_encode(array("abc" => $shellReturn));
For simplicity i excluded the redirect of the error pipe. In addition i would suggest you pass the arguments as JSON wrapped in base64 encoding. This eliminates URL spacing resulting in multiple arguments. Once PhantomJS receives the system args use atob() to bring the JSON back and iterate over the JSON obj rather than the raw string arguments.
I would also point you towards this project: https://github.com/merlinthemagic/MTS, Under the hood is an instance of PhantomJS, the project just wraps the functionality of PhantomJS.
$myUrl = "http://www.example.com"; //replace with content of your $website variable
$windowObj = \MTS\Factories::getDevices()->getLocalHost()->getBrowser('phantomjs')->getNewWindow($myUrl);
//if you want the DOM or maybe screenshot and any point run:
$dom = $windowObj->getDom();
$imageData = $windowObj->screenshot();
How can we execute an external .js file using selenium webdriver file using java selenium. I got some reference "Call external javascript functions from java code", however invoke function is able to accept the function inside that file. I want to just execute the whole file as a whole.
It's as simple as this to run an external JavaScript from your server upon the client:
// Assume Guava, but whatever you use to load files...
String externalJS = Files.toString( new File("external.js"), Charset.forName("utf-8"));
// Execute, assume no arguments, and no value to return
Object ignore = ((JavascriptExecutor) driver).executeScript(externalJS);
The link you provided isn't useful, because it's about executing JavaScript upon the server (within the Java VM) rather than upon the browser/device client.
If rather than executing, you're interested in injecting JavaScript into the page for other scripts etc. to interact with (i.e. rather than a one-off execution), see this question.
Here is the code for nodeJS calling external JS and executing a function within the JS:
var fs = require('fs');
var webdriver = require('selenium-webdriver'),
By = webdriver.By,
until = webdriver.until;
var driver = new webdriver.Builder()
.forBrowser('phantomjs')
.build();
var axeSource = fs.readFileSync('lib/axe.js', 'utf8');
driver
.get('http://www.google.com/ncr')
driver.executeScript(axeSource)
.then(function(){
driver.switchTo().defaultContent();
driver.executeAsyncScript(function() {
var callback = arguments[arguments.length - 1];
window.axe.a11yCheck(document, null, function (results) {
callback(results);
});
}).then(function(str) {
var viola = processResults(str);
console.log(viola);
});
})
driver.quit();
I have PHP script which acts as a DNode client. Then I have Node.js Dnode server which evaluates code which receives from PHP client and it returns DOM as HTML. However, Node.js acts strangely to me (beeing a Node.js newbie). It doesn't return anything, even though the returning string is not empty. My code is below:
PHP client code using DNode-PHP library:
<?php
require(__DIR__.'/../../vendor/autoload.php');
$loop = new React\EventLoop\StreamSelectLoop();
$dnode = new DNode\DNode($loop);
$dnode->connect(7070, function($remote, $connection) {
$js = 'var a = document.createElement("A");';
$js.= 'document.getElementsByTagName("body")[0].appendChild(a);'
$remote->zing($js, function($n) use ($connection) {
print_r($n);
$connection->end();
});
});
$loop->run();
?>
Node.js server code:
var dnode = require('dnode');
var jsdom = require("jsdom");
var server = dnode({
zing: function (n, cb) {
var document = jsdom.jsdom('<!DOCTYPE html>');
var window = jsdom.parentWindow;
eval(n);
var html = jsdom.serializeDocument(document);
// console.log(html);
cb(html);
}
});
server.listen(7070);
Console.log() clearly outputs <!DOCTYPE html><html><head></head><body><a></a></body></html> what is expected result. But it never gets to PHP client. But what is strange, if I change line cb(html); to cb('test');, PHP outputs "test". So the problem must be somewhere on the Node.js side. But I have no idea where to look for.
Thanks in advance for any hints.
How are you viewing the response? Through a web browser? If so, then you're depending on whatever you're evaluating in eval(n) to change the DOM of the document... If nothing changes, then you won't end up seeing anything because you'll have an empty DOM other than the html/head/body tags. It would be worth your time confirming that you're getting an empty response back and it's not just an empty DOM.
That being said, The eval function has any context of you wanting to execute it on the document/window you declare above. As it is, it is just executing in the context of node itself, not on the page you are attempting to create. To fix this, try using:
window.eval(n)
If you take a look at the example Creating a browser-like window object
on the Github page for jsdom, this will give you a better idea of how exactly to use this package.
https://github.com/tmpvar/jsdom
What you have above should look something like this:
var document = jsdom.jsdom("<!DOCUMENT html>");
var window = document.parentWindow;
window.eval(n);
var html = jsdom.serializeDocument(document);
cb(html);
Now you'll be executing the Javascript on the DOM you were previously creating :-)
Your problem is not in Node. When I use the server code you show in your question and try with this client code, I get the expected result:
var dnode = require("dnode");
var d = dnode();
d.on('remote', function (remote) {
var js = 'var a = document.createElement("A");' +
'document.getElementsByTagName("body")[0].appendChild(a);';
remote.zing(js, function (s) {
console.log(s);
});
});
d.connect('localhost', '7070');
I don't do PHP so I don't know what the problem might be on that side.
I need to make a server-side script run when a user from the browser clicks a button...
I've been researching for a while, and can't figure it out.
What we have:
Node.js server (on localhost) running on Fedora Red Hat
NO PHP
Most pages are html + javascript + jQuery
To be more clear, here is what we'd like to happen:
-->User goes to http:// localhost /index.html
-->User selects colors, pushes "submit" button.
-->Selected colors go to the bash script (on the server) ./sendColors [listOfColors]
-->The bash script does it's thing.
================
Things I've tried
child_process.spawn
I WISH I could do this on the html page:
var spawn = require('child_process').spawn;
ls = spawn(commandLine, [listOfColors]);
ls.stdout.on('data', function (data) {
console.log('stdout: ' + data);
});
ls.stderr.on('data', function (data) {
console.log('stderr: ' + data);
});
ls.on('close', function (code) {
console.log('child process exited with code ' + code);
});
but this script is server-side, not client-side, so I can't run it on the html page (I believe). The error I get when I try to run this is that require is undefined.
browserify
I've tried installinst browserify, but the machine we are using isn't connected to the internet, and cannot use npm install. I've manually copied over the files to usr/lib and "required" it fine, but then it said that it couldn't find require "through", which is in browserify's index.js...
getRuntime
tried this thing:
var bash_exit_code = 0; // global to provide exit code from bash shell invocation
function bash(command)
{
var c; // a character of the shell's stdout stream
var retval = ""; // the return value is the stdout of the shell
var rt = Runtime.getRuntime(); // get current runTime object
var shell = rt.exec("bash -c '" + command + "'"); // start the shell
var shellIn = shell.getInputStream(); // this captures the output from the command
while ((c = shellIn.read()) != -1) // loop to capture shell's stdout
{
retval += String.fromCharCode(c); // one character at a time
}
bash_exit_code = shell.waitFor(); // wait for the shell to finish and get the return code
shellIn.close(); // close the shell's output stream
return retval;
}
said it didn't know what Runtime was
RequireJS
I've looked into RequireJS, but didn't understand how to use it in my case
eval
I've tried eval also... but I think that's for algebric expressions... didn't work.
ActiveX
even tried activeX:
variable=new ActiveXObject(...
said it didn't know what ActiveXObject is
================
Currently what I'm trying
HttpServer.js:
var http = require('http');
...
var colors = require('./colorsRequest.js').Request;
...
http.get('http://localhost/colorsRequest', function(req, res){
// run your request.js script
// when index.html makes the ajax call to www.yoursite.com/request, this runs
// you can also require your request.js as a module (above) and call on that:
res.send(colors.getList()); // try res.json() if getList() returns an object or array
console.log("Got response ");// + res.statusCode);
});
colorsRequest.js
var RequestClass = function() {
console.log("HELLO");
};
// now expose with module.exports:
exports.Request = RequestClass;
index.html
...
var colorsList = ...
...
$.get('http://localhost/colorsRequest', function(colors) {
$('#response').html(colorsList); // show the list
});
I'm getting
GET http://localhost/colorsRequest 404 (Not Found)
Anyone got any ideas?
Here's a simple boilerplate for the server (which uses Express, so you might need to install that first: npm install express):
var spawn = require('child_process').spawn;
var express = require('express');
var app = express();
app.use(express.static(__dirname));
app.get('/colorsRequest', function(req, res) {
var command = spawn(__dirname + '/run.sh', [ req.query.color || '' ]);
var output = [];
command.stdout.on('data', function(chunk) {
output.push(chunk);
});
command.on('close', function(code) {
if (code === 0)
res.send(Buffer.concat(output));
else
res.send(500); // when the script fails, generate a Server Error HTTP response
});
});
app.listen(3000);
You can pass it a color, and it will run the shellscript run.sh (of which it assumes is located in the same directory as the server JS file) with the color passed as argument:
curl -i localhost:3000/colorsRequest?color=green
# this runs './run.sh green' on the server
Here's a boilerplate HTML page (save it as index.html, put it in the same directory as the server code and the shell script, start the server, and open http://localhost:3000 in your browser):
<!doctype html>
<html>
<head>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
</head>
<body>
<select>
<optgroup label="Pick a color:">
<option>green</option>
<option>blue</option>
<option>yellow</option>
<option>orange</option>
</optgroup>
</select>
<script>
$('select').on('change', function() {
$.get('/colorsRequest', { color : $(this).val() });
});
</script>
</body>
</html>
You are on the right way with your first approach, the child_process.spawn variant. Ofcourse you can't put this in the HTML page, as it is then executed in the browser, not in the server, but you can easily create a request in the browser (AJAX or page load, depending on what you need), that triggers running this script in the server.
I'm building a .hta (with javascript) from which i want to launch several applications.
But when i execute my .hta i get the error message can't find file
this is the code:
<script type="text/javascript" language="javascript">
function RunFile(path) {
var relpath = window.location.href;
var fullpath = relpath + path;
WshShell = new ActiveXObject("WScript.Shell");
WshShell.Run(fullpath, 1, false);
}
RunFile("\file.exe");
</script>
window.location.href includes filename and protocol too. Try this:
var relpath = window.location.pathname.replace(/\\/g,'/').split('/');
relpath.pop();// JScript: relpath.length = relpath.length - 1;
relpath = relpath.join('/') + '/';
Notice use of / instead \, and it's also handy to end up relpath with /, so you don't need to add it to function argument.
EDIT
I'm not sure what you mean with getting location without file, maybe this (citation from Windows Sripting Technologies (unfortunately broken now):
"The CurrentDirectory returns a string that contains the fully qualified path of
the current working directory of the active process."
The active process is for example the running HTA, so this will give the local path of the HTA file (without filename).
currentDirectory is a property of WScript.Shell, so you can use it with WshShell in your code, also to set working directory.