Changeset 4494

Show
Ignore:
Timestamp:
10/14/08 06:09:35 (1 month ago)
Author:
coling
Message:

Make it work with Zendesk Restful API. It currently only supports PUT... it should work generically with other Restful APIs as all the specific stuff is done in the XSLT, but the code is very specific to how things work with zendesk....

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • clientsplugin/0.11/clients/action_zendesk_forum.py

    r4492 r4494  
    105105    host, port, path = parseuri(uri) 
    106106 
    107     redirect = set([301, 302, 307]) 
    108     authenticate = set([401]) 
    109107    okay = set([200, 201, 204]) 
    110108 
    111     authorized = False 
    112     authorization = None 
    113     tries = 0 
    114     verbose = True 
     109    import base64 
     110    userpass = username + ':' + password 
     111    userpass = base64.encodestring(userpass).strip() 
     112    authorization = 'Basic ' + userpass 
    115113 
    116     while True:  
    117       # Attempt to HTTP PUT the data 
    118       h = httplib.HTTPConnection(host, port) 
     114    # Attempt to HTTP PUT the data 
     115    h = httplib.HTTPConnection(host, port) 
    119116 
    120       h.putrequest('PUT', path) 
     117    data = str(result) 
     118    h.putrequest('PUT', path) 
    121119 
    122       h.putheader('User-Agent', 'Trac/1.0') 
    123       h.putheader('Connection', 'keep-alive') 
    124       h.putheader('Transfer-Encoding', 'chunked') 
    125       h.putheader('Expect', '100-continue') 
    126       h.putheader('Accept', 'application/xml') 
    127       h.putheader('Content-Type', 'text/xml') 
    128       h.putheader('Content-Length', len(str(result))) 
    129       if authorization:  
    130          h.putheader('Authorization', authorization) 
    131       h.endheaders() 
     120    h.putheader('User-Agent', 'Trac/1.0') 
     121    h.putheader('Accept', 'application/xml') 
     122    h.putheader('Content-Type', 'text/xml') 
     123    h.putheader('Authorization', authorization) 
     124    h.putheader('Content-Length', len(data)) 
     125    h.endheaders() 
    132126 
    133       # Chunked transfer encoding 
    134       # Cf. 'All HTTP/1.1 applications MUST be able to receive and  
    135       # decode the "chunked" transfer-coding' 
    136       # - http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html 
    137       while True:  
    138          #bytes = f.read(2048) 
    139          bytes = str(result) 
    140          if not bytes: break 
     127    h.send(str(data)) 
    141128 
    142          length = len(bytes) 
    143          h.send('%X\r\n' % length) 
    144          h.send(bytes + '\r\n') 
    145          break 
    146       h.send('0\r\n\r\n') 
     129    resp = h.getresponse() 
     130    status = resp.status # an int 
    147131 
    148       resp = h.getresponse() 
    149       status = resp.status # an int 
     132    # Got a response, now decide how to act upon it 
     133    if status not in okay:  
     134      print 'Got "%s %s"' % (status, resp.reason) 
     135      return False 
    150136 
    151       # Got a response, now decide how to act upon it 
    152       if status in redirect:  
    153          location = resp.getheader('Location') 
    154          uri = urlparse.urljoin(uri, location) 
    155          host, port, path = parseuri(uri) 
    156  
    157          # We may have to authenticate again 
    158          if authorization:  
    159             authorization = None 
    160  
    161       elif status in authenticate:  
    162          # If we've done this already, break 
    163          if authorization:  
    164             # barf("Going around in authentication circles") 
    165             print "Authentication failed" 
    166             return False 
    167  
    168          if not (username and password):  
    169             print "Need a username and password to authenticate with" 
    170             return False 
    171  
    172          # Get the scheme: Basic or Digest? 
    173          wwwauth = resp.msg['www-authenticate'] # We may need this again 
    174          wauth = wwwauth.lstrip(' \t') # Hence use wauth not wwwauth here 
    175          wauth = wwwauth.replace('\t', ' ') 
    176          i = wauth.index(' ') 
    177          scheme = wauth[:i].lower() 
    178  
    179          if scheme in set(['basic', 'digest']):  
    180             if verbose:  
    181                msg = "Performing %s Authentication..." % scheme.capitalize() 
    182                print >> sys.stderr, msg 
    183          else: 
    184             print "Unknown authentication scheme: %s" % scheme 
    185             return False 
    186  
    187          if scheme == 'basic':  
    188             import base64 
    189             userpass = username + ':' + password 
    190             userpass = base64.encodestring(userpass).strip() 
    191             authorized, authorization = True, 'Basic ' + userpass 
    192  
    193          elif scheme == 'digest':  
    194             if verbose:  
    195                msg = "uses fragile, undocumented features in urllib2" 
    196                print >> sys.stderr, "Warning! Digest Auth %s" % msg 
    197  
    198             import urllib2 # See warning above 
    199  
    200             passwd = type('Password', (object,), { 
    201                'find_user_password': lambda self, *args: (username, password),  
    202                'add_password': lambda self, *args: None 
    203             })() 
    204  
    205             xreq = type('Request', (object,), {  
    206                'get_full_url': lambda self: uri,  
    207                'has_data': lambda self: None,  
    208                'get_method': lambda self: 'PUT',  
    209                'get_selector': lambda self: path 
    210             })() 
    211  
    212             # Cf. urllib2.AbstractDigestAuthHandler.retry_http_digest_auth 
    213             auth = urllib2.AbstractDigestAuthHandler(passwd) 
    214             token, challenge = wwwauth.split(' ', 1) 
    215             chal = urllib2.parse_keqv_list(urllib2.parse_http_list(challenge)) 
    216             userpass = auth.get_authorization(xreq, chal) 
    217             authorized, authorization = True, 'Digest ' + userpass 
    218  
    219       elif status in okay:  
    220          if (username and password) and (not authorized):  
    221             msg = "Warning! The supplied username and password went unused" 
    222             print >> sys.stderr, msg 
    223  
    224          if verbose:  
    225             resultLine = "Success! Resource %s" 
    226             statuses = {200: 'modified', 201: 'created', 204: 'modified'} 
    227             print resultLine % statuses[status] 
    228  
    229             statusLine = "Response-Status: %s %s" 
    230             print statusLine % (status, resp.reason) 
    231  
    232             body = resp.read(58) 
    233             body = body.rstrip('\r\n') 
    234             body = body.encode('string_escape') 
    235  
    236             if len(body) >= 58:  
    237                body = body[:57] + '[...]' 
    238  
    239             bodyLine = 'Response-Body: "%s"' 
    240             print bodyLine % body 
    241          break 
    242  
    243       # @@ raise PutError, do the catching in main? 
    244       else:  
    245         print 'Got "%s %s"' % (status, resp.reason) 
    246         return False 
    247  
    248       tries += 1 
    249       if tries >= 50:  
    250          print "Too many redirects" 
    251          return False 
    252  
    253     print str(result) 
    254137    return True