Commit 9bda69f5 authored by Sergey Lyubka's avatar Sergey Lyubka

Fix issue 180 - make mg_read() handle PUT requests, too. Stop checking for...

Fix issue 180 - make mg_read() handle PUT requests, too. Stop checking for request method in mg_read().
parents fb9493a0 0db96c5b
...@@ -14,13 +14,15 @@ all: ...@@ -14,13 +14,15 @@ all:
# -DNO_SSL - disable SSL functionality (-2kb) # -DNO_SSL - disable SSL functionality (-2kb)
# -DCONFIG_FILE=\"file\" - use `file' as the default config file # -DCONFIG_FILE=\"file\" - use `file' as the default config file
# -DHAVE_STRTOUI64 - use system strtoui64() function for strtoull() # -DHAVE_STRTOUI64 - use system strtoui64() function for strtoull()
# -DSSL_LIB=\"libssl.so.<version>\" - use system versioned SSL shared object
# -DCRYPTO_LIB=\"libcrypto.so.<version>\" - use system versioned CRYPTO so
########################################################################## ##########################################################################
### UNIX build: linux, bsd, mac, rtems ### UNIX build: linux, bsd, mac, rtems
########################################################################## ##########################################################################
CFLAGS= -W -Wall -std=c99 -pedantic -O2 -fomit-frame-pointer $(COPT) CFLAGS= -W -Wall -std=c99 -pedantic -O2 $(COPT)
MAC_SHARED= -flat_namespace -bundle -undefined suppress MAC_SHARED= -flat_namespace -bundle -undefined suppress
LINFLAGS= -ldl -pthread $(CFLAGS) LINFLAGS= -ldl -pthread $(CFLAGS)
LIB= _$(PROG).so LIB= _$(PROG).so
...@@ -126,7 +128,7 @@ do_test: ...@@ -126,7 +128,7 @@ do_test:
perl test/test.pl $(TEST) perl test/test.pl $(TEST)
release: clean release: clean
F=mongoose-`perl -lne '/define\s+MONGOOSE_VERSION\s+"(\S+)"/ and print $$1' mongoose.c`.tgz ; cd .. && tar --exclude \*.hg --exclude \*.svn --exclude \*.swp --exclude \*.nfs\* --exclude win32 -czf x mongoose && mv x mongoose/$$F F=mongoose-`perl -lne '/define\s+MONGOOSE_VERSION\s+"(\S+)"/ and print $$1' mongoose.c`.tgz ; cd .. && tar --exclude \*.hg --exclude \*.svn --exclude \*.swp --exclude \*.nfs\* -czf x mongoose && mv x mongoose/$$F
clean: clean:
rm -rf *.o *.core $(PROG) *.obj $(PROG).txt *.dSYM *.tgz rm -rf *.o *.core $(PROG) *.obj $(PROG).txt *.dSYM *.tgz
...@@ -374,7 +374,7 @@ int main(void) { ...@@ -374,7 +374,7 @@ int main(void) {
srand((unsigned) time(0)); srand((unsigned) time(0));
// Setup and start Mongoose // Setup and start Mongoose
ctx = mg_start(&event_handler, options); ctx = mg_start(&event_handler, NULL, options);
assert(ctx != NULL); assert(ctx != NULL);
// Wait until enter is pressed, then exit // Wait until enter is pressed, then exit
......
This diff is collapsed.
...@@ -31,39 +31,45 @@ ...@@ -31,39 +31,45 @@
#include "mongoose.h" #include "mongoose.h"
#if !defined(LISTENING_PORT) #if !defined(LISTENING_PORT)
#define LISTENING_PORT "23456" #define LISTENING_PORT "23456"
#endif #endif
static const char *standard_reply = "HTTP/1.1 200 OK\r\n" static const char *standard_reply = "HTTP/1.1 200 OK\r\n"
"Content-Type: text/plain\r\n" "Content-Type: text/plain\r\n"
"Connection: close\r\n\r\n"; "Connection: close\r\n\r\n";
static void test_get_var(struct mg_connection *conn, static void test_get_var(struct mg_connection *conn,
const struct mg_request_info *ri) { const struct mg_request_info *ri) {
char *var, *buf; char *var, *buf;
size_t buf_len; size_t buf_len;
const char *cl; const char *cl;
int var_len; int var_len;
mg_printf(conn, "%s", standard_reply); mg_printf(conn, "%s", standard_reply);
buf_len = 0; buf_len = 0;
var = buf = NULL; var = buf = NULL;
cl = mg_get_header(conn, "Content-Length"); cl = mg_get_header(conn, "Content-Length");
mg_printf(conn, "cl: %p\n", cl); mg_printf(conn, "cl: %p\n", cl);
printf("reqeust method = %s\n", ri->request_method); if ((!strcmp(ri->request_method, "POST") ||
if ((!strcmp(ri->request_method, "POST") || !strcmp(ri->request_method, "PUT")) !strcmp(ri->request_method, "PUT"))
&& cl != NULL) { && cl != NULL) {
buf_len = atoi(cl); buf_len = atoi(cl);
buf = malloc(buf_len); buf = malloc(buf_len);
mg_read(conn, buf, buf_len); /* Read in two pieces, to test continuation */
if (buf_len > 2) {
mg_read(conn, buf, 2);
mg_read(conn, buf + 2, buf_len - 2);
} else {
mg_read(conn, buf, buf_len);
}
} else if (ri->query_string != NULL) { } else if (ri->query_string != NULL) {
buf_len = strlen(ri->query_string); buf_len = strlen(ri->query_string);
buf = malloc(buf_len + 1); buf = malloc(buf_len + 1);
strcpy(buf, ri->query_string); strcpy(buf, ri->query_string);
} }
var = malloc(buf_len + 1); var = malloc(buf_len + 1);
var_len = mg_get_var(buf, buf_len, "my_var", var, buf_len + 1); var_len = mg_get_var(buf, buf_len, "my_var", var, buf_len + 1);
mg_printf(conn, "Value: [%s]\n", var); mg_printf(conn, "Value: [%s]\n", var);
mg_printf(conn, "Value size: [%d]\n", var_len); mg_printf(conn, "Value size: [%d]\n", var_len);
free(buf); free(buf);
...@@ -72,50 +78,50 @@ static void test_get_var(struct mg_connection *conn, ...@@ -72,50 +78,50 @@ static void test_get_var(struct mg_connection *conn,
static void test_get_header(struct mg_connection *conn, static void test_get_header(struct mg_connection *conn,
const struct mg_request_info *ri) { const struct mg_request_info *ri) {
const char *value; const char *value;
int i; int i;
mg_printf(conn, "%s", standard_reply); mg_printf(conn, "%s", standard_reply);
printf("HTTP headers: %d\n", ri->num_headers); printf("HTTP headers: %d\n", ri->num_headers);
for (i = 0; i < ri->num_headers; i++) { for (i = 0; i < ri->num_headers; i++) {
printf("[%s]: [%s]\n", ri->http_headers[i].name, ri->http_headers[i].value); printf("[%s]: [%s]\n", ri->http_headers[i].name, ri->http_headers[i].value);
} }
value = mg_get_header(conn, "Host"); value = mg_get_header(conn, "Host");
if (value != NULL) { if (value != NULL) {
mg_printf(conn, "Value: [%s]", value); mg_printf(conn, "Value: [%s]", value);
} }
} }
static void test_get_request_info(struct mg_connection *conn, static void test_get_request_info(struct mg_connection *conn,
const struct mg_request_info *ri) { const struct mg_request_info *ri) {
int i; int i;
mg_printf(conn, "%s", standard_reply); mg_printf(conn, "%s", standard_reply);
mg_printf(conn, "Method: [%s]\n", ri->request_method); mg_printf(conn, "Method: [%s]\n", ri->request_method);
mg_printf(conn, "URI: [%s]\n", ri->uri); mg_printf(conn, "URI: [%s]\n", ri->uri);
mg_printf(conn, "HTTP version: [%s]\n", ri->http_version); mg_printf(conn, "HTTP version: [%s]\n", ri->http_version);
for (i = 0; i < ri->num_headers; i++) { for (i = 0; i < ri->num_headers; i++) {
mg_printf(conn, "HTTP header [%s]: [%s]\n", mg_printf(conn, "HTTP header [%s]: [%s]\n",
ri->http_headers[i].name, ri->http_headers[i].name,
ri->http_headers[i].value); ri->http_headers[i].value);
} }
mg_printf(conn, "Query string: [%s]\n", mg_printf(conn, "Query string: [%s]\n",
ri->query_string ? ri->query_string: ""); ri->query_string ? ri->query_string: "");
mg_printf(conn, "Remote IP: [%lu]\n", ri->remote_ip); mg_printf(conn, "Remote IP: [%lu]\n", ri->remote_ip);
mg_printf(conn, "Remote port: [%d]\n", ri->remote_port); mg_printf(conn, "Remote port: [%d]\n", ri->remote_port);
mg_printf(conn, "Remote user: [%s]\n", mg_printf(conn, "Remote user: [%s]\n",
ri->remote_user ? ri->remote_user : ""); ri->remote_user ? ri->remote_user : "");
} }
static void test_error(struct mg_connection *conn, static void test_error(struct mg_connection *conn,
const struct mg_request_info *ri) { const struct mg_request_info *ri) {
mg_printf(conn, "HTTP/1.1 %d XX\r\n" mg_printf(conn, "HTTP/1.1 %d XX\r\n"
"Conntection: close\r\n\r\n", ri->status_code); "Conntection: close\r\n\r\n", ri->status_code);
mg_printf(conn, "Error: [%d]", ri->status_code); mg_printf(conn, "Error: [%d]", ri->status_code);
} }
static void test_post(struct mg_connection *conn, static void test_post(struct mg_connection *conn,
...@@ -124,7 +130,7 @@ static void test_post(struct mg_connection *conn, ...@@ -124,7 +130,7 @@ static void test_post(struct mg_connection *conn,
char *buf; char *buf;
int len; int len;
mg_printf(conn, "%s", standard_reply); mg_printf(conn, "%s", standard_reply);
if (strcmp(ri->request_method, "POST") == 0 && if (strcmp(ri->request_method, "POST") == 0 &&
(cl = mg_get_header(conn, "Content-Length")) != NULL) { (cl = mg_get_header(conn, "Content-Length")) != NULL) {
len = atoi(cl); len = atoi(cl);
...@@ -166,10 +172,10 @@ static void *callback(enum mg_event event, ...@@ -166,10 +172,10 @@ static void *callback(enum mg_event event,
} }
int main(void) { int main(void) {
struct mg_context *ctx; struct mg_context *ctx;
const char *options[] = {"listening_ports", LISTENING_PORT, NULL}; const char *options[] = {"listening_ports", LISTENING_PORT, NULL};
ctx = mg_start(callback, NULL, options); ctx = mg_start(callback, NULL, options);
pause(); pause();
return 0; return 0;
} }
...@@ -50,7 +50,7 @@ sub get_num_of_log_entries { ...@@ -50,7 +50,7 @@ sub get_num_of_log_entries {
# Send the request to the 127.0.0.1:$port and return the reply # Send the request to the 127.0.0.1:$port and return the reply
sub req { sub req {
my ($request, $inc) = @_; my ($request, $inc, $timeout) = @_;
my $sock = IO::Socket::INET->new(Proto=>"tcp", my $sock = IO::Socket::INET->new(Proto=>"tcp",
PeerAddr=>'127.0.0.1', PeerPort=>$port); PeerAddr=>'127.0.0.1', PeerPort=>$port);
fail("Cannot connect: $!") unless $sock; fail("Cannot connect: $!") unless $sock;
...@@ -59,8 +59,12 @@ sub req { ...@@ -59,8 +59,12 @@ sub req {
last unless print $sock $byte; last unless print $sock $byte;
select undef, undef, undef, .001 if length($request) < 256; select undef, undef, undef, .001 if length($request) < 256;
} }
my @lines = <$sock>; my ($out, $buf) = ('', '');
my $out = join '', @lines; eval {
alarm $timeout if $timeout;
$out .= $buf while (sysread($sock, $buf, 1024) > 0);
alarm 0 if $timeout;
};
close $sock; close $sock;
$num_requests += defined($inc) ? $inc : 1; $num_requests += defined($inc) ? $inc : 1;
...@@ -129,6 +133,7 @@ sub kill_spawned_child { ...@@ -129,6 +133,7 @@ sub kill_spawned_child {
unlink @files_to_delete; unlink @files_to_delete;
$SIG{PIPE} = 'IGNORE'; $SIG{PIPE} = 'IGNORE';
$SIG{ALRM} = sub { die "timeout\n" };
#local $| =1; #local $| =1;
# Make sure we export only symbols that start with "mg_", and keep local # Make sure we export only symbols that start with "mg_", and keep local
...@@ -175,6 +180,14 @@ o("GET /hello.txt HTTP/1.0\n\n", 'Content-Length: 17\s', ...@@ -175,6 +180,14 @@ o("GET /hello.txt HTTP/1.0\n\n", 'Content-Length: 17\s',
o("GET /%68%65%6c%6c%6f%2e%74%78%74 HTTP/1.0\n\n", o("GET /%68%65%6c%6c%6f%2e%74%78%74 HTTP/1.0\n\n",
'HTTP/1.1 200 OK', 'URL-decoding'); 'HTTP/1.1 200 OK', 'URL-decoding');
# Break CGI reading after 1 second. We must get full output.
# Since CGI script does sleep, we sleep as well and increase request count
# manually.
fail('Slow CGI output forward ') unless
req("GET /timeout.cgi HTTP/1.0\r\n\r\n", 0, 1) =~ /Some data/s;
sleep 3;
$num_requests++;
# '+' in URI must not be URL-decoded to space # '+' in URI must not be URL-decoded to space
write_file("$root/a+.txt", ''); write_file("$root/a+.txt", '');
o("GET /a+.txt HTTP/1.0\n\n", 'HTTP/1.1 200 OK', 'URL-decoding, + in URI'); o("GET /a+.txt HTTP/1.0\n\n", 'HTTP/1.1 200 OK', 'URL-decoding, + in URI');
......
#!/usr/bin/env perl
# Make stdout unbuffered
$| = 1;
# This script outputs some content, then sleeps for 5 seconds, then exits.
# Web server should return the content immediately after it is sent,
# not waiting until the script exits.
print "Content-Type: text/html\r\n\r\n";
print "Some data";
sleep 3;
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment