Sfoglia il codice sorgente

Fixed multiple worker_process issue

 * Added a content handler that overrides the original handler (but calls it). It is
used to add our own read_event_handler.

 * Implemented a read_event_handler that calls the original handler, and store the rest/content_length in our
own node.

 * modified the different handlers to use the new node fields
tags/v0.4
Brice Figureau 18 anni fa
parent
commit
9a7740f118
3 ha cambiato i file con 150 aggiunte e 88 eliminazioni
  1. 7
    0
      CHANGES
  2. 2
    0
      README
  3. 141
    88
      ngx_http_uploadprogress_module.c

+ 7
- 0
CHANGES Vedi File

1
+nginx_upload_progress release 0.3                                  08 May 2008
2
+
3
+ * Incompatible change: track_uploads MUST be the last directive of a location
4
+   it also must be in a proxy_pass or fastcgi_pass location.
5
+
6
+ * fixed multiple worker_process issue
7
+
1
 nginx_upload_progress release 0.3                                  06 May 2008
8
 nginx_upload_progress release 0.3                                  06 May 2008
2
 
9
 
3
  * fixed crash if the upload was denied by nginx because of any error
10
  * fixed crash if the upload was denied by nginx because of any error

+ 2
- 0
README Vedi File

79
 	unique identifier used to get progress information. If the POST has no such information, the upload will not be tracked.
79
 	unique identifier used to get progress information. If the POST has no such information, the upload will not be tracked.
80
 	The tracked connections are kept at most <timeout> seconds after they have been finished to be able to serve 
80
 	The tracked connections are kept at most <timeout> seconds after they have been finished to be able to serve 
81
 	unseful information to upload progress probes.
81
 	unseful information to upload progress probes.
82
+  Warning: this directive must be the last directive of the location. It must be in a proxy_pass or fastcgi_pass
83
+  location.
82
 	
84
 	
83
 report_uploads
85
 report_uploads
84
 ++++++++++++++
86
 ++++++++++++++

+ 141
- 88
ngx_http_uploadprogress_module.c Vedi File

14
 
14
 
15
 struct ngx_http_uploadprogress_node_s {
15
 struct ngx_http_uploadprogress_node_s {
16
     ngx_rbtree_node_t                node;
16
     ngx_rbtree_node_t                node;
17
-    ngx_http_request_t              *r;
18
     ngx_uint_t                       err_status;
17
     ngx_uint_t                       err_status;
18
+    ngx_uint_t                       rest;
19
+    ngx_uint_t                       length;
20
+    ngx_uint_t                       done;
19
     time_t                           timeout;
21
     time_t                           timeout;
20
     struct ngx_http_uploadprogress_node_s *prev;
22
     struct ngx_http_uploadprogress_node_s *prev;
21
     struct ngx_http_uploadprogress_node_s *next;
23
     struct ngx_http_uploadprogress_node_s *next;
37
 
39
 
38
 typedef struct {
40
 typedef struct {
39
     ngx_shm_zone_t                  *shm_zone;
41
     ngx_shm_zone_t                  *shm_zone;
40
-		time_t                           timeout;
42
+    time_t                           timeout;
41
     ngx_event_t                      cleanup;
43
     ngx_event_t                      cleanup;
44
+    ngx_http_handler_pt              handler;
45
+    ngx_http_event_handler_pt        read_event_handler;
42
     u_char                           track;
46
     u_char                           track;
43
 } ngx_http_uploadprogress_conf_t;
47
 } ngx_http_uploadprogress_conf_t;
44
 
48
 
248
     return NULL;
252
     return NULL;
249
 }
253
 }
250
 
254
 
255
+static void ngx_http_uploadprogress_event_handler(ngx_http_request_t *r);
251
 
256
 
252
 static ngx_int_t
257
 static ngx_int_t
253
 ngx_http_uploadprogress_content_handler(ngx_http_request_t *r)
258
 ngx_http_uploadprogress_content_handler(ngx_http_request_t *r)
