Skip to content

Commit 832c013

Browse files
author
Sebastiano Merlino
committed
Merge branch 'master' of github.com:etr/libhttpserver
2 parents a47f526 + 5c949f2 commit 832c013

File tree

10 files changed

+392
-173
lines changed

10 files changed

+392
-173
lines changed

Makefile.am

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,13 +26,13 @@ ACLOCAL_AMFLAGS = -I m4
2626

2727
SUBDIRS = src test $(PYTHON_DIR) $(JAVA_DIR) $(PHP_DIR) $(LUA_DIR) $(PERL_DIR) $(RUBY_DIR) $(GUILE_DIR)
2828
DIST_SUBDIRS = src test $(PYTHON_DIST_DIR) $(JAVA_DIST_DIR) $(PHP_DIST_DIR) $(LUA_DIST_DIR) $(PERL_DIST_DIR) $(RUBY_DIST_DIR) $(GUILE_DIST_DIR)
29-
EXTRA_DIST = libhttpserver.pc.in debian/changelog.in debian/control.in debian/rules.in debian/libhttpserver-dev.install.in debian/libhttpserver.install.in redhat/libhttpserver.SPEC.in $(DX_CONFIG) $(PYTHON_EXTRA) $(PHP_EXTRA) $(PERL_EXTRA)
29+
EXTRA_DIST = libhttpserver.pc.in debian/changelog.in debian/control.in debian/copyright.in debian/rules.in debian/libhttpserver-dev.install.in debian/libhttpserver.install.in redhat/libhttpserver.SPEC.in $(DX_CONFIG) $(PYTHON_EXTRA) $(PHP_EXTRA) $(PERL_EXTRA)
3030

