~mcfletch/+junk/restclient

« back to all changes in this revision

Viewing changes to restclient.py

  • Committer: Mike C. Fletcher
  • Date: 2008-12-15 04:24:39 UTC
  • Revision ID: mcfletch@vrplumber.com-20081215042439-oftazes45b3d9m7z
Initial creation of a rest client for turbogears applications

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
"""Web client for uploading files to Turbogears web "services" (regular controllers)"""    
 
2
from restclient.encodemultipart import build_request
 
3
import urllib2
 
4
 
 
5
class RESTClient( object ):
 
6
    """Encode a REST request (potentially including files) for upload to server"""
 
7
    cookies = ()
 
8
    def __init__( self, login_url, **named ):
 
9
        self.login_url = login_url 
 
10
        self.login_params = named 
 
11
    def login( self ):
 
12
        """Get our login cookie by attempting to load url
 
13
        
 
14
        named gives the login parameters (login-form only)
 
15
        """
 
16
        if self.cookies:
 
17
            return self.cookies
 
18
        # look for a set-cookie in the result and use that going forward...
 
19
        try:
 
20
            result = urllib2.urlopen(build_request(self.login_url, self.login_params, [] ))
 
21
        except Exception, err:
 
22
            # Turbogears returns a 403 by default... sigh
 
23
            headers = err.headers
 
24
        else:
 
25
            headers = result.info()
 
26
        if headers.has_key( 'set-cookie' ):
 
27
            cookie = headers['set-cookie']
 
28
            self.cookies = []
 
29
            for key in ('tg-visit','session_id'):
 
30
                if key in cookie:
 
31
                    cook = cookie[cookie.find( key):]
 
32
                    cook = cook.split( ';' )[0]
 
33
                    self.cookies.append( cook )
 
34
            return self.cookies
 
35
        raise RuntimeError( "Unable to retrieve cookie from server: %s"%(result,) )
 
36
    def call( self, url, **named ):
 
37
        """Call the given url with parameters in named
 
38
        
 
39
        Constructs a POST request and uses urllib2 to post to given url,
 
40
        if not self.cookies, will first log into the web-site.
 
41
        
 
42
        returns a response object that can be read to retrieve results
 
43
        """
 
44
        cookies = self.login()
 
45
        # add the json-return-value flag for turbogears
 
46
        fields,files = self.encode_request( **named ) 
 
47
        request = build_request( url, fields, files )
 
48
        request.add_header( 'Cookie', '; '.join( cookies) )
 
49
        result = urllib2.urlopen(request)
 
50
        return result
 
51
        
 
52
    def encode_request( self, **named ):
 
53
        """Encode the request parameters for HTTP communication"""
 
54
        fields = []
 
55
        files = []
 
56
        def simple( value ):
 
57
            if isinstance( value, (str,unicode,int,float,long)):
 
58
                return True
 
59
        def add_file( key, value ):
 
60
            filename,data = value 
 
61
            files.append( (key,filename,data) )
 
62
        for key,value in named.items():
 
63
            if isinstance( value, list):
 
64
                for item in value:
 
65
                    if simple( item ):
 
66
                        fields.append( (key, item) )
 
67
                    elif isinstance( item, tuple ):
 
68
                        add_file( key, item )
 
69
            elif simple( value ):
 
70
                fields.append( (key,value) )
 
71
            elif isinstance( value, tuple ):
 
72
                assert len(value) == 2, value # expected filename, data
 
73
                add_file( key, value )
 
74
        return fields, files