blob info page

This commit is contained in:
Brad Fitzpatrick 2011-05-30 16:41:56 -07:00
parent a3dc3f3ad7
commit 335f3187a8
6 changed files with 174 additions and 36 deletions

View File

@ -143,18 +143,19 @@ func (sh *searchHandler) serveDescribe(rw http.ResponseWriter, req *http.Request
}
mime, size, err := sh.index.GetBlobMimeType(br)
if err != nil {
// TODO: special error value for not found
ret["errorText"] = err.String()
} else {
m := dmap(br)
setMimeType(m, mime)
m["size"] = size
if err != os.ENOENT {
if err != nil {
ret["errorText"] = err.String()
} else {
m := dmap(br)
setMimeType(m, mime)
m["size"] = size
if mime == "application/json; camliType=permanode" {
pm := make(jsonMap)
m["permanode"] = pm
sh.populatePermanodeFields(pm, br, sh.owner, dmap)
if mime == "application/json; camliType=permanode" {
pm := make(jsonMap)
m["permanode"] = pm
sh.populatePermanodeFields(pm, br, sh.owner, dmap)
}
}
}

View File

@ -133,6 +133,10 @@ func wantsPermanode(req *http.Request) bool {
return req.Method == "GET" && blobref.Parse(req.FormValue("p")) != nil
}
func wantsBlobInfo(req *http.Request) bool {
return req.Method == "GET" && blobref.Parse(req.FormValue("b")) != nil
}
func (ui *UIHandler) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
base := req.Header.Get("X-PrefixHandler-PathBase")
suffix := req.Header.Get("X-PrefixHandler-PathSuffix")
@ -147,13 +151,18 @@ func (ui *UIHandler) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
file := ""
if m := staticFilePattern.FindStringSubmatch(suffix); m != nil {
file = m[1]
} else if wantsPermanode(req) {
file = "permanode.html"
} else if req.URL.Path == base {
file = "index.html"
} else {
http.Error(rw, "Illegal URL.", 404)
return
switch {
case wantsPermanode(req):
file = "permanode.html"
case wantsBlobInfo(req):
file = "blobinfo.html"
case req.URL.Path == base:
file = "index.html"
default:
http.Error(rw, "Illegal URL.", 404)
return
}
}
http.ServeFile(rw, req, filepath.Join(ui.FilesDir, file))
}

View File

@ -0,0 +1,16 @@
<html>
<head>
<title>Blob</title>
<script type="text/javascript" src="camli.js"></script>
<script type="text/javascript" src="?camli.mode=config&cb=onConfiguration"></script>
<script type="text/javascript" src="blobinfo.js"></script>
</head>
<body>
<h1>Blob Search Metadata</h1>
<pre id="blobpre"></pre>
<h1>Blob Contents</h1>
<pre id="blobdata" style="overflow: auto; max-width: 800px"></pre>
</body>
</html>

View File

@ -0,0 +1,74 @@
/*
Copyright 2011 Google Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Gets the |p| query parameter, assuming that it looks like a blobref.
function getBlobParam() {
var blobRef = getQueryParam('b');
return (blobRef && isPlausibleBlobRef(blobRef)) ? blobRef : null;
}
function blobInfoUpdate(bmap) {
var blobpre = document.getElementById('blobpre');
var blobref = getBlobParam();
if (!blobref) {
alert("no blobref?");
return;
}
var binfo = bmap[blobref];
if (!binfo) {
blobpre.innerHTML = "(not found)";
return;
}
blobpre.innerHTML = JSON.stringify(binfo, null, 2);
if (binfo.camliType) {
camliGetBlobContents(
blobref,
{
success: function(data) {
document.getElementById("blobdata").innerHTML = linkifyBlobRefs(data);
},
fail: alert
});
} else {
document.getElementById("blobdata").innerHTML = "Unknown/binary data; <a href='" + camliBlobUrl(blobref) + "'>download</a>";
}
}
function linkifyBlobRefs(schemaBlob) {
var re = /(\w{3,6}-[a-f0-9]{30,})/g;
return schemaBlob.replace(re, "<a href='./?b=$1'>$1</a>");
}
function blobInfoOnLoad() {
var blobref = getBlobParam();
if (!blobref) {
return
}
var blobpre = document.getElementById('blobpre');
blobpre.innerText = "(loading)";
camliDescribeBlob(
blobref,
{
success: blobInfoUpdate,
fail: function(msg) {
alert("Error describing blob " + blobref + ": " + msg);
}
}
);
}
window.addEventListener("load", blobInfoOnLoad);

View File

@ -60,6 +60,45 @@ function camliSigDiscovery(opts) {
xhr.send();
}
function camliDescribeBlob(blobref, opts) {
opts = saneOpts(opts);
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function() {
if (xhr.readyState != 4) { return; }
if (xhr.status != 200) {
opts.fail("got HTTP status " + xhr.status);
return;
}
var jres;
try {
jres = JSON.parse(xhr.responseText);
} catch (x) {
opts.fail("JSON parse error");
return;
}
opts.success(jres);
};
var path = disco.searchRoot + "camli/search/describe?blobref=" + blobref;
xhr.open("GET", path, true);
xhr.send();
}
function camliGetBlobContents(blobref, opts) {
opts = saneOpts(opts);
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function() {
if (xhr.readyState != 4) { return; }
if (xhr.status != 200) {
opts.fail("got HTTP status " + xhr.status);
return;
}
opts.success(xhr.responseText);
};
var path = disco.blobRoot + "camli/" + blobref;
xhr.open("GET", path, true);
xhr.send();
}
function camliSign(clearObj, opts) {
opts = saneOpts(opts);
@ -160,3 +199,19 @@ function camliCreateNewPermanode(opts) {
});
}
// Returns the first value from the query string corresponding to |key|.
// Returns null if the key isn't present.
function getQueryParam(key) {
var params = document.location.search.substring(1).split('&');
for (var i = 0; i < params.length; ++i) {
var parts = params[i].split('=');
if (parts.length == 2 && decodeURIComponent(parts[0]) == key)
return decodeURIComponent(parts[1]);
}
return null;
}
// Returns true if the passed-in string might be a blobref.
function isPlausibleBlobRef(blobRef) {
return /^\w+-[a-f0-9]+$/.test(blobRef);
}

View File

@ -14,27 +14,10 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
// Returns the first value from the query string corresponding to |key|.
// Returns null if the key isn't present.
function getQueryParam(key) {
var params = document.location.search.substring(1).split('&');
for (var i = 0; i < params.length; ++i) {
var parts = params[i].split('=');
if (parts.length == 2 && decodeURIComponent(parts[0]) == key)
return decodeURIComponent(parts[1]);
}
return null;
}
// Returns true if the passed-in string might be a blobref.
function isPlausibleBlobRef(blobRef) {
return /^\w+-[a-f0-9]+$/.test(blobRef);
}
// Gets the |p| query parameter, assuming that it looks like a blobref.
function getPermanodeParam() {
var blobRef = getQueryParam('p');
return (blobRef && isPlausibleBlobRef(blobRef)) ? blobRef : null;
var blobRef = getQueryParam('p');
return (blobRef && isPlausibleBlobRef(blobRef)) ? blobRef : null;
}
window.addEventListener("load", function (e) {