source: admin/Sources/Clients/ogagent/src/opengnsys/httpserver.py @ d57fcbc

918-git-images-111dconfigfileconfigure-oglivegit-imageslgromero-new-oglivemainmaint-cronmount-efivarfsmultivmmultivm-ogboot-installerogClonningEngineogboot-installer-jenkinsoglive-ipv6test-python-scriptsticket-301ticket-50ticket-50-oldticket-577ticket-585ticket-611ticket-612ticket-693ticket-700ubu24tplunification2use-local-agent-oglivevarios-instalacionwebconsole3
Last change on this file since d57fcbc was a739060, checked in by ramon <ramongomez@…>, 8 years ago

#718: Agente OGAgent usa mensajes en UTF-8; actualizar definición de la API REST.

git-svn-id: https://opengnsys.es/svn/branches/version1.1@5256 a21b9725-9963-47de-94b9-378ad31fedc9

  • Property mode set to 100644
File size: 5.6 KB
Line 
1# -*- coding: utf-8 -*-
2#
3# Copyright (c) 2015 Virtual Cable S.L.
4# All rights reserved.
5#
6# Redistribution and use in source and binary forms, with or without modification,
7# are permitted provided that the following conditions are met:
8#
9#    * Redistributions of source code must retain the above copyright notice,
10#      this list of conditions and the following disclaimer.
11#    * Redistributions in binary form must reproduce the above copyright notice,
12#      this list of conditions and the following disclaimer in the documentation
13#      and/or other materials provided with the distribution.
14#    * Neither the name of Virtual Cable S.L. nor the names of its contributors
15#      may be used to endorse or promote products derived from this software
16#      without specific prior written permission.
17#
18# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
22# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
25# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
26# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28'''
29@author: Adolfo Gómez, dkmaster at dkmon dot com
30'''
31# pylint: disable=unused-wildcard-import,wildcard-import
32from __future__ import unicode_literals, print_function
33
34# Pydev can't parse "six.moves.xxxx" because it is loaded lazy
35import six
36from six.moves.socketserver import ThreadingMixIn  # @UnresolvedImport
37from six.moves.BaseHTTPServer import BaseHTTPRequestHandler  # @UnresolvedImport
38from six.moves.BaseHTTPServer import HTTPServer  # @UnresolvedImport
39from six.moves.urllib.parse import unquote  # @UnresolvedImport
40
41import json
42import threading
43import ssl
44
45from .utils import exceptionToMessage
46from .certs import createSelfSignedCert
47from .log import logger
48
49class HTTPServerHandler(BaseHTTPRequestHandler):
50    service = None
51    protocol_version = 'HTTP/1.0'
52    server_version = 'OpenGnsys Agent Server'
53    sys_version = ''
54   
55    def sendJsonError(self, code, message):
56        self.send_response(code)
57        self.send_header('Content-type', 'application/json')
58        self.end_headers()
59        self.wfile.write(json.dumps({'error': message}))
60        return
61
62    def sendJsonResponse(self, data):
63        self.send_response(200)
64        data = json.dumps(data)
65        self.send_header('Content-type', 'application/json')
66        self.send_header('Content-Length', len(data))
67        self.end_headers()
68        # Send the html message
69        self.wfile.write(data)
70       
71   
72    # parseURL
73    def parseUrl(self):
74        # Very simple path & params splitter
75        path = self.path.split('?')[0][1:].split('/')
76       
77        try:
78            params = dict((v[0], unquote(v[1])) for v in (v.split('=') for v in self.path.split('?')[1].split('&')))
79        except Exception:
80            params = {}
81
82        for v in self.service.modules:
83            if v.name == path[0]:  # Case Sensitive!!!!
84                return (v, path[1:], params)
85           
86        return (None, path, params)
87   
88    def notifyMessage(self, module, path, getParams, postParams):
89        '''
90        Locates witch module will process the message based on path (first folder on url path)
91        '''
92        try:
93            data = module.processServerMessage(path, getParams, postParams, self)
94            self.sendJsonResponse(data)
95        except Exception as e:
96            logger.exception()
97            self.sendJsonError(500, exceptionToMessage(e))
98           
99    def do_GET(self):
100        module, path, params = self.parseUrl()
101       
102        self.notifyMessage(module, path, params, None)
103       
104    def do_POST(self):
105        module, path, getParams = self.parseUrl()
106
107        # Tries to get JSON content (UTF-8 encoded)
108        try:
109            length = int(self.headers.getheader('content-length'))
110            content = self.rfile.read(length).decode('utf-8')
111            logger.debug('length: {}, content >>{}<<'.format(length, content))
112            postParams = json.loads(content)
113        except Exception as e:
114            self.sendJsonError(500, exceptionToMessage(e))
115           
116        self.notifyMessage(module, path, getParams, postParams)
117           
118
119    def log_error(self, fmt, *args):
120        logger.error('HTTP ' + fmt % args)
121       
122    def log_message(self, fmt, *args):
123        logger.info('HTTP ' + fmt % args)
124       
125
126class HTTPThreadingServer(ThreadingMixIn, HTTPServer):
127    pass
128
129class HTTPServerThread(threading.Thread):
130    def __init__(self, address, service):
131        super(self.__class__, self).__init__()
132
133        HTTPServerHandler.service = service  # Keep tracking of service so we can intercact with it
134
135        self.certFile = createSelfSignedCert()
136        self.server = HTTPThreadingServer(address, HTTPServerHandler)
137        self.server.socket = ssl.wrap_socket(self.server.socket, certfile=self.certFile, server_side=True)
138       
139        logger.debug('Initialized HTTPS Server thread on {}'.format(address))
140
141    def getServerUrl(self):
142        return 'https://{}:{}/'.format(self.server.server_address[0], self.server.server_address[1])
143
144    def stop(self):
145        self.server.shutdown()
146
147    def run(self):
148        self.server.serve_forever()
149
150   
Note: See TracBrowser for help on using the repository browser.