- Serve static files
- Download folder as zip file
- Upload files and folders (Drag & Drop)
-- Search files
+- Create/Edit/Search files
- Partial responses (Parallel/Resume download)
- Path level access control
- Support https
curl -X DELETE http://127.0.0.1:5000/path-to-file-or-folder
```
-List/search directory contents
+Create a directory
```
-curl http://127.0.0.1:5000?simple # output pathname only, just like `ls -1`
+curl -X MKCOL https://127.0.0.1:5000/path-to-folder
+```
-curl http://127.0.0.1:5000?json # output name/mtime/type/size and other information in json format
+Move the file/folder to the new path
+
+```
+curl -X MOVE https://127.0.0.1:5000/path -H "Destination: https://127.0.0.1:5000/new-path"
+```
+
+List/search directory contents
+```
+curl http://127.0.0.1:5000?simple # output name only, just like `ls -1`
+curl http://127.0.0.1:5000?json # output name/mtime/type/size and other information in json format
curl http://127.0.0.1:5000?q=Dockerfile&simple # search for files, just like `find -name Dockerfile`
```
+With authorization
+
+```
+curl --user user:pass --digest http://192.168.8.10:5000/file # digest auth
+curl --user user:pass http://192.168.8.10:5000/file # basic auth
+```
+
<details>
<summary><h2>Advanced topics</h2></summary>
<input type="submit" hidden />
</form>
<div class="toolbox2">
- <div class="login-btn hidden" title="Login">
+ <div class="login-btn hidden" title="Login for upload/move/delete/edit permissions">
<svg width="16" height="16" viewBox="0 0 16 16">
<path fill-rule="evenodd"
d="M6 3.5a.5.5 0 0 1 .5-.5h8a.5.5 0 0 1 .5.5v9a.5.5 0 0 1-.5.5h-8a.5.5 0 0 1-.5-.5v-2a.5.5 0 0 0-1 0v2A1.5 1.5 0 0 0 6.5 14h8a1.5 1.5 0 0 0 1.5-1.5v-9A1.5 1.5 0 0 0 14.5 2h-8A1.5 1.5 0 0 0 5 3.5v2a.5.5 0 0 0 1 0v-2z" />
</div>
<div class="user-btn hidden">
<svg width="16" height="16" viewBox="0 0 16 16">
- <path d="M8 8a3 3 0 1 0 0-6 3 3 0 0 0 0 6Zm2-3a2 2 0 1 1-4 0 2 2 0 0 1 4 0Zm4 8c0 1-1 1-1 1H3s-1 0-1-1 1-4 6-4 6 3 6 4Zm-1-.004c-.001-.246-.154-.986-.832-1.664C11.516 10.68 10.289 10 8 10c-2.29 0-3.516.68-4.168 1.332-.678.678-.83 1.418-.832 1.664h10Z"/>
+ <path
+ d="M8 8a3 3 0 1 0 0-6 3 3 0 0 0 0 6Zm2-3a2 2 0 1 1-4 0 2 2 0 0 1 4 0Zm4 8c0 1-1 1-1 1H3s-1 0-1-1 1-4 6-4 6 3 6 4Zm-1-.004c-.001-.246-.154-.986-.832-1.664C11.516 10.68 10.289 10 8 10c-2.29 0-3.516.68-4.168 1.332-.678.678-.83 1.418-.832 1.664h10Z" />
</svg>
</div>
<div class="save-btn hidden" title="Save file">
async function login(alert = false) {
if (!DATA.auth) return;
try {
- const res = await fetch(baseUrl() + "?auth");
+ const res = await fetch(baseUrl(), {
+ method: "WRITEABLE",
+ });
await assertResOK(res);
document.querySelector(".login-btn").classList.add("hidden");
$userBtn.classList.remove("hidden");
pub fn is_reject(&self) -> bool {
*self == GuardType::Reject
}
- pub fn is_readwrite(&self) -> bool {
- *self == GuardType::ReadWrite
- }
}
fn sanitize_path(path: &str, uri_prefix: &str) -> String {
.map(|(k, v)| (k.to_string(), v.to_string()))
.collect();
- if query_params.contains_key("auth") {
- if !guard_type.is_readwrite() {
- self.auth_reject(&mut res);
- }
+ if method.as_str() == "WRITEABLE" {
return Ok(res);
}
fn auth_check(
#[with(&["--auth", "/@user:pass@user2:pass2", "-A"])] server: TestServer,
) -> Result<(), Error> {
- let url = format!("{}index.html?auth", server.url());
- let resp = fetch!(b"GET", &url).send()?;
+ let url = format!("{}index.html", server.url());
+ let resp = fetch!(b"WRITEABLE", &url).send()?;
assert_eq!(resp.status(), 401);
- let resp = fetch!(b"GET", &url).send_with_digest_auth("user2", "pass2")?;
+ let resp = fetch!(b"WRITEABLE", &url).send_with_digest_auth("user2", "pass2")?;
assert_eq!(resp.status(), 401);
- let resp = fetch!(b"GET", &url).send_with_digest_auth("user", "pass")?;
+ let resp = fetch!(b"WRITEABLE", &url).send_with_digest_auth("user", "pass")?;
assert_eq!(resp.status(), 200);
Ok(())
}