254
 {
259
 {
255
-  ngx_log_debug0(NGX_LOG_DEBUG_HTTP, log, 0, "upload-progress: ngx_http_uploadprogress_content_handler");
256
-	return ngx_http_proxy_handler(r);
260
+    ngx_int_t                        rc;
261
+    ngx_http_uploadprogress_conf_t  *upcf;
262
+    ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "upload-progress: ngx_http_uploadprogress_content_handler");
263
+    upcf = ngx_http_get_module_loc_conf(r, ngx_http_uploadprogress_module);
264
+
265
+    /* call the original request handler */
266
+    rc = upcf->handler(r);
267
+
268
+    /* hijack the read_event_handler */
269
+    upcf->read_event_handler = r->read_event_handler;
270
+    r->read_event_handler = ngx_http_uploadprogress_event_handler;
271
+
272
+    return rc;
273
+}
274
+
275
+static void ngx_http_uploadprogress_event_handler(ngx_http_request_t *r)
276
+{
277
+    ngx_str_t                       *id;
278
+    ngx_slab_pool_t                 *shpool;
279
+    ngx_http_uploadprogress_ctx_t   *ctx;
280
+    ngx_http_uploadprogress_node_t  *up;
281
+    ngx_http_uploadprogress_conf_t  *upcf;
282
+
283
+    ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "upload-progress: ngx_http_uploadprogress_event_handler");
284
+    
285
+    /* call the original read event handler */
286
+    upcf = ngx_http_get_module_loc_conf(r, ngx_http_uploadprogress_module);
287
+    upcf->read_event_handler(r);
288
+
289
+    /* find node, update rest */
290
+    id = get_tracking_id(r);
291
+
292
+    if (id == NULL) {
293
+        ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
294
+                       "upload-progress: read_event_handler cant find id");
295
+        return;
296
+    }
297
+
298
+    ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
299
+                   "upload-progress: read_event_handler found id: %V", id);
300
+
301
+    if (upcf->shm_zone == NULL) {
302
+        ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
303
+                       "upload-progress: read_event_handler no shm_zone for id: %V", id);
304
+        return;
305
+    }
306
+
307
+    ctx = upcf->shm_zone->data;
308
+
309
+    /* get the original connection of the upload */
310
+    shpool = (ngx_slab_pool_t *) upcf->shm_zone->shm.addr;
311
+
312
+    ngx_shmtx_lock(&shpool->mutex);
313
+
314
+    up = find_node(id, ctx, r->connection->log);
315
+    if (up != NULL) {
316
+        ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
317
+                       "upload-progress: read_event_handler found node: %V", id);
318
+				up->rest = r->request_body->rest;
319
+				up->length = r->headers_in.content_length_n;
320
+        ngx_log_debug3(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
321
+                       "upload-progress: read_event_handler storing rest %uO/%uO for %V", up->rest, up->length, id);
322
+    } else {
323
+        ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
324
+                       "upload-progress: read_event_handler not found: %V", id);
325
+    }
326
+    ngx_shmtx_unlock(&shpool->mutex);
257
 }
327
 }
258
 
328
 
259
 /* This generates the response for the report */
329
 /* This generates the response for the report */
263
     ngx_str_t                       *id;
333
     ngx_str_t                       *id;
264
     ngx_buf_t                       *b;
334
     ngx_buf_t                       *b;
265
     ngx_chain_t                      out;
335
     ngx_chain_t                      out;
266
-    ngx_http_request_t              *orig;
267
-    ngx_int_t                        rc, size;
336
+    ngx_int_t                        rc, size, found=0, rest=0, length=0, done=0, err_status=0;
268
     ngx_uint_t                       len, i;
337
     ngx_uint_t                       len, i;
269
     ngx_slab_pool_t                 *shpool;
338
     ngx_slab_pool_t                 *shpool;
270
     ngx_http_uploadprogress_conf_t  *upcf;
339
     ngx_http_uploadprogress_conf_t  *upcf;
303
         return NGX_DECLINED;
372
         return NGX_DECLINED;
304
     }
373
     }
305
 
374
 
306
-    orig = NULL;
307
     ctx = upcf->shm_zone->data;
375
     ctx = upcf->shm_zone->data;
308
 
376
 
309
     /* get the original connection of the upload */
377
     /* get the original connection of the upload */
315
     if (up != NULL) {
383
     if (up != NULL) {
316
         ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
384
         ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
317
                        "reportuploads found node: %V", id);
385
                        "reportuploads found node: %V", id);
318
-        orig = up->r;
386
+				rest = up->rest;
387
+				length = up->length;
388
+				done = up->done;
389
+				err_status = up->err_status;
390
+				found = 1;
319
     } else {
391
     } else {
320
         ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
392
         ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
321
                        "reportuploads not found: %V", id);
393
                        "reportuploads not found: %V", id);
395
         }
467
         }
396
     }
468
     }
397
 
469
 
