JSON directory API

This commit is contained in:
Scott Shawcroft 2022-06-21 16:18:34 -07:00
parent 847ac60dce
commit 964828398e
No known key found for this signature in database
GPG Key ID: 0DFD512649C052DA

View File

@ -34,6 +34,7 @@
#include "shared-bindings/wifi/Radio.h" #include "shared-bindings/wifi/Radio.h"
#include "shared-module/storage/__init__.h" #include "shared-module/storage/__init__.h"
#include "shared/timeutils/timeutils.h"
#include "supervisor/shared/translate/translate.h" #include "supervisor/shared/translate/translate.h"
#include "supervisor/shared/web_workflow/web_workflow.h" #include "supervisor/shared/web_workflow/web_workflow.h"
#include "supervisor/usb.h" #include "supervisor/usb.h"
@ -77,6 +78,7 @@ typedef struct {
bool done; bool done;
bool authenticated; bool authenticated;
bool expect; bool expect;
bool json;
} _request; } _request;
static wifi_radio_error_t wifi_status = WIFI_RADIO_ERROR_NONE; 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) {
_send_str(socket, "\r\n\r\n"); _send_str(socket, "\r\n\r\n");
} }
static void _reply_directory_json(socketpool_socket_obj_t *socket, FF_DIR *dir, const char *request_path, const char *path) {
const char *ok_response = "HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\n"
"Content-Type: application/json\r\n\r\n";
socketpool_socket_send(socket, (const uint8_t *)ok_response, strlen(ok_response));
_send_chunk(socket, "[");
bool first = true;
FILINFO file_info;
char *fn = file_info.fname;
FRESULT res = f_readdir(dir, &file_info);
while (res == FR_OK && fn[0] != 0) {
if (!first) {
_send_chunk(socket, ",");
}
_send_chunk(socket, "{\"name\": \"");
_send_chunk(socket, file_info.fname);
_send_chunk(socket, "\", \"directory\": ");
if ((file_info.fattrib & AM_DIR) != 0) {
_send_chunk(socket, "true");
} else {
_send_chunk(socket, "false");
}
// We use nanoseconds past Jan 1, 1970 for consistency with BLE API and
// LittleFS.
_send_chunk(socket, ", \"modified_ns\": ");
uint64_t truncated_time = timeutils_mktime(1980 + (file_info.fdate >> 9),
(file_info.fdate >> 5) & 0xf,
file_info.fdate & 0x1f,
file_info.ftime >> 11,
(file_info.ftime >> 5) & 0x1f,
(file_info.ftime & 0x1f) * 2) * 1000000000ULL;
char encoded_number[32];
snprintf(encoded_number, sizeof(encoded_number), "%lld", truncated_time);
_send_chunk(socket, encoded_number);
_send_chunk(socket, ", \"file_size\": ");
size_t file_size = 0;
if ((file_info.fattrib & AM_DIR) == 0) {
file_size = file_info.fsize;
}
snprintf(encoded_number, sizeof(encoded_number), "%d", file_size);
_send_chunk(socket, encoded_number);
_send_chunk(socket, "}");
first = false;
res = f_readdir(dir, &file_info);
}
_send_chunk(socket, "]");
_send_chunk(socket, "");
}
static void _reply_directory_html(socketpool_socket_obj_t *socket, FF_DIR *dir, const char *request_path, const char *path) { static void _reply_directory_html(socketpool_socket_obj_t *socket, FF_DIR *dir, const char *request_path, const char *path) {
const char *ok_response = "HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\n" const char *ok_response = "HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\n"
"Content-Type: text/html\r\n\r\n"; "Content-Type: text/html\r\n\r\n";
@ -737,7 +792,12 @@ static void _reply(socketpool_socket_obj_t *socket, _request *request) {
_reply_missing(socket); _reply_missing(socket);
return; return;
} }
_reply_directory_html(socket, &dir, request->path, path); if (request->json) {
_reply_directory_json(socket, &dir, request->path, path);
} else {
_reply_directory_html(socket, &dir, request->path, path);
}
f_closedir(&dir); f_closedir(&dir);
} else if (strcmp(request->method, "PUT") == 0) { } else if (strcmp(request->method, "PUT") == 0) {
if (_usb_active()) { if (_usb_active()) {
@ -884,6 +944,8 @@ static void _process_request(socketpool_socket_obj_t *socket, _request *request)
request->content_length = strtoul(request->header_value, NULL, 10); request->content_length = strtoul(request->header_value, NULL, 10);
} else if (strcmp(request->header_key, "Expect") == 0) { } else if (strcmp(request->header_key, "Expect") == 0) {
request->expect = strcmp(request->header_value, "100-continue") == 0; request->expect = strcmp(request->header_value, "100-continue") == 0;
} else if (strcmp(request->header_key, "Accept") == 0) {
request->json = strcmp(request->header_value, "application/json") == 0;
} }
ESP_LOGW(TAG, "Header %s %s", request->header_key, request->header_value); ESP_LOGW(TAG, "Header %s %s", request->header_key, request->header_value);
} else if (request->offset > sizeof(request->header_value) - 1) { } else if (request->offset > sizeof(request->header_value) - 1) {