Loopback: How to stop a console command? - loopbackjs

I am running a loopback command through the command line.
the script is as follows:
const app = require('../../server/server');
let acquireToken = function() {
app.stop();
};
acquireToken();
However this does not seem to work as stop() is not a function. So I have added this in the server.js file:
'use strict';
let loopback = require('loopback');
let boot = require('loopback-boot');
let app = module.exports = loopback();
let winston = require('./winston');
app.start = function() {
// start the web server
return app.listen(function() {
app.emit('started');
let baseUrl = app.get('url').replace(/\/$/, '');
winston.info('Web server listening at: %s', baseUrl);
if (app.get('loopback-component-explorer')) {
let explorerPath = app.get('loopback-component-explorer').mountPath;
winston.info('Browse your REST API at %s%s', baseUrl, explorerPath);
}
});
};
let server;
app.stop = () => {
server.close();
}
// Bootstrap the application, configure models, datasources and middleware.
// Sub-apps like REST API are mounted via boot scripts.
boot(app, __dirname, function(err) {
if (err) throw err;
// start the server if `$ node server.js`
if (require.main === module)
server = app.start();
});
module.exports = app;
But require.main == module is preventing this from working as this gives me the following:
TypeError: Cannot read property 'close' of undefined
What is the recommended way of making this work?

Your question is a bit misleading because you're trying to stop an express object returned from a require call, so a more accurate question is
How do I start and stop a listening loopback app from another script?
In server.js change app.start = function() to app.start = function(cb) and add if (cb) {cb()}; to the end.
'use strict';
let loopback = require('loopback');
let boot = require('loopback-boot');
let app = module.exports = loopback();
let winston = require('./winston');
app.start = function(cb) {
// start the web server
return app.listen(function() {
app.emit('started');
let baseUrl = app.get('url').replace(/\/$/, '');
winston.info('Web server listening at: %s', baseUrl);
if (app.get('loopback-component-explorer')) {
let explorerPath = app.get('loopback-component-explorer').mountPath;
winston.info('Browse your REST API at %s%s', baseUrl, explorerPath);
}
if (cb) cb();
});
};
let server;
app.stop = () => {
server.close();
}
// Bootstrap the application, configure models, datasources and middleware.
// Sub-apps like REST API are mounted via boot scripts.
boot(app, __dirname, function(err) {
if (err) throw err;
// start the server if `$ node server.js`
if (require.main === module)
server = app.start();
});
module.exports = app;
And for your file which starts and stops loopback
// Setup loopback, but don't start the server
const app = require('./server');
// Define our callback function
let acquireToken = function() {
app.server.close();
console.log('closed');
};
// Hold onto the listener object so we can stop it later and start the server with the callback which executes after startup.
app.server = app.start(acquireToken);

Related

when i update to webpack5, there is a error: configuration has an unknown property 'before'

when I update webpack 4 to 5, the error exits.
I have a webpackDevServer.js which include the error message 'error'
// webpackDevServer.js
module.exports = function(proxy, allowedHost) {
return {
before(app, server) {
if (fs.existsSync(paths.proxySetup)) {
// This registers user provided middleware for proxy reasons
require(paths.proxySetup)(app);
}
// This lets us fetch source contents from webpack for the error overlay
app.use(evalSourceMapMiddleware(server));
// This lets us open files from the runtime error overlay.
app.use(errorOverlayMiddleware());
// This service worker file is effectively a 'no-op' that will reset any
// previous service worker registered for the same host:port combination.
// We do this in development to avoid hitting the production cache if
// it used the same host and port.
// https://github.com/facebook/create-react-app/issues/2272#issuecomment-302832432
app.use(noopServiceWorkerMiddleware());
},
};
};
I use the above file in a start.js file, when I run the project, I type node scripts/start.js
// start.js
...
const createDevServerConfig = require('../config/webpackDevServer.config');
...
const serverConfig = createDevServerConfig(
proxyConfig,
urls.lanUrlForConfig
);
const devServer = new WebpackDevServer(compiler, serverConfig);
then it throws an error
configuration has an unknown property 'before'. These properties are valid:
object { bonjour?, client?, compress?, dev?, firewall?, headers?, historyApiFallback?, host?, hot?, http2?, https?, injectClient?, injectHot?, liveReload?, onAfterSetupMiddleware?, onBeforeSetupMiddleware?, onListening?, open?, openPage?, overlay?, port?, proxy?, public?, setupExitSignals?, static?, stdin?, transportMode?, useLocalIp? }
here is my package.json
"webpack": "^5.20.2",
"webpack-dev-server": "^4.0.0-beta.0",
"webpack-manifest-plugin": "2.0.4",
"workbox-webpack-plugin": "^6.1.0"
You have to change before to the onBeforeSetupMiddleware. Link with migration description from v3 to v4. https://github.com/webpack/webpack-dev-server/blob/master/migration-v4.md
In case, something will change on the migration guide, details are attached below
v3:
module.exports = {
devServer: {
after: function (app, server, compiler) {
app.get("/some/path", function (req, res) {
res.json({ custom: "response" });
});
},
},
};
v4:
module.exports = {
devServer: {
onAfterSetupMiddleware: function (devServer) {
devServer.app.get("/some/path", function (req, res) {
res.json({ custom: "response" });
});
},
},
};
fxxk, I'm stupid, when i search some key word (eg: onBeforeSetupMiddleware), I found the github of webpack-dev-server which tell the changes in new version 4.0.0 beta. https://github.com/webpack/webpack-dev-server/releases

