blob: ad94d1126588032c4faed0e28849071a083ec5e3 [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
Bryan Duxbury69720412012-01-03 17:32:30 +000020import httplib
21import socket
22import urlparse
23import warnings
24
Mark Sleebd8b9912007-02-27 20:17:00 +000025from cStringIO import StringIO
26
Bryan Duxbury69720412012-01-03 17:32:30 +000027from TTransport import *
28
Mark Sleebd8b9912007-02-27 20:17:00 +000029
30class THttpClient(TTransportBase):
Mark Sleebd8b9912007-02-27 20:17:00 +000031 """Http implementation of TTransport base."""
32
David Reiss2aa28902009-03-26 06:22:18 +000033 def __init__(self, uri_or_host, port=None, path=None):
34 """THttpClient supports two different types constructor parameters.
35
36 THttpClient(host, port, path) - deprecated
37 THttpClient(uri)
38
Bryan Duxbury69720412012-01-03 17:32:30 +000039 Only the second supports https.
40 """
David Reiss2aa28902009-03-26 06:22:18 +000041 if port is not None:
Bryan Duxbury69720412012-01-03 17:32:30 +000042 warnings.warn(
43 "Please use the THttpClient('http://host:port/path') syntax",
44 DeprecationWarning,
45 stacklevel=2)
David Reiss2aa28902009-03-26 06:22:18 +000046 self.host = uri_or_host
47 self.port = port
48 assert path
49 self.path = path
50 self.scheme = 'http'
51 else:
52 parsed = urlparse.urlparse(uri_or_host)
53 self.scheme = parsed.scheme
54 assert self.scheme in ('http', 'https')
55 if self.scheme == 'http':
56 self.port = parsed.port or httplib.HTTP_PORT
57 elif self.scheme == 'https':
58 self.port = parsed.port or httplib.HTTPS_PORT
59 self.host = parsed.hostname
60 self.path = parsed.path
Bryan Duxbury727d67d2010-09-02 01:00:19 +000061 if parsed.query:
62 self.path += '?%s' % parsed.query
Mark Sleebd8b9912007-02-27 20:17:00 +000063 self.__wbuf = StringIO()
64 self.__http = None
David Reissff3d2492010-03-09 05:19:16 +000065 self.__timeout = None
Mark Sleebd8b9912007-02-27 20:17:00 +000066
67 def open(self):
David Reiss2aa28902009-03-26 06:22:18 +000068 if self.scheme == 'http':
69 self.__http = httplib.HTTP(self.host, self.port)
70 else:
71 self.__http = httplib.HTTPS(self.host, self.port)
Mark Sleebd8b9912007-02-27 20:17:00 +000072
73 def close(self):
74 self.__http.close()
75 self.__http = None
David Reiss0c90f6f2008-02-06 22:18:40 +000076
Mark Sleebd8b9912007-02-27 20:17:00 +000077 def isOpen(self):
Bryan Duxbury69720412012-01-03 17:32:30 +000078 return self.__http is not None
Mark Sleebd8b9912007-02-27 20:17:00 +000079
David Reissff3d2492010-03-09 05:19:16 +000080 def setTimeout(self, ms):
81 if not hasattr(socket, 'getdefaulttimeout'):
82 raise NotImplementedError
83
84 if ms is None:
85 self.__timeout = None
86 else:
Bryan Duxbury69720412012-01-03 17:32:30 +000087 self.__timeout = ms / 1000.0
David Reissff3d2492010-03-09 05:19:16 +000088
Mark Sleebd8b9912007-02-27 20:17:00 +000089 def read(self, sz):
90 return self.__http.file.read(sz)
91
92 def write(self, buf):
93 self.__wbuf.write(buf)
94
David Reissff3d2492010-03-09 05:19:16 +000095 def __withTimeout(f):
96 def _f(*args, **kwargs):
97 orig_timeout = socket.getdefaulttimeout()
98 socket.setdefaulttimeout(args[0].__timeout)
99 result = f(*args, **kwargs)
100 socket.setdefaulttimeout(orig_timeout)
101 return result
102 return _f
103
Mark Sleebd8b9912007-02-27 20:17:00 +0000104 def flush(self):
David Reiss7c1f6f82009-03-24 20:10:24 +0000105 if self.isOpen():
106 self.close()
Bryan Duxbury69720412012-01-03 17:32:30 +0000107 self.open()
David Reiss7c1f6f82009-03-24 20:10:24 +0000108
Mark Sleebd8b9912007-02-27 20:17:00 +0000109 # Pull data out of buffer
110 data = self.__wbuf.getvalue()
111 self.__wbuf = StringIO()
112
113 # HTTP request
David Reiss2aa28902009-03-26 06:22:18 +0000114 self.__http.putrequest('POST', self.path)
Mark Sleebd8b9912007-02-27 20:17:00 +0000115
116 # Write headers
117 self.__http.putheader('Host', self.host)
118 self.__http.putheader('Content-Type', 'application/x-thrift')
119 self.__http.putheader('Content-Length', str(len(data)))
120 self.__http.endheaders()
121
122 # Write payload
123 self.__http.send(data)
124
125 # Get reply to flush the request
126 self.code, self.message, self.headers = self.__http.getreply()
David Reissff3d2492010-03-09 05:19:16 +0000127
128 # Decorate if we know how to timeout
129 if hasattr(socket, 'getdefaulttimeout'):
130 flush = __withTimeout(flush)