mirror of
https://github.com/cesanta/mongoose.git
synced 2026-10-22 11:36:21 +00:00
Define mg_file_upload_handler() only if needed
Namely, define it if only `MG_ENABLE_HTTP_STREAMING_MULTIPART` and `MG_ENABLE_FILESYSTEM` are on PUBLISHED_FROM=3094738a4b76ceb09a3c2374e8d9d914b71c3441
This commit is contained in:
1 parent
304dbca63d
commit
731512a947
2 files changed
+149
-147
No files matched your search
+118
-116
@@ -6034,122 +6034,6 @@ struct file_upload_state {
|
||||
FILE *fp;
|
||||
};
|
||||
|
||||
void mg_file_upload_handler(struct mg_connection *nc, int ev, void *ev_data,
|
||||
mg_fu_fname_fn local_name_fn) {
|
||||
switch (ev) {
|
||||
case MG_EV_HTTP_PART_BEGIN: {
|
||||
struct mg_http_multipart_part *mp =
|
||||
(struct mg_http_multipart_part *) ev_data;
|
||||
struct file_upload_state *fus =
|
||||
(struct file_upload_state *) calloc(1, sizeof(*fus));
|
||||
mp->user_data = NULL;
|
||||
|
||||
struct mg_str lfn = local_name_fn(nc, mg_mk_str(mp->file_name));
|
||||
if (lfn.p == NULL || lfn.len == 0) {
|
||||
LOG(LL_ERROR, ("%p Not allowed to upload %s", nc, mp->file_name));
|
||||
mg_printf(nc,
|
||||
"HTTP/1.1 403 Not Allowed\r\n"
|
||||
"Content-Type: text/plain\r\n"
|
||||
"Connection: close\r\n\r\n"
|
||||
"Not allowed to upload %s\r\n",
|
||||
mp->file_name);
|
||||
nc->flags |= MG_F_SEND_AND_CLOSE;
|
||||
return;
|
||||
}
|
||||
fus->lfn = (char *) malloc(lfn.len + 1);
|
||||
memcpy(fus->lfn, lfn.p, lfn.len);
|
||||
fus->lfn[lfn.len] = '\0';
|
||||
if (lfn.p != mp->file_name) free((char *) lfn.p);
|
||||
LOG(LL_DEBUG,
|
||||
("%p Receiving file %s -> %s", nc, mp->file_name, fus->lfn));
|
||||
fus->fp = mg_fopen(fus->lfn, "w");
|
||||
if (fus->fp == NULL) {
|
||||
mg_printf(nc,
|
||||
"HTTP/1.1 500 Internal Server Error\r\n"
|
||||
"Content-Type: text/plain\r\n"
|
||||
"Connection: close\r\n\r\n");
|
||||
LOG(LL_ERROR, ("Failed to open %s: %d\n", fus->lfn, mg_get_errno()));
|
||||
mg_printf(nc, "Failed to open %s: %d\n", fus->lfn, mg_get_errno());
|
||||
/* Do not close the connection just yet, discard remainder of the data.
|
||||
* This is because at the time of writing some browsers (Chrome) fail to
|
||||
* render response before all the data is sent. */
|
||||
}
|
||||
mp->user_data = (void *) fus;
|
||||
break;
|
||||
}
|
||||
case MG_EV_HTTP_PART_DATA: {
|
||||
struct mg_http_multipart_part *mp =
|
||||
(struct mg_http_multipart_part *) ev_data;
|
||||
struct file_upload_state *fus =
|
||||
(struct file_upload_state *) mp->user_data;
|
||||
if (fus == NULL || fus->fp == NULL) break;
|
||||
if (fwrite(mp->data.p, 1, mp->data.len, fus->fp) != mp->data.len) {
|
||||
LOG(LL_ERROR, ("Failed to write to %s: %d, wrote %d", fus->lfn,
|
||||
mg_get_errno(), (int) fus->num_recd));
|
||||
if (mg_get_errno() == ENOSPC
|
||||
#ifdef SPIFFS_ERR_FULL
|
||||
|| mg_get_errno() == SPIFFS_ERR_FULL
|
||||
#endif
|
||||
) {
|
||||
mg_printf(nc,
|
||||
"HTTP/1.1 413 Payload Too Large\r\n"
|
||||
"Content-Type: text/plain\r\n"
|
||||
"Connection: close\r\n\r\n");
|
||||
mg_printf(nc, "Failed to write to %s: no space left; wrote %d\r\n",
|
||||
fus->lfn, (int) fus->num_recd);
|
||||
} else {
|
||||
mg_printf(nc,
|
||||
"HTTP/1.1 500 Internal Server Error\r\n"
|
||||
"Content-Type: text/plain\r\n"
|
||||
"Connection: close\r\n\r\n");
|
||||
mg_printf(nc, "Failed to write to %s: %d, wrote %d", mp->file_name,
|
||||
mg_get_errno(), (int) fus->num_recd);
|
||||
}
|
||||
fclose(fus->fp);
|
||||
remove(fus->lfn);
|
||||
fus->fp = NULL;
|
||||
/* Do not close the connection just yet, discard remainder of the data.
|
||||
* This is because at the time of writing some browsers (Chrome) fail to
|
||||
* render response before all the data is sent. */
|
||||
return;
|
||||
}
|
||||
fus->num_recd += mp->data.len;
|
||||
LOG(LL_DEBUG, ("%p rec'd %d bytes, %d total", nc, (int) mp->data.len,
|
||||
(int) fus->num_recd));
|
||||
break;
|
||||
}
|
||||
case MG_EV_HTTP_PART_END: {
|
||||
struct mg_http_multipart_part *mp =
|
||||
(struct mg_http_multipart_part *) ev_data;
|
||||
struct file_upload_state *fus =
|
||||
(struct file_upload_state *) mp->user_data;
|
||||
if (fus == NULL) break;
|
||||
if (mp->status >= 0 && fus->fp != NULL) {
|
||||
LOG(LL_DEBUG, ("%p Uploaded %s (%s), %d bytes", nc, mp->file_name,
|
||||
fus->lfn, (int) fus->num_recd));
|
||||
mg_printf(nc,
|
||||
"HTTP/1.1 200 OK\r\n"
|
||||
"Content-Type: text/plain\r\n"
|
||||
"Connection: close\r\n\r\n"
|
||||
"Ok, %s - %d bytes.\r\n",
|
||||
mp->file_name, (int) fus->num_recd);
|
||||
} else {
|
||||
LOG(LL_ERROR, ("Failed to store %s (%s)", mp->file_name, fus->lfn));
|
||||
/*
|
||||
* mp->status < 0 means connection was terminated, so no reason to send
|
||||
* HTTP reply
|
||||
*/
|
||||
}
|
||||
if (fus->fp != NULL) fclose(fus->fp);
|
||||
free(fus->lfn);
|
||||
free(fus);
|
||||
mp->user_data = NULL;
|
||||
nc->flags |= MG_F_SEND_AND_CLOSE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* MG_ENABLE_HTTP_STREAMING_MULTIPART */
|
||||
|
||||
void mg_set_protocol_http_websocket(struct mg_connection *nc) {
|
||||
@@ -7576,6 +7460,124 @@ void mg_serve_http(struct mg_connection *nc, struct http_message *hm,
|
||||
}
|
||||
}
|
||||
|
||||
#if MG_ENABLE_HTTP_STREAMING_MULTIPART
|
||||
void mg_file_upload_handler(struct mg_connection *nc, int ev, void *ev_data,
|
||||
mg_fu_fname_fn local_name_fn) {
|
||||
switch (ev) {
|
||||
case MG_EV_HTTP_PART_BEGIN: {
|
||||
struct mg_http_multipart_part *mp =
|
||||
(struct mg_http_multipart_part *) ev_data;
|
||||
struct file_upload_state *fus =
|
||||
(struct file_upload_state *) calloc(1, sizeof(*fus));
|
||||
mp->user_data = NULL;
|
||||
|
||||
struct mg_str lfn = local_name_fn(nc, mg_mk_str(mp->file_name));
|
||||
if (lfn.p == NULL || lfn.len == 0) {
|
||||
LOG(LL_ERROR, ("%p Not allowed to upload %s", nc, mp->file_name));
|
||||
mg_printf(nc,
|
||||
"HTTP/1.1 403 Not Allowed\r\n"
|
||||
"Content-Type: text/plain\r\n"
|
||||
"Connection: close\r\n\r\n"
|
||||
"Not allowed to upload %s\r\n",
|
||||
mp->file_name);
|
||||
nc->flags |= MG_F_SEND_AND_CLOSE;
|
||||
return;
|
||||
}
|
||||
fus->lfn = (char *) malloc(lfn.len + 1);
|
||||
memcpy(fus->lfn, lfn.p, lfn.len);
|
||||
fus->lfn[lfn.len] = '\0';
|
||||
if (lfn.p != mp->file_name) free((char *) lfn.p);
|
||||
LOG(LL_DEBUG,
|
||||
("%p Receiving file %s -> %s", nc, mp->file_name, fus->lfn));
|
||||
fus->fp = mg_fopen(fus->lfn, "w");
|
||||
if (fus->fp == NULL) {
|
||||
mg_printf(nc,
|
||||
"HTTP/1.1 500 Internal Server Error\r\n"
|
||||
"Content-Type: text/plain\r\n"
|
||||
"Connection: close\r\n\r\n");
|
||||
LOG(LL_ERROR, ("Failed to open %s: %d\n", fus->lfn, mg_get_errno()));
|
||||
mg_printf(nc, "Failed to open %s: %d\n", fus->lfn, mg_get_errno());
|
||||
/* Do not close the connection just yet, discard remainder of the data.
|
||||
* This is because at the time of writing some browsers (Chrome) fail to
|
||||
* render response before all the data is sent. */
|
||||
}
|
||||
mp->user_data = (void *) fus;
|
||||
break;
|
||||
}
|
||||
case MG_EV_HTTP_PART_DATA: {
|
||||
struct mg_http_multipart_part *mp =
|
||||
(struct mg_http_multipart_part *) ev_data;
|
||||
struct file_upload_state *fus =
|
||||
(struct file_upload_state *) mp->user_data;
|
||||
if (fus == NULL || fus->fp == NULL) break;
|
||||
if (fwrite(mp->data.p, 1, mp->data.len, fus->fp) != mp->data.len) {
|
||||
LOG(LL_ERROR, ("Failed to write to %s: %d, wrote %d", fus->lfn,
|
||||
mg_get_errno(), (int) fus->num_recd));
|
||||
if (mg_get_errno() == ENOSPC
|
||||
#ifdef SPIFFS_ERR_FULL
|
||||
|| mg_get_errno() == SPIFFS_ERR_FULL
|
||||
#endif
|
||||
) {
|
||||
mg_printf(nc,
|
||||
"HTTP/1.1 413 Payload Too Large\r\n"
|
||||
"Content-Type: text/plain\r\n"
|
||||
"Connection: close\r\n\r\n");
|
||||
mg_printf(nc, "Failed to write to %s: no space left; wrote %d\r\n",
|
||||
fus->lfn, (int) fus->num_recd);
|
||||
} else {
|
||||
mg_printf(nc,
|
||||
"HTTP/1.1 500 Internal Server Error\r\n"
|
||||
"Content-Type: text/plain\r\n"
|
||||
"Connection: close\r\n\r\n");
|
||||
mg_printf(nc, "Failed to write to %s: %d, wrote %d", mp->file_name,
|
||||
mg_get_errno(), (int) fus->num_recd);
|
||||
}
|
||||
fclose(fus->fp);
|
||||
remove(fus->lfn);
|
||||
fus->fp = NULL;
|
||||
/* Do not close the connection just yet, discard remainder of the data.
|
||||
* This is because at the time of writing some browsers (Chrome) fail to
|
||||
* render response before all the data is sent. */
|
||||
return;
|
||||
}
|
||||
fus->num_recd += mp->data.len;
|
||||
LOG(LL_DEBUG, ("%p rec'd %d bytes, %d total", nc, (int) mp->data.len,
|
||||
(int) fus->num_recd));
|
||||
break;
|
||||
}
|
||||
case MG_EV_HTTP_PART_END: {
|
||||
struct mg_http_multipart_part *mp =
|
||||
(struct mg_http_multipart_part *) ev_data;
|
||||
struct file_upload_state *fus =
|
||||
(struct file_upload_state *) mp->user_data;
|
||||
if (fus == NULL) break;
|
||||
if (mp->status >= 0 && fus->fp != NULL) {
|
||||
LOG(LL_DEBUG, ("%p Uploaded %s (%s), %d bytes", nc, mp->file_name,
|
||||
fus->lfn, (int) fus->num_recd));
|
||||
mg_printf(nc,
|
||||
"HTTP/1.1 200 OK\r\n"
|
||||
"Content-Type: text/plain\r\n"
|
||||
"Connection: close\r\n\r\n"
|
||||
"Ok, %s - %d bytes.\r\n",
|
||||
mp->file_name, (int) fus->num_recd);
|
||||
} else {
|
||||
LOG(LL_ERROR, ("Failed to store %s (%s)", mp->file_name, fus->lfn));
|
||||
/*
|
||||
* mp->status < 0 means connection was terminated, so no reason to send
|
||||
* HTTP reply
|
||||
*/
|
||||
}
|
||||
if (fus->fp != NULL) fclose(fus->fp);
|
||||
free(fus->lfn);
|
||||
free(fus);
|
||||
mp->user_data = NULL;
|
||||
nc->flags |= MG_F_SEND_AND_CLOSE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* MG_ENABLE_HTTP_STREAMING_MULTIPART */
|
||||
#endif /* MG_ENABLE_FILESYSTEM */
|
||||
|
||||
/* returns 0 on success, -1 on error */
|
||||
|
||||
+31
-31
@@ -4558,37 +4558,6 @@ void mg_serve_http(struct mg_connection *nc, struct http_message *hm,
|
||||
void mg_http_serve_file(struct mg_connection *nc, struct http_message *hm,
|
||||
const char *path, const struct mg_str mime_type,
|
||||
const struct mg_str extra_headers);
|
||||
#endif /* MG_ENABLE_FILESYSTEM */
|
||||
|
||||
/*
|
||||
* Registers a callback for a specified http endpoint
|
||||
* Note: if callback is registered it is called instead of the
|
||||
* callback provided in mg_bind
|
||||
*
|
||||
* Example code snippet:
|
||||
*
|
||||
* ```c
|
||||
* static void handle_hello1(struct mg_connection *nc, int ev, void *ev_data) {
|
||||
* (void) ev; (void) ev_data;
|
||||
* mg_printf(nc, "HTTP/1.0 200 OK\r\n\r\n[I am Hello1]");
|
||||
* nc->flags |= MG_F_SEND_AND_CLOSE;
|
||||
* }
|
||||
*
|
||||
* static void handle_hello1(struct mg_connection *nc, int ev, void *ev_data) {
|
||||
* (void) ev; (void) ev_data;
|
||||
* mg_printf(nc, "HTTP/1.0 200 OK\r\n\r\n[I am Hello2]");
|
||||
* nc->flags |= MG_F_SEND_AND_CLOSE;
|
||||
* }
|
||||
*
|
||||
* void init() {
|
||||
* nc = mg_bind(&mgr, local_addr, cb1);
|
||||
* mg_register_http_endpoint(nc, "/hello1", handle_hello1);
|
||||
* mg_register_http_endpoint(nc, "/hello1/hello2", handle_hello2);
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
void mg_register_http_endpoint(struct mg_connection *nc, const char *uri_path,
|
||||
mg_event_handler_t handler);
|
||||
|
||||
#if MG_ENABLE_HTTP_STREAMING_MULTIPART
|
||||
|
||||
@@ -4631,6 +4600,37 @@ typedef struct mg_str (*mg_fu_fname_fn)(struct mg_connection *nc,
|
||||
void mg_file_upload_handler(struct mg_connection *nc, int ev, void *ev_data,
|
||||
mg_fu_fname_fn local_name_fn);
|
||||
#endif /* MG_ENABLE_HTTP_STREAMING_MULTIPART */
|
||||
#endif /* MG_ENABLE_FILESYSTEM */
|
||||
|
||||
/*
|
||||
* Registers a callback for a specified http endpoint
|
||||
* Note: if callback is registered it is called instead of the
|
||||
* callback provided in mg_bind
|
||||
*
|
||||
* Example code snippet:
|
||||
*
|
||||
* ```c
|
||||
* static void handle_hello1(struct mg_connection *nc, int ev, void *ev_data) {
|
||||
* (void) ev; (void) ev_data;
|
||||
* mg_printf(nc, "HTTP/1.0 200 OK\r\n\r\n[I am Hello1]");
|
||||
* nc->flags |= MG_F_SEND_AND_CLOSE;
|
||||
* }
|
||||
*
|
||||
* static void handle_hello1(struct mg_connection *nc, int ev, void *ev_data) {
|
||||
* (void) ev; (void) ev_data;
|
||||
* mg_printf(nc, "HTTP/1.0 200 OK\r\n\r\n[I am Hello2]");
|
||||
* nc->flags |= MG_F_SEND_AND_CLOSE;
|
||||
* }
|
||||
*
|
||||
* void init() {
|
||||
* nc = mg_bind(&mgr, local_addr, cb1);
|
||||
* mg_register_http_endpoint(nc, "/hello1", handle_hello1);
|
||||
* mg_register_http_endpoint(nc, "/hello1/hello2", handle_hello2);
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
void mg_register_http_endpoint(struct mg_connection *nc, const char *uri_path,
|
||||
mg_event_handler_t handler);
|
||||
|
||||
/*
|
||||
* Authenticates a HTTP request against an opened password file.
|
||||
|
||||
Reference in new issue
Block a user