diff --git a/examples/restful_server/restful_server.c b/examples/restful_server/restful_server.c index 85e52e933fc2c067cef7238f6202b6c745e47678..27ada98bb3a1401897c03c3b4f886150744bae94 100644 --- a/examples/restful_server/restful_server.c +++ b/examples/restful_server/restful_server.c @@ -74,7 +74,7 @@ int main(int argc, char *argv[]) { #endif } else if (strcmp(argv[i], "-P") == 0 && i + 1 < argc) { s_http_server_opts.global_auth_file = argv[++i]; - } else if (strcmp(argv[i], "-p") == 0 && i + 1 < argc) { + } else if (strcmp(argv[i], "-A") == 0 && i + 1 < argc) { s_http_server_opts.per_directory_auth_file = argv[++i]; } else if (strcmp(argv[i], "-r") == 0 && i + 1 < argc) { s_http_server_opts.url_rewrites = argv[++i]; diff --git a/mongoose.c b/mongoose.c index 73a1f1791eb5191bfc16f6f420dc0fa6d6a12ccc..c24e740ec59337357333799f4a25785e19b1b2f7 100644 --- a/mongoose.c +++ b/mongoose.c @@ -4488,6 +4488,12 @@ void mg_send_response_line(struct mg_connection *nc, int status_code, case 206: status_message = "Partial Content"; break; + case 301: + status_message = "Moved"; + break; + case 302: + status_message = "Found"; + break; case 416: status_message = "Requested range not satisfiable"; break; @@ -5502,6 +5508,34 @@ MG_INTERNAL int find_index_file(char *path, size_t path_len, const char *list, return found; } +static int send_port_based_redirect(struct mg_connection *c, + struct http_message *hm, + const struct mg_serve_http_opts *opts) { + const char *rewrites = opts->url_rewrites; + struct mg_str a, b; + char local_port[20] = {'%'}; + +#ifndef MG_ESP8266 + mg_sock_to_str(c->sock, local_port + 1, sizeof(local_port) - 1, + MG_SOCK_STRINGIFY_PORT); +#else + /* TODO(lsm): remove when mg_sock_to_str() is implemented in LWIP codepath */ + snprintf(local_port, sizeof(local_port), "%s", "%0"); +#endif + + while ((rewrites = mg_next_comma_list_entry(rewrites, &a, &b)) != NULL) { + if (mg_vcmp(&a, local_port) == 0) { + mg_send_response_line(c, 301, NULL); + mg_printf(c, "Content-Length: 0\r\nLocation: %.*s%.*s\r\n\r\n", + (int) b.len, b.p, (int) (hm->proto.p - hm->uri.p - 1), + hm->uri.p); + return 1; + } + } + + return 0; +} + static void uri_to_path(struct http_message *hm, char *buf, size_t buf_len, const struct mg_serve_http_opts *opts) { char uri[MG_MAX_PATH]; @@ -6132,6 +6166,10 @@ void mg_serve_http(struct mg_connection *nc, struct http_message *hm, char path[MG_MAX_PATH]; struct mg_str *hdr; + if (send_port_based_redirect(nc, hm, &opts)) { + return; + } + if (opts.document_root == NULL) { opts.document_root = "."; } diff --git a/mongoose.h b/mongoose.h index f8dd00fc9607a55c8c3d6f1433079e6f6c3d02a2..a1674203d1ae83cff3f9b67163707a9b8f0a3379 100644 --- a/mongoose.h +++ b/mongoose.h @@ -1772,6 +1772,13 @@ struct mg_serve_http_opts { * If uri_pattern starts with `@` symbol, then Mongoose compares it with the * HOST header of the request. If they are equal, Mongoose sets document root * to `file_or_directory_path`, implementing virtual hosts support. + * Example: `@foo.com=/document/root/for/foo.com` + * + * If `uri_pattern` starts with `%` symbol, then Mongoose compares it with + * the listening port. If they match, then Mongoose issues a 301 redirect. + * For example, to redirect all HTTP requests to the + * HTTPS port, do `%80=https://my.site.com`. Note that the request URI is + * automatically appended to the redirect location. */ const char *url_rewrites;