Skip to content

Commit

Permalink
doc: readme
Browse files Browse the repository at this point in the history
Signed-off-by: 117503445 <[email protected]>
  • Loading branch information
117503445 committed Feb 18, 2024
1 parent f3b3e8e commit 1f45321
Show file tree
Hide file tree
Showing 6 changed files with 130 additions and 126 deletions.
171 changes: 61 additions & 110 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,181 +1,132 @@
# GoWebdav
# GoWebDAV

> Share local files with WebDAV, lightweight and very easy to use.
> Share local files using WebDAV, lightweight and easy to use
English | [中文](./README_zh_CN.md)
English | [简体中文](./README_zh_CN.md)

## feature
## Features

- Based on Golang implementation, high performance
- Implemented in Golang for high performance.

- Finally compiled into a single binary file, no need for Apache and other environments, more stable
- Finally compiled into a single binary file, no need for Apache or similar environments, with few dependencies.

- Support browser access
- Supports browser access.

- Multiple WebDAV services can be enabled under the same port, each with a different mount directory, user name, and password
- Multiple WebDAV services can be enabled on the same port, each with different mount directories, usernames, and passwords.

- Docker is well supported
- Good Docker support.

## quickstart
## Quick Start

### bin
Download the binary file from <https://github.com/117503445/GoWebDAV/releases>

Go to <https://github.com/117503445/GoWebDAV/releases> to download the latest binaries.
Run

Then run `. /gowebdav`
```sh
./gowebdav
```

GoWebDAV will automatically create the example file under the `./data` path with the following file structure
GoWebDAV will automatically create sample files under the `./data` path, with the following file structure

```sh
> tree ./data
./data
├── public-writable
│ └── 1.txt
└── 1.txt
├── public-readonly
│ └── 2.txt
└── 1.txt
└── private-writable
└── 3.txt
└── 1.txt
```

Visit <http://localhost:80> with your browser and you will see 3 different GoWebDAV services.
Access <http://localhost:80> in your browser to see the 3 different GoWebDAV services.

![index](./doc/index.png)

where <http://localhost:80/public-writable> is the `public-writable` service that maps the local `./data/public-writable` folder. It is Anonymizable and writable. You can view the contents of the file in the browser, as well as perform operations such as uploading and deleting.
Among them, <http://localhost:80/public-writable> is the `public-writable` service, mapping to the local `./data/public-writable` folder. It is unauthenticated and writable. You can view file contents in the browser and perform operations like upload and delete.

![public-writable](./doc/public-writable.png)

<http://localhost:80/public-readonly> is the `public-readonly` service that maps the local `./data/public-readonly` folder. It is Anonymizable and read-only. You can view the contents of the file in your browser, but you cannot upload, delete, etc.
<http://localhost:80/public-readonly> is the `public-readonly` service, mapping to the local `./data/public-readonly` folder. It is unauthenticated and read-only. You can view file contents in the browser but cannot upload, delete, etc.

![public-readonly](./doc/public-readonly.png)

<http://localhost:80/private-writable> is the `private-writable` service that maps the local `./data/private-writable` folder. It is user-authenticated and writable. After logging in with `user1` and `pass1`, you can view the contents of the files in the browser, as well as upload, delete, etc.
<http://localhost:80/private-writable> is the `private-writable` service, mapping to the local `./data/private-writable` folder. It requires user authentication and is writable. After logging in with `user1` and `pass1`, you can view file contents in the browser and perform operations like upload and delete.

![private-writable](./doc/private-writable.png)

The `dav` parameter can also be specified to configure the local path, user authentication, read-only, etc. properties of the WebDAV service, as described in the *Configuration Strings Description* section. When `dav` is not specified, the default `dav` parameter used by GoWebDAV is `/public-writable,./data/public-writable,null,null,false;/public-readonly,./data/public-readonly,null,null,true;/private-writable,./data/private-writable,user1,pass1,false`.

### Docker
Besides using a browser, you can also access it using other WebDAV client tools.

