diff --git a/rest/dav/prop.go b/rest/dav/prop.go index 01f3068..3b3bf8b 100644 --- a/rest/dav/prop.go +++ b/rest/dav/prop.go @@ -6,12 +6,12 @@ package dav import ( "bytes" - "context" "errors" "fmt" "io" "net/http" "tank/rest/dav/xml" + "tank/rest/result" ) // Proppatch describes a property update instruction as defined in RFC 4918. @@ -100,26 +100,6 @@ func EscapeXML(s string) string { -// ContentTyper is an optional interface for the os.FileInfo -// objects returned by the FileSystem. -// -// If this interface is defined then it will be used to read the -// content type from the object. -// -// If this interface is not defined the file will be opened and the -// content type will be guessed from the initial contents of the file. -type ContentTyper interface { - // ContentType returns the content type for the file. - // - // If this returns error ErrNotImplemented then the error will - // be ignored and the base implementation will be used - // instead. - ContentType(ctx context.Context) (string, error) -} - - - - // http://www.webdav.org/specs/rfc4918.html#status.code.extensions.to.http11 const ( StatusMulti = 207 @@ -245,33 +225,37 @@ type Propfind struct { } //从request中读出需要的属性。比如:getcontentlength 大小 creationdate 创建时间 -func ReadPropfind(reader io.Reader) (propfind Propfind, status int, err error) { +func ReadPropfind(reader io.Reader) (propfind *Propfind) { + propfind = &Propfind{} + c := CountingReader{reader: reader} - if err = xml.NewDecoder(&c).Decode(&propfind); err != nil { + if err := xml.NewDecoder(&c).Decode(&propfind); err != nil { if err == io.EOF { if c.n == 0 { // An empty body means to propfind allprop. // http://www.webdav.org/specs/rfc4918.html#METHOD_PROPFIND - return Propfind{Allprop: new(struct{})}, 0, nil + return &Propfind{Allprop: new(struct{})} } err = errInvalidPropfind } - return Propfind{}, http.StatusBadRequest, err + + panic(result.BadRequest(err.Error())) } if propfind.Allprop == nil && propfind.Include != nil { - return Propfind{}, http.StatusBadRequest, errInvalidPropfind + panic(result.BadRequest(errInvalidPropfind.Error())) } if propfind.Allprop != nil && (propfind.Prop != nil || propfind.Propname != nil) { - return Propfind{}, http.StatusBadRequest, errInvalidPropfind + panic(result.BadRequest(errInvalidPropfind.Error())) } if propfind.Prop != nil && propfind.Propname != nil { - return Propfind{}, http.StatusBadRequest, errInvalidPropfind + panic(result.BadRequest(errInvalidPropfind.Error())) } if propfind.Propname == nil && propfind.Allprop == nil && propfind.Prop == nil { - return Propfind{}, http.StatusBadRequest, errInvalidPropfind + panic(result.BadRequest(errInvalidPropfind.Error())) } - return propfind, 0, nil + + return propfind } // Property represents a single DAV resource property as defined in RFC 4918. @@ -395,16 +379,16 @@ type MultiStatusWriter struct { // first, valid response to be written, Write prepends the XML representation // of r with a multistatus tag. Callers must call close after the last response // has been written. -func (this *MultiStatusWriter) Write(r *Response) error { - switch len(r.Href) { +func (this *MultiStatusWriter) Write(response *Response) error { + switch len(response.Href) { case 0: return errInvalidResponse case 1: - if len(r.Propstat) > 0 != (r.Status == "") { + if len(response.Propstat) > 0 != (response.Status == "") { return errInvalidResponse } default: - if len(r.Propstat) > 0 || r.Status == "" { + if len(response.Propstat) > 0 || response.Status == "" { return errInvalidResponse } } @@ -412,7 +396,7 @@ func (this *MultiStatusWriter) Write(r *Response) error { if err != nil { return err } - return this.Encoder.Encode(r) + return this.Encoder.Encode(response) } // writeHeader writes a XML multistatus start element on w's underlying diff --git a/rest/dav_service.go b/rest/dav_service.go index 990b62d..19e10c6 100644 --- a/rest/dav_service.go +++ b/rest/dav_service.go @@ -11,11 +11,13 @@ import ( "tank/rest/dav/xml" ) + /** * * WebDav协议文档 * https://tools.ietf.org/html/rfc4918 * 主要参考 golang.org/x/net/webdav + * 测试机:http://www.webdav.org/neon/litmus/ */ //@Service type DavService struct { @@ -129,7 +131,7 @@ func (this *DavService) AllPropXmlNames(matter *Matter) []xml.Name { } //从一个matter中获取其 []dav.Propstat -func (this *DavService) Propstats(user *User, matter *Matter, propfind dav.Propfind) []dav.Propstat { +func (this *DavService) Propstats(user *User, matter *Matter, propfind *dav.Propfind) []dav.Propstat { propstats := make([]dav.Propstat, 0) if propfind.Propname != nil { @@ -158,8 +160,7 @@ func (this *DavService) HandlePropfind(writer http.ResponseWriter, request *http depth := this.ParseDepth(request) //读取请求参数。按照用户的参数请求返回内容。 - propfind, _, err := dav.ReadPropfind(request.Body) - this.PanicError(err) + propfind := dav.ReadPropfind(request.Body) //寻找符合条件的matter. //如果是空或者/就是请求根目录 @@ -177,7 +178,7 @@ func (this *DavService) HandlePropfind(writer http.ResponseWriter, request *http } //准备一个输出结果的Writer - multiStatusWriter := dav.MultiStatusWriter{Writer: writer} + multiStatusWriter := &dav.MultiStatusWriter{Writer: writer} for _, matter := range matters { @@ -187,12 +188,12 @@ func (this *DavService) HandlePropfind(writer http.ResponseWriter, request *http path := fmt.Sprintf("%s%s", WEBDAV_PREFFIX, matter.Path) response := this.makePropstatResponse(path, propstats) - err = multiStatusWriter.Write(response) + err := multiStatusWriter.Write(response) this.PanicError(err) } //闭合 - err = multiStatusWriter.Close() + err := multiStatusWriter.Close() this.PanicError(err) fmt.Printf("%v %v \n", subPath, propfind.Prop) diff --git a/rest/logger.go b/rest/logger.go index 6c35923..c913d76 100644 --- a/rest/logger.go +++ b/rest/logger.go @@ -122,7 +122,8 @@ func (this *Logger) openFile() { panic("日志文件无法正常打开: " + err.Error()) } - this.goLogger = log.New(f, "", log.Ltime) + this.goLogger = log.New(f, "", log.LstdFlags|log.Lshortfile) + this.file = f } diff --git a/rest/test/dav_test.go b/rest/test/dav_test.go index f7376e9..5e0c9fc 100644 --- a/rest/test/dav_test.go +++ b/rest/test/dav_test.go @@ -8,7 +8,7 @@ import ( "time" ) -func TestReadPropfind(t *testing.T) { +func TestXmlDecoder(t *testing.T) { propfind := &dav.Propfind{} @@ -46,7 +46,55 @@ func TestReadPropfind(t *testing.T) { for k, v := range resultMap { if !v { - t.Errorf("index = %s error", k) + t.Errorf(" %s error", k) + } + } + + t.Logf("[%v] pass!", time.Now()) + +} + +func TestXmlEncoder(t *testing.T) { + + writer := &bytes.Buffer{} + + response := &dav.Response{ + XMLName: xml.Name{Space: "DAV:", Local: "response"}, + Href: []string{"/api/dav"}, + Propstat: []dav.SubPropstat{ + { + Prop: []dav.Property{ + { + XMLName: xml.Name{Space: "DAV:", Local: "resourcetype"}, + InnerXML: []byte(``), + }, + { + XMLName: xml.Name{Space: "DAV:", Local: "getlastmodified"}, + InnerXML: []byte(`Mon, 22 Apr 2019 06:38:36 GMT`), + }, + }, + Status: "HTTP/1.1 200 OK", + }, + }, + } + + err := xml.NewEncoder(writer).Encode(response) + + if err != nil { + t.Error(err.Error()) + } + + bs := writer.Bytes() + + str := string(bs) + + resultMap := make(map[string]bool) + + resultMap["equal"] = str == `/api/davMon, 22 Apr 2019 06:38:36 GMTHTTP/1.1 200 OK` + + for k, v := range resultMap { + if !v { + t.Errorf("%s error", k) } }