mirror of
https://github.com/clearlinux/uwsgi.git
synced 2026-09-05 05:01:36 +00:00
completed virtual propfind support in rados
This commit is contained in:
+12
-7
@@ -17,7 +17,7 @@ struct uwsgi_buffer *uwsgi_webdav_multistatus_new() {
|
||||
struct uwsgi_buffer *ub = uwsgi_buffer_new(uwsgi.page_size);
|
||||
if (uwsgi_buffer_append(ub, "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n", 40)) goto error;
|
||||
if (uwsgi_buffer_append(ub, "<D:multistatus xmlns:D=\"DAV:\">\n", 31)) goto error;
|
||||
|
||||
return ub;
|
||||
error:
|
||||
uwsgi_buffer_destroy(ub);
|
||||
return NULL;
|
||||
@@ -63,19 +63,25 @@ int uwsgi_webdav_propfind_item_add(struct uwsgi_buffer *ub, char *href, uint16_t
|
||||
if (uwsgi_webdav_multistatus_response_new(ub)) return -1;
|
||||
if (uwsgi_buffer_append(ub, "<D:href>", 8)) return -1;
|
||||
if (uwsgi_buffer_append(ub, href, href_len)) return -1;
|
||||
if (uwsgi_buffer_append(ub, "</D:href>\n", 10)) return -1;
|
||||
if (uwsgi_webdav_multistatus_propstat_new(ub)) return -1;
|
||||
if (uwsgi_webdav_multistatus_prop_new(ub)) return -1;
|
||||
|
||||
// getcontentlength
|
||||
if (uwsgi_buffer_append(ub, "<D:getcontentlength>", 20)) return -1;
|
||||
if (uwsgi_buffer_num64(ub, cl)) return -1;
|
||||
if (uwsgi_buffer_append(ub, "</D:getcontentlength>", 21)) return -1;
|
||||
if (href[href_len-1] == '/') {
|
||||
if (uwsgi_buffer_append(ub, "<D:resourcetype><D:collection/></D:resourcetype>\n", 49)) return -1;
|
||||
}
|
||||
else {
|
||||
// getcontentlength
|
||||
if (uwsgi_buffer_append(ub, "<D:getcontentlength>", 20)) return -1;
|
||||
if (uwsgi_buffer_num64(ub, cl)) return -1;
|
||||
if (uwsgi_buffer_append(ub, "</D:getcontentlength>\n", 22)) return -1;
|
||||
}
|
||||
|
||||
// getlastmodified
|
||||
if (mtime > 0) {
|
||||
if (uwsgi_buffer_append(ub, "<D:getlastmodified>", 19)) return -1;
|
||||
if (uwsgi_buffer_httpdate(ub, mtime)) return -1;
|
||||
if (uwsgi_buffer_append(ub, "</D:getlastmodified>", 20)) return -1;
|
||||
if (uwsgi_buffer_append(ub, "</D:getlastmodified>\n", 21)) return -1;
|
||||
}
|
||||
|
||||
// displayname
|
||||
@@ -99,7 +105,6 @@ int uwsgi_webdav_propfind_item_add(struct uwsgi_buffer *ub, char *href, uint16_t
|
||||
|
||||
if (uwsgi_webdav_multistatus_prop_close(ub)) return -1;
|
||||
if (uwsgi_webdav_multistatus_propstat_close(ub)) return -1;
|
||||
if (uwsgi_buffer_append(ub, "</D:href>\n", 10)) return -1;
|
||||
if (uwsgi_webdav_multistatus_response_close(ub)) return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -46,6 +46,7 @@ struct uwsgi_rados_mountpoint {
|
||||
char *allow_put;
|
||||
char *allow_delete;
|
||||
char *allow_mkcol;
|
||||
char *allow_propfind;
|
||||
};
|
||||
|
||||
static struct uwsgi_option uwsgi_rados_options[] = {
|
||||
@@ -313,6 +314,77 @@ static int uwsgi_rados_read_async(struct wsgi_request *wsgi_req, rados_ioctx_t c
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void uwsgi_rados_propfind(struct wsgi_request *wsgi_req, rados_ioctx_t ctx, char *key, uint64_t size, time_t mtime, int timeout) {
|
||||
if (uwsgi_response_prepare_headers(wsgi_req, "207 Multi-Status", 16)) return;
|
||||
if (uwsgi_response_add_content_type(wsgi_req, "text/xml; charset=\"utf-8\"", 25)) return;
|
||||
struct uwsgi_buffer *ub = uwsgi_webdav_multistatus_new();
|
||||
if (!ub) return;
|
||||
if (key) {
|
||||
size_t mime_type_len = 0;
|
||||
char *mime_type = uwsgi_get_mime_type(key, strlen(key), &mime_type_len);
|
||||
char *slashed = uwsgi_concat2("/", key);
|
||||
if (uwsgi_webdav_propfind_item_add(ub, slashed, strlen(key)+1, size, mtime, mime_type, mime_type_len, NULL, 0, NULL, 0)) {
|
||||
free(slashed);
|
||||
goto end;
|
||||
}
|
||||
free(slashed);
|
||||
if (uwsgi_webdav_multistatus_close(ub)) goto end;
|
||||
uwsgi_response_write_body_do(wsgi_req, ub->buf, ub->pos);
|
||||
goto end;
|
||||
}
|
||||
// request for /
|
||||
size_t depth = 0;
|
||||
uint16_t http_depth_len = 0;
|
||||
char *http_depth = uwsgi_get_var(wsgi_req, "HTTP_DEPTH", 10, &http_depth_len);
|
||||
if (http_depth) {
|
||||
depth = uwsgi_str_num(http_depth, http_depth_len);
|
||||
}
|
||||
|
||||
if (depth == 0) {
|
||||
if (uwsgi_webdav_propfind_item_add(ub, "/", 1, 0, 0, NULL, 0, NULL, 0, NULL, 0)) {
|
||||
goto end;
|
||||
}
|
||||
if (uwsgi_webdav_multistatus_close(ub)) goto end;
|
||||
uwsgi_response_write_body_do(wsgi_req, ub->buf, ub->pos);
|
||||
goto end;
|
||||
}
|
||||
|
||||
struct uwsgi_rados_io *urio = &urados.urio[wsgi_req->async_id];
|
||||
rados_list_ctx_t ctx_list;
|
||||
if (rados_objects_list_open(ctx, &ctx_list) < 0) {
|
||||
goto end;
|
||||
}
|
||||
|
||||
char *entry = NULL;
|
||||
while(rados_objects_list_next(ctx_list, (const char **)&entry, NULL) == 0) {
|
||||
uint64_t stat_size = 0;
|
||||
time_t stat_mtime = 0;
|
||||
if (uwsgi.async > 1) {
|
||||
if (uwsgi_rados_async_stat(urio, ctx, entry, &stat_size, &stat_mtime, timeout) < 0) goto end;
|
||||
}
|
||||
else {
|
||||
if (rados_stat(ctx, entry, &stat_size, &stat_mtime) < 0) goto end;
|
||||
}
|
||||
|
||||
size_t mime_type_len = 0;
|
||||
char *mime_type = uwsgi_get_mime_type(entry, strlen(entry), &mime_type_len);
|
||||
char *slashed = uwsgi_concat2("/", entry);
|
||||
if (uwsgi_webdav_propfind_item_add(ub, slashed, strlen(entry)+1, stat_size, stat_mtime, mime_type, mime_type_len, NULL, 0, NULL, 0)) {
|
||||
free(slashed);
|
||||
goto end;
|
||||
}
|
||||
free(slashed);
|
||||
if (uwsgi_response_write_body_do(wsgi_req, ub->buf, ub->pos)) goto end;
|
||||
// reset buffer;
|
||||
ub->pos = 0;
|
||||
}
|
||||
rados_objects_list_close(ctx_list);
|
||||
if (uwsgi_webdav_multistatus_close(ub)) goto end;
|
||||
uwsgi_response_write_body_do(wsgi_req, ub->buf, ub->pos);
|
||||
|
||||
end:
|
||||
uwsgi_buffer_destroy(ub);
|
||||
}
|
||||
|
||||
static void uwsgi_rados_add_mountpoint(char *arg, size_t arg_len) {
|
||||
struct uwsgi_rados_mountpoint *urmp = uwsgi_calloc(sizeof(struct uwsgi_rados_mountpoint));
|
||||
@@ -324,6 +396,7 @@ static void uwsgi_rados_add_mountpoint(char *arg, size_t arg_len) {
|
||||
"allow_put", &urmp->allow_put,
|
||||
"allow_delete", &urmp->allow_delete,
|
||||
"allow_mkcol", &urmp->allow_mkcol,
|
||||
"allow_propfind", &urmp->allow_propfind,
|
||||
NULL)) {
|
||||
uwsgi_log("unable to parse rados mountpoint definition\n");
|
||||
exit(1);
|
||||
@@ -538,12 +611,32 @@ static int uwsgi_rados_request(struct wsgi_request *wsgi_req) {
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
if (urmp->allow_propfind) {
|
||||
if (uwsgi_buffer_append(ub_allow, ", PROPFIND", 10)) {
|
||||
uwsgi_buffer_destroy(ub_allow);
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
|
||||
uwsgi_response_add_header(wsgi_req, "Allow", 5, ub_allow->buf, ub_allow->pos);
|
||||
uwsgi_buffer_destroy(ub_allow);
|
||||
goto end;
|
||||
}
|
||||
|
||||
// empty paths are mapped to propfind
|
||||
if (!wsgi_req->path_info_len == 0) {
|
||||
if (!urmp->allow_propfind) {
|
||||
goto nopropfind;
|
||||
}
|
||||
if (!uwsgi_strncmp(wsgi_req->method, wsgi_req->method_len, "GET", 3) || !uwsgi_strncmp(wsgi_req->method, wsgi_req->method_len, "PROPFIND", 8)) {
|
||||
uwsgi_rados_propfind(wsgi_req, ctx, NULL, 0, 0, timeout);
|
||||
goto end;
|
||||
}
|
||||
nopropfind:
|
||||
uwsgi_405(wsgi_req);
|
||||
goto end;
|
||||
}
|
||||
|
||||
// MKCOL does not require stat
|
||||
if (!uwsgi_strncmp(wsgi_req->method, wsgi_req->method_len, "MKCOL", 5)) {
|
||||
if (!urmp->allow_mkcol) {
|
||||
@@ -611,6 +704,15 @@ static int uwsgi_rados_request(struct wsgi_request *wsgi_req) {
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (!uwsgi_strncmp(wsgi_req->method, wsgi_req->method_len, "PROPFIND", 8)) {
|
||||
if (!urmp->allow_propfind) {
|
||||
uwsgi_405(wsgi_req);
|
||||
goto end;
|
||||
}
|
||||
uwsgi_rados_propfind(wsgi_req, ctx, filename, stat_size, stat_mtime, timeout);
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (uwsgi_strncmp(wsgi_req->method, wsgi_req->method_len, "HEAD", 4) && uwsgi_strncmp(wsgi_req->method, wsgi_req->method_len, "GET", 3)) {
|
||||
uwsgi_405(wsgi_req);
|
||||
goto end;
|
||||
|
||||
@@ -4821,6 +4821,15 @@ void uwsgi_emperor_ini_attrs(char *, char *, struct uwsgi_dyn_dict **);
|
||||
int uwsgi_buffer_httpdate(struct uwsgi_buffer *, time_t);
|
||||
int uwsgi_buffer_append_xml(struct uwsgi_buffer *, char *, size_t);
|
||||
|
||||
struct uwsgi_buffer *uwsgi_webdav_multistatus_new();
|
||||
int uwsgi_webdav_propfind_item_add(struct uwsgi_buffer *, char *, uint16_t, uint64_t, time_t, char *, uint16_t, char *, uint16_t, char *, uint16_t);
|
||||
int uwsgi_webdav_multistatus_close(struct uwsgi_buffer *);
|
||||
int uwsgi_webdav_multistatus_response_new(struct uwsgi_buffer *);
|
||||
int uwsgi_webdav_multistatus_response_close(struct uwsgi_buffer *);
|
||||
int uwsgi_webdav_multistatus_propstat_new(struct uwsgi_buffer *);
|
||||
int uwsgi_webdav_multistatus_propstat_close(struct uwsgi_buffer *);
|
||||
int uwsgi_webdav_multistatus_prop_new(struct uwsgi_buffer *);
|
||||
int uwsgi_webdav_multistatus_prop_close(struct uwsgi_buffer *);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user