Selaa lähdekoodia

Document option for disabling CGI buffering

bel2125 3 vuotta sitten
vanhempi
commit
762493c16f
3 muutettua tiedostoa jossa 28 lisäystä ja 5 poistoa
  1. 10 0
      docs/UserManual.md
  2. 10 1
      src/civetweb.c
  3. 8 4
      test/flush.php

+ 10 - 0
docs/UserManual.md

@@ -260,6 +260,16 @@ Maximum allowed runtime for CGI scripts.  CGI processes are terminated by
 the server after this time.  The default is "no timeout", so scripts may
 run or block for undefined time.
 
+### cgi\_buffering `yes`
+Allow buffering response of CGI program before sending to the client.
+When buffering is enabled content created by CGI scripts is collected in 
+a buffer and forwarded to the client in larger blocks, improving efficiency.
+If partial content has to be sent to the client, try setting 
+`cgi_buffering` to `no`, `allow_sendfile_call` to `no` 
+and `tcp_nodelay` to `1`. This will cost some performance, but not guarantee
+there is no buffering between CGI program and client code, since intermediate 
+proxies or browsers may also buffer data.
+
 ### decode\_query\_string `no`
 URL decode all query strings in the server. 
 If you set this option to `yes`, all callbacks and scripts will only see the already

+ 10 - 1
src/civetweb.c

@@ -10003,7 +10003,16 @@ send_file_data(struct mg_connection *conn,
 			    "Error: Unable to access file at requested position.");
 		} else {
 			while (len > 0) {
-				/* Calculate how much to read from the file into the buffer */
+				/* Calculate how much to read from the file into the buffer. */
+				/* If no_buffering is set, we should not wait until the
+				 * CGI->Server buffer is filled, but send everything
+				 * immediately. In theory buffering could be turned off using
+				 * setbuf(filep->access.fp, NULL);
+				 * setvbuf(filep->access.fp, NULL, _IONBF, 0);
+				 * but in practice this does not work. A "Linux only" solution
+				 * may be to use select(). The only portable way is to read byte
+				 * by byte, but this is quite inefficient from a performance
+				 * point of view. */
 				to_read = no_buffering ? 1 : sizeof(buf);
 				if ((int64_t)to_read > len) {
 					to_read = (int)len;

+ 8 - 4
test/flush.php

@@ -1,12 +1,16 @@
 <?php
+// Server test options:
+//  ./civetweb -document_root test -cgi_interpreter /usr/bin/php-cgi -allow_sendfile_call no -num_threads 2 -cgi_buffering no &
+
 set_time_limit(20);
 header('Content-Type: text/plain; charset=utf-8');
-echo "CivetWeb Auto Flush Test\n";
-for($i = 0; $i <10; $i++) {
-	echo "Auto flush $i\n";
+
+echo "CivetWeb Flush Test:\nPrint one line every second.\n\n";
+for($i = 1; $i <= 10; $i++) {
+	@printf("Line: %2d / 10\n", $i);
 	@flush();
 	@ob_flush();
 	sleep(1);
 }
-echo "\nCurrently this test fails, only the first FLUSH is processed by the server.\n";
+echo "\nEnd of test.\n";
 ?>