Skip to content

Commit 874dcd5

Browse files
author
Sebastiano Merlino
committed
Solved a bug that was causing problems with File Responses.
Created support methods in order to implement protocol switch.
1 parent 6af4d2f commit 874dcd5

File tree

7 files changed

+166
-80
lines changed

7 files changed

+166
-80
lines changed

src/HttpResource.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -59,17 +59,17 @@ HttpResponse HttpResource::render(const HttpRequest& r)
5959

6060
HttpResponse HttpResource::render_404()
6161
{
62-
return HttpResponse(NOT_FOUND_ERROR, 404);
62+
return HttpStringResponse(NOT_FOUND_ERROR, 404);
6363
}
6464

6565
HttpResponse HttpResource::render_405()
6666
{
67-
return HttpResponse(METHOD_ERROR, 405);
67+
return HttpStringResponse(METHOD_ERROR, 405);
6868
}
6969

7070
HttpResponse HttpResource::render_500()
7171
{
72-
return HttpResponse(GENERIC_ERROR, 500);
72+
return HttpStringResponse(GENERIC_ERROR, 500);
7373
}
7474

7575
HttpResponse HttpResource::render_GET(const HttpRequest& r)

src/HttpResponse.cpp

Lines changed: 25 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -22,45 +22,46 @@
2222
#include "Webserver.hpp"
2323
#include "HttpResponse.hpp"
2424

25+
#include <iostream>
26+
2527
using namespace std;
2628

2729
namespace httpserver
2830
{
2931
//RESPONSE
30-
void HttpResponse::HttpResponseInit
32+
HttpFileResponse::HttpFileResponse
3133
(
32-
const string& content,
34+
const string& filename,
3335
int responseCode,
34-
const std::string& contentType,
35-
const HttpResponse::ResponseType_T& responseType
36+
const std::string& contentType
3637
)
3738
{
38-
if(responseType == HttpResponse::FILE_CONTENT)
39+
FILE* f;
40+
this->filename = filename;
41+
if(!(f = fopen(filename.c_str(), "r")))
3942
{
40-
FILE* f;
41-
if(!(f = fopen(content.c_str(), "r")))
42-
{
43-
this->content = NOT_FOUND_ERROR;
44-
this->responseCode = 404;
45-
this->setHeader(HttpUtils::http_header_content_type, contentType);
46-
this->fp = -1;
47-
}
48-
else
49-
{
50-
this->responseCode = responseCode;
51-
this->filename = content;
52-
this->fp = fileno(f);
53-
}
43+
this->responseType = HttpResponse::STRING_CONTENT;
44+
this->content = NOT_FOUND_ERROR;
45+
this->responseCode = HttpUtils::http_not_found;
46+
this->setHeader(HttpUtils::http_header_content_type, contentType);
47+
this->fp = -1;
5448
}
5549
else
5650
{
57-
this->content = content;
51+
this->responseType = HttpResponse::FILE_CONTENT;
5852
this->responseCode = responseCode;
59-
if(responseType == HttpResponse::SHOUTCAST_CONTENT)
60-
this->responseCode |= HttpUtils::shoutcast_response;
61-
this->setHeader(HttpUtils::http_header_content_type, contentType);
62-
this->fp = -1;
53+
this->fp = fileno(f);
6354
}
6455
}
6556

57+
ShoutCASTResponse::ShoutCASTResponse
58+
(
59+
const std::string& content,
60+
int responseCode,
61+
const std::string& contentType
62+
):
63+
HttpResponse(HttpResponse::SHOUTCAST_CONTENT, content, responseCode | HttpUtils::shoutcast_response, contentType)
64+
{
65+
}
66+
6667
};

src/Webserver.cpp

Lines changed: 25 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -427,15 +427,13 @@ void Webserver::allowIp(const string& ip)
427427
{
428428
ip_representation t_ip(ip);
429429
set<ip_representation>::iterator it = allowances.find(t_ip);
430-
if(t_ip.weight() > (*it).weight())
430+
if(it != allowances.end() && (t_ip.weight() < (*it).weight()))
431431
{
432432
this->allowances.erase(it);
433433
this->allowances.insert(t_ip);
434434
}
435435
else
436-
{
437436
this->allowances.insert(t_ip);
438-
}
439437
}
440438

441439
void Webserver::unbanIp(const string& ip)
@@ -566,6 +564,11 @@ int Webserver::post_iterator (void *cls, enum MHD_ValueKind kind,
566564
return MHD_YES;
567565
}
568566

