Skip to content

Commit f814124

Browse files
committed
Handle redirect on response status for apache
1 parent 7d926e1 commit f814124

File tree

3 files changed

+67
-8
lines changed

3 files changed

+67
-8
lines changed

src/mod_redirectionio.c

Lines changed: 54 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,13 @@ static char errbuf[1024];
1313

1414
static void redirectionio_register_hooks(apr_pool_t *p);
1515

16+
static void ap_headers_insert_output_filter(request_rec *r);
17+
1618
static int redirectionio_redirect_handler(request_rec *r);
1719
static int redirectionio_log_handler(request_rec *r);
1820

21+
static apr_status_t redirectionio_filter_match_on_response(ap_filter_t *f, apr_bucket_brigade *b);
22+
1923
static apr_status_t redirectionio_create_connection(redirectionio_connection *conn, redirectionio_config *config, apr_pool_t *pool);
2024
static redirectionio_connection* redirectionio_acquire_connection(redirectionio_config *config, apr_pool_t *pool);
2125
static apr_status_t redirectionio_release_connection(redirectionio_connection *conn, redirectionio_config *config, apr_pool_t *pool);
@@ -54,6 +58,29 @@ module AP_MODULE_DECLARE_DATA redirectionio_module = {
5458
static void redirectionio_register_hooks(apr_pool_t *p) {
5559
ap_hook_handler(redirectionio_redirect_handler, NULL, NULL, APR_HOOK_FIRST);
5660
ap_hook_log_transaction(redirectionio_log_handler, NULL, NULL, APR_HOOK_MIDDLE);
61+
62+
ap_hook_insert_filter(ap_headers_insert_output_filter, NULL, NULL, APR_HOOK_LAST);
63+
ap_hook_insert_error_filter(ap_headers_insert_output_filter, NULL, NULL, APR_HOOK_LAST);
64+
ap_register_output_filter("redirectionio_redirect_filter", redirectionio_filter_match_on_response, NULL, AP_FTYPE_CONTENT_SET);
65+
}
66+
67+
static void ap_headers_insert_output_filter(request_rec *r) {
68+
redirectionio_config *config = (redirectionio_config*) ap_get_module_config(r->per_dir_config, &redirectionio_module);
69+
redirectionio_context *ctx = ap_get_module_config(r->request_config, &redirectionio_module);
70+
71+
if (config->enable != 1) {
72+
return;
73+
}
74+
75+
if (ctx == NULL || ctx->status == 0 || ctx->match_on_response_status == 0 || ctx->is_redirected) {
76+
return;
77+
}
78+
79+
if (r->status != ctx->match_on_response_status) {
80+
return;
81+
}
82+
83+
ap_add_output_filter("redirectionio_redirect_filter", ctx, r, r->connection);
5784
}
5885

5986
static int redirectionio_redirect_handler(request_rec *r) {
@@ -72,6 +99,10 @@ static int redirectionio_redirect_handler(request_rec *r) {
7299
return DECLINED;
73100
}
74101

102+
context->status = 0;
103+
context->match_on_response_status = 0;
104+
context->is_redirected = 0;
105+
75106
ap_set_module_config(r->request_config, &redirectionio_module, context);
76107
redirectionio_connection* conn = redirectionio_acquire_connection(config, r->pool);
77108

@@ -86,10 +117,14 @@ static int redirectionio_redirect_handler(request_rec *r) {
86117
return DECLINED;
87118
}
88119

89-
// No match
120+
redirectionio_release_connection(conn, config, r->pool);
121+
122+
// No match here
90123
if (context->status == 0) {
91-
redirectionio_release_connection(conn, config, r->pool);
124+
return DECLINED;
125+
}
92126

127+
if (context->match_on_response_status > 0) {
93128
return DECLINED;
94129
}
95130

@@ -98,12 +133,27 @@ static int redirectionio_redirect_handler(request_rec *r) {
98133
}
99134

100135
r->status = context->status;
101-
102-
redirectionio_release_connection(conn, config, r->pool);
136+
context->is_redirected = 1;
103137

104138
return context->status;
105139
}
106140

141+
static apr_status_t redirectionio_filter_match_on_response(ap_filter_t *f, apr_bucket_brigade *bb) {
142+
redirectionio_context *ctx = (redirectionio_context *)f->ctx;
143+
144+
if (ctx->status != 410) {
145+
apr_table_setn(f->r->headers_out, "Location", ctx->target);
146+
}
147+
148+
f->r->status = ctx->status;
149+
ctx->is_redirected = 1;
150+
151+
/* remove ourselves from the filter chain */
152+
ap_remove_output_filter(f);
153+
154+
return ap_pass_brigade(f->next, bb);
155+
}
156+
107157
static int redirectionio_log_handler(request_rec *r) {
108158
redirectionio_config *config = (redirectionio_config*) ap_get_module_config(r->per_dir_config, &redirectionio_module);
109159

src/mod_redirectionio.h

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,9 +40,11 @@ typedef struct {
4040
} redirectionio_connection;
4141

4242
typedef struct {
43-
char *matched_rule_id;
44-
char *target;
45-
int status;
43+
char *matched_rule_id;
44+
char *target;
45+
int status;
46+
int match_on_response_status;
47+
int is_redirected;
4648
} redirectionio_context;
4749

4850
#endif

src/redirectionio_protocol.c

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
static char errbuf[1024];
77

8-
const char COMMAND_MATCH_NAME[] = "MATCH";
8+
const char COMMAND_MATCH_NAME[] = "MATCH_WITH_RESPONSE";
99
const char COMMAND_MATCH_QUERY[] = "{ \"project_id\": \"%s\", \"request_uri\": \"%s\", \"host\": \"%s\" }";
1010
const char COMMAND_LOG_NAME[] = "LOG";
1111
const char COMMAND_LOG_QUERY[] = "{ \"project_id\": \"%s\", \"request_uri\": \"%s\", \"host\": \"%s\", \"rule_id\": \"%s\", \"target\": \"%s\", \"status_code\": %d, \"user_agent\": \"%s\", \"referer\": \"%s\" }";
@@ -48,6 +48,7 @@ apr_status_t redirectionio_protocol_match(redirectionio_connection *conn, redire
4848
}
4949

5050
cJSON *status = cJSON_GetObjectItem(result, "status_code");
51+
cJSON *match_on_response_status = cJSON_GetObjectItem(result, "match_on_response_status");
5152
cJSON *location = cJSON_GetObjectItem(result, "location");
5253
cJSON *matched_rule = cJSON_GetObjectItem(result, "matched_rule");
5354
cJSON *rule_id = NULL;
@@ -59,13 +60,19 @@ apr_status_t redirectionio_protocol_match(redirectionio_connection *conn, redire
5960
if (matched_rule == NULL || matched_rule->type == cJSON_NULL) {
6061
ctx->matched_rule_id = "";
6162
ctx->status = 0;
63+
ctx->match_on_response_status = 0;
6264

6365
return APR_SUCCESS;
6466
}
6567

6668
ctx->matched_rule_id = rule_id->valuestring;
6769
ctx->target = location->valuestring;
6870
ctx->status = status->valueint;
71+
ctx->match_on_response_status = 0;
72+
73+
if (match_on_response_status != NULL && match_on_response_status->type != cJSON_NULL) {
74+
ctx->match_on_response_status = match_on_response_status->valueint;
75+
}
6976

7077
return APR_SUCCESS;
7178
}

0 commit comments

Comments
 (0)