blob: 50269785c6b63de978c47efb252420e119544ad2 [file] [log] [blame]
Mark Slee89e2bb82007-03-01 00:20:36 +00001#
David Reissea2cba82009-03-30 21:35:00 +00002# Licensed to the Apache Software Foundation (ASF) under one
3# or more contributor license agreements. See the NOTICE file
4# distributed with this work for additional information
5# regarding copyright ownership. The ASF licenses this file
6# to you under the Apache License, Version 2.0 (the
7# "License"); you may not use this file except in compliance
8# with the License. You may obtain a copy of the License at
9#
10# http://www.apache.org/licenses/LICENSE-2.0
11#
12# Unless required by applicable law or agreed to in writing,
13# software distributed under the License is distributed on an
14# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15# KIND, either express or implied. See the License for the
16# specific language governing permissions and limitations
17# under the License.
18#
Mark Slee89e2bb82007-03-01 00:20:36 +000019
Mark Sleebd8b9912007-02-27 20:17:00 +000020from TTransport import *
21from cStringIO import StringIO
22
David Reiss2aa28902009-03-26 06:22:18 +000023import urlparse
Mark Sleebd8b9912007-02-27 20:17:00 +000024import httplib
David Reiss2aa28902009-03-26 06:22:18 +000025import warnings
David Reissff3d2492010-03-09 05:19:16 +000026import socket
Mark Sleebd8b9912007-02-27 20:17:00 +000027
28class THttpClient(TTransportBase):
29
30 """Http implementation of TTransport base."""
31
David Reiss2aa28902009-03-26 06:22:18 +000032 def __init__(self, uri_or_host, port=None, path=None):
33 """THttpClient supports two different types constructor parameters.
34
35 THttpClient(host, port, path) - deprecated
36 THttpClient(uri)
37
38 Only the second supports https."""
39
40 if port is not None:
41 warnings.warn("Please use the THttpClient('http://host:port/path') syntax", DeprecationWarning, stacklevel=2)
42 self.host = uri_or_host
43 self.port = port
44 assert path
45 self.path = path
46 self.scheme = 'http'
47 else:
48 parsed = urlparse.urlparse(uri_or_host)
49 self.scheme = parsed.scheme
50 assert self.scheme in ('http', 'https')
51 if self.scheme == 'http':
52 self.port = parsed.port or httplib.HTTP_PORT
53 elif self.scheme == 'https':
54 self.port = parsed.port or httplib.HTTPS_PORT
55 self.host = parsed.hostname
56 self.path = parsed.path
Bryan Duxbury727d67d2010-09-02 01:00:19 +000057 if parsed.query:
58 self.path += '?%s' % parsed.query
Mark Sleebd8b9912007-02-27 20:17:00 +000059 self.__wbuf = StringIO()
60 self.__http = None
David Reissff3d2492010-03-09 05:19:16 +000061 self.__timeout = None
Mark Sleebd8b9912007-02-27 20:17:00 +000062
63 def open(self):
David Reiss2aa28902009-03-26 06:22:18 +000064 if self.scheme == 'http':
65 self.__http = httplib.HTTP(self.host, self.port)
66 else:
67 self.__http = httplib.HTTPS(self.host, self.port)
Mark Sleebd8b9912007-02-27 20:17:00 +000068
69 def close(self):
70 self.__http.close()
71 self.__http = None
David Reiss0c90f6f2008-02-06 22:18:40 +000072
Mark Sleebd8b9912007-02-27 20:17:00 +000073 def isOpen(self):
74 return self.__http != None
75
David Reissff3d2492010-03-09 05:19:16 +000076 def setTimeout(self, ms):
77 if not hasattr(socket, 'getdefaulttimeout'):
78 raise NotImplementedError
79
80 if ms is None:
81 self.__timeout = None
82 else:
83 self.__timeout = ms/1000.0
84
Mark Sleebd8b9912007-02-27 20:17:00 +000085 def read(self, sz):
86 return self.__http.file.read(sz)
87
88 def write(self, buf):
89 self.__wbuf.write(buf)
90
David Reissff3d2492010-03-09 05:19:16 +000091 def __withTimeout(f):
92 def _f(*args, **kwargs):
93 orig_timeout = socket.getdefaulttimeout()
94 socket.setdefaulttimeout(args[0].__timeout)
95 result = f(*args, **kwargs)
96 socket.setdefaulttimeout(orig_timeout)
97 return result
98 return _f
99
Mark Sleebd8b9912007-02-27 20:17:00 +0000100 def flush(self):
David Reiss7c1f6f82009-03-24 20:10:24 +0000101 if self.isOpen():
102 self.close()
103 self.open();
104
Mark Sleebd8b9912007-02-27 20:17:00 +0000105 # Pull data out of buffer
106 data = self.__wbuf.getvalue()
107 self.__wbuf = StringIO()
108
109 # HTTP request
David Reiss2aa28902009-03-26 06:22:18 +0000110 self.__http.putrequest('POST', self.path)
Mark Sleebd8b9912007-02-27 20:17:00 +0000111
112 # Write headers
113 self.__http.putheader('Host', self.host)
114 self.__http.putheader('Content-Type', 'application/x-thrift')
115 self.__http.putheader('Content-Length', str(len(data)))
116 self.__http.endheaders()
117
118 # Write payload
119 self.__http.send(data)
120
121 # Get reply to flush the request
122 self.code, self.message, self.headers = self.__http.getreply()
David Reissff3d2492010-03-09 05:19:16 +0000123
124 # Decorate if we know how to timeout
125 if hasattr(socket, 'getdefaulttimeout'):
126 flush = __withTimeout(flush)