diff --git a/README.lwsws.md b/README.lwsws.md index 96174d19..cebc6b29 100644 --- a/README.lwsws.md +++ b/README.lwsws.md @@ -275,6 +275,14 @@ options are given, the content is marked uncacheable. } +4) You can also define a list of additional mimetypes per-mount + + "extra-mimetypes": { + ".zip": "application/zip", + ".doc": "text/evil" + } + + Plugins ------- diff --git a/lib/libwebsockets.h b/lib/libwebsockets.h index 4256c5b7..0affce07 100644 --- a/lib/libwebsockets.h +++ b/lib/libwebsockets.h @@ -1391,6 +1391,7 @@ struct lws_http_mount { const char *def; /* default target, eg, "index.html" */ const struct lws_protocol_vhost_options *cgienv; + const struct lws_protocol_vhost_options *extra_mimetypes; int cgi_timeout; int cache_max_age; diff --git a/lib/server.c b/lib/server.c index 82ebc2de..fd373b1e 100644 --- a/lib/server.c +++ b/lib/server.c @@ -192,9 +192,14 @@ lws_select_vhost(struct lws_context *context, int port, const char *servername) return NULL; } -static const char * get_mimetype(const char *file) +static const char * +get_mimetype(const char *file, const struct lws_http_mount *m) { int n = strlen(file); + const struct lws_protocol_vhost_options *pvo = NULL; + + if (m) + pvo = m->extra_mimetypes; if (n < 5) return NULL; @@ -238,10 +243,19 @@ static const char * get_mimetype(const char *file) if (!strcmp(&file[n - 4], ".xml")) return "application/xml"; + while (pvo) { + if (!strcmp(&file[n - strlen(pvo->name)], pvo->name)) + return pvo->value; + + pvo = pvo->next; + } + return NULL; } -int lws_http_serve(struct lws *wsi, char *uri, const char *origin) +static int +lws_http_serve(struct lws *wsi, char *uri, const char *origin, + const struct lws_http_mount *m) { const char *mimetype; #ifndef _WIN32_WCE @@ -329,7 +343,7 @@ int lws_http_serve(struct lws *wsi, char *uri, const char *origin) return -1; #endif - mimetype = get_mimetype(path); + mimetype = get_mimetype(path, m); if (!mimetype) { lwsl_err("unknown mimetype for %s", path); goto bail; @@ -696,7 +710,7 @@ lws_http_action(struct lws *wsi) wsi->cache_revalidate = hit->cache_revalidate; wsi->cache_intermediaries = hit->cache_intermediaries; - n = lws_http_serve(wsi, s, hit->origin); + n = lws_http_serve(wsi, s, hit->origin, hit); if (n) { /* * lws_return_http_status(wsi, HTTP_STATUS_NOT_FOUND, NULL); diff --git a/lwsws/conf.c b/lwsws/conf.c index ce77d940..fa00095d 100644 --- a/lwsws/conf.c +++ b/lwsws/conf.c @@ -60,6 +60,7 @@ static const char * const paths_vhosts[] = { "vhosts[].mounts[].cache-reuse", "vhosts[].mounts[].cache-revalidate", "vhosts[].mounts[].cache-intermediaries", + "vhosts[].mounts[].extra-mimetypes.*", "vhosts[].ws-protocols[].*.*", "vhosts[].ws-protocols[].*", "vhosts[].ws-protocols[]", @@ -89,6 +90,7 @@ enum lejp_vhost_paths { LEJPVP_MOUNT_CACHE_REUSE, LEJPVP_MOUNT_CACHE_REVALIDATE, LEJPVP_MOUNT_CACHE_INTERMEDIARIES, + LEJPVP_MOUNT_EXTRA_MIMETYPES, LEJPVP_PROTOCOL_NAME_OPT, LEJPVP_PROTOCOL_NAME, LEJPVP_PROTOCOL, @@ -108,9 +110,12 @@ struct jpargs { struct lws_http_mount *head, *last; struct lws_protocol_vhost_options *pvo; + struct lws_protocol_vhost_options *pvo_em; struct lws_http_mount m; const char **plugin_dirs; int count_plugin_dirs; + + unsigned int fresh_mount:1; }; static void * @@ -229,8 +234,10 @@ lejp_vhosts_cb(struct lejp_ctx *ctx, char reason) } if (reason == LEJPCB_OBJECT_START && - ctx->path_match == LEJPVP_MOUNTS + 1) + ctx->path_match == LEJPVP_MOUNTS + 1) { + a->fresh_mount = 1; memset(&a->m, 0, sizeof(a->m)); + } /* this catches, eg, vhosts[].ws-protocols[].xxx-protocol */ if (reason == LEJPCB_OBJECT_START && @@ -243,7 +250,7 @@ lejp_vhosts_cb(struct lejp_ctx *ctx, char reason) a->pvo->next = a->info->pvo; a->info->pvo = a->pvo; a->pvo->name = a->p; - lwsl_err("adding %s\n", a->p); + lwsl_notice(" adding protocol %s\n", a->p); a->p += n; a->pvo->value = a->p; a->pvo->options = NULL; @@ -283,10 +290,14 @@ lejp_vhosts_cb(struct lejp_ctx *ctx, char reason) ">https://", }; + if (!a->fresh_mount) + return 0; + if (!a->m.mountpoint || !a->m.origin) { lwsl_err("mountpoint and origin required\n"); return 1; } + lwsl_debug("adding mount %s\n", a->m.mountpoint); m = lwsws_align(a); memcpy(m, &a->m, sizeof(*m)); if (a->last) @@ -310,6 +321,7 @@ lejp_vhosts_cb(struct lejp_ctx *ctx, char reason) a->head = m; a->last = m; + a->fresh_mount = 0; } /* we only match on the prepared path strings */ @@ -419,8 +431,21 @@ lejp_vhosts_cb(struct lejp_ctx *ctx, char reason) a->p += n; pvo->value = a->p; pvo->options = NULL; - a->p += snprintf(a->p, a->end - a->p, "%s", ctx->buf); - *(a->p)++ = '\0'; + break; + + case LEJPVP_MOUNT_EXTRA_MIMETYPES: + a->pvo_em = lwsws_align(a); + a->p += sizeof(*a->pvo_em); + + n = lejp_get_wildcard(ctx, 0, a->p, a->end - a->p); + /* ie, enable this protocol, no options yet */ + a->pvo_em->next = a->m.extra_mimetypes; + a->m.extra_mimetypes = a->pvo_em; + a->pvo_em->name = a->p; + lwsl_notice(" adding extra-mimetypes %s -> %s\n", a->p, ctx->buf); + a->p += n; + a->pvo_em->value = a->p; + a->pvo_em->options = NULL; break; default: diff --git a/test-server/test-server-v2.0.c b/test-server/test-server-v2.0.c index 56afca58..7df51819 100644 --- a/test-server/test-server-v2.0.c +++ b/test-server/test-server-v2.0.c @@ -83,6 +83,7 @@ static const struct lws_http_mount mount = { LOCAL_RESOURCE_PATH, /* where to go on the filesystem for that */ "test.html", /* default filename if none given */ NULL, + NULL, 0, 0, 0,