398
-    if (orig == NULL || orig->request_body == NULL) {
399
-        if (up == NULL ) {
400
-            size = sizeof("new Object({ 'state' : 'starting' })\r\n");
401
-        } else if (up != NULL && up->err_status >= NGX_HTTP_SPECIAL_RESPONSE) {
402
-            size = sizeof("new Object({ 'state' : 'error', 'status' : ") + NGX_INT_T_LEN + sizeof(" })\r\n");
403
-        } else {
404
-            size = sizeof("new Object({ 'state' : 'done' })\r\n");
405
-        }
406
-    } else if (orig->err_status == NGX_HTTP_REQUEST_ENTITY_TOO_LARGE) {
407
-        size = sizeof("new Object({ 'state' : 'error', 'status' : 413 })\r\n");
408
-    } else {
470
+/*
471
+ There are 4 possibilities
472
+   * request not yet started: found = false
473
+   * request in error:        err_status >= NGX_HTTP_SPECIAL_RESPONSE
474
+   * request finished:        done = true
475
+   * reauest in progress:     rest > 0 
476
+ */
477
+
478
+    if (!found) {
479
+      size = sizeof("new Object({ 'state' : 'starting' })\r\n");			
480
+		} else if (err_status >= NGX_HTTP_SPECIAL_RESPONSE) {
481
+        size = sizeof("new Object({ 'state' : 'error', 'status' : ") + NGX_INT_T_LEN + sizeof(" })\r\n");
482
+		} else if (done) {
483
+    		size = sizeof("new Object({ 'state' : 'done' })\r\n");
484
+	  } else {
409
         size =
485
         size =
410
             sizeof("new Object({ 'state' : 'uploading', 'received' : ") +
486
             sizeof("new Object({ 'state' : 'uploading', 'received' : ") +
411
             NGX_INT_T_LEN + sizeof(" })\r\n");
487
             NGX_INT_T_LEN + sizeof(" })\r\n");
420
     out.buf = b;
496
     out.buf = b;
421
     out.next = NULL;
497
     out.next = NULL;
422
 
498
 
423
-    if (orig == NULL || orig->request_body == NULL ) {
424
-        if (up == NULL) {
425
-            b->last = ngx_cpymem(b->last, "new Object({ 'state' : 'starting' })\r\n",
426
-                                 sizeof("new Object({ 'state' : 'starting' })\r\n") -
427
-                                 1);
428
-            ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
429
-                           "reportuploads returning starting");
430
-        } else if (up != NULL && up->err_status >= NGX_HTTP_SPECIAL_RESPONSE) {
431
-            b->last = ngx_cpymem(b->last, "new Object({ 'state' : 'error', 'status' : ",
432
-                                   sizeof("new Object({ 'state' : 'error', 'status' : ") - 1);
433
-        		b->last =	ngx_sprintf(b->last, "%ui })\r\n", up->err_status );
434
-            ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
435
-                           "reportuploads returning error condition: %ui", up->err_status);
436
-        }
437
-				else {
438
-            b->last = ngx_cpymem(b->last, "new Object({ 'state' : 'done' })\r\n",
439
-                                   sizeof("new Object({ 'state' : 'done' })\r\n") -
440
-                                 1);
441
-            ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
442
-                           "reportuploads returning done");
443
-				}
444
-    } else if (orig->err_status == NGX_HTTP_REQUEST_ENTITY_TOO_LARGE) {
445
-        b->last =
446
-            ngx_cpymem(b->last,
447
-                       "new Object({ 'state' : 'error', 'status' : 413 })\r\n",
448
-                       sizeof
449
-                       ("new Object({ 'state' : 'error', 'status' : 413 })\r\n") -
450
-                       1);
451
-        ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
452
-                       "reportuploads returning error 413");
453
-    } else {
454
-        b->last =
455
-            ngx_cpymem(b->last, "new Object({ 'state' : 'uploading', 'received' : ",
456
-                         sizeof("new Object({ 'state' : 'uploading', 'received' : ") -
457
-                       1);
458
-
459
-        b->last =
460
-            ngx_sprintf(b->last, "%uO, 'size' : %uO })\r\n",
461
-                        (orig->headers_in.content_length_n -
462
-                         orig->request_body->rest),
463
-                        orig->headers_in.content_length_n);
464
-
465
-        ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
466
-                       "reportuploads returning %uO / %uO",
467
-                       (orig->headers_in.content_length_n -
468
-                        orig->request_body->rest),
469
-                       orig->headers_in.content_length_n);
470
-
499
+    if (!found) {
500
+      b->last = ngx_cpymem(b->last, "new Object({ 'state' : 'starting' })\r\n",
501
+                           sizeof("new Object({ 'state' : 'starting' })\r\n") -
502
+                           1);
503
+      ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
504
+                     "reportuploads returning starting");
505
+		} else if (err_status >= NGX_HTTP_SPECIAL_RESPONSE) {
506
+      b->last = ngx_cpymem(b->last, "new Object({ 'state' : 'error', 'status' : ",
507
+                             sizeof("new Object({ 'state' : 'error', 'status' : ") - 1);
508
+  		b->last =	ngx_sprintf(b->last, "%ui })\r\n", err_status );
509
+      ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
510
+                     "reportuploads returning error condition: %ui", err_status);
511
+		} else if (done) {
512
+      b->last = ngx_cpymem(b->last, "new Object({ 'state' : 'done' })\r\n",
513
+                             sizeof("new Object({ 'state' : 'done' })\r\n") -
514
+                           1);
515
+      ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
516
+                     "reportuploads returning done");
517
+	  } else {
518
+      b->last =
519
+          ngx_cpymem(b->last, "new Object({ 'state' : 'uploading', 'received' : ",
520
+                       sizeof("new Object({ 'state' : 'uploading', 'received' : ") -
521
+                     1);
522
+
523
+      b->last = ngx_sprintf(b->last, "%uO, 'size' : %uO })\r\n", (length - rest), length);
524
+
525
+      ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
526
+				"reportuploads returning %uO / %uO",(length - rest), length );
471
     }
