Skip to content

Commit d6f399e

Browse files
authored
Refactoring Database Code (#66)
* Extracted the HTTP client logic into a separate internal module; Changed return order of set_if_unchanged(); Updated test cases * Disabling a test case temporarily * Updated documentation and tests * Using the readonly accessor to patch the session
1 parent 5744b69 commit d6f399e

File tree

4 files changed

+289
-131
lines changed

4 files changed

+289
-131
lines changed

firebase_admin/_http_client.py

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
# Copyright 2017 Google Inc.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://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,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
"""Internal HTTP client module.
16+
17+
This module provides utilities for making HTTP calls using the requests library.
18+
"""
19+
20+
from google.auth import transport
21+
import requests
22+
23+
24+
class HttpClient(object):
25+
"""Base HTTP client used to make HTTP calls.
26+
27+
HttpClient maintains an HTTP session, and handles request authentication if necessary.
28+
"""
29+
30+
def __init__(self, credential=None, session=None, base_url='', headers=None):
31+
"""Cretes a new HttpClient instance from the provided arguments.
32+
33+
If a credential is provided, initializes a new HTTP session authorized with it. If neither
34+
a credential nor a session is provided, initializes a new unauthorized session.
35+
36+
Args:
37+
credential: A Google credential that can be used to authenticate requests (optional).
38+
session: A custom HTTP session (optional).
39+
base_url: A URL prefix to be added to all outgoing requests (optional).
40+
headers: A map of headers to be added to all outgoing requests (optional).
41+
"""
42+
if credential:
43+
self._session = transport.requests.AuthorizedSession(credential)
44+
elif session:
45+
self._session = session
46+
else:
47+
self._session = requests.Session() # pylint: disable=redefined-variable-type
48+
49+
if headers:
50+
self._session.headers.update(headers)
51+
self._base_url = base_url
52+
53+
@property
54+
def session(self):
55+
return self._session
56+
57+
@property
58+
def base_url(self):
59+
return self._base_url
60+
61+
def parse_body(self, resp):
62+
raise NotImplementedError
63+
64+
def request(self, method, url, **kwargs):
65+
"""Makes an HTTP call using the Python requests library.
66+
67+
This is the sole entry point to the requests library. All other helper methods in this
68+
class call this method to send HTTP requests out. Refer to
69+
http://docs.python-requests.org/en/master/api/ for more information on supported options
70+
and features.
71+
72+
Args:
73+
method: HTTP method name as a string (e.g. get, post).
74+
url: URL of the remote endpoint.
75+
kwargs: An additional set of keyword arguments to be passed into the requests API
76+
(e.g. json, params).
77+
78+
Returns:
79+
Response: An HTTP response object.
80+
81+
Raises:
82+
RequestException: Any requests exceptions encountered while making the HTTP call.
83+
"""
84+
resp = self._session.request(method, self._base_url + url, **kwargs)
85+
resp.raise_for_status()
86+
return resp
87+
88+
def headers(self, method, url, **kwargs):
89+
resp = self.request(method, url, **kwargs)
90+
return resp.headers
91+
92+
def body(self, method, url, **kwargs):
93+
resp = self.request(method, url, **kwargs)
94+
return self.parse_body(resp)
95+
96+
def headers_and_body(self, method, url, **kwargs):
97+
resp = self.request(method, url, **kwargs)
98+
return resp.headers, self.parse_body(resp)
99+
100+
def close(self):
101+
self._session.close()
102+
self._session = None
103+
104+
105+
class JsonHttpClient(HttpClient):
106+
"""An HTTP client that parses response messages as JSON."""
107+
108+
def __init__(self, **kwargs):
109+
HttpClient.__init__(self, **kwargs)
110+
111+
def parse_body(self, resp):
112+
return resp.json()

0 commit comments

Comments
 (0)