I am trying to understand the concept of JSON RPC and it's Perl implementation. Though I can fin d a lot of examples for Python/Java, I find surprisingly little or no examples for it in Perl.
I am following this example but am not sure it is complete. The example I had in mind was to add 2 integers. Now I have a very basic HTML page set up, like so:
<html>
<body>
<input type="text" name="num1"><br>
<input type="text" name="num2"><br>
<button>Add</button>
</body>
</html>
Next, based on the example above, I have 3 files:
test1.pl
# Daemon version
use JSON::RPC::Server::Daemon;
# see documentation at:
# https://metacpan.org/pod/distribution/JSON-RPC/lib/JSON/RPC/Legacy.pm
my $server = JSON::RPC::Server::Daemon->new(LocalPort => 8080);
$server -> dispatch({'/test' => 'myApp'});
$server -> handle();
test2.pl
#!/usr/bin/perl
use JSON::RPC::Client;
my $client = new JSON::RPC::Client;
my $uri = 'http://localhost:8080/test';
my $obj = {
method => 'sum', # or 'MyApp.sum'
params => [10, 20],
};
my $res = $client->call( $uri, $obj );
if($res){
if ($res->is_error) {
print "Error : ", $res->error_message;
} else {
print $res->result;
}
} else {
print $client->status_line;
}
myApp.pl
package myApp;
#optionally, you can also
use base qw(JSON::RPC::Procedure); # for :Public and :Private attributes
sub sum : Public(a:num, b:num) {
my ($s, $obj) = #_;
return $obj->{a} + $obj->{b};
}
1;
While I understand what these files individually do, I am at a complete loss when it comes to combining them and making them work together.
My questions are as follows:
Does the button in the HTML page come inside a tag (like we would normally do in a CGI-based program)? If yes, what file does that call? If no, then how do I pass the values to be added?
What is the order of execution of the 3 Perl files? Which one calls which one? How is the flow of execution?
When I tried to run the perl files from the CLI, i.e using $./test2.pl, I got the following error: Error 301 Moved Permanently. What moved permanently? which file was it trying to access? I tried running the files from withing /var/www/html and /var/www/html/test.
Some help in understanding the nuances of this would really be appreciated. Thanks in advance
Does the button in the HTML page come inside a tag (like we would
*normally do in a CGI-based program)? If yes, what file does that call?*
If no, then how do I pass the values to be added?
HTML has nothing at all to do with JSON-RPC. While the RPC call is done via an HTTP POST request, if you're doing that from the browser, you'll need to use XMLHttpRequest (i.e: AJAX). Unlink an HTML form post the Content-encoding: header will need to be something specific to JSON-RPC (e.g: application/json or similar), and you'll need to encode your form data via JSON.stringify and correctly construct the JSON-RPC "envelope", including the id, jsonrpc, method and params properties.
Rather than doing this by hand you might use a purpose-build JSON-RPC JavaScript client like the jQuery-JSONRP plugin (there are many others) -- although the protocol is so simple that implementations usually are less than 20 lines of code.
From the jQuery-RPC documentation, you'd set up the connection like this:
$.jsonRPC.setup({
endPoint: '/ENDPOINT-ROUTE-GOES-HERE'
});
and you'd call the server-side method like this:
$.jsonRPC.request('sum', {
params: [YOURNUMBERINPUTELEMENT1.value, YOURNUMBERINPUT2.value],
success: function(result) {
/* Do something with the result here */
},
error: function(result) {
/* Result is an RPC 2.0 compatible response object */
}
});
What is the order of execution of the 3 Perl files? Which one calls
*which one? How is the flow of execution?*
You'll likely only need test2.pl for testing. It's an example implementation of a JSON-RPC client. You likely want your client to run in your web-browser (as described above). The client JavaScript will make an HTTP POST request to wherever test1.pl is serving content. (e.g: http://localhost:8080).
Or, if you want to keep your code as HTML<-->CGI, then you'll need to make JSON-RPC client calls from within your Perl CGI server-side code (which seems silly if it's on the same machine).
When test1.pl calls dispatch, the MyApp module will be loaded.
Then, when test1.pl calls handle, the sum function in the MyApp package will be called.
The JSON::RPC::Server module takes care of marshalling from JSON-RPC to perl datastructures and back again around the call to handle. die()ing in sum should result in a JSON-RPC exception being transmitted to the calling client, rather than death of the test1.pl script.
When I tried to run the perl files from the CLI, i.e using
*$./test2.pl, I got the following error: Error 301 Moved Permanently.*
What moved permanently? which file was it trying to access? I tried
*running the files from withing /var/www/html and /var/www/html/test.*
This largely depends the configuration of your machine. There's nothing obvious (in your code) to suggest that a 301 Moved Permanently would be issued in response to a valid JSON-RPC request.
Related
My goal is to convert a C++ program in to a .pexe file in order to execute it later on a remote computer. The .pexe file will contain some mathematical formulas or functions to be calculated on a remote computer, so I’ll be basically using the computational power of the remote computer. For all this I’ll be using the nacl_sdk with the Pepper library and I will be grateful if someone could clarify some things for me:
Is it possible to save the outputs of the executed .pexe file on the remote computer in to a file, if it’s possible then how? Which file formats are supported?
Is it possible to send the outputs of the executed .pexe file on the remote computer automatically to the host computer, if it’s possible then how?
Do I have to install anything for that to work on the remote computer?
Any suggestion will be appreciated.
From what I've tried it seems like you can't capture the stuff that your pexe writes to stdout - it just goes to the stdout of the browser (it took me hours to realize that it does go somewhere - I followed a bad tutorial that had me believe the pexes stdout was going to be posted to the javascript side and was wondering why it "did nothing").
I currently work on porting my stuff to .pexe also, and it turned out to be quite simple, but that has to do with the way I write my programs:
I write my (C++) programs such that all code-parts read inputs only from an std::istream object and write their outputs to some std::ostream object. Then I just pass std::cin and std::cout to the top-level call and can use the program interactively in the shell. But then I can easily swap out the top-level call to use an std::ifstream and std::ofstream to use the program for batch-processing (without pipes from cat and redirecting to files, which can be troublesome under some circumstances).
Since I write my programs like that, I can just implement the message handler like
class foo : public pp::Instance {
... ctor, dtor,...
virtual void HandleMessage(const pp::Var& msg) override {
std::stringstream i, o;
i << msg.AsString();
toplevelCall(i,o);
PostMessage(o.str());
}
};
so the data I get from the browser is put into a stringstream, which the rest of the code can use for inputs. It gets another stringstream where the rest of the code can write its outputs to. And then I just send that output back to the browser. (Downside is you have to wait for the program to finish before you get to see the result - you could derive a class from ostream and have the << operator post to the browser directly... nacl should come with a class that does that - I don't know if it actually does...)
On the html/js side, you can then have a textarea and a pre (which I like to call stdin and stdout ;-) ) and a button which posts the content of the textarea to the pexe - And have an eventhandler that writes the messages from the pexe to the pre like this
<embed id='pnacl' type='application/x-pnacl' src='manifest.nmf' width='0' height='0'/>
<textarea id="stdin">Type your input here...</textarea>
<pre id='stdout' width='80' height='25'></pre>
<script>
var pnacl = document.getElementById('pnacl');
var stdout = document.getElementById('stdout');
var stdin = document.getElementById('stdin');
pnacl.addEventListener('message', function(ev){stdout.textContent += ev.data;});
</script>
<button onclick="pnacl.postMessage(stdin.value);">Submit</button>
Congratulations! Your program now runs in the browser!
I am not through with porting my compilers, but it seems like this would even work for stuff that uses flex & bison (you only have to copy FlexLexer.h to the include directory of the pnacl sdk and ignore the warnings about the "register" storage location specifier :-)
Are you using the .pexe in a browser? That's the usual case.
I recommend using nacl_io to emulate POSIX in the browser (also look at file_io. This will allow you to save files locally, retrieve them, in any format you fancy.
To send the output use the browser's usual capabilities such as XMLHttpRequest. You need PNaCl to talk to JavaScript for this, you may want to look at some of the examples.
A regular web server will do, it really depends on what you're doing.
I am accessing a third party web service using JAX-WS generated client (Java) code.
A call to a service that initiates a client session returns a Token in the response which, a.o., contains a Signature. The Token is required in subsequent calls to other services for authentication purposes.
I learned from using SoapUI that the WS/Endpoint requires the Token to be used as-is... meaning everything works fine when I literally copy the Token (which is one big line) from the initial response to whatever request I like to make next.
Now I am doing the same in my JAX-WS client. I retrieved a Token (I copied it from the response which I captured with Fiddler) and I tested it succesfully in a subsequent call using SoapUI.
However, when performing a subsequent call to a service using the JAX-WS client, the Signature part in the Token is changed. It should look like:
<Signature xmlns="http://www.w3.org/2000/09/xmldsig#">...</Signature>
But (when capturing the request with Fiddler) it now looks like:
<Signature:Signature xmlns:Signature="http://www.w3.org/2000/09/xmldsig#" xmlns="http://www.w3.org/2000/09/xmldsig#">...</Signature:Signature>
Apparently this is not acceptable according to the WS/Endpoint so now I'd like to know:
Why is the Token marshalled back this way?
More importantly, how can I prevent my client from doing that?
Thanks in advance!
Have you tested it? It should work nevertheless. The original signature used the defautl namespace (...xmldigsig) the JAXB version uses the same namespace but explicit says that the Signature element belongs to that namespae (Signature:Signature). The effect is the same, both xml express that Signature is in the http://www.w3.org/2000/09/xmldsig# namespace
You can customize the jaxby output with #XMLSchema on the package info, #XMLType on the class or inside the element.
http://blog.bdoughan.com/2010/08/jaxb-namespaces.html
By the help of #Zielu I was able to solve this by altering package-info.java (in the package of the generated files) like so:
#javax.xml.bind.annotation.XmlSchema(
namespace = "http://namespaceofthirdparty-asingeneratedversionof package-info.java"
, xmlns = {
#javax.xml.bind.annotation.XmlNs(namespaceURI = "http://www.w3.org/2000/09/xmldsig#", prefix = "")
}
, elementFormDefault = javax.xml.bind.annotation.XmlNsForm.QUALIFIED) package com.where.generated.files.are;
Is there a way to change the numericSymbols when rendering a Highchart on a server with Phantomjs?
I generate the JSON locally on the server and pass it to Phantomjs as a parameter along with the highcharts-convert.js script and my output file
My graphs are rendered to images fine but I need to in effect do the same server-side (or via JSON) that is done on a browser client by setting the global options with:
Highcharts.setOptions({
lang:{
numericSymbols: null
}
});
Is there a way of doing it with the callback maybe?
Or is there a JSON object that this can be done with?
This might help you:
http://forum.highcharts.com/highcharts-usage/setting-global-options-on-export-server-t28909/
It helped me to solve my decimalPoint problem.
If you are using the POST method, just follow the instructions in the link, if using the command line method (like me), just add globaloptions as a parameter:
phantomjs highcharts-convert.js -infile temp/test.js -outfile temp/chart.png -globaloptions temp/test2.js
And the content of temp/test2.js was in my case:
{
lang:{
decimalPoint:",",
thousandsSep:"."
}
};
I am trying to read a JSON file with Meteor. I've seen various answers on stackoverflow but cannot seem to get them to work. I have tried this one which basically says:
Create a file called private/test.json with the following contents:
[{"id":1,"text":"foo"},{"id":2,"text":"bar"}]
Read the file contents when the server starts (server/start.js):
Meteor.startup(function() {
console.log(JSON.parse(Assets.getText('test.json')));
});
However this seemingly very simple example does not log anything to the console. If I trye to store it in a variable instead on console.logging it and then displaying it client side I get
Uncaught ReferenceError: myjson is not defined
where myjson was the variable I stored it in. I have tried reading the JSON client side
Template.hello.events({
'click input': function () {
myjson = JSON.parse(Assets.getText("myfile.json"));
console.log("myjson")
});
}
Which results in:
Uncaught ReferenceError: Assets is not defined
If have tried all of the options described here: Importing a JSON file in Meteor with more or less the same outcome.
Hope someone can help me out
As per the docs, Assets.getText is only available on the server as it's designed to read data in the private directory, to which clients should not have access (thus the name).
If you want to deliver this information to the client, you have two options:
Use Assets.getText exactly as you have done, but inside a method on the server, and call this method from the client to return the results. This seems like the best option to me as you're rationing access to your data via the method, rather than making it completely public.
Put it in the public folder instead and use something like jQuery.getJSON() to read it. This isn't something I've ever done, so I can't provide any further advice, but it looks pretty straightforward.
The server method is OK, just remove the extra semi-colon(;). You need a little more in the client call. The JSON data comes from the callback.
Use this in your click event:
if (typeof console !== 'undefined'){
console.log("You're calling readit");
Meteor.call('readit',function(err,response){
console.log(response);
});
}
Meteor!
I have no idea how to achieve this, but I have a HTML form, with several different elements in it.
For testing, right now, all I would like to do is write a piece of C code that will take anything that is submitted and print this out on the screen.
I can write my own parsing code - I just cannot work out how to get the form data to print directly to the screen.
Thanks in advance.
Assuming you have a web server configured to allow you to do CGI, your HTML form needs to be written to either GET or POST the form data to the CGI script. You can then implement a CGI script in C to process the form data.
As a starter CGI script, you can simply echo whatever is provided in the input as the output.
int main () {
int c;
puts("Content-type: text/plain");
puts("Connection: close");
puts("");
while ((c = getchar()) != EOF) {
putchar(c);
}
return 0;
}
You need an HTTP server, with settings that let you run CGI scripts. This could be a server installed locally in your computer, using e.g. XAMPP, or it could be a web server that you have access to.
Then you will write a C program that uses CGI conventions for I/O. As output, it should write a complete HTML document with accompanying HTTP headers. You will need to compile the program into an executable, upload the executable on the HTTP server, and put the URL of the executable into the action attribute of the form.
For details etc., check out Getting Started with CGI Programming in C.
Here's an example of a form echoing script in C, which you might find helpful in terms of responding to both GET and POST methods, parsing the query string or input, etc:
http://www.paulgriffiths.net/program/c/formecho.php