mirror of
https://github.com/1f349/go-webdav.git
synced 2024-12-22 16:24:14 +00:00
sync-collection for client
This commit is contained in:
parent
25df841e2b
commit
9e23289610
@ -99,3 +99,17 @@ type AddressObject struct {
|
|||||||
ETag string
|
ETag string
|
||||||
Card vcard.Card
|
Card vcard.Card
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//SyncQuery is the query struct represents a sync-collection request
|
||||||
|
type SyncQuery struct {
|
||||||
|
DataRequest AddressDataRequest
|
||||||
|
SyncToken string
|
||||||
|
Limit int // <= 0 means unlimited
|
||||||
|
}
|
||||||
|
|
||||||
|
//SyncResponse contains the returned sync-token for next time
|
||||||
|
type SyncResponse struct {
|
||||||
|
SyncToken string
|
||||||
|
Updated []AddressObject
|
||||||
|
Deleted []string
|
||||||
|
}
|
||||||
|
@ -429,3 +429,56 @@ func (c *Client) PutAddressObject(path string, card vcard.Card) (*AddressObject,
|
|||||||
}
|
}
|
||||||
return ao, nil
|
return ao, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SyncCollection do a sync-collection operation on resource(path), it returns a SyncResponse
|
||||||
|
func (c *Client) SyncCollection(path string, query *SyncQuery) (*SyncResponse, error) {
|
||||||
|
var limit *internal.Limit
|
||||||
|
if query.Limit > 0 {
|
||||||
|
limit = &internal.Limit{NResults: uint(query.Limit)}
|
||||||
|
}
|
||||||
|
|
||||||
|
propReq, err := encodeAddressPropReq(&query.DataRequest)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
ms, err := c.ic.SyncCollection(path, query.SyncToken, internal.DepthOne, limit, propReq)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
ret := &SyncResponse{SyncToken: ms.SyncToken}
|
||||||
|
for _, resp := range ms.Responses {
|
||||||
|
p, err := resp.Path()
|
||||||
|
if err != nil {
|
||||||
|
if err, ok := err.(*internal.HTTPError); ok && err.Code == http.StatusNotFound {
|
||||||
|
ret.Deleted = append(ret.Deleted, p)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if p == path || path == fmt.Sprintf("%s/", p) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
var getLastMod internal.GetLastModified
|
||||||
|
if err := resp.DecodeProp(&getLastMod); err != nil && !internal.IsNotFound(err) {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var getETag internal.GetETag
|
||||||
|
if err := resp.DecodeProp(&getETag); err != nil && !internal.IsNotFound(err) {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
o := AddressObject{
|
||||||
|
Path: p,
|
||||||
|
ModTime: time.Time(getLastMod.LastModified),
|
||||||
|
ETag: string(getETag.ETag),
|
||||||
|
}
|
||||||
|
ret.Updated = append(ret.Updated, o)
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret, nil
|
||||||
|
}
|
||||||
|
@ -190,3 +190,25 @@ func (c *Client) Options(path string) (classes map[string]bool, methods map[stri
|
|||||||
methods = parseCommaSeparatedSet(resp.Header["Allow"], true)
|
methods = parseCommaSeparatedSet(resp.Header["Allow"], true)
|
||||||
return classes, methods, nil
|
return classes, methods, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SyncCollection perform a `sync-collection` REPORT operation on a resource
|
||||||
|
func (c *Client) SyncCollection(path, syncToken string, level Depth, limit *Limit, prop *Prop) (*Multistatus, error) {
|
||||||
|
q := SyncCollectionQuery{
|
||||||
|
SyncToken: syncToken,
|
||||||
|
SyncLevel: string(level),
|
||||||
|
Limit: limit,
|
||||||
|
Prop: prop,
|
||||||
|
}
|
||||||
|
|
||||||
|
req, err := c.NewXMLRequest("REPORT", path, &q)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
ms, err := c.DoMultiStatus(req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return ms, nil
|
||||||
|
}
|
||||||
|
@ -93,6 +93,7 @@ type Multistatus struct {
|
|||||||
XMLName xml.Name `xml:"DAV: multistatus"`
|
XMLName xml.Name `xml:"DAV: multistatus"`
|
||||||
Responses []Response `xml:"response"`
|
Responses []Response `xml:"response"`
|
||||||
ResponseDescription string `xml:"responsedescription,omitempty"`
|
ResponseDescription string `xml:"responsedescription,omitempty"`
|
||||||
|
SyncToken string `xml:"sync-token,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewMultistatus(resps ...Response) *Multistatus {
|
func NewMultistatus(resps ...Response) *Multistatus {
|
||||||
@ -396,3 +397,18 @@ type Set struct {
|
|||||||
XMLName xml.Name `xml:"DAV: set"`
|
XMLName xml.Name `xml:"DAV: set"`
|
||||||
Prop Prop `xml:"prop"`
|
Prop Prop `xml:"prop"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// https://tools.ietf.org/html/rfc6578#section-6.1
|
||||||
|
type SyncCollectionQuery struct {
|
||||||
|
XMLName xml.Name `xml:"DAV: sync-collection"`
|
||||||
|
SyncToken string `xml:"sync-token"`
|
||||||
|
Limit *Limit `xml:"limit,omitempty"`
|
||||||
|
SyncLevel string `xml:"sync-level"`
|
||||||
|
Prop *Prop `xml:"prop"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://tools.ietf.org/html/rfc5323#section-5.17
|
||||||
|
type Limit struct {
|
||||||
|
XMLName xml.Name `xml:"DAV: limit"`
|
||||||
|
NResults uint `xml:"nresults"`
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user