static int manage_raw_response(struct wsgi_request *wsgi_req) { int ret = 0; if (!wsgi_req->async_force_again) { ret = uwsgi_python_send_body(wsgi_req, (PyObject *) wsgi_req->async_result); if (ret == 0) { if (PyInt_Check((PyObject *) wsgi_req->async_result) || PyObject_HasAttrString((PyObject *) wsgi_req->async_result, "fileno")) { // is it a file ? int fd = PyObject_AsFileDescriptor((PyObject *) wsgi_req->async_result); if (fd >= 0) { wsgi_req->sendfile_fd = fd; uwsgi_response_sendfile_do(wsgi_req, fd, 0, 0); wsgi_req->sendfile_fd = -1; return UWSGI_OK; } } } } if (ret == 0) { if (!wsgi_req->async_placeholder) { wsgi_req->async_placeholder = PyObject_GetIter((PyObject *) wsgi_req->async_result); if (!wsgi_req->async_placeholder) return UWSGI_OK; } PyObject *pychunk = PyIter_Next((PyObject *) wsgi_req->async_placeholder); if (!pychunk) return UWSGI_OK; ret = uwsgi_python_send_body(wsgi_req, pychunk); if (ret == 0) { if (PyInt_Check(pychunk) || PyObject_HasAttrString(pychunk, "fileno")) { // is it a file ? int fd = PyObject_AsFileDescriptor(pychunk); if (fd >= 0) { wsgi_req->sendfile_fd = fd; uwsgi_response_sendfile_do(wsgi_req, fd, 0, 0); wsgi_req->sendfile_fd = -1; } } } Py_DECREF(pychunk); return UWSGI_AGAIN; } return UWSGI_OK; }
int uwsgi_response_subhandler_wsgi(struct wsgi_request *wsgi_req) { PyObject *pychunk; // return or yield ? // in strict mode we do not optimize apps directly returning strings (or bytes) if (!up.wsgi_strict) { if (uwsgi_python_send_body(wsgi_req, (PyObject *)wsgi_req->async_result)) goto clear; } if (wsgi_req->sendfile_obj == wsgi_req->async_result) { if (wsgi_req->sendfile_fd >= 0) { UWSGI_RELEASE_GIL uwsgi_response_sendfile_do(wsgi_req, wsgi_req->sendfile_fd, 0, 0); UWSGI_GET_GIL } // we do not have an iterable, check for read() method else if (PyObject_HasAttrString((PyObject *)wsgi_req->async_result, "read")) {
int uwsgi_response_subhandler_wsgi(struct wsgi_request *wsgi_req) { PyObject *pychunk = NULL; const char* chunk = NULL; Py_ssize_t chunk_size = 0; // return or yield ? PyObject *async_result = wsgi_req->async_result; if (PyObject_AsCharBuffer(async_result, &chunk, &chunk_size)<0) { PyErr_Clear(); // is one element list if (PyList_Check(async_result) && PyList_GET_SIZE(async_result)==1) { PyObject *elem = PyList_GET_ITEM(async_result, 0); if (PyObject_AsCharBuffer(elem, &chunk, &chunk_size)<0) { PyErr_Clear(); } } } if(chunk) { UWSGI_RELEASE_GIL uwsgi_response_write_body_do(wsgi_req, (char*)chunk, chunk_size); UWSGI_GET_GIL uwsgi_py_check_write_errors { uwsgi_py_write_exception(wsgi_req); } goto clear; } if (wsgi_req->sendfile_obj == async_result) { if (wsgi_req->sendfile_fd >= 0) { UWSGI_RELEASE_GIL uwsgi_response_sendfile_do(wsgi_req, wsgi_req->sendfile_fd, 0, 0); UWSGI_GET_GIL } // we do not have an iterable, check for read() method else if (PyObject_HasAttrString(async_result, "read")) {
int uwsgi_jvm_object_to_response_body(struct wsgi_request *wsgi_req, jobject body) { // check for string if (uwsgi_jvm_object_is_instance(body, ujvm.str_class)) { char *c_body = uwsgi_jvm_str2c(body); size_t c_body_len = uwsgi_jvm_strlen(body); uwsgi_response_write_body_do(wsgi_req, c_body, c_body_len); uwsgi_jvm_release_chars(body, c_body); return 0; } // check for string array if (uwsgi_jvm_object_is_instance(body, ujvm.str_array_class)) { size_t items = uwsgi_jvm_array_len(body); size_t i; for(i=0;i<items;i++) { jobject chunk = uwsgi_jvm_array_get(body, i); if (!chunk) return 0; if (!uwsgi_jvm_object_is_instance(chunk, ujvm.str_class)) { uwsgi_log("body array item must be java/lang/String !!!\n"); uwsgi_jvm_local_unref(chunk); return 0; } char *c_body = uwsgi_jvm_str2c(chunk); size_t c_body_len = uwsgi_jvm_strlen(chunk); int ret = uwsgi_response_write_body_do(wsgi_req, c_body, c_body_len); uwsgi_jvm_release_chars(chunk, c_body); uwsgi_jvm_local_unref(chunk); if (ret) return 0; } } // check for bytearray if (uwsgi_jvm_object_is_instance(body, ujvm.bytearray_class)) { char *c_body = uwsgi_jvm_bytearray2c(body); size_t c_body_len = uwsgi_jvm_array_len(body); uwsgi_response_write_body_do(wsgi_req, c_body, c_body_len); uwsgi_jvm_release_bytearray(body, c_body); return 0; } // check for iterable jobject chunks = uwsgi_jvm_auto_iterator(body); if (chunks) { while(uwsgi_jvm_iterator_hasNext(chunks)) { jobject chunk = uwsgi_jvm_iterator_next(chunks); if (!chunk) goto done; int ret = -1; if (uwsgi_jvm_object_is_instance(chunk, ujvm.str_class)) { char *c_body = uwsgi_jvm_str2c(chunk); size_t c_body_len = uwsgi_jvm_strlen(chunk); ret = uwsgi_response_write_body_do(wsgi_req, c_body, c_body_len); uwsgi_jvm_release_chars(chunk, c_body); uwsgi_jvm_local_unref(chunk); if (ret) goto done; continue; } if (uwsgi_jvm_object_is_instance(chunk, ujvm.bytearray_class)) { char *c_body = uwsgi_jvm_bytearray2c(chunk); size_t c_body_len = uwsgi_jvm_array_len(chunk); ret = uwsgi_response_write_body_do(wsgi_req, c_body, c_body_len); uwsgi_jvm_release_bytearray(chunk, c_body); uwsgi_jvm_local_unref(chunk); if (ret) goto done; continue; } jobject str_o = uwsgi_jvm_to_string(chunk); if (str_o) { char *c_body = uwsgi_jvm_str2c(str_o); size_t c_body_len = uwsgi_jvm_strlen(str_o); ret = uwsgi_response_write_body_do(wsgi_req, c_body, c_body_len); uwsgi_jvm_release_chars(str_o, c_body); uwsgi_jvm_local_unref(str_o); uwsgi_jvm_local_unref(chunk); if (ret) goto done; continue; } uwsgi_log("body iterable item must be java/lang/String or array of bytes!!!\n"); uwsgi_jvm_local_unref(chunk); goto done; } done: uwsgi_jvm_local_unref(chunks); return 0; } if (uwsgi_jvm_object_is_instance(body, ujvm.file_class)) { jobject j_filename = uwsgi_jvm_filename(body); if (!j_filename) return 0; char *c_filename = uwsgi_jvm_str2c(j_filename); int fd = open(c_filename, O_RDONLY); if (fd < 0) { uwsgi_error("java/io/File.open()"); goto done2; } uwsgi_response_sendfile_do(wsgi_req, fd, 0, 0); done2: uwsgi_jvm_release_chars(j_filename, c_filename); uwsgi_jvm_local_unref(j_filename); return 0; } if (uwsgi_jvm_object_is_instance(body, ujvm.input_stream_class)) { uwsgi_jvm_consume_input_stream(wsgi_req, 8192, body); return 0; } return -1; }
int uwsgi_real_file_serve(struct wsgi_request *wsgi_req, char *real_filename, size_t real_filename_len, struct stat *st) { size_t mime_type_size = 0; char http_last_modified[49]; if (uwsgi.threads > 1) pthread_mutex_lock(&uwsgi.lock_static); char *mime_type = uwsgi_get_mime_type(real_filename, real_filename_len, &mime_type_size); if (uwsgi.threads > 1) pthread_mutex_unlock(&uwsgi.lock_static); if (wsgi_req->if_modified_since_len) { time_t ims = parse_http_date(wsgi_req->if_modified_since, wsgi_req->if_modified_since_len); if (st->st_mtime <= ims) { uwsgi_response_prepare_headers(wsgi_req, "304 Not Modified", 16); return uwsgi_response_write_headers_do(wsgi_req); } } #ifdef UWSGI_DEBUG uwsgi_log("[uwsgi-fileserve] file %s found\n", real_filename); #endif size_t fsize = st->st_size; if (wsgi_req->range_to) { fsize = wsgi_req->range_to - wsgi_req->range_from; if (fsize > (size_t)st->st_size) { fsize = st->st_size; } } else { // reset in case of inconsistent size if (wsgi_req->range_from > fsize) { wsgi_req->range_from = 0; fsize = 0 ; } else { fsize -= wsgi_req->range_from; } } // HTTP status if (fsize > 0 && (wsgi_req->range_from || wsgi_req->range_to)) { if (uwsgi_response_prepare_headers(wsgi_req, "206 Partial Content", 19)) return -1; } else { if (uwsgi_response_prepare_headers(wsgi_req, "200 OK", 6)) return -1; } #ifdef UWSGI_PCRE uwsgi_add_expires(wsgi_req, real_filename, real_filename_len, st); uwsgi_add_expires_path_info(wsgi_req, st); uwsgi_add_expires_uri(wsgi_req, st); #endif // Content-Type (if available) if (mime_type_size > 0 && mime_type) { if (uwsgi_response_add_content_type(wsgi_req, mime_type, mime_type_size)) return -1; // check for content-type related headers uwsgi_add_expires_type(wsgi_req, mime_type, mime_type_size, st); } // increase static requests counter uwsgi.workers[uwsgi.mywid].cores[wsgi_req->async_id].static_requests++; // nginx if (uwsgi.file_serve_mode == 1) { if (uwsgi_response_add_header(wsgi_req, "X-Accel-Redirect", 16, real_filename, real_filename_len)) return -1; // this is the final header (\r\n added) int size = set_http_date(st->st_mtime, http_last_modified); if (uwsgi_response_add_header(wsgi_req, "Last-Modified", 13, http_last_modified, size)) return -1; } // apache else if (uwsgi.file_serve_mode == 2) { if (uwsgi_response_add_header(wsgi_req, "X-Sendfile", 10, real_filename, real_filename_len)) return -1; // this is the final header (\r\n added) int size = set_http_date(st->st_mtime, http_last_modified); if (uwsgi_response_add_header(wsgi_req, "Last-Modified", 13, http_last_modified, size)) return -1; } // raw else { // here we need to choose if we want the gzip variant; if (uwsgi_static_want_gzip(wsgi_req, real_filename, real_filename_len, st)) { if (uwsgi_response_add_header(wsgi_req, "Content-Encoding", 16, "gzip", 4)) return -1; } // set Content-Length (to fsize NOT st->st_size) if (uwsgi_response_add_content_length(wsgi_req, fsize)) return -1; if (fsize > 0 && (wsgi_req->range_from || wsgi_req->range_to)) { // here use teh original size !!! if (uwsgi_response_add_content_range(wsgi_req, wsgi_req->range_from, wsgi_req->range_to, st->st_size)) return -1; } int size = set_http_date(st->st_mtime, http_last_modified); if (uwsgi_response_add_header(wsgi_req, "Last-Modified", 13, http_last_modified, size)) return -1; // if it is a HEAD request just skip transfer if (!uwsgi_strncmp(wsgi_req->method, wsgi_req->method_len, "HEAD", 4)) { wsgi_req->status = 200; return 0; } // Ok, the file must be transferred from uWSGI // offloading will be automatically managed int fd = open(real_filename, O_RDONLY); if (fd < 0) return -1; // fd will be closed in the following function uwsgi_response_sendfile_do(wsgi_req, fd, wsgi_req->range_from, fsize); } wsgi_req->status = 200; return 0; }