diff --git a/server/go/camlistored/camlistored.go b/server/go/camlistored/camlistored.go index b6f83cb8e..fe6ac8e92 100644 --- a/server/go/camlistored/camlistored.go +++ b/server/go/camlistored/camlistored.go @@ -279,6 +279,8 @@ func configFileMain() { installHandler(createRootHandler) case handlerType == "ui": installHandler(createUIHandler) + case handlerType == "jsonsign": + installHandler(createJSONSignHandler) default: // Assume a storage interface pstorage, err := blobserver.CreateStorage(handlerType, jsonconfig.Obj(handlerArgs)) diff --git a/server/go/camlistored/sig.go b/server/go/camlistored/sig.go new file mode 100644 index 000000000..b407329fe --- /dev/null +++ b/server/go/camlistored/sig.go @@ -0,0 +1,41 @@ +/* +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. +*/ + +package main + +import ( + "http" + "os" + + "camli/jsonconfig" +) + +type JSONSignHandler struct { +} + +func createJSONSignHandler(conf jsonconfig.Obj) (http.Handler, os.Error) { + h := &JSONSignHandler{} + //h.Stealth = conf.OptionalBool("stealth", false) + if err := conf.Validate(); err != nil { + return nil, err + } + return h, nil +} + +func (h *JSONSignHandler) ServeHTTP(conn http.ResponseWriter, req *http.Request) { + // TODO +} + diff --git a/server/go/camlistored/ui.go b/server/go/camlistored/ui.go index a7ec095e3..41a8df8f7 100644 --- a/server/go/camlistored/ui.go +++ b/server/go/camlistored/ui.go @@ -27,15 +27,17 @@ import ( "camli/jsonconfig" ) -var staticFilePattern = regexp.MustCompile(`/([a-z0-9\-\_]+\.(html|js|css|png|jpg|gif))$`) +var staticFilePattern = regexp.MustCompile(`/static/([a-zA-Z0-9\-\_]+\.(html|js|css|png|jpg|gif))$`) +var identPattern = regexp.MustCompile(`^[a-zA-Z\_]+$`) // UIHandler handles serving the UI and discovery JSON. type UIHandler struct { // URL prefixes (path or full URL) to the primary blob and // search root. Only used by the UI and thus necessary if UI // is true. - BlobRoot string - SearchRoot string + BlobRoot string + SearchRoot string + JSONSignRoot string FilesDir string } @@ -47,8 +49,9 @@ func defaultFilesDir() string { func createUIHandler(conf jsonconfig.Obj) (h http.Handler, err os.Error) { ui := &UIHandler{} - ui.BlobRoot = conf.RequiredString("blobRoot") - ui.SearchRoot = conf.RequiredString("searchRoot") + ui.BlobRoot = conf.OptionalString("blobRoot", "") + ui.SearchRoot = conf.OptionalString("searchRoot", "") + ui.JSONSignRoot = conf.OptionalString("jsonSignRoot", "") ui.FilesDir = conf.OptionalString("staticFiles", defaultFilesDir()) if err = conf.Validate(); err != nil { return @@ -64,18 +67,18 @@ func createUIHandler(conf jsonconfig.Obj) (h http.Handler, err os.Error) { func wantsDiscovery(req *http.Request) bool { return req.Method == "GET" && (req.Header.Get("Accept") == "text/x-camli-configuration" || - req.FormValue("camli.mode") == "config") + req.FormValue("camli.mode") == "config") } func (ui *UIHandler) ServeHTTP(rw http.ResponseWriter, req *http.Request) { rw.Header().Set("Vary", "Accept") switch { case wantsDiscovery(req): - ui.serveDiscovery(rw) + ui.serveDiscovery(rw, req) default: - file := staticFilePattern.FindString(req.URL.Path) - if file != "" { - file = file[1:] + file := "" + if m := staticFilePattern.FindStringSubmatch(req.URL.Path); m != nil { + file = m[1] } else { file = "index.html" } @@ -83,10 +86,20 @@ func (ui *UIHandler) ServeHTTP(rw http.ResponseWriter, req *http.Request) { } } -func (ui *UIHandler) serveDiscovery(rw http.ResponseWriter) { +func (ui *UIHandler) serveDiscovery(rw http.ResponseWriter, req *http.Request) { rw.Header().Set("Content-Type", "text/javascript") - json.NewEncoder(rw).Encode(map[string]interface{}{ - "blobRoot": ui.BlobRoot, - "searchRoot": ui.SearchRoot, - }) + inCb := false + if cb := req.FormValue("cb"); identPattern.MatchString(cb) { + fmt.Fprintf(rw, "%s(", cb) + inCb = true + } + bytes, _ := json.Marshal(map[string]interface{}{ + "blobRoot": ui.BlobRoot, + "searchRoot": ui.SearchRoot, + "jsonSignRoot": ui.JSONSignRoot, + }) + rw.Write(bytes) + if inCb { + rw.Write([]byte{')'}) + } } diff --git a/server/go/camlistored/ui/index.html b/server/go/camlistored/ui/index.html index 7137b8f9c..e896a3757 100644 --- a/server/go/camlistored/ui/index.html +++ b/server/go/camlistored/ui/index.html @@ -1,7 +1,8 @@ Camlistored UI - + +

Camlistored UI

diff --git a/server/go/camlistored/ui/ui.js b/server/go/camlistored/ui/ui.js index 0b3598b63..4401045d4 100644 --- a/server/go/camlistored/ui/ui.js +++ b/server/go/camlistored/ui/ui.js @@ -16,6 +16,13 @@ limitations under the License. var disco = null; +// Method 1 to get discovery information (JSONP style): +function onConfiguration(conf) { + disco = conf; + console.log("Got config: " + JSON.stringify(conf)); +} + +// Or get configuration info like this: function discover() { var xhr = new XMLHttpRequest(); xhr.onreadystatechange = function() {