Hi list,
this is a (unfortunatly large) patch to support the HEAD HTTP method
in the gwlib/http.c module. Currently we only support POST and GET
which are switched by the presence of a request body.
For WAP realted download (like the Ericsson devices) we need to have
the HEAD method too.
So please apply this patch to your testing systems and check if your
normal functionality works and vote for commitment into cvs.
Stipe
[EMAIL PROTECTED]
-------------------------------------------------------------------
Wapme Systems AG
Vogelsanger Weg 80
40470 D�sseldorf
Tel: +49-211-74845-0
Fax: +49-211-74845-299
E-Mail: [EMAIL PROTECTED]
Internet: http://www.wapme-systems.de
-------------------------------------------------------------------
wapme.net - wherever you are
diff -ur --exclude=Entries gateway-cvs/gw/numhash.c gateway/gw/numhash.c
--- gateway-cvs/gw/numhash.c 2002-04-18 18:19:28.000000000 +0200
+++ gateway/gw/numhash.c 2002-08-19 19:42:25.000000000 +0200
@@ -261,7 +261,7 @@
url = octstr_create(seek_url);
request_headers = list_create();
- status = http_get_real(url, request_headers, &final_url,
+ status = http_get_real(HTTP_METHOD_GET, url, request_headers, &final_url,
&reply_headers, &reply_body);
octstr_destroy(url);
octstr_destroy(final_url);
diff -ur --exclude=Entries gateway-cvs/gw/smsbox.c gateway/gw/smsbox.c
--- gateway-cvs/gw/smsbox.c 2002-08-05 19:03:47.000000000 +0200
+++ gateway/gw/smsbox.c 2002-08-19 19:25:59.000000000 +0200
@@ -215,6 +215,7 @@
struct receiver {
Msg *msg;
URLTranslation *trans;
+ int method; /* the HTTP method to use */
Octstr *url; /* the after pattern URL */
List *http_headers;
Octstr *body; /* body content of the request */
@@ -222,8 +223,9 @@
};
-static void *remember_receiver(Msg *msg, URLTranslation *trans, Octstr *url,
- List *headers, Octstr *body, unsigned int retries)
+static void *remember_receiver(Msg *msg, URLTranslation *trans, int method,
+ Octstr *url, List *headers, Octstr *body,
+ unsigned int retries)
{
struct receiver *receiver;
@@ -254,6 +256,7 @@
receiver->trans = trans;
/* remember the HTTP request if we need to queue this */
+ receiver->method = method;
receiver->url = octstr_duplicate(url);
receiver->http_headers = http_header_duplicate(headers);
receiver->body = octstr_duplicate(body);
@@ -263,14 +266,16 @@
}
-static void get_receiver(void *id, Msg **msg, URLTranslation **trans, Octstr **url,
- List **headers, Octstr **body, unsigned long *retries)
+static void get_receiver(void *id, Msg **msg, URLTranslation **trans, int *method,
+ Octstr **url, List **headers, Octstr **body,
+ unsigned long *retries)
{
struct receiver *receiver;
receiver = id;
*msg = receiver->msg;
*trans = receiver->trans;
+ *method = receiver->method;
*url = receiver->url;
*headers = receiver->http_headers;
*body = receiver->body;
@@ -830,6 +835,7 @@
List *req_headers;
Octstr *req_body;
unsigned long retries;
+ int method;
while ((id = list_consume(smsbox_http_requests)) != NULL) {
/*
@@ -844,16 +850,17 @@
* Get all required HTTP request data from the queue and reconstruct
* the id pointer for later lookup in url_result_thread.
*/
- get_receiver(id, &msg, &trans, &req_url, &req_headers, &req_body, &retries);
+ get_receiver(id, &msg, &trans, &method, &req_url, &req_headers, &req_body,
+&retries);
if (retries < max_http_retries) {
- id = remember_receiver(msg, trans, req_url, req_headers, req_body,
++retries);
+ id = remember_receiver(msg, trans, method, req_url, req_headers,
+req_body, ++retries);
debug("sms.http",0,"HTTP: Retrying request <%s> (%ld/%ld)",
octstr_get_cstr(req_url), retries, max_http_retries);
/* re-queue this request to the HTTPCaller list */
- http_start_request(caller, req_url, req_headers, req_body, 1, id, NULL);
+ http_start_request(caller, method, req_url, req_headers, req_body,
+ 1, id, NULL);
}
}
}
@@ -863,7 +870,7 @@
{
Octstr *final_url, *reply_body, *type, *charset, *replytext;
List *reply_headers;
- int status;
+ int status, method;
void *id;
Msg *msg;
URLTranslation *trans;
@@ -901,7 +908,7 @@
if (id == NULL)
break;
- get_receiver(id, &msg, &trans, &req_url, &req_headers, &req_body, &retries);
+ get_receiver(id, &msg, &trans, &method, &req_url, &req_headers, &req_body,
+&retries);
from = to = udh = smsc = NULL;
octets = mclass = mwi = coding = compress = pid = alt_dcs = rpi = 0;
@@ -959,7 +966,7 @@
octstr_destroy(type);
octstr_destroy(charset);
} else if (max_http_retries > 0) {
- id = remember_receiver(msg, trans, req_url, req_headers, req_body,
retries);
+ id = remember_receiver(msg, trans, method, req_url, req_headers,
+req_body, retries);
list_produce(smsbox_http_requests, id);
queued++;
goto requeued;
@@ -1082,9 +1089,9 @@
octstr_get_cstr(msg->sms.receiver));
}
- id = remember_receiver(msg, trans, pattern, request_headers, NULL, 0);
- http_start_request(caller, pattern, request_headers, NULL, 1, id,
- NULL);
+ id = remember_receiver(msg, trans, HTTP_METHOD_GET, pattern, request_headers,
+NULL, 0);
+ http_start_request(caller, HTTP_METHOD_GET, pattern, request_headers,
+ NULL, 1, id, NULL);
octstr_destroy(pattern);
http_destroy_headers(request_headers);
*result = NULL;
@@ -1200,9 +1207,9 @@
octstr_get_cstr(os));
octstr_destroy(os);
}
- id = remember_receiver(msg, trans, pattern, request_headers, msg->sms.msgdata,
0);
- http_start_request(caller, pattern, request_headers,
- msg->sms.msgdata, 1, id, NULL);
+ id = remember_receiver(msg, trans, HTTP_METHOD_POST, pattern, request_headers,
+msg->sms.msgdata, 0);
+ http_start_request(caller, HTTP_METHOD_POST, pattern, request_headers,
+ msg->sms.msgdata, 1, id, NULL);
octstr_destroy(pattern);
http_destroy_headers(request_headers);
*result = NULL;
@@ -1345,9 +1352,9 @@
msg->sms.msgdata = xml;
debug("sms", 0, "XMLBuild: XML: <%s>", octstr_get_cstr(msg->sms.msgdata));
- id = remember_receiver(msg, trans, pattern, request_headers, msg->sms.msgdata,
0);
- http_start_request(caller, pattern, request_headers,
- msg->sms.msgdata, 1, id, NULL);
+ id = remember_receiver(msg, trans, HTTP_METHOD_POST, pattern, request_headers,
+msg->sms.msgdata, 0);
+ http_start_request(caller, HTTP_METHOD_POST, pattern, request_headers,
+ msg->sms.msgdata, 1, id, NULL);
octstr_destroy(pattern);
http_destroy_headers(request_headers);
*result = NULL;
diff -ur --exclude=Entries gateway-cvs/gw/smsc/smsc_http.c gateway/gw/smsc/smsc_http.c
--- gateway-cvs/gw/smsc/smsc_http.c 2002-08-09 12:38:15.000000000 +0200
+++ gateway/gw/smsc/smsc_http.c 2002-08-19 18:19:34.000000000 +0200
@@ -259,7 +259,8 @@
headers = list_create();
debug("smsc.http.kannel", 0, "start request");
- http_start_request(conndata->http_ref, url, headers, NULL, 0, sms, NULL);
+ http_start_request(conndata->http_ref, HTTP_METHOD_GET, url, headers,
+ NULL, 0, sms, NULL);
octstr_destroy(url);
http_destroy_headers(headers);
diff -ur --exclude=Entries gateway-cvs/gw/wap-appl.c gateway/gw/wap-appl.c
--- gateway-cvs/gw/wap-appl.c 2002-08-08 12:25:42.000000000 +0200
+++ gateway/gw/wap-appl.c 2002-08-19 20:06:00.000000000 +0200
@@ -823,7 +823,8 @@
p->url = url;
p->x_wap_tod = x_wap_tod;
p->request_headers = actual_headers;
- http_start_request(caller, url, actual_headers, request_body, 0, p, NULL);
+ http_start_request(caller, http_name2method(method), url, actual_headers,
+ request_body, 0, p, NULL);
octstr_destroy(request_body);
} else {
error(0, "WSP: Method %s not supported.", octstr_get_cstr(method));
diff -ur --exclude=Entries gateway-cvs/gwlib/http.c gateway/gwlib/http.c
--- gateway-cvs/gwlib/http.c 2002-06-11 22:59:52.000000000 +0200
+++ gateway/gwlib/http.c 2002-08-19 20:01:54.000000000 +0200
@@ -543,14 +543,24 @@
/*
+ * The implemented HTTP method strings
+ * Order is sequenced by the enum in the header
+ */
+static char *http_methods[] = {
+ "GET", "POST", "HEAD"
+};
+
+
+/*
* Information about a server we've connected to.
*/
typedef struct {
HTTPCaller *caller;
void *request_id;
+ int method; /* uses enums from http.h for the HTTP methods */
Octstr *url;
List *request_headers;
- Octstr *request_body; /* NULL for GET, non-NULL for POST */
+ Octstr *request_body; /* NULL for GET or HEAD, non-NULL for POST */
enum {
request_not_sent,
reading_status,
@@ -572,16 +582,16 @@
} HTTPServer;
-static HTTPServer *server_create(HTTPCaller *caller, Octstr *url,
- List *headers, Octstr *body,
- int follow_remaining,
- Octstr *certkeyfile)
+static HTTPServer *server_create(HTTPCaller *caller, int method, Octstr *url,
+ List *headers, Octstr *body, int follow_remaining,
+ Octstr *certkeyfile)
{
HTTPServer *trans;
trans = gw_malloc(sizeof(*trans));
trans->caller = caller;
trans->request_id = NULL;
+ trans->method = method;
trans->url = octstr_duplicate(url);
trans->request_headers = http_header_duplicate(headers);
trans->request_body = octstr_duplicate(body);
@@ -946,11 +956,10 @@
* Add Host: and Content-Length: headers (and others that may be necessary).
* Return the request as an Octstr.
*/
-static Octstr *build_request(Octstr *path_or_url, Octstr *host, long port,
- List *headers, Octstr *request_body,
- char *method_name)
+static Octstr *build_request(char *method_name, Octstr *path_or_url,
+ Octstr *host, long port, List *headers,
+ Octstr *request_body)
{
-
/* XXX headers missing */
Octstr *request;
int i;
@@ -1115,7 +1124,7 @@
* response can be read or -1 for error.
*/
-static Connection *send_request(HTTPServer *trans, char *method_name)
+static Connection *send_request(HTTPServer *trans)
{
Octstr *path, *request;
Connection *conn;
@@ -1131,40 +1140,39 @@
trans->host = NULL;
if (parse_url(trans->url, &trans->host, &trans->port, &path, &trans->ssl,
- &trans->username, &trans->password) == -1)
+ &trans->username, &trans->password) == -1)
goto error;
if (trans->username != NULL)
- http_add_basic_auth(trans->request_headers, trans->username,
- trans->password);
+ http_add_basic_auth(trans->request_headers, trans->username,
+ trans->password);
if (proxy_used_for_host(trans->host)) {
- proxy_add_authentication(trans->request_headers);
- request = build_request(trans->url, trans->host, trans->port,
- trans->request_headers,
- trans->request_body, method_name);
- host = proxy_hostname;
- port = proxy_port;
+ proxy_add_authentication(trans->request_headers);
+ request = build_request(http_method2name(trans->method),
+ trans->url, trans->host, trans->port,
+ trans->request_headers, trans->request_body);
+ host = proxy_hostname;
+ port = proxy_port;
} else {
- request = build_request(path, trans->host, trans->port,
- trans->request_headers,
- trans->request_body, method_name);
- host = trans->host;
- port = trans->port;
+ request = build_request(http_method2name(trans->method), path, trans->host,
+ trans->port, trans->request_headers,
+ trans->request_body);
+ host = trans->host;
+ port = trans->port;
}
if (trans->retrying) {
#ifdef HAVE_LIBSSL
- if (trans->ssl) conn =
- conn_open_ssl(host, port, trans->certkeyfile, our_host);
- else
+ if (trans->ssl)
+ conn = conn_open_ssl(host, port, trans->certkeyfile, our_host);
+ else
#endif /* HAVE_LIBSSL */
- conn = conn_open_tcp(host, port, our_host);
- debug("gwlib.http", 0, "HTTP: Opening NEW connection to `%s:%d' (fd=%d).",
- octstr_get_cstr(host), port, conn_get_id(conn));
+ conn = conn_open_tcp(host, port, our_host);
+ debug("gwlib.http", 0, "HTTP: Opening NEW connection to `%s:%d' (fd=%d).",
+ octstr_get_cstr(host), port, conn_get_id(conn));
} else
- conn = conn_pool_get(host, port, trans->ssl, trans->certkeyfile,
- our_host);
+ conn = conn_pool_get(host, port, trans->ssl, trans->certkeyfile, our_host);
if (conn == NULL)
goto error;
@@ -1199,34 +1207,39 @@
char buf[128];
while (run_status == running) {
- trans = list_consume(pending_requests);
- if (trans == NULL)
- break;
-
- gw_assert(trans->state == request_not_sent);
-
- if (trans->request_body == NULL)
- method = "GET";
- else {
- method = "POST";
- /*
- * Add a Content-Length header. Override an existing one, if
- * necessary. We must have an accurate one in order to use the
- * connection for more than a single request.
- */
- http_header_remove_all(trans->request_headers, "Content-Length");
- sprintf(buf, "%ld", octstr_len(trans->request_body));
- http_header_add(trans->request_headers, "Content-Length", buf);
- }
+ trans = list_consume(pending_requests);
+ if (trans == NULL)
+ break;
+
+ gw_assert(trans->state == request_not_sent);
+
+ if (trans->method == HTTP_METHOD_POST) {
+ /*
+ * Add a Content-Length header. Override an existing one, if
+ * necessary. We must have an accurate one in order to use the
+ * connection for more than a single request.
+ */
+ http_header_remove_all(trans->request_headers, "Content-Length");
+ sprintf(buf, "%ld", octstr_len(trans->request_body));
+ http_header_add(trans->request_headers, "Content-Length", buf);
+ }
+ /*
+ * ok, this has to be an GET or HEAD request method then,
+ * if it contains a body, then this is not HTTP conform, so at
+ * least warn the user
+ */
+ else if (trans->request_body != NULL) {
+ warning(0, "HTTP: GET or HEAD method request contains body:");
+ octstr_dump(trans->request_body, 0);
+ }
- trans->conn = send_request(trans, method);
- if (trans->conn == NULL)
- list_produce(trans->caller, trans);
- else {
- trans->state = reading_status;
- conn_register(trans->conn, client_fdset, handle_transaction,
- trans);
- }
+ trans->conn = send_request(trans);
+ if (trans->conn == NULL)
+ list_produce(trans->caller, trans);
+ else {
+ trans->state = reading_status;
+ conn_register(trans->conn, client_fdset, handle_transaction, trans);
+ }
}
}
@@ -1251,7 +1264,7 @@
}
-void http_start_request(HTTPCaller *caller, Octstr *url, List *headers,
+void http_start_request(HTTPCaller *caller, int method, Octstr *url, List *headers,
Octstr *body, int follow, void *id, Octstr *certkeyfile)
{
HTTPServer *trans;
@@ -1262,7 +1275,7 @@
else
follow_remaining = 0;
- trans = server_create(caller, url, headers, body, follow_remaining,
+ trans = server_create(caller, method, url, headers, body, follow_remaining,
certkeyfile);
if (id == NULL)
@@ -1308,7 +1321,7 @@
}
-int http_get_real(Octstr *url, List *request_headers, Octstr **final_url,
+int http_get_real(int method, Octstr *url, List *request_headers, Octstr **final_url,
List **reply_headers, Octstr **reply_body)
{
HTTPCaller *caller;
@@ -1316,7 +1329,8 @@
void *ret;
caller = http_caller_create();
- http_start_request(caller, url, request_headers, NULL, 1, http_get_real, NULL);
+ http_start_request(caller, method, url, request_headers,
+ NULL, 1, http_get_real, NULL);
ret = http_receive_result(caller, &status, final_url,
reply_headers, reply_body);
http_caller_destroy(caller);
@@ -2705,3 +2719,31 @@
sclass = code - (code % 100);
return sclass;
}
+
+
+int http_name2method(Octstr *method)
+{
+ gw_assert(method != NULL);
+
+ if (octstr_str_compare(method, "GET") == 0) {
+ return HTTP_METHOD_GET;
+ }
+ else if (octstr_str_compare(method, "POST") == 0) {
+ return HTTP_METHOD_POST;
+ }
+ else if (octstr_str_compare(method, "HEAD") == 0) {
+ return HTTP_METHOD_HEAD;
+ }
+
+ return -1;
+}
+
+
+char *http_method2name(int method)
+{
+ gw_assert(method > 0 && method <= 3);
+
+ return http_methods[method-1];
+}
+
+
diff -ur --exclude=Entries gateway-cvs/gwlib/http.h gateway/gwlib/http.h
--- gateway-cvs/gwlib/http.h 2002-04-26 12:39:19.000000000 +0200
+++ gateway/gwlib/http.h 2002-08-19 20:01:07.000000000 +0200
@@ -183,9 +183,9 @@
*
* XXX these are going away in the future
*/
-int http_get_real(Octstr *url, List *request_headers, Octstr **final_url,
- List **reply_headers, Octstr **reply_body);
-
+int http_get_real(int method, Octstr *url, List *request_headers,
+ Octstr **final_url, List **reply_headers,
+ Octstr **reply_body);
/*
* An identification for a caller of HTTP. This is used with
@@ -238,8 +238,8 @@
* is no ssl authentication, unless you have set a global one with
* use_global_certkey_file() from conn.c.
*/
-void http_start_request(HTTPCaller *caller, Octstr *url, List *headers,
- Octstr *body, int follow, void *id,
+void http_start_request(HTTPCaller *caller, int method, Octstr *url,
+ List *headers, Octstr *body, int follow, void *id,
Octstr *certkeyfile);
@@ -481,4 +481,17 @@
*/
int http_status_class(int code);
+
+/*
+ * Return the HTTP_METHOD_xxx enum code for a Octstr containing
+ * the HTTP method name.
+ */
+int http_name2method(Octstr *method);
+
+
+/*
+ * Return the char containing the HTTP method name.
+ */
+char *http_method2name(int method);
+
#endif
diff -ur --exclude=Entries gateway-cvs/gwlib/xmlrpc.c gateway/gwlib/xmlrpc.c
--- gateway-cvs/gwlib/xmlrpc.c 2002-04-29 14:58:00.000000000 +0200
+++ gateway/gwlib/xmlrpc.c 2002-08-19 18:20:12.000000000 +0200
@@ -248,7 +248,8 @@
*/
body = xmlrpc_call_octstr(call);
- http_start_request(http_ref, url, headers, body, 0, ref, NULL);
+ http_start_request(http_ref, HTTP_METHOD_GET,
+ url, headers, body, 0, ref, NULL);
octstr_destroy(body);
http_destroy_headers(headers);
diff -ur --exclude=Entries gateway-cvs/test/test_http.c gateway/test/test_http.c
--- gateway-cvs/test/test_http.c 2002-05-20 16:12:56.000000000 +0200
+++ gateway/test/test_http.c 2002-08-19 20:07:31.000000000 +0200
@@ -17,6 +17,7 @@
static Counter *counter = NULL;
static long max_requests = 1;
+static int method = HTTP_METHOD_GET;
static char **urls = NULL;
static int num_urls = 0;
static int verbose = 1;
@@ -26,6 +27,7 @@
static Octstr *ssl_client_certkey_file = NULL;
static Octstr *extra_headers = NULL;
static Octstr *content_file = NULL; /* if set use POST method */
+static Octstr *method_name = NULL;
static int file = 0;
static List *split = NULL;
@@ -62,18 +64,21 @@
http_header_combine(reqh, split);
/*
- * if a body content file has been specified, then we
- * assume to send a POST request.
+ * if a body content file has been specified, then
+ * we assume this should be a POST
*/
- if (content_file != NULL)
+ if (content_file != NULL) {
content = post_content_create();
-
+ method = HTTP_METHOD_POST;
+ }
+
/*
* if this is a POST request then pass the required content as body to
* the HTTP server, otherwise skip the body, the arguments will be
* urlencoded in the URL itself.
*/
- http_start_request(caller, url, reqh, content, 0, id, ssl_client_certkey_file);
+ http_start_request(caller, method,
+ url, reqh, content, 0, id, ssl_client_certkey_file);
debug("", 0, "Started request %ld with url:", *id);
octstr_url_decode(url);
@@ -232,6 +237,8 @@
info(0, "-B filename");
info(0, " read content from file 'filename' and send it as body");
info(0, " of a POST method request (default: GET if no -B is set)");
+ info(0, "-m method");
+ info(0, " use a specific HTTP method for request to server");
info(0, "-s");
info(0, " use HTTPS scheme to access SSL-enabled HTTP server");
info(0, "-c ssl_client_cert_key_file");
@@ -264,7 +271,7 @@
file = 0;
fp = NULL;
- while ((opt = getopt(argc, argv, "hv:qr:p:P:e:t:a:u:sc:H:B:")) != EOF) {
+ while ((opt = getopt(argc, argv, "hv:qr:p:P:e:t:a:u:sc:H:B:m:")) != EOF) {
switch (opt) {
case 'v':
log_set_output_level(atoi(optarg));
@@ -354,6 +361,10 @@
content_file = octstr_create(optarg);
break;
+ case 'm':
+ method_name = octstr_create(optarg);
+ break;
+
case '?':
default:
error(0, "Invalid option %c", opt);
@@ -380,6 +391,11 @@
}
}
#endif
+
+ if (method_name != NULL) {
+ debug("",0,"XXX %s", octstr_get_cstr(method_name));
+ method = http_name2method(method_name);
+ }
if (proxy != NULL && proxy_port > 0) {
http_use_proxy(proxy, proxy_port, exceptions,
diff -ur --exclude=Entries gateway-cvs/test/test_ppg.c gateway/test/test_ppg.c
--- gateway-cvs/test/test_ppg.c 2002-05-14 13:05:08.000000000 +0200
+++ gateway/test/test_ppg.c 2002-08-19 18:21:34.000000000 +0200
@@ -360,8 +360,8 @@
id = gw_malloc(sizeof(long));
*id = i;
make_url(&push_url);
- http_start_request(caller, push_url, push_headers, push_content, 0, id,
- ssl_client_certkey_file);
+ http_start_request(caller, HTTP_METHOD_GET, push_url, push_headers,
+ push_content, 0, id, ssl_client_certkey_file);
debug("test.ppg", 0, "TEST_PPG: started pushing job %ld", i);
octstr_destroy(push_content);
@@ -408,7 +408,7 @@
http_add_basic_auth(retry_headers, username, password);
trid = gw_malloc(sizeof(long));
*trid = tries;
- http_start_request(caller, final_url, retry_headers,
+ http_start_request(caller, HTTP_METHOD_GET, final_url, retry_headers,
push_content, 0, trid, NULL);
debug("test.ppg ", 0, "TEST_PPG: doing response to %s",
octstr_get_cstr(final_url));
diff -ur --exclude=Entries gateway-cvs/test/test_smsc.c gateway/test/test_smsc.c
--- gateway-cvs/test/test_smsc.c 2002-08-09 12:55:47.000000000 +0200
+++ gateway/test/test_smsc.c 2002-08-19 19:41:01.000000000 +0200
@@ -645,8 +645,8 @@
admin_port, admin_password);
req_headers = http_create_empty_headers();
http_header_add(req_headers, "Content-Type", "text/plain");
- ret = http_get_real(url, req_headers, &final_url, &reply_headers,
- &reply_body);
+ ret = http_get_real(HTTP_METHOD_GET, url, req_headers, &final_url,
+ &reply_headers, &reply_body);
if (ret != -1) {
octstr_destroy(final_url);
http_destroy_headers(reply_headers);