studio-b12 / gowebdav Goto Github PK
View Code? Open in Web Editor NEWA golang WebDAV client library and command line tool.
License: BSD 3-Clause "New" or "Revised" License
A golang WebDAV client library and command line tool.
License: BSD 3-Clause "New" or "Revised" License
Hello.
I found a bug about authorization.
At requests.go:req(...)
authorization processed after copying headers from WebDAV client to HTTP client, not before. So authorization is impossible.
I created pull request which solves this issue -- #13
I saw that the Type File Struct has a field of ContentType that can be used, but this is just a struct and cannot get the ContentType of the file. Maybe I'm not very familiar with golang and would like to ask how to get it?
type File struct {
path string
name string
contentType string
size int64
modified time.Time
etag string
isdir bool
}
func (f File) ContentType() string {
return f.contentType
}
Supports write file via io.WriteCloser i.e., create a function that returns io.WriteCloser.
Could be as follows:
#63 func (c *Client)CreateWdFile(path string,r io.Reader) (writer io.WriteCloser, err error) {}
Hello, studio-b12!
I use following software:
OS: Windows 10 x64
Golang: 1.10.1
I trying to use your app to connect to my WebDav sever (Apache HTTPS Server), via following commands in cmd
:
set ROOT=mywebdav.lan
set USER=user
set PASSWORD=password
gowebdav -X LS /user
and expect to see my files and folders in /user
folder:
folder-1
folder-2
folder-3
file.txt
but instead I got following:
ReadDir /data/: 401 Unauthorized - PROPFIND /data/
My server works good and I have no problem to connect to it via Google Chrome
.
How can I fix this?
Thanks in advance.
I propose to:
gowebdav
library and its cmd client
godoc
text from README filefix #14 in commit b45378c changed the behaviour of the req()
method. the auth checks were moved from Connect()
to req()
.
how to improve the code to keep the modification inside the client, because it's a client improvement and to keep the request as small as possible.
suggestions and discussion are welcome!
Describe the bug
I discovered a bug in the file upload that has some relation to #20.
When uploading a file to Nextcloud, the command succeeds and exits without any error, but the uploaded file has a size of 0 bytes.
Software
To Reproduce
gowebdav -X PUT /webdav_test.png .\Chart_KAD.PNG
Put: .\Chart_KAD.PNG -> /webdav_test.png`
Apache access log (nextcloud)
80.187.108.153 - - [12/Aug/2020:12:32:26 +0200] "PUT /remote.php/dav/files/RAYs3T/webdav_test.png HTTP/1.1" 401 557
80.187.108.153 - - [12/Aug/2020:12:32:27 +0200] "PUT /remote.php/dav/files/RAYs3T/webdav_test.png HTTP/1.1" 201 -
Expected
The file should upload completly or fail with an error
Additional context
I initially discovered this issue via PhotoPrism (which uses this client for the uploads).
At least one other user is facing the same issue (photoprism/photoprism#443).
I'm sometimes getting this panic when running multiple requests in parallel using a single webdav client:
/usr/local/Cellar/go/1.14.6/libexec/src/runtime/panic.go:1116 +0x72 fp=0xc0001d9448 sp=0xc0001d9418 pc=0x10351d2
runtime.mapassign_faststr(0x1c15400, 0xc00001f0b0, 0x1ce5cd4, 0xd, 0x64)
/usr/local/Cellar/go/1.14.6/libexec/src/runtime/map_faststr.go:291 +0x3de fp=0xc0001d94b0 sp=0xc0001d9448 pc=0x101529e
net/textproto.MIMEHeader.Set(...)
/usr/local/Cellar/go/1.14.6/libexec/src/net/textproto/header.go:22
net/http.Header.Set(...)
/usr/local/Cellar/go/1.14.6/libexec/src/net/http/header.go:37
github.com/studio-b12/gowebdav.(*BasicAuth).Authorize(0xc0005585c0, 0xc00001f0e0, 0x1ce1500, 0x8, 0x1cdc5ce, 0x1)
/Users/jarek/go/pkg/mod/github.com/studio-b12/[email protected]/basicAuth.go:32 +0x1d0 fp=0xc0001d9578 sp=0xc0001d94b0 pc=0x18d1c80
github.com/studio-b12/gowebdav.(*Client).req(0xc00001f0e0, 0x1ce1500, 0x8, 0x1cdc5ce, 0x1, 0x1e96e40, 0xc0002807a0, 0xc0001d97a0, 0x0, 0x0, ...)
/Users/jarek/go/pkg/mod/github.com/studio-b12/[email protected]/requests.go:28 +0x283 fp=0xc0001d9740 sp=0xc0001d9578 pc=0x18d6353
github.com/studio-b12/gowebdav.(*Client).propfind(0xc00001f0e0, 0x1cdc5ce, 0x1, 0x26cdc00, 0x1d1eebf, 0xcb, 0x1acf280, 0xc00028d2f0, 0xc0001d98b0, 0x0, ...)
/Users/jarek/go/pkg/mod/github.com/studio-b12/[email protected]/requests.go:93 +0x114 fp=0xc0001d9808 sp=0xc0001d9740 pc=0x18d7544
github.com/studio-b12/gowebdav.(*Client).ReadDir(0xc00001f0e0, 0x1cdc5ce, 0x1, 0x1cdc5ce, 0x1, 0x1cdc5ce, 0x1, 0xc0002a8520)
/Users/jarek/go/pkg/mod/github.com/studio-b12/[email protected]/client.go:164 +0x1a6 fp=0xc0001d98e8 sp=0xc0001d9808 pc=0x18d2476
Should parallel calls using single webdav client be supported?
A user of Kopia reported this error in kopia/kopia#1509:
Propfind "https://myhost.mydomain.com/kopia/p5f/7be/": http2: Transport: cannot retry err [http2: Transport received Serv
er's graceful shutdown GOAWAY] after Request.Body was written; define Request.GetBody to avoid this error
There appears to be an issue with some proxy servers that force connection closure after receiving the request and Go cannot automatically retry the request unless http.Request.GetBody is set.
Could this be added in gowebdav
?
Hello Collaborators,
can we add the ability to set the CookieJar
of the internal http.Client
of the gowebdav.Client
?
I got proprietary webdav server, which does authentication via kerberos. It is way faster to use the cookie after the initial authentication than to reauthenticate at every request.
I see 3 possibilities to implement this:
provide a SetJar
method for the gowebdav.Client
like this
func (c *Client) SetJar(jar http.CookieJar) {
c.c.Jar = jar
}
expose the internal http.Client
by making the c
field public or add an option to gowebdav.NewClient
so a configured http.Client
for the webdav client to use can be provided.
use the http.DefaultClient
in gowebdav.NewClient
function to initialize the c
field.
I like number 2. with an option to provide a http.Client
best, because it adds the most flexibility. Maybe there is a good reason why the library uses its own clean http.Client
that I don't see right now. In that case I would like number 1 implemented.
Thoughts?
(I can provide the pull request if we reach a decision)
Hello!
When I use Stat()
for retrieve directory last modification time, I got zero-time.
In source code (client.go):
if p.Type.Local == "collection" {
if !strings.HasSuffix(f.path, "/") {
f.path += "/"
}
f.size = 0
f.modified = time.Unix(0, 0) // Why ??
f.isdir = true
} else {
f.size = parseInt64(&p.Size)
f.modified = parseModified(&p.Modified)
f.isdir = false
}
Hello Collaborators,
Describe the bug
401 Authorization error on trying to connect to a WebDAV server with Bearer
type of authentication
Software
To Reproduce
Bearer
type of authentication. I used OwnCloudc.ReadDir("/")
(Any other operation also fails)Expected
No authorization error, the client should be able to connect to the server and execute any operation
Additional context
This seems to be due the fact that only two types of auth: Basic
and Digest
are supported.
I would be willing to work on a PR to add Bearer
authentication support
Here are my points which I have to think more about.
Originally posted by @chripo in #36 (comment)
I wrote an app on Windows using basic authentication, which appears as Go-http-client/2.0 on the server, if run from my developer machine with Go installed, and works well.
On a different machine without Go installed (or on my machine after uninstalling Go) the same client appears as Microsoft-WebDAV-MiniRedir/10.0.16299 on the server, and authentication fails.
I read quite a bit about dynamic linking if using the net package, but right now I am stuck.
hi contributors,
hi folks,
we improved the project in a nice way.
thank you for your work and interest.
most of your commits were picked without a pull requests, this was fine.
please see my modifications as a kind of talking to and with you by source code.
so feel free to review and to improve the source and project.
let's start to review these files
In Read
/ReadStream
no HTTP response code handling is done. The expected behaviour IMO is to promote 404 and similar errors to actual err
responses.
I tried to call ReadStream with header SetHeader("Range", "bytes=10-100"), but it failed because ReadStream only accepts 200 http response code. The response code of range bytes request is 206 (Partial Content).
Line 332 in 3cd755d
I think the above code needs to be revised as follows:
if rs.StatusCode == 200 || rs.StatusCode == 206 {
If we carefully see on following methods:
client.mkcol()
, client.Mkdir()
, client.MkdirAll()
client.copymove()
, client.doCopyMove()
client.Write()
and client.WriteStream()
error
s and returns only status code in the best case.I propose to change this behaviour to allow user of our library to get original error message.
Hello Collaborators,
during testing current version of gowebdav
I notice that client's method WriteStream
does not set request body even if body should be set for current request (for example during uploading non-empty file via gowebdav.exe -X PUT /my_folder/file.txt file.txt
). Also, @chuckwagoncomputing face with this problem too, but he used propfind
request instead.
Software
master
is 008b27eTo Reproduce
gowebdav/cmd/gowebdav
with go build
to get gowebdav.exe
ROOT
-- WebDav Server's URLUSER
-- WebDav Server's usernamePASSWORD
-- WebDav Server's passwordmy_folder
, and your local file to upload located near gowebdav.exe
, named file.txt
and has some text (so actually file's size is not zero).gowebdav.exe -X PUT /my_folder/file.txt file.txt
putty
, web browser
etc), and you will see that file is exist but file's size is zeroExpected
Uploaded file contains body
Actually
Uploaded file does not contains body
Hello Collaborators,
Describe the bug
A short description of what you think the bug is.
Software
To Reproduce
I've started to build a small tool which would allow file syncing via WebDAV. It's not fully ready but at least it allows to scan a folder and create a list of files which should be uploaded. The flow of the program now is the following:
What I observe is enormous RAM usage by my tool (e.g. even if a folder contains files for 1G, it can easily take up to several gigabytes of RAM). I've tried to narrow the scope of the problem and here's what I've got:
I believe there's something wrong with current usage of TeeReader introduced in #b45378c. It looks like persistConn inside of a Transport somehow doesn't allow to collect the unused objects (i.e even if a new file gets uploaded, the data for the old one doesn't get cleared). Unfortunately I'm pretty new to Go and couldn't resolve the issue by myself.
Expected
Well, no memleak
Additional context
Just in case you're curious how do I use gowebdav exactly, here is the tool I'm using.
Please let me know if you need any additional info.
Some webdav servers (like yandex) send 204 status for successful delete operation. On client.go file (line: 195) you can add 204 status. Note: Thanks for this good client.
pw
login: foo
url: https://host.tld/
Hello Collaborators,
Describe the bug
A short description of what you think the bug is.
Software
To Reproduce
Expected
A short description of what you expected to happen.
err:WriteStream xx: 500
Additional context
Add any other context about the problem here.
server is on WSL2 of docker, images is derkades/webdav.
I try to upload a image file
Here is the current version of Connect
function:
// Connect connects to our dav server
func (c *Client) Connect() error {
rs, err := c.options("/")
if err != nil {
return err
}
err = rs.Body.Close()
if err != nil {
return err
}
if rs.StatusCode != 200 || (rs.Header.Get("Dav") == "" && rs.Header.Get("DAV") == "") {
return newPathError("Connect", c.root, rs.StatusCode)
}
return nil
}
but Apache HTTPS Server
does not return Dav
or DAV
header, so application returns following message on any request:
Failed to connect due to: Connect https://mywebdav.me/: 200
Is it bug in library, or wrong settings of Apache HTTPS Server
?
gowebdav
is generally used as a three-party librarie,and we prefer to use the release version rather than the unstable development version
Hello Collaborators,
During testing current version of gowebdav/cmd
I notice that uploaded file has incorrect content if function getStream()
can not find required file to open.
Software
gowebdav/cmd
To Reproduce
gowebdav.exe
with args: -X PUT /webdav_folder/file.txt
Expected
File not found
error returned
Actual
Application uploads file with it's path as content
Hello Collaborators,
Describe the bug
When we want to Propfind a folder which contains folders with "+", the call fails. Due to the QueryUnescape at
https://github.com/studio-b12/gowebdav/blob/master/client.go#L141
the "+" results in a wrong foldername. in this case "lost+found" becomes "lost found".
Not sure what the purpose of QueryUnescape is, but once we remove it, it works just fine.
Software
To Reproduce
Expected
Expected the folder name "lost+found" to stay that way
Hi,
I've run into trouble using this library with a server that returns a Www-Authenticate header of "BASIC" instead of "Basic". This is allowed as per https://tools.ietf.org/html/rfc2617, but the check on Lines 46 and 48 of requests.go does a case-sensitive check against 'Digest' or 'Basic'.
Can this be changed to a case-insensitive match like
strings.Index(strings.ToLower(rs.Header.Get("Www-Authenticate")), "digest")
?
Is there any workaround? I can't see any way to manually specify the authentication method.
Regards,
Wade
Webdav does not require the server to support recursive traversal, but recursive traversal is commonly used in some scenarios, so we should support the walk function for users. just like filepath.Walk()
Hello Collaborators,
Describe the bug
c.Copy() doesn't handle whitespace characters in file/folder names.
Software
To Reproduce
Expected
Spaces should be handled.
Additional context
Add any other context about the problem here.
OS: Windows 10 x64
GO: go1.9.2 windows/amd64
gowebdav: latest version from master
set GOARCH=386
set GOBIN=
set GOEXE=.exe
set GOHOSTARCH=amd64
set GOHOSTOS=windows
set GOOS=windows
set GOPATH=D:\Go\
set GORACE=
set GOROOT=D:\Programs\Go
set GOTOOLDIR=D:\Programs\Go\pkg\tool\windows_amd64
set GCCGO=gccgo
set GO386=sse2
set CC=gcc
set GOGCCFLAGS=-m32 -fmessage-length=0 -fdebug-prefix-map=C:\Users\PC\AppData\Local\Temp\go-build886287271=/tmp/go-build -gno-record-gcc-switches
set CXX=g++
set CGO_ENABLED=0
set CGO_CFLAGS=-g -O2
set CGO_CPPFLAGS=
set CGO_CXXFLAGS=-g -O2
set CGO_FFLAGS=-g -O2
set CGO_LDFLAGS=-g -O2
set PKG_CONFIG=pkg-config
We use http.Do()
method inside c.req()
, and do not check for errors returned. So, it is possible to receive nil
response, and got nil pointer dereference panic
in line 42.
http.Do()
method will return non-nil error
in following cases:
nil
as a poiner to http.Response
, which will force app to panic later.Taking into account the above mentioned, we need to perform error-checking for http.Do()
method results.
Hello Collaborators,
Describe the bug
When using OneDrive as the WebDav server things get weird. In short: The authentication fails because of Microsoft.
Software
To Reproduce
ReadDir()
)Expected
At least an authentication error should be returned. Even better would be support for MS's need to be proprietary.
Additional context
Microsoft (as expected) does not follow industry standards and instead of returning 401
on unauthenticated requests they return 302
to redirect you to the login page. The login page then return a 200
status so the webdav client thinks it is a valid result for the original request. On its own this would not be too bad as you could catch the redirect and handle it like a 401
. But since Microsoft use their own authentication method (MS-PASS with Passport1.4
) you also need a new authenticator.
Hello Collaborators,
From the docs I see there is a support to use DigestAuth, but I couldn't find how exactly am I supposed to pass the credentials for using Digest Auth, I see by default gowebdav uses basic auth. How can I explicitly ask it to use digest auth? Could you provide an example on how to use DigestAuth with gowebdav client?
Software
go version
go version go1.17.1 darwin/amd64
github.com/studio-b12/gowebdav v0.0.0-20230203202212-3282f94193f2
Additional context
I'm trying to upload my HLS content to AWS Elemental MediaPackager
Hello Collaborators,
I am reading a directory using ReadDir API. The contents of the directory are two directories. ReadDir only returns the second directory.
I debugged the code, and the culprit is the following block of code in client.go file
if skipSelf {
skipSelf = false
if p := getProps(r, "200"); p != nil && p.Type.Local == "collection" {
r.Props = nil
return nil
}
return newPathError("ReadDir", path, 405)
}
If I comment out this code, it works as expected. I do not know what this skipSelf thingy is. It does not seem to have it there be necessary when I used it
Software
To Reproduce
Expected
ReadDir should return both dirs.
Additional context
My test file: main.go - you need to add your WebDav Url and username/password.
package main
import (
"log"
"path/filepath"
"github.com/studio-b12/gowebdav"
)
func main() {
root := "xxxx"
user := "yyyy"
password := "zzzz"
c := gowebdav.NewClient(root, user, password)
err := c.Connect()
if err != nil {
log.Fatalf("could not connect %v\n", err)
}
readDir(c, "/")
}
func readDir(c *gowebdav.Client, dpath string) {
fi, err := c.ReadDir(dpath)
if err != nil {
log.Fatalf("could not read dir %v\n", err)
}
for _, file := range fi {
if file.IsDir() {
d := filepath.ToSlash(filepath.Join(dpath, file.Name()))
log.Printf("Directory: %v\n", d)
readDir(c, d)
continue
}
log.Printf("File: %v\n", file.Name())
}
}
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.