The local file paths to be shared are `/root/dir1` and `/root/dir2`.
You can configure the local path, user authentication, read-only status, and other properties of the WebDAV service by specifying the `dav` parameter. For details, see the *Usage* section.

```sh
docker run -it --name go_webdav -d -v /root/dir1:/root/dir1 -v /root/dir2:/root/dir2 -e dav="/dav1,/root/dir1,user1,pass1,true;/dav2,/root/dir2,null,null,false" -p 80:80 --restart=unless-stopped 117503445/go_webdav
```
## Usage

```sh
-e dav="/dav1,/root/dir1,user1,pass1,true;/dav2,/root/dir2,null,null,false"
```

Indicates passing a configuration string into the Docker image.

Then open <http://localhost/dav1> and <http://localhost/dav2> in the browser or webdav client like [raidrive](https://www.raidrive.com/).

## Configuration String

You can pass the `--dav` parameter to change the configuration.
./gowebdav --help # View help

On Windows, the same call as quickstart is made as follows
./gowebdav --addr 127.0.0.1 # Listen on 127.0.0.1, default is 0.0.0.0
./gowebdav --port 8080 # Listen on port 8080, default is port 80

./gowebdav --dav "/dir1,/data/dir1,user1,pass1,true" # Configure folder path and properties
```
// cmd
gowebdav_windows_amd64.exe --dav "/public-writable,./data/public-writable,null,null,false;/public-readonly,./data/public-readonly,null,null,true;/private-writable,./data/private-writable,user1,pass1,false"
// PowerShell
.\gowebdav_windows_amd64.exe --dav "/public-writable,./data/public-writable,null,null,false;/public-readonly,./data/public-readonly,null,null,true;/private-writable,./data/private-writable,user1,pass1,false"
```

On Windows, the same call as quickstart is made as follows

```sh
./gowebdav_linux_amd64 --dav "/public-writable,./data/public-writable,null,null,false;/public-readonly,./data/public-readonly,null,null,true;/private-writable,./data/private-writable,user1,pass1,false"
```

The following is a specific explanation of `dav`

Use a semicolon to separate each WebDAV service configuration, which means that `"/dav1,/root/dir1,user1,pass1,true;/dav2,/root/dir2,null,null,false"` describes 2 services, which are

> /dav1,/root/dir1,user1,pass1,false

and
The `dav` parameter can specify the local path, user authentication, read-only status, and other properties of the WebDAV service.

> /dav2,/root/dir2,null,null,true
Each local path can be configured for a WebDAV service, separated by semicolons. For example:

The first service will mount the `/root/dir1` directory of the Docker image under `/dav1`. The required username and password for access are `user1` and `pass1` respectively.
- `"/dir1,/data/dir1,user1,pass1,true;/dir2,/data/dir2,null,null,false"` describes 2 services, mapping the folder `/data/dir1` to the WebDAV service `/dir1` and the folder `/data/dir2` to the WebDAV service `/dir2`.

Then, according to the previous `-v /root/dir1:/root/dir1`, the mapping relationship with `/root/dir1` of the physical machine can be completed and accessed.
For each service, you need to separate 5 parameters with commas: `service path, local path, username, password, read-only status`. When both the username and password are `null`, no authentication is required. For example:

The fifth parameter `false` indicates that this is a non-read-only service that supports addition, deletion, modification and query.
- `"/dir1,/data/dir1,user1,pass1,true"` describes mapping `/data/dir1` to the `/dir1` service, where access requires the username and password `user1` and `pass1`, respectively, and is read-only (prohibits upload, update, delete).
- `"/dir2,/data/dir2,null,null,false"` describes mapping `/data/dir2` to the `/dir2` service, where no authentication is required and it is read-write.
- `"/dir3,/data/dir3,null,null,true"` describes mapping `/data/dir3` to the `/dir3` service, where no authentication is required and it is read-only.

