+// Output filters
+#ifdef SHIB_DEFERRED_HEADERS
+static void set_output_filter(request_rec *r)
+{
+ ap_add_output_filter("SHIB_HEADERS_OUT", NULL, r, r->connection);
+}
+
+static void set_error_filter(request_rec *r)
+{
+ ap_add_output_filter("SHIB_HEADERS_ERR", NULL, r, r->connection);
+}
+
+static int _table_add(void *v, const char *key, const char *value)
+{
+ apr_table_addn((apr_table_t*)v, key, value);
+ return 1;
+}
+
+static apr_status_t do_output_filter(ap_filter_t *f, apr_bucket_brigade *in)
+{
+ request_rec *r = f->r;
+ shib_request_config *rc = (shib_request_config*) ap_get_module_config(r->request_config, &mod_shib);
+
+ if (rc) {
+ ap_log_rerror(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,SH_AP_R(r),"shib_out_filter: merging %d headers", apr_table_elts(rc->hdr_out)->nelts);
+ apr_table_do(_table_add,r->headers_out, rc->hdr_out,NULL);
+ // can't use overlap call because it will collapse Set-Cookie headers
+ //apr_table_overlap(r->headers_out, rc->hdr_out, APR_OVERLAP_TABLES_MERGE);
+ }
+
+ /* remove ourselves from the filter chain */
+ ap_remove_output_filter(f);
+
+ /* send the data up the stack */
+ return ap_pass_brigade(f->next,in);
+}
+
+static apr_status_t do_error_filter(ap_filter_t *f, apr_bucket_brigade *in)
+{
+ request_rec *r = f->r;
+ shib_request_config *rc = (shib_request_config*) ap_get_module_config(r->request_config, &mod_shib);
+
+ if (rc) {
+ ap_log_rerror(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,SH_AP_R(r),"shib_err_filter: merging %d headers", apr_table_elts(rc->hdr_out)->nelts);
+ apr_table_do(_table_add,r->err_headers_out, rc->hdr_out,NULL);
+ // can't use overlap call because it will collapse Set-Cookie headers
+ //apr_table_overlap(r->err_headers_out, rc->hdr_out, APR_OVERLAP_TABLES_MERGE);
+ }
+
+ /* remove ourselves from the filter chain */
+ ap_remove_output_filter(f);
+
+ /* send the data up the stack */
+ return ap_pass_brigade(f->next,in);
+}
+#endif // SHIB_DEFERRED_HEADERS
+