Continued Services woes
After hours of searching, scouring, absorbing it was determined that there was little hope of (currently) getting past Services 2.4 and REST returning a 404 error, so I switched to xmlrpc. I have a simple script to hit my service from outside the site, fine-tuned a couple dozen times based on various recommendations, to currently be: $url = "http://localhost/mydomain/services/xmlrpc"; $ch = curl_init(); $data = 'method=my.method&id=12345&text=hello'; curl_setopt($ch, CURLOPT_POST, 1); curl_setopt($ch, CURLOPT_POSTFIELDS, $data); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_URL, $url); $response = curl_exec($ch); with $data as a string like above, I continuously receive: faultCode -32700 faultString Parse error. Request not well formed. If I change the postfields to be an array('method'=>'my.method','id'=>12345... I instead continuously receive a message that xmlrpc will only handle Post transactions. -- /I am a non sequitur. Beware, the contents were packaged where peanuts are processed./ Ayen Designs 388 Bullsboro Drive #105 · Newnan, Georgia 30263 404-271-9734 Web:ayendesigns.com <http://ayendesigns.com/> Blog: theAccidentalCoder.com <http://theaccidentalcoder.com/> Drupal: j. ayen green <http://drupal.org/user/367108> (367108) IRQ: j_ayen_green IM (Yahoo) baalwww (MSN) baalwww@yahoo.com Skype: ayendesigns | Facebook: ayendesigns | Twitter: @ayendesigns Ayen Designs is the computer services division of
Here's some example code I posed at d.o showing how to communicate between two Drupal 6 sites using Services 2.2 thru 2.4, & the XMLRPC server: http://drupal.org/node/774298 you'll want to examine the "send()" routine, which is used to call any xmlrpc method. The example code uses the Drupal API, rather than cURL, as you are attempting to use. However, the key logic you'll want to see is the "send()" routine, which is the handling & packaging of the method arguments before calling the remote method. Your code you show below is incorrect for XMLRPC parameter packaging. Additionally, as an aid for you to convert between the logic I give above and your attempts to use cURL, I have another post at g.o showing how to communicate with a Services 3.0 REST remote API - with two examples: one using cURL and one using the Drupal API. Granted, my second example is for a REST server in Services 3.0, but it demonstrates the cURL handling - you'll just need to translate the first code example's packaging of the method parameters for XMLRPC transport. http://drupal.org/node/1070066 And for your assurance, both code examples I've posted are taken directly from live sites using those implementations. Sincerely, -Blake bsenftner@earthlink.net www.BlakeSenftner.com www.MissingUbercartManual.com On Mar 4, 2011, at 2:30 PM, jeff@ayendesigns.com wrote:
After hours of searching, scouring, absorbing it was determined that there was little hope of (currently) getting past Services 2.4 and REST returning a 404 error, so I switched to xmlrpc.
I have a simple script to hit my service from outside the site, fine-tuned a couple dozen times based on various recommendations, to currently be:
$url = "http://localhost/mydomain/services/xmlrpc"; $ch = curl_init(); $data = 'method=my.method&id=12345&text=hello'; curl_setopt($ch, CURLOPT_POST, 1); curl_setopt($ch, CURLOPT_POSTFIELDS, $data); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_URL, $url);
$response = curl_exec($ch);
with $data as a string like above, I continuously receive: faultCode -32700 faultString Parse error. Request not well formed.
If I change the postfields to be an array('method'=>'my.method','id'=>12345... I instead continuously receive a message that xmlrpc will only handle Post transactions.
-- I am a non sequitur. Beware, the contents were packaged where peanuts are processed. <ayenlogo.jpeg>Ayen Designs 388 Bullsboro Drive #105 · Newnan, Georgia 30263 404-271-9734 Web:ayendesigns.com Blog: theAccidentalCoder.com Drupal: j. ayen green (367108) IRQ: j_ayen_green IM (Yahoo) baalwww (MSN) baalwww@yahoo.com Skype: ayendesigns | Facebook: ayendesigns | Twitter: @ayendesigns
Ayen Designs is the computer services division of <acmelogo.jpeg>
Blake, thanks very much for pointing me at these two examples. So, my first question is regarding the packaging of the parameters. In my case, there will be no authentication. How does that affect the creation of a hash, etc.? Jeff On 03/04/2011 06:42 PM, Blake Senftner wrote:
Here's some example code I posed at d.o showing how to communicate between two Drupal 6 sites using Services 2.2 thru 2.4, & the XMLRPC server:
you'll want to examine the "send()" routine, which is used to call any xmlrpc method. The example code uses the Drupal API, rather than cURL, as you are attempting to use. However, the key logic you'll want to see is the "send()" routine, which is the handling & packaging of the method arguments before calling the remote method. Your code you show below is incorrect for XMLRPC parameter packaging.
Additionally, as an aid for you to convert between the logic I give above and your attempts to use cURL, I have another post at g.o showing how to communicate with a Services 3.0 REST remote API - with two examples: one using cURL and one using the Drupal API. Granted, my second example is for a REST server in Services 3.0, but it demonstrates the cURL handling - you'll just need to translate the first code example's packaging of the method parameters for XMLRPC transport.
I've written several times over the years on how to use this module, the last time using an application key that is only good from a given domain: "Accessing a Drupal xmlrpc server using api key and session id from php - a working example you can actually use": http://awebfactory.com.ar/node/434 <http://awebfactory.com.ar/node/434>The login service also works. Victor Kane http://awebfactory.com.ar http://projectflowandtracker On Sat, Mar 5, 2011 at 1:32 AM, <jeff@ayendesigns.com> wrote:
Blake, thanks very much for pointing me at these two examples. So, my first question is regarding the packaging of the parameters. In my case, there will be no authentication. How does that affect the creation of a hash, etc.?
Jeff
On 03/04/2011 06:42 PM, Blake Senftner wrote:
Here's some example code I posed at d.o showing how to communicate between two Drupal 6 sites using Services 2.2 thru 2.4, & the XMLRPC server:
you'll want to examine the "send()" routine, which is used to call any xmlrpc method. The example code uses the Drupal API, rather than cURL, as you are attempting to use. However, the key logic you'll want to see is the "send()" routine, which is the handling & packaging of the method arguments before calling the remote method. Your code you show below is incorrect for XMLRPC parameter packaging.
Additionally, as an aid for you to convert between the logic I give above and your attempts to use cURL, I have another post at g.o showing how to communicate with a Services 3.0 REST remote API - with two examples: one using cURL and one using the Drupal API. Granted, my second example is for a REST server in Services 3.0, but it demonstrates the cURL handling - you'll just need to translate the first code example's packaging of the method parameters for XMLRPC transport.
Hi Victor. I did see that one earlier on, but I still question what I need to do to resolve inside the code that in the case of this server the incoming request will not be using authentication, so there won't be an application/api key needed, no specific domain, etc. Jeff On 03/05/2011 03:04 AM, Victor Kane wrote:
I've written several times over the years on how to use this module, the last time using an application key that is only good from a given domain: "Accessing a Drupal xmlrpc server using api key and session id from php - a working example you can actually use":
http://awebfactory.com.ar/node/434
The login service also works.
Victor Kane http://awebfactory.com.ar http://projectflowandtracker
Hi Jeff, The code can easily be adapted to not using the app key, the difference in the parameter signature is clear in the services test page. Doesn't this Drupal handbook page (http://drupal.org/node/816934) help? On Sat, Mar 5, 2011 at 9:00 AM, <jeff@ayendesigns.com> wrote:
Hi Victor. I did see that one earlier on, but I still question what I need to do to resolve inside the code that in the case of this server the incoming request will not be using authentication, so there won't be an application/api key needed, no specific domain, etc.
Jeff
On 03/05/2011 03:04 AM, Victor Kane wrote:
I've written several times over the years on how to use this module, the last time using an application key that is only good from a given domain: "Accessing a Drupal xmlrpc server using api key and session id from php - a working example you can actually use":
http://awebfactory.com.ar/node/434
The login service also works.
Victor Kane http://awebfactory.com.ar http://projectflowandtracker
Jeff, Take a look at this d.o page: http://drupal.org/node/816934 It shows example XMLRPC code for Services 6.x-2.0 (which predates the 6.x-2.2 rewrite) using both with and without API keys. (The example code showing logic with API key authentication is a comment at the bottom.) Perhaps this will provide the comparison info you seek to learn how your parameters need to be handled without authentication. Sincerely, -Blake bsenftner@earthlink.net www.BlakeSenftner.com www.MissingUbercartManual.com On Mar 4, 2011, at 8:32 PM, jeff@ayendesigns.com wrote:
Blake, thanks very much for pointing me at these two examples. So, my first question is regarding the packaging of the parameters. In my case, there will be no authentication. How does that affect the creation of a hash, etc.?
Jeff
On 03/04/2011 06:42 PM, Blake Senftner wrote:
Here's some example code I posed at d.o showing how to communicate between two Drupal 6 sites using Services 2.2 thru 2.4, & the XMLRPC server:
you'll want to examine the "send()" routine, which is used to call any xmlrpc method. The example code uses the Drupal API, rather than cURL, as you are attempting to use. However, the key logic you'll want to see is the "send()" routine, which is the handling & packaging of the method arguments before calling the remote method. Your code you show below is incorrect for XMLRPC parameter packaging.
Additionally, as an aid for you to convert between the logic I give above and your attempts to use cURL, I have another post at g.o showing how to communicate with a Services 3.0 REST remote API - with two examples: one using cURL and one using the Drupal API. Granted, my second example is for a REST server in Services 3.0, but it demonstrates the cURL handling - you'll just need to translate the first code example's packaging of the method parameters for XMLRPC transport.
Hi Victor and Blake. Thanks for the link! Had a time-warp weekend rescuing a crashed dev environment (magic sysrq keys leaves much to be desired), but am trying it this morning! On 03/05/2011 10:37 AM, Victor Kane wrote: The code can easily be adapted to not using the app key, the difference in the parameter signature is clear in the services test page. Doesn't this Drupal handbook page (http://drupal.org/node/816934) help? On 03/05/2011 09:49 AM, Blake Senftner wrote:
Jeff,
Take a look at this d.o page:
It shows example XMLRPC code for Services 6.x-2.0 (which predates the 6.x-2.2 rewrite) using both with and without API keys. (The example code showing logic with API key authentication is a comment at the bottom.) Perhaps this will provide the comparison info you seek to learn how your parameters need to be handled without authentication.
I downloaded and installed xmlrpc.inc, and looked at the example in the node below. It wasn't evident how to handle multiple method parameters and a type other than int on a parameter, or why the url was broken into two parts. So I read the class docs (surprise!) and assembled the code below. There are a couple different forms given in the docs for each call, so I used the simpler version for a couple. When I hit the service url from the browser, I get 'xml-rpc accepts POST request only' as I should, the point being that it responds. When I execute the code below, it ends up timing out with the error being KO. Error: Connect error: A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond. (10060) <?php // Load the XML-RPC for PHP library from wherever you've put it // File path relative to the Drupal root require_once("./www/sites/all/libraries/xmlrpc/xmlrpc.inc"); // Create an XMLRPC message $m = new xmlrpcmsg('video.transcribe', array( new xmlrpcval("12345", "int"), new xmlrpcval("hello world", "string") ) ); // Create a connection to the remote server $c = new xmlrpc_client('http://localhost/www/services/xmlrpc'); $c->return_type = 'phpvals'; // Send the message to the remote server and get the response $r = $c->send($m); if ($r->faultCode()) echo 'KO. Error: '.$r->faultString(); else print '<pre>' . print_r($r->value(),1) . '</pre>'; ?>
On 03/05/2011 10:37 AM, Victor Kane wrote:
The code can easily be adapted to not using the app key, the difference in the parameter signature is clear in the services test page.
Doesn't this Drupal handbook page (http://drupal.org/node/816934) help?
On 03/05/2011 09:49 AM, Blake Senftner wrote:
Jeff,
Take a look at this d.o page:
It shows example XMLRPC code for Services 6.x-2.0 (which predates the 6.x-2.2 rewrite) using both with and without API keys. (The example code showing logic with API key authentication is a comment at the bottom.) Perhaps this will provide the comparison info you seek to learn how your parameters need to be handled without authentication.
Maybe this will help. I recently launched http://projectflowandtracker.com/ (on Pantheon, yay!) in alpha (beta will come with jquery enhanced usability improvements) and was working on an everything in code basis; so... I had to import from the legacy site all the projects, user stories, etc. for the 150-200 folks who had been using the previous version. I opted to use services on the legacy site, and did not use the authentication key, but opted for user login instead, bringing the stuff over to the new site using the Drupal API http://api.drupal.org/api/drupal/includes--common.inc/function/xmlrpc/6 which does not need to be downloaded or required. /* * client code for use with Services 6.x-2.4 * with following modules enabled on server, and following server config: * Key Authentication, XMLRPC Server, Node Service, System Service, User Service, Views Service * with no special permissions for anonymous on server * Key Authentication is chosen at Site building > Services > Settings * but Use ssid selected, Use keys de-selected */ $server = 'http://legacy.projectflowandtracker.com/services/xmlrpc'; $anon_session = xmlrpc($server, 'system.connect'); // login as... // Use anon session id to login with authentication $user = 'the_user'; $password = 'the_password'; $authenticated_session = xmlrpc($server, 'user.login', $anon_session['sessid'], $user, $password); if (xmlrpc_error()) { $error_num = xmlrpc_errno(); $error = xmlrpc_error(); print_r ($error); } /*********** code just to bring a single node ****************/ $xmlrpc_result = xmlrpc($server, 'node.get', $authenticated_session['sessid'], 2); if (xmlrpc_error()) { $error_num = xmlrpc_errno(); $error = xmlrpc_error(); print_r ($error); } print '<pre>' . print_r($xmlrpc_result, TRUE) . '</pre>'; This worked for me. Victor Kane http://awebfactory.com.ar http://projectflowandtracker.com
Victor, two questions regarding this (for now). Where does another server sending the request get a session id to send? And in this example, and really every one I've seen, a standard method is being used (node.get in this one), but I'm wondering if part of the issue is that I'm defining a method in my module as opposed to using one packaged with the services module. In my case, I'm receiving data, and if its id matches a cck value in a content type I take the data and update a field in the node with it, if not, I put the data into a holding queue until there -is- a node with the id being matched by the cck field. On 03/07/2011 04:14 PM, Victor Kane wrote:
Maybe this will help. I recently launched http://projectflowandtracker.com/ (on Pantheon, yay!) in alpha (beta will come with jquery enhanced usability improvements) and was working on an everything in code basis; so... I had to import from the legacy site all the projects, user stories, etc. for the 150-200 folks who had been using the previous version.
I opted to use services on the legacy site, and did not use the authentication key, but opted for user login instead, bringing the stuff over to the new site using the Drupal API http://api.drupal.org/api/drupal/includes--common.inc/function/xmlrpc/6 which does not need to be downloaded or required.
/* * client code for use with Services 6.x-2.4 * with following modules enabled on server, and following server config: * Key Authentication, XMLRPC Server, Node Service, System Service, User Service, Views Service * with no special permissions for anonymous on server * Key Authentication is chosen at Site building > Services > Settings * but Use ssid selected, Use keys de-selected */
$server = 'http://legacy.projectflowandtracker.com/services/xmlrpc';
$anon_session = xmlrpc($server, 'system.connect');
// login as... // Use anon session id to login with authentication $user = 'the_user'; $password = 'the_password'; $authenticated_session = xmlrpc($server, 'user.login', $anon_session['sessid'], $user, $password); if (xmlrpc_error()) { $error_num = xmlrpc_errno(); $error = xmlrpc_error(); print_r ($error); }
/*********** code just to bring a single node ****************/ $xmlrpc_result = xmlrpc($server, 'node.get', $authenticated_session['sessid'], 2); if (xmlrpc_error()) { $error_num = xmlrpc_errno(); $error = xmlrpc_error(); print_r ($error); } print '<pre>' . print_r($xmlrpc_result, TRUE) . '</pre>';
This worked for me.
Victor Kane http://awebfactory.com.ar http://projectflowandtracker.com
On Mon, Mar 7, 2011 at 6:40 PM, <jeff@ayendesigns.com> wrote:
Victor, two questions regarding this (for now). Where does another server sending the request get a session id to send?
Second line: $anon_session = xmlrpc($server, 'system.connect'); This is then reused in the login request: $authenticated_session = xmlrpc($server, 'user.login', $anon_session['sessid'], $user, $password);
And in this example, and really every one I've seen, a standard method is being used (node.get in this one), but I'm wondering if part of the issue is that I'm defining a method in my module as opposed to using one packaged with the services module.
That's fine. I did the same thing recently, for example uploading performance times to a performance content type. I copied the closest existing service module into my own module and edited it. That way, I had my own custom service written as part of services. For a bare-bones xmlprc example using Drupal functions without the services module, check out my 2007 article leveraging hook_xmlrpc: http://awebfactory.com.ar/node/234 This gets it done. Either way, your own code can implement the logic you describe. Victor
In my case, I'm receiving data, and if its id matches a cck value in a content type I take the data and update a field in the node with it, if not, I put the data into a holding queue until there -is- a node with the id being matched by the cck field.
On 03/07/2011 04:14 PM, Victor Kane wrote:
Maybe this will help. I recently launched http://projectflowandtracker.com/ (on Pantheon, yay!) in alpha (beta will come with jquery enhanced usability improvements) and was working on an everything in code basis; so... I had to import from the legacy site all the projects, user stories, etc. for the 150-200 folks who had been using the previous version.
I opted to use services on the legacy site, and did not use the authentication key, but opted for user login instead, bringing the stuff over to the new site using the Drupal API http://api.drupal.org/api/drupal/includes--common.inc/function/xmlrpc/6 which does not need to be downloaded or required.
/* * client code for use with Services 6.x-2.4 * with following modules enabled on server, and following server config: * Key Authentication, XMLRPC Server, Node Service, System Service, User Service, Views Service * with no special permissions for anonymous on server * Key Authentication is chosen at Site building > Services > Settings * but Use ssid selected, Use keys de-selected */
$server = 'http://legacy.projectflowandtracker.com/services/xmlrpc';
$anon_session = xmlrpc($server, 'system.connect');
// login as... // Use anon session id to login with authentication $user = 'the_user'; $password = 'the_password'; $authenticated_session = xmlrpc($server, 'user.login', $anon_session['sessid'], $user, $password); if (xmlrpc_error()) { $error_num = xmlrpc_errno(); $error = xmlrpc_error(); print_r ($error); }
/*********** code just to bring a single node ****************/ $xmlrpc_result = xmlrpc($server, 'node.get', $authenticated_session['sessid'], 2); if (xmlrpc_error()) { $error_num = xmlrpc_errno(); $error = xmlrpc_error(); print_r ($error); } print '<pre>' . print_r($xmlrpc_result, TRUE) . '</pre>';
This worked for me.
Victor Kane http://awebfactory.com.ar http://projectflowandtracker.com
On 4 Mar 2011 22h30 WET, jeff@ayendesigns.com wrote:
[1 <text/plain; ISO-8859-1 (8bit)>] After hours of searching, scouring, absorbing it was determined that there was little hope of (currently) getting past Services 2.4 and REST returning a 404 error, so I switched to xmlrpc.
I have a simple script to hit my service from outside the site, fine-tuned a couple dozen times based on various recommendations, to currently be:
$url = "http://localhost/mydomain/services/xmlrpc"; $ch = curl_init(); $data = 'method=my.method&id=12345&text=hello'; curl_setopt($ch, CURLOPT_POST, 1); curl_setopt($ch, CURLOPT_POSTFIELDS, $data); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_URL, $url);
$response = curl_exec($ch);
with $data as a string like above, I continuously receive: faultCode -32700 faultString Parse error. Request not well formed.
Does it really need to be a POST? If not then a mere hook_menu that takes arguments might fit the bill. It all depends on exactly what you're trying to do and what level of security it's required. It's true that a GET can be considered insecure. But you can secure it using: 1. Access control based on IP address at the server and/or PHP/Drupal level. Please have your 2. Encrypt the arguments in the URI and decrypt in the server or page callback. 3. Use authentication, be it Basic or Digest. 4. Run the all shebang over TLS. a) If you use a self-signed cert no endpoint trust is ensured and one of the main design features of TLS is defeated. It only raises a little bit the bar against traffic sniffing. b) With a proper cert issued by a recognized CA (the most secure setup, with level of security depending on key length and cypher suite chosen). This might be a slightly OT rant, but perhaps it points you to a easier way to achieve your purpose. Also there are much less verbose ways to do HTTP on PHP than cURL, e.g.: http://pecl.php.net/package/pecl_http http://stackoverflow.com/questions/2075570/php-pecl-http-vs-curl-extension HTH, --- appa
Well, 'need to' would be a more subjective answer :) but the requirement is that it be a Services 2.x service (thus, since I've given up on REST for the time, xmlrpc), which means post. I'm not so concerned about the curl in terms of verbosity...I'm only using it to test the service, well, -try- to test the service. At the moment, I'm stuck on the proper way to format the post request in curl when no authentication will be used. On 03/05/2011 07:31 AM, António P. P. Almeida wrote:
Does it really need to be a POST? If not then a mere hook_menu that takes arguments might fit the bill.
It all depends on exactly what you're trying to do and what level of security it's required.
It's true that a GET can be considered insecure. But you can secure it using:
1. Access control based on IP address at the server and/or PHP/Drupal level. Please have your
2. Encrypt the arguments in the URI and decrypt in the server or page callback.
3. Use authentication, be it Basic or Digest.
4. Run the all shebang over TLS.
a) If you use a self-signed cert no endpoint trust is ensured and one of the main design features of TLS is defeated. It only raises a little bit the bar against traffic sniffing.
b) With a proper cert issued by a recognized CA (the most secure setup, with level of security depending on key length and cypher suite chosen).
This might be a slightly OT rant, but perhaps it points you to a easier way to achieve your purpose.
Also there are much less verbose ways to do HTTP on PHP than cURL, e.g.:
http://pecl.php.net/package/pecl_http http://stackoverflow.com/questions/2075570/php-pecl-http-vs-curl-extension
HTH, --- appa
Generally either get or post can be used, but get restricts the size of the data, since it reallyneeds to fit on a url. Post data in a reqest is not much different than get data, that is, in its simplest form, it is just a series of urlencoded key value pairs. Sent from my iPad On Mar 5, 2011, at 4:55 AM, jeff@ayendesigns.com wrote:
Well, 'need to' would be a more subjective answer :) but the requirement is that it be a Services 2.x service (thus, since I've given up on REST for the time, xmlrpc), which means post. I'm not so concerned about the curl in terms of verbosity...I'm only using it to test the service, well, -try- to test the service. At the moment, I'm stuck on the proper way to format the post request in curl when no authentication will be used.
On 03/05/2011 07:31 AM, António P. P. Almeida wrote:
Does it really need to be a POST? If not then a mere hook_menu that takes arguments might fit the bill.
It all depends on exactly what you're trying to do and what level of security it's required.
It's true that a GET can be considered insecure. But you can secure it using:
1. Access control based on IP address at the server and/or PHP/Drupal level. Please have your
2. Encrypt the arguments in the URI and decrypt in the server or page callback.
3. Use authentication, be it Basic or Digest.
4. Run the all shebang over TLS.
a) If you use a self-signed cert no endpoint trust is ensured and one of the main design features of TLS is defeated. It only raises a little bit the bar against traffic sniffing.
b) With a proper cert issued by a recognized CA (the most secure setup, with level of security depending on key length and cypher suite chosen).
This might be a slightly OT rant, but perhaps it points you to a easier way to achieve your purpose.
Also there are much less verbose ways to do HTTP on PHP than cURL, e.g.:
http://pecl.php.net/package/pecl_http http://stackoverflow.com/questions/2075570/php-pecl-http-vs-curl-extension
HTH, --- appa
participants (5)
-
António P. P. Almeida -
Blake Senftner -
Dave Metzler -
jeff@ayendesigns.com -
Victor Kane