1 # -*- coding: utf-8 -*-
3 # Licensed under the Apache License, Version 2.0 (the "License"); you may
4 # not use this file except in compliance with the License. You may obtain
5 # a copy of the License at
7 # https://www.apache.org/licenses/LICENSE-2.0
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11 # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12 # License for the specific language governing permissions and limitations
15 """linebot.http_client module."""
17 from __future__ import unicode_literals
19 from abc import ABCMeta, abstractmethod, abstractproperty
22 from future.utils import with_metaclass
25 class HttpClient(with_metaclass(ABCMeta)):
26 """Abstract Base Classes of HttpClient."""
30 def __init__(self, timeout=DEFAULT_TIMEOUT):
33 :param timeout: (optional) How long to wait for the server
34 to send data before giving up, as a float,
35 or a (connect timeout, read timeout) float tuple.
36 Default is :py:attr:`DEFAULT_TIMEOUT`
37 :type timeout: float | tuple(float, float)
38 :rtype: T <= :py:class:`HttpResponse`
39 :return: HttpResponse instance
41 self.timeout = timeout
44 def get(self, url, headers=None, params=None, stream=False, timeout=None):
47 :param str url: Request url
48 :param dict headers: (optional) Request headers
49 :param dict params: (optional) Request query parameter
50 :param bool stream: (optional) get content as stream
51 :param timeout: (optional), How long to wait for the server
52 to send data before giving up, as a float,
53 or a (connect timeout, read timeout) float tuple.
54 Default is :py:attr:`self.timeout`
55 :type timeout: float | tuple(float, float)
56 :rtype: T <= :py:class:`HttpResponse`
57 :return: HttpResponse instance
59 raise NotImplementedError
62 def post(self, url, headers=None, data=None, timeout=None):
65 :param str url: Request url
66 :param dict headers: (optional) Request headers
67 :param data: (optional) Dictionary, bytes, or file-like object to send in the body
68 :param timeout: (optional), How long to wait for the server
69 to send data before giving up, as a float,
70 or a (connect timeout, read timeout) float tuple.
71 Default is :py:attr:`self.timeout`
72 :type timeout: float | tuple(float, float)
73 :rtype: T <= :py:class:`HttpResponse`
74 :return: HttpResponse instance
76 raise NotImplementedError
79 def delete(self, url, headers=None, data=None, timeout=None):
82 :param str url: Request url
83 :param dict headers: (optional) Request headers
84 :param data: (optional) Dictionary, bytes, or file-like object to send in the body
85 :param timeout: (optional), How long to wait for the server
86 to send data before giving up, as a float,
87 or a (connect timeout, read timeout) float tuple.
88 Default is :py:attr:`self.timeout`
89 :type timeout: float | tuple(float, float)
90 :rtype: T <= :py:class:`HttpResponse`
91 :return: HttpResponse instance
93 raise NotImplementedError
96 class RequestsHttpClient(HttpClient):
97 """HttpClient implemented by requests."""
99 def __init__(self, timeout=HttpClient.DEFAULT_TIMEOUT):
102 :param timeout: (optional) How long to wait for the server
103 to send data before giving up, as a float,
104 or a (connect timeout, read timeout) float tuple.
105 Default is :py:attr:`DEFAULT_TIMEOUT`
106 :type timeout: float | tuple(float, float)
108 super(RequestsHttpClient, self).__init__(timeout)
110 def get(self, url, headers=None, params=None, stream=False, timeout=None):
113 :param str url: Request url
114 :param dict headers: (optional) Request headers
115 :param dict params: (optional) Request query parameter
116 :param bool stream: (optional) get content as stream
117 :param timeout: (optional), How long to wait for the server
118 to send data before giving up, as a float,
119 or a (connect timeout, read timeout) float tuple.
120 Default is :py:attr:`self.timeout`
121 :type timeout: float | tuple(float, float)
122 :rtype: :py:class:`RequestsHttpResponse`
123 :return: RequestsHttpResponse instance
126 timeout = self.timeout
128 response = requests.get(
129 url, headers=headers, params=params, stream=stream, timeout=timeout
132 return RequestsHttpResponse(response)
134 def post(self, url, headers=None, data=None, timeout=None):
137 :param str url: Request url
138 :param dict headers: (optional) Request headers
139 :param data: (optional) Dictionary, bytes, or file-like object to send in the body
140 :param timeout: (optional), How long to wait for the server
141 to send data before giving up, as a float,
142 or a (connect timeout, read timeout) float tuple.
143 Default is :py:attr:`self.timeout`
144 :type timeout: float | tuple(float, float)
145 :rtype: :py:class:`RequestsHttpResponse`
146 :return: RequestsHttpResponse instance
149 timeout = self.timeout
151 response = requests.post(
152 url, headers=headers, data=data, timeout=timeout
155 return RequestsHttpResponse(response)
157 def delete(self, url, headers=None, data=None, timeout=None):
160 :param str url: Request url
161 :param dict headers: (optional) Request headers
162 :param data: (optional) Dictionary, bytes, or file-like object to send in the body
163 :param timeout: (optional), How long to wait for the server
164 to send data before giving up, as a float,
165 or a (connect timeout, read timeout) float tuple.
166 Default is :py:attr:`self.timeout`
167 :type timeout: float | tuple(float, float)
168 :rtype: :py:class:`RequestsHttpResponse`
169 :return: RequestsHttpResponse instance
172 timeout = self.timeout
174 response = requests.delete(
175 url, headers=headers, data=data, timeout=timeout
178 return RequestsHttpResponse(response)
181 class HttpResponse(with_metaclass(ABCMeta)):
185 def status_code(self):
186 """Get status code."""
187 raise NotImplementedError
192 raise NotImplementedError
196 """Get request body as text-decoded."""
197 raise NotImplementedError
201 """Get request body as binary."""
202 raise NotImplementedError
206 """Get request body as json-decoded."""
207 raise NotImplementedError
210 def iter_content(self, chunk_size=1024, decode_unicode=False):
211 """Get request body as iterator content (stream).
213 :param int chunk_size:
214 :param bool decode_unicode:
216 raise NotImplementedError
219 class RequestsHttpResponse(HttpResponse):
220 """HttpResponse implemented by requests lib's response."""
222 def __init__(self, response):
225 :param response: requests lib's response
227 self.response = response
230 def status_code(self):
231 """Get status code."""
232 return self.response.status_code
237 return self.response.headers
241 """Get request body as text-decoded."""
242 return self.response.text
246 """Get request body as binary."""
247 return self.response.content
251 """Get request body as json-decoded."""
252 return self.response.json()
254 def iter_content(self, chunk_size=1024, decode_unicode=False):
255 """Get request body as iterator content (stream).
257 :param int chunk_size:
258 :param bool decode_unicode:
260 return self.response.iter_content(chunk_size=chunk_size, decode_unicode=decode_unicode)