The second service will mount the `/root/dir2` directory of the Docker image under `/dav2`. The user name and password required for access are `null` and `null` respectively. At this time, it means that the service can be accessed without a password. .
In particular, if there is only one service named `/`, you can access <http://localhost:80> directly without specifying a service name. For example:

Then according to the previous `-v /root/dir2:/root/dir2`, you can complete the mapping relationship with `/root/dir2` of the physical machine and access it.
- `"/,/data/dir1,user1,pass1,true"` describes mapping `/data/dir1` to the `/` service, where access requires the username and password `user1` and `pass1`, respectively, and is read-only.

The fifth parameter `true` indicates that this is a read-only service, only supports GET, does not support additions, deletions and modifications.
When `dav` is not specified, the default `dav` parameter used by GoWebDAV is `/public-writable,./data/public-writable,null,null,false;/public-readonly,./data/public-readonly,null,null,true;/private-writable,./data/private-writable,user1,pass1,false`.

This method is recommended for file sharing without confidentiality requirements.
## Docker

You can pass in the `--port` parameter to change the port to listen on. The default listens on port 80.

You can pass in the `--addr` parameter to change the address to listen on. The default listens on `0.0.0.0`.
Prepare the local folder paths to be shared as `/data/dir1` and `/data/dir2`.

```sh
# Listening on port 8080
./gowebdav_linux_amd64 --port 8080
docker run -it -d -v /data:/data -e dav="/dir1,/data/dir1,user1,pass1,true;/dir2,/data/dir2,null,null,false" -p 80:80 --restart=unless-stopped 117503445/go_webdav
```

## Docker Compose
Open <http://localhost/dir1> and <http://localhost/dir2> in your browser to access disk files in WebDAV format.

Expose `/root/dir1`, which requires authentication, and `/root/dir2`, which does not require authentication.
Pass the `data` parameter through the environment variable `dav` and specify the mapped port with `-p 80:80`.

## Docker Compose

```yaml
version: "3.9"
version: "3.8"
services:
go_webdav:
image: 117503445/go_webdav
container_name: go_webdav
restart: unless-stopped
volumes:
- "/root/dir1:/root/dir1"
- "/root/dir2:/root/dir2"
- /data:/data
environment:
- "dav=/dav1,/root/dir1,user1,pass1,true;/dav2,/root/dir2,null,null,false"
- "dav=/dir1,/data/dir1,user1,pass1,true;/dir2,/data/dir2,null,null,false"
ports:
- "80:80"
restart: unless-stopped
image: 117503445/go_webdav
- "80:80"
```
## Background introduction
`GoWebdav` is used to build a WebDAV-based file sharing server.

### Reasons to use WebDAV

1. Samba is inconvenient to use on Windows clients, and it is difficult to use non-default ports.

2. FTP mount trouble.

3. NextCloud is too heavy and difficult to share files on the server.

Because I didn't see a server-side implementation that could meet the above features, this project recreated a WebDAV Server.

## Local debugging

Rename `config.yml.example` to `config.yml`, configure in `config.yml` file

`go run .`

## Local Docker build
## Security
Using a layered build, the executable app is built through `go build` in the build layer, and then run in the prod layer. If you need to modify the structure of the configuration file later, you will also need to modify the Dockerfile.
GoWebDAV uses HTTP Basic Auth for authentication, with account passwords transmitted in plaintext, lacking security. If dealing with important files or passwords, be sure to use a layer of HTTPS with Nginx or Traefik proxy servers.
````sh
docker build -t 117503445/go_webdav .
docker run --name go_webdav -d -v ${PWD}/TestDir1:/root/TestDir1 -v ${PWD}/TestDir2:/root/TestDir2 -e dav="/dav1,/root/TestDir1,user1,pass1,false;/dav2,/root/TestDir2,user2,pass2,true" -p 80:80 --restart=unless-stopped 117503445/go_webdav
````
GoWebDAV currently does not have plans to directly support HTTPS, as I believe that tasks like domain names and certificate renewal should be handled at the higher-level proxy server.
## Safety
## Development
HTTP Basic Auth is used for authentication, and the account password is sent in clear text, which has no security at all. If important files or passwords are involved, be sure to use a gateway such as Nginx or Traefik to provide HTTPS.
Refer to [dev.md](./doc/dev.md)
## Acknowledgments
## Acknowledgements
<https://github.com/dom111/webdav-js> provides front-end support
<https://github.com/dom111/webdav-js> provides frontend support
24 changes: 16 additions & 8 deletions README_zh_CN.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# GoWebdav
# GoWebDAV

