-STATIC int servFile (struct MHD_Connection *connection, AFB_session *session, const char *url, AFB_staticfile *staticfile) {
- const char *etagCache, *mimetype;
- char etagValue[15];
- struct MHD_Response *response;
- struct stat sbuf;
- int ret;
-
- if (fstat (staticfile->fd, &sbuf) != 0) {
- fprintf(stderr, "Fail to stat file: [%s] error:%s\n", staticfile->path, strerror(errno));
- return (FAILED);
- }
-
- // if url is a directory let's add index.html and redirect client
- if (S_ISDIR (sbuf.st_mode)) {
- if (url [strlen (url) -1] != '/') strncat (staticfile->path, "/", sizeof (staticfile->path));
- strncat (staticfile->path, "index.html", sizeof (staticfile->path));
- close (staticfile->fd); // close directory try to open index.html
- if (-1 == (staticfile->fd = open(staticfile->path, O_RDONLY)) || (fstat (staticfile->fd, &sbuf) != 0)) {
- fprintf(stderr, "No Index.html in direcory [%s]\n", staticfile->path);
- return (FAILED);
- }
-
- } 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", staticfile->path);
- 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);
- MHD_queue_response (connection, MHD_HTTP_INTERNAL_SERVER_ERROR, response);
- goto finishJob;
-
- }
-
- // 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(staticfile->fd); // file did not change since last upload
- if (verbose) fprintf(stderr, "Not Modify: [%s]\n", staticfile->path);
- 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);
- MHD_queue_response(connection, MHD_HTTP_NOT_MODIFIED, response);
-
- } else { // it's a new file, we need to upload it to client
- // if we have magic let's try to guest mime type
- if (session->magic) {
- mimetype="Unknown";
- mimetype= magic_descriptor(session->magic, staticfile->fd);
- if (mimetype != NULL) MHD_add_response_header (response, MHD_HTTP_HEADER_CONTENT_TYPE, mimetype);
- };
- if (verbose) fprintf(stderr, "Serving: [%s] mine=%s\n", staticfile->path, mimetype);
- response = MHD_create_response_from_fd(sbuf.st_size, staticfile->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);
- MHD_queue_response(connection, MHD_HTTP_OK, response);
- }
-
-finishJob:
- MHD_destroy_response(response);
- return (MHD_YES);
+static int afb_hreq_rest_api(struct afb_hreq *hreq, void *data)
+{
+ const char *api, *verb;
+ size_t lenapi, lenverb;
+
+ api = hreq->tail;
+ lenapi = strspn(api, "/");
+ verb = &hreq->tail[lenapi];
+ verb = &verb[strcspn(verb, "/")];
+ lenverb = strspn(verb, "/");
+
+ if (!(*api && *verb && lenapi && lenverb))
+ return 0;
+
+ return afb_apis_handle(afb_hreq_to_req(hreq), api, lenapi, verb, lenverb);