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.
Related
I'm new to Web Development (including JavaScript and HTML) and have a few issues within my personal project that seem to have no clear fixes.
Overview
My project is taking input from a user on the website, and feeding it to my back-end to output a list of word completion suggestions.
For example, input => "bass", then the program would suggest "bassist", "bassa", "bassalia", "bassalian", "bassalan", etc. as possible completions for the pattern "bass" (these are words extracted from an English dictionary text file).
The backend - running on Node JS libraries
trie.js file:
/* code for the trie not fully shown */
var Deque = require("collections/deque"); // to be used somewhere
function add_word_to_trie(word) { ... }
function get_words_matching_pattern(pattern, number_to_get = DEFAULT_FETCH) { ... }
// read in words from English dictionary
var file = require('fs');
const DICTIONARY = 'somefile.txt';
function preprocess() {
file.readFileSync(DICTIONARY, 'utf-8')
.split('\n')
.forEach( (item) => {
add_word_to_trie(item.replace(/\r?\n|\r/g, ""));
});
}
preprocess();
module.exports = get_words_matching_trie;
The frontend
An HTML script that renders the visuals for the website, as well as getting input from the user and passing it onto the backend script for getting possible suggestions. It looks something like this:
index.html script:
<!DOCTYPE HTML>
<html>
<!-- code for formatting website and headers not shown -->
<body>
<script src = "./trie.js">
function get_predicted_text() {
const autofill_options = get_words_matching_pattern(input.value);
/* add the first suggestion we get from the autofill options to the user's input
arbitrary, because I couldn't get this to actually work. Actual version of
autofill would be more sophisticated. */
document.querySelector("input").value += autofill_options[0];
}
</script>
<input placeholder="Enter text..." oninput="get_predicted_text()">
<!-- I get a runtime error here saying that get_predicted_text is not defined -->
</body>
</html>
Errors I get
Firstly, I get the obvious error of 'require()' being undefined on the client-side. This, I fix using browserify.
Secondly, there is the issue of 'fs' not existing on the client-side, for being a node.js module. I have tried running the trie.js file using node and treating it with some server-side code:
function respond_to_user_input() {
fs.readFile('./index.html', null, (err, html) => {
if (err) throw err;
http.createServer( (request, response) => {
response.write(html);
response.end();
}).listen(PORT);
});
respond_to_user_input();
}
With this, I'm not exactly sure how to edit document elements, such as changing input.value in index.html, or calling the oninput event listener within the input field. Also, my CSS formatting script is not called if I invoke the HTML file through node trie.js command in terminal.
This leaves me with the question: is it even possible to run index.html directly (through Google Chrome) and have it use node JS modules when it calls the trie.js script? Can the server-side code I described above with the HTTP module, how can I fix the issues of invoking my external CSS script (which my HTML file sends an href to) and accessing document.querySelector("input") to edit my input field?
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.
}
I have a website hosted on server, now what I want is to run a .php script (Also located on the same server) when someone presses the submit button in the website.
Following is the ajax code
$.ajax({url: "/test.php",
success: function(response){
console.log("Success",response);
}
});
My test.php consists of
<?php
//exec('sudo -u www-data python /var/www/html/test.py');
echo "PHP Script Ran";
mkdir("/var/www/html/test", 0700);
?>
When I navigate to ip_address/test.php, the echo message is displayed correctly but the mkdir command doesn't seem to be executed as there is no folder created in my server's directory.
Also I want to know, how can I run this test.php script when someone presses the submit button in my website.
The Javascript code is
var $ = jQuery;
var timestamp = Number(new Date());
var form = document.querySelector("form");
var database = firebase.database();
form.addEventListener("submit", function(event) {
var ary = $(form).serializeArray();
var obj = {};
for (var a = 0; a < ary.length; a++) obj[ary[a].name] = ary[a].value;
console.log("JSON",obj);
firebase.database().ref('users/' + timestamp).set(obj);
database.ref('users/' + timestamp).once('value').then(function(snapshot) {
console.log("Received value",snapshot.val());
$.ajax({
url: "/test.php",
success: function(response){
console.log("Success",response);
}
});
});
});
Any help on this would be much appreciated.
Thanks
In this case it's recommended to use mkdir within try...catch function and capture the error if it's the case.
On the other hand mkidr will return a boolean value: true if the directory creation was successful or false in the case of a failure.
1.version
try {
mkdir("/var/www/html/test", 0700, true);
} catch ($ex Exception) {
echo $ex->getMessage();
}
2.version
if (!mkdir("/var/www/html/test", 0700, true)) {
echo 'Failed to create folder...';
}
If mkdir cannot create the folder two things you need to check: if the folder exist and if it has the right permissions. By this i mean if the user group is set to apache (because apache, through web browser is executing the mkdir command) and second if apache (www-data) has the necessary permissions to execute this command.
Revise your php.ini in the server, the tag disable_functions = "..." and making sure that mkdir not this included in the list.
I can't read the debugging issues in the command prompt. Can I send that to a text file in my PhantomJS or CasperJS scripts?
Here is my python code;
import os
import subprocess
#proxies = {'https': 'http://wmhproxy2:8080'}
APP_ROOT = os.path.dirname(os.path.realpath(__file__))
CASPER = "C:/casperjs/bin/casperjs"
#SCRIPT = os.path.join(APP_ROOT,'unicorn.js')
SCRIPT = os.path.join(APP_ROOT,'unicorn.js')
params = CASPER +' '+ SCRIPT
paper = subprocess.check_output(params,shell=True)
rock = paper.text
salesforce = open('S:/N/salesforce2.txt','w')
salesforce.write(write)
print(subprocess.check_output(params,shell=True))
CasperJS script:
var casper = require('casper').create({
verbose: true,
logLevel: "debug"
});
var x = require('casper').selectXPath;
casper.options.waitTimeout = 7000;
casper.start('http://www.click2houston.com/',function(){
this.echo(this.getTitle());
}).viewport(1200,1000);
casper.run();
Yes, you can append the logs to a file in your CasperJS script.
CasperJS has an internal event management which exposes the log event. A simple object is passed into the event handler which also contains the log message. If you want a different formatting of the logs, then you need to do it yourself or implement a part of the log code in your event handler.
var fs = require("fs");
fs.write("mylogfile.log", "", "w"); // overwrite log file
casper.on("log", function(entry){
fs.write("mylogfile.log", entry.message + "\n", "a");
});
CasperJS is built on top of PhantomJS, so you can directly use PhantomJS' file system module. Of course you can also pass the log file as a commandline option into the script and get it out through casper.cli.
I have this NodeJS script:
var util = require('util'),
process = require('child_process'),
ls = process.exec('test.sh');
ls.stdout.on('data', function (data) {
console.log(data.toString());
ls.stdin.write('Test');
});
and this shell script:
#!/bin/bash
echo "Please input your name:";
read name;
echo "Your name is $name";
I tried to run the NodeJS script and it stucked at "Please input your name:". Does anyone know how to send an input from NodeJS script to the shell script ?
Thanks
You will have to say something like this:
ls.stdin.write('test\n');
OR
you can inherit standard streams if you want input from user using spawn.
like this:
var spawn = require('child_process').spawn;
spawn('sh',['test.sh'], { stdio: 'inherit' });
Did you try adding '\n' to the end of your input (e.g. ls.stdin.write('Test\n');) to simulate pressing return/enter?
Also, you want process.spawn, not process.exec. The latter does not have a streaming interface like you are using, but it instead executes the command and buffers stdout and stderr output (passing it to the callback given to process.exec()).