> 使用 WebDAV 分享本地文件,轻量、易于使用
Expand Down Expand Up @@ -55,6 +55,8 @@ GoWebDAV 会自动在 `./data` 路径下创建示例文件,文件结构如下

![private-writable](./doc/private-writable.png)

当然,除了浏览器,也可以使用其他 WebDAV 客户端工具进行访问。

可以通过指定 `dav` 参数来配置 WebDAV 服务的本地路径、用户验证、是否只读等属性,详情见 *使用* 章节。

## 使用
Expand All @@ -70,15 +72,19 @@ GoWebDAV 会自动在 `./data` 路径下创建示例文件,文件结构如下

`dav` 参数可以指定 WebDAV 服务的本地路径、用户验证、是否只读等属性。

每个本地路径都可以配置一个 WebDAV 服务,使用分号分隔。例子:
每个本地路径都可以配置一个 WebDAV 服务,使用分号分隔。例子:

- `"/dir1,/data/dir1,user1,pass1,true;/dir2,/data/dir2,null,null,false"` 描述了 2 个服务,分别是将文件夹 `/data/dir1` 映射至 WebDAV 服务 `/dir1`,将文件夹 `/data/dir2` 映射至 WebDAV 服务 `/dir2`

- `"/dir1,/data/dir1,user1,pass1,true;/dir2,/data/dir2,null,null,false"` 描述了 2 个服务,分别是将 `/data/dir1` 映射至 `/dir1`,将 `/data/dir2` 映射至 `/dir2`
对于每个服务,需要使用逗号分隔 5 个参数,分别是 `服务路径,本地路径,用户名,密码,是否只读`。其中用户名和密码都为 `null` 时表示不需要验证。例子:

对于每个服务,需要使用逗号分隔 5 个参数,分别是 `服务路径,本地路径,用户名,密码,是否只读`。其中用户名和密码都为 `null` 时表示不需要验证。例子:
- `"/dir1,/data/dir1,user1,pass1,true"` 描述了将 `/data/dir1` 映射至 `/dir1` 服务,访问需要的用户名和密码分别为 `user1``pass1`,只读(禁止上传、更新、删除)。
- `"/dir2,/data/dir2,null,null,false"` 描述了将 `/data/dir2` 映射至 `/dir2` 服务,访问不需要验证,可读写。
- `"/dir3,/data/dir3,null,null,true"` 描述了将 `/data/dir3` 映射至 `/dir3` 服务,访问不需要验证,只读。

- `"/dir1,/data/dir1,user1,pass1,true"` 描述了一个服务,将 `/data/dir1` 映射至 `/dir1`,访问需要的用户名和密码分别为 `user1``pass1`,只读(禁止上传、更新、删除)。
- `"/dir2,/data/dir2,null,null,false"` 描述了一个服务,将 `/data/dir2` 映射至 `/dir2`,访问不需要用户名和密码,可读写。
- `"/dir3,/data/dir3,null,null,true"` 描述了一个服务,将 `/data/dir3` 映射至 `/dir3`,访问不需要用户名和密码,只读。
特别的,如果只有 1 个服务且名为 `/`,则可以直接访问 <http://localhost:80> 而不需要指定服务名。例子:

- `"/,/data/dir1,user1,pass1,true"` 描述了将 `/data/dir1` 映射至 `/` 服务,访问需要的用户名和密码分别为 `user1``pass1`,只读。

