From f3e409a15c1722b0a7cb73549511ec4be3e91362 Mon Sep 17 00:00:00 2001 From: Brad Fitzpatrick Date: Sat, 2 Jul 2011 18:29:57 -0700 Subject: [PATCH] publish cleanup Change-Id: I81c5296acf3d3b7951782c5417348952902721cf --- server/go/camlistored/publish.go | 93 +++++++++++++++++++++++++------- 1 file changed, 74 insertions(+), 19 deletions(-) diff --git a/server/go/camlistored/publish.go b/server/go/camlistored/publish.go index dc24c2fb5..d51c22357 100644 --- a/server/go/camlistored/publish.go +++ b/server/go/camlistored/publish.go @@ -23,6 +23,7 @@ import ( "json" "log" "os" + "strings" "camli/blobref" "camli/blobserver" @@ -99,43 +100,97 @@ func newPublishFromConfig(ld blobserver.Loader, conf jsonconfig.Obj) (h http.Han return pub, nil } -func (pub *PublishHandler) ServeHTTP(rw http.ResponseWriter, req *http.Request) { - base := req.Header.Get("X-PrefixHandler-PathBase") - suffix := req.Header.Get("X-PrefixHandler-PathSuffix") +func (pub *PublishHandler) rootPermanode() (*blobref.BlobRef, os.Error) { + // TODO: caching, but this can change over time (though + // probably rare). might be worth a 5 second cache or + // something in-memory? better invalidation story first would + // be nice. + br, err := pub.Search.Index().PermanodeOfSignerAttrValue(pub.Search.Owner(), "camliRoot", pub.RootName) + if err != nil { + log.Printf("Error: publish handler at serving root name %q has no configured permanode: %v", + pub.RootName, err) + } + return br, err +} - pn, err := pub.Search.Index().PermanodeOfSignerAttrValue(pub.Search.Owner(), "camliRoot", pub.RootName) +// resString is the type of the string that follows "/camli/res/" in publish URLs. +type resString string + +func (s resString) None() bool { + return string(s) == "" +} + +// parseRequest splits a path request into its suffix and subresource parts. +// e.g. /blog/foo/camli/res/file/xxx -> ("foo", "file/xxx") +func (pub *PublishHandler) parseRequest(req *http.Request) (suffix string, subres resString) { + suffix, res := req.Header.Get("X-PrefixHandler-PathSuffix"), "" + if s := strings.SplitN(suffix, "/camli/res/", 2); len(s) == 2 { + suffix, res = s[0], s[1] + } + return suffix, resString(res) +} + +func (pub *PublishHandler) lookupPathTarget(root *blobref.BlobRef, suffix string) (*blobref.BlobRef, os.Error) { + path, err := pub.Search.Index().PathLookup(pub.Search.Owner(), root, suffix, nil /* as of now */ ) + if err != nil { + return nil, err + } + if path.Target == nil { + return nil, os.ENOENT + } + return path.Target, nil +} + +func (pub *PublishHandler) ServeHTTP(rw http.ResponseWriter, req *http.Request) { + rootpn, err := pub.rootPermanode() if err != nil { rw.WriteHeader(404) - fmt.Fprintf(rw, "Error: publish handler at base %q, serving root name %q has no configured permanode", - base, pub.RootName) return } + suffix, subres := pub.parseRequest(req) + if req.FormValue("debug") == "1" { - fmt.Fprintf(rw, "I am publish handler at base %q, serving root %q (permanode=%s), suffix %q
", - base, pub.RootName, pn, html.EscapeString(suffix)) + base := req.Header.Get("X-PrefixHandler-PathBase") + fmt.Fprintf(rw, "I am publish handler at base %q, serving root %q (permanode=%s), suffix %q, subreq %q
", + base, pub.RootName, rootpn, html.EscapeString(suffix), html.EscapeString(string(subres))) } - path, err := pub.Search.Index().PathLookup(pub.Search.Owner(), pn, suffix, nil) + target, err := pub.lookupPathTarget(rootpn, suffix) if err != nil { - fmt.Fprintf(rw, "Error: %v", err) - return - } - if req.FormValue("debug") == "1" { - fmt.Fprintf(rw, "

Target: %s

", path.Target, path.Target) + if err == os.ENOENT { + rw.WriteHeader(404) + return + } + log.Printf("Error looking up %s/%q: %v", rootpn, suffix, err) + rw.WriteHeader(500) return } + if req.FormValue("debug") == "1" { + fmt.Fprintf(rw, "

Target: %s

", target, target) + return + } + + switch { + case subres.None(): + pub.serveHtmlDescribe(rw, req, target) + default: + rw.WriteHeader(500) + } +} + +func (pub *PublishHandler) serveHtmlDescribe(rw http.ResponseWriter, req *http.Request, subject *blobref.BlobRef) { dr := pub.Search.NewDescribeRequest() - dr.Describe(path.Target, 3) + dr.Describe(subject, 3) res, err := dr.Result() if err != nil { - log.Printf("Errors loading %s, permanode %s: %v, %#v", req.URL, path.Target, err, err) + log.Printf("Errors loading %s, permanode %s: %v, %#v", req.URL, subject, err, err) fmt.Fprintf(rw, "

Errors loading.

") return } - subject := res[path.Target.String()] - title := subject.Title() + subdes := res[subject.String()] + title := subdes.Title() // HTML header + Javascript { @@ -153,7 +208,7 @@ func (pub *PublishHandler) ServeHTTP(rw http.ResponseWriter, req *http.Request) fmt.Fprintf(rw, "

%s

\n", html.EscapeString(title)) } - if members := subject.Members(); len(members) > 0 { + if members := subdes.Members(); len(members) > 0 { fmt.Fprintf(rw, "