Skip to content

Instantly share code, notes, and snippets.

@ArtemGr
Created March 30, 2014 10:09
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ArtemGr/9870554 to your computer and use it in GitHub Desktop.
Save ArtemGr/9870554 to your computer and use it in GitHub Desktop.
SUSPENDED test case
// apxs -i -a -c mod_sustest.c
// SetHandler sustest
#include <httpd.h>
#include <http_protocol.h>
#include <http_config.h>
#include <http_request.h>
#include <http_log.h>
#include <http_connection.h>
#include <ap_mpm.h>
module sustest_module;
APLOG_USE_MODULE (sustest);
static void render (request_rec* r) {
r->content_type = "text/html; charset=utf-8";
if (!r->header_only) {
ap_rputs ("<!doctype html><html lang=\"ru\"><head><meta charset=\"UTF-8\"><title>test</title></head><body>\n", r);
if (r->filename) ap_rprintf (r, "FS path: %s<br/>\n", r->filename);
ap_rputs ("</body></html>\n", r);
}
}
/// SUSPENDED connection fails to close in a browser if any of these is missing:
static void setupSuspended (request_rec* r) {
apr_table_unset (r->headers_in, "Accept-Encoding"); // DEFLATE messing with SUSPENDED?
r->chunked = 0;
r->connection->keepalive = AP_CONN_CLOSE;
}
static void finishSuspended (request_rec* r) {
apr_thread_mutex_lock (r->invoke_mtx);
if (r->connection->aborted) {
ap_die (HTTP_INTERNAL_SERVER_ERROR, r);
} else if (r->status == HTTP_OK) {
apr_bucket_brigade* bb = apr_brigade_create (r->pool, r->connection->bucket_alloc);
APR_BRIGADE_INSERT_TAIL (bb, apr_bucket_flush_create (r->connection->bucket_alloc));
APR_BRIGADE_INSERT_TAIL (bb, apr_bucket_eos_create (r->connection->bucket_alloc));
ap_pass_brigade (r->output_filters, bb);
apr_brigade_destroy (bb);
ap_finalize_request_protocol (r);
}
conn_rec* c = r->connection;
apr_thread_mutex_unlock (r->invoke_mtx);
ap_process_request_after_handler (r);
}
static void callback (void* vr) {
request_rec* r = (request_rec*) vr;
ap_log_rerror (APLOG_MARK, LOG_INFO, r->status, r, "Callback.");
if (!r->connection->aborted) render (r);
finishSuspended (r);
}
static int sustest_handler (request_rec* r) {
if (!r->handler || strcmp (r->handler, "sustest")) return DECLINED;
if (ap_meets_conditions (r) != OK) {ap_log_rerror (APLOG_MARK, APLOG_NOTICE, 0, r, "!ap_meets_conditions"); return DECLINED;}
ap_log_rerror (APLOG_MARK, LOG_INFO, r->status, r, "sustest_handler");
//render (r); return OK;
setupSuspended (r);
ap_mpm_register_timed_callback (apr_time_from_msec (1), callback, r);
return SUSPENDED;
}
static void sustest_hooks (apr_pool_t *pool) {
ap_hook_handler (sustest_handler, NULL, NULL, APR_HOOK_FIRST);
}
module sustest_module = {
STANDARD20_MODULE_STUFF,
NULL,
NULL,
NULL,
NULL,
NULL,
sustest_hooks
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment