summaryrefslogtreecommitdiffstats
path: root/cpp/sca/modules
diff options
context:
space:
mode:
authorjsdelfino <jsdelfino@13f79535-47bb-0310-9956-ffa450edef68>2009-10-05 08:21:43 +0000
committerjsdelfino <jsdelfino@13f79535-47bb-0310-9956-ffa450edef68>2009-10-05 08:21:43 +0000
commita575399e56f324c453fef1989b59616e8b474582 (patch)
tree35768b1506853fc3201e864b250c6ded1df10ff9 /cpp/sca/modules
parent71fb4b80593369073dbd5f3c892aef2865c5a2ae (diff)
Strawman implementation of an HTTPD module, like the extensions/rest/service module, but simpler.
git-svn-id: http://svn.us.apache.org/repos/asf/tuscany@821716 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'cpp/sca/modules')
-rw-r--r--cpp/sca/modules/Makefile.am3
-rw-r--r--cpp/sca/modules/httpd/Makefile.am24
-rw-r--r--cpp/sca/modules/httpd/mod.cpp330
3 files changed, 356 insertions, 1 deletions
diff --git a/cpp/sca/modules/Makefile.am b/cpp/sca/modules/Makefile.am
index 0c9ccc4fbc..f152862a75 100644
--- a/cpp/sca/modules/Makefile.am
+++ b/cpp/sca/modules/Makefile.am
@@ -15,4 +15,5 @@
# specific language governing permissions and limitations
# under the License.
-SUBDIRS = eval json
+SUBDIRS = eval httpd json
+
diff --git a/cpp/sca/modules/httpd/Makefile.am b/cpp/sca/modules/httpd/Makefile.am
new file mode 100644
index 0000000000..f7906d09ac
--- /dev/null
+++ b/cpp/sca/modules/httpd/Makefile.am
@@ -0,0 +1,24 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+libdir=$(prefix)/lib
+lib_LTLIBRARIES = libmod_tuscany.la
+
+INCLUDES = -I. -I$(top_builddir)/kernel -I${HTTPD_INCLUDE} -I${APR_INCLUDE}
+
+libmod_tuscany_la_SOURCES = mod.cpp
+libmod_tuscany_la_LIBADD = -lpthread
diff --git a/cpp/sca/modules/httpd/mod.cpp b/cpp/sca/modules/httpd/mod.cpp
new file mode 100644
index 0000000000..7ecf2840bd
--- /dev/null
+++ b/cpp/sca/modules/httpd/mod.cpp
@@ -0,0 +1,330 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+/* $Rev$ $Date$ */
+
+/**
+ * Tuscany HTTPD server module.
+ */
+
+#include <string>
+#include <iostream>
+#include <sstream>
+
+#include "apr_strings.h"
+#include "apr_fnmatch.h"
+#include "apr_lib.h"
+#define APR_WANT_STRFUNC
+#include "apr_want.h"
+#include "ap_config.h"
+
+#include "httpd.h"
+#include "http_config.h"
+#include "http_core.h"
+#include "http_request.h"
+#include "http_protocol.h"
+#include "http_log.h"
+#include "http_main.h"
+#include "util_script.h"
+#include "util_md5.h"
+
+#include "mod_core.h"
+
+#include "list.hpp"
+#include "slist.hpp"
+
+extern "C" {
+extern module AP_MODULE_DECLARE_DATA mod_tuscany;
+}
+
+namespace tuscany {
+
+/**
+ * Server configuration.
+ */
+struct ServerConf {
+ const char* home;
+};
+
+/**
+ * Directory configuration.
+ */
+struct DirConf {
+ const char* root;
+ const char* path;
+ const char* uri;
+ const char* component;
+};
+
+/**
+ * Returns an HTTP request path as a list of strings.
+ */
+const list<std::string> path(const request_rec* r) {
+ const char* p = r->path_info;
+ if (p == NULL || p[0] == '\0')
+ return list<std::string>();
+ return tokenize("/", p + 1);
+}
+
+/**
+ * Returns an HTTP query string as a list of lists of strings.
+ */
+const list<list<std::string> > args(const request_rec* r) {
+ const char* a = r->args;
+ if (a == NULL)
+ return list<list<std::string> >();
+ const lambda<list<std::string>(std::string, std::string)> tok(tokenize);
+ return map(curry(tok, std::string("=")), tokenize("&", a));
+}
+
+/**
+ * Log HTTP request info to standard out for now, for debugging purposes.
+ */
+bool logRequests = true;
+
+int logHeader(void* r, const char* key, const char* value) {
+ std::cout << "header key: " << key << ", value: " << value << std::endl;
+ return 1;
+}
+
+const char* optional(const char* s) {
+ if (s == NULL)
+ return "(null)";
+ return s;
+}
+
+const bool logRequest(request_rec* r, const ServerConf& sc, const DirConf& dc) {
+ std::cout << "mod-tuscany..." << std::endl;
+ std::cout << "tuscany home: " << sc.home << std::endl;
+ std::cout << "tuscany root: " << dc.root << std::endl;
+ std::cout << "tuscany path: " << dc.path << std::endl;
+ std::cout << "component: " << dc.component << std::endl;
+ std::cout << "protocol: " << optional(r->protocol) << std::endl;
+ std::cout << "method: " << optional(r->method) << std::endl;
+ std::cout << "method number: " << r->method_number << std::endl;
+ std::cout << "content type: " << optional(apr_table_get(r->headers_in, "Content-Type")) << std::endl;
+ std::cout << "content encoding: " << optional(r->content_encoding) << std::endl;
+ apr_table_do(logHeader, r, r->headers_in, NULL);
+ std::cout << "uri: " << optional(r->uri) << std::endl;
+ std::cout << "path info: " << optional(r->path_info) << std::endl;
+ std::cout << "path: " << path(r) << std::endl;
+ std::cout << "args info: " << optional(r->args) << std::endl;
+ std::cout << "args: " << args(r) << std::endl;
+ return true;
+}
+
+/**
+ * Handle an HTTP GET request.
+ */
+const int get(request_rec* r) {
+ std::string str("<result>OK</result>");
+ if (false) {
+ r->status = HTTP_NOT_FOUND;
+ return OK;
+ }
+
+ // Handle a conditional GET
+ std::string etag(ap_md5(r->pool, (const unsigned char*)str.c_str()));
+ const char* match = apr_table_get(r->headers_in, "If-None-Match");
+ if (match != NULL && etag == match) {
+ r->status = HTTP_NOT_MODIFIED;
+ return OK;
+ }
+
+ // Send response
+ ap_set_content_type(r, "text/xml");
+ apr_table_setn(r->headers_out, "ETag", etag.c_str());
+ ap_rputs(str.c_str(), r);
+
+ return OK;
+}
+
+/**
+ * Handle an HTTP POST request.
+ */
+const int post(request_rec* r) {
+ return OK;
+}
+
+/**
+ * Handle an HTTP PUT request.
+ */
+const int put(request_rec* r) {
+ std::ostringstream sos;
+ char buffer[2049];
+ for ( ; ; )
+ {
+ int size = ap_get_client_block(r, buffer, 2048);
+ if (size > 0)
+ {
+ buffer[size] = '\0';
+ sos << buffer;
+ }
+ else if (size == 0)
+ {
+ break;
+ }
+ else if (size < 0)
+ {
+ return HTTP_INTERNAL_SERVER_ERROR;
+ }
+ }
+ std::string input = sos.str();
+ return OK;
+}
+
+/**
+ * Handle an HTTP DELETE request.
+ */
+const int del(request_rec* r) {
+ return OK;
+}
+
+/**
+ * HTTP handler entry point.
+ */
+int handler(request_rec *r) {
+ if(strcmp(r->handler, "mod_tuscany"))
+ return DECLINED;
+
+ // Get the server and dir config
+ ServerConf& serverConf = *(ServerConf*)ap_get_module_config(r->server->module_config, &mod_tuscany);
+ DirConf& dirConf = *(DirConf*)ap_get_module_config(r->per_dir_config, &mod_tuscany);
+
+ // Log the request
+ if(logRequests)
+ logRequest(r, serverConf, dirConf);
+
+ // Set up the read policy
+ const int rc = ap_setup_client_block(r, REQUEST_CHUNKED_DECHUNK);
+ if(rc != OK)
+ return rc;
+ ap_should_client_block(r);
+ if(r->read_chunked == true && r->remaining == 0)
+ r->chunked = true;
+ apr_table_setn(r->headers_out, "Connection", "close");
+
+ if (r->header_only)
+ return OK;
+
+ // Handle HTTP method
+ if(r->method_number == M_GET)
+ return get(r);
+ if(r->method_number == M_POST)
+ return post(r);
+ if(r->method_number == M_PUT)
+ return put(r);
+ if(r->method_number == M_DELETE)
+ return del(r);
+ return HTTP_NOT_IMPLEMENTED;
+}
+
+/**
+ * Configuration commands.
+ */
+const char *confHome(cmd_parms *cmd, void *dummy, const char *arg) {
+ ServerConf *conf = (ServerConf*)ap_get_module_config(cmd->server->module_config, &mod_tuscany);
+ conf->home = apr_pstrdup(cmd->pool, arg);
+ return NULL;
+}
+const char *confPath(cmd_parms *cmd, void *c, const char *arg) {
+ DirConf *conf = (DirConf*)c;
+ conf->path = apr_pstrdup(cmd->pool, arg);
+ return NULL;
+}
+const char *confRoot(cmd_parms *cmd, void *c, const char *arg) {
+ DirConf *conf = (DirConf*)c;
+ conf->root = apr_pstrdup(cmd->pool, arg);
+ return NULL;
+}
+const char *confURI(cmd_parms *cmd, void *c, const char *arg) {
+ DirConf *conf = (DirConf*)c;
+ conf->uri = apr_pstrdup(cmd->pool, arg);
+ return NULL;
+}
+const char *confComponent(cmd_parms *cmd, void *c, const char *arg) {
+ DirConf *conf = (DirConf*)c;
+ conf->component = apr_pstrdup(cmd->pool, arg);
+ return NULL;
+}
+void *makeDirConf(apr_pool_t *p, char *dirspec) {
+ DirConf* conf = (DirConf*)apr_palloc(p, sizeof(*conf));
+ conf->path = "";
+ conf->root = "";
+ conf->uri = "";
+ conf->component = "";
+ return conf;
+}
+void* makeServerConf(apr_pool_t *p, server_rec *s) {
+ ServerConf* conf = (ServerConf* )apr_palloc(p, sizeof(*conf));
+ conf->home = "";
+ return conf;
+}
+
+/**
+ * HTTP server module declarations.
+ */
+const command_rec commands[] = {
+ AP_INIT_TAKE1("home", (const char*(*)())confHome, NULL, RSRC_CONF, "Tuscany home directory"),
+ AP_INIT_TAKE1("path", (const char*(*)())confPath, NULL, ACCESS_CONF, "Tuscany SCA composite search path"),
+ AP_INIT_TAKE1("root", (const char*(*)())confRoot, NULL, ACCESS_CONF, "Tuscany root SCA configuration path"),
+ AP_INIT_TAKE1("uri", (const char*(*)())confURI, NULL, ACCESS_CONF, "Tuscany SCA system base URI"),
+ AP_INIT_TAKE1("component", (const char*(*)())confComponent, NULL, ACCESS_CONF, "SCA component name"),
+ {NULL}
+};
+
+int init(apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp, server_rec *s) {
+ return OK;
+}
+
+void childInit(apr_pool_t* p, server_rec* svr_rec) {
+ ServerConf *conf = (ServerConf*)ap_get_module_config(svr_rec->module_config, &mod_tuscany);
+ if(conf == NULL) {
+ std::cerr << "[Tuscany] Due to one or more errors mod_rest loading failed. Causing apache2 to stop loading" << std::endl;
+ exit(APEXIT_CHILDFATAL);
+ }
+}
+
+void registerHooks(apr_pool_t *p) {
+ ap_hook_handler(handler, NULL, NULL, APR_HOOK_MIDDLE);
+ ap_hook_post_config(init, NULL, NULL, APR_HOOK_MIDDLE);
+ ap_hook_child_init(childInit, NULL, NULL, APR_HOOK_MIDDLE);
+}
+
+}
+
+extern "C" {
+
+module AP_MODULE_DECLARE_DATA mod_tuscany = {
+ STANDARD20_MODULE_STUFF,
+ // dir config
+ tuscany::makeDirConf,
+ // dir merger, default is to override
+ NULL,
+ // server config
+ tuscany::makeServerConf,
+ // merge server config
+ NULL,
+ // command table
+ tuscany::commands,
+ // register hooks
+ tuscany::registerHooks
+};
+
+}