527
     }
472
 
528
 
529
+
473
     r->headers_out.status = NGX_HTTP_OK;
530
     r->headers_out.status = NGX_HTTP_OK;
474
     r->headers_out.content_length_n = b->last - b->pos;
531
     r->headers_out.content_length_n = b->last - b->pos;
475
 
532
 
480
         return rc;
537
         return rc;
481
     }
538
     }
482
 
539
 
483
-    return ngx_http_output_filter(r, &out);;
540
+    return ngx_http_output_filter(r, &out);
484
 }
541
 }
485
 
542
 
486
 /* 
543
 /* 
568
 
625
 
569
     node->key = hash;
626
     node->key = hash;
570
     up->len = (u_char) id->len;
627
     up->len = (u_char) id->len;
571
-    up->r = r;
572
     up->err_status = r->err_status;
628
     up->err_status = r->err_status;
573
 
629
 
574
     up->next = ctx->list_head.next;
630
     up->next = ctx->list_head.next;
694
         up = (ngx_http_uploadprogress_node_t *) node;
750
         up = (ngx_http_uploadprogress_node_t *) node;
695
 
751
 
696
         ngx_log_debug3(NGX_LOG_DEBUG_HTTP, shm_zone->shm.log, 0,
752
         ngx_log_debug3(NGX_LOG_DEBUG_HTTP, shm_zone->shm.log, 0,
697
-                       "uploadprogress clean: scanning %08XD (req %p) timeout at %T",
698
-                       node->key, up->r, up->timeout);
753
+                       "uploadprogress clean: scanning %08XD (req done %ui) timeout at %T",
754
+                       node->key, up->done, up->timeout);
699
 
755
 
700
-        if (up->r == NULL && up->timeout < now) {
756
+        if (up->done && up->timeout < now) {
701
             up->next->prev = up->prev;
757
             up->next->prev = up->prev;
702
             up->prev->next = up->next;
758
             up->prev->next = up->next;
703
 
759
 
704
             ngx_log_debug3(NGX_LOG_DEBUG_HTTP, shm_zone->shm.log, 0,
760
             ngx_log_debug3(NGX_LOG_DEBUG_HTTP, shm_zone->shm.log, 0,
705
-                           "uploadprogress clean: removing %08XD (req %p) ",
706
-                           node->key, up->r, up->timeout);
761
+                           "uploadprogress clean: removing %08XD (req %ui) ",
762
+                           node->key, up->done, up->timeout);
707
 
763
 
708
             ngx_rbtree_delete(ctx->rbtree, node);
764
             ngx_rbtree_delete(ctx->rbtree, node);
709
             ngx_slab_free_locked(shpool, node);
765
             ngx_slab_free_locked(shpool, node);
741
     node = upcln->node;
797
     node = upcln->node;
742
     up = (ngx_http_uploadprogress_node_t *) node;
798
     up = (ngx_http_uploadprogress_node_t *) node;
743
 
799
 
744
-    up->r = NULL;               /* mark the original request as done */
800
+    ngx_shmtx_lock(&shpool->mutex);
801
+    up->done = 1;               /* mark the original request as done */
745
     up->timeout = ngx_time() + upcln->timeout;      /* keep tracking for 60s */
