-
Notifications
You must be signed in to change notification settings - Fork 2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
gcoap/fileserver: add file and directory creation and deletion #18133
gcoap/fileserver: add file and directory creation and deletion #18133
Conversation
From a CoAP point of view, I think that PUT should be used for file creation -- this has not only better properties (w/rt idempotency) but is also aligned with what WebDAV does. (POST would have a place if you want to create a file whose name you don't care about, but I don't think that that is a common use case). |
Indeed PUT can also be used for resource creation according to RFC7252. The handlers for POST and PUT anyways show some code duplication. I should be able to reduce it to just PUT. |
I think that makes things simper. It also aligns it with the CoAP file service draft. I feel obliged to point out that that is very drafty and has not even been properly discussed. If you want to consider that text for here, I'd rather hope for any disagreements between the text and the implementation would lead to a discussion on what good behavior is. (For example, this changes files non-atomically; maybe the text should rather not make promises unless one or the other behavior is advertised). |
return coap_opt_finish(pdu, COAP_OPT_FINISH_NONE); | ||
} | ||
|
||
static ssize_t _delete_directory(coap_pkt_t *pdu, uint8_t *buf, size_t len, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there the possibility to signal recursive deletion?
Or is the CoAP fileserver API fundamentally low-level?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Personally I am not interested in recursive deletion. Only empty directories can be deleted with vfs_rmdir
,
If we want to implement recursive deletion later, we could define that a client must append a URI query DELETE: coap://server:port/path/to/resource?recursive=1
. But this is just a first idea.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I suggest that recursive is the default. The UNIX behavior can be easily emulated with ETags (just pick a special ETag for empty directories on the server side, and insist that the client send an If-Match
if a directory would be removed recursively), whereas the other direction is cumbersome to emulate by the client.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do I understand this right?
If the client sends a DELETE
on a directory, without an If-Match
, the server should recursively delete the directory and all of its sub content.
If the client sends a DELETE
on a directory, with an If-Match
that contains the special Etag for empty directories, the server only deletes the directory if it is empty.
cce8a0c
to
cf39dcf
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If @chrysn has no objections to the server logic/API, this should be fine.
I still need to implement the recursive DELETE. But I was not sure if I understood it right. |
Recursive delete might be generally useful, so best implement it in |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks pretty good!
No need to wait for an approval to rebase btw to fix the merge conflicts 😉
Just one more thing: Can you make the write support a compile-time conditional (gcoap_fileserver_read_only
? gcoap_fileserver_write
?) so read-only applications can save a few bytes and don't have to worry about possible security implications.
e26aa9c
to
7a98128
Compare
I am going to do that. I would add pseudomodules |
Let me know if I can squash |
Please squash! |
|
||
#define ENABLE_DEBUG 0 | ||
#include "debug.h" | ||
|
||
/** Maximum length of an expressible path, including the trailing 0 character. */ | ||
#define COAPFILESERVER_PATH_MAX (64) | ||
|
||
/** Randomly generated Etag, used by a client that a directory should only be | ||
deleted, if it is empty */ | ||
#define COAPFILESERVER_DIR_DELETE_ETAG (0x6ce88b56u) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If a client is supposed to use this, shouldn't this be made available in a header?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also (sorry for jumping in so late, if this was discussed before), why is an ETag the signifier for this? Usually, with a REST API, this is done with some specific parameters (either as a query parameter or e.g. as a CBOR/JSON object).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, I saw that this was proposed by @chrysn in #18133 (comment). But still, I am a bit confused about this
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But still, I am a bit confused about this
The content of an If-Match
option is an Etag.
Simply formulated: If the client sends that special Etag, it expects the directory to be empty. And if so, the request is processed, which means it is DELETE
ed. My first idea was indeed a query parameter, but I think the If-Match
option works as well. Does this help or what exactly is unclear?
6636cdf
to
9333970
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Works like a charm!
For testing with coap-client
I had to ignore the URI_HOST option as it would send it and it's a critical option - but we aren't doing vhosting, so any hostname will do.
Since it's just a two line change I've taken the liberty to just push that to your branch.
Awesome, Thank You! |
Contribution description
With this PR I added write support for the
gcoap
fileserver, usingPOST
,PUT
andDELETE
methods.POST
: used to create files and directoriesPUT
: creates files or directories or updates files in a random access fashionDELETE
: delete files and directoriesCoAP options
If-Match
andIf-None-Match
are added and handled inPUT
requests.Somehow directory deletion does not work for me. I end up in
littlefs2/lfs.c:1457
.I don´t know why. Maybe it works for you.Works with #18141
Testing procedure
Flash
examples/gcoap_fileserver
to a board with Ethernet support, connect with your PC and use a CoAP client to upload some files to the board´s VFS.RIOT shell
I test with
libcoap
example client. andCFLAGS += -DCONFIG_GNRC_IPV6_NIB_ARSM=1
Host shell
Issues/PRs references