diff --git a/lib/context.c b/lib/context.c index 11a0694d..5054d8a5 100644 --- a/lib/context.c +++ b/lib/context.c @@ -583,6 +583,11 @@ lws_create_vhost(struct lws_context *context, else vh->name = info->vhost_name; + vh->error_document_404 = info->error_document_404; + if (info->error_document_404 && + info->error_document_404[0] == '/') + vh->error_document_404 = info->error_document_404 + 1; + if (info->options & LWS_SERVER_OPTION_ONLY_RAW) lwsl_info("%s set to only support RAW\n", vh->name); diff --git a/lib/header.c b/lib/header.c index 564b0751..5022f26a 100644 --- a/lib/header.c +++ b/lib/header.c @@ -233,6 +233,20 @@ lws_return_http_status(struct lws *wsi, unsigned int code, int n = 0, m = 0, len; char slen[20]; + if (wsi->vhost && + !wsi->handling_404 && + wsi->vhost->error_document_404 && + code == HTTP_STATUS_NOT_FOUND) + /* we should do a redirect, and do the 404 there */ + if (lws_http_redirect(wsi, HTTP_STATUS_FOUND, + (uint8_t *)wsi->vhost->error_document_404, + strlen(wsi->vhost->error_document_404), + &p, end) > 0) + return 0; + + /* if the redirect failed, just do a simple status */ + p = start; + if (!html_body) html_body = ""; diff --git a/lib/libwebsockets.h b/lib/libwebsockets.h index f3fb4598..b62660d6 100644 --- a/lib/libwebsockets.h +++ b/lib/libwebsockets.h @@ -2850,6 +2850,10 @@ struct lws_context_creation_info { * platform default values. * Just leave all at 0 if you don't care. */ + const char *error_document_404; + /**< VHOST: If non-NULL, when asked to serve a non-existent file, + * lws attempts to server this url path instead. Eg, + * "/404.html" */ /* Add new things just above here ---^ * This is part of the ABI, don't needlessly break compatibility diff --git a/lib/private-libwebsockets.h b/lib/private-libwebsockets.h index e4be958c..fcd08dc3 100644 --- a/lib/private-libwebsockets.h +++ b/lib/private-libwebsockets.h @@ -965,6 +965,7 @@ struct lws_vhost { const struct lws_protocol_vhost_options *pvo; const struct lws_protocol_vhost_options *headers; struct lws **same_vh_protocol_list; + const char *error_document_404; #ifdef LWS_OPENSSL_SUPPORT lws_tls_ctx *ssl_ctx; lws_tls_ctx *ssl_client_ctx; @@ -1951,6 +1952,7 @@ struct lws { unsigned int rxflow_will_be_applied:1; unsigned int event_pipe:1; unsigned int on_same_vh_list:1; + unsigned int handling_404; unsigned int could_have_pending:1; /* detect back-to-back writes */ diff --git a/lib/server/lejp-conf.c b/lib/server/lejp-conf.c index da21697f..488680ca 100644 --- a/lib/server/lejp-conf.c +++ b/lib/server/lejp-conf.c @@ -101,6 +101,7 @@ static const char * const paths_vhosts[] = { "vhosts[].onlyraw", "vhosts[].client-cert-required", "vhosts[].ignore-missing-cert", + "vhosts[].error-document-404", }; enum lejp_vhost_paths { @@ -150,6 +151,7 @@ enum lejp_vhost_paths { LEJPVP_FLAG_ONLYRAW, LEJPVP_FLAG_CLIENT_CERT_REQUIRED, LEJPVP_IGNORE_MISSING_CERT, + LEJPVP_ERROR_DOCUMENT_404, }; static const char * const parser_errs[] = { @@ -708,6 +710,10 @@ lejp_vhosts_cb(struct lejp_ctx *ctx, char reason) return 0; + case LEJPVP_ERROR_DOCUMENT_404: + a->info->error_document_404 = a->p; + break; + case LEJPVP_SSL_OPTION_SET: a->info->ssl_options_set |= atol(ctx->buf); return 0; diff --git a/lib/server/server.c b/lib/server/server.c index 0e3e79af..1cf60ba1 100644 --- a/lib/server/server.c +++ b/lib/server/server.c @@ -386,6 +386,11 @@ lws_http_serve(struct lws *wsi, char *uri, const char *origin, #endif int n; + wsi->handling_404 = 0; + if (wsi->vhost && wsi->vhost->error_document_404 && + !strcmp(uri, wsi->vhost->error_document_404)) + wsi->handling_404 = 1; + lws_snprintf(path, sizeof(path) - 1, "%s/%s", origin, uri); #if !defined(_WIN32_WCE) @@ -2736,6 +2741,9 @@ lws_serve_http_file(struct lws *wsi, const char *file, const char *content_type, const struct lws_plat_file_ops *fops; const char *vpath; + if (wsi->handling_404) + n = HTTP_STATUS_NOT_FOUND; + /* * We either call the platform fops .open with first arg platform fops, * or we call fops_zip .open with first arg platform fops, and fops_zip diff --git a/minimal-examples/minimal-http-server/minimal-http-server.c b/minimal-examples/minimal-http-server/minimal-http-server.c index 0e2e29e7..0784b550 100644 --- a/minimal-examples/minimal-http-server/minimal-http-server.c +++ b/minimal-examples/minimal-http-server/minimal-http-server.c @@ -54,6 +54,7 @@ int main(int argc, char **argv) memset(&info, 0, sizeof info); /* otherwise uninitialized garbage */ info.port = 7681; info.mounts = &mount; + info.error_document_404 = "/404.html"; lws_set_log_level(LLL_ERR | LLL_WARN | LLL_NOTICE | LLL_USER /* | LLL_INFO */ /* | LLL_DEBUG */, NULL);