baalexander / node-xmlrpc Goto Github PK
View Code? Open in Web Editor NEWA pure JavaScript XML-RPC client and server for Node.js.
License: MIT License
A pure JavaScript XML-RPC client and server for Node.js.
License: MIT License
How do I trap a connection error? Like if the wrong credentials were used.
This came out of the discussion from Pull Request #56.
There was a need to be able to respond to a listening
and close
event from the XML-RPC server. However, server.on('listening')
could cause a conflict if the XML-RPC method call's name was listening
. One proposed solution is to change the API to something like:
server.on('methodCall', function(method, args) {
// switch based on method name
});
server.on('listening', function() {
})
server.on('close', function() {
});
server.on('error', function(error) {
});
The disadvantage is a big API change. The advantage is other events can be emitted (listening, close, etc.) and not be confused with method names.
If I add this testcase:
diff --git a/test/xmlrpc-parser-test.js b/test/xmlrpc-parser-test.js
index df55cbc..b672eb6 100644
--- a/test/xmlrpc-parser-test.js
+++ b/test/xmlrpc-parser-test.js
@@ -452,6 +452,18 @@ vows.describe('XML-RPC Parser').addBatch({
assert.deepEqual(params, ['testString1', 'testString2', 'testString3'])
}
}
+ , 'with a multiline String param' : {
+ topic: function() {
+ var xml = '<methodResponse><params>'
+ + '<param><value><string>test\n\n<test></string></value></param>'
+ + '</params></methodResponse>'
+ xmlrpcParser.parseMethodResponse(xml, this.callback)
+ }
+ , 'contains the multiline string' : function (error, value) {
+ assert.isString(value)
+ assert.strictEqual(value, 'test\n\n<test>')
+ }
+ }
, 'with a String param and newlines in xml' : {
topic: function() {
var xml = ['<?xml version=\'1.0\'?>'
it fails with:
A parseMethodCall call with a multiline String param
✗ contains the empty string
» expected 'test\n\n<test>',
got 'test\n\n' (===) // xmlrpc-parser-test.js:464
The issue is, that onCharacters is called only once and ignored afterwards. But it seems not expected by the node-xml lib. I am working on a fix in my fork, I will send a pull request as soon as it's finished.
Originally reported by ProjectMoon in Issue #16:
This returns a very small response, but the callback gives me null as an answer.
get_upload_rate
returns me something like this:
<?xml version="1.0" encoding="UTF-8"?>
<methodResponse>
<params>
<param><value><i8>296960</i8></value></param>
</params>
</methodResponse>
The function encodeIso8601 in date_formatter.js produces odd results when trying to act as an XML RCP client for wordpress. Wordpress expects the dates to end in a Z or the have the GMT offset. Since encodeIso8601 just leaves the ends with + zeroPad(date.getSeconds(), 2)
it breaks. In my project I have changed encodeIso8601 to include the + 'Z'
but perhaps there is a way to provide an override to the encodeIso8601 or take into account the GMT offset.
After tested in the field a bit more, package the code and submit to NPM.
Check on how node dependencies should be handled with NPM 1.x. For example, should the local node_modules directory be included now?
Also, ignore the test and example directory in .npmignore.
using this,
client.methodCall(method, ['args1','args2'], function (error, value) { console.log(value); } );
i discovered that when the rpc server returns this, it works
<methodResponse>
<params>
<param>
<value><struct><member><name>entry</name><value><int>6</int></value></member><member><name>size</name><value><int>1</int></value></member><member><name>slot</name><value><struct><member><name>item</name><value><struct><member><name>name</name><value><string>4::num</string></value></member><member><name>value</name><value><int>1</int></value></member></struct></value></member></struct></value></member></struct>
</value>
</param>
</params>
</methodResponse>
but this, it doesn't.
<methodResponse>
<params>
<param>
<value><struct><member><name>entry</name><value><int>6</int></value></member><member><name>size</name><value><int>1</int></value></member><member><name>slot</name><value><struct><member><name>item</name><value><struct><member><name>name</name><value><string>4::num</string></value></member><member><name>value</name><value><int>1</int></value></member></struct></value></member></struct></value></member></struct>
<struct><member><name>entry</name><value><int>11</int></value></member><member><name>size</name><value><int>1</int></value></member><member><name>slot</name><value><struct><member><name>item</name><value><struct><member><name>name</name><value><string>3::num</string></value></member><member><name>value</name><value><int>1</int></value></member></struct></value></member></struct></value></member></struct>
</value>
</param>
</params>
</methodResponse>
i wonder why?
does it have something to do with the reply having 2 entries? how do i work around this? i want to parse the 2 entries.
Sure Node v0.6 is not ready as of writing this issue, but the v0.5 branch is getting close to ready. Need to confirm no issues on the next major Node release. Test the test cases, test the example program, etc.
The xml-rpc 'protocol' (specifically the serialising and deserializing component) could be easily refactored out of this module and into its own separate module.
Benefits:
Thoughts?
Create a detailed README file (you have great documentation in the code, don't stop now!) with info on what it does (XML-RPC and node.js? Why??), how to install (include info about npm package not yet ready), how to test, how to use, and what license.
I'm really liking the concept and implementation of Travis CI and the affects it may have on open source quality. Xmlrpc already has a battery of tests, so it should just be a matter of integration.
Tests fail on 0.10. Need to investigate.
When running node example/client-server.js
, some of the getters are called before the setters. For example, getArray returns null even though setArray is called before with a value.
Putting the getArray code in the callback for the setArray ended up with the callback never getting called. It's possible the callback was never getting called.
// Nest the getter in the callback of the setter (getter does not currently get called)
client.methodCall('setArray', [['value1', 'value2']], function (error, value) {
client.methodCall('getArray', null, function (error, value) {
console.log('Get Array Response: ' + value)
})
})
This test has failed ever since I can remember. I just now decided to take a look at it:
A buildMethodCall call with a one-level struct and an empty property name
✗ contains the struct
» expected '<?xml version="1.0"?><methodCall><methodName>testMethod</methodName><params><param><value><struct><member><name/><value><string>string1</string></value></member><member><name>intName</name><value><int>3</int></value></member></struct></value></param></params></methodCall>',
got '<?xml version="1.0"?><methodCall><methodName>testMethod</methodName><params><param><value><struct><member><name>stringName</name><value><string/></value></member><member><name>intName</name><value><int>3</int></value></member></struct></value></param></params></methodCall>' (==) // xmlrpc-builder-test.js:170
✗ Broken » 75 honored ∙ 1 broken (1.036s)
If you match them:
expect: <?xml version="1.0"?><methodCall><methodName>testMethod</methodName><params><param><value><struct><member><name/><value><string>string1</string></value></member><member><name>intName</name><value><int>3</int></value></member></struct></value></param></params></methodCall>
got: <?xml version="1.0"?><methodCall><methodName>testMethod</methodName><params><param><value><struct><member><name>stringName</name><value><string/></value></member><member><name>intName</name><value><int>3</int></value></member></struct></value></param></params></methodCall>
Given test data:
[{stringName: '', intName: 3}]
It seems like the 'expected' XML is wrong? For example, I don't know where string1
came from. The name
property, based on the intName
, should be set to stringName
just like it is in the received XML. The string passed is empty so presumably we should indeed have a <string/>
. I changed it to match this and of course it passes, but I wanted to ask before I file a pull request in case I'm misunderstanding something.
In short, I believe the test's expected result is actually wrong and should indeed be set to what we're actually receiving, which would allow the test to pass. I base this hypothesis on how the intName
data is structured.
The xml-rpc API in WordPress produces invalid responses (usually a html error page) under certain error conditions. In those cases, access to the actual response would be very valuable to debug the issue. Currently all we get is something like Unknown XML-RPC tag 'TITLE'
.
Would be used in https://github.com/scottgonzalez/node-wordpress and https://github.com/scottgonzalez/grunt-wordpress
Instead of an response object I just get null
.
I gisted the response XML here: https://raw.github.com/gist/1852071/c6195cd12be6d77be16b68a26e183ae9a76b9195/gistfile1.txt
Would be great if you could take a look.
Cheers,
agnat
Library fails to produce an error when given this response:
<?xml version="1.0" encoding="iso-8859-1"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<title>401 - Unauthorized</title>
</head>
<body>
<h1>401 - Unauthorized</h1>
</body>
</html>
The callback fires, but the error object is null
.
node-xml hasn't been updated in a year and while it's worked out well, there's been a few issues creeping up:
Isaac's Sax.js looks like a good replacement candidate as it's a SAX parser too and it's JavaScript only (no libxml).
if I try to connect to glances, I get an 404
https://github.com/nicolargo/glances
working fine with python/ruby xmlrpc clients
Currently getting the following error from a xmlrpc call to a bugzilla server:
error:{ [Error: Unexpected end
Line: 0
Column: 36294
Char: ]
[message]: 'Unexpected end\nLine: 0\nColumn: 36294\nChar: ' }
when looking at the response headers the content length shows up with a higher value than show above, but if i try to print the end of the response body it seems to be cutoff.
headers from the response:
{ date: 'Wed, 23 Jul 2014 14:04:54 GMT',
server: 'Apache/2.2.17 (Win32) mod_perl/2.0.4 Perl/v5.8.9',
soapserver: 'SOAP::Lite/Perl/0.714',
'content-length': '36418',
'keep-alive': 'timeout=5, max=100',
connection: 'Keep-Alive',
'content-type': 'text/xml' }
Also this issue happens with smaller responses (content-lenght >3000k)
By default, xmlrpc will stay a pure-JavaScript, no build required XML-RPC client and server module. However, there has been some interest in a more robust xml parsing engine for speed and hostile environments.
An option should be added to use a different parser. The likely candidate right now is Expat, a fast, SAX-like XML parser in C.
Depending on the API for the expat module, it would be great to utilize the same parser front-end that would handle events events from either parser.
node-xmlrpc uses an older version of xmlbuilder, which results in a warning during installation:
npm WARN package.json [email protected] No README.md file found!
latest xmlbuilder version is 0.4.2 and has a readme.md. I did not test the latest version against node-xmlrpc and its not a big issue. though, it would be nice to update xmlbuilder with the next release.
The Client module has a function call
for making an XML-RPC request. This function can be confused with the call
function on JavaScript's function prototype.
Rename the Client's call
function to something else, perhaps send
or methodCall
.
As the major semver is still 0 implying the API may change, this will probably just be a change from 0.6.x to 0.7.0. However, to ease upgrading, the initial update may keep the call
function and throw a deprecation error. The call
function could then be removed completely in a later release.
Thanks to @nw for bringing the call
conflict up.
When calling client.methodCall with int parameters from this code,
Ubigraph.prototype.removeVertex = function(vertexID, callback){ this.client.methodCall('ubigraph.remove_vertex', [parseInt(vertexID)], function(error, value){}); };
I get this error message:
{ [Error: Value of type DOUBLE supplied where type INT was expected.] faultCode: -501, code: -501, faultString: 'Value of type DOUBLE supplied where type INT was expected.' }
The values I pass in look like 1223540139
.
Add a history log to know what's been changed for each release.
Hi,
the current server code expects that a request has always only a single data chunk:
https://github.com/baalexander/node-xmlrpc/blob/master/lib/server.js#L51
Unfortunately, that causes errors when XML-serialized method calls comes as splitted into multiple chunks. (Every chunk is handled like a complete method call, which causes multiple broken calls to be done.)
I think, request.on('data') should only concatenate received chunks into temporary httpServer.on('request')-level variable, until request.on('end') handles the method call (as request.on('data') currently does).
Thanks.
I have a requirement to implement these extensions: system.multicall and introspection
It might make sense to (optionally) include these in this module. Your call.
RIght now, geared towards making client calls and handling the response. What about receiving a client call from another party?
Could add another file Server and maybe a common file for reading and writing the XML since Client and Server will need to do both.
Or could put client and server in main xmlrpc file. Example: xmlrpc.call(). The xmlrpc could automatically enter server mode when created (passed in the http object).
xmlrpc constructor should take an HTTP server object since both Client and Server will use that.
The server could use listeners and emit events.
[email protected] test /home/skypjack/projects/node-xmlrpc/node_xmlrpc.orig
make test
·············· ··············· ···········✗··············· ······································································· ·······································
·····
A local date when encoded to utc representation
✗ must match the correct time
» expected '20140120T13:25:25Z' to match /T[0]?12[:]?[0]?25[:]?25(\.000)?Z/ // date_formatter.js:66
✗ Broken » 170 honored ∙ 1 broken (1.479s)
make: *** [test] Error 1
npm ERR! Test failed. See above for more details.
npm WARN This failure might be due to the use of legacy binary "node"
npm WARN For further explanations, please read
/usr/share/doc/nodejs/README.Debian
npm ERR! not ok code 0
The XML-RPC specifications allow value-elements without an explicit type: "If no type is indicated, the type is string."
This seems to be unsupported by node-xmlrpc and would be a nice addition. I will post it here if I can find a good solution myself.
In client-test.js, there are two tests that rely on an http server (with a very long response
and with a chunked response
). If both are run, the with a very long response
test will fail. If the with a chunked response
test is commented out, the with a very long response
test will pass.
Nil is an extension to XML-RPC. Right now, the XML building partially supports nil (considers JavaScript's null
to be a nil value). Need to add support to all method calls and responses.
If I read the code correctly all clients share a single xml parser. Chunks are written to the parser concurrently and the parser is destroyed and replaced whenever a method call finishes. Is that correct? How is that supposed to work?
This is not related to #42. I only have one client right now.
As mentioned by @agnant in https://gist.github.com/1856367, more robust testing would add integration testing with other proven XML-RPC libraries, like pythons.
Create an object with the fault message if receives an XML-RPC fault. The object should be passed in the error parameter of callbacks.
Add test cases to support.
When creating a client, how should one pass the option strictSSL: false
for requests to be able to communicate with servers that have a "Self-Signed SSL Certificate" and prevent the DEPTH_ZERO_SELF_SIGNED_CERT exception from being thrown?
rTorrent has a fully-featured XMLRPC API. I've run into two problems with your library regarding it:
get_upload_rate
. This returns a very small response, but the callback gives me null as an answer.get_upload_rate
returns me something like this:
<?xml version="1.0" encoding="UTF-8"?>
<methodResponse>
<params>
<param><value><i8>296960</i8></value></param>
</params>
</methodResponse>
It seems the parsing of this response fails somehow, and the callback returns with a null object.
When a value contains a multi-byte character the length is incorrectly calculated as 1 byte. The problem is in Client.prototype.methodCall
when the Content-Length
header is set based on the length of the XML.
README currently refers to this module as node-xmlrpc
. The "node-" is only meant to apply to the repository name, to emphasize it's a Node.js module. The module itself is named xmlrpc
and is xmlrpc
in NPM.
I am using the xmlrpc node module to send xmlrpc request to a twisted server (in house) to receive events.
A request is send and if no events are there, a 'timeout' response is sent after one minute.
Apparently the twisted server is not closing the connexion after sending the response.
It means that after some time the number of active connexions is the maximum (1024 in this case) and the server stops accepting new connexions.
It is probably a bug in the twisted server which should close the connexions after sending the response.
But I think the xmlrpc node client should also close the connexion after receiving the response (or after a delay ?).
In my case I was able to solve this by calling request.abort() in the function(response) which is in Client.prototype.methodCall
When calling parseMethodCall the callback parameter function is never fired.
Run the vows test suite below.
Excepted Result: Successful test execution
Actual Result: Test produces error:
fquatro-imac:testable fquatro$ ./node_modules/vows/bin/vows ./test/XMLRPCSuite.js
✗ Errored » callback not fired
in should parse method call
in XMLRPCSuite
in test/XMLRPCSuite.js✗ Errored » 1 errored ∙ 1 dropped
Mac OS X 10.6.8
fquatro-imac:testable fquatro$ node --version
v0.5.4
fquatro-imac:testable fquatro$ npm list
/Users/fquatro/workspace/test-wip/testable
├── [email protected]
├─┬ [email protected]
│ └── [email protected]
├─┬ [email protected]
│ ├── [email protected]
│ ├── [email protected]
│ ├── [email protected]
│ ├─┬ [email protected]
│ │ ├── [email protected]
│ │ └── [email protected]
│ ├── [email protected]
│ └── [email protected]
└─┬ [email protected]
├── [email protected]
└── [email protected]
var vows = require('vows');
var assert = require('assert');
var oXMLRPCParser = require("xmlrpc/lib/xmlrpc-parser");
var strMessage = "<methodCall>\n<methodName>testMethod?version=1.0.0&timeoutInSecs=240</methodName>\n<params>\n<param>\n<value><string>http://www.silver.com?test=12&loop=</string></value>\n</param>\n</params>\n</methodCall>";
// Create a Test Suite
vows.describe('XMLRPCSuite').addBatch({
'should parse method call' : {
topic : function() {
oXMLRPCParser.parseMethodCall(strMessage, this.callback);
},
'with callback result of success' : function(p_oError, p_oMethod, p_arrayParams) {
logger.log("debug", "callback - p_oError=[" + p_oError + "], p_oMethod=[" + p_oMethod + "], p_arrayParams=[" + p_arrayParams + "]");
assert.isNull(p_oError);
assert.isTrue(p_oMethod.indexOf("testMethod") > -1);
}
}
}).export(module);
Is it possible to send request PHP server ?
var xmlrpc = require('xmlrpc');
var client = xmlrpc.createClient({host: 'localhost/rpc/index.php/xmlrpc_server', port: 80});
client.methodCall('Greetings', ['aParam'], function (error, value) {
console.log(error)
});
When I use it I get this error
{ [Error: getaddrinfo ENOTFOUND] code: 'ENOTFOUND', errno: 'ENOTFOUND', syscall:
'getaddrinfo' }
This is the code I'm running
xmlrpc = require 'xmlrpc'
client = xmlrpc.createClient
host: 'localhost'
port: 51041
path: '/'
client.methodCall 'system.listMethods', null, (err, value) ->
console.log 'response'
throw err if err
console.log value
And I get this error whenever I do methodCall no matter the method I pass in.
node.js:134
throw e; // process.nextTick error, or 'error' event on first tick
^
Error: socket hang up
at Socket.<anonymous> (http.js:1288:45)
at Socket.emit (events.js:64:17)
at Array.<anonymous> (net.js:831:12)
at EventEmitter._tickCallback (node.js:126:26)
Node's buffers may be a good place to start.
The xmlrpc.createClient function (xmlrpc.js) only takes options and assumes the request is always over HTTP only.
xmlrpc.createClient = function(options) {
return new Client(options, false)
}
Furthermore, the Client function (client.js) does not switch to HTTPS when port 443 is set in the options. Since the Client function already takes an argument for "isSecure" it would be much easier to do this in the xmlrpc.createClient function:
xmlrpc.createClient = function(options, isSecure) {
return new Client(options, !!(isSecure));
};
And then it could be easily specified when creating the client:
var options = { host: 'localhost', port: 443, path: '/' };
var xmlclient = require('xmlrpc').createClient(options, true);
When creating a client or server, support both HTTP and HTTPS connections.
Client code could have another function like secureCall(). Actually, since server params are passed as part of the Client constructor, should take another parameter isSecure, which defaults to false.
When using Python's XML-RPC library to call a node-xmlrpc server, the xmlrpc server gets hung up on the newlines Python inserts in its method calls.
Example Python XML-RPC method call:
<?xml version='1.0'?>
<methodCall>
<methodName>getPublications</methodName>
<params>
<param>
<value><string>/ohyeah</string></value>
</param>
</params>
</methodCall>
Python code:
import xmlrpclib
caller_id = "/ohyeah"
m = xmlrpclib.ServerProxy("http://localhost:9098")
code, msg, val = m.getPublications(caller_id)
Testing shows the parser is the culprit and is including the newlines in its parsing.
If an empty string is passed, the resulting XML looks like <string></></string>
. Look at how other libraries handle this.
Hi, is there a way to set a timeout for a request in the client?
Because, if the remote server does not answer I would like to be notified. :)
http://nodejs.org/api/http.html#http_request_settimeout_timeout_callback
Thanks.
Please delete this!
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.