Skip to content

Commit 89b9786

Browse files
committed
for nginx-clojure#49 Access request BODY in rewrite handler
1 parent 7318085 commit 89b9786

File tree

10 files changed

+1936
-19
lines changed

10 files changed

+1936
-19
lines changed

src/c/config

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ JNI_HEADER_2="${JNI_HEADER_1}/linux"
3636

3737
CFLAGS="-I \"${JNI_HEADER_1}\" \
3838
-I \"${JNI_HEADER_2}\" \
39+
-DNGX_CLOJURE_BE_SILENT_WITHOUT_JVM \
3940
$CFLAGS"
4041

4142
#for easy debug on linux or macosx

src/c/ngx_http_clojure_mem.h

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,12 +25,12 @@
2525
#include <inttypes.h>
2626
#endif
2727

28-
#define nginx_clojure_ver 2006 /*0.2.6*/
28+
#define nginx_clojure_ver 2007 /*0.2.7*/
2929

3030
/*the least jar version required*/
3131
#define nginx_clojure_required_rt_lver 2006
3232

33-
#define NGINX_CLOJURE_VER "nginx clojure/0.2.6"
33+
#define NGINX_CLOJURE_VER "nginx clojure/0.2.7"
3434

3535
typedef struct {
3636
ngx_int_t phrase;
@@ -40,14 +40,18 @@ typedef struct {
4040
/*these two members only used by hijack send & read, default is 0*/
4141
unsigned last_buf_meeted : 1;
4242
unsigned ignore_filters : 1;
43+
unsigned async_body_read : 1;
44+
unsigned client_body_done : 1;
4345
} ngx_http_clojure_module_ctx_t;
4446

4547
#define ngx_http_clojure_init_ctx(ctx, p) \
4648
ctx->handled_couter = 1; \
4749
ctx->phrase = p; \
4850
ctx->last_buf_meeted = 0; \
4951
ctx->busy = ctx->free = NULL; \
50-
ctx->ignore_filters = 0
52+
ctx->ignore_filters = 0; \
53+
ctx->client_body_done = 0; \
54+
ctx->async_body_read = 0
5155

5256
#define NGX_HTTP_CLOJURE_MEM_IDX_START 0
5357

src/c/ngx_http_clojure_module.c

Lines changed: 78 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -656,8 +656,41 @@ static ngx_int_t ngx_http_clojure_postconfiguration(ngx_conf_t *cf) {
656656

657657
static void ngx_http_clojure_client_body_handler(ngx_http_request_t *r) {
658658
ngx_http_clojure_loc_conf_t *lcf = ngx_http_get_module_loc_conf(r, ngx_http_clojure_module);
659-
int rc = ngx_http_clojure_eval(lcf->handler_id, r);
660-
ngx_http_finalize_request (r , rc);
659+
ngx_http_clojure_module_ctx_t *ctx = ngx_http_get_module_ctx(r, ngx_http_clojure_module);
660+
ngx_int_t handler_id;
661+
int rc = NGX_DECLINED;
662+
int rewrite_phase = 0;
663+
ctx->client_body_done = 1;
664+
665+
if (!ctx->async_body_read) {
666+
ctx->phrase = -1;
667+
return;
668+
}
669+
670+
ctx->async_body_read = 0;
671+
672+
if (ctx->phrase == NGX_HTTP_REWRITE_PHASE) {
673+
handler_id = lcf->rewrite_handler_id;
674+
rewrite_phase = 1;
675+
r->write_event_handler = ngx_http_core_run_phases;
676+
}else {
677+
handler_id = lcf->handler_id;
678+
}
679+
680+
if (handler_id > 0) {
681+
rc = ngx_http_clojure_eval(handler_id, r);
682+
ngx_log_debug2(NGX_LOG_DEBUG_HTTP, ngx_http_clojure_global_cycle->log, 0, "ngx clojure rewrite (body done callback) request: %" PRIu64 ", rc: %d", (jlong)(uintptr_t)r, rc);
683+
}
684+
685+
if (rewrite_phase) {
686+
r->main->count --;
687+
if (rc != NGX_DONE) {
688+
ctx->phrase = ~ctx->phrase;
689+
r->write_event_handler(r);
690+
}
691+
}else {
692+
ngx_http_finalize_request (r , rc);
693+
}
661694
}
662695

663696

@@ -706,21 +739,24 @@ static ngx_int_t ngx_http_clojure_handler(ngx_http_request_t * r) {
706739
r->request_body_in_single_buf = 1;
707740
r->request_body_in_clean_file = 1;
708741
r->request_body_in_persistent_file = 1;
742+
709743
rc = ngx_http_read_client_request_body(r, ngx_http_clojure_client_body_handler);
710-
if (rc >= NGX_HTTP_SPECIAL_RESPONSE) {
744+
if (rc == NGX_ERROR || rc >= NGX_HTTP_SPECIAL_RESPONSE) {
711745
return rc;
712746
}
713-
return NGX_DONE;
747+
748+
if (rc == NGX_AGAIN) {
749+
ctx->async_body_read = 1;
750+
return NGX_DONE;
751+
}
714752
}else {
715753
rc = ngx_http_discard_request_body(r);
716754
if (rc != NGX_OK && rc != NGX_AGAIN) {
717755
return rc;
718756
}
719-
rc = ngx_http_clojure_eval(lcf->handler_id, r);
720757
}
721-
//for debug
722-
//ngx_log_error(NGX_LOG_DEBUG, r->connection->log, 0, "finished one request \n==============================================================\n\n");
723758

759+
rc = ngx_http_clojure_eval(lcf->handler_id, r);
724760
return rc;
725761
}
726762

@@ -731,13 +767,43 @@ static ngx_int_t ngx_http_clojure_rewrite_handler(ngx_http_request_t * r) {
731767
ngx_http_clojure_module_ctx_t *ctx;
732768
ngx_http_clojure_loc_conf_t *lcf = ngx_http_get_module_loc_conf(r, ngx_http_clojure_module);
733769

734-
if (!lcf->enable || (lcf->rewrite_handler_code.len == 0 && lcf->rewrite_handler_name.len == 0)) {
735-
return NGX_DECLINED;
770+
if (lcf->enable && (lcf->rewrite_handler_code.len > 0 || lcf->rewrite_handler_name.len > 0)) {
771+
rc = ngx_http_clojure_init_clojure_script("rewrite handler", &lcf->handler_type, &lcf->rewrite_handler_name,
772+
&lcf->rewrite_handler_code, &lcf->rewrite_handler_id, ngx_http_clojure_global_cycle->log);
773+
if (rc != NGX_HTTP_CLOJURE_JVM_OK) {
774+
return rc;
775+
}
736776
}
737777

738-
rc = ngx_http_clojure_init_clojure_script("rewrite handler", &lcf->handler_type, &lcf->rewrite_handler_name, &lcf->rewrite_handler_code, &lcf->rewrite_handler_id, ngx_http_clojure_global_cycle->log);
739-
if (rc != NGX_HTTP_CLOJURE_JVM_OK) {
740-
return rc;
778+
if (lcf->always_read_body) {
779+
if ((ctx = ngx_http_get_module_ctx(r, ngx_http_clojure_module)) == NULL) {
780+
ctx = ngx_palloc(r->pool, sizeof(ngx_http_clojure_module_ctx_t));
781+
if (ctx == NULL) {
782+
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "OutOfMemory of create ngx_http_clojure_module_ctx_t");
783+
return NGX_HTTP_INTERNAL_SERVER_ERROR;
784+
}
785+
786+
ngx_http_clojure_init_ctx(ctx, NGX_HTTP_REWRITE_PHASE);
787+
ngx_http_set_ctx(r, ctx, ngx_http_clojure_module);
788+
789+
if (!ctx->client_body_done) {
790+
r->request_body_in_single_buf = 1;
791+
r->request_body_in_clean_file = 1;
792+
r->request_body_in_persistent_file = 1;
793+
rc = ngx_http_read_client_request_body(r, ngx_http_clojure_client_body_handler);
794+
if (rc >= NGX_HTTP_SPECIAL_RESPONSE || rc == NGX_ERROR) {
795+
return rc;
796+
}
797+
if (rc == NGX_AGAIN) {
798+
ctx->async_body_read = 1;
799+
return NGX_DONE;
800+
}
801+
}
802+
}
803+
}
804+
805+
if (!lcf->enable || (lcf->rewrite_handler_code.len == 0 && lcf->rewrite_handler_name.len == 0)) {
806+
return NGX_DECLINED;
741807
}
742808

743809
if ((ctx = ngx_http_get_module_ctx(r, ngx_http_clojure_module)) == NULL) {

test/clojure/nginx/clojure/asyn_channel_handlers_for_test.clj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@
4444
(ashutdown! upstream :soft-write)
4545
(arecv! upstream buf pipe error-handler pipe-handler)
4646
)]
47-
(aconnect! upstream "mirror.bit.edu.cn:80" nil error-handler
47+
(aconnect! upstream "mirror.bit.edu.cn:80" upstream error-handler
4848
(fn [status att]
4949
(.info logger "connected successfully")
5050
(asend! upstream (str "GET /apache/httpcomponents/httpclient/RELEASE_NOTES-4.3.x.txt HTTP/1.1\r\n"

test/clojure/nginx/clojure/test_all.clj

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -556,6 +556,22 @@
556556
(debug-println "=================rewritesimple=============================")
557557
(is (= 200 (:status r)))
558558
(is (or (= "hello,a!/mytestpath" (:body r)) (= "hello,b!/mytestpath" (:body r))))))
559+
(testing "rewrite proxy pass by body -- small body"
560+
(let [r (client/post (str "http://" *host* ":" *port* "/javarewritebybodyproxy/") {:follow-redirects false, :body "ub"})
561+
h (:headers r)
562+
b (r :body)]
563+
(debug-println r)
564+
(debug-println "=================rewrite proxy pass by body -- small body=============================")
565+
(is (= 200 (:status r)))
566+
(is (= "hello,b!/javarewritebybodyproxy/" (:body r)) )))
567+
(testing "rewrite proxy pass by body -- large body"
568+
(let [r (client/post (str "http://" *host* ":" *port* "/javarewritebybodyproxy/") {:follow-redirects false, :body (clojure.java.io/file "test/nginx-working-dir/post-rewrite-large-body-data")})
569+
h (:headers r)
570+
b (r :body)]
571+
(debug-println r)
572+
(debug-println "=================rewritesimple=============================")
573+
(is (= 200 (:status r)))
574+
(is (= "hello,b!/javarewritebybodyproxy/" (:body r)) )))
559575
)
560576

561577
;eg. (concurrent-run 10 (run-tests 'nginx.clojure.test-all))

test/java/nginx/clojure/java/RewriteHandlerTestSet4NginxJavaRingHandler.java

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
package nginx.clojure.java;
22

3+
import java.io.BufferedReader;
4+
import java.io.IOException;
5+
import java.io.InputStream;
6+
import java.io.InputStreamReader;
37
import java.util.Map;
48

59
import nginx.clojure.NginxClojureRT;
@@ -27,4 +31,32 @@ public Object[] invoke(Map<String, Object> request) {
2731
}
2832
}
2933

34+
35+
public static class SimpleRewriteByBodyHandler implements NginxJavaRingHandler {
36+
@Override
37+
public Object[] invoke(Map<String, Object> request) {
38+
NginxJavaRequest req = (NginxJavaRequest) request;
39+
InputStream in = (InputStream) req.get(Constants.BODY);
40+
if (in != null) {
41+
long nr = req.nativeRequest();
42+
BufferedReader reader;
43+
try {
44+
reader = new BufferedReader( new InputStreamReader(in, "utf-8"));
45+
//just for test no arguments check
46+
//read last line for test small or large body
47+
String up = null, l = null;
48+
while ( (l = reader.readLine()) != null) {
49+
up = l;
50+
}
51+
System.err.println("[SimpleRewriteByBodyHandler] up=" + up + ", body inputstream type = " + in.getClass());
52+
NginxClojureRT.setNGXVariable(nr, "myup", up);
53+
} catch (IOException e) {
54+
NginxClojureRT.UNSAFE.throwException(e);
55+
}
56+
}
57+
return Constants.PHRASE_DONE;
58+
}
59+
}
60+
61+
3062
}

test/nginx-working-dir/conf/nginx-coroutine.conf

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,6 @@ http {
186186
handler_type 'clojure';
187187
handler_code '
188188
(fn[req]
189-
(println )
190189
{
191190
:status 200,
192191
:headers {"content-type" "text/plain"},
@@ -282,6 +281,13 @@ http {
282281
handler_name 'nginx.clojure.java.RewriteHandlerTestSet4NginxJavaRingHandler$SimpleVarHandler';
283282
}
284283

284+
location /javarewritebybodyproxy {
285+
always_read_body on;
286+
handler_type 'java';
287+
rewrite_handler_name 'nginx.clojure.java.RewriteHandlerTestSet4NginxJavaRingHandler$SimpleRewriteByBodyHandler';
288+
proxy_pass http://$myup;
289+
}
290+
285291
set $myup "";
286292
set $mypath "";
287293
location /uptest {

test/nginx-working-dir/conf/nginx-plain.conf

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ http {
4545
#gzip on;
4646

4747

48-
jvm_path "/usr/lib/jvm/java-7-oracle/jre/lib/amd64/server/libjvm.so";
48+
jvm_path "/usr/lib/jvm/java-7-oracle/jre/lib/amd64/server/libjvm.so";
4949
#jvm_path "/usr/lib/jvm/jdk1.8.0_11/jre/lib/amd64/server/libjvm.so";
5050

5151

@@ -283,6 +283,13 @@ http {
283283
handler_name 'nginx.clojure.java.RewriteHandlerTestSet4NginxJavaRingHandler$SimpleVarHandler';
284284
}
285285

286+
location /javarewritebybodyproxy {
287+
always_read_body on;
288+
handler_type 'java';
289+
rewrite_handler_name 'nginx.clojure.java.RewriteHandlerTestSet4NginxJavaRingHandler$SimpleRewriteByBodyHandler';
290+
proxy_pass http://$myup;
291+
}
292+
286293
set $myup "";
287294
set $mypath "";
288295
location /uptest {

test/nginx-working-dir/conf/nginx-threadpool.conf

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,6 @@ http {
186186
handler_type 'clojure';
187187
handler_code '
188188
(fn[req]
189-
(println )
190189
{
191190
:status 200,
192191
:headers {"content-type" "text/plain"},
@@ -282,6 +281,13 @@ http {
282281
handler_name 'nginx.clojure.java.RewriteHandlerTestSet4NginxJavaRingHandler$SimpleVarHandler';
283282
}
284283

284+
location /javarewritebybodyproxy {
285+
always_read_body on;
286+
handler_type 'java';
287+
rewrite_handler_name 'nginx.clojure.java.RewriteHandlerTestSet4NginxJavaRingHandler$SimpleRewriteByBodyHandler';
288+
proxy_pass http://$myup;
289+
}
290+
285291
set $myup "";
286292
set $mypath "";
287293
location /uptest {

0 commit comments

Comments
 (0)