Selaa lähdekoodia

Added MG_OPEN_FILE message

Sergey Lyubka 12 vuotta sitten
vanhempi
commit
557d1f4c49
4 muutettua tiedostoa jossa 343 lisäystä ja 243 poistoa
  1. 6 0
      main.c
  2. 281 232
      mongoose.c
  3. 15 0
      mongoose.h
  4. 41 11
      test/unit_test.c

+ 6 - 0
main.c

@@ -224,6 +224,12 @@ static void *mongoose_callback(enum mg_event ev, struct mg_connection *conn) {
     printf("%s\n", (const char *) mg_get_request_info(conn)->ev_data);
   }
 
+  if (ev == MG_OPEN_FILE &&
+      !memcmp(mg_get_request_info(conn)->ev_data, "./x", 3)) {
+    mg_get_request_info(conn)->ev_data = (void *) (int) 5;
+    return "hello";
+  }
+
   // Returning NULL marks request as not handled, signalling mongoose to
   // proceed with handling it.
   return NULL;

Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 281 - 232
mongoose.c


+ 15 - 0
mongoose.h

@@ -82,6 +82,21 @@ enum mg_event {
   //   SSL_CTX *ssl_context = request_info->ev_data;
   MG_INIT_SSL,
 
+  // Mongoose tries to open file.
+  // If callback returns non-NULL, Mongoose will not try to open it, but
+  // will use the returned value as a pointer to the file data. This allows
+  // for example to serve files from memory.
+  // ev_data contains file path, including document root path.
+  // Upon return, ev_data should return file size,  which should be an int.
+  //
+  //   const char *file_name = request_info->ev_data;
+  //   if (strcmp(file_name, "foo.txt") == 0) {
+  //     request_info->ev_data = (void *) (int) 4;
+  //     return "data";
+  //   }
+  //   return NULL;
+  MG_OPEN_FILE,
+
   // Sent on HTTP connect, before websocket handshake.
   // If user callback returns NULL, then mongoose proceeds
   // with handshake, otherwise it closes the connection.

+ 41 - 11
test/unit_test.c

@@ -7,6 +7,8 @@
 } while (0)
 #define ASSERT(expr) do { if (!(expr)) FATAL(#expr, __LINE__); } while (0)
 
