Services 3.0 Python example using XML-RPC and OAuth2
Last updated on
30 April 2025
You are browsing documentation for an older version of Drupal, which is not supported any longer, and the information may not be correct. See current documentation for Contributed modules
This code connects using two-legged OAuth to a drupal host running services-3.x, OAuth and an XMLRPC endpoint. This example uses two different ways to connect - one using xmlrpclib, one not. It could probably be easily adapted for python-oauth instead of oauth2.
# Note, am using two-legged auth here.
# needs http://drupal.org/node/1336974 for two-legged and http://drupal.org/node/1337718 if using a nonstandard port.
#
# there's a couple of approaches here. One uses xmlrpclib, one doesn't. Both use oauth2 - but could probably be worked with oauth
#
# services_endpoint needs to be something like (serialiazed as I've pulled it from database and there's no form yet):
# a:1:{s:14:"services_oauth";a:3:{s:13:"oauth_context";s:n:"CONTEXT GOES HERE";s:11:"credentials";s:8:"consumer";s:13:"authorization";s:n:"DEFAULT SECURITY LEVEL GOES HERE";}}
# Don't forget to fix for 'CONTEXT GOES HERE' and 'DEFAULT SECURITY LEVEL GOES HERE' (and fix 'n' to be the right number)
import oauth2
import time
import urllib2
import xmlrpclib
host_key = 'PUT A KEY HERE'
host_secret = 'PUT A SECRET HERE'
# this is the endpoint.
host = 'https://testserver:1081/endpoint'
class OAuthTransport(xmlrpclib.SafeTransport):
def __init__(self, host, verbose = None, use_datetime=0):
xmlrpclib.SafeTransport.__init__(self)
self.verbose = verbose
self._use_datetime = use_datetime
self.host = host
def oauth_request(self, url, moreparams={}, body=''):
params = {
'oauth_version': "1.0",
'oauth_nonce': oauth2.generate_nonce(),
'oauth_timestamp': int(time.time())
}
consumer = oauth2.Consumer(key=host_key,secret=host_secret)
params['oauth_consumer_key'] = consumer.key
params.update(moreparams)
req = oauth2.Request(method='POST', url=url, parameters=params, body=body)
signature_method = oauth2.SignatureMethod_HMAC_SHA1()
req.sign_request(signature_method, consumer, None)
return req
def single_request(self, host, handler, request_body, verbose=0):
if (verbose):
print(host)
print(handler)
print(request_body)
# the parameters call for host + handler - but they've dropped the method (eg:https)
request = self.oauth_request(url=self.host, body=request_body)
req = urllib2.Request(request.to_url())
req.add_header('Content-Type', 'text/xml')
req.add_data(request_body)
f = urllib2.urlopen(req)
return(self.parse_response(f))
def build_request(url, moreparams={}, body=''):
params = {
'oauth_version': "1.0",
'oauth_nonce': oauth2.generate_nonce(),
'oauth_timestamp': int(time.time())
}
consumer = oauth2.Consumer(key=host_key,secret=host_secret)
params['oauth_consumer_key'] = consumer.key
params.update(moreparams)
req = oauth2.Request(method='POST', url=url, parameters=params, body=body)
signature_method = oauth2.SignatureMethod_HMAC_SHA1()
req.sign_request(signature_method, consumer, None)
return req
trans = OAuthTransport(host)
server = xmlrpclib.ServerProxy(host, transport=trans)
if (1):
try:
for method in server.system.listMethods():
print method
# it would be really nice if introspection works. Currently it doesn't.
# print '\n'.join([' ' + x for x in server.system.methodHelp(method).split('\n')])
# print
except xmlrpclib.Fault, err:
print "A fault occurred"
print "Fault code: %d" % err.faultCode
print "Fault string: %s" % err.faultString
if (1):
req_body = '<methodCall><methodName>system.listMethods</methodName><params></params></methodCall>'
request = build_request(url=host, moreparams={}, body=req_body)
u = urllib2.urlopen(request.to_url(), req_body)
print u.readlines()
# note that it returns a lot of extra information. Suspect node.retrieve unfinished.
try:
print server.node.retrieve(3, ['nid','title'])
except xmlrpclib.Fault, err:
print "A fault occurred"
print "Fault code: %d" % err.faultCode
print "Fault string: %s" % err.faultString
req_body = '<methodCall><methodName>system.listMethods</methodName><params></params></methodCall>'
request = build_request(url=host, moreparams={}, body=req_body)
u = urllib2.urlopen(request.to_url(), req_body)
print u.readlines()
Help improve this page
Page status: Not set
You can:
You can:
- Log in, click Edit, and edit this page
- Log in, click Discuss, update the Page status value, and suggest an improvement
- Log in and create a Documentation issue with your suggestion