166 lines
5.8 KiB
Python
166 lines
5.8 KiB
Python
import re
|
|
from typing import Dict
|
|
from yarl import URL
|
|
import aiohttp
|
|
from aiohttp.web import (Application,
|
|
HTTPException,
|
|
Request, Response, get,
|
|
json_response, middleware, post, HTTPSeeOther)
|
|
from aiohttp.client import ClientSession
|
|
from injector import inject, singleton, Injector, provider
|
|
|
|
from backup.time import Time
|
|
from backup.logger import getLogger
|
|
from backup.server import Server
|
|
from tests.faketime import FakeTime
|
|
from backup.module import BaseModule
|
|
from backup.config import Config, Setting
|
|
from .http_exception import HttpMultiException
|
|
from .simulated_google import SimulatedGoogle
|
|
from .base_server import BaseServer
|
|
from .ports import Ports
|
|
from .request_interceptor import RequestInterceptor
|
|
from .simulated_supervisor import SimulatedSupervisor
|
|
from .apiingress import APIIngress
|
|
import aiorun
|
|
|
|
logger = getLogger(__name__)
|
|
|
|
mimeTypeQueryPattern = re.compile("^mimeType='.*'$")
|
|
parentsQueryPattern = re.compile("^'.*' in parents$")
|
|
bytesPattern = re.compile("^bytes \\d+-\\d+/\\d+$")
|
|
resumeBytesPattern = re.compile("^bytes \\*/\\d+$")
|
|
intPattern = re.compile("\\d+")
|
|
rangePattern = re.compile("bytes=\\d+-\\d+")
|
|
|
|
|
|
@singleton
|
|
class SimulationServer(BaseServer):
|
|
@inject
|
|
def __init__(self, ports: Ports, time: Time, session: ClientSession, authserver: Server, config: Config, google: SimulatedGoogle, supervisor: SimulatedSupervisor, api_ingress: APIIngress, interceptor: RequestInterceptor):
|
|
self.interceptor = interceptor
|
|
self.google = google
|
|
self.supervisor = supervisor
|
|
self.config = config
|
|
self.id_counter = 0
|
|
self.files: Dict[str, bytearray] = {}
|
|
self._port = ports.server
|
|
self._time: FakeTime = time
|
|
self.urls = []
|
|
self.relative = True
|
|
self._authserver = authserver
|
|
self._api_ingress = api_ingress
|
|
|
|
def wasUrlRequested(self, pattern):
|
|
for url in self.urls:
|
|
if pattern in url:
|
|
return True
|
|
return False
|
|
|
|
def blockBackups(self):
|
|
self.block_backups = True
|
|
|
|
def unBlockBackups(self):
|
|
self.block_backups = False
|
|
|
|
async def uploadfile(self, request: Request):
|
|
name: str = str(request.query.get("name", "test"))
|
|
self.files[name] = await self.readAll(request)
|
|
return Response(text="")
|
|
|
|
async def readFile(self, request: Request):
|
|
return self.serve_bytes(request, self.files[request.query.get("name", "test")])
|
|
|
|
async def slugRedirect(self, request: Request):
|
|
raise HTTPSeeOther("https://localhost:" + str(self.config.get(Setting.INGRESS_PORT)))
|
|
|
|
@middleware
|
|
async def error_middleware(self, request: Request, handler):
|
|
self.urls.append(str(request.url))
|
|
resp = await self.interceptor.checkUrl(request)
|
|
if resp is not None:
|
|
return resp
|
|
try:
|
|
resp = await handler(request)
|
|
return resp
|
|
except Exception as ex:
|
|
await self.readAll(request)
|
|
if isinstance(ex, HttpMultiException):
|
|
return Response(status=ex.status_code)
|
|
elif isinstance(ex, HTTPException):
|
|
raise
|
|
else:
|
|
logger.printException(ex)
|
|
return json_response(str(ex), status=500)
|
|
|
|
def createApp(self):
|
|
app = Application(middlewares=[self.error_middleware])
|
|
app.add_routes(self.routes())
|
|
self._authserver.buildApp(app)
|
|
return app
|
|
|
|
async def start(self, port):
|
|
self.runner = aiohttp.web.AppRunner(self.createApp())
|
|
await self.runner.setup()
|
|
site = aiohttp.web.TCPSite(self.runner, "0.0.0.0", port=port)
|
|
await site.start()
|
|
|
|
async def stop(self):
|
|
self.interceptor.stop()
|
|
await self.runner.shutdown()
|
|
await self.runner.cleanup()
|
|
|
|
def routes(self):
|
|
return [
|
|
get('/readfile', self.readFile),
|
|
post('/uploadfile', self.uploadfile),
|
|
get('/ingress/self_slug', self.slugRedirect),
|
|
get('/debug/config', self.debug_config)
|
|
] + self.google.routes() + self.supervisor.routes() + self._api_ingress.routes()
|
|
|
|
async def debug_config(self, request: Request):
|
|
return json_response(self.supervisor._options)
|
|
|
|
|
|
class SimServerModule(BaseModule):
|
|
def __init__(self, base_url: URL):
|
|
super().__init__(override_dns=False)
|
|
self._base_url = base_url
|
|
|
|
@provider
|
|
@singleton
|
|
def getConfig(self) -> Config:
|
|
return Config.withOverrides({
|
|
Setting.DRIVE_AUTHORIZE_URL: str(self._base_url.with_path("o/oauth2/v2/auth")),
|
|
Setting.AUTHORIZATION_HOST: str(self._base_url),
|
|
Setting.TOKEN_SERVER_HOSTS: str(self._base_url),
|
|
Setting.DRIVE_TOKEN_URL: str(self._base_url.with_path("token")),
|
|
Setting.DRIVE_DEVICE_CODE_URL: str(self._base_url.with_path("device/code")),
|
|
Setting.DRIVE_REFRESH_URL: str(self._base_url.with_path("oauth2/v4/token")),
|
|
Setting.INGRESS_PORT: 56152
|
|
})
|
|
|
|
@provider
|
|
@singleton
|
|
def getPorts(self) -> Ports:
|
|
return Ports(56153, 56151, 56152)
|
|
|
|
|
|
async def main():
|
|
port = 56153
|
|
base = URL("http://localhost").with_port(port)
|
|
injector = Injector(SimServerModule(base))
|
|
server = injector.get(SimulationServer)
|
|
|
|
# start the server
|
|
runner = aiohttp.web.AppRunner(server.createApp())
|
|
await runner.setup()
|
|
site = aiohttp.web.TCPSite(runner, "0.0.0.0", port=port)
|
|
await site.start()
|
|
print("Server started on port " + str(port))
|
|
print("Open a browser at http://localhost:" + str(port))
|
|
|
|
|
|
if __name__ == '__main__':
|
|
aiorun.run(main())
|