802
     up->timeout = ngx_time() + upcln->timeout;      /* keep tracking for 60s */
803
+    ngx_shmtx_unlock(&shpool->mutex);
746
 
804
 
747
     ngx_log_debug2(NGX_LOG_DEBUG_HTTP, upcln->shm_zone->shm.log, 0,
805
     ngx_log_debug2(NGX_LOG_DEBUG_HTTP, upcln->shm_zone->shm.log, 0,
748
                    "uploadprogress cleanup: connection %08XD to be deleted at %T",
806
                    "uploadprogress cleanup: connection %08XD to be deleted at %T",
845
         if ((up = find_node(id, ctx, r->connection->log)) != NULL) {
903
         if ((up = find_node(id, ctx, r->connection->log)) != NULL) {
846
             ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
904
             ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
847
                            "trackuploads error-tracking found node for id: %V", id);
905
                            "trackuploads error-tracking found node for id: %V", id);
848
-            up->r = NULL;       /* don't really track it since it errors */
849
             up->err_status = r->err_status;
906
             up->err_status = r->err_status;
850
             ngx_shmtx_unlock(&shpool->mutex);
907
             ngx_shmtx_unlock(&shpool->mutex);
851
             goto finish;
908
             goto finish;
871
 
928
 
872
         node->key = hash;
929
         node->key = hash;
873
         up->len = (u_char) id->len;
930
         up->len = (u_char) id->len;
874
-        up->r = NULL;           /* don't really track it since it errors */
875
         up->err_status = r->err_status;
931
         up->err_status = r->err_status;
876
         ngx_memcpy(up->data, id->data, id->len);
932
         ngx_memcpy(up->data, id->data, id->len);
877
 
933
 
896
         upcln = cln->data;
952
         upcln = cln->data;
897
         upcln->shm_zone = upcf->shm_zone;
953
         upcln->shm_zone = upcf->shm_zone;
898
         upcln->node = node;
954
         upcln->node = node;
899
-        upcln->timeout = upcf->timeout;				
955
+        upcln->timeout = upcf->timeout;
900
 
956
 
901
         ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
957
         ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
902
                        "trackuploads error-tracking adding: %08XD", node->key);
958
                        "trackuploads error-tracking adding: %08XD", node->key);
1031
 static char*
1087
 static char*
1032
 ngx_http_track_uploads(ngx_conf_t * cf, ngx_command_t * cmd, void *conf)
1088
 ngx_http_track_uploads(ngx_conf_t * cf, ngx_command_t * cmd, void *conf)
1033
 {
1089
 {
1034
-    ngx_http_handler_pt        *h;
1035
-    ngx_http_core_main_conf_t  *cmcf;
1036
-
1090
+    ngx_http_core_loc_conf_t        *clcf;
1037
     ngx_http_uploadprogress_conf_t  *lzcf = conf;
1091
     ngx_http_uploadprogress_conf_t  *lzcf = conf;
1038
     ngx_str_t                       *value;
1092
     ngx_str_t                       *value;
1039
 
1093
 
1070
         return NGX_CONF_ERROR;
1124
         return NGX_CONF_ERROR;
1071
     }
1125
     }
1072
 
1126
 
1073
-    cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module);
1074
-
1075
-    h = ngx_array_push(&cmcf->phases[NGX_HTTP_CONTENT_PHASE].handlers);
1076
-    if (h == NULL) {
1077
-        return NGX_ERROR;
1127
+    clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module);
1128
+    lzcf->handler = clcf->handler;
1129
+    if ( lzcf->handler == NULL )
1130
+    {
1131
+        return "track_upload should be the last directive in the location, after either proxy_pass or fastcgi_pass";
1078
     }
1132
     }
1079
-
1080
-    *h = ngx_http_uploadprogress_content_handler;
1133
+    clcf->handler = ngx_http_uploadprogress_content_handler;
1081
     return NGX_CONF_OK;
1134
     return NGX_CONF_OK;
1082
 }
1135
 }
1083
 
1136
 

Loading…
Annulla
Salva