7e27639fdb
Change-Id: I11d3fecc9c767c95c1c1035806c28769ad7a895b Partially-Implements: bp console-support
147 lines
4.7 KiB
Python
147 lines
4.7 KiB
Python
# Copyright 2017 Huawei Technologies Co.,LTD.
|
|
#
|
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
|
# not use this file except in compliance with the License. You may obtain
|
|
# a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
# License for the specific language governing permissions and limitations
|
|
# under the License.
|
|
|
|
import select
|
|
import socket
|
|
|
|
import BaseHTTPServer
|
|
from oslo_context import context
|
|
import six
|
|
import SocketServer
|
|
import urlparse
|
|
|
|
from mogan.common import exception
|
|
from mogan.consoleauth import rpcapi as consoleauth_rpcapi
|
|
|
|
|
|
class ProxyHandler(BaseHTTPServer.BaseHTTPRequestHandler):
|
|
rbufsize = 0
|
|
|
|
def setup(self):
|
|
self.connection = self.request
|
|
self.rfile = socket._fileobject(self.request, "rb", self.rbufsize)
|
|
self.wfile = socket._fileobject(self.request, "wb", self.wbufsize)
|
|
|
|
def _connect_to(self, connect_info, soc):
|
|
host_port = connect_info['host'], connect_info['port']
|
|
try:
|
|
soc.connect(host_port)
|
|
except socket.error as e:
|
|
self.send_error(404, six.text_type(e))
|
|
return 0
|
|
return 1
|
|
|
|
def _check_valid(self):
|
|
query = urlparse.urlparse(self.path).query
|
|
token = urlparse.parse_qs(query).get("token", [""]).pop()
|
|
referer = self.headers.get('Referer', None)
|
|
if not token:
|
|
token = referer.split('?token=')[1]
|
|
|
|
ctxt = context.get_admin_context()
|
|
rpcapi = consoleauth_rpcapi.ConsoleAuthAPI()
|
|
connect_info = rpcapi.check_token(ctxt, token=token)
|
|
|
|
if not connect_info:
|
|
self.send_error(404, 'The token is invalid or has expired')
|
|
self.connection.close()
|
|
raise exception.InvalidToken(token=token)
|
|
|
|
return connect_info
|
|
|
|
def do_CONNECT(self):
|
|
connect_info = self._check_valid()
|
|
|
|
soc = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
|
try:
|
|
if self._connect_to(connect_info, soc):
|
|
self.log_request(200)
|
|
self.wfile.write(
|
|
self.protocol_version +
|
|
" 200 Connection Established\r\nConnection: close\r\n\r\n")
|
|
self.wfile.write("\r\n")
|
|
self._read_write(soc, 300)
|
|
finally:
|
|
soc.close()
|
|
self.connection.close()
|
|
|
|
def do_GET(self):
|
|
connect_info = self._check_valid()
|
|
|
|
soc = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
|
try:
|
|
if self._connect_to(connect_info, soc):
|
|
self.log_request()
|
|
soc.send("%s %s %s\r\n" % (
|
|
self.command,
|
|
urlparse.urlunparse(('', '', self.path, '', '', '')),
|
|
self.request_version))
|
|
self.headers['Connection'] = 'close'
|
|
for key_val in self.headers.items():
|
|
soc.send("%s: %s\r\n" % key_val)
|
|
soc.send("\r\n")
|
|
if self.command != 'GET':
|
|
length = int(self.headers['content-length'])
|
|
content = self.rfile.read(length)
|
|
soc.send("%s\r\n" % content)
|
|
soc.send("\r\n")
|
|
self._read_write(soc)
|
|
finally:
|
|
soc.close()
|
|
self.connection.close()
|
|
|
|
def _read_write(self, soc, max_idling=20):
|
|
iw = [self.connection, soc]
|
|
ow = []
|
|
count = 0
|
|
while 1:
|
|
count += 1
|
|
(ins, _, exs) = select.select(iw, ow, iw, 3)
|
|
if exs:
|
|
break
|
|
if ins:
|
|
for i in ins:
|
|
if i is soc:
|
|
out = self.connection
|
|
else:
|
|
out = soc
|
|
data = i.recv(8192)
|
|
if data:
|
|
out.send(data)
|
|
count = 0
|
|
if count == max_idling:
|
|
break
|
|
|
|
def do_OPTIONS(self):
|
|
try:
|
|
self.send_response(200)
|
|
self.end_headers()
|
|
except Exception:
|
|
pass
|
|
|
|
do_HEAD = do_GET
|
|
do_POST = do_GET
|
|
do_PUT = do_GET
|
|
do_DELETE = do_GET
|
|
|
|
|
|
class ThreadingHTTPServer(SocketServer.ThreadingMixIn,
|
|
BaseHTTPServer.HTTPServer):
|
|
def __init__(self, server_address, RequestHandlerClass, logger=None):
|
|
BaseHTTPServer.HTTPServer.__init__(self, server_address,
|
|
RequestHandlerClass)
|
|
|
|
def service_start(self):
|
|
self.serve_forever()
|