3131
JAVACLEANFILES = $(top_srcdir)/src/java/*.java $(top_srcdir)/src/java/webserver_wrap.*
3232
PYTHONCLEANFILES = $(top_srcdir)/src/python/*.py $(top_srcdir)/src/python/webserver_wrap.*
3333

3434
MOSTLYCLEANFILES = $(DX_CLEANFILES) redhat/SOURCES/* $(JAVACLEANFILES) $(PYTHONCLEANFILES)
35-
DISTCLEANFILES = redhat/SOURCES/* redhat/SPEC/* redhat/* debian/* DIST_REVISION
35+
DISTCLEANFILES = redhat/SOURCES/* redhat/SPEC/* redhat/RPMS/* redhat/SRPMS/* redhat/* debian/* DIST_REVISION
3636

3737
pkgconfigdir = $(libdir)/pkgconfig
3838
pkgconfig_DATA = libhttpserver.pc
@@ -94,7 +94,9 @@ deb:
9494

9595
rpm: dist
9696
mkdir -p redhat/SOURCES
97-
mkdir -p redhar/BUILD
97+
mkdir -p redhat/BUILD
98+
mkdir -p redhat/RPMS
99+
mkdir -p redhat/SRPMS
98100
cp libhttpserver-@VERSION@.tar.gz redhat/SOURCES
99101
rpmbuild -v -bb redhat/libhttpserver.SPEC
100102
rpmbuild -v -ba redhat/libhttpserver.SPEC

configure.ac

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -410,6 +410,7 @@ AC_OUTPUT(
410410
src/guile/Makefile
411411
test/Makefile
412412
debian/changelog
413+
debian/copyright
413414
debian/control
414415
debian/libhttpserver-dev.install
415416
debian/libhttpserver.install

debian/copyright.in

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
Files: *
2+
Copyright: (C) 2011-2012 Sebastiano Merlino <electrictwister2000@gmail.com>
3+
License: LGPL-2.1+
4+
5+
Files: doc/*
6+
Copyright: (C) 2011-2012 Sebastiano Merlino <electrictwister2000@gmail.com>
7+
8+
License: GFDL-1.3+
9+
Permission is granted to copy, distribute and/or modify this document
10+
under the terms of the GNU Free Documentation License, Version 1.3
11+
or any later version published by the Free Software Foundation;
12+
with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts.
13+
.
14+
The complete text of the GNU Free Documentation License
15+
can be found in /usr/share/common-licenses/GFDL-1.3 file.
16+
17+
License: LGPL-2.1+
18+
This library is free software; you can redistribute it and/or
19+
modify it under the terms of the GNU Lesser General Public
20+
License as published by the Free Software Foundation; either
21+
version 2.1 of the License, or (at your option) any later version.
22+
.
23+
This library is distributed in the hope that it will be useful,
24+
but WITHOUT ANY WARRANTY; without even the implied warranty of
25+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
26+
Lesser General Public License for more details.
27+
.
28+
You should have received a copy of the GNU Lesser General Public
29+
License along with this library; if not, write to the Free Software
30+
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
31+
.
32+
The complete text of the GNU Library General Public License
33+
can be found in /usr/share/common-licenses/LGPL-2.1 file.

src/http_response.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,8 @@ void http_file_response::get_raw_response(MHD_Response** response, webserver* ws
170170
size_t size = http::load_file(filename.c_str(), &page);
171171
if(size)
172172
*response = MHD_create_response_from_buffer(size, page, MHD_RESPMEM_MUST_FREE);
173-
//TODO: At the moment if the file does not exist the system returns empty response
173+
else
174+
*response = MHD_create_response_from_buffer(size, (void*) "", MHD_RESPMEM_PERSISTENT);
174175
}
175176

176177
void cache_response::get_raw_response(MHD_Response** response, webserver* ws)

src/http_utils.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -437,7 +437,8 @@ size_t load_file (const char* filename, char** content)
437437
fp.close();
438438
return size;
439439
}
440-
return 0;
440+
else
441+
throw file_access_exception();
441442
}
442443

443444
char* load_file (const char *filename)

src/httpserver/http_utils.hpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,14 @@ class bad_ip_format_exception: public std::exception
4848
}
4949
};
5050

51+
class file_access_exception: public std::exception
52+
{
53+
virtual const char* what() const throw()
54+
{
55+
return "Unable to open file!";
56+
}
57+
};
58+
5159
class http_utils
5260
{
5361
public:

src/httpserver/webserver.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -363,7 +363,7 @@ class webserver
363363
void clean_connections();
364364

365365
void method_not_allowed_page(http_response** dhrs, details::modded_request* mr);
366-
void internal_error_page(http_response** dhrs, details::modded_request* mr);
366+
void internal_error_page(http_response** dhrs, details::modded_request* mr, bool force_our = false);
367367
void not_found_page(http_response** dhrs, details::modded_request* mr);
368368

369369
static int method_not_acceptable_page

src/webserver.cpp

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1063,9 +1063,9 @@ void webserver::method_not_allowed_page(http_response** dhrs, details::modded_re
10631063
*dhrs = new http_string_response(METHOD_ERROR, http_utils::http_method_not_allowed);
10641064
}
10651065

1066-
void webserver::internal_error_page(http_response** dhrs, details::modded_request* mr)
1066+
void webserver::internal_error_page(http_response** dhrs, details::modded_request* mr, bool force_our)
10671067
{
1068-
if(internal_error_resource != 0x0)
1068+
if(internal_error_resource != 0x0 || !force_our)
10691069
((internal_error_resource)->*(mr->callback))(*mr->dhr, dhrs);
10701070
else
10711071
*dhrs = new http_string_response(GENERIC_ERROR, http_utils::http_internal_server_error);
@@ -1271,7 +1271,32 @@ int webserver::finalize_answer(MHD_Connection* connection, struct details::modde
12711271
#endif //WITH_PYTHON
12721272
mr->dhrs = dhrs;
12731273
mr->dhrs->underlying_connection = connection;
1274-
dhrs->get_raw_response(&raw_response, this);
1274+
try
1275+
{
1276+
try
1277+
{
1278+
dhrs->get_raw_response(&raw_response, this);
1279+
}
1280+
catch(const file_access_exception& fae)
1281+
{
1282+
not_found_page(&dhrs, mr);
1283+
dhrs->get_raw_response(&raw_response, this);
1284+
}
1285+
catch(const std::exception& e)
1286+
{
1287+
internal_error_page(&dhrs, mr);
1288+
dhrs->get_raw_response(&raw_response, this);
1289+
}
1290+
catch(...)
1291+
{
1292+
internal_error_page(&dhrs, mr);
1293+
dhrs->get_raw_response(&raw_response, this);
1294+
}
1295+
}
1296+
catch(...)
1297+
{
1298+
internal_error_page(&dhrs, mr, true);
1299+
}
12751300
dhrs->decorate_response(raw_response);
12761301
to_ret = dhrs->enqueue_response(connection, raw_response);
12771302
MHD_destroy_response (raw_response);

test/basic.cpp

Lines changed: 140 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,28 @@
11
#include "littletest.hpp"
22
#include <curl/curl.h>
3+
#include <string>
4+
#include <map>
35
#include "httpserver.hpp"
46

57
using namespace httpserver;
8+
using namespace std;
9+
10+
size_t writefunc(void *ptr, size_t size, size_t nmemb, std::string *s)
11+
{
12+
s->append((char*) ptr, size*nmemb);
13+
return size*nmemb;
14+
}
15+
16+
size_t headerfunc( void *ptr, size_t size, size_t nmemb, map<string, string>* ss)
17+
{
18+
string s_ptr((char*)ptr, size*nmemb);
19+
size_t pos = s_ptr.find(":");
20+
if(pos != string::npos)
21+
{
22+
(*ss)[s_ptr.substr(0, pos)] = s_ptr.substr(pos + 2, s_ptr.size() - pos - 4);
23+
}
24+
return size*nmemb;
25+
}
626

727
class simple_resource : public http_resource
828
{
@@ -13,38 +33,152 @@ class simple_resource : public http_resource
1333
}
1434
};
1535

36+
class header_test_resource : public http_resource
37+
{
38+
public:
39+
virtual void render_GET(const http_request& req, http_response** res)
40+
{
41+
*res = new http_string_response("OK", 200, "text/plain");
42+
(*res)->set_header("KEY", "VALUE");
43+
}
44+
};
45+
46+
class complete_test_resource : public http_resource
47+
{
48+
public:
49+
virtual void render_GET(const http_request& req, http_response** res)
50+
{
51+
*res = new http_string_response("OK", 200, "text/plain");
52+
}
53+
virtual void render_POST(const http_request& req, http_response** res)
54+
{
55+
*res = new http_string_response("OK", 200, "text/plain");
56+
}
57+
virtual void render_PUT(const http_request& req, http_response** res)
58+
{
59+
*res = new http_string_response("OK", 200, "text/plain");
60+
}
61+
virtual void render_DELETE(const http_request& req, http_response** res)
62+
{
63+
*res = new http_string_response("OK", 200, "text/plain");
64+
}
65+
virtual void render_HEAD(const http_request& req, http_response** res)
66+
{
67+
*res = new http_string_response("OK", 200, "text/plain");
68+
}
69+
virtual void render_CONNECT(const http_request& req, http_response** res)
70+
{
71+
*res = new http_string_response("OK", 200, "text/plain");
72+
}
73+
};
74+
1675
LT_BEGIN_SUITE(basic_suite)
1776

1877
webserver* ws;
19-
simple_resource* res;
2078

2179
void set_up()
2280
{
2381
ws = new webserver(create_webserver(8080));
24-
res = new simple_resource();
25-
ws->register_resource("base", res);
2682
ws->start(false);
2783
}
2884

29-
void tier_down()
85+
void tear_down()
3086
{
3187
ws->stop();
3288
delete ws;
33-
delete res;
3489
}
3590
LT_END_SUITE(basic_suite)
3691

3792
LT_BEGIN_AUTO_TEST(basic_suite, read_body)
93+
simple_resource* resource = new simple_resource();
94+
ws->register_resource("base", resource);
3895
curl_global_init(CURL_GLOBAL_ALL);
96+
std::string s;
3997
CURL *curl = curl_easy_init();
4098
CURLcode res;
4199
curl_easy_setopt(curl, CURLOPT_URL, "localhost:8080/base");
42100
curl_easy_setopt(curl, CURLOPT_HTTPGET, 1L);
101+
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writefunc);
102+
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &s);
43103
res = curl_easy_perform(curl);
104+
LT_ASSERT_EQ(res, 0);
105+
LT_CHECK_EQ(s, "OK");
106+
curl_easy_cleanup(curl);
107+
LT_END_AUTO_TEST(read_body)
44108

109+
LT_BEGIN_AUTO_TEST(basic_suite, read_header)
110+
header_test_resource* resource = new header_test_resource();
111+
ws->register_resource("base", resource);
112+
curl_global_init(CURL_GLOBAL_ALL);
113+
std::string s;
114+
map<string, string> ss;
115+
CURL *curl = curl_easy_init();
116+
CURLcode res;
117+
curl_easy_setopt(curl, CURLOPT_URL, "localhost:8080/base");
118+
curl_easy_setopt(curl, CURLOPT_HTTPGET, 1L);
119+
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writefunc);
120+
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &s);
121+
curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, headerfunc);
122+
curl_easy_setopt(curl, CURLOPT_WRITEHEADER, &ss);
123+
res = curl_easy_perform(curl);
45124
LT_ASSERT_EQ(res, 0);
125+
LT_CHECK_EQ(s, "OK");
126+
LT_CHECK_EQ(ss["KEY"], "VALUE");
127+
curl_easy_cleanup(curl);
128+
LT_END_AUTO_TEST(read_header)
46129

47-
LT_END_AUTO_TEST(read_body)
130+
LT_BEGIN_AUTO_TEST(basic_suite, complete)
131+
simple_resource* resource = new simple_resource();
132+
ws->register_resource("base", resource);
133+
curl_global_init(CURL_GLOBAL_ALL);
134+
std::string s;
135+
CURL* curl;
136+
CURLcode res;
137+
138+
curl = curl_easy_init();
139+
curl_easy_setopt(curl, CURLOPT_URL, "localhost:8080/base");
140+
curl_easy_setopt(curl, CURLOPT_HTTPGET, 1L);
141+
res = curl_easy_perform(curl);
142+
LT_ASSERT_EQ(res, 0);
143+
curl_easy_cleanup(curl);
144+
145+
curl = curl_easy_init();
146+
curl_easy_setopt(curl, CURLOPT_URL, "localhost:8080/base");
147+
curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "DELETE");
148+
res = curl_easy_perform(curl);
149+
LT_ASSERT_EQ(res, 0);
150+
curl_easy_cleanup(curl);
151+
152+
curl = curl_easy_init();
153+
curl_easy_setopt(curl, CURLOPT_URL, "localhost:8080/base");
154+
curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "PUT");
155+
res = curl_easy_perform(curl);
156+
LT_ASSERT_EQ(res, 0);
157+
curl_easy_cleanup(curl);
158+
159+
curl = curl_easy_init();
160+
curl_easy_setopt(curl, CURLOPT_URL, "localhost:8080/base");
161+
curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "HEAD");
162+
res = curl_easy_perform(curl);
163+
LT_ASSERT_EQ(res, 0);
164+
curl_easy_cleanup(curl);
165+
166+
curl = curl_easy_init();
167+
curl_easy_setopt(curl, CURLOPT_URL, "localhost:8080/base");
168+
curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "CONNECT");
169+
res = curl_easy_perform(curl);
170+
LT_ASSERT_EQ(res, 0);
171+
curl_easy_cleanup(curl);
172+
173+
curl = curl_easy_init();
174+
curl_easy_setopt(curl, CURLOPT_URL, "localhost:8080/base");
175+
curl_easy_setopt(curl, CURLOPT_POST, 1L);
176+
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, NULL);
177+
curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, 0);
178+
res = curl_easy_perform(curl);
179+
LT_ASSERT_EQ(res, 0);
180+
curl_easy_cleanup(curl);
181+
LT_END_AUTO_TEST(complete)
48182

49183

50184
LT_BEGIN_AUTO_TEST_ENV()

0 commit comments

Comments
 (0)