3131
3232#include "celix_compiler.h"
3333#include "celix_threads.h"
34+ #include "celix_stdlib_cleanup.h"
35+
36+ #define CELIX_HTTP_ADMIN_READ_ERROR_MSG "Bad Request: Read error"
37+ #define CELIX_HTTP_ADMIN_INCOMPLETE_BODY_MSG "Bad Request: Incomplete Body"
38+ #define CELIX_HTTP_ADMIN_INSUFFICIENT_MEM_MSG "Server Error: Insufficient memory"
3439
3540
3641struct http_admin_manager {
@@ -56,7 +61,11 @@ typedef struct http_alias {
5661
5762//Local function prototypes
5863static int http_request_handle (struct mg_connection * connection );
59- static bool httpAdmin_readRequestBody (struct mg_connection * connection , long long content_length , char * * bufferOut , size_t * bytesReadOut );
64+ /**
65+ * @brief read the request body.
66+ * @return 0 if succesfull, > 0 and a error code (4xx or 5xx) if not sucessfull.
67+ */
68+ static int httpAdmin_readRequestBody (struct mg_connection * connection , long long content_length , char * * bufferOut , size_t * bytesReadOut , const char * * errorMsgOut );
6069static void httpAdmin_updateInfoSvc (http_admin_manager_t * admin );
6170static void createAliasesSymlink (const char * aliases , const char * admin_root , const char * bundle_root , long bundle_id , celix_array_list_t * alias_list );
6271static bool aliasList_containsAlias (celix_array_list_t * alias_list , const char * alias );
@@ -174,32 +183,37 @@ void http_admin_removeHttpService(void *handle, void *svc CELIX_UNUSED, const ce
174183 }
175184}
176185
177- static bool httpAdmin_readRequestBody (struct mg_connection * connection , long long contentLength , char * * bufferOut , size_t * bytesReadOut ) {
178- char * buffer = NULL ;
186+ static int httpAdmin_readRequestBody (struct mg_connection * connection , long long contentLength , char * * bufferOut , size_t * bytesReadOut , const char * * errorMsgOut ) {
187+ celix_autofree char * buffer = NULL ;
179188 size_t totalBytesRead = 0 ;
180- bool success = true ;
189+ * errorMsgOut = NULL ;
181190 if (contentLength > 0 ) {
182191 size_t length = (contentLength > INT_MAX ) ? INT_MAX : (size_t )contentLength ;
183192 buffer = malloc (length + 1 );
184193 if (buffer == NULL ) {
185- success = false;
186- } else {
187- while (totalBytesRead < length ) {
188- int read = mg_read (connection , buffer + totalBytesRead , length - totalBytesRead );
189- if (read <= 0 ) {
190- success = false;
191- break ;
192- }
193- totalBytesRead += (size_t )read ;
194- }
195- if (success ) {
196- buffer [totalBytesRead ] = '\0' ;
194+ * errorMsgOut = CELIX_HTTP_ADMIN_INSUFFICIENT_MEM_MSG ;
195+ return 500 ;
196+ }
197+
198+ while (totalBytesRead < length ) {
199+ int read = mg_read (connection , buffer + totalBytesRead , length - totalBytesRead );
200+ if (read == 0 ) {
201+ break ; //EOF
202+ } else if (read < 0 ) {
203+ * errorMsgOut = CELIX_HTTP_ADMIN_READ_ERROR_MSG ;
204+ return 400 ;
197205 }
206+ totalBytesRead += (size_t )read ;
207+ }
208+ if (totalBytesRead < length ) {
209+ * errorMsgOut = CELIX_HTTP_ADMIN_INCOMPLETE_BODY_MSG ;
210+ return 400 ;
198211 }
212+ buffer [totalBytesRead ] = '\0' ;
199213 }
200- * bufferOut = buffer ;
214+ * bufferOut = celix_steal_ptr ( buffer ) ;
201215 * bytesReadOut = totalBytesRead ;
202- return success ;
216+ return 0 ;
203217}
204218
205219int http_request_handle (struct mg_connection * connection ) {
@@ -239,12 +253,13 @@ int http_request_handle(struct mg_connection *connection) {
239253 if (httpSvc -> doPost != NULL ) {
240254 char * rcv_buf = NULL ;
241255 size_t bytesRead = 0 ;
242- bool success = httpAdmin_readRequestBody (connection , ri -> content_length , & rcv_buf , & bytesRead );
243- if (success ) {
256+ const char * errMsg ;
257+ int errCode = httpAdmin_readRequestBody (connection , ri -> content_length , & rcv_buf , & bytesRead , & errMsg );
258+ if (errCode == 0 ) {
244259 ret_status = httpSvc -> doPost (httpSvc -> handle , connection , rcv_buf , bytesRead );
245260 } else {
246- mg_send_http_error (connection , 400 , "%s" , "Bad request" );
247- ret_status = 400 ; //Bad Request, failed to read data
261+ mg_send_http_error (connection , errCode , "%s" , errMsg );
262+ ret_status = errCode ; //set status to the error code, so the request is not passed to civetweb
248263 }
249264 free (rcv_buf );
250265 } else {
@@ -255,12 +270,13 @@ int http_request_handle(struct mg_connection *connection) {
255270 if (httpSvc -> doPut != NULL ) {
256271 char * rcv_buf = NULL ;
257272 size_t bytesRead = 0 ;
258- bool success = httpAdmin_readRequestBody (connection , ri -> content_length , & rcv_buf , & bytesRead );
259- if (success ) {
273+ const char * errMsg ;
274+ int errCode = httpAdmin_readRequestBody (connection , ri -> content_length , & rcv_buf , & bytesRead , & errMsg );
275+ if (errCode == 0 ) {
260276 ret_status = httpSvc -> doPut (httpSvc -> handle , connection , req_uri , rcv_buf , bytesRead );
261277 } else {
262- mg_send_http_error (connection , 400 , "%s" , "Bad request" );
263- ret_status = 400 ; //Bad Request, failed to read data
278+ mg_send_http_error (connection , errCode , "%s" , errMsg );
279+ ret_status = errCode ; //set status to the error code, so the request is not passed to civetweb
264280 }
265281 free (rcv_buf );
266282 } else {
@@ -276,12 +292,13 @@ int http_request_handle(struct mg_connection *connection) {
276292 if (httpSvc -> doTrace != NULL ) {
277293 char * rcv_buf = NULL ;
278294 size_t bytesRead = 0 ;
279- bool success = httpAdmin_readRequestBody (connection , ri -> content_length , & rcv_buf , & bytesRead );
280- if (success ) {
295+ const char * errMsg = NULL ;
296+ int errCode = httpAdmin_readRequestBody (connection , ri -> content_length , & rcv_buf , & bytesRead , & errMsg );
297+ if (errCode == 0 ) {
281298 ret_status = httpSvc -> doTrace (httpSvc -> handle , connection , rcv_buf , bytesRead );
282299 } else {
283- mg_send_http_error (connection , 400 , "%s" , "Bad request" );
284- ret_status = 400 ; //Bad Request, failed to read data
300+ mg_send_http_error (connection , errCode , "%s" , errMsg );
301+ ret_status = errCode ; //set status to the error code, so the request is not passed to civetweb
285302 }
286303 free (rcv_buf );
287304 } else {
@@ -297,12 +314,13 @@ int http_request_handle(struct mg_connection *connection) {
297314 if (httpSvc -> doPatch != NULL ) {
298315 char * rcv_buf = NULL ;
299316 size_t bytesRead = 0 ;
300- bool success = httpAdmin_readRequestBody (connection , ri -> content_length , & rcv_buf , & bytesRead );
301- if (success ) {
317+ const char * errMsg ;
318+ int errCode = httpAdmin_readRequestBody (connection , ri -> content_length , & rcv_buf , & bytesRead , & errMsg );
319+ if (errCode == 0 ) {
302320 ret_status = httpSvc -> doPatch (httpSvc -> handle , connection , req_uri , rcv_buf , bytesRead );
303321 } else {
304- mg_send_http_error (connection , 400 , "%s" , "Bad request" );
305- ret_status = 400 ; //Bad Request, failed to read data
322+ mg_send_http_error (connection , errCode , "%s" , errMsg );
323+ ret_status = errCode ; //set status to the error code, so the request is not passed to civetweb
306324 }
307325 free (rcv_buf );
308326 } else {
0 commit comments