func (rh *RootHandler) serveDiscovery(rw http.ResponseWriter, req *http.Request) { m := map[string]interface{}{ "blobRoot": rh.BlobRoot, "searchRoot": rh.SearchRoot, "ownerName": rh.OwnerName, "username": rh.Username, "statusRoot": rh.statusRoot, "wsAuthToken": auth.ProcessRandom(), "thumbVersion": images.ThumbnailVersion(), } if gener, ok := rh.Storage.(blobserver.Generationer); ok { initTime, gen, err := gener.StorageGeneration() if err != nil { m["storageGenerationError"] = err.Error() } else { m["storageInitTime"] = initTime.UTC().Format(time.RFC3339) m["storageGeneration"] = gen } } else { log.Printf("Storage type %T is not a blobserver.Generationer; not sending storageGeneration", rh.Storage) } if rh.ui != nil { rh.ui.populateDiscoveryMap(m) } if len(rh.sync) > 0 { var syncHandlers []map[string]interface{} for _, sh := range rh.sync { syncHandlers = append(syncHandlers, sh.discoveryMap()) } m["syncHandlers"] = syncHandlers } discoveryHelper(rw, req, m) }
func (rh *RootHandler) serveDiscovery(rw http.ResponseWriter, req *http.Request) { d := &camtypes.Discovery{ BlobRoot: rh.BlobRoot, JSONSignRoot: rh.JSONSignRoot, HelpRoot: rh.helpRoot, ImporterRoot: rh.importerRoot, SearchRoot: rh.SearchRoot, ShareRoot: rh.shareRoot, StatusRoot: rh.statusRoot, OwnerName: rh.OwnerName, UserName: rh.Username, AuthToken: auth.DiscoveryToken(), ThumbVersion: images.ThumbnailVersion(), } if gener, ok := rh.Storage.(blobserver.Generationer); ok { initTime, gen, err := gener.StorageGeneration() if err != nil { d.StorageGenerationError = err.Error() } else { d.StorageInitTime = types.Time3339(initTime) d.StorageGeneration = gen } } else { log.Printf("Storage type %T is not a blobserver.Generationer; not sending storageGeneration", rh.Storage) } if rh.ui != nil { d.UIDiscovery = rh.ui.discovery() } if rh.sigh != nil { d.Signing = rh.sigh.Discovery(rh.JSONSignRoot) } if len(rh.sync) > 0 { syncHandlers := make([]camtypes.SyncHandlerDiscovery, 0, len(rh.sync)) for _, sh := range rh.sync { syncHandlers = append(syncHandlers, sh.discovery()) } d.SyncHandlers = syncHandlers } discoveryHelper(rw, req, d) }
// returns a path relative to the UI handler. // // Locking: requires that DescribedRequest is done loading or that // Request.mu is held (as it is from metaMap) func (b *DescribedBlob) thumbnail(thumbSize int) (path string, width, height int, ok bool) { if thumbSize <= 0 || !b.isPermanode() { return } if b.Stub { return "node.png", thumbSize, thumbSize, true } if b.Permanode.IsContainer() { return "folder.png", thumbSize, thumbSize, true } if content, ok := b.ContentRef(); ok { peer := b.peerBlob(content) if peer.File != nil { if peer.File.IsImage() { image := fmt.Sprintf("thumbnail/%s/%s?mh=%d&tv=%s", peer.BlobRef, url.QueryEscape(peer.File.FileName), thumbSize, images.ThumbnailVersion()) if peer.Image != nil { mw, mh := images.ScaledDimensions( int(peer.Image.Width), int(peer.Image.Height), MaxImageSize, thumbSize) return image, mw, mh, true } return image, thumbSize, thumbSize, true } // TODO: different thumbnails based on peer.File.MIMEType. const fileIconAspectRatio = 260.0 / 300.0 var width = int(math.Floor(float64(thumbSize)*fileIconAspectRatio + 0.5)) return "file.png", width, thumbSize, true } if peer.Dir != nil { return "folder.png", thumbSize, thumbSize, true } } return "node.png", thumbSize, thumbSize, true }
// Key format: "scaled:" + bref + ":" + width "x" + height // where bref is the blobref of the unscaled image. func cacheKey(bref string, width int, height int) string { return fmt.Sprintf("scaled:%v:%dx%d:tv%d", bref, width, height, images.ThumbnailVersion()) }