From ba7b63204667e8f9bd0bee89cae0f2da842d2cb1 Mon Sep 17 00:00:00 2001 From: zicla Date: Wed, 17 Apr 2019 22:26:13 +0800 Subject: [PATCH] Try to fix the xml things. --- main_test.go | 129 +++++++++++++++++++++++++++++++++++++++++ rest/dav/webdav.go | 4 +- rest/dav/xml_test.go | 2 +- rest/dav_controller.go | 21 +++++-- rest/dav_model.go | 33 +++++++++++ rest/dav_service.go | 62 ++++++++++++++++++++ rest/matter_dao.go | 20 +++++++ 7 files changed, 263 insertions(+), 8 deletions(-) create mode 100644 main_test.go create mode 100644 rest/dav_model.go diff --git a/main_test.go b/main_test.go new file mode 100644 index 0000000..c45ebf5 --- /dev/null +++ b/main_test.go @@ -0,0 +1,129 @@ +package main + +import ( + "encoding/xml" + "fmt" + "tank/rest" + "testing" +) + +func TestXmlMarshal(t *testing.T) { + fmt.Println("Hello World!") + + type Address struct { + City, State string + } + type Person struct { + XMLName xml.Name `xml:"person"` + Id int `xml:"id,attr"` + FirstName string `xml:"name>first"` + LastName string `xml:"name>last"` + Age int `xml:"age"` + Height float32 `xml:"height,omitempty"` + Married bool + Address + Comment string `xml:",comment"` + } + + v := &Person{Id: 13, FirstName: "John", LastName: "Doe", Age: 42} + v.Comment = " Need more details. " + v.Address = Address{"Hanga Roa", "Easter Island"} + + output, err := xml.MarshalIndent(v, " ", " ") + if err != nil { + fmt.Printf("error: %v\n", err) + } + + fmt.Println(string(output)) + // Output: + // + // + // John + // Doe + // + // 42 + // false + // Hanga Roa + // Easter Island + // + // + +} + +func TestXmlUnMarshal(t *testing.T) { + type Email struct { + Where string `xml:"where,attr"` + Addr string + } + type Address struct { + City, State string + } + type Result struct { + XMLName xml.Name `xml:"Person"` + Name string `xml:"FullName"` + Phone string + Email []Email + Groups []string `xml:"Group>Value"` + Address + } + v := Result{Name: "none", Phone: "none"} + + data := ` + + Grace R. Emlin + Example Inc. + + gre@example.com + + + gre@work.com + + + Friends + Squash + + Hanga Roa + Easter Island + + ` + err := xml.Unmarshal([]byte(data), &v) + if err != nil { + fmt.Printf("error: %v", err) + return + } + fmt.Printf("XMLName: %#v\n", v.XMLName) + fmt.Printf("Name: %q\n", v.Name) + fmt.Printf("Phone: %q\n", v.Phone) + fmt.Printf("Email: %v\n", v.Email) + fmt.Printf("Groups: %v\n", v.Groups) + fmt.Printf("Address: %v\n", v.Address) + // Output: + // XMLName: xml.Name{Space:"", Local:"Person"} + // Name: "Grace R. Emlin" + // Phone: "none" + // Email: [{home gre@example.com} {work gre@work.com}] + // Groups: [Friends Squash] + // Address: {Hanga Roa Easter Island} +} + +func TestPropfind(t *testing.T) { + data := ` + + + + + + + + + + ` + propfind := &rest.Propfind{XmlNS: "DAV:"} + err := xml.Unmarshal([]byte(data), &propfind) + if err != nil { + panic(err) + } + + output, err := xml.MarshalIndent(propfind, " ", " ") + fmt.Println(string(output)) +} diff --git a/rest/dav/webdav.go b/rest/dav/webdav.go index 22ec2bd..28793d4 100644 --- a/rest/dav/webdav.go +++ b/rest/dav/webdav.go @@ -564,7 +564,9 @@ func (this *Handler) handlePropfind(writer http.ResponseWriter, request *http.Re if info.IsDir() { href += "/" } - return multiStatusWriter.write(makePropstatResponse(href, propstats)) + + propstatResponse := makePropstatResponse(href, propstats) + return multiStatusWriter.write(propstatResponse) } walkErr := walkFS(ctx, this.FileSystem, depth, reqPath, fileInfo, walkFn) diff --git a/rest/dav/xml_test.go b/rest/dav/xml_test.go index ca5913b..57f0189 100644 --- a/rest/dav/xml_test.go +++ b/rest/dav/xml_test.go @@ -16,7 +16,7 @@ import ( "strings" "testing" - ixml "golang.org/x/net/webdav/internal/xml" + ixml "tank/rest/dav/internal/xml" ) func TestReadLockInfo(t *testing.T) { diff --git a/rest/dav_controller.go b/rest/dav_controller.go index a51e42f..04186a4 100644 --- a/rest/dav_controller.go +++ b/rest/dav_controller.go @@ -10,8 +10,10 @@ import ( * * WebDav协议文档 * https://tools.ietf.org/html/rfc4918 + * http://www.webdav.org/specs/rfc4918.html * */ + type DavController struct { BaseController uploadTokenDao *UploadTokenDao @@ -90,17 +92,24 @@ func (this *DavController) HandleRoutes(writer http.ResponseWriter, request *htt return nil, false } - //完成系统安装 func (this *DavController) Index(writer http.ResponseWriter, request *http.Request, subPath string) { this.logger.Info("请求访问来了:%s %s", request.RequestURI, subPath) - handler := &dav.Handler{ - FileSystem: dav.Dir("D:/Group/Golang/src/webdav/tmp"), - LockSystem: dav.NewMemLS(), + method := request.Method + if method == "PROPFIND1" { + + this.davService.HandlePropfind(writer, request, subPath) + + } else { + + handler := &dav.Handler{ + FileSystem: dav.Dir("D:/Group/Golang/src/webdav/tmp"), + LockSystem: dav.NewMemLS(), + } + + handler.ServeHTTP(writer, request) } - handler.ServeHTTP(writer, request) - } diff --git a/rest/dav_model.go b/rest/dav_model.go new file mode 100644 index 0000000..f118216 --- /dev/null +++ b/rest/dav_model.go @@ -0,0 +1,33 @@ +package rest + +import ( + "encoding/xml" +) + +/** + * + * WebDav协议文档 + * https://tools.ietf.org/html/rfc4918 + * http://www.webdav.org/specs/rfc4918.html + * + */ + +const ( + //有多少层展示多少层 + INFINITE_DEPTH = -1 +) + +// http://www.webdav.org/specs/rfc4918.html#ELEMENT_propfind +//PROPFIND方法请求时POST BODY入参 +type Propfind struct { + XMLName xml.Name `xml:"D:propfind"` + XmlNS string `xml:"xmlns:D,attr"` + + Allprop *struct{} `xml:"D:allprop"` + Propname *struct{} `xml:"D:propname"` + Prop PropfindProps `xml:"D:prop"` + Include PropfindProps `xml:"D:include"` +} + +// http://www.webdav.org/specs/rfc4918.html#ELEMENT_prop (for propfind) +type PropfindProps []xml.Name diff --git a/rest/dav_service.go b/rest/dav_service.go index 6618ca2..8d2e54c 100644 --- a/rest/dav_service.go +++ b/rest/dav_service.go @@ -1,6 +1,18 @@ package rest +import ( + "encoding/xml" + "fmt" + "io/ioutil" + "net/http" +) +/** + * + * WebDav协议文档 + * https://tools.ietf.org/html/rfc4918 + * + */ //@Service type DavService struct { Bean @@ -17,3 +29,53 @@ func (this *DavService) Init() { this.matterDao = b } } + +//从request中读取深度 +func (this *DavService) readDepth(request *http.Request) int { + + depth := INFINITE_DEPTH + if hdr := request.Header.Get("Depth"); hdr != "" { + if hdr == "0" { + depth = 0 + } else if hdr == "1" { + depth = 1 + } else if hdr == "infinity" { + depth = INFINITE_DEPTH + } else { + panic("Depth格式错误!") + } + } + return depth +} + +//处理 方法 +func (this *DavService) HandlePropfind(writer http.ResponseWriter, request *http.Request, subPath string) { + + //获取请求者 + user := this.checkUser(writer, request) + + //读取希望访问的深度。 + depth := this.readDepth(request) + + //找寻请求的目录 + matter := this.matterDao.checkByUserUuidAndPath(user.Uuid, subPath) + + //TODO: 读取请求参数。按照用户的参数请求返回内容。 + propfind := &Propfind{} + body, err := ioutil.ReadAll(request.Body) + this.PanicError(err) + + //从xml中解析内容到struct + err = xml.Unmarshal(body, &propfind) + this.PanicError(err) + + //从struct还原到xml + output, err := xml.MarshalIndent(propfind, " ", " ") + this.PanicError(err) + fmt.Println(string(output)) + + + + fmt.Printf("%v %v \n", depth, matter.Name) + +} diff --git a/rest/matter_dao.go b/rest/matter_dao.go index a9ab0d7..550b2fc 100644 --- a/rest/matter_dao.go +++ b/rest/matter_dao.go @@ -283,6 +283,26 @@ func (this *MatterDao) SizeBetweenTime(startTime time.Time, endTime time.Time) i return size } +//根据userUuid和path来查找 +func (this *MatterDao) checkByUserUuidAndPath(userUuid string, path string) *Matter { + + var wp = &WherePair{Query: "user_uuid = ? AND path = ?", Args: []interface{}{userUuid, path}} + + var matter = &Matter{} + db := CONTEXT.DB.Model(&Matter{}).Where(wp.Query, wp.Args...).First(matter) + + + if db.Error != nil { + if db.Error.Error() == DB_ERROR_NOT_FOUND { + this.PanicNotFound("%s 不存在", path) + } else { + this.PanicError(db.Error) + } + } + + return matter +} + //执行清理操作 func (this *MatterDao) Cleanup() { this.logger.Info("[MatterDao]执行清理:清除数据库中所有Matter记录。删除磁盘中所有Matter文件。")