+#define UNUSED_PORT "33796"
+
 static void test_parse_http_request() {
   struct mg_request_info ri;
   char req1[] = "GET / HTTP/1.1\r\n\r\n";
@@ -126,15 +128,24 @@ static void test_remove_double_dots() {
 }
 
 static const char *fetch_data = "hello world!\n";
-static void *event_handler(enum mg_event event,
-                           struct mg_connection *conn) {
+static const char *inmemory_file_data = "hi there";
+static void *event_handler(enum mg_event event, struct mg_connection *conn) {
   const struct mg_request_info *request_info = mg_get_request_info(conn);
+
   if (event == MG_NEW_REQUEST && !strcmp(request_info->uri, "/data")) {
     mg_printf(conn, "HTTP/1.1 200 OK\r\n"
               "Content-Length: %d\r\n"
               "Content-Type: text/plain\r\n\r\n"
               "%s", (int) strlen(fetch_data), fetch_data);
     return "";
+  } else if (event == MG_OPEN_FILE) {
+    const char *path = request_info->ev_data;
+    printf("%s: [%s]\n", __func__, path);
+    if (strcmp(path, "./blah") == 0) {
+      mg_get_request_info(conn)->ev_data =
+        (void *) (int) strlen(inmemory_file_data);
+      return (void *) inmemory_file_data;
+    }
   } else if (event == MG_EVENT_LOG) {
     printf("%s\n", (const char *) mg_get_request_info(conn)->ev_data);
   }
@@ -145,33 +156,33 @@ static void *event_handler(enum mg_event event,
 static void test_mg_fetch(void) {
   static const char *options[] = {
     "document_root", ".",
-    "listening_ports", "33796",
+    "listening_ports", UNUSED_PORT,
     NULL,
   };
   char buf[2000], buf2[2000];
-  int length;
+  int n, length;
   struct mg_context *ctx;
   struct mg_request_info ri;
   const char *tmp_file = "temporary_file_name_for_unit_test.txt";
-  struct mgstat st;
+  struct file file;
   FILE *fp;
 
   ASSERT((ctx = mg_start(event_handler, NULL, options)) != NULL);
 
   // Failed fetch, pass invalid URL
   ASSERT(mg_fetch(ctx, "localhost", tmp_file, buf, sizeof(buf), &ri) == NULL);
-  ASSERT(mg_fetch(ctx, "localhost:33796", tmp_file,
+  ASSERT(mg_fetch(ctx, "localhost:" UNUSED_PORT, tmp_file,
                   buf, sizeof(buf), &ri) == NULL);
   ASSERT(mg_fetch(ctx, "http://$$$.$$$", tmp_file,
                   buf, sizeof(buf), &ri) == NULL);
 
   // Failed fetch, pass invalid file name
-  ASSERT(mg_fetch(ctx, "http://localhost:33796/data",
+  ASSERT(mg_fetch(ctx, "http://localhost:" UNUSED_PORT "/data",
                   "/this/file/must/not/exist/ever",
                   buf, sizeof(buf), &ri) == NULL);
 
   // Successful fetch
-  ASSERT((fp = mg_fetch(ctx, "http://localhost:33796/data",
+  ASSERT((fp = mg_fetch(ctx, "http://localhost:" UNUSED_PORT "/data",
                         tmp_file, buf, sizeof(buf), &ri)) != NULL);
   ASSERT(ri.num_headers == 2);
   ASSERT(!strcmp(ri.request_method, "HTTP/1.1"));
@@ -184,12 +195,31 @@ static void test_mg_fetch(void) {
   fclose(fp);
 
   // Fetch big file, mongoose.c
-  ASSERT((fp = mg_fetch(ctx, "http://localhost:33796/mongoose.c",
+  ASSERT((fp = mg_fetch(ctx, "http://localhost:" UNUSED_PORT "/mongoose.c",
                         tmp_file, buf, sizeof(buf), &ri)) != NULL);
-  ASSERT(mg_stat("mongoose.c", &st) == 0);
-  ASSERT(st.size == ftell(fp));
+  ASSERT(mg_stat(fc(ctx), "mongoose.c", &file));
+  ASSERT(file.size == ftell(fp));
   ASSERT(!strcmp(ri.request_method, "HTTP/1.1"));
 
+  // Fetch nonexistent file, /blah
+  ASSERT((fp = mg_fetch(ctx, "http://localhost:" UNUSED_PORT "/boo",
+                        tmp_file, buf, sizeof(buf), &ri)) != NULL);
+  ASSERT(!mg_strcasecmp(ri.uri, "404"));
+  fclose(fp);
+
+  // Fetch existing inmemory file
+  ASSERT((fp = mg_fetch(ctx, "http://localhost:" UNUSED_PORT "/blah",
+                        tmp_file, buf, sizeof(buf), &ri)) != NULL);
+  ASSERT(!mg_strcasecmp(ri.uri, "200"));
+  n = ftell(fp);
+  fseek(fp, 0, SEEK_SET);
+  printf("%s %d %d [%.*s]\n", __func__, n, (int) feof(fp), n, buf2);
+  n = fread(buf2, 1, n, fp);
+  printf("%s %d %d [%.*s]\n", __func__, n, (int) feof(fp), n, buf2);
+  ASSERT((size_t) ftell(fp) == (size_t) strlen(inmemory_file_data));
+  ASSERT(!memcmp(inmemory_file_data, buf2, ftell(fp)));
+  fclose(fp);
+
   remove(tmp_file);
   mg_stop(ctx);
 }

Kaikkia tiedostoja ei voida näyttää, sillä liian monta tiedostoa muuttui tässä diffissä