`dav` 未指定时,GoWebDAV 默认使用的 `dav` 参数为 `/public-writable,./data/public-writable,null,null,false;/public-readonly,./data/public-readonly,null,null,true;/private-writable,./data/private-writable,user1,pass1,false`

Expand All @@ -92,6 +98,8 @@ docker run -it -d -v /data:/data -e dav="/dir1,/data/dir1,user1,pass1,true;/dir2

在浏览器中打开 <http://localhost/dir1><http://localhost/dir2>,就能以 WebDAV 的形式访问磁盘文件了。

通过环境变量 `dav` 传递 `data` 参数,通过 `-p 80:80` 指定映射的端口。

## Docker Compose

```yaml
Expand All @@ -117,7 +125,7 @@ GoWebDAV 目前没有直接支持 HTTPS 的计划,因为我认为 HTTPS 涉及
## 开发
见 [dev.md](./doc/dev.md)
见 [dev.md](./doc/dev_zh_CN.md)
## 致谢
Expand Down
22 changes: 21 additions & 1 deletion doc/dev.md
Original file line number Diff line number Diff line change
@@ -1 +1,21 @@
#
# Development

## Setting Up Development Environment

```sh
docker compose up -d
```

Then attach to the `gowebdav-dev` container using VSCode and start development in the `/workspace` directory.

## Common Development Operations

```sh
go run . # Run
go run . --port 8080 # Run and specify port

go build . # Build binary
go test ./... # Test

docker build -t 117503445/go_webdav . # Build Docker image
```
11 changes: 10 additions & 1 deletion internal/server/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ func NewHandler(cfg *HandlerConfig) *handler {
}

func (h *handler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
enableBasicAuth := h.username != ""
enableBasicAuth := h.username != "" && h.username != "null"
if enableBasicAuth {
username, password, ok := req.BasicAuth()
// log.Debug().Str("username", username).Str("password", password).Bool("ok", ok).Msg("BasicAuth Request")
Expand Down Expand Up @@ -148,6 +148,15 @@ func checkHandlerConfigs(cfgs []*HandlerConfig) error {
}
}

if len(cfgs) > 1 {
for _, cfg := range cfgs {
if cfg.Prefix == "/" {
return errors.New("prefix / is not allowed if there are more than one handler")
}
}
}

// check if prefix is duplicated
prefixs := make(map[string]bool)
for _, cfg := range cfgs {
if _, ok := prefixs[cfg.Prefix]; ok {
Expand Down
12 changes: 12 additions & 0 deletions internal/server/handler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,18 @@ func TestHandlerConfigs(t *testing.T) {
},
},
false,
}, {
[]*HandlerConfig{
{
Prefix: "/",
PathDir: wd,
},
{
Prefix: "/data1",
PathDir: wd,
},
},
false,
},
}

Expand Down
16 changes: 10 additions & 6 deletions internal/server/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,14 +44,18 @@ func NewWebDAVServer(addr string, handlerConfigs []*HandlerConfig) (*WebDAVServe
}
}

// create a webdav.Handler for listing all available prefixes
memFileSystem := webdav.NewMemFS()
for _, cfg := range handlerConfigs {
if err := memFileSystem.Mkdir(context.TODO(), cfg.Prefix, os.ModeDir); err != nil {
log.Error().Err(err).Str("prefix", cfg.Prefix).Msg("Failed to create directory in memFileSystem")
continue
var memFileSystem webdav.FileSystem
if !enableSingleDavMode {
// create a webdav.Handler for listing all available prefixes
memFileSystem = webdav.NewMemFS()
for _, cfg := range handlerConfigs {
if err := memFileSystem.Mkdir(context.TODO(), cfg.Prefix, os.ModeDir); err != nil {
log.Error().Err(err).Str("prefix", cfg.Prefix).Msg("Failed to create directory in memFileSystem")
continue
}
}
}

indexHandler := &webdav.Handler{
FileSystem: memFileSystem,
LockSystem: webdav.NewMemLS(),
Expand Down

0 comments on commit 1f45321

Please sign in to comment.