nat: Include platform specific headers on FreeBSD
[vpp.git] / src / plugins / http_static / static_server.c
index a76cb87..040cdca 100644 (file)
@@ -89,7 +89,7 @@ start_send_data (hss_session_t *hs, http_status_code_t status)
 
   msg.type = HTTP_MSG_REPLY;
   msg.code = status;
-  msg.content_type = HTTP_CONTENT_TEXT_HTML;
+  msg.content_type = hs->content_type;
   msg.data.len = hs->data_len;
 
   if (hs->data_len > hss_main.use_ptr_thresh)
@@ -145,6 +145,71 @@ hss_session_send_data (hss_url_handler_args_t *args)
   start_send_data (hs, args->sc);
 }
 
+/*
+ * path_has_known_suffix()
+ * Returns 1 if the request ends with a known suffix, like .htm or .ico
+ * Used to avoid looking for "/favicon.ico/index.html" or similar.
+ */
+
+static int
+path_has_known_suffix (u8 *request)
+{
+  u8 *ext;
+  uword *p;
+
+  if (vec_len (request) == 0)
+    {
+      return 0;
+    }
+
+  ext = request + vec_len (request) - 1;
+
+  while (ext > request && ext[0] != '.')
+    ext--;
+
+  if (ext == request)
+    return 0;
+
+  p = hash_get_mem (hss_main.mime_type_indices_by_file_extensions, ext);
+  if (p)
+    return 1;
+
+  return 0;
+}
+
+/*
+ * content_type_from_request
+ * Returns the index of the request's suffix in the
+ * http-layer http_content_type_str[] array.
+ */
+
+static http_content_type_t
+content_type_from_request (u8 *request)
+{
+  u8 *ext;
+  uword *p;
+  /* default to text/html */
+  http_content_type_t rv = HTTP_CONTENT_TEXT_HTML;
+
+  ASSERT (vec_len (request) > 0);
+
+  ext = request + vec_len (request) - 1;
+
+  while (ext > request && ext[0] != '.')
+    ext--;
+
+  if (ext == request)
+    return rv;
+
+  p = hash_get_mem (hss_main.mime_type_indices_by_file_extensions, ext);
+
+  if (p == 0)
+    return rv;
+
+  rv = p[0];
+  return rv;
+}
+
 static int
 try_url_handler (hss_main_t *hsm, hss_session_t *hs, http_req_method_t rt,
                 u8 *request)
@@ -152,11 +217,20 @@ try_url_handler (hss_main_t *hsm, hss_session_t *hs, http_req_method_t rt,
   http_status_code_t sc = HTTP_STATUS_OK;
   hss_url_handler_args_t args = {};
   uword *p, *url_table;
+  http_content_type_t type;
   int rv;
 
   if (!hsm->enable_url_handlers || !request)
     return -1;
 
+  /* zero-length? try "index.html" */
+  if (vec_len (request) == 0)
+    {
+      request = format (request, "index.html");
+    }
+
+  type = content_type_from_request (request);
+
   /* Look for built-in GET / POST handlers */
   url_table =
     (rt == HTTP_REQ_GET) ? hsm->get_url_handlers : hsm->post_url_handlers;
@@ -193,6 +267,7 @@ try_url_handler (hss_main_t *hsm, hss_session_t *hs, http_req_method_t rt,
   hs->data = args.data;
   hs->data_len = args.data_len;
   hs->free_data = args.free_vec_data;
+  hs->content_type = type;
 
   start_send_data (hs, sc);
 
@@ -284,11 +359,14 @@ try_file_handler (hss_main_t *hsm, hss_session_t *hs, http_req_method_t rt,
   http_status_code_t sc = HTTP_STATUS_OK;
   u8 *path;
   u32 ce_index;
+  http_content_type_t type;
 
   /* Feature not enabled */
   if (!hsm->www_root)
     return -1;
 
+  type = content_type_from_request (request);
+
   /*
    * Construct the file to open
    * Browsers are capable of sporadically including a leading '/'
@@ -306,7 +384,6 @@ try_file_handler (hss_main_t *hsm, hss_session_t *hs, http_req_method_t rt,
   if (hs->data && hs->free_data)
     vec_free (hs->data);
 
-  hs->path = path;
   hs->data_offset = 0;
 
   ce_index =
@@ -315,6 +392,17 @@ try_file_handler (hss_main_t *hsm, hss_session_t *hs, http_req_method_t rt,
     {
       if (!file_path_is_valid (path))
        {
+         /*
+          * Generate error 404 right now if we can't find a path with
+          * a known file extension. It's silly to look for
+          * "favicon.ico/index.html" if you can't find
+          * "favicon.ico"; realistic example which used to happen.
+          */
+         if (path_has_known_suffix (path))
+           {
+             sc = HTTP_STATUS_NOT_FOUND;
+             goto done;
+           }
          sc = try_index_file (hsm, hs, path);
          goto done;
        }
@@ -327,10 +415,12 @@ try_file_handler (hss_main_t *hsm, hss_session_t *hs, http_req_method_t rt,
        }
     }
 
+  hs->path = path;
   hs->cache_pool_index = ce_index;
 
 done:
 
+  hs->content_type = type;
   start_send_data (hs, sc);
   if (!hs->data)
     hss_session_disconnect_transport (hs);
@@ -908,6 +998,16 @@ hss_main_init (vlib_main_t *vm)
   hsm->app_index = ~0;
   hsm->vlib_main = vm;
 
+  /* Set up file extension to mime type index map */
+  hsm->mime_type_indices_by_file_extensions =
+    hash_create_string (0, sizeof (uword));
+
+#define _(def, ext, str)                                                      \
+  hash_set_mem (hsm->mime_type_indices_by_file_extensions, ext,               \
+               HTTP_CONTENT_##def);
+  foreach_http_content_type;
+#undef _
+
   return 0;
 }