blob: 05ca53abbef6015bf4f7992a03f6e74d8ff6a08c [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
Mark Sleebd8b9912007-02-27 20:17:00 +000057 self.__wbuf = StringIO()
58 self.__http = None
David Reissff3d2492010-03-09 05:19:16 +000059 self.__timeout = None
Mark Sleebd8b9912007-02-27 20:17:00 +000060
61 def open(self):
David Reiss2aa28902009-03-26 06:22:18 +000062 if self.scheme == 'http':
63 self.__http = httplib.HTTP(self.host, self.port)
64 else:
65 self.__http = httplib.HTTPS(self.host, self.port)
Mark Sleebd8b9912007-02-27 20:17:00 +000066
67 def close(self):
68 self.__http.close()
69 self.__http = None
David Reiss0c90f6f2008-02-06 22:18:40 +000070
Mark Sleebd8b9912007-02-27 20:17:00 +000071 def isOpen(self):
72 return self.__http != None
73
David Reissff3d2492010-03-09 05:19:16 +000074 def setTimeout(self, ms):
75 if not hasattr(socket, 'getdefaulttimeout'):
76 raise NotImplementedError
77
78 if ms is None:
79 self.__timeout = None
80 else:
81 self.__timeout = ms/1000.0
82
Mark Sleebd8b9912007-02-27 20:17:00 +000083 def read(self, sz):
84 return self.__http.file.read(sz)
85
86 def write(self, buf):
87 self.__wbuf.write(buf)
88
David Reissff3d2492010-03-09 05:19:16 +000089 def __withTimeout(f):
90 def _f(*args, **kwargs):
91 orig_timeout = socket.getdefaulttimeout()
92 socket.setdefaulttimeout(args[0].__timeout)
93 result = f(*args, **kwargs)
94 socket.setdefaulttimeout(orig_timeout)
95 return result
96 return _f
97
Mark Sleebd8b9912007-02-27 20:17:00 +000098 def flush(self):
David Reiss7c1f6f82009-03-24 20:10:24 +000099 if self.isOpen():
100 self.close()
101 self.open();
102
Mark Sleebd8b9912007-02-27 20:17:00 +0000103 # Pull data out of buffer
104 data = self.__wbuf.getvalue()
105 self.__wbuf = StringIO()
106
107 # HTTP request
David Reiss2aa28902009-03-26 06:22:18 +0000108 self.__http.putrequest('POST', self.path)
Mark Sleebd8b9912007-02-27 20:17:00 +0000109
110 # Write headers
111 self.__http.putheader('Host', self.host)
112 self.__http.putheader('Content-Type', 'application/x-thrift')
113 self.__http.putheader('Content-Length', str(len(data)))
114 self.__http.endheaders()
115
116 # Write payload
117 self.__http.send(data)
118
119 # Get reply to flush the request
120 self.code, self.message, self.headers = self.__http.getreply()
David Reissff3d2492010-03-09 05:19:16 +0000121
122 # Decorate if we know how to timeout
123 if hasattr(socket, 'getdefaulttimeout'):
124 flush = __withTimeout(flush)