source: ogAgent-Git/src/test_rest_server.py

qndtest
Last change on this file was 11f7a07, checked in by ramon <ramongomez@…>, 8 years ago

#718: Integrar código fuente de agente OGAgent en rama de desarrollo.

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

  • Property mode set to 100644
File size: 8.3 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'''
30@author: Adolfo Gómez, dkmaster at dkmon dot com
31'''
32# pylint: disable=unused-wildcard-import,wildcard-import
33from __future__ import unicode_literals, print_function
34
35# Pydev can't parse "six.moves.xxxx" because it is loaded lazy
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
45import logging
46from tempfile import gettempdir
47from os.path import exists, join
48
49logger = logging.getLogger(__name__)
50
51
52CERTFILE = 'OGTestServer.pem'
53
54
55def createSelfSignedCert(force=False):
56
57    certFile = join(gettempdir(), CERTFILE)
58
59    if exists(certFile) and not force:
60        return certFile
61
62    certData = '''-----BEGIN PRIVATE KEY-----
63MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCb50K3mIznNklz
64yVAD7xSQOSJQ6+NPXj7U9/4zLZ+TvmbQ7RqUUsxbfxHbeRnoYTWV2nKk4+tHqmvz
65ujLSS/loFhTSMqtrLn7rowSYJoQhKOUkAiQlWkqCfItWgL5pJopDpNHFul9Rn3ds
66PMWQTiGeUNR4Y3RnBhr1Q1BsqAzf4m6zFUmgLPPmVLdF4uJ3Tuz8TSy2gWLs5aSr
675do4WamwUfYjRSVMJECmwjUM4rQ8SQgg0sHBeBuDUGNBvBQFac1G7qUcMReeu8Zr
68DUtMsXma/l4rA8NB5CRmTrQbTBF4l+jb2BDFebDqDUK1Oqs9X35yOQfDOAFYHiix
69PX0IsXOZAgMBAAECggEBAJi3000RrIUZUp6Ph0gzPMuCjDEEwWiQA7CPNX1gpb8O
70dp0WhkDhUroWIaICYPSXtOwUTtVjRqivMoxPy1Thg3EIoGC/rdeSdlXRHMEGicwJ
71yVyalFnatr5Xzg5wkxVh4XMd0zeDt7e3JD7s0QLo5lm1CEzd77qz6lhzFic5/1KX
72bzdULtTlq60dazg2hEbcS4OmM1UMCtRVDAsOIUIZPL0M9j1C1d1iEdYnh2xshKeG
73/GOfo95xsgdMlGjtv3hUT5ryKVoEsu+36rGb4VfhPfUvvoVbRx5QZpW+QvxaYh5E
74Fi0JEROozFwG31Y++8El7J3yQko8cFBa1lYYUwwpNAECgYEAykT+GiM2YxJ4uVF1
75OoKiE9BD53i0IG5j87lGPnWqzEwYBwnqjEKDTou+uzMGz3MDV56UEFNho7wUWh28
76LpEkjJB9QgbsugjxIBr4JoL/rYk036e/6+U8I95lvYWrzb+rBMIkRDYI7kbQD/mQ
77piYUpuCkTymNAu2RisK6bBzJslkCgYEAxVE23OQvkCeOV8hJNPZGpJ1mDS+TiOow
78oOScMZmZpail181eYbAfMsCr7ri812lSj98NvA2GNVLpddil6LtS1cQ5p36lFBtV
79xQUMZiFz4qVbEak+izL+vPaev/mXXsOcibAIQ+qI/0txFpNhJjpaaSy6vRCBYFmc
808pgSoBnBI0ECgYAUKCn2atnpp5aWSTLYgNosBU4vDA1PShD14dnJMaqyr0aZtPhF
81v/8b3btFJoGgPMLxgWEZ+2U4ju6sSFhPf7FXvLJu2QfQRkHZRDbEh7t5DLpTK4Fp
82va9vl6Ml7uM/HsGpOLuqfIQJUs87OFCc7iCSvMJDDU37I7ekT2GKkpfbCQKBgBrE
830NeY0WcSJrp7/oqD2sOcYurpCG/rrZs2SIZmGzUhMxaa0vIXzbO59dlWELB8pmnE
84Tf20K//x9qA5OxDe0PcVPukdQlH+/1zSOYNliG44FqnHtyd1TJ/gKVtMBiAiE4uO
85aSClod5Yosf4SJbCFd/s5Iyfv52NqsAyp1w3Aj/BAoGAVCnEiGUfyHlIR+UH4zZW
86GXJMeqdZLfcEIszMxLePkml4gUQhoq9oIs/Kw+L1DDxUwzkXN4BNTlFbOSu9gzK1
87dhuIUGfS6RPL88U+ivC3A0y2jT43oUMqe3hiRt360UQ1GXzp2dMnR9odSRB1wHoO
88IOjEBZ8341/c9ZHc5PCGAG8=
89-----END PRIVATE KEY-----
90-----BEGIN CERTIFICATE-----
91MIID7zCCAtegAwIBAgIJAIrEIthCfxUCMA0GCSqGSIb3DQEBCwUAMIGNMQswCQYD
92VQQGEwJFUzEPMA0GA1UECAwGTWFkcmlkMREwDwYDVQQHDAhBbGNvcmNvbjEMMAoG
93A1UECgwDVURTMQ4wDAYDVQQLDAVBY3RvcjESMBAGA1UEAwwJVURTIEFjdG9yMSgw
94JgYJKoZIhvcNAQkBFhlzdXBwb3J0QHVkc2VudGVycHJpc2UuY29tMB4XDTE0MTAy
95NjIzNDEyNFoXDTI0MTAyMzIzNDEyNFowgY0xCzAJBgNVBAYTAkVTMQ8wDQYDVQQI
96DAZNYWRyaWQxETAPBgNVBAcMCEFsY29yY29uMQwwCgYDVQQKDANVRFMxDjAMBgNV
97BAsMBUFjdG9yMRIwEAYDVQQDDAlVRFMgQWN0b3IxKDAmBgkqhkiG9w0BCQEWGXN1
98cHBvcnRAdWRzZW50ZXJwcmlzZS5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw
99ggEKAoIBAQCb50K3mIznNklzyVAD7xSQOSJQ6+NPXj7U9/4zLZ+TvmbQ7RqUUsxb
100fxHbeRnoYTWV2nKk4+tHqmvzujLSS/loFhTSMqtrLn7rowSYJoQhKOUkAiQlWkqC
101fItWgL5pJopDpNHFul9Rn3dsPMWQTiGeUNR4Y3RnBhr1Q1BsqAzf4m6zFUmgLPPm
102VLdF4uJ3Tuz8TSy2gWLs5aSr5do4WamwUfYjRSVMJECmwjUM4rQ8SQgg0sHBeBuD
103UGNBvBQFac1G7qUcMReeu8ZrDUtMsXma/l4rA8NB5CRmTrQbTBF4l+jb2BDFebDq
104DUK1Oqs9X35yOQfDOAFYHiixPX0IsXOZAgMBAAGjUDBOMB0GA1UdDgQWBBRShS90
1055lJTNvYPIEqP3GxWwG5iiDAfBgNVHSMEGDAWgBRShS905lJTNvYPIEqP3GxWwG5i
106iDAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQAU0Sp4gXhQmRVzq+7+
107vRFUkQuPj4Ga/d9r5Wrbg3hck3+5pwe9/7APoq0P/M0DBhQpiJKjrD6ydUevC+Y/
10843ZOJPhMlNw0o6TdQxOkX6FDwQanLLs7sfvJvqtVzYn3nuRFKT3dvl7Zg44QMw2M
109ay42q59fAcpB4LaDx/i7gOYSS5eca3lYW7j7YSr/+ozXK2KlgUkuCUHN95lOq+dF
110trmV9mjzM4CNPZqKSE7kpHRywgrXGPCO000NvEGSYf82AtgRSFKiU8NWLQSEPdcB
111k//2dsQZw2cRZ8DrC2B6Tb3M+3+CA6wVyqfqZh1SZva3LfGvq/C+u+ItguzPqNpI
112xtvM
113-----END CERTIFICATE-----'''
114    with open(certFile, "wt") as f:
115        f.write(certData)
116
117    return certFile
118
119class HTTPServerHandler(BaseHTTPRequestHandler):
120    service = None
121    protocol_version = 'HTTP/1.0'
122    server_version = 'OpenGnsys Test REST Server'
123    sys_version = ''
124   
125    def sendJsonError(self, code, message):
126        self.send_response(code)
127        self.send_header('Content-type', 'application/json')
128        self.end_headers()
129        self.wfile.write(json.dumps({'error': message}))
130        return
131
132    def sendJsonResponse(self, data):
133        self.send_response(200)
134        data = json.dumps(data)
135        self.send_header('Content-type', 'application/json')
136        self.send_header('Content-Length', len(data))
137        self.end_headers()
138        # Send the html message
139        self.wfile.write(data)
140       
141   
142    # parseURL
143    def parseUrl(self):
144        # Very simple path & params splitter
145        path = self.path.split('?')[0][1:].split('/')
146       
147        try:
148            params = dict((v[0], unquote(v[1])) for v in (v.split('=') for v in self.path.split('?')[1].split('&')))
149        except Exception:
150            params = {}
151       
152        return (path, params)
153   
154
155    def do_GET(self):
156        path, params = self.parseUrl()
157       
158        self.sendJsonResponse({'path': path, 'params': params})
159       
160    def do_POST(self):
161        path, getParams = self.parseUrl()
162       
163        # Now post parameters, that are in JSON format
164        self.sendJsonResponse({'path': path, 'params': getParams})
165
166    def log_error(self, fmt, *args):
167        logger.error('HTTP ' + fmt % args)
168       
169    def log_message(self, fmt, *args):
170        logger.info('HTTP ' + fmt % args)
171       
172
173class HTTPThreadingServer(ThreadingMixIn, HTTPServer):
174    pass
175
176class HTTPServerThread(threading.Thread):
177    def __init__(self, address, service):
178        super(self.__class__, self).__init__()
179
180        HTTPServerHandler.service = service
181
182        self.certFile = createSelfSignedCert()
183        self.server = HTTPThreadingServer(address, HTTPServerHandler)
184        self.server.socket = ssl.wrap_socket(self.server.socket, certfile=self.certFile, server_side=True)
185       
186        logger.info('Initialized HTTPS Server thread on {}'.format(address))
187
188    def getServerUrl(self):
189        return 'https://{}:{}/{}'.format(self.server.server_address[0], self.server.server_address[1], HTTPServerHandler.uuid)
190
191    def stop(self):
192        self.server.shutdown()
193
194    def run(self):
195        self.server.serve_forever()
196
197   
198
199if __name__ == '__main__':
200    logging.basicConfig(
201        filename='/tmp/restserver.log',
202        filemode='w',
203        format='%(levelname)s %(asctime)s %(message)s',
204        level=logging.DEBUG
205    )
206   
207    thr = HTTPServerThread(('0.0.0.0', 9999), None)
208    print('Server started: {}'.format(thr))
209    thr.run()
210   
Note: See TracBrowser for help on using the repository browser.