#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
# Copyright (C) 2015-2015: Alignak team, see AUTHORS.txt file for contributors
#
# This file is part of Alignak.
#
# Alignak is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Alignak is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with Alignak. If not, see <http://www.gnu.org/licenses/>.
#
#
# This file incorporates work covered by the following copyright and
# permission notice:
#
# Copyright (C) 2009-2014:
# David Moreau Simard, dmsimard@iweb.com
# Frédéric Vachon, fredvac@gmail.com
# aviau, alexandre.viau@savoirfairelinux.com
# Grégory Starck, g.starck@gmail.com
# Sebastien Coavoux, s.coavoux@free.fr
# Jean Gabes, naparuba@gmail.com
# This file is part of Shinken.
#
# Shinken is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Shinken is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with Shinken. If not, see <http://www.gnu.org/licenses/>.
"""This module provides HTTPClient class. Used by daemon to connect to HTTP servers (other daemons)
"""
import cPickle
import json
import warnings
import zlib
import requests
from alignak.log import logger
[docs]class HTTPException(Exception):
"""Simple HTTP Exception
"""
pass
HTTPEXCEPTIONS = (HTTPException,)
[docs]class HTTPClient(object):
"""HTTPClient class use python request to communicate over HTTP
Basically used to get / post to other daemons
"""
def __init__(self, address='', port=0, use_ssl=False, timeout=3,
data_timeout=120, uri='', strong_ssl=False, proxy=''):
self.address = address
self.port = port
self.timeout = timeout
self.data_timeout = data_timeout
self.use_ssl = use_ssl
self.strong_ssl = strong_ssl
if not uri:
protocol = "https" if use_ssl else "http"
uri = "%s://%s:%s/" % (protocol, self.address, self.port)
self.uri = uri
self._requests_con = requests.Session()
self.set_proxy(proxy)
@property
[docs] def con(self):
"""Deprecated properrty of HTTPClient
:return: connection
:rtype: object
"""
warnings.warn("HTTPClient.con is deprecated attribute, "
"please use HTTPClient.connection instead.",
DeprecationWarning, stacklevel=2)
return self.connection
@property
[docs] def connection(self):
"""Get connection attribute
:return:
:rtype:
"""
return self._requests_con
[docs] def make_uri(self, path):
"""Create uri from path
:param path: path to make uri
:type path: str
:return: self.uri + path
:rtype: str
"""
return '%s%s' % (self.uri, path)
[docs] def make_timeout(self, wait):
"""Get timeout depending on wait time
:param wait: wait is short or long (else)
:type wait: int
:return: self.timeout if wait is short, self.data_timeout otherwise
:rtype: int
"""
return self.timeout if wait == 'short' else self.data_timeout
[docs] def set_proxy(self, proxy):
"""Set HTTP proxy
:param proxy: proxy url
:type proxy: str
:return: None
"""
if proxy:
logger.debug('PROXY SETTING PROXY %s', proxy)
self._requests_con.proxies = {
'http': proxy,
'https': proxy,
}
[docs] def get(self, path, args={}, wait='short'):
"""Do a GET HTTP request
:param path: path to do the request
:type path: str
:param args: args to add in the request
:type args: dict
:param wait: timeout policy (short / long)
:type wait: int
:return: None
"""
uri = self.make_uri(path)
timeout = self.make_timeout(wait)
try:
rsp = self._requests_con.get(uri, params=args, timeout=timeout, verify=self.strong_ssl)
if rsp.status_code != 200:
raise Exception('HTTP GET not OK: %s ; text=%r' % (rsp.status_code, rsp.text))
return rsp.json()
except Exception as err:
raise HTTPException('Request error to %s: %s' % (uri, err))
[docs] def post(self, path, args, wait='short'):
"""Do a POST HTTP request
:param path: path to do the request
:type path: str
:param args: args to add in the request
:type args: dict
:param wait: timeout policy (short / long)
:type wait: int
:return: Content of the HTTP response if server returned 200
:rtype: str
"""
uri = self.make_uri(path)
timeout = self.make_timeout(wait)
for (key, value) in args.iteritems():
args[key] = cPickle.dumps(value)
try:
headers = {'content-type': 'application/zlib'}
args = zlib.compress(json.dumps(args, ensure_ascii=False), 2)
rsp = self._requests_con.post(uri, data=args, timeout=timeout, verify=self.strong_ssl,
headers=headers)
if rsp.status_code != 200:
raise Exception("HTTP POST not OK: %s ; text=%r" % (rsp.status_code, rsp.text))
except Exception as err:
raise HTTPException('Request error to %s: %s' % (uri, err))
return rsp.content
[docs] def put(self, path, data, wait='short'):
"""Do a PUT HTTP request
:param path: path to do the request
:type path: str
:param data: data to send in the request
:type data:
:param args: args to add in the request
:type args:
:param wait: timeout policy (short / long)
:type wait: int
:return: Content of the HTTP response if server returned 200
:rtype: str
"""
uri = self.make_uri(path)
timeout = self.make_timeout(wait)
try:
rsp = self._requests_con.put(uri, data, timeout=timeout, verify=self.strong_ssl)
if rsp.status_code != 200:
raise Exception('HTTP PUT not OK: %s ; text=%r' % (rsp.status_code, rsp.text))
except Exception as err:
raise HTTPException('Request error to %s: %s' % (uri, err))
return rsp.content