2

What is the best approach to modify the output of a file served by mongoose mg_http_serve_dir and mg_http_serve_file.

I am using this example https://github.com/cesanta/mongoose/blob/master/examples/http-restful-server/main.c

I am searching for a way to modify the output like this

    } else if (mg_http_match_uri(hm, "/api/f2/*")) {
      mg_http_reply(c, 200, "", "{\"result\": \"%.*s\"}\n", (int) hm->uri.len,
                    hm->uri.ptr);
    } else {
      struct mg_http_serve_opts opts = {.root_dir = s_root_dir};
      mg_http_serve_dir(c, ev_data, &opts);
     //After this call, I want to modify the output send by mongoose if possible for example replacing a string, and then setting the content length to the new size.
    }
  }
  (void) fn_data;
}

Currently I reimplement mg_http_serve_dir as local_mg_http_serve_dir and mg_http_serve_file as local_mg_http_serve_file

I ask myself if there is an easier way that I was unable to find.

As of another question this is my customized serve dir function to clarify what i want to do:

void local_mg_http_serve_dir(struct mg_connection* c, struct mg_http_message* hm, const struct mg_http_serve_opts* opts) {
 char path[MG_PATH_MAX];
 const char* sp = opts->ssi_pattern;
 int flags = uri_to_path(c, hm, opts, path, sizeof(path));
 if (flags < 0) {
  // Do nothing: the response has already been sent by uri_to_path()
 }
 else if (flags & MG_FS_DIR) {
#if MG_ENABLE_DIRLIST
  listdir(c, hm, opts, path);
#else
  mg_http_reply(c, 403, "", "Forbidden\n");
#endif
 }
 else if (flags && sp != NULL &&
  mg_globmatch(sp, strlen(sp), path, strlen(path))) {
  mg_http_serve_ssi(c, opts->root_dir, path);
 }
 else {
  if (mg_http_match_uri(hm, "#.csp") || mg_http_match_uri(hm, "/")) {
   if(!local_mg_http_serve_404(c, hm, path, opts)) {
    char* cont;
    cont = readFile(path);
    Poco::JSON::Object::Ptr jdb = jdbRead("./var/db");
    std::string menuHtml = jdbMenuToHtml("mainmenu", jdb);
    replaceInPlace(cont, "<* menu *>", menuHtml.c_str());
    mg_http_reply(c, 200, "content-type: text/html\r\n", "%s", cont);
   }
  }
  else {
   local_mg_http_serve_file(c, hm, path, opts);
  }
 }
}
1u1u
  • 141
  • 1
  • 5

1 Answers1

1

After some debugging I found what I missed. Insead of manually opening files and sending them as response after modification I can define a custom callback that is set as default

static void static_cb(struct mg_connection *c, int ev, void *ev_data, void *fn_data)

Which is called from the mg_http_serve_file function

  else {
   // Track to-be-sent content length at the end of c->data, aligned
   size_t* clp = (size_t*)&c->data[(sizeof(c->data) - sizeof(size_t)) /
    sizeof(size_t) * sizeof(size_t)];
   c->pfn = static_cb;
   c->pfn_data = fd;
   *clp = cl;
  }

Unfortunally this approach still needs reimplementing the mg_http_serve_file once for modifying the content length of the file descriptor, then replacing the output.

So I still keep using my old local_mg_http_serve_file within the event handler callback function as example here:

https://github.com/cesanta/mongoose/blob/master/examples/huge-response/main.c

1u1u
  • 141
  • 1
  • 5