/* * mod_echoserver_module for Apache httpd * Echo-back HTTP request headers. * * Usage: * * LoadModule mod_echoserver_module modules/mod_echoserver.so * * * SetHandler mod_echoserver_module * * * * Compile [-c] and install [-i]: * apxs -c -i mod_echoserver.c * * Caveats: * Multiple headers of same name are aggregated; thus * X-Header: a * X-Header: b * will appear as * X-Header:a, b * * This is done by apr_table_compress() in * last part of server/protocol.c:ap_get_mime_headers_core() . */ #include "httpd.h" #include "http_config.h" #include "http_log.h" #include "apr_strings.h" #include "apr_xml.h" /* apr_xml_quote_string */ #include "http_protocol.h" #if APR_HAVE_UNISTD_H #include #endif module AP_MODULE_DECLARE_DATA mod_echoserver_module; static int proc_before(request_rec *r) { //fcfg *cfg = ap_get_module_config(r->server->module_config, &mod_echoserver_module); const apr_array_header_t *fields; int i; apr_table_entry_t *e = 0; if (!r) return(DECLINED); //ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, r->server, "mod_echoserver_module: r=0x%lx r->handler=\"%s\" r->filename=\"%s\" the_request=\"%s\"", (unsigned long)r, r->handler, r->filename, r->the_request); if (!r->handler) return(DECLINED); if (!!strcmp(r->handler, "mod_echoserver_module")) return (DECLINED); ap_set_content_type(r, "text/html"); /* Additional headers */ apr_table_addn(r->headers_out, "Vary", "*"); #if 0 { char *date = apr_palloc(r->pool, APR_RFC822_DATE_LEN); ap_recent_rfc822_date(date, r->request_time); apr_table_addn(r->headers_out, "Expires", date); } #endif /* html body */ ap_rprintf(r, "%s\r\n", DOCTYPE_HTML_2_0); ap_rputs("\r\nechoserver\r\n\r\n", r); ap_rputs("\r\n", r); ap_rputs("
\r\n", r);
    /* GET / HTTP/1.0 */
    /* use quote_string just in case */
    ap_rprintf(r, "%s\r\n", apr_xml_quote_string(r->pool, r->the_request, 0)); 	
    /* request headers */
    fields = apr_table_elts(r->headers_in);
    e = (apr_table_entry_t *) fields->elts;
    for (i=0; i < fields->nelts; i++) {
	ap_rprintf(r, "%s:%s\r\n", 
	    apr_xml_quote_string(r->pool, e[i].key, 0),
	    apr_xml_quote_string(r->pool, e[i].val, 0)
	);
    }
    ap_rputs("\r\n", r);

    /* get POST content if it exists */
    {
    apr_bucket_brigade *bb = apr_brigade_create(r->pool, r->connection->bucket_alloc);
    int seen_eos = 0;
    do {
	apr_bucket *bucket;
	apr_status_t rv;

	rv = ap_get_brigade(r->input_filters, bb, AP_MODE_READBYTES, 
			    APR_BLOCK_READ, HUGE_STRING_LEN);
	if (rv != APR_SUCCESS) {
	    ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, "Error reading request entity data");
	    return ap_map_http_request_error(rv, HTTP_BAD_REQUEST);
	}
	for (bucket = APR_BRIGADE_FIRST(bb);
             bucket != APR_BRIGADE_SENTINEL(bb);
             bucket = APR_BUCKET_NEXT(bucket)) {
	    const char *data;
	    apr_size_t len;
	    if (APR_BUCKET_IS_EOS(bucket)) {
		seen_eos = 1;
		break;
	    }
	    if (APR_BUCKET_IS_FLUSH(bucket)) {
		continue;
	    }
	    apr_bucket_read(bucket, &data, &len, APR_BLOCK_READ);
	    /* this stops at '\0' regardess of len */
	    ap_rprintf(r, "%s", ap_escape_html2(r->pool, data, 1/*escape nonascii*/));
	}/*endfor bucket*/
    } while(!seen_eos);
    }/*request data*/

    ap_rputs("\r\n", r);
    ap_rputs("
\r\n", r); ap_rputs("\r\n", r); return DONE; /* no further handler processing */ } static void register_hooks(apr_pool_t *p) { ap_hook_handler(proc_before,NULL,NULL,APR_HOOK_FIRST); } module AP_MODULE_DECLARE_DATA mod_echoserver_module = { STANDARD20_MODULE_STUFF, NULL, /* create per-dir config */ NULL, /* merge per-dir config */ NULL, /* server config */ NULL, /* merge server config */ NULL, /* command apr_table_t */ register_hooks /* register hooks */ };