I am trying to create a node.js app to automatically update a webpage every few seconds with new data from a mysql database. I have followed the information on this site: http://www.gianlucaguarini.com/blog/push-notification-server-streaming-on-a-mysql-database/
The code on this site does indeed work, but upon further testing it keeps running the "handler" function and therefore executing the readFile function for each row of the database processed.
I am in the process of learning node.js, but cannot understand why the handler function keeps getting called. I would only like it to get called once per connection. Constantly reading the index.html file like this seems very ineffecient.
The reason that I know the handler function keeps getting called is that I placed a console.log("Hello"); statement in the handler function and it keeps outputting that line to the console.
Do you provide the image URLs that the client.html is looking for? Here's what I think is happening:
The client connects to your server via Socket.IO and retrieves the user information (user_name, user_description, and user_img). The client then immediately tries to load an image using the user_img URL. The author's server code however, doesn't appear to support serving these pictures. Instead it just returns the same client.html file for every request. This would be why it appears to be calling handler over and over again - it's trying to load a picture for every user.
I would recommend using the express module in node to serve static files instead of trying to do it by hand. Your code would look something like this:
var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http);
http.use(app.static(__dirname + "/public"));
That essentially says to serve any static files they request from the public folder. In that folder you will put client.html as well as the user photos.
Related
Im trying to perform a simple download of a .docx file info a buffer so I can handle it latter inside my Cloud Function. I've been using the whole Google Platform for multiple projects but never faced the need to download in server side, and now I need to, I just cant.
The following piece of code is not working, it just sends timeout as a response (I don't even get an error If I try to catch it or something):
var bucket = admin.storage().bucket("gs://myBucket.com");
return bucket.file("001Lineales/4x3-1/1000.docx").download().then((contents)=>{
var buffer = contents[0];
//I never get into this point
}).catch((error)=>{
//No error
})
I tried in a local NodeJs script and worked as expected. Also tried to perform a readStream() download but no luck, the function gets hang up in any try of downloading the file.
return new Promise((resolve,reject)=>{
var archivo = bucket.file(selectedCategory).createReadStream();
var array = [];
//Under here, never happens
archivo.on('data', (d) => {array.push(d)}).on("end",()=>{
var newbuff = Buffer.concat(array);
resolve(newbuff)
})
})
The file permissions read/write are public. And the main problem is that debugging is difficult cause Im not able to perform this function in local emulator.
What can I do? Thanks in advance.
EDIT:
Double checking a local call with emulator, I get the following error:
Anonymous caller does not have storage.objects.get access to the Google Cloud Storage object.
Double check the service account hat you've assigned to the Cloud Function and that you've given it the permission it needs.
I think Storage Object Viewer will give you what you need to read a file into the buffer.
By default, if you haven't changed it, the AppEngine's default service account gets used, which I don't think has access to Storage.
I have read near 20 other posts about this particular error, but most seem to be issues with the code calling Response.Close or similar, which is not our case. I understand that this particular error means that typically a user browsed away from the web page or cancelled the request midway, but in our case we are getting this error without cancelling a request. I can observe the error just after a few seconds, the download just fails in the browser (both Chrome and IE, so it's not browser specific).
We have a web api controller that serves a file download.
[HttpGet]
public HttpResponseMessage Download()
{
//
// Enumerates a directory and returns a Read-only FileStream of the download
var stream = dataProvider.GetServerVersionAssemblyStream(configuration.DownloadDirectory, configuration.ServerVersion);
if (stream == null)
{
return new HttpResponseMessage(HttpStatusCode.NotFound);
}
var response = new HttpResponseMessage(HttpStatusCode.OK)
{
Content = new StreamContent(stream)
};
response.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment");
response.Content.Headers.ContentDisposition.FileName = $"{configuration.ServerVersion}.exe";
response.Content.Headers.ContentType = new MediaTypeHeaderValue(MediaTypeNames.Application.Octet);
response.Content.Headers.ContentLength = stream.Length;
return response;
}
Is there something incorrect we are doing in our Download method, or is there something we need to tweak in IIS?
This happens sporadically. I can't observe a pattern, it works sometimes and other times it fails repeatedly.
The file download is about 150MB
The download is initiated from a hyperlink on our web page, there is no special calling code
The download is over HTTPS (HTTP is disabled)
The Web Api is hosted on Azure
It doesn't appear to be timing out, it can happen just after a second or two, so it's not hitting the default 30 second timeout values
I also noticed I can't seem to initiate multiple file downloads from the server at once, which is concerning. This needs to be able to serve 150+ businesses and multiple simultaneous downloads, so I'm concerned there is something we need to tweak in IIS or the Web Api.
I was able to finally fix our problem. For us it turned out to be a combination of two things: 1) we had several memory leaks and CPU intensive code in our Web Api that was impacting concurrent downloads, and 2) we ultimately resolved the issue by changing MinBytesPerSecond (see: https://blogs.msdn.microsoft.com/benjaminperkins/2013/02/01/its-not-iis/) to a lower value, or 0 to disable. We have not had an issue since.
I have a RESTful Web API that is running properly as I can test it with Fiddler. I see calls going through, I see responses coming back.
I am developing a tablet application that needs to use the Web API in order to fetch data or make updates in the repository.
My calls do not return and there is not a single trace in the Fiddler to show that my calls even reach the server.
The first call I need to make is to login. The URI would be this:
http://localhost:53060/api/user
This call would normally return some information about the user (such as group membership, level of authorization and so on). The Web API uses Windows Authentication, so the repository is able to resolve all these fields based on the credentials passed in. As I said, in Fiddler I see the three calls made to the URI as the authentication is negotiated between the caller and the server. The third call returns with a JSON object that contains all information generated from the repository as expected.
Now, moving to my client I have the following:
var webApiClient = new HttpClient(new HttpClientHandler()
{
UseDefaultCredentials = true
})
{
BaseAddress = new Uri("http://localhost:53060/")
};
webApiClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
HttpResponseMessage response = await webApiClient.GetAsync("api/user");
var userLoginInfo = await response.Content.ReadAsAsync<UserLoginInformation>();
My call to "GetAsync" never returns and, like I said, I see no trace of it in Fiddler.
Any idea of what I'm doing wrong?
Changing the URL where the Web API was exposed seemed to have fixed the problem. Thanks to #Nkosi for the suggestion.
For anyone stumbling onto this question and asking themselves how to change the URL of the Web API, there are two ways. If the simulator is running on the same machine with the Web API, the change has to be made in the "applicationhost.config" file for IIS Express. You can locate this file by right-clicking on the IIS Express icon in the Notification Area (the bottom right corner) and selecting show all websites. Highlight the desired Web API and it will show where the application host configuration file is located. In there, one needs to locate the following section:
<bindings>
<binding protocol="http" bindingInformation="*:53060:localhost" />
</bindings>
and replace the "localhost" name with the IP address of the machine where the Web API is running.
However, this approach will not work once you start testing your tablet app with a real device. IIS Express must be coerced into exposing the Web API to the outside world. I found an excellent node.js package that can help with that. It is called IISExpress-proxy.
I've recently started with pushing my locally tested Node,mongo, angularjs sites to live environments hosted on DigitalOcean.
I'm having inconsistency with ajax/http calls. on my Local machine, I am able to do http request and update an angularjs variable and this in return populates the html on the frontend. all works Great! now testing this on my server with same envireontment setup, the only time the variable load new data is when i refresh the page.
For example (not my actualy code):
Nodejs - app.js:
app.get('/getlist', requiredAuthentication, function(req, res) {
list.find({'username':req.session.user.username}, function(err,list) {
res.send(list);
});});
Angularjs - angular_app.js:
$scope.onClick = function (points, evt) {
$http.get('/getlist').then(function(response) {
$rootScope.list = response;});
};
Jade - home:
li(ng-repeat="row in list")
So like I said, this works perfectly on my local machine, but on my server I must refresh my page to load new data, it's as though my variable gets cached on the server.
Any idea would help.
Thanks.!
------- UPDATE - testing v0.1 --------
So after some intensive testing here is what I've found, but still no fix.
If I add new data via an http post, and I go look in my mongo db, I see the new data. Then when I click on the ng-click to retrieve the new data via HTTP, it doesn't return the new data, and is stuck on the old.
If I leave the page open for 10mins, and then click the button, it retrieves the new data, this is such a shlep.
Sounds like cache, but why des it work perfectly on my local?
When looking at the console > network > status. it is code 304, and this means nothing changed?
------- UPDATE - testing v0.2 --------
I've now tested the return data with a log in the console and I did the GET with ajax jQuery, and I'm getting the same issue/behaviour, it's stuck on the same collection of data, so my conclusion must be that node.js is causing the issues.
------- UPDATE - testing v0.3 --------
Okay so I've completely stopped mongo and switched everything to mysql using node-mysql. once again, on my local it works like a machine and on my actual server its laggy with reading new data.
I used Sequal PRO to access mysql and I started adding new entries to a table.
Opening my web url in the brower it Immediately showed the new entries. But after that, adding new entries or deleting entries only showed affect in 10mins or so.
So my conclusion is that Nodejs is caching like a mother, anyone know more bout this? am i really the only one every to experience this?
Try res.json for return data from node
app.get('/getlist', requiredAuthentication, function(req, res)
{
list.find({'username':req.session.user.username}, function(err,list)
{
res.json(list);
});
});
My conclusion to this issue was that port 80 was somehow caching the content of a page and will only load new data with a page refresh.
I upgrade Node and used latest Express. And I'm running my web app on a custom port, all is working now.
I have created a Jar that I want to fill with fireflies, depending on how many users are online.
I did a little digging and I found how to create a XMLSocket. It worked but I didn't know how to get the information how many people are online and also it required a CMD window to run all the time.
The second way I found was trough a PHP,MYSQL witch I have runing with my Apache server, but the tutorials and scripts I found did not work for me, for example. I did not create the required tables.
My question is what is the simplest way to find the current count of users online on your page/flash file? Is there a quick way to do it inside flash and not get involved with MYSQL or PHP?
No, there is not a simple way to only do it in Flash without using any external part (PHP, MySQL, Java, and more...). Remember that Flash is run locally, and thus needs to interact with PHP or similar to interact with the server to tell the server about the activity by the user and to ask the server about other users activities (number of users online).
If you only want to display the users online, I recommend the way that is shown in the example you posted. Simply update the database when activity has been seen by a user and count the user as offline when no activity has been seen for x minutes. There's no need to involve XMLSockets for this unless you want the users to interact with each other in any way.
If you want more than just displaying the users online, I recommend using XMLSockets in ActionScript and looking into PHP Sockets.
i dont think so, the flash player must need a way to "check" on the server the number of users who are online. the simplest would be to send a URLRequest (i hope i got the class name right) to a server script, which could be either a php or an aspx (or any server technology) script / page.
that server script should return the number of users the site has.
e.g.
var numberOfVisitors:Int = 0;
function onLoaded(e:Event):void {
numberOfVisitors = e.target.data;
// now print this 'numberOfVisitors' where you want to on the client
}
var numVisitors:URLLoader = new URLLoader();
numVisitors.addEventListener(Event.COMPLETE, onLoaded);
numVisitors.load(new URLRequest("num_users.php"));
the next part would be a php script (or any other server script) that keeps track of the number of users. that i think you should post as another SO question perhaps?
I got it to work, but I hat to link the php file not trough it's HTTP address, instead just the path relative to the .swf file (just myFile.php or path/myFile.php).
AS3 file:
NewRequest = new URLRequest("numOnline.php");
var numberOfVisitors:int = 10;
var NewRequest:URLRequest;
var UrlLoader:URLLoader;
UrlLoader = new URLLoader();
UrlLoader.dataFormat = URLLoaderDataFormat.TEXT;
UrlLoader.addEventListener(Event.COMPLETE, onLoaded);
UrlLoader.load(NewRequest);
function onLoaded(e:Event):void {
trace(e.target.data);
numberOfVisitors = int(e.target.data);
}
I convert the text As3 receives to int, because i don't know yet how to send veria
php files
main PHP file (the file that as3 connects to):
<?php
include_once 'config.php'; //This file would contain the variables needed to connect to the database with $link, below
include_once 'functions.php'; //We include the functions we have created
$database = "online";
$link = mysql_connect($server, $db_user, $db_pass)or die ("Could not connect to mysql because ".mysql_error());
mysql_select_db($database)or die ("Could not select database because ".mysql_error());
usersOnline(5); //We call the usersOnline function with a time span of 5 minutes
showUsersOnline(1); //Show the number of users online, and the list of users
mysql_close($link);
?>
the function file sends the number of Visiters Online with echo $count;
Yes, you can do it without a database (MYSQL) and PHP; BUT you will still need a (Media) Server.
I wouldn't suggest the following if your "only" purpose is to count the connecting clients, but if you have the reasons and have access to a Flash Media Server, you can try the following:
On Server Side:
Create an application (folder) on FMS, create the main.asc file inside that folder.
Inside the main.asc; create a (remote) SharedObject (server-side) (e.g.: users_so)
Watch for connecting clients on application.onConnect event. Add each connecting client to that SharedObject inside this handler.
Also watch for disconnecting clients on application.onDisconnect event. Remove each disconnecting client from the SharedObject inside this handler.
On Client Side:
Connect each Flash client to FMS (with your new app-folder path in the URI) when the application loads in the browser.
Watch for the NetStatusEvent.NET_STATUS event and "NetConnection.Connect.Success" code. When connected; create a SharedObject (client-side) and get the remote from the server.
Add the SyncEvent.SYNC event listener to the SharedObject. This will sync with each Flash client when a user connects or disconnects from the server.
Inside the sync event handler, get and count the users from the event response.
Display the count on your Flash client.
See Server-Side ActionScript Language Reference for Flash Media Server 4.5, especially the Application Class.
Also useful: Flash Media Server Developer Center
Hope this helps.