Hello,

I am looking to sync particular types of nodes between one site with 8 sub-sites. I realize you can use Domain Access, but these subsites are run by different organizations who require different functions and the only thing they need are particular node types (which they can't edit or create, it comes down from above basically). Once a day, I would like to sync these nodes into the other websites.

So, I have turned on Services module, and I can go into the admin and see that if I click on node.get, and enter a node ID, it returns all the information. My question is where are there code examples or tutorials of how to actually implement Services in your own module so that you can talk to the other servers? I haven't found any solid information on how to do this.

I've exhausted trying to make Feeds import data with CCK fields...

I am very new to Services but know that I can get this working if someone could point me in the right direction.

Comments

kevinquillen’s picture

As a test, I tried node.get:


function test_init() {
	$node = xmlrpc('http://localhost/services/xmlrpc', 'node.get', 2, 'nid,title');
	var_dump($node);exit;
}

The response was null.

kevinquillen’s picture

Okay, got it. Forgot to wrap fields with array().

If anyone is curious as to how to expand on Services with custom methods I wrote a quick blog post of what I've been working on for a project.

http://www.delawarewebdesigner.com/tech-stuff/sync-drupal-content-using-...

I know the authentication method there is no good- can anyone point me to a good example/tutorial of basic authentication for Services? I only need 1 account/role to perform the requests.

kevinquillen’s picture

Title: Exposing Nodes for Retrieval from a sister site » Basic Drupal to Drupal User Authentication?
gdd’s picture

There is a tutorial on how to do this in the handbook

http://drupal.org/node/394364

Although it is slightly out of date. You have to enabled the Key Authentication module in admin/build/modules for this to work.

Also have you looked into the Deploy module? It was made to synch content between servers. You may find it useful, although it also looks like it may be overkill for you.

kevinquillen’s picture

Yeah, Deploy worked for exporting a content type. When I tried to do it for a node, it gave me 'Success'- but nothing happened on the receiving end. No watchdog log or apache log either. I couldn't figure it out. Thanks for the link.

kevinquillen’s picture

I see. Is this for Anonymous users only? I was watching a deployment screencast and they were using a special user/role to do this instead of Anonymous.

If you created the same user on two sites, how could you tell that the user requesting a service is the same user on the other website? Thats where I was scratching my head and thought well if there is no return response, or access denied, user name mismatch, then it couldbe good enough... but I want to be sure so we don't open a security hole.

gdd’s picture

No this is not for anonymous users only, you can definitely use this for all users. You have to call system.connect first to get an anonymous user's session, then use that session to pass into user.login, which returns your 'real' session.

The problem is that the login process has a check to see if you already have an existing session. This works on Drupal sites through the browser, because even anonymous users get sessions on their first hit. In the Services area we have to simulate this by first getting an anonymous session, then passing that information to the user.login service.

The code sample just retrieves the anonymous user's information from user.get because the code sample has to be generic, and that user is present on every Drupal site.

Make sense?

kevinquillen’s picture

So ok, first I would do system.connect locally, user.login with my local user, get that session and send that to the remote server with user.login?

kevinquillen’s picture

Here is what I tried:


$user = 'services';
	$password = 'services';
	$xmlrpc_url = 'http://www.remotesite.com/services/xmlrpc';
	$anon_session = xmlrpc($xmlrpc_url, 'system.connect');
	
	$authenticated_session = xmlrpc($xmlrpc_url, 'user.login', $anon_session['sessid'], $user, $password);
	$xmlrpc_result = xmlrpc($xmlrpc_url, 'user.get', $authenticated_session['sessid'], 0);

	if ($xmlrpc_result === FALSE) {
  print '<pre>' . print_r(xmlrpc_error(), TRUE) . '<pre>';
}

The user exists on the local and remote site.
else {
  print '<pre>' . print_r($xmlrpc_result, TRUE) . '<pre>';
}
exit;

I get:

stdClass Object
(
    [is_error] => 1
    [code] => 1
    [message] => There is no user with such ID.
)
gdd’s picture

Are you using XMLRPC on the remote server or some other server? At a glance that code looks correct to me.

marcingy’s picture

Have you tried this with UID 1 as in certain edge cases uid 0 can disappear!!

gdd’s picture

Also can you go look in your user table and see if uid 0 exists? There are some weird edge cases where uid 0 can get changed to another value. The error code you got indicates that the authentication part of this code worked, just the call to user.get failed because the remote user couldn't be found. To verify this you could try

$xmlrpc_result = xmlrpc($xmlrpc_url, 'user.get', $authenticated_session['sessid'], 1);

instead

kevinquillen’s picture

Another site on the same server. UID 0 does exist.

kevinquillen’s picture

Looks like user.login and user.get only accept username/password and uid as fields, how does it know how to handle the session ID if you pass that in?

kevinquillen’s picture

Gotcha. Needed to enable sessid under Settings- I thought I had done that. Now I don't get 'There is no user with such ID.'- I can use user.get on any user.

This way, I can be sure I am requesting based on authenticated session id right? I see that sessid is now required for all methods.

gdd’s picture

Status: Active » Fixed

Yes that should be correct. You should test with various combinations of permissions to make sure it is working as you expect.

Glad you got this sorted out!

Status: Fixed » Closed (fixed)

Automatically closed -- issue fixed for 2 weeks with no activity.