blob: c21fe8567b603e2f231e47e2f16d0be28144cdff [file]
/* ====================================================================
* The Apache Software License, Version 1.1
*
* Copyright (c) 2002 The Apache Software Foundation. All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The end-user documentation included with the redistribution,
* if any, must include the following acknowledgment:
* "This product includes software developed by the
* Apache Software Foundation (http://www.apache.org/)."
* Alternately, this acknowledgment may appear in the software itself,
* if and wherever such third-party acknowledgments normally appear.
*
* 4. The names "Apache" and "Apache Software Foundation" must
* not be used to endorse or promote products derived from this
* software without prior written permission. For written
* permission, please contact apache@apache.org.
*
* 5. Products derived from this software may not be called "Apache",
* nor may "Apache" appear in their name, without prior written
* permission of the Apache Software Foundation.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ====================================================================
*
*/
#include <stdlib.h>
#include <apr.h>
#include <apr_uri.h>
#include "serf.h"
#if 0
#include "serf_filters.h"
#include "serf_version.h"
#define CRLF "\r\n"
/* Yes, it'd be nice if these were command-line options... */
/* Define this to 1 to print out header information. */
#define SERF_GET_DEBUG 0
/* httpd-2.0 is cute WRT chunking and will only do it on a keep-alive.
* Define this to 1 to test serf's ability to handle chunking.
*/
#define SERF_GET_TEST_CHUNKING 0
static apr_status_t print_bucket(apr_bucket *bucket, apr_file_t *file)
{
const char *buf;
apr_size_t length, written;
apr_status_t status;
status = apr_bucket_read(bucket, &buf, &length, APR_BLOCK_READ);
if (status) {
return status;
}
return apr_file_write_full(file, buf, length, &written);
}
static apr_status_t http_source(apr_bucket_brigade *brigade,
serf_request_t *request,
apr_pool_t *pool)
{
apr_bucket *bucket;
bucket = serf_bucket_request_line_create(request->method,
request->uri->path,
"HTTP/1.1", pool,
brigade->bucket_alloc);
APR_BRIGADE_INSERT_HEAD(brigade, bucket);
#if !SERF_GET_TEST_CHUNKING
bucket = serf_bucket_header_create("Connection",
"Close",
pool, brigade->bucket_alloc);
APR_BRIGADE_INSERT_TAIL(brigade, bucket);
#endif
return APR_SUCCESS;
}
static apr_status_t host_header_filter(apr_bucket_brigade *brigade,
serf_filter_t *filter,
apr_pool_t *pool)
{
apr_bucket *bucket;
serf_request_t *request = filter->ctx;
bucket = serf_bucket_header_create("Host",
request->uri->hostname,
pool, brigade->bucket_alloc);
APR_BRIGADE_INSERT_TAIL(brigade, bucket);
return APR_SUCCESS;
}
static apr_status_t user_agent_filter(apr_bucket_brigade *brigade,
serf_filter_t *filter,
apr_pool_t *pool)
{
apr_bucket *bucket;
bucket = serf_bucket_header_create("User-Agent",
"Serf " SERF_VERSION_STRING,
pool, brigade->bucket_alloc);
APR_BRIGADE_INSERT_TAIL(brigade, bucket);
return APR_SUCCESS;
}
static apr_status_t http_headers_filter(apr_bucket_brigade *brigade,
serf_filter_t *filter,
apr_pool_t *pool)
{
apr_bucket *bucket;
/* All we do here is stick CRLFs in the right places. */
bucket = APR_BRIGADE_FIRST(brigade);
while (bucket != APR_BRIGADE_SENTINEL(brigade)) {
if (SERF_BUCKET_IS_REQUEST_LINE(bucket) ||
SERF_BUCKET_IS_HEADER(bucket)) {
apr_bucket *eol;
eol = apr_bucket_immortal_create(CRLF, sizeof(CRLF)-1,
brigade->bucket_alloc);
APR_BUCKET_INSERT_AFTER(bucket, eol);
}
bucket = APR_BUCKET_NEXT(bucket);
}
/* FIXME: We need a way to indicate we are EOH. */
bucket = apr_bucket_immortal_create(CRLF, sizeof(CRLF)-1,
brigade->bucket_alloc);
APR_BRIGADE_INSERT_TAIL(brigade, bucket);
return APR_SUCCESS;
}
static apr_status_t debug_request(apr_bucket_brigade *brigade,
serf_filter_t *filter,
apr_pool_t *pool)
{
apr_status_t status;
apr_file_t *out_file;
apr_bucket *bucket;
status = apr_file_open_stdout(&out_file, pool);
if (status) {
return status;
}
for (bucket = APR_BRIGADE_FIRST(brigade);
bucket != APR_BRIGADE_SENTINEL(brigade);
bucket = APR_BUCKET_NEXT(bucket)) {
status = print_bucket(bucket, out_file);
if (status) {
return status;
}
}
return APR_SUCCESS;
}
static apr_status_t debug_response(apr_bucket_brigade *brigade,
serf_filter_t *filter,
apr_pool_t *pool)
{
apr_status_t status;
apr_file_t *out_file;
apr_bucket *bucket;
status = apr_file_open_stdout(&out_file, pool);
if (status) {
return status;
}
/* Print the STATUS bucket first. */
for (bucket = APR_BRIGADE_FIRST(brigade);
bucket != APR_BRIGADE_SENTINEL(brigade);
bucket = APR_BUCKET_NEXT(bucket)) {
if (SERF_BUCKET_IS_STATUS(bucket)) {
status = print_bucket(bucket, out_file);
if (status) {
return status;
}
status = apr_file_putc('\n', out_file);
if (status) {
return status;
}
}
}
/* Now, print all headers. */
for (bucket = APR_BRIGADE_FIRST(brigade);
bucket != APR_BRIGADE_SENTINEL(brigade);
bucket = APR_BUCKET_NEXT(bucket)) {
if (SERF_BUCKET_IS_HEADER(bucket)) {
status = print_bucket(bucket, out_file);
if (status) {
return status;
}
status = apr_file_putc('\n', out_file);
if (status) {
return status;
}
}
}
/* Print a separator line. */
status = apr_file_putc('\n', out_file);
if (status) {
return status;
}
return APR_SUCCESS;
}
static apr_status_t http_handler(serf_response_t *response, apr_pool_t *pool)
{
apr_status_t status;
apr_file_t *out_file;
apr_bucket *bucket;
status = apr_file_open_stdout(&out_file, pool);
if (status) {
return status;
}
/* Print anything that isn't metadata. */
for (bucket = APR_BRIGADE_FIRST(response->entity);
bucket != APR_BRIGADE_SENTINEL(response->entity);
bucket = APR_BUCKET_NEXT(bucket)) {
if (!APR_BUCKET_IS_METADATA(bucket)) {
status = print_bucket(bucket, out_file);
if (status) {
return status;
}
}
}
apr_brigade_cleanup(response->entity);
return APR_SUCCESS;
}
#endif /* 0 */
static void closed_connection(serf_connection_t *conn,
void *closed_baton,
apr_status_t why,
apr_pool_t *pool)
{
abort();
}
static serf_bucket_t* accept_response(serf_request_t *request,
apr_socket_t *socket,
void *acceptor_baton,
apr_pool_t *pool)
{
abort();
return NULL;
}
static apr_status_t handle_response(serf_bucket_t *response,
void *handler_baton,
apr_pool_t *pool)
{
abort();
return APR_SUCCESS;
}
int main(int argc, const char **argv)
{
apr_status_t status;
apr_pool_t *pool;
apr_sockaddr_t *address;
serf_context_t *context;
serf_connection_t *connection;
serf_request_t *request;
serf_bucket_t *req_bkt;
#if 0
serf_filter_t *filter;
#endif /* 0 */
apr_uri_t url;
const char *raw_url;
#if 0
int using_ssl = 0;
#endif /* 0 */
if (argc != 2) {
puts("Gimme a URL, stupid!");
exit(-1);
}
raw_url = argv[1];
apr_initialize();
atexit(apr_terminate);
apr_pool_create(&pool, NULL);
/* serf_initialize(); */
#if 0
serf_register_filter("SOCKET_WRITE", serf_socket_write, pool);
serf_register_filter("SOCKET_READ", serf_socket_read, pool);
#if SERF_HAS_OPENSSL
serf_register_filter("SSL_WRITE", serf_ssl_write, pool);
serf_register_filter("SSL_READ", serf_ssl_read, pool);
#endif
serf_register_filter("USER_AGENT", user_agent_filter, pool);
serf_register_filter("HOST_HEADER", host_header_filter, pool);
serf_register_filter("HTTP_HEADERS_OUT", http_headers_filter, pool);
serf_register_filter("HTTP_STATUS_IN", serf_http_status_read, pool);
serf_register_filter("HTTP_HEADERS_IN", serf_http_header_read, pool);
serf_register_filter("HTTP_DECHUNK", serf_http_dechunk, pool);
serf_register_filter("DEFLATE_SEND_HEADER", serf_deflate_send_header, pool);
serf_register_filter("DEFLATE_READ", serf_deflate_read, pool);
serf_register_filter("DEBUG_REQUEST", debug_request, pool);
serf_register_filter("DEBUG_RESPONSE", debug_response, pool);
/*
serf_register_filter("DEFLATE_READ", serf_deflate_read, pool);
*/
#endif /* 0 */
apr_uri_parse(pool, raw_url, &url);
if (!url.port) {
url.port = apr_uri_port_of_scheme(url.scheme);
}
#if SERF_HAS_OPENSSL
if (strcasecmp(url.scheme, "https") == 0) {
using_ssl = 1;
}
#endif
status = apr_sockaddr_info_get(&address,
url.hostname, APR_UNSPEC, url.port, 0,
pool);
if (status) {
printf("Error creating address: %d\n", status);
exit(1);
}
context = serf_context_create(pool);
connection = serf_connection_create(context, address,
closed_connection, NULL, pool);
request = serf_connection_request_create(connection);
req_bkt = serf_bucket_request_create("GET", url.path, NULL,
serf_request_get_alloc(request));
#if 0
serf_bucket_set_metadata(request, SERF_REQUEST_HEADERS, "User-Agent",
"Serf" SERF_VERSION_STRING);
#endif /* 0 */
serf_request_deliver(request, req_bkt,
accept_response, NULL,
handle_response, NULL);
while (1) {
status = serf_context_run(context, SERF_DURATION_FOREVER, pool);
if (APR_STATUS_IS_TIMEUP(status))
continue;
if (status) {
printf("Error running context: %d\n", status);
exit(1);
}
}
#if 0
status = serf_open_uri(url, &connection, &request, pool);
if (status) {
printf("Error opening uri: %d\n", status);
exit(1);
}
request->source = http_source;
request->handler = http_handler;
request->method = "GET";
request->uri = url;
/* FIXME: Get serf to install an endpoint which has access to the conn. */
if (using_ssl) {
filter = serf_add_filter(connection->request_filters,
"SSL_WRITE", pool);
filter->ctx = connection;
filter = serf_add_filter(connection->response_filters,
"SSL_READ", pool);
filter->ctx = connection;
}
else {
filter = serf_add_filter(connection->request_filters,
"SOCKET_WRITE",
pool);
filter->ctx = connection;
filter = serf_add_filter(connection->response_filters,
"SOCKET_READ", pool);
filter->ctx = connection;
}
#if SERF_GET_DEBUG
filter = serf_add_filter(connection->request_filters, "DEBUG_REQUEST", pool);
#endif
filter = serf_add_filter(request->request_filters, "USER_AGENT", pool);
filter = serf_add_filter(request->request_filters, "HOST_HEADER", pool);
filter->ctx = request;
filter = serf_add_filter(request->request_filters, "DEFLATE_SEND_HEADER",
pool);
filter = serf_add_filter(request->request_filters, "HTTP_HEADERS_OUT",
pool);
/* Now add the response filters. */
filter = serf_add_filter(request->response_filters, "HTTP_STATUS_IN",
pool);
filter = serf_add_filter(request->response_filters, "HTTP_HEADERS_IN",
pool);
filter = serf_add_filter(request->response_filters, "HTTP_DECHUNK",
pool);
filter = serf_add_filter(request->response_filters, "DEFLATE_READ",
pool);
#if SERF_GET_DEBUG
filter = serf_add_filter(request->response_filters, "DEBUG_RESPONSE",
pool);
#endif
status = serf_open_connection(connection);
if (status) {
printf("Error opening connection: %d\n", status);
exit(1);
}
status = serf_write_request(request, connection);
if (status) {
printf("Error writing request: %d\n", status);
exit(1);
}
status = serf_read_response(&response, connection, pool);
if (status) {
printf("Error reading response: %d\n", status);
exit(1);
}
#endif /* 0 */
return 0;
}