How to setup a Sockect.io server in aws EC2 and then connect remotely to the server?

Good morning.
I created a simple server for a chat using Socket.io. In the next screen, which would be the client interface, you can see some inputs
In localhost, in my computer works fine. Here are the logs messages from the server:
I uploaded the server to an EC2 instance with ubuntu. And it work fine, in the same way
Logs from the server in EC2
The main problem is when I tried to connect from my computer to the Socket.io server in EC2. I got this error from my client side file in my computer:
socket.io.js:3888 GET
https://mydomain:80/socket.io/?EIO=4&transport=polling&t=NQB59WG
Here is my server code:
const path = require("path");
const express = require("express");
const socketio = require("socket.io");
const app = express();
app.set('port', 3000);
//static files
app.use(express.static(path.join(__dirname, "public")));
//start the server
const server = app.listen(app.get('port'), () => {
console.log("server on port", app.get('port'));
});
const io = socketio(server);
//websockects
io.on('connection', (socket) => {
console.log("new connection " + socket.id);
socket.on('chat:message', (data) => {
console.log(data);
io.sockets.emit("chat:server", data);
});
socket.on('chat:typing', (data) => {
console.log(data);
socket.broadcast.emit("chat:typing", data);
});
});
Here is my client code:
const socket = io("https://domain:80");
//dom elements
let message = document.getElementById("message");
let username = document.getElementById("username");
let btn = document.getElementById("button");
let output = document.getElementById("output");
let actions = document.getElementById("actions");
btn.addEventListener('click', function() {
console.log({
username: username.value,
message: message.value
});
socket.emit("chat:message", {
username: username.value,
message: message.value
});
});
message.addEventListener('keypress', function() {
socket.emit("chat:typing", username.value);
});
socket.on("chat:server", function(data) {
console.log(data);
actions.innerHTML = "";
output.innerHTML += "<p><strong>" + data.username + "</strong>: " + data.message + " </p>";
});
socket.on("chat:typing", function(data) {
console.log(data);
actions.innerHTML = "<p><strong>" + data + "</strong> esta escribiendo </p>";
});
And here are the instance inboud rules for ports:
When i tried to connect from my computer to the EC2 instance, I tried with several ways to connect, like this:
const socket = io("https://url.org:80");
const socket = io("https://url.org");
const socket = io("https://ipaddres:80");
const socket = io("https://ipaddres");
const socket = io("ec2-xxxx.compute-1.amazonaws.com");
const socket = io("ec2-xxxx.compute-1.amazonaws.com:80");
Nothing works, Any help?
In my case the solution was to do two things:
I use my domaind without port
const socket = io("https://url.org");
The EC2 Instance work with nginx, I modified the header to add this property:
Access-Control-Allow-Origin: *
And it worked

host.json not respected by Visual Studio or web job

I have a queue processing application which is workign fine. I am now trying to persuade the queue trigger to only process one item at a time. My host.json is set up correctly, I think:
But when I run the app (either in Azure as a web job, or locally in Visual Studio), I see this:
I suspect that I am missing something really obvious, so wondering whether anyone has come across this before. I have found a few articles, but nothing that gives me any insight into what I am doing wrong.
Adding the contents of program.cs. I have tried adding "host.json" after the AddAzureAppConfiguration entry, but that makes no difference.
class Program
{
static async Task Main()
{
//var builder = new HostBuilder();
var builder = Host.CreateDefaultBuilder();
builder.ConfigureLogging((context, a) =>
{
a.AddConsole();
});
builder.ConfigureAppConfiguration((hostContext, config) =>
{
config.AddUserSecrets(
"5aa19112-5ff7-467b-b062-f37c3654872d"); // This is automatic for a web app, but not for a console app
var settings = config.Build();
var connectionString = settings.GetConnectionString("AzureAppConfiguration");
config.AddAzureAppConfiguration(connectionString);
});
builder.ConfigureWebJobs(b =>
{
b.AddAzureStorageCoreServices();
b.AddAzureStorage();
});
builder.ConfigureServices((hostContext, services) =>
{
services.AddMemoryCache();
});
var host = builder.Build();
using (host)
{
await host.RunAsync();
}
}
}
I think you are using the Azure WebJobs SDK v3.x. In v3.x, hosts.json does not work for WebJob.
Instead, version 3.x uses the standard ASP.NET Core APIs, so you need to configure it using the ConfigureWebJobs method:
static async Task Main()
{
var builder = new HostBuilder();
builder.ConfigureWebJobs(b =>
{
b.AddAzureStorageCoreServices();
b.AddAzureStorage(a => {
a.BatchSize = 8;
a.NewBatchThreshold = 4;
a.MaxDequeueCount = 4;
a.MaxPollingInterval = TimeSpan.FromSeconds(15);
});
});
var host = builder.Build();
using (host)
{
await host.RunAsync();
}
}
Docs: https://learn.microsoft.com/pt-pt/azure/app-service/webjobs-sdk-how-to#queue-storage-trigger-configuration

