int uwsgi_python_mount_app(char *mountpoint, char *app, int regexp) { int id; if (strchr(app, ':') || uwsgi_endswith(app, ".py") || uwsgi_endswith(app, ".wsgi")) { uwsgi.wsgi_req->appid = mountpoint; uwsgi.wsgi_req->appid_len = strlen(mountpoint); if (uwsgi.single_interpreter) { id = init_uwsgi_app(LOADER_MOUNT, app, uwsgi.wsgi_req, up.main_thread, PYTHON_APP_TYPE_WSGI); } else { id = init_uwsgi_app(LOADER_MOUNT, app, uwsgi.wsgi_req, NULL, PYTHON_APP_TYPE_WSGI); } #ifdef UWSGI_PCRE int i; if (regexp && id != -1) { struct uwsgi_app *ua = &uwsgi_apps[id]; uwsgi_regexp_build(mountpoint, &ua->pattern, &ua->pattern_extra); if (uwsgi.mywid == 0) { for(i=1;i<=uwsgi.numproc;i++) { uwsgi.workers[i].apps[id].pattern = ua->pattern; uwsgi.workers[i].apps[id].pattern_extra = ua->pattern_extra; } } } #endif return id; } return -1; }
int uwsgi_python_mount_app(char *mountpoint, char *app) { int id; if (strchr(app, ':') || uwsgi_endswith(app, ".py") || uwsgi_endswith(app, ".wsgi")) { uwsgi.wsgi_req->appid = mountpoint; uwsgi.wsgi_req->appid_len = strlen(mountpoint); if (uwsgi.single_interpreter) { id = init_uwsgi_app(LOADER_MOUNT, app, uwsgi.wsgi_req, up.main_thread, PYTHON_APP_TYPE_WSGI); } else { id = init_uwsgi_app(LOADER_MOUNT, app, uwsgi.wsgi_req, NULL, PYTHON_APP_TYPE_WSGI); } return id; } return -1; }
void uwsgi_textApp(void *userData, const char *s, int len) { struct wsgi_request *wsgi_req = (struct wsgi_request *) userData ; if (current_xmlnode) { wsgi_req->wsgi_script = (char *) s; wsgi_req->wsgi_script_len = len; init_uwsgi_app(NULL, NULL); current_xmlnode = 0; } };
void uwsgi_python_init_apps() { struct http_status_codes *http_sc; #ifndef UWSGI_PYPY // prepare for stack suspend/resume if (uwsgi.async > 1) { up.current_recursion_depth = uwsgi_malloc(sizeof(int)*uwsgi.async); up.current_frame = uwsgi_malloc(sizeof(struct _frame)*uwsgi.async); } #endif // setup app loaders #ifdef UWSGI_MINTERPRETERS up.loaders[LOADER_DYN] = uwsgi_dyn_loader; #endif up.loaders[LOADER_UWSGI] = uwsgi_uwsgi_loader; up.loaders[LOADER_FILE] = uwsgi_file_loader; up.loaders[LOADER_PASTE] = uwsgi_paste_loader; up.loaders[LOADER_EVAL] = uwsgi_eval_loader; up.loaders[LOADER_MOUNT] = uwsgi_mount_loader; up.loaders[LOADER_CALLABLE] = uwsgi_callable_loader; up.loaders[LOADER_STRING_CALLABLE] = uwsgi_string_callable_loader; struct uwsgi_string_list *upli = up.import_list; while(upli) { if (strchr(upli->value, '/') || uwsgi_endswith(upli->value, ".py")) { uwsgi_pyimport_by_filename(uwsgi_pythonize(upli->value), upli->value); } else { if (PyImport_ImportModule(upli->value) == NULL) { PyErr_Print(); } } upli = upli->next; } struct uwsgi_string_list *uppa = up.post_pymodule_alias; PyObject *modules = PyImport_GetModuleDict(); PyObject *tmp_module; while(uppa) { // split key=value char *value = strchr(uppa->value, '='); if (!value) { uwsgi_log("invalid pymodule-alias syntax\n"); goto next; } value[0] = 0; if (!strchr(value + 1, '/')) { // this is a standard pymodule tmp_module = PyImport_ImportModule(value + 1); if (!tmp_module) { PyErr_Print(); exit(1); } PyDict_SetItemString(modules, uppa->value, tmp_module); } else { // this is a filepath that need to be mapped tmp_module = uwsgi_pyimport_by_filename(uppa->value, value + 1); if (!tmp_module) { PyErr_Print(); exit(1); } } uwsgi_log("mapped virtual pymodule \"%s\" to real pymodule \"%s\"\n", uppa->value, value + 1); // reset original value value[0] = '='; next: uppa = uppa->next; } if (up.wsgi_config != NULL) { init_uwsgi_app(LOADER_UWSGI, up.wsgi_config, uwsgi.wsgi_req, up.main_thread, PYTHON_APP_TYPE_WSGI); } if (up.file_config != NULL) { init_uwsgi_app(LOADER_FILE, up.file_config, uwsgi.wsgi_req, up.main_thread, PYTHON_APP_TYPE_WSGI); } if (up.paste != NULL) { init_uwsgi_app(LOADER_PASTE, up.paste, uwsgi.wsgi_req, up.main_thread, PYTHON_APP_TYPE_WSGI); } if (up.eval != NULL) { init_uwsgi_app(LOADER_EVAL, up.eval, uwsgi.wsgi_req, up.main_thread, PYTHON_APP_TYPE_WSGI); } if (up.web3 != NULL) { init_uwsgi_app(LOADER_UWSGI, up.web3, uwsgi.wsgi_req, up.main_thread, PYTHON_APP_TYPE_WEB3); } if (up.pump != NULL) { init_uwsgi_app(LOADER_UWSGI, up.pump, uwsgi.wsgi_req, up.main_thread, PYTHON_APP_TYPE_PUMP); // filling http status codes for (http_sc = hsc; http_sc->message != NULL; http_sc++) { http_sc->message_size = (int) strlen(http_sc->message); } } if (up.wsgi_lite != NULL) { init_uwsgi_app(LOADER_UWSGI, up.wsgi_lite, uwsgi.wsgi_req, up.main_thread, PYTHON_APP_TYPE_WSGI_LITE); } #ifndef UWSGI_PYPY if (uwsgi.profiler) { if (!strcmp(uwsgi.profiler, "pycall")) { PyEval_SetProfile(uwsgi_python_profiler_call, NULL); } else if (!strcmp(uwsgi.profiler, "pyline")) { PyEval_SetTrace(uwsgi_python_tracer, NULL); } } #endif PyObject *uwsgi_dict = get_uwsgi_pydict("uwsgi"); if (uwsgi_dict) { up.after_req_hook = PyDict_GetItemString(uwsgi_dict, "after_req_hook"); if (up.after_req_hook) { Py_INCREF(up.after_req_hook); up.after_req_hook_args = PyTuple_New(0); Py_INCREF(up.after_req_hook_args); } } }
int init_uwsgi_app(int loader, void *arg1, struct wsgi_request *wsgi_req, PyThreadState *interpreter, int app_type) { PyObject *app_list = NULL, *applications = NULL; if (uwsgi_apps_cnt >= uwsgi.max_apps) { uwsgi_log("ERROR: you cannot load more than %d apps in a worker\n", uwsgi.max_apps); return -1; } int id = uwsgi_apps_cnt; int multiapp = 0; int i; struct uwsgi_app *wi; time_t now = uwsgi_now(); if (uwsgi_get_app_id(NULL, wsgi_req->appid, wsgi_req->appid_len, -1) != -1) { uwsgi_log( "mountpoint %.*s already configured. skip.\n", wsgi_req->appid_len, wsgi_req->appid); return -1; } wi = &uwsgi_apps[id]; memset(wi, 0, sizeof(struct uwsgi_app)); wi->mountpoint_len = wsgi_req->appid_len < 0xff ? wsgi_req->appid_len : (0xff-1); strncpy(wi->mountpoint, wsgi_req->appid, wi->mountpoint_len); // dynamic chdir ? if (wsgi_req->chdir_len > 0) { strncpy(wi->chdir, wsgi_req->chdir, wsgi_req->chdir_len < 0xff ? wsgi_req->chdir_len : (0xff-1)); #ifdef UWSGI_DEBUG uwsgi_debug("chdir to %s\n", wi->chdir); #endif if (chdir(wi->chdir)) { uwsgi_error("chdir()"); } } // Initialize a new environment for the new interpreter // reload "os" environ to allow dynamic setenv() if (up.reload_os_env) { char **e, *p; PyObject *k, *env_value; PyObject *os_module = PyImport_ImportModule("os"); if (os_module) { PyObject *os_module_dict = PyModule_GetDict(os_module); PyObject *py_environ = PyDict_GetItemString(os_module_dict, "environ"); if (py_environ) { for (e = environ; *e != NULL; e++) { p = strchr(*e, '='); if (p == NULL) continue; k = PyString_FromStringAndSize(*e, (int)(p-*e)); if (k == NULL) { PyErr_Print(); continue; } env_value = PyString_FromString(p+1); if (env_value == NULL) { PyErr_Print(); Py_DECREF(k); continue; } #ifdef UWSGI_DEBUG uwsgi_log("%s = %s\n", PyString_AsString(k), PyString_AsString(env_value)); #endif if (PyObject_SetItem(py_environ, k, env_value)) { PyErr_Print(); } Py_DECREF(k); Py_DECREF(env_value); } } } } if (interpreter == NULL && id) { wi->interpreter = Py_NewInterpreter(); if (!wi->interpreter) { uwsgi_log( "unable to initialize the new python interpreter\n"); exit(1); } PyThreadState_Swap(wi->interpreter); init_pyargv(); // we need to inizialize an embedded module for every interpreter init_uwsgi_embedded_module(); init_uwsgi_vars(); } else if (interpreter) { wi->interpreter = interpreter; } else { wi->interpreter = up.main_thread; } if (wsgi_req->home_len) { set_dyn_pyhome(wsgi_req->home, wsgi_req->home_len); } if (wsgi_req->touch_reload_len > 0 && wsgi_req->touch_reload_len < 0xff) { struct stat trst; strncpy(wi->touch_reload, wsgi_req->touch_reload, wsgi_req->touch_reload_len); if (!stat(wi->touch_reload, &trst)) { wi->touch_reload_mtime = trst.st_mtime; } } wi->callable = up.loaders[loader](arg1); if (!wi->callable) { uwsgi_log("unable to load app %d (mountpoint='%s') (callable not found or import error)\n", id, wi->mountpoint); goto doh; } // the module contains multiple apps if (PyDict_Check((PyObject *)wi->callable)) { applications = wi->callable; uwsgi_log("found a multiapp module...\n"); app_list = PyDict_Keys(applications); multiapp = PyList_Size(app_list); if (multiapp < 1) { uwsgi_log("you have to define at least one app in the apllications dictionary\n"); goto doh; } PyObject *app_mnt = PyList_GetItem(app_list, 0); if (!PyString_Check(app_mnt)) { uwsgi_log("the app mountpoint must be a string\n"); goto doh; } char *tmp_mountpoint = PyString_AsString(app_mnt); wi->mountpoint_len = strlen(wi->mountpoint) < 0xff ? strlen(wi->mountpoint) : (0xff-1); strncpy(wi->mountpoint, tmp_mountpoint, wi->mountpoint_len); wsgi_req->appid = wi->mountpoint; wsgi_req->appid_len = wi->mountpoint_len; #ifdef UWSGI_DEBUG uwsgi_log("main mountpoint = %s\n", wi->mountpoint); #endif wi->callable = PyDict_GetItem(applications, app_mnt); if (PyString_Check((PyObject *) wi->callable)) { PyObject *callables_dict = get_uwsgi_pydict((char *)arg1); if (callables_dict) { wi->callable = PyDict_GetItem(callables_dict, (PyObject *)wi->callable); } } } Py_INCREF((PyObject *)wi->callable); wi->environ = malloc(sizeof(PyObject*)*uwsgi.cores); if (!wi->environ) { uwsgi_error("malloc()"); exit(1); } for(i=0;i<uwsgi.cores;i++) { wi->environ[i] = PyDict_New(); if (!wi->environ[i]) { uwsgi_log("unable to allocate new env dictionary for app\n"); exit(1); } } wi->argc = 1; if (app_type == PYTHON_APP_TYPE_WSGI) { #ifdef UWSGI_DEBUG uwsgi_log("-- WSGI callable selected --\n"); #endif wi->request_subhandler = uwsgi_request_subhandler_wsgi; wi->response_subhandler = uwsgi_response_subhandler_wsgi; wi->argc = 2; } else if (app_type == PYTHON_APP_TYPE_WEB3) { #ifdef UWSGI_DEBUG uwsgi_log("-- Web3 callable selected --\n"); #endif wi->request_subhandler = uwsgi_request_subhandler_web3; wi->response_subhandler = uwsgi_response_subhandler_web3; } else if (app_type == PYTHON_APP_TYPE_PUMP) { #ifdef UWSGI_DEBUG uwsgi_log("-- Pump callable selected --\n"); #endif wi->request_subhandler = uwsgi_request_subhandler_pump; wi->response_subhandler = uwsgi_response_subhandler_pump; } wi->args = malloc(sizeof(PyObject*)*uwsgi.cores); if (!wi->args) { uwsgi_error("malloc()"); exit(1); } for(i=0;i<uwsgi.cores;i++) { wi->args[i] = PyTuple_New(wi->argc); if (!wi->args[i]) { uwsgi_log("unable to allocate new tuple for app args\n"); exit(1); } // add start_response on WSGI app Py_INCREF((PyObject *)up.wsgi_spitout); if (app_type == PYTHON_APP_TYPE_WSGI) { if (PyTuple_SetItem(wi->args[i], 1, up.wsgi_spitout)) { uwsgi_log("unable to set start_response in args tuple\n"); exit(1); } } } if (app_type == PYTHON_APP_TYPE_WSGI) { // prepare sendfile() for WSGI app wi->sendfile = PyCFunction_New(uwsgi_sendfile_method, NULL); wi->eventfd_read = PyCFunction_New(uwsgi_eventfd_read_method, NULL); wi->eventfd_write = PyCFunction_New(uwsgi_eventfd_write_method, NULL); } // cache most used values wi->error = PyFile_FromFile(stderr, "wsgi_errors", "w", NULL); Py_INCREF((PyObject *)wi->error); wi->gateway_version = PyTuple_New(2); PyTuple_SetItem(wi->gateway_version, 0, PyInt_FromLong(1)); PyTuple_SetItem(wi->gateway_version, 1, PyInt_FromLong(0)); Py_INCREF((PyObject *)wi->gateway_version); wi->uwsgi_version = PyString_FromString(UWSGI_VERSION); Py_INCREF((PyObject *)wi->uwsgi_version); wi->uwsgi_node = PyString_FromString(uwsgi.hostname); Py_INCREF((PyObject *)wi->uwsgi_node); if (uwsgi.threads > 1 && id) { // if we have multiple threads we need to initialize a PyThreadState for each one for(i=0;i<uwsgi.threads;i++) { //uwsgi_log("%p\n", uwsgi.core[i]->ts[id]); uwsgi.workers[uwsgi.mywid].cores[i].ts[id] = PyThreadState_New( ((PyThreadState *)wi->interpreter)->interp); if (!uwsgi.workers[uwsgi.mywid].cores[i].ts[id]) { uwsgi_log("unable to allocate new PyThreadState structure for app %s", wi->mountpoint); goto doh; } } PyThreadState_Swap((PyThreadState *) pthread_getspecific(up.upt_save_key) ); } else if (interpreter == NULL && id) { PyThreadState_Swap(up.main_thread); } const char *default_app = ""; if ((wsgi_req->appid_len == 0 || (wsgi_req->appid_len = 1 && wsgi_req->appid[0] == '/')) && uwsgi.default_app == -1) { default_app = " (default app)" ; uwsgi.default_app = id; } wi->started_at = now; wi->startup_time = uwsgi_now() - now; if (app_type == PYTHON_APP_TYPE_WSGI) { uwsgi_log( "WSGI app %d (mountpoint='%.*s') ready in %d seconds on interpreter %p pid: %d%s\n", id, wi->mountpoint_len, wi->mountpoint, (int) wi->startup_time, wi->interpreter, (int) getpid(), default_app); } else if (app_type == PYTHON_APP_TYPE_WEB3) { uwsgi_log( "Web3 app %d (mountpoint='%.*s') ready in %d seconds on interpreter %p pid: %d%s\n", id, wi->mountpoint_len, wi->mountpoint, (int) wi->startup_time, wi->interpreter, (int) getpid(), default_app); } else if (app_type == PYTHON_APP_TYPE_PUMP) { uwsgi_log( "Pump app %d (mountpoint='%.*s') ready in %d seconds on interpreter %p pid: %d%s\n", id, wi->mountpoint_len, wi->mountpoint, (int) wi->startup_time, wi->interpreter, (int) getpid(), default_app); } uwsgi_apps_cnt++; if (multiapp > 1) { for(i=1;i<multiapp;i++) { PyObject *app_mnt = PyList_GetItem(app_list, i); if (!PyString_Check(app_mnt)) { uwsgi_log("applications dictionary key must be a string, skipping.\n"); continue; } wsgi_req->appid = PyString_AsString(app_mnt); wsgi_req->appid_len = strlen(wsgi_req->appid); PyObject *a_callable = PyDict_GetItem(applications, app_mnt); if (PyString_Check(a_callable)) { PyObject *callables_dict = get_uwsgi_pydict((char *)arg1); if (callables_dict) { a_callable = PyDict_GetItem(callables_dict, a_callable); } } if (!a_callable) { uwsgi_log("skipping broken app %s\n", wsgi_req->appid); continue; } init_uwsgi_app(LOADER_CALLABLE, a_callable, wsgi_req, wi->interpreter, app_type); } } // emulate COW uwsgi_emulate_cow_for_apps(id); return id; doh: if (PyErr_Occurred()) PyErr_Print(); if (interpreter == NULL && id) { Py_EndInterpreter(wi->interpreter); if (uwsgi.threads > 1) { PyThreadState_Swap((PyThreadState *) pthread_getspecific(up.upt_save_key)); } else { PyThreadState_Swap(up.main_thread); } } return -1; }
void uwsgi_xml_config(struct wsgi_request *wsgi_req, struct option *long_options) { xmlDoc *doc = NULL; xmlNode *element = NULL; xmlNode *node = NULL; xmlNode *node2 = NULL; xmlChar *xml_uwsgi_mountpoint = NULL; xmlChar *xml_uwsgi_script = NULL; struct option *lopt, *aopt; doc = xmlReadFile(uwsgi.xml_config, NULL, 0); if (doc == NULL) { fprintf(stderr, "[uWSGI] could not parse file %s.\n", uwsgi.xml_config); exit(1); } if (long_options) { fprintf(stderr, "[uWSGI] parsing config file %s\n", uwsgi.xml_config); } element = xmlDocGetRootElement(doc); if (element == NULL) { fprintf(stderr, "[uWSGI] invalid xml config file.\n"); exit(1); } if (strcmp((char *) element->name, "uwsgi")) { fprintf(stderr, "[uWSGI] invalid xml root element, <uwsgi> expected.\n"); exit(1); } if (long_options) { // first check for pythonpath for (node = element->children; node; node = node->next) { if (node->type == XML_ELEMENT_NODE) { lopt = long_options; while ((aopt = lopt)) { if (!aopt->name) break; if (!strcmp((char *) node->name, aopt->name)) { if (!node->children && aopt->has_arg) { fprintf(stderr, "[uWSGI] %s option need a value. skip.\n", aopt->name); exit(1); } if (node->children) { if (!node->children->content && aopt->has_arg) { fprintf(stderr, "[uWSGI] %s option need a value. skip.\n", aopt->name); exit(1); } } if (aopt->flag) { *aopt->flag = aopt->val; } else { if (node->children) { manage_opt(aopt->val, (char *) node->children->content); } else { manage_opt(aopt->val, NULL); } } } lopt++; } } } } else { // ... then for wsgi apps for (node = element->children; node; node = node->next) { if (node->type == XML_ELEMENT_NODE) { if (!strcmp((char *) node->name, "app")) { xml_uwsgi_mountpoint = xmlGetProp(node, (const xmlChar *) "mountpoint"); if (xml_uwsgi_mountpoint == NULL) { fprintf(stderr, "no mountpoint defined for app. skip.\n"); continue; } wsgi_req->script_name = (char *) xml_uwsgi_mountpoint; wsgi_req->script_name_len = strlen(wsgi_req->script_name); for (node2 = node->children; node2; node2 = node2->next) { if (node2->type == XML_ELEMENT_NODE) { if (!strcmp((char *) node2->name, "script")) { if (!node2->children) { fprintf(stderr, "no wsgi script defined. skip.\n"); continue; } xml_uwsgi_script = node2->children->content; if (xml_uwsgi_script == NULL) { fprintf(stderr, "no wsgi script defined. skip.\n"); continue; } wsgi_req->wsgi_script = (char *) xml_uwsgi_script; wsgi_req->wsgi_script_len = strlen(wsgi_req->wsgi_script); init_uwsgi_app(NULL, NULL); } } } } } } } /* We cannot free xml resources on the first round as the string pointer must be valid for all the server lifecycle */ if (!long_options) { xmlFreeDoc (doc); xmlCleanupParser (); } }