Added flask support #70 #75 #71

Merged
edraft merged 107 commits from #70 into 0.3 2022-11-05 13:55:42 +01:00
8 changed files with 64 additions and 21 deletions
Showing only changes of commit 801d4bf16b - Show all commits

View File

@ -13,7 +13,7 @@
},
"BotLoggingSettings": {
"Api": {
"Path": "logs/",
"Path": "logs/$date_now/",
"Filename": "api.log",
"ConsoleLogLevel": "TRACE",
"FileLogLevel": "TRACE"

View File

@ -8,7 +8,7 @@
"LoggingSettings": {
"Path": "logs/",
"Filename": "bot.log",
"ConsoleLogLevel": "TRACE",
"ConsoleLogLevel": "DEBUG",
edraft marked this conversation as resolved Outdated

Log Level evtl wieder auch Trace setzen?

Log Level evtl wieder auch Trace setzen?
"FileLogLevel": "TRACE"
},
"BotLoggingSettings": {
@ -27,7 +27,7 @@
"Database": {
"Path": "logs/",
"Filename": "database.log",
"ConsoleLogLevel": "TRACE",
"ConsoleLogLevel": "DEBUG",
"FileLogLevel": "TRACE"
},
"Message": {

View File

@ -13,7 +13,7 @@
},
"BotLoggingSettings": {
"Api": {
"Path": "logs/",
"Path": "logs/$date_now/",
"Filename": "api.log",
"ConsoleLogLevel": "ERROR",
"FileLogLevel": "INFO"

View File

@ -13,7 +13,7 @@
},
"BotLoggingSettings": {
"Api": {
"Path": "logs/",
"Path": "logs/$date_now/",
"Filename": "api.log",
"ConsoleLogLevel": "INFO",
"FileLogLevel": "DEBUG"

View File

@ -1,13 +1,15 @@
import json
import re
import sys
import textwrap
import uuid
from functools import partial
from typing import Union
import eventlet
from cpl_core.dependency_injection import ServiceProviderABC
from cpl_core.utils import CredentialManager
from eventlet import wsgi
from flask import Flask, request, jsonify, Response, make_response
from flask import Flask, request, jsonify, Response
from flask_cors import CORS
from flask_socketio import SocketIO
from werkzeug.exceptions import NotFound
@ -40,21 +42,36 @@ class Api(Flask):
self._logger = logger
self._services = services
self._apt_settings = api_settings
self._api_settings = api_settings
self._auth_settings = auth_settings
self._cors = CORS(self, support_credentials=True)
# register before request
self.before_request_funcs.setdefault(None, []).append(self.before_request)
# register hooks
self.before_request(self.before_request_hook)
self.after_request(self.after_request_hook)
# register error handler
exc_class, code = self._get_exc_class_and_code(Exception)
self.error_handler_spec[None][code][exc_class] = self.handle_exception
self.register_error_handler(exc_class, self.handle_exception)
# websockets
self._socketio = SocketIO(self, cors_allowed_origins='*', path='/api/socket.io')
self._socketio.on_event('connect', self.on_connect)
self._socketio.on_event('disconnect', self.on_disconnect)
self._requests = {}
@staticmethod
def _get_methods_from_registered_route() -> Union[list[str], str]:
methods = ['Unknown']
if request.path in Route.registered_routes and len(Route.registered_routes[request.path]) >= 1 and 'methods' in Route.registered_routes[request.path][1]:
methods = Route.registered_routes[request.path][1]['methods']
if len(methods) == 1:
return methods[0]
return methods
def _register_routes(self):
for path, f in Route.registered_routes.items():
route = f[0]
@ -88,20 +105,46 @@ class Api(Flask):
error = ErrorDTO(None, user_message)
return jsonify(error.to_dict()), 400
def before_request(self, *args, **kwargs):
self._logger.debug(__name__, f'Received GET @{request.url}')
headers = str(request.headers).replace("\n", "\n\t")
self._logger.trace(__name__, f'Headers: \n\t{headers}')
def before_request_hook(self):
request_id = uuid.uuid4()
self._requests[request] = request_id
method = request.access_control_request_method
self._logger.info(__name__, f'Received {request_id} @ {self._get_methods_from_registered_route() if method is None else method} {request.url} from {request.remote_addr}')
headers = str(request.headers).replace('\n', '\n\t\t')
data = request.get_data()
data = '' if len(data) == 0 else str(data.decode(encoding="utf-8"))
text = textwrap.dedent(f'Request: {request_id}:\n\tHeader:\n\t\t{headers}\n\tUser-Agent: {request.user_agent.string}\n\tBody: {data}')
self._logger.trace(__name__, text)
def after_request_hook(self, response: Response):
method = request.access_control_request_method
request_id = f'{self._get_methods_from_registered_route() if method is None else method} {request.url} from {request.remote_addr}'
if request in self._requests:
request_id = self._requests[request]
self._logger.info(__name__, f'Answered {request_id}')
headers = str(request.headers).replace('\n', '\n\t\t')
data = request.get_data()
data = '' if len(data) == 0 else str(data.decode(encoding="utf-8"))
text = textwrap.dedent(f'Request: {request_id}:\n\tHeader:\n\t\t{headers}\n\tResponse: {data}')
self._logger.trace(__name__, text)
return response
def start(self):
self._logger.info(__name__, f'Starting API {self._apt_settings.host}:{self._apt_settings.port}')
self._logger.info(__name__, f'Starting API {self._api_settings.host}:{self._api_settings.port}')
self._register_routes()
self.secret_key = CredentialManager.decrypt(self._auth_settings.secret_key)
# from waitress import serve
# https://docs.pylonsproject.org/projects/waitress/en/stable/arguments.html
# serve(self, host=self._apt_settings.host, port=self._apt_settings.port, threads=10, connection_limit=1000, channel_timeout=10)
wsgi.server(
eventlet.listen((self._apt_settings.host, self._apt_settings.port)),
eventlet.listen((self._api_settings.host, self._api_settings.port)),
self,
log_output=False
)

View File

@ -1,19 +1,18 @@
{
"Api": {
"Port": 5000,
"Port": 8044,
"Host": "0.0.0.0",
"RedirectToHTTPS": false
},
"Authentication": {
"SecretKey": "RjNiNUxEeisjSnZ6Zz1XIUBnc2EleHNG",
"Issuer": "http://localhost:5000",
"Issuer": "http://localhost:8084",
"Audience": "http://localhost:4200",
"TokenExpireTime": 1,
"RefreshTokenExpireTime": 7
},
"DiscordAuthentication": {
"ClientSecret": "V3FTb3JYVFBiVktEeHZxdWJDWW4xcnBCbXRwdmpwcy0=",
"_RedirectURL": "http://localhost:5000/api/auth/discord/register",
"RedirectURL": "http://localhost:4200/auth/register",
"Scope": [
"identify",

View File

@ -37,7 +37,7 @@ import { SettingsService } from './services/settings/settings.service';
JwtModule.forRoot({
config: {
tokenGetter,
allowedDomains: ['localhost:5000', 'localhost:5001'],
allowedDomains: ['localhost:8044', 'localhost:8041', 'localhost:5000'],
disallowedRoutes: []
}
}),

View File

@ -56,6 +56,7 @@ export class SocketService {
this.socket.on("disconnect", () => {
if (this.disconnected) {
this.spinnerService.showSpinner();
return;
}