Skip to content

Commit 9648283

Browse files
committed
JSON directory API
1 parent 847ac60 commit 9648283

File tree

1 file changed

+63
-1
lines changed

1 file changed

+63
-1
lines changed

supervisor/shared/web_workflow/web_workflow.c

Lines changed: 63 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434

3535
#include "shared-bindings/wifi/Radio.h"
3636
#include "shared-module/storage/__init__.h"
37+
#include "shared/timeutils/timeutils.h"
3738
#include "supervisor/shared/translate/translate.h"
3839
#include "supervisor/shared/web_workflow/web_workflow.h"
3940
#include "supervisor/usb.h"
@@ -77,6 +78,7 @@ typedef struct {
7778
bool done;
7879
bool authenticated;
7980
bool expect;
81+
bool json;
8082
} _request;
8183

8284
static wifi_radio_error_t wifi_status = WIFI_RADIO_ERROR_NONE;
@@ -381,6 +383,59 @@ static void _reply_redirect(socketpool_socket_obj_t *socket, const char *path) {
381383
_send_str(socket, "\r\n\r\n");
382384
}
383385

386+
static void _reply_directory_json(socketpool_socket_obj_t *socket, FF_DIR *dir, const char *request_path, const char *path) {
387+
const char *ok_response = "HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\n"
388+
"Content-Type: application/json\r\n\r\n";
389+
socketpool_socket_send(socket, (const uint8_t *)ok_response, strlen(ok_response));
390+
_send_chunk(socket, "[");
391+
bool first = true;
392+
393+
FILINFO file_info;
394+
char *fn = file_info.fname;
395+
FRESULT res = f_readdir(dir, &file_info);
396+
while (res == FR_OK && fn[0] != 0) {
397+
if (!first) {
398+
_send_chunk(socket, ",");
399+
}
400+
_send_chunk(socket, "{\"name\": \"");
401+
_send_chunk(socket, file_info.fname);
402+
_send_chunk(socket, "\", \"directory\": ");
403+
if ((file_info.fattrib & AM_DIR) != 0) {
404+
_send_chunk(socket, "true");
405+
} else {
406+
_send_chunk(socket, "false");
407+
}
408+
// We use nanoseconds past Jan 1, 1970 for consistency with BLE API and
409+
// LittleFS.
410+
_send_chunk(socket, ", \"modified_ns\": ");
411+
412+
uint64_t truncated_time = timeutils_mktime(1980 + (file_info.fdate >> 9),
413+
(file_info.fdate >> 5) & 0xf,
414+
file_info.fdate & 0x1f,
415+
file_info.ftime >> 11,
416+
(file_info.ftime >> 5) & 0x1f,
417+
(file_info.ftime & 0x1f) * 2) * 1000000000ULL;
418+
419+
char encoded_number[32];
420+
snprintf(encoded_number, sizeof(encoded_number), "%lld", truncated_time);
421+
_send_chunk(socket, encoded_number);
422+
423+
_send_chunk(socket, ", \"file_size\": ");
424+
size_t file_size = 0;
425+
if ((file_info.fattrib & AM_DIR) == 0) {
426+
file_size = file_info.fsize;
427+
}
428+
snprintf(encoded_number, sizeof(encoded_number), "%d", file_size);
429+
_send_chunk(socket, encoded_number);
430+
431+
_send_chunk(socket, "}");
432+
first = false;
433+
res = f_readdir(dir, &file_info);
434+
}
435+
_send_chunk(socket, "]");
436+
_send_chunk(socket, "");
437+
}
438+
384439
static void _reply_directory_html(socketpool_socket_obj_t *socket, FF_DIR *dir, const char *request_path, const char *path) {
385440
const char *ok_response = "HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\n"
386441
"Content-Type: text/html\r\n\r\n";
@@ -737,7 +792,12 @@ static void _reply(socketpool_socket_obj_t *socket, _request *request) {
737792
_reply_missing(socket);
738793
return;
739794
}
740-
_reply_directory_html(socket, &dir, request->path, path);
795+
if (request->json) {
796+
_reply_directory_json(socket, &dir, request->path, path);
797+
} else {
798+
_reply_directory_html(socket, &dir, request->path, path);
799+
}
800+
741801
f_closedir(&dir);
742802
} else if (strcmp(request->method, "PUT") == 0) {
743803
if (_usb_active()) {
@@ -884,6 +944,8 @@ static void _process_request(socketpool_socket_obj_t *socket, _request *request)
884944
request->content_length = strtoul(request->header_value, NULL, 10);
885945
} else if (strcmp(request->header_key, "Expect") == 0) {
886946
request->expect = strcmp(request->header_value, "100-continue") == 0;
947+
} else if (strcmp(request->header_key, "Accept") == 0) {
948+
request->json = strcmp(request->header_value, "application/json") == 0;
887949
}
888950
ESP_LOGW(TAG, "Header %s %s", request->header_key, request->header_value);
889951
} else if (request->offset > sizeof(request->header_value) - 1) {

0 commit comments

Comments
 (0)