custom handler module - dynamic response with unknown content length

Yasser Zamani yasser.zamani at live.com
Sat Mar 1 17:26:40 UTC 2014



On Sat 01 Mar 2014 06:27:38 PM IRST, Yasser Zamani wrote:
>
>
> The transcoding process already is doing by an external process,
> ffmpeg, into an incomplete file. I just need to read from first of
> this incomplete file one by one chunks and send them to client until
> seeing a real EOF. I have following plan for nginx configuration:
> location \*.mp4 { mymodule; }
>
> So, did you mean if two clients get x.mp4 and y.mp4 in same time then
> one of them is blocked until another one get complete file?! I don't
> think so while web servers usually make new threads.
>
> I saw './nginx-1.4.5/src/http/ngx_http_upstream.c' but was so complex
> for me to understand.
>
> However, I saw FastCGI is simple for me to understand. So, do you
> advise me to `regularly read ffmpeg output file` in a FastCGI script
> and then fasctcgi_pass the nginx to that?

Thank you very much Maxim; Good news that as you advised, I finally 
have done it in a nice way via FastCGI:

1. I wrote my code in a FastCGI structure with a lot of thanks to [4].
[4] http://chriswu.me/blog/writing-hello-world-in-fcgi-with-c-plus-plus/
2. I compiled and fcgi-spawn my executable on 127.0.0.1:8000 (see [4])
3. I configured nginx to proxy requests to 127.0.0.1:8000 (see [4])
4. I started my friend, nginx, and pointed the browser to 
localhost:8080.

RESULTS:
1. Multiple sametime clients download same file in a very good balanced 
speed.
2. There is no error in nginx error log.
3. OK, the best one result...we escaped from write_event_handler and 
NGX_AGAIN(=-2) :)

THE FASTCGI CODE: (for future researchers ;) )
#include <iostream>
#include "fcgio.h"

using namespace std;

int main(void) {
    // Backup the stdio streambufs
    streambuf * cin_streambuf  = cin.rdbuf();
    streambuf * cout_streambuf = cout.rdbuf();
    streambuf * cerr_streambuf = cerr.rdbuf();

    FCGX_Request request;

    FCGX_Init();
    FCGX_InitRequest(&request, 0, 0);

    while (FCGX_Accept_r(&request) == 0) {
        fcgi_streambuf cin_fcgi_streambuf(request.in);
        fcgi_streambuf cout_fcgi_streambuf(request.out);
        fcgi_streambuf cerr_fcgi_streambuf(request.err);

        cin.rdbuf(&cin_fcgi_streambuf);
        cout.rdbuf(&cout_fcgi_streambuf);
        cerr.rdbuf(&cerr_fcgi_streambuf);

        cout << "Content-type: application/octet-stream\r\n";
int i;
for(i=0;i<1000000;i++) cout
             << "\r\n"
             << "<html>\n"
             << "  <head>\n"
             << "    <title>Hello, World!</title>\n"
             << "  </head>\n"
             << "  <body>\n"
             << "    <h1>Hello, World!</h1>\n"
             << "  </body>\n"
             << "</html>\n";

        // Note: the fcgi_streambuf destructor will auto flush
    }

    // restore stdio streambufs
    cin.rdbuf(cin_streambuf);
    cout.rdbuf(cout_streambuf);
    cerr.rdbuf(cerr_streambuf);

    return 0;
}



More information about the nginx mailing list