567+
void Webserver::upgrade_handler (void *cls, struct MHD_Connection* connection,
568+
void **con_cls, int upgrade_socket)
569+
{
570+
}
571+
569572
int Webserver::not_found_page (const void *cls,
570573
struct MHD_Connection *connection)
571574
{
@@ -777,27 +780,33 @@ int Webserver::answerToConnection(void* cls, MHD_Connection* connection,
777780
PyGILState_Release(gstate);
778781
}
779782
#endif
780-
if(dhrs.content != "")
781-
{
782-
vector<char> v_page(dhrs.content.begin(), dhrs.content.end());
783-
size = v_page.size();
784-
page = (void*) malloc(size*sizeof(char));
785-
memcpy( page, &v_page[0], sizeof( char ) * size );
786-
to_free = true;
787-
}
788-
else
789-
{
790-
page = (void*)"";
791-
}
792783
if(dhrs.responseType == HttpResponse::FILE_CONTENT)
793784
{
794785
struct stat st;
795786
fstat(dhrs.fp, &st);
796787
size_t filesize = st.st_size;
797-
response = MHD_create_response_from_fd_at_offset(filesize, dhrs.fp, 0);
788+
response = MHD_create_response_from_fd(filesize, dhrs.fp);
789+
}
790+
else if(dhrs.responseType == HttpResponse::SWITCH_PROTOCOL)
791+
{
792+
response = MHD_create_response_for_upgrade(&upgrade_handler, (void*)dhrs.getSwitchCallback());
798793
}
799794
else
795+
{
796+
if(dhrs.content != "")
797+
{
798+
vector<char> v_page(dhrs.content.begin(), dhrs.content.end());
799+
size = v_page.size();
800+
page = (void*) malloc(size*sizeof(char));
801+
memcpy( page, &v_page[0], sizeof( char ) * size );
802+
to_free = true;
803+
}
804+
else
805+
{
806+
page = (void*)"";
807+
}
800808
response = MHD_create_response_from_buffer(size, page, MHD_RESPMEM_MUST_COPY);
809+
}
801810
vector<pair<string,string> > response_headers = dhrs.getHeaders();
802811
vector<pair<string,string> > response_footers = dhrs.getFooters();
803812
vector<pair<string,string> >::iterator it;

src/httpserver.hpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,11 @@ namespace std {
5656
%feature("director") Webserver;
5757
%feature("director") HttpRequest;
5858
%feature("director") HttpResponse;
59+
%feature("director") HttpStringResponse;
60+
%feature("director") HttpFileResponse;
61+
%feature("director") HttpBasicAuthFailResponse;
62+
%feature("director") HttpDigestAuthFailResponse;
63+
%feature("director") ShoutCASTResponse;
5964
%feature("director") HttpResource;
6065
%feature("director") HttpEndpoint;
6166
%feature("director") HttpUtils;

src/httpserver/HttpResponse.hpp

Lines changed: 98 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -51,19 +51,10 @@ class HttpResponse
5151
FILE_CONTENT,
5252
SHOUTCAST_CONTENT,
5353
DIGEST_AUTH_FAIL,
54-
BASIC_AUTH_FAIL
54+
BASIC_AUTH_FAIL,
55+
SWITCH_PROTOCOL
5556
};
5657

57-
/**
58-
* Default constructor
59-
**/
60-
HttpResponse():
61-
content("{}"),
62-
responseCode(200),
63-
fp(-1)
64-
{
65-
setHeader(HttpUtils::http_header_content_type, "text/plain");
66-
}
6758
/**
6859
* Constructor used to build an HttpResponse with a content and a responseCode
6960
* @param content The content to set for the request. (if the responseType is FILE_CONTENT, it represents the path to the file to read from).
@@ -72,41 +63,41 @@ class HttpResponse
7263
**/
7364
HttpResponse
7465
(
75-
const std::string& content,
76-
int responseCode,
77-
const std::string& contentType = "text/plain",
7866
const HttpResponse::ResponseType_T& responseType = HttpResponse::STRING_CONTENT,
67+
const std::string& content = "",
68+
int responseCode = 200,
69+
const std::string& contentType = "text/plain",
7970
const std::string& realm = "",
8071
const std::string& opaque = "",
8172
bool reloadNonce = false
8273
):
8374
responseType(responseType),
75+
content(content),
76+
responseCode(responseCode),
8477
realm(realm),
8578
opaque(opaque),
86-
reloadNonce(reloadNonce)
79+
reloadNonce(reloadNonce),
80+
fp(-1),
81+
filename(content)
8782
{
88-
HttpResponseInit(content, responseCode, contentType, responseType);
83+
setHeader(HttpUtils::http_header_content_type, contentType);
8984
}
90-
void HttpResponseInit
91-
(
92-
const std::string& content,
93-
int responseCode,
94-
const std::string& contentType = "text/plain",
95-
const HttpResponse::ResponseType_T& responseType = HttpResponse::STRING_CONTENT
96-
);
85+
9786
/**
9887
* Copy constructor
9988
* @param b The HttpResponse object to copy attributes value from.
10089
**/
10190
HttpResponse(const HttpResponse& b):
102-
content(b.content),
10391
responseType(b.responseType),
92+
content(b.content),
10493
responseCode(b.responseCode),
105-
headers(b.headers),
106-
footers(b.footers),
10794
realm(b.realm),
10895
opaque(b.opaque),
109-
reloadNonce(b.reloadNonce)
96+
reloadNonce(b.reloadNonce),
97+
fp(b.fp),
98+
filename(b.filename),
99+
headers(b.headers),
100+
footers(b.footers)
110101
{
111102
}
112103
/**
@@ -257,18 +248,92 @@ class HttpResponse
257248
{
258249
return this->reloadNonce;
259250
}
260-
private:
251+
int getSwitchCallback() const
252+
{
253+
return 0;
254+
}
255+
protected:
261256
friend class Webserver;
262-
std::string content;
263257
ResponseType_T responseType;
258+
std::string content;
264259
int responseCode;
265-
std::map<std::string, std::string, HeaderComparator> headers;
266-
std::map<std::string, std::string, ArgComparator> footers;
267-
int fp;
268-
std::string filename;
269260
std::string realm;
270261
std::string opaque;
271262
bool reloadNonce;
263+
int fp;
264+
std::string filename;
265+
std::map<std::string, std::string, HeaderComparator> headers;
266+
std::map<std::string, std::string, ArgComparator> footers;
267+
};
268+
269+
class HttpStringResponse : public HttpResponse
270+
{
271+
public:
272+
HttpStringResponse
273+
(
274+
const std::string& content,
275+
int responseCode,
276+
const std::string& contentType = "text/plain"
277+
): HttpResponse(HttpResponse::STRING_CONTENT, content, responseCode, contentType) { }
278+
};
279+
280+
class HttpFileResponse : public HttpResponse
281+
{
282+
public:
283+
HttpFileResponse
284+
(
285+
const std::string& filename,
286+
int responseCode,
287+
const std::string& contentType = "text/plain"
288+
);
289+
};
290+
291+
class HttpBasicAuthFailResponse : public HttpResponse
292+
{
293+
public:
294+
HttpBasicAuthFailResponse
295+
(
296+
const std::string& content,
297+
int responseCode,
298+
const std::string& contentType = "text/plain",
299+
const std::string& realm = "",
300+
const HttpResponse::ResponseType_T& responseType = HttpResponse::BASIC_AUTH_FAIL
301+
) : HttpResponse(HttpResponse::BASIC_AUTH_FAIL, content, responseCode, contentType, realm) { }
302+
};
303+
304+
class HttpDigestAuthFailResponse : public HttpResponse
305+
{
306+
public:
307+
HttpDigestAuthFailResponse
308+
(
309+
const std::string& content,
310+
int responseCode,
311+
const std::string& contentType = "text/plain",
312+
const std::string& realm = "",
313+
const std::string& opaque = "",
314+
bool reloadNonce = false
315+
) : HttpResponse(HttpResponse::DIGEST_AUTH_FAIL, content, responseCode, contentType, realm, opaque, reloadNonce)
316+
{
317+
}
318+
};
319+
320+
class ShoutCASTResponse : public HttpResponse
321+
{
322+
public:
323+
ShoutCASTResponse
324+
(
325+
const std::string& content,
326+
int responseCode,
327+
const std::string& contentType = "text/plain"
328+
);
329+
};
330+
331+
class SwitchProtocolResponse : public HttpResponse
332+
{
333+
public:
334+
SwitchProtocolResponse
335+
(
336+
);
272337
};
273338

274339
};

src/httpserver/Webserver.hpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -285,6 +285,12 @@ class Webserver
285285
const char *transfer_encoding,
286286
const char *data, uint64_t off, size_t size
287287
);
288+
static void upgrade_handler
289+
(
290+
void *cls,
291+
struct MHD_Connection* connection,
292+
void **con_cls, int upgrade_socket
293+
);
288294

289295
friend int policyCallback (void *cls, const struct sockaddr* addr, socklen_t addrlen);
290296
friend void error_log(void* cls, const char* fmt, va_list ap);

0 commit comments

Comments
 (0)