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;

}
Example #2
0
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;

}
Example #3
0
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);
		}
	}

}
Example #5
0
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;
}
Example #6
0
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 ();
	}

}