FS readFileSync causing problems in windows service - javascript

I have a small express script that was making an api. I then used node services to make it a service and set it up to run after mongoDb kicked off. Worked like a charm however I had to add HTTPS support which requires me to read the keys using fs.readFileSync. Now the process just ends after starting. If I run the file it works fine so I think it has to do with the window service trying to access a users file. Has anyone run into this before? Below is both the code for the file creating the API and the code used to make the service.
https
.createServer(
{
key: fs.readFileSync("certs/server.com.key"),
cert: fs.readFileSync("certs/server.com.crt"),
passphrase: "redacted",
},
app
)
.listen(port, function () {
console.log(
`Example app listening on port ${port}! Go to https://localhost:${port}/api`
);
});
var Service = require("node-windows").Service;
var svc = new Service({
name: "FavoritesAPI1.1",
description:
"This starts the express server for the favorites API and connects to MongoDB.",
script: "C:\\Users\\srv-qlik\\Desktop\\FavoritesAPI\\index.js",
nodeOptions: ["--harmony", "--max_old_space_size=4096"],
});
svc.on("install", function () {
svc.start();
});
svc.install();

Changed the fs file paths to the full paths and it seem to be working.

Related

How to call function from Nodejs running as windows service

I have created windows service from nodeJs application using node-windows package. Below is my code.
Main.js
var Service = require('node-windows').Service;
// Create a new service object
var svc = new Service({
name:'SNMPCollector',
description: 'SNMP collector',
script: './app.js',
nodeOptions: [
'--harmony',
'--max_old_space_size=4096'
]
//, workingDirectory: '...'
});
// Listen for the "install" event, which indicates the
// process is available as a service.
svc.on('install',function(){
svc.start();
});
svc.install();
/* svc.uninstall(); */
App.js
const { workerData, parentPort, isMainThread, Worker } = require('worker_threads')
var NodesList = ["xxxxxxx", "xxxxxxx"]
module.exports.run = function (Nodes) {
if (isMainThread) {
while (Nodes.length > 0) {
// my logic
})
}
}
}
Now when I run main.js, it creates a windows service and I can see the service running in services.msc
But, how can I call this run() method which is inside the running service, from any outside application? I couldn't find any solution for this, any help would be great.
You might consider simply importing your run function where you need it and run it there, then there is no need for a windows service or main.js - this assumes that "any outside application" is a Node application.
In your other application you you do the folowing:
const app = require('<path to App.js>');
app.run(someNodes)
For broader usage or if you do need to run it as a service, you could be starting an express (or another webserver) in your App.js with an endpoint that invokes your run function. Then from anywhere else you'll need to make an http call to that endpoint.
App.js
const express = require('express')
const bodyParser = require('body-parser')
const { workerData, parentPort, isMainThread, Worker } = require('worker_threads')
const app = express()
const port = 3000
var NodesList = ["xxxxxxx", "xxxxxxx"]
const run = function (Nodes) {
if (isMainThread) {
while (Nodes.length > 0) {
// my logic
})
}
}
}
app.use(bodyParser.json())
app.post('/', (req, res) => res.send(run(req.body)))
app.listen(port, () => console.log(`Example app listening at http://localhost:${port}`))
(Based off of example for express - https://expressjs.com/en/starter/hello-world.html)
You'll need to install both express and body-parser: $ npm install --save express body-parser from the directory of App.js.
From your other applications you will need to call the endpoint http://localhost:3000 with a POST request and the Nodes as a JSON array.
You can expose it on a port like the other answer mentions, though you'll want to make sure you don't expose it more broadly depending on the environment you're running in. There's a good answer here on ensuring the port is locked down.
As an alternative to exposing it on a port you can simply call the function by running the command in any other application:
node -e 'require("/somePathToYourJS/app").run()'
One concern is that app.js will now run at whatever permissions the calling application has. Although that can be resolved by running runas prior. More details here. But an example is:
runas /user:domainname\username "node -e 'require(^"/somePathToYourJS/app^").run()'"

Error: 7 PERMISSION_DENIED: Your application has authenticated using end user credentials from the Google Cloud SDK

This was working a couple months ago without code changes inside of my websocket server, however using it today it seems that the Google speech to text api no longer allows authentication using access tokens.
This was my previously working method until I hit this error today
const client = new speech.SpeechClient({
access_token: ACCESS_TOKEN,
projectId: 'project-name'
});
That nets me the above error in the title.
I also tried switching to a service account (which I used in the past) by setting up the environment as follows
export GOOGLE_APPLICATION_CREDENTIALS="path-to-key.json"
I then run the client without the above code and instead run:
const client = new speech.SpeechClient();
and that nets me this beautiful error instead, even though the environment is set at this point with the project Id
Error: Unable to detect a Project Id in the current environment.
Any help in resolving this would be much appreciated!
I resolved the environment problem and subsequent error by doing the following:
const options = {
keyFilename: 'path-to-key.json',
projectId: 'project-name',
};
const client = new speech.SpeechClient(options);
I was able to follow the Official Quickstart and got it working by using Client Libraries with no issues. I will explain what I did right below.
From Cloud Speech-to-Text - Quickstart:
Create or select a project:
gcloud config set project YOUR_PROJECT_NAME
Enable the Cloud Speech-to-Text API for the current project:
gcloud services enable speech.googleapis.com
Create a service account:
gcloud iam service-accounts create [SA-NAME] \
--description "[SA-DESCRIPTION]" \
--display-name "[SA-DISPLAY-NAME]"
Download a private key as JSON:
gcloud iam service-accounts keys create ~/key.json \
--iam-account [SA-NAME]#[PROJECT-ID].iam.gserviceaccount.com
Set the environment variable GOOGLE_APPLICATION_CREDENTIALS to the file path of the JSON file that contains your service account key:
export GOOGLE_APPLICATION_CREDENTIALS="[PATH]"
Install the Client Library
npm install --save #google-cloud/speech
Created a quickstart.js file and put the following code sample inside:
'use strict';
// [START speech_quickstart]
async function main() {
// Imports the Google Cloud client library
const speech = require('#google-cloud/speech');
const fs = require('fs');
// Creates a client
const client = new speech.SpeechClient();
// The name of the audio file to transcribe
const fileName = './resources/audio.raw';
// Reads a local audio file and converts it to base64
const file = fs.readFileSync(fileName);
const audioBytes = file.toString('base64');
// The audio file's encoding, sample rate in hertz, and BCP-47 language code
const audio = {
content: audioBytes,
};
const config = {
encoding: 'LINEAR16',
sampleRateHertz: 16000,
languageCode: 'en-US',
};
const request = {
audio: audio,
config: config,
};
// Detects speech in the audio file
const [response] = await client.recognize(request);
const transcription = response.results
.map(result => result.alternatives[0].transcript)
.join('\n');
console.log("Transcription: ${transcription}");
}
main().catch(console.error);
WHERE const fileName = './resources/audio.raw' is the path where your test.raw audio is located.

How to test nodejs modules that transitively require itself

Assume the following scenario :
Rest client is a module, which has many middlewares; which are themselves modules.
Now, we're trying to create a new middleware that requires client itself to fetch/update metadata for the client input url.
Testing this middleware, will bring in a published version of the client from npm registry, because middleware has a devDependency on the client. But we want to serve our local client.
Also, the published version of client does not contain this new middleware, so it will not allow testing the request pipeline with this middleware.
We want to initiate the client with this middleware, when we're testing the middleware itself to send a request to fetch data.
The middleware is smart enough to not request metadata for metadata, so it will skip the second call. The new flow should be like the diagram below :
Wrap the nodejs module loader, to return local client instead of published one when client is requested during test execution.
describe(()=>{
const localClient = require('../client');
const m = require('module');
const orig = m._load;
before(()=>{
m._load = function(name){
if(name==='client'){
return localClient;
}
return orig.appy(this, arguments)
}
});
after(()=>{
m._load = orig;
});
it('test goes here',()=>{...})
})

Getting html and js weather api request to work in node. It works before I upload to Node

It works fine outside of node. I cant get it to work in node.js. Please help as this is my last resort. Ill need to see i suppose the correct layout of app.js
ITs something simple i knwo. No answers out there currently. I hope stack can
help.
Thanks. Mike
html file:
Weather
Get Weather Conditions From Anywhere!
Enter a location:
Get Current Humidity!
JS FILE:
$(document).ready(function() {
$('#weatherLocation').click(function() {
let city = $('#location').val();
$('#location').val("");
$.ajax({
url: `http://api.openweathermap.org/data/2.5/weather?q=${city}&appid=b7a0ab9fa0acf51a850b7a621c63d38f`,
type: 'GET',
data: {
format: 'json'
},
success: function(response) {
$('.showHumidity').text(`The humidity in ${city} is ${response.main.humidity}%`);
$('.showTemp').text(`The temperature in Kelvins is ${response.main.temp}.`);
},
error: function() {
$('#errors').text("There was an error processing your request. Please try again.");
}
});
});
});
APP.JS FILE
// app.js
var express = require('express');
var app = express();
var request = require('request');
app.use(express.static("app")); // Allow access to content of views folder (Showing how we get app to recognise folders)
// Allow access to content of views folder (Showing how we get app to recognise folders)
// Allow access to content of views folder (Showing how we get app to recognise folders)
app.use(express.static("js"));
app.use(express.static("views")); // Allow access to content of views folder (Showing how we get app to recognise folders)
app.use(express.static("images")); // Allow access to images folder (Showing how we get app to recognise folders)
// Allow access to content of views folder (Showing how we get app to recognise folders)
// Allow access to scripts folder {No need for this)
app.use(express.static("css")); // Allow access to css folder (Showing how we get app to recognise folders)
// Allow access to js folder (Showing how we get app to recognise
var server = app.listen(3000, function () {
var host = server.address().address;
var port = server.address().port;
console.log('Your app listening at https://%s:%s', host, port);
});
Node.js doesn't support HTML, or any kind of DOM*. Use console.log calls to output to stdout instead.
*by default.

Dashing-JS "Hello World" Demo

I am attempting to work with Dashing-JS, a port of a Sinatra based framework project in Ruby, Dashing.IO, to Javascript/Node. Essentially I have the core packages and dependencies for Dashing-JS configured; however, when attempting to run just the sample, I am unable to display anything other than this 404 error rather than a sample dashboard:
NodeJS CLI output is as follows:
The project is not well maintained; however, I am curious if an expert in Node might be able to shed some light on the situation. Is a path reference incorrect?
Notes:
1. server.js is referencing sample.jade.
var dashing = require('new-dashing-js').Dashing();
// Set your auth token here
//dashing.auth_token = 'YOUR_AUTH_TOKEN';
/*
dashing.protected = function(req, res, next) {
// Put any authentication code you want in here.
// This method is run before accessing any resource.
// if (true) next();
}
*/
// Set your default dashboard here
dashing.default_dashboard = 'sample';
dashing.start();
"Sample.jade" is located within the "dashboards" directory

Categories