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.
Related
I'm new to coding and was pretty proud when I created the following PHP code. Using TwitchTV's API, I can show the game someone is playing on TwitchTV. It works.
$info = "https://api.twitch.tv/kraken/channels/celgaming";
$json = json_decode(file_get_contents($info), true);
$thegame = $json['game'];
echo $thegame;
But I'm planning on caching the page this code is on and realized it won't work because PHP is server side. How do I convert this piece of code to Ajax or some other asynchronous method that will work with page caching?
I´m not sure about an async call being what you need, but I would try that first.
Here is, not a real answer, but hopefully some pointers to it:
Tried to make an Ajax call to "https://api.twitch.tv/kraken/channels/celgaming"
and stumbled upon 'same-domain policy' issue. See below link.
[Solutions to Ajax cross-domain problem][1]
I tried this from [1]: Ways to circumvent the same-origin policy
$.getJSON("https://api.twitch.tv/kraken/search/games?q=star&type=suggest&callback=?", function (data) {
$.each(data.games, function (index, item) {
console.log(index, item);
});
});
It works. Maybe you should scan the API docs for an alternate way to get the data you need.
I won't write you the javascript, you should try that first yourself, but propose other solutions that might solve your primary objective (caching):
you may use a database (e.g. MySQL) instead of client side caching. Just store the result of your TwitchTV query together with an expiration date in your database and check it before sending another request to TwitchTV.
you could send HTTP Cache-Control headers via PHP or included in your HTML code. See this question for instructions: Cache control and expires header for PHP. They suggest to the client to no query the server before the expiration date is reached.
I have been working with jquery/ajax requests. I have successfully got a ajax request which will retrieve data from a database, the problem is, that i'm constantly serving window.setInterval() to refresh this function every x amount of seconds.
How would I change this to keep the ajax request alive, so it updates the html content without having to serve multiple requests to my ajax script.
My code follows:
window.setInterval(function()
{
$(function ()
{
$.ajax({
url: 'Ajax.php'+SearchTerm, dataType: 'json', success: function(rows)
{
$('#NumberOfVotes').empty();
for (var i in rows)
{
var row = rows[i];
var QuestionID = row[0];
var Votes = row[1];
$('#NumberOfVotes')
.append(Votes);
}
}
});
});
}, 500);
A lot of this depends on how your server would be able to update it's content dynamically. That said, what you are looking for is websockets. Websockets are designed to replace the long-polling paradigm.
EDIT: Since you use mainly php for your server technology, look at Ratchet. I've heard good things about it http://socketo.me/
Here is an excellent article on using websockets with HTML
http://net.tutsplus.com/tutorials/javascript-ajax/start-using-html5-websockets-today/
.NET has a great socket library in SignalR
http://signalr.net/
There is a myriad of php documentation on sockets out there
http://php.net/manual/en/book.sockets.php
look into using web sockets - you could send the client a message anytime they need to go an look for new data - that way your not making any unnecessary requests. Try checking out pubnub -service is cheap and could handle everything you need.
You could set xhr.multipart = true and modify server code. see Multipart Responses Example Code. Alternative way is to use websockets as mentioned
You need something server side that keeps the request alive until it has something to return. This is usually called "Comet", "Long-polling" or "Push".
The principle is :
You send a request client-side via AJAX
Your server receives the request, and doesn't return a response yet. It sleeps/waits until it has something to return
A new entry in your database ! Your server now has something to return : it returns some JSON data for the waiting request
Your receive the response server side, display what you have to display, and go back to step 1 sending another request.
Now, the implementation server side will depend on the language/framework you are using.
Edit :
Some examples using PHP :
Comet and PHP
Simple Comet Implementation Using PHP and jQuery
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.
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>
So far when creating AJAX requests I have been posting to a separate PHP file. Is it possible to create a jQuery AJAX request that calls a PHP function rather than posts to a separate page?
If you could send me any examples or documentation would be great.
I believe there's a fundamental misunderstanding of how the technology works here.
AJAX (Javascript), Flash, or any client-sided technology cannot directly call PHP functions (or other languages running on the server).
This is true for going the other way around as well (eg: PHP can't call JS functions).
Client and server codes reside on different machines, and they communicate through the HTTP protocol (or what have you). HTTP works roughly like this:
Client (eg: browser) sends a REQUEST -> Server processes request and sends a RESPONSE -> Client gets and displays and/or processes the response
You have to see these requests and responses as messages. Messages cannot call functions on a server-side language directly 1, but can furnish enough information for them to do so and get a meaningful message back from the server.
So you could have a handler that processes and dispatches these requests, like so:
// ajax_handler.php
switch ($_POST['action']) {
case 'post_comment':
post_comment($_POST['content']);
break;
case '....':
some_function();
break;
default:
output_error('invalid request');
break;
}
Then just have your client post requests to this centralized handler with the correct parameters. Then the handler decides what functions to call on the server side, and finally it sends a response back to the client.
1 Technically there are remote procedure calls (RPCs), but these can get messy.
AJAX requests call a URL (make a HTTP request), not a file, in most cases the URL is translated by the server to point at a file (or a php script in your case), but everything that happens from the HTTP request to the response that is received is up to you (on your server).
There are many PHP frameworks that map URL's to specific php functions, AJAX is just an asynchronous way to access a URL and receive a response.
Said URL CAN trigger the server to call a specific function and send back a response. But it is up to you to structure your URL's and server side code as such.
If you're asking whether you can call any arbitrary PHP function with AJAX the answer is no*, for obvious security reasons (in addition to the technical reasons). You could make a PHP script that does different things depending on what parameter it's given (for example, execute a single function) if you don't want to create multiple separate files.
*Although you could make a script that would execute any arbitrary PHP command coming from the client, but that would be very, very, very unwise.
Short answer is "no" but the real answer is that you can fake it. NullUserException's answer is good. You create a server that will take the function name and its parameters. Then the server executes the function, and returns the value.
This was done a while back via a protocol called XML-RPC. There was also an effort called JSON-RPC that used some JS techniques.
One things that's cool about JS is that you can do things like this:
var base64_decode = create_remote_call('base64_decode');
function create_remote_call(name) {
return function(x) {
jQuery.getJSON('url/server.php',
{func:name,arg:x},
function(d){return d;});
}
}
A call to base64_decode('sarefdsfsaes') will make a ajax request and return the value.
That code probably won't work because it hasn't been tested, but it's a function that produces a function that will call the server, and then return the value. Handling more than one argument requires more work.
All that said... in my experience, it's usually good to make all network communications explicit instead of disguising it as a regular function.
you may achieve the same result using a bridge, like my phery library http://phery-php-ajax.net you can call PHP functions directly from Javascript and deal with the value. The AJAX is bound to DOM elements, so you can manipulate the calling DOM or just use jQuery from the PHP side. An example would be:
Phery::instance()->set(array(
'phpfunction' => function(){
return PheryResponse::factory()->jquery('body')->addClass('whoops');
}
))->process();
and in the javascript side (or HTML)
phery.remote('phpfunction');
the equivalent to the https://stackoverflow.com/a/7016986/647380 from John Kawakami answer, using phery is:
function base64($data){
return !empty($data['encode']) ? base64_encode($data['content']) : base64_decode($data['content']);
}
Phery::instance()->set(array(
'base64' => 'base64'
))->process();
function base64(content, decode, output){
phery.remote('base64', {'content': content, 'encode': decode ? 1 : 0}, {'type':'text'}).done(output);
}
base64('asdf', false, function(data){
console.log(data); // or assign to some variable
});
since AJAX is asynchronous and you can't just return a value from the AJAX call, you need a callback, but this would suffice.