Add the sendfile function to the nginx lua module instead of the X-Accel-Redirect function.

Source: Internet
Author: User
Tags sendfile

Nginx sends static files at extremely fast speeds. The x-sendfile mechanism in Nginx relies on the X-Accel-Redirect feature. However, after my tests, it cannot meet my needs, I want to use lua to process the business logic and then send the file content. It is implemented in the following method at the beginning. If the file size is small, it doesn't matter, but when the file size is large, it has a great impact on performance. [Cpp] local file = io. open (filePath, "rb") local size = file: seek ("end") ngx. header ["Content-Length"] = size file: seek ("set", 0) data = file: read ("* a") ngx. print (data) ngx. flush (true) file: close () As we all know, there is a sendfile function in the Linux kernel, which can copy and send files 0. Therefore, the same article is found on the Internet, this document describes how to use X-Accel-Redirect of Nginx. After testing X-Accel-Redirect, it cannot meet my needs. Introduction X-Accel-Redirect official Article address: http://wiki.nginx.org/XSendfile finally no way, can only start from the source code. Referring to the ngx_http_static_module.c Module source code for sending static files, we decided to implement a lua interface that allows lua to directly call the sendfile function and send the file content. The print function is implemented in ngx_http_lua_log.c. Let me put the sendfile function here and use the ngx_lua framework directly. [Cpp] void evaluate (lua_State * L) {evaluate (L); lua_pushcfunction (L, ngx_http_lua_ngx_log); lua_setfield (L,-2, "log"); lua_pushcfunction (L, ngx_http_lua_print); lua_setglobal (L, "print"); lua_pushcfunction (L, ngx_http_lua_sendfile); // Add content lua_setglobal (L, "sendfile "); // added content} in the above Code, lua_pushcfunction is to push the function pointer into the stack, lua_setglobal is used to push "sendfile" into the stack, and The global function is set. If the global function is called in lua, it is directly sendfile (). If lua_setfield is used to press the stack, ngx is used in lua. sendfile () is called. You can use either of them. The following shows the implementation of the ngx_http_lua_sendfile function: [cpp] static int ngx_http_lua_sendfile (lua_State * L) {u_char * last, * location; size_t root, len; using * r; ngx_str_t path; ngx_int_t rc; ngx_uint_t level; ngx_log_t * log; ngx_buf_t * B; ngx_chain_t out; degree of; Limit * clcf; int offset; int bytes; char * filename; int nargs; lua_pushlightuserdata (L, & ngx_http_lua_req Uest_key); lua_rawget (L, LUA_GLOBALSINDEX); r = lua_touserdata (L,-1); lua_pop (L, 1); if (r = NULL) {luaL_error (L, "no request object found"); return 1;} nargs = lua_gettop (L); filename = (char *) lua_tolstring (L, 1, & len ); offset = lua_tonumber (L, 2); bytes = lua_tonumber (L, 3); log = r-> connection-> log; path. len = ngx_strlen (filename); path. data = ngx_pnalloc (r-> pool, path. len + 1); if (path. Data = NULL) {return 0;} (void) ngx_cpystrn (path. data, (u_char *) filename, path. len + 1); ngx_log_debug1 (NGX_LOG_DEBUG_HTTP, log, 0, "ngx send lua filename: \" % s \ "", filename); clcf = parse (r, ngx_http_core_module ); ngx_memzero (& of, sizeof (ngx_open_file_info_t);. read_ahead = clcf-> read_ahead;. directio = clcf-> directio;. valid = clcf-> open_file_cache_valid;. mi N_uses = clcf-> records; of. errors = clcf-> open_file_cache_errors; of. events = clcf-> open_file_cache_events; if (records (r, clcf, & path, & )! = NGX_ OK) {return 0; // NGX_HTTP_INTERNAL_SERVER_ERROR;} if (ngx_open_cached_file (clcf-> open_file_cache, & path, & of, r-> pool )! = NGX_ OK) {switch (. err) {case 0: return 0; // else; case NGX_ENOENT: case NGX_ENOTDIR: case ngx_enam1_long: level = NGX_LOG_ERR; rc = break; case NGX_EACCES: # if (NGX_HAVE_OPENAT) case NGX_EMLINK: case NGX_ELOOP: # endif level = NGX_LOG_ERR; rc = NGX_HTTP_FORBIDDEN; break; default: level = NGX_LOG_CRIT; rc = NGX_HTTP_INTERNAL_SERVER_ERROR; break ;} If (rc! = NGX_HTTP_NOT_FOUND | clcf-> log_not_found) {ngx_log_error (level, log,. err, "% s \" % s \ "failed",. failed, path. data);} return 0; // rc;} r-> root_tested =! R-> error_page; ngx_log_debug1 (NGX_LOG_DEBUG_HTTP, log, 0, "http static fd: % d",. fd); if (offset <0) {offset = 0;} if (bytes <= 0) {bytes =. size-offset ;}# if! (NGX_WIN32)/* the not regular files are probably Unix specific */if (! Of. is_file) {ngx_log_error (NGX_LOG_CRIT, log, 0, "\" % s \ "is not a regular file", path. data); return 0; // NGX_HTTP_NOT_FOUND;} # endif if (r-> method & NGX_HTTP_POST) {return 0; // NGX_HTTP_NOT_ALLOWED;} rc = ngx_http_discard_request_body (r ); if (rc! = NGX_ OK) {return 0; // rc;} log-> action = "sending response to client"; len = (offset + bytes)> = of. size? Of. size: (offset + bytes); r-> headers_out.status = NGX_HTTP_ OK; r-> headers_out.content_length_n = len-offset; r-> headers_out.last_modified_time =. mtime; if (ngx_http_set_content_type (r )! = NGX_ OK) {return 0; // NGX_HTTP_INTERNAL_SERVER_ERROR;} if (r! = R-> main &. size = 0) {ngx_http_send_header (r); return 0; //} r-> allow_ranges = 1; /* we need to allocate all before the header wocould be sent */B = ngx_pcalloc (r-> pool, sizeof (ngx_buf_t); if (B = NULL) {return 0; // NGX_HTTP_INTERNAL_SERVER_ERROR;} B-> file = ngx_pcalloc (r-> pool, sizeof (ngx_file_t); if (B-> file = NULL) {return 0; // NGX_HTTP_INTERNAL_SERVER_ERROR;} rc = ngx_http_send_head Er (r); if (rc = NGX_ERROR | rc> NGX_ OK | r-> header_only) {return 0; // rc;} B-> file_pos = offset; b-> file_last = (offset + bytes)> =. size? Of. size: (offset + bytes); B-> in_file = 1; B-> last_buf = (r = r-> main )? 1: 0; B-> last_in_chain = 1; B-> file-> fd =. fd; B-> file-> name = path; B-> file-> log = log; B-> file-> directio =. is_directio; out. buf = B; out. next = NULL; ngx_http_output_filter (r, & out); return 0; //} The sendfile function has three parameters. The first parameter is the file name filename. The second parameter is the file offset. offset <0 indicates that the file is sent from the file header. The third parameter is bytes, which indicates the number of bytes to be sent. If bytes is <0, it indicates that it is sent to the end of the file. In this way, you can call sendfile ("/opt/f1.ts",-1,-1) in the lua script to send the entire file or sendfile ("/opt/f1.ts ", 104857600,104857600) the speed of sending MB of data starting from MB is the same as that of sending static files directly through nginx. When you added this function, you encountered some minor issues and recorded them. The Return Value of the C function in ngx_lua indicates the number of values returned from the stack. Based on the code above, basically all return 0, indicating that I have not pushed any parameters to the lua stack, the following code [cpp] luaL_error (L, "no request object found"); return 1; indicates that a parameter is pushed, so the return value is 1, or a segment error occurs.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.