0

I'm quite a beginner and I've been looking for an answer for days now.. I am building a webapp using nodejs.

Here is the app.js I node to start (my server-side)

http = require("http"),
path = require("path"),
url = require("url"),
fs = require("fs");


function sendError(errCode, errString, response)
{
  response.writeHead(errCode, {"Content-Type": "text/plain"});
  response.write(errString + "\n");
  response.end();
  return;
}

function sendFile(err, file, response)
{
  if(err) return sendError(500, err, response);
  response.writeHead(200);
  response.write(file, "binary");
  response.end();
}

function getFile(exists, response, localpath)
{
  if(!exists) return sendError(404, '404 Not Found', response);
  fs.readFile(localpath, "binary",
   function(err, file){ sendFile(err, file, response);});
}

function getFilename(request, response)
{
  var urlpath = url.parse(request.url).pathname; // following domain or IP and port
  var localpath = path.join(process.cwd(), urlpath); // if we are at root
  fs.exists(localpath, function(result) { getFile(result, response, localpath)});
}

var server = http.createServer(getFilename);
server.listen(1000);
console.log("Server available..."); 

I can therefore access my app using localhost:1000/index.html

My index.html (client-side) is a html page containing buttons i want to use to start a python script.

<!DOCTYPE html>
<html lang="fr">
  <head>
    <meta charset="utf-8">
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
    <title>Lights</title>
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css" integrity="sha384-9aIt2nRpC12Uk9gS9baDl411NQApFmC26EwAOH8WgZl5MYYxFfc+NcPb1dKGj7Sk" crossorigin="anonymous">

  </head>
  <body class="text-white bg-dark">
  
    <center>
    <input type="submit" value="OFF" name="OFF" onclick="turnOff()">
    <input type="submit" value="ON" name="ON" onclick="turnOn()">
    </center>
    
    <div id="texttest"> </div>
    <div id="fil"> </div>
    
    <script src="funcs.js"></script>
    
  </body>
</html>

from there you can see i use a script to run the "onclick()" this script is calling a python run.. But obviously I can't do that 'cause I am trying to run python client side.. ERROR "require not definded"

my funcs.js

const { exec } = require('child_process');

function turnOff() {
    console.log("enter Off");
    exec('python3 turnOff.py', (err, stdout, stderr) => {
        if (err) {
            document.getElementById("fil").innerHTML = "error..."+err;
        } else {
            document.getElementById("fil").innerHTML = "running python...";
        }
    });
    document.getElementById("texttest").innerHTML = "trying off sucess  :<br>      " ;
}   
        
function turnOn() {     
    console.log("enter On");
    exec('python3 turnOn.py', (err, stdout, stderr) => {
        if (err) {
            document.getElementById("fil").innerHTML = "error..."+err;
        } else {
            document.getElementById("fil").innerHTML = "running python...";
        }
    });
    document.getElementById("texttest").innerHTML = "trying on sucess  :<br>      " ;
}

I should be using AJAX request, but i can't seem to find how to run python on server side using it.. because the ajax request is sent from html inside nodejs..

What can I do ?

Thanks for your help

Ratcen
  • 49
  • 1
  • 6

1 Answers1

1

You're right about your errors

require is defined on server side only. funcs.js is executed on client side, so you can't use require.

And you'll need to make an AJAX call in order to reach your goal.

// server.js

const { exec } = require('child_process');

const http = require('http');

const server = http.createServer((req, res) => {
  /* When a request will call the http://localhost:5000/run url
   it will execute this code block */
  if (req.url === '/run') {
    exec('python ...', () => {
      // ...

      res.write('Python script executed');
      res.end();
    });
  }
});

server.listen(5000);
// funcs.js

function turnOff() {
    console.log("enter Off");

    // Turn off will send a request on the http://localhost:5000/run endpoint
    fetch("/run", {
      method: "POST"
    })
    .then(() => {
       document.getElementById("fil").innerHTML = "running python...";
    })
    .catch(() => {
       document.getElementById("fil").innerHTML = "error..."+err;
    })
}   
jean-smaug
  • 346
  • 2
  • 11
  • Thanks for your help. I don't quite understand how i will execute server.js and how to make the ajax request to call the right file to execute... – Ratcen Jan 06 '21 at 12:10
  • 1
    In you **app.js** you can create a second server with the code I posted. You can run two Node.js servers in one file. The second option is to put my code in your `getFilename` function – jean-smaug Jan 06 '21 at 12:13
  • the thing is when i send an ajax request to /run it is sent to port 1000 and therefore returns 404 not found.. – Ratcen Jan 06 '21 at 12:31
  • I managed to get it to work with the code inside the geFilename function, this way there is still only one server running on port 1000 and the ajax request is sent to /run. If the url called is /run, then exec is run. Thanks for your help ! – Ratcen Jan 06 '21 at 13:16
  • 1
    You created another server ? So you need to specify the URL explicitly ```js fetch("http://localhost:5000/run", { method: "POST" }) ``` And also on the server running on port 5000 you'll need to add ```js res.setHeader('Access-Control-Allow-Origin', 'http://localhost:8888'); ``` https://stackoverflow.com/questions/18310394/no-access-control-allow-origin-node-apache-port-issue – jean-smaug Jan 06 '21 at 13:18