Latest Threat Research:SANDWORM_MODE: Shai-Hulud-Style npm Worm Hijacks CI Workflows and Poisons AI Toolchains.Details
Socket
Book a DemoInstallSign in
Socket

app-server

Package Overview
Dependencies
Maintainers
1
Versions
28
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

app-server - npm Package Compare versions

Comparing version
0.9.9
to
0.9.10
+1
-1
PKG-INFO
Metadata-Version: 2.1
Name: app_server
Version: 0.9.9
Version: 0.9.10
Summary: a lightweight web application launcher for gunicorn and static files.

@@ -5,0 +5,0 @@ Home-page: https://github.com/viur-framework/viur-app_server

Metadata-Version: 2.1
Name: app_server
Version: 0.9.9
Version: 0.9.10
Summary: a lightweight web application launcher for gunicorn and static files.

@@ -5,0 +5,0 @@ Home-page: https://github.com/viur-framework/viur-app_server

@@ -1,21 +0,30 @@

import sys, os, re, subprocess, yaml, argparse, time, mimetypes, logging
import argparse
import logging
import mimetypes
import os
import re
import subprocess
import sys
import time
import typing as t
import yaml
from werkzeug._internal import _logger # noqa
from werkzeug.http import http_date, is_resource_modified
from werkzeug.middleware.dispatcher import DispatcherMiddleware
from werkzeug.middleware.http_proxy import ProxyMiddleware
from werkzeug.middleware.shared_data import SharedDataMiddleware
from werkzeug.serving import run_simple, WSGIRequestHandler, _ansi_style, \
_log_add_style
from werkzeug.urls import uri_to_iri
from werkzeug.utils import get_content_type
from werkzeug.wrappers import Request, Response
from werkzeug.middleware.shared_data import SharedDataMiddleware
from werkzeug.middleware.http_proxy import ProxyMiddleware
from werkzeug.middleware.dispatcher import DispatcherMiddleware
from werkzeug.serving import run_simple, WSGIRequestHandler,_ansi_style,_log_add_style
from werkzeug.wsgi import get_path_info, wrap_file
from werkzeug.utils import get_content_type
from werkzeug.http import http_date, is_resource_modified
from werkzeug._internal import _logger
from werkzeug.urls import uri_to_iri, url_unquote
__version__ = "0.9.10"
subprocesses = []
__version__ = "0.9.9"
subprocesses = []
class myWSGIRequestHandler(WSGIRequestHandler):
class MainWSGIRequestHandler(WSGIRequestHandler):
def log_date_time_string(self):

@@ -26,7 +35,10 @@ """Return the current time formatted for logging."""

s = "%04d-%02d-%02d %02d:%02d:%02d" % (
year , month,day , hh, mm, ss)
year, month, day, hh, mm, ss)
return s
def log_request(self, code: t.Union[int, str] = "-", size: t.Union[int, str] = "-") -> None:
def log_request(
self,
code: t.Union[int, str] = "-",
size: t.Union[int, str] = "-",
) -> None:
"""coloring the status code"""

@@ -43,3 +55,3 @@ try:

log_type = "info"
if code != "200": #possibility to filter 200 requests
if code != "200": # possibility to filter 200 requests
log_type = "warning"

@@ -73,6 +85,7 @@

getattr(_logger, type)(f"[{self.log_date_time_string()}] {message % args}")
getattr(_logger, type)(
f"[{self.log_date_time_string()}] {message % args}")
class WrappingApp(object):
class WrappingApp:
"""simple wrapping app"""

@@ -85,3 +98,4 @@

request = Request(environ)
response = Response(f'Path not found or invalid: {request.path}', status=404)
response = Response(f'Path not found or invalid: {request.path}',
status=404)
return response(environ, start_response)

@@ -92,3 +106,4 @@

class myProxy(ProxyMiddleware):
class Proxy(ProxyMiddleware):
"""this addition allows to redirect all routes to given targets"""

@@ -110,3 +125,4 @@

def __call__(self, environ: "WSGIEnvironment", start_response: "StartResponse") -> t.Iterable[bytes]:
def __call__(self, environ: "WSGIEnvironment",
start_response: "StartResponse") -> t.Iterable[bytes]:
path = get_path_info(environ, charset='utf-8', errors='replace')

@@ -121,3 +137,4 @@ app = self.app

