OSDN Git Service

remove system collection
[simple-tornado-bot/simple-tornado-bot.git] / linebot / http_client.py
1 # -*- coding: utf-8 -*-
2
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
6 #
7 #       https://www.apache.org/licenses/LICENSE-2.0
8 #
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
13 #  under the License.
14
15 """linebot.http_client module."""
16
17 from __future__ import unicode_literals
18
19 from abc import ABCMeta, abstractmethod, abstractproperty
20
21 import requests
22 from future.utils import with_metaclass
23
24
25 class HttpClient(with_metaclass(ABCMeta)):
26     """Abstract Base Classes of HttpClient."""
27
28     DEFAULT_TIMEOUT = 5
29
30     def __init__(self, timeout=DEFAULT_TIMEOUT):
31         """__init__ method.
32
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
40         """
41         self.timeout = timeout
42
43     @abstractmethod
44     def get(self, url, headers=None, params=None, stream=False, timeout=None):
45         """GET request.
46
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
58         """
59         raise NotImplementedError
60
61     @abstractmethod
62     def post(self, url, headers=None, data=None, timeout=None):
63         """POST request.
64
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
75         """
76         raise NotImplementedError
77
78     @abstractmethod
79     def delete(self, url, headers=None, data=None, timeout=None):
80         """DELETE request.
81
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
92         """
93         raise NotImplementedError
94
95
96 class RequestsHttpClient(HttpClient):
97     """HttpClient implemented by requests."""
98
99     def __init__(self, timeout=HttpClient.DEFAULT_TIMEOUT):
100         """__init__ method.
101
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)
107         """
108         super(RequestsHttpClient, self).__init__(timeout)
109
110     def get(self, url, headers=None, params=None, stream=False, timeout=None):
111         """GET request.
112
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
124         """
125         if timeout is None:
126             timeout = self.timeout
127
128         response = requests.get(
129             url, headers=headers, params=params, stream=stream, timeout=timeout
130         )
131
132         return RequestsHttpResponse(response)
133
134     def post(self, url, headers=None, data=None, timeout=None):
135         """POST request.
136
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
147         """
148         if timeout is None:
149             timeout = self.timeout
150
151         response = requests.post(
152             url, headers=headers, data=data, timeout=timeout
153         )
154
155         return RequestsHttpResponse(response)
156
157     def delete(self, url, headers=None, data=None, timeout=None):
158         """DELETE request.
159
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
170         """
171         if timeout is None:
172             timeout = self.timeout
173
174         response = requests.delete(
175             url, headers=headers, data=data, timeout=timeout
176         )
177
178         return RequestsHttpResponse(response)
179
180
181 class HttpResponse(with_metaclass(ABCMeta)):
182     """HttpResponse."""
183
184     @abstractproperty
185     def status_code(self):
186         """Get status code."""
187         raise NotImplementedError
188
189     @abstractproperty
190     def headers(self):
191         """Get headers."""
192         raise NotImplementedError
193
194     @abstractproperty
195     def text(self):
196         """Get request body as text-decoded."""
197         raise NotImplementedError
198
199     @abstractproperty
200     def content(self):
201         """Get request body as binary."""
202         raise NotImplementedError
203
204     @abstractproperty
205     def json(self):
206         """Get request body as json-decoded."""
207         raise NotImplementedError
208
209     @abstractmethod
210     def iter_content(self, chunk_size=1024, decode_unicode=False):
211         """Get request body as iterator content (stream).
212
213         :param int chunk_size:
214         :param bool decode_unicode:
215         """
216         raise NotImplementedError
217
218
219 class RequestsHttpResponse(HttpResponse):
220     """HttpResponse implemented by requests lib's response."""
221
222     def __init__(self, response):
223         """__init__ method.
224
225         :param response: requests lib's response
226         """
227         self.response = response
228
229     @property
230     def status_code(self):
231         """Get status code."""
232         return self.response.status_code
233
234     @property
235     def headers(self):
236         """Get headers."""
237         return self.response.headers
238
239     @property
240     def text(self):
241         """Get request body as text-decoded."""
242         return self.response.text
243
244     @property
245     def content(self):
246         """Get request body as binary."""
247         return self.response.content
248
249     @property
250     def json(self):
251         """Get request body as json-decoded."""
252         return self.response.json()
253
254     def iter_content(self, chunk_size=1024, decode_unicode=False):
255         """Get request body as iterator content (stream).
256
257         :param int chunk_size:
258         :param bool decode_unicode:
259         """
260         return self.response.iter_content(chunk_size=chunk_size, decode_unicode=decode_unicode)