@@ -20,6 +20,8 @@ static int redirectionio_match_handler(request_rec *r);
2020static int redirectionio_redirect_handler (request_rec * r );
2121static int redirectionio_log_handler (request_rec * r );
2222
23+ static int redirectionio_redirect_handler_for_status_code (request_rec * r , uint16_t status_code );
24+
2325static apr_status_t redirectionio_filter_match_on_response (ap_filter_t * f , apr_bucket_brigade * b );
2426static apr_status_t redirectionio_filter_header_filtering (ap_filter_t * f , apr_bucket_brigade * b );
2527static apr_status_t redirectionio_filter_body_filtering (ap_filter_t * f , apr_bucket_brigade * b );
@@ -124,14 +126,10 @@ static int redirectionio_match_handler(request_rec *r) {
124126 return DECLINED ;
125127 }
126128
127- ctx -> matched_rule_id = NULL ;
128- ctx -> target = NULL ;
129- ctx -> status = 0 ;
130- ctx -> match_on_response_status = 0 ;
129+ ctx -> matched_rule_str = NULL ;
130+ ctx -> matched_rule = NULL ;
131+ ctx -> filter_id = NULL ;
131132 ctx -> is_redirected = 0 ;
132- ctx -> should_filter_body = 0 ;
133- ctx -> should_filter_headers = 0 ;
134- ctx -> body_filter_conn = NULL ;
135133
136134 ap_set_module_config (r -> request_config , & redirectionio_module , ctx );
137135 redirectionio_connection * conn = redirectionio_acquire_connection (config , r -> pool );
@@ -169,7 +167,9 @@ static void ap_headers_insert_output_filter(request_rec *r) {
169167 ap_add_output_filter ("redirectionio_body_filter" , ctx , r , r -> connection );
170168}
171169
172- static int redirectionio_redirect_handler (request_rec * r ) {
170+ static int redirectionio_redirect_handler_for_status_code (request_rec * r , uint16_t status_code ) {
171+ char * redirect_str , * location_str ;
172+ cJSON * redirect , * location , * status ;
173173 redirectionio_config * config = (redirectionio_config * ) ap_get_module_config (r -> per_dir_config , & redirectionio_module );
174174
175175 // Not enabled
@@ -184,42 +184,47 @@ static int redirectionio_redirect_handler(request_rec *r) {
184184 }
185185
186186 // No match here
187- if (ctx -> status == 0 || ctx -> is_redirected == 1 ) {
187+ if (ctx -> matched_rule_str == NULL || ctx -> is_redirected == 1 ) {
188188 return DECLINED ;
189189 }
190190
191- if (ctx -> match_on_response_status > 0 ) {
192- return DECLINED ;
193- }
191+ redirect_str = (char * )redirectionio_get_redirect (ctx -> matched_rule_str , r -> unparsed_uri , status_code );
194192
195- if (ctx -> status != 410 ) {
196- apr_table_setn ( r -> headers_out , "Location" , ctx -> target ) ;
193+ if (redirect_str == NULL ) {
194+ return DECLINED ;
197195 }
198196
199- r -> status = ctx -> status ;
200- ctx -> is_redirected = 1 ;
201-
202- return ctx -> status ;
203- }
204-
205- static apr_status_t redirectionio_filter_match_on_response (ap_filter_t * f , apr_bucket_brigade * bb ) {
206- redirectionio_context * ctx = (redirectionio_context * )f -> ctx ;
197+ redirect = cJSON_Parse (redirect_str );
207198
208- if (ctx == NULL ) {
209- return ap_pass_brigade ( f -> next , bb ) ;
199+ if (redirect == NULL ) {
200+ return DECLINED ;
210201 }
211202
212- if (ctx -> is_redirected || ctx -> status == 0 || (ctx -> match_on_response_status > 0 && ctx -> match_on_response_status != f -> r -> status )) {
213- return ap_pass_brigade (f -> next , bb );
203+ status = cJSON_GetObjectItem (redirect , "status_code" );
204+ location = cJSON_GetObjectItem (redirect , "location" );
205+
206+ if (status == NULL || location == NULL ) {
207+ return DECLINED ;
214208 }
215209
216- if (ctx -> status != 410 ) {
217- apr_table_setn (f -> r -> headers_out , "Location" , ctx -> target );
210+ if (status -> valueint != 410 ) {
211+ location_str = apr_pstrdup (r -> pool , location -> valuestring );
212+ apr_table_setn (r -> headers_out , "Location" , location_str );
218213 }
219214
220- f -> r -> status = ctx -> status ;
215+ r -> status = status -> valueint ;
221216 ctx -> is_redirected = 1 ;
222217
218+ return r -> status ;
219+ }
220+
221+ static int redirectionio_redirect_handler (request_rec * r ) {
222+ return redirectionio_redirect_handler_for_status_code (r , 0 );
223+ }
224+
225+ static apr_status_t redirectionio_filter_match_on_response (ap_filter_t * f , apr_bucket_brigade * bb ) {
226+ redirectionio_redirect_handler_for_status_code (f -> r , f -> r -> status );
227+
223228 /* remove ourselves from the filter chain */
224229 ap_remove_output_filter (f );
225230
@@ -228,66 +233,41 @@ static apr_status_t redirectionio_filter_match_on_response(ap_filter_t *f, apr_b
228233
229234static apr_status_t redirectionio_filter_header_filtering (ap_filter_t * f , apr_bucket_brigade * bb ) {
230235 redirectionio_context * ctx = (redirectionio_context * )f -> ctx ;
231- redirectionio_config * config = (redirectionio_config * ) ap_get_module_config (f -> r -> per_dir_config , & redirectionio_module );
232236
233237 if (ctx == NULL ) {
234238 return ap_pass_brigade (f -> next , bb );
235239 }
236240
237- if (ctx -> should_filter_headers == 0 || ( ctx -> is_redirected != 1 && ctx -> match_on_response_status > 0 && ctx -> match_on_response_status != f -> r -> status ) ) {
241+ if (ctx -> matched_rule_str == NULL ) {
238242 return ap_pass_brigade (f -> next , bb );
239243 }
240244
245+ redirectionio_protocol_send_filter_headers (ctx , f -> r );
241246 ap_remove_output_filter (f );
242247
243- // Get connection
244- redirectionio_connection * conn = redirectionio_acquire_connection (config , f -> r -> pool );
245-
246- if (conn == NULL ) {
247- return ap_pass_brigade (f -> next , bb );
248- }
249-
250- // Send headers
251- if (redirectionio_protocol_send_filter_headers (conn , ctx , f -> r , config -> project_key ) != APR_SUCCESS ) {
252- redirectionio_invalidate_connection (conn , config , f -> r -> pool );
253-
254- return ap_pass_brigade (f -> next , bb );
255- }
256-
257- redirectionio_release_connection (conn , config , f -> r -> pool );
258-
259248 return ap_pass_brigade (f -> next , bb );
260249}
261250
262251static apr_status_t redirectionio_filter_body_filtering (ap_filter_t * f , apr_bucket_brigade * bb ) {
263252 redirectionio_context * ctx = (redirectionio_context * )f -> ctx ;
264- redirectionio_config * config = (redirectionio_config * ) ap_get_module_config (f -> r -> per_dir_config , & redirectionio_module );
265253 apr_bucket * b , * b_new ;
266254 apr_bucket_brigade * bb_new ;
267- const char * input , * output ;
255+ const char * input , * output , * input_str ;
268256 int64_t input_size , output_size ;
269257 apr_status_t rv ;
270258
271259 if (ctx == NULL ) {
272260 return ap_pass_brigade (f -> next , bb );
273261 }
274262
275- if (ctx -> should_filter_body == 0 || ( ctx -> is_redirected != 1 && ctx -> match_on_response_status > 0 && ctx -> match_on_response_status != f -> r -> status ) ) {
263+ if (ctx -> matched_rule_str == NULL ) {
276264 return ap_pass_brigade (f -> next , bb );
277265 }
278266
279- // If first -> remove content_length, get_connection, init filtering command
280- if (ctx -> body_filter_conn == NULL ) {
281- ctx -> body_filter_conn = redirectionio_acquire_connection (config , f -> r -> pool );
282-
283- if (ctx -> body_filter_conn == NULL ) {
284- ap_remove_output_filter (f );
285-
286- return ap_pass_brigade (f -> next , bb );
287- }
267+ if (ctx -> filter_id == NULL ) {
268+ ctx -> filter_id = (char * )redirectionio_create_body_filter (ctx -> matched_rule_str );
288269
289- if (redirectionio_protocol_send_filter_body_init (ctx -> body_filter_conn , ctx , f -> r , config -> project_key ) != APR_SUCCESS ) {
290- redirectionio_invalidate_connection (ctx -> body_filter_conn , config , f -> r -> pool );
270+ if (ctx -> filter_id == NULL ) {
291271 ap_remove_output_filter (f );
292272
293273 return ap_pass_brigade (f -> next , bb );
@@ -310,29 +290,32 @@ static apr_status_t redirectionio_filter_body_filtering(ap_filter_t *f, apr_buck
310290 rv = apr_bucket_read (b , & input , (apr_size_t * )& input_size , APR_BLOCK_READ );
311291
312292 if (rv != APR_SUCCESS ) {
313- redirectionio_invalidate_connection (ctx -> body_filter_conn , config , f -> r -> pool );
293+ free (ctx -> filter_id );
294+ ctx -> filter_id = NULL ;
314295 ap_remove_output_filter (f );
315296
316297 return ap_pass_brigade (f -> next , bb );
317298 }
318299
319300 // Send bucket
320301 if (input_size > 0 ) {
321- rv = redirectionio_protocol_send_filter_body_chunk (ctx -> body_filter_conn , input , input_size , & output , & output_size , f -> r -> pool );
302+ input_str = strndup (input , input_size );
303+ output = redirectionio_body_filter (ctx -> filter_id , input_str );
304+ free ((char * )input_str );
322305
323- if (rv != APR_SUCCESS ) {
324- redirectionio_invalidate_connection (ctx -> body_filter_conn , config , f -> r -> pool );
306+ if (output == NULL ) {
325307 ap_remove_output_filter (f );
326308
327309 return ap_pass_brigade (f -> next , bb );
328310 }
329311
312+ output_size = strlen (output );
313+
330314 // Create a new one
331315 if (output_size > 0 ) {
332316 b_new = apr_bucket_transient_create (output , output_size , f -> r -> connection -> bucket_alloc );
333317
334318 if (b_new == NULL ) {
335- redirectionio_invalidate_connection (ctx -> body_filter_conn , config , f -> r -> pool );
336319 ap_remove_output_filter (f );
337320
338321 return ap_pass_brigade (f -> next , bb );
@@ -344,22 +327,21 @@ static apr_status_t redirectionio_filter_body_filtering(ap_filter_t *f, apr_buck
344327 }
345328
346329 if (APR_BUCKET_IS_EOS (b )) {
347- // Send termination to the connection and wait for it to return us the last data
348- rv = redirectionio_protocol_send_filter_body_finish (ctx -> body_filter_conn , & output , & output_size , f -> r -> pool );
330+ output = redirectionio_body_filter_end (ctx -> filter_id );
349331
350- if (rv != APR_SUCCESS ) {
351- redirectionio_invalidate_connection (ctx -> body_filter_conn , config , f -> r -> pool );
332+ if (output == NULL ) {
352333 ap_remove_output_filter (f );
353334
354335 return ap_pass_brigade (f -> next , bb );
355336 }
356337
338+ output_size = strlen (output );
339+
357340 if (output_size > 0 ) {
358341 // Create a new one
359342 b_new = apr_bucket_transient_create (output , output_size , f -> r -> connection -> bucket_alloc );
360343
361344 if (b_new == NULL ) {
362- redirectionio_invalidate_connection (ctx -> body_filter_conn , config , f -> r -> pool );
363345 ap_remove_output_filter (f );
364346
365347 return ap_pass_brigade (f -> next , bb );
@@ -373,17 +355,13 @@ static apr_status_t redirectionio_filter_body_filtering(ap_filter_t *f, apr_buck
373355 b_new = apr_bucket_eos_create (f -> r -> connection -> bucket_alloc );
374356
375357 if (b_new == NULL ) {
376- redirectionio_invalidate_connection (ctx -> body_filter_conn , config , f -> r -> pool );
377358 ap_remove_output_filter (f );
378359
379360 return ap_pass_brigade (f -> next , bb );
380361 }
381362
382363 APR_BRIGADE_INSERT_TAIL (bb_new , b_new );
383364
384- // Release connection
385- redirectionio_release_connection (ctx -> body_filter_conn , config , f -> r -> pool );
386-
387365 // Remove filter
388366 ap_remove_output_filter (f );
389367
0 commit comments