class myDispatcher(DispatcherMiddleware):
class Dispatcher(DispatcherMiddleware):
"""use regex to find a matching route"""

@@ -135,16 +152,17 @@

class mySharedData(SharedDataMiddleware):
class SharedData(SharedDataMiddleware):
"""use regex to find a matching files"""
def __init__(
self,
app,
exports,
disallow: None = None,
cache: bool = True,
cache_timeout: int = 60 * 60 * 12,
fallback_mimetype: str = "application/octet-stream",
self,
app,
exports,
disallow: None = None,
cache: bool = True,
cache_timeout: int = 60 * 60 * 12,
fallback_mimetype: str = "application/octet-stream",
) -> None:
self.org_exports = exports.copy()
super().__init__(app, exports, disallow, cache, cache_timeout, fallback_mimetype)
super().__init__(app, exports, disallow, cache, cache_timeout,
fallback_mimetype)

@@ -158,4 +176,6 @@ def __call__(self, environ, start_response):

if re.match(search_path, path):
real_path = re.sub(search_path, self.org_exports[search_path], path, 1)
real_filename, file_loader = self.get_file_loader(real_path)(None)
real_path = re.sub(search_path, self.org_exports[search_path],
path, 1)
real_filename, file_loader = self.get_file_loader(real_path)(
None)

@@ -180,7 +200,8 @@ if file_loader is not None:

if file_loader is None or not self.is_allowed(real_filename): # type: ignore
if file_loader is None or not self.is_allowed(real_filename): # noqa
return self.app(environ, start_response)
guessed_type = mimetypes.guess_type(real_filename) # type: ignore
mime_type = get_content_type(guessed_type[0] or self.fallback_mimetype, "utf-8")
mime_type = get_content_type(guessed_type[0] or self.fallback_mimetype,
"utf-8")

@@ -196,3 +217,4 @@ try:

