-STATIC int servFile (struct MHD_Connection *connection, AFB_session *session, const char *url, char *filepath, int fd) {
- const char *etagCache;
- char etagValue[15];
- struct MHD_Response *response;
- struct stat sbuf;
- int ret;
-
- if (fstat (fd, &sbuf) != 0) {
- fprintf(stderr, "Fail to stat file: [%s] error:%s\n", filepath, strerror(errno));
- return (FAILED);
- }
-
- // if url is a directory let's add index.html and redirect client
- if (S_ISDIR (sbuf.st_mode)) {
- strncpy (filepath, url, sizeof (filepath));
-
- if (url [strlen (url) -1] != '/') strncat (filepath, "/", sizeof (filepath));
- strncat (filepath, "index.html", sizeof (filepath));
- close (fd);
- response = MHD_create_response_from_buffer (0,"", MHD_RESPMEM_PERSISTENT);
- MHD_add_response_header (response,MHD_HTTP_HEADER_LOCATION, filepath);
- ret = MHD_queue_response (connection, MHD_HTTP_MOVED_PERMANENTLY, response);
-
- } else if (! S_ISREG (sbuf.st_mode)) { // only standard file any other one including symbolic links are refused.
-
- fprintf (stderr, "Fail file: [%s] is not a regular file\n", filepath);
- const char *errorstr = "<html><body>Alsa-Json-Gateway Invalid file type</body></html>";
- response = MHD_create_response_from_buffer (strlen (errorstr),
- (void *) errorstr, MHD_RESPMEM_PERSISTENT);
- ret = MHD_queue_response (connection, MHD_HTTP_INTERNAL_SERVER_ERROR, response);
-
- } else {
-
- // https://developers.google.com/web/fundamentals/performance/optimizing-content-efficiency/http-caching?hl=fr
- // ftp://ftp.heanet.ie/disk1/www.gnu.org/software/libmicrohttpd/doxygen/dc/d0c/microhttpd_8h.html
-
- // Check etag value and load file only when modification date changes
- etagCache = MHD_lookup_connection_value(connection, MHD_HEADER_KIND, MHD_HTTP_HEADER_IF_NONE_MATCH);
- computeEtag(etagValue, sizeof (etagValue), &sbuf);
-
- if (etagCache != NULL && strcmp(etagValue, etagCache) == 0) {
- close(fd); // file did not change since last upload
- if (verbose) fprintf(stderr, "Not Modify: [%s]\n", filepath);
- response = MHD_create_response_from_buffer(0, "", MHD_RESPMEM_PERSISTENT);
- MHD_add_response_header(response, MHD_HTTP_HEADER_CACHE_CONTROL, session->cacheTimeout); // default one hour cache
- MHD_add_response_header(response, MHD_HTTP_HEADER_ETAG, etagValue);
- ret = MHD_queue_response(connection, MHD_HTTP_NOT_MODIFIED, response);
-
- } else { // it's a new file, we need to upload it to client
- if (verbose) fprintf(stderr, "Serving: [%s]\n", filepath);
- response = MHD_create_response_from_fd(sbuf.st_size, fd);
- MHD_add_response_header(response, MHD_HTTP_HEADER_CACHE_CONTROL, session->cacheTimeout); // default one hour cache
- MHD_add_response_header(response, MHD_HTTP_HEADER_ETAG, etagValue);
- ret = MHD_queue_response(connection, MHD_HTTP_OK, response);
- }
- }
- MHD_destroy_response(response);
- return (ret);