NodeJS / iOS - How to get a returned value from a binary after calling it with HTTP POST

I have an iOS app (Objective C) and this app call some C++ binaries using NodeJs.
So far, I have been able to execute remotely my C++ program from a clicked button on my app using HTTP POST with the library AFNetworking 3.
iOS App --> Button clicked --> HTTP POST --> Node JS call --> C++ program call (this latter return true or false)
Now, I would like to get the value (True or False) returned by my program. How can I do that ?
I have already used the GET method to get a file on my server but I don't know if it's appropriate to use it for this case i.e get the returned result of my program.
Do you have an idea how can I achieve this ?
Thank
To be able to retrieve the value returned by your C++ program, you need first to retrieve the returned result from NodeJS.
Assuming you are using ExpressJS as your HTTP server, you should implement your endpoint with something like:
var execFile = require('child_process').execFile;
var express = require('express');
var app = express();
app.post('/endpoint', function (req, res) {
const child = execFile('my_exe', (error, stdout, stderr) => {
if (error) {
res.status(500).send('False')
} else {
if (stdout === 'True') {
res.status(200).send('True')
} else {
res.status(500).send('False')
}
}
});
});
app.listen(3000, function () {
console.log('Example app listening on port 3000!');
});
If the call succeeded, the server will respond True with the status 200 and if it fails, it will return Falsewith a status False.
Now, in your call to the server from the iOS application, you can use Alamofire like:
NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
AFURLSessionManager *manager = [[AFURLSessionManager alloc] initWithSessionConfiguration:configuration];
NSURLRequest *request = [[AFHTTPRequestSerializer serializer] requestWithMethod:#"POST" URLString:#"someURL" parameters:#{} error:nil];
NSURLSessionDataTask *dataTask = [manager dataTaskWithRequest:request completionHandler:^(NSURLResponse *response, id responseObject, NSError *error) {
if (error) {
/* Network error*/
NSLog(#"Error: %#", error);
} else {
NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;
switch (httpResponse.statusCode) {
case 200:
NSLog(#"Success")
/* Code in case of success == Server returned True */
default:
/* Code in case of no success == Server returned False */
NSLog(#"Error");
}
}
}];
[dataTask resume];

Upload an image to Drupal 7 / Services 3 from Titanium?

This must be close but I can't figure out what's causing the error.
In my Titanium app, I have a Webview with a canvas element and this code:
function getImageData() {
return canvas.toDataURL('image/png');
}
I am moving that data to the Titanium app like this:
var imageBase64data = webview.evalJS('getImageData()')
The data looks good starting with "data:image/png;base64,"...
Then in Titanium, I have a logged-in drupal session and call this function:
function uploadImage(imageBase64data, callback) {
var url = REST_PATH + "file.json";
var file = {
filename: utils.createRandomString() + ".png",
file: imageBase64data
// uid: Titanium.App.Properties.getString("userUid"),
// filesize: ""+Titanium.Utils.base64decode(imageBase64data).length,
};
var xhr = Titanium.Network.createHTTPClient({timeout: 30000});
xhr.setRequestHeader("Content-Type", "application/json; charset=utf-8");
var authString = Titanium.App.Properties.getString("userSessionName")+'='+Titanium.App.Properties.getString("userSessionId");
xhr.setRequestHeader("Cookie", authString);
xhr.onload = function() {
if(xhr.status == 200) {
var response = xhr.responseText;
callback(response);
}
};
xhr.onerror = function(e) {
alert("There was an error: " + e.error);
Ti.API.info(JSON.stringify(this));
};
xhr.open("POST", url);
xhr.send(file);
}
xhr.onerror is being called with e.error = "undefined"
The trace looks like this:
{
"responseData":{},
"readyState":4,
"connected":true,"UNSENT":0,"DONE":4,"HEADERS_RECEIVED":2,"OPENED":1,"LOADING":3,
"responseText":null,"status":406
}
I think authentication is working because I was previously getting a "need authentication" error until I added the Cookie header.
That was with the installation provided by Drupanium. I just did a fresh Drupal and fresh Services 3 install and my file is uploading nicely.