timeout = self.cache_timeout
etag = self.generate_etag(mtime, file_size, real_filename) # type: ignore
etag = self.generate_etag(mtime, file_size,
real_filename) # type: ignore
headers += [

@@ -223,3 +245,11 @@ ("Etag", f'"{etag}"'),

def start_server(host, port, gunicorn_port, appFolder, appYaml, timeout, protocol="http"):
def start_server(
host: str,
port: int,
gunicorn_port: int,
app_folder: str,
app_yaml: dict,
timeout: int,
protocol: str = "http",
) -> None:
"""use the dispatcherMiddleware to connect SharedDataMiddleware and ProxyMiddleware with the wrapping app."""

@@ -230,3 +260,3 @@ app = WrappingApp({})

# make shared middlewares for static files as configured in app.yaml
for route in appYaml["handlers"]:
for route in app_yaml["handlers"]:
if path := route.get("static_dir"):

@@ -242,5 +272,7 @@ pattern = route["url"] + "/.*"

# print(pattern, route["url"], path)
apps[pattern] = mySharedData(app.wsgi_app, {route["url"]: os.path.join(appFolder, path)})
apps[pattern] = SharedData(
app.wsgi_app, {route["url"]: os.path.join(app_folder, path)}
)
apps.update({"/": myProxy(app.wsgi_app, {
apps["/"] = Proxy(app.wsgi_app, {
"/": {

@@ -250,9 +282,10 @@ "target": f"{protocol}://{host}:{gunicorn_port}/",

}
},timeout=timeout)})
app.wsgi_app = myDispatcher(app.wsgi_app, apps)
}, timeout=timeout)
app.wsgi_app = Dispatcher(app.wsgi_app, apps)
run_simple(host, port, app, use_debugger=False, use_reloader=True, threaded=True, request_handler=myWSGIRequestHandler)
run_simple(host, port, app, use_debugger=False, use_reloader=True,
threaded=True, request_handler=MainWSGIRequestHandler)
def envVars(application_id: str, args: argparse.Namespace, app_yaml: dict):
def set_env_vars(application_id: str, args: argparse.Namespace, app_yaml: dict):
"""set necessary environment variables"""

@@ -263,3 +296,4 @@ # First, merge the app.yaml into the environment so that the variables

if not isinstance(env_vars, dict):
raise TypeError(f"env_variables section in app.yaml must be a dict. Got {type(env_vars)}")
raise TypeError(
f"env_variables section in app.yaml must be a dict. Got {type(env_vars)}")
os.environ |= {k: str(v) for k, v in app_yaml["env_variables"].items()}

@@ -274,3 +308,4 @@

if args.storage:
os.environ["STORAGE_EMULATOR_HOST"] = f"http://{args.host}:{args.storage_port}"
os.environ["STORAGE_EMULATOR_HOST"] = \
f"http://{args.host}:{args.storage_port}"

@@ -284,2 +319,3 @@ if args.tasks:

def patch_gunicorn():

@@ -300,14 +336,22 @@ import gunicorn.workers.base

def start_gunicorn(args, appYaml, appFolder, myFolder):
def start_gunicorn(
args: argparse.Namespace,
app_yaml: dict,
app_folder: str,
) -> None:
# Gunicorn call command
entrypoint = appYaml.get("entrypoint", "gunicorn -b :$PORT -w $WORKER --threads $THREADS "
"--disable-redirect-access-to-syslog main:app")
for var, value in {
"PORT": args.gunicorn_port,
"WORKER": args.worker,
"THREADS": args.threads
}.items():
entrypoint = entrypoint.replace(f"${var}", str(value))
if not (entrypoint := args.entrypoint):
entrypoint = app_yaml.get(
"entrypoint",
"gunicorn -b :$PORT --disable-redirect-access-to-syslog main:app"
)
entrypoint = entrypoint.replace(f"$PORT", str(args.gunicorn_port))
# Remove -w / --workers / --threads arguments,
# we set them later with the values from our argparser
entrypoint = re.sub(r"\s+-(w|-workers|-threads)\s+\d+", " ", entrypoint)
entrypoint = entrypoint.split()
entrypoint.extend(["--workers", str(args.workers)])
entrypoint.extend(["--threads", str(args.threads)])
if "--reload" not in entrypoint:

@@ -320,6 +364,5 @@ entrypoint.insert(1, "--reload")

os.chdir(appFolder)
subprocesses.append(subprocess.Popen(entrypoint))
os.chdir(myFolder)
subprocesses.append(subprocess.Popen(entrypoint, cwd=app_folder))
def main():

@@ -334,23 +377,43 @@ """main entrypoint

ap = argparse.ArgumentParser(
description="alternative dev_appserver"
description="alternative dev_appserver",
epilog=f"Version: {__version__}"
)
ap.add_argument("config_paths", metavar='yaml_path', nargs='+', help='Path to app.yaml file')
ap.add_argument("config_paths", metavar='yaml_path', nargs='+',
help='Path to app.yaml file')
ap.add_argument(
'-A', '--application', action='store', dest='app_id', required=True, help='Set the application id')
ap.add_argument('--host', default="localhost", help='host name to which application modules should bind')
ap.add_argument('--port', type=int, default=8080, help='port to which we bind the application')
ap.add_argument('--gunicorn_port', type=int, default=8090, help='internal gunicorn port')
ap.add_argument('--worker', type=int, default=1, help='amount of gunicorn workers')
ap.add_argument('--threads', type=int, default=5, help='amount of gunicorn threads')
ap.add_argument('--timeout', type=int, default=60, help='Time is seconds before gunicorn abort a request')
ap.add_argument('-V', '--version', action='version', version='%(prog)s ' + __version__)
'-A', '--application', action='store', dest='app_id', required=True,
help='Set the application id')
ap.add_argument('--host', default="localhost",
help='host name to which application modules should bind')
ap.add_argument('--entrypoint', type=str, default=None,
help='The entrypoint is the basic gunicorn command. By default, it\'s taken from app.yaml. '
'This parameter can be used to set a different entrypoint. '
'To provide this parameter via ViUR-CLI, you have to double quote it: '
' --entrypoint "\'gunicorn -b :\$PORT --disable-redirect-access-to-syslog main:app\'"')
ap.add_argument('--port', type=int, default=8080,
help='port to which we bind the application')
ap.add_argument('--gunicorn_port', type=int, default=8090,
help='internal gunicorn port')
ap.add_argument('--workers', '--worker', type=int, default=1,
help='amount of gunicorn workers')
ap.add_argument('--threads', type=int, default=5,
help='amount of gunicorn threads')
ap.add_argument('--timeout', type=int, default=60,
help='Time is seconds before gunicorn abort a request')
ap.add_argument('-V', '--version', action='version',
version='%(prog)s ' + __version__)
ap.add_argument('--storage', default=False, action="store_true", dest="storage", help="also start Storage Emulator")
ap.add_argument('--storage_port', type=int, default=8092, help='internal Storage Emulator Port')
ap.add_argument('--storage', default=False, action="store_true",
dest="storage", help="also start Storage Emulator")
ap.add_argument('--storage_port', type=int, default=8092,
help='internal Storage Emulator Port')
ap.add_argument('--tasks', default=False, action='store_true', dest="tasks", help='also start Task-Queue Emulator')
ap.add_argument('--tasks_port', type=int, default=8091, help='internal Task-Queue Emulator Port')
ap.add_argument('--tasks', default=False, action='store_true', dest="tasks",
help='also start Task-Queue Emulator')
ap.add_argument('--tasks_port', type=int, default=8091,
help='internal Task-Queue Emulator Port')
ap.add_argument('--cron', default=False, action='store_true', dest="cron", help='also start Cron Emulator')
ap.add_argument('--cron', default=False, action='store_true', dest="cron",
help='also start Cron Emulator')

@@ -366,40 +429,43 @@ ap.add_argument(

appFolder = os.path.abspath(args.config_paths[0])
app_folder = os.path.abspath(args.config_paths[0])
# load & parse the app.yaml
with open(os.path.join(appFolder, "app.yaml"), "r") as f:
appYaml = yaml.load(f, Loader=yaml.Loader)
with open(os.path.join(app_folder, "app.yaml"), "r") as f:
app_yaml = yaml.load(f, Loader=yaml.Loader)
envVars(args.app_id, args, appYaml)
set_env_vars(args.app_id, args, app_yaml)
patch_gunicorn()
myFolder = os.getcwd()
# Check for correct runtime
myRuntime = f"python{sys.version_info.major}{sys.version_info.minor}"
appRuntime = appYaml["runtime"]
assert appRuntime == myRuntime, f"app.yaml specifies {appRuntime} but you're on {myRuntime}, please correct this."
current_runtime = f"python{sys.version_info.major}{sys.version_info.minor}"
app_runtime = app_yaml["runtime"]
assert app_runtime == current_runtime, f"app.yaml specifies {app_runtime} but you're on {current_runtime}, please correct this."
if "WERKZEUG_RUN_MAIN" in os.environ and os.environ["WERKZEUG_RUN_MAIN"]:
#only start subprocesses wenn reloader starts
# only start subprocesses wenn reloader starts
if args.storage:
storage_subprocess =subprocess.Popen(
f"gcloud-storage-emulator start --port={args.storage_port} --default-bucket={args.app_id}.appspot.com".split())
storage_subprocess = subprocess.Popen(
f"gcloud-storage-emulator start --port={args.storage_port}"
f" --default-bucket={args.app_id}.appspot.com".split())
subprocesses.append(storage_subprocess)
if args.tasks and os.path.exists(os.path.join(appFolder, 'queue.yaml')):
if args.tasks and os.path.exists(
os.path.join(app_folder, 'queue.yaml')):
cron = ""
if args.cron:
cron = f"--cron-yaml={os.path.join(appFolder, 'cron.yaml')}"
cron = f"--cron-yaml={os.path.join(app_folder, 'cron.yaml')}"
tasks_subprocess = subprocess.Popen(
f"gcloud-tasks-emulator start -p={args.tasks_port} -t={args.port} {cron} --queue-yaml={os.path.join(appFolder, 'queue.yaml')} --queue-yaml-project={args.app_id} --queue-yaml-location=local -r 50".split())
f"gcloud-tasks-emulator start -p={args.tasks_port} -t={args.port} {cron}"
f" --queue-yaml={os.path.join(app_folder, 'queue.yaml')}"
f" --queue-yaml-project={args.app_id} --queue-yaml-location=local -r 50".split())
subprocesses.append(tasks_subprocess)
start_gunicorn(args, appYaml, appFolder, myFolder)
start_gunicorn(args, app_yaml, app_folder)
start_server(args.host, args.port, args.gunicorn_port, appFolder, appYaml, args.timeout)
start_server(args.host, args.port, args.gunicorn_port, app_folder, app_yaml,
args.timeout)

@@ -415,2 +481,1 @@ try:

main()