I'm planning on converting a small PHP codebase (less than 1000 lines) to Node.js. It's a web app that contains about 50k lines of JS, so I figured I'd move it to Node.js. (Plus, PHP sucks donkey balls.) There's a few static files (CSS, HTML, etc.) that I'll be serving with the node-static package. My issue is with my PHP files that are not static.
For example, I have a search page that runs on a GET variable. I tack on ?keyword=blah onto the end of the URL and the PHP script searches the DB and outputs HTML for the browser. How do I replicate this behavior in Node.js? (In other words, how can I create a server to listen at localhost/search.html and accept GET variables in the URL?)
I know I can change the way searches are done to accomplish this, but I'd really like to figure out how to replicate this behavior since I have several scripts that act the same way.
EDIT: As for the database, I'm actually using OrientDB. But I don't connect directly to it, I use a set of Java services that I post JSON requests to. So really, all I need to be able to do is post a JSON request (synchronously) and output HTML.
Here's how I do it:
Create a new ExpressJS app
"express myapp"
Install all the dependencies
"cd myapp && npm install".
In app.js, make sure you require the "url" package before "var app"
var url = require('url');
Add a new route to "app.js" so that it looks for any GET requests to "search.html"
app.get('/search.html', function(req, res) {
// Process the request for the GET variables
var url_parts = url.parse(req.url, true);
var query = url_parts.query; // These are all your GET variables
var search_keyword = query.keyword;
if(search_keyword) {
// The keyword indeed exists
console.log(search_keyword);
}
res.end();
});
If you run the app and go to "search.html?keyword=haha", your console will output "haha". You can do anything after that with the keyword.
Related
I have Wamp setup on my windows 8.1 machine which I am using for development. My problem is Apache wont serve me pages from the specific web app I am working on in a reasonable time while I am running the script that is doing the polling. Here is the script and its back end implementation
window.fetch_messages = function () // I call this when my page is loaded
{
var last_message = $("div.message:last").attr('data-ai_id');
var project_id = getParameterByName('project-id'); // Another one of my helpers
$.ajax({
url:'project_messages',
type:'POST',
data:{ project_id:project_id, latest_message:last_message },
timeout:50000,
success:new_messages,
error:function(data){ console.log(data); setTimeout(fetch_messages(),50000); }
});
};
And the backend
do
{
$messages = $this->mentor_model->query_messages($this->project_id,$this->viewer, $this->last_message_id);
if($messages)
break;
usleep(25000);
}
while(empty($messages));
echo json_encode($messages);
exit;
This all works but I cant work properly if apache is not responding to my other request to go to another page or something in a reasonable time. I have other web apps on the machine and they will work fine while polling but the web app itself wont respond to other requests in reasonable time and this only happends when I'm on the page that uses this script. As a note I also made sure mysql was not giving the issues here by visiting another wapp(coining) on the localhost that uses mysql and it responds fine.
What's apache's deal ? is there some setting or something I have to change. It should be able to handle this fine since its just me testing.
This is more than less a resource handle problem. The all round use of sessions were being blocked because the script in question was not allowing session data use while it was running (because it was using the data).
A simple session_write_close() placed in the loop just before calling usleep()/sleep() on the script solved my problem.
Placing it anywhere after you have done using the session data should solve yours.
Can someone please tell me if socket.io is only useful if the page your clients will use is a HTML page.
I want to create a node server that can push events to my existing PHP pages.
The pages are different and not suffixed with html.
All the examples I read use Chatroom examples with Index.html etc.
I simply want to know if what I want to do is even feasible.
Many thanks in advance.
When you write a php page the output is html. I hope that answers your question
PHP and socket.io work together. The only difference between doing it with html and with PHP is the way you link the two together (the common tutorial shows a way that only works with html, but there is another way that works with both html and php).
Try something like this (from a similar answer of mine, https://stackoverflow.com/a/25189436/3842050):
var socket = require('socket.io');
var express = require('express');
var http = require('http');
var app = express();
var server = http.createServer(app);
var io = socket.listen(server);
Then remove the app.use and app.get as they are no longer needed for how this is going to be done. Then add server.listen(8000); at the end of the server.js. For dependencies, use: <script src="//cdn.socket.io/socket.io-1.0.0.js"></script>. Then, to run your server, go to it in terminal and type node server.js. Then just connect to it with your client. Also, for events, in the server, use:
io.on('connection', function (client) {
client.on('someEvent', function(someVariables){
//Do something with someVariables when the client emits 'someEvent'
io.emit('anEventToClients', someData);
});
client.on('anotherEvent', function(someMoreVariables){
//Do more things with someMoreVariables when the client emits 'anotherEvent'
io.emit('anotherEventToClients', someMoreData);
});
});
And in your client code:
socket.emit('someEvent', variables);
socket.on('anEventToClients', function(something){
//Code when anEventToClient is emitted from the server
});
To begin, this question deals primarily with HTTP requests, BackboneJS, some sort of RESTful API (such as Slim API), and how these things work with each other. Additionally, this question is coming from someone who doesn't have much experience on the server-side, other than just handling basic PHP/MySQL stuff.
I've been looking at Backbone, and I've seen some tutorials regarding the use of RESTful APIs on the back-end (including this one from 9bit).
I also read this answer to a StackOverflow question (Understand BackboneJS REST Calls).
If I open up a JS file, and type type in some code to send a POST request such as this:
(function() {
var http = new XMLHttpRequest();
var value = '{ "prop1": "value 1", "prop2": "value 2" }';
http.open('POST', 'dir', true);
http.setRequestHeader('Content-Type', 'application/json; charset=utf-8');
http.setRequestHeader('Content-Length', value.length);
http.onreadystatechange = function () {
if (http.readyState == 4 && http.status == 200) {
alert(http.responseText);
}
}
http.send(value);
})();
I see in the console that it sent a POST request looking something like this:
Method: POST
Body: { "prop1": "value 1", "prop2": "value 2" }
Location: http://localhost/~myusername/Todo/dir/
And then, since it's just my local server, the server sends back a response with the basic HTML page that shows the files in that directory, etc.
I tried using a GET request to retrieve a similar JSON object as well, but obviously I couldn't get anything from that location, presumably because the object I was trying to request from some empty folder doesn't even exist anywhere.
My question is, when you use a BackboneJS method such as .save(), from what I understand, it might use, in that instance, a PUT method to send a request with a body of an object, perhaps parsed as a string, to a directory, such as 'article/id', with 'id' possibly being something like '43' (potentially the corresponding id of whatever model's properties you sent). So...
1) What does an API, such as Slim do with that request?
2) Where is it saving those object properties to (a MySQL database)?
3) Is there a file, such as 'index.php', sitting in the directory 'article', in which a script grabs the parameters in the body of the POST requests and uses though to communicate with the MySQL database? (I'm wondering why the location is simply a 'folder', such as '/article'. To put it in another context, whenever you type in a website like 'http://www.mywebsite.com', the server will automatically look for an 'index' page in that directory, such as 'index.html', and automatically open that file as the default file of that directory. Is that same type of thing happening in the context of using a location '/somefoldername' as the location of the HTTP request)?
Basically, it just looks strange to me that you would send an HTTP request to just some folder, and not a specific PHP file (for example) that would handle the request and communicate with a database. Using BackboneJS with a RESTful API, would our theoretical folder '/article' even exist, or is that just appended to the URL for some reason?
Thank you very much.
Since you asked your questions in the context of Slim, I'm going to answer them that way, although much of the information will generally apply to other web applications/frameworks.
What does an API, such as Slim do with that request?
Not to be to cheeky, but it does whatever you (or the API developer) wants it to do (more on that shortly).
Where is it saving those object properties to (a MySQL database)?
In general, those object properties are being used to create a resource (POST) or to updated a resource (PUT), and most likely the resource is being persisted in some sort of storage, be it an RDMS or a NoSQL solution.
Is there a file, such as 'index.php', sitting in the directory 'article', in which a script grabs the parameters in the body of the POST requests and uses though to communicate with the MySQL database?
Here's where things get interesting, IMHO. Considering the route article/id, here's what happens in a Slim application:
A request is received at example.com/article/22
The request is routed to a front controller script which, based on the request URI and HTTP method, makes a decision about what to do with the request.
If a PUT route for article exists, then the application code perhaps would take the request body and update the resource identified by the provided id.
With that in mind, in a Slim application, likely the only web accessible file is index.php. What appear to be directories are merely routes defined in the application's index.php that Slim used to make decisions about how to handle requests. With that in mind . . .
Using BackboneJS with a RESTful API, would our theoretical folder '/article' even exist, or is that just appended to the URL for some reason?
In the context of a Slim application, no, /article wouldn't exist as a directory, but rather a route.
Perhaps this won't help much, but this is what a portion of that index.php routing file might look like on the Slim side:
$app->post('/article', function () {
// Get data from post
// Create resource
});
$app->get('/article/:id', function ($id) {
// Return an article resource identified by $id
});
$app->put('/article/:id', function ($id) {
// Use $id to retrieve resource from storage
// Update resource with request data
});
I've been working on a project for a couple of Minecraft servers that use Bukkit. I'm trying to create a web page that contains a dynamic map of the servers' worlds, as well as a real-time event update system, where a <div> is updated as events happen on the server. To give a brief outline of how my system works, the Minecraft servers communicate events with a Node.js webserver over the same network via UDP packets, and the Node.js webserver uses these packets to build JavaScript objects containing the event info. The objects are then stored, and passed to Jade whenever the page is requested. Jade takes care of the templating.
What I want to do is update this page dynamically, so that the user doesn't have to refresh the entire page to update the list of events. What I'm trying to implement is something like the Facebook ticker, which updates every time a Facebook friend does something like posting a status, commenting on a post, or 'liking' a post.
In reading this question on SO, I've concluded that I need to use long polling in a PHP script, but I'm not sure of how to integrate PHP with a webserver written almost entirely in Node.js. How could I go about doing this?
EDIT:
I've run into a problem in the clientside code.
This is the script block:
script(src='/scripts/jadeTemplate.js')
script(src='/socket.io/socket.io.js')
script(type='text/javascript')
var socket = io.connect();
socket.on('obj', function(obj) {
var newsItem = document.createElement("item");
jade.render(newsItem, 'objTemplate', { object: obj });
$('#newsfeed').prepend(newsItem);
console.log(obj);
alert(obj);
});
And this is objTemplate.jade:
p #{object}
// That's it.
When the alert() and console.log() are placed at the top of the script, it alerts and logs, but at the bottom, they don't execute (hence, I think it's a problem with either the creation of newsItem, the jade.render(), or the prepend.
If I need to provide any more snippets or files let me know. I'm still tinkering, so I might solve it on my own, but unless I update, I still need help. :)
I'd skip PHP and take a look at socket.io. It uses websockets when possible, but it will fall back to long-polling when necessary, and the client side library is very easy to use.
Whenever your node.js server has a new object ready to go, it will push it to all connected browsers. Use ClientJade to render the object using your template (you may have to break out the relevant part of the main template into its own file), then prepend the generated dom element to your feed.
First, if it isn't this way already, you'll need to break out the relevant part of your jade template into its own file. Call it objTemplate.jade. Then use ClientJade to create a compiled template that can be run in the browser: clientjade objTemplate.jade > jadeTemplate.js. Put jadeTemplate.js in your public js directory.
In your node.js app, you'll have something like this (pseudo-codey):
var io = require('socket.io').listen(httpServer);
listenForUDPPackets(function(obj) {
saveObjSomewhere(obj);
io.sockets.emit('obj', obj);
});
Then on the client, something like this:
<script src="/js/jadeTemplate.js"></script>
<script src="/socket.io/socket.io.js"></script>
<script>
var socket = io.connect();
socket.on('obj', function(obj) {
var newsItem = document.createElement();
jade.render(newsItem, 'objTemplate', obj);
$('#newsFeed').prepend(newsItem);
});
</script>
Whats the best way to do a RPC (Remote Procedure Call) from a webpage or from JavaScript code? I want to keep it in JavaScript if possible so that I can do live updates to the webpage without having to do anything in PHP in case my server goes down I still want the JavaScript to handle page updates... possibly even sending a request to a python shell script running locally... Is this legal from JavaScript?
I prefer having remote machines handling the requests. I see a lot of talk about how XMLRPC or JSONRPC can do this however, I haven't seen any good examples. I guess Microsoft suggests using their XMLhttprequest however, I haven't seen anything that doesn't use their ActiveX call or require special code for Internet Explorer... I just want some simple way of passing a command to some python/ruby/c++ code from a webpage.
Python Server Code (Waiting for a RPC Request):
import xmlrpclib
from SimpleXMLRPCServer import SimpleXMLRPCServer
def my_awesome_remote_function(str):
return str + "awesome"
server = SimpleXMLRPCServer(("localhost", 8000))
print "Listening on port 8000..."
server.register_function(is_even, "is_even")
server.serve_forever()
EXAMPLE JavaScript Code:
var client = rpc.server("http://localhost:8000/");
var my_local_variable = client.my_awesome_remote_function(param);
Is there a good JSON/JavaScript example someone can point me to that sends a request to a server and gets some data back from that server?
Thanks!
Hardly it will work this way: client.my_awesome_remote_function. There's no magic in js like __call in php. Also remote calls are done in js mostly asynchronously using idea of callback - function which is called after finishing of some task.
var client = rpc.server("http://localhost:8000/");
var my_local_variable;
client.rpc('my_awesome_remote_function', [param], function(result) {
my_local_variable = result;
});
You can easily find tutorials about that calls. Just google "ajax tutorials".
E.g.: http://www.w3schools.com/ajax/ajax_intro.asp (event though w3schools isn't the best site and have errors in some details, it is still good for beginners).
All ajax implementations use both modern both XMLHttpRequest and ActiveX control for older IE.
It is possible to run those requests synchronously, but is considered very bad from the point of user experience. Also, you'll need to deal with concept of callbacks anyway.