Merge "Tiny HTTP server that sets CORS header"
authorEric Z <ezavesky@research.att.com>
Thu, 12 Jul 2018 13:25:18 +0000 (13:25 +0000)
committerGerrit Code Review <gerrit@acumos.org>
Thu, 12 Jul 2018 13:25:18 +0000 (13:25 +0000)
docs/tutorials/demonstration.rst
docs/tutorials/example_running.jpg
web_demo/demo-framework.js
web_demo/face-privacy.html
web_demo/protobuf.Image.bin [new file with mode: 0644]
web_demo/protobuf.RegionDetectionSet.bin [new file with mode: 0644]

index 21ce3b1..1904852 100644 (file)
@@ -74,6 +74,19 @@ Afterwards, just point your browser at
 ``http://localhost:5000/face-privacy.html``.
 
 
+Usage of protobuf binaries for testing
+--------------------------------------
+Binary (protobuf encoded) data can be downloaded from the web page or directly with curl.
+Two demonstration binaries have been included in the source repository for testing.
+
+- ``protobuf.Image.bin`` - a protobuf-encoded image of Ellen DeGeneres
+- ``protobuf.RegionDetectionSet.bin`` - a protobuf-encoded region set from the reunion example
+
+Within the webpage demo, simply select the correct protobuf method and then drag and
+drop the binary file into the ``Protobuf Payload Input`` file uploader.  It will be
+immediately uploaded through javascript to your specified ``Transform Url``.
+
+
 Example face privacy demo (docker and protobuf)
 ===============================================
 
index fa5d417..a0e3e92 100644 (file)
Binary files a/docs/tutorials/example_running.jpg and b/docs/tutorials/example_running.jpg differ
index fe11fdb..20bd08b 100644 (file)
@@ -29,6 +29,7 @@
  E. Zavesky 10/19/17 adapted for video+image
  E. Zavesky 05/05/18 adapted for row-based image and other results
  E. Zavesky 05/30/18 adapted for single image input, github preview, safe posting (forked from model-specific code)
+ E. Zavesky 07/11/18 allow proto type grouping, proto text file download, binary chunk upload (as proto)
  */
 
 
@@ -52,10 +53,14 @@ function demo_init(objSetting) {
         maxSrcVideoWidth: 512, // maximum image width for processing
         serverIsLocal: true,    // server is local versus 'firewall' version
         imageIsWaiting: false,  // blocking to prevent too many queued frames
+
         // functional customizations for each demo
         documentTitle: "Protobuf Demo",
         mediaList: [],        //relative URLs of media files
         protoList: [],        //relative URLs of proto files to include
+        domHeaders: { "Content-type": "text/plain;charset=UTF-8" },   //defaults for headers
+        // TODO: should be binary ideally, domHeaders: { "Content-type": "application/octet-stream;charset=UTF-8" },   //defaults for headers
+
         // Objects from DOM elements
         video: document.getElementById('srcVideo'),
         srcImgCanvas: document.getElementById('srcImgCanvas'), // we have a 'src' source image
@@ -66,9 +71,12 @@ function demo_init(objSetting) {
         hd.video.addEventListener("loadedmetadata", newVideo);
     }
 
+    $("#protoSource").prop("disabled",true).click(downloadBlobProto);
     $("#protoInput").prop("disabled",true).click(downloadBlobIn);
     $("#protoOutput").prop("disabled",true).click(downloadBlobOut);
     $("#resultText").hide();
+    $("#protoBinary").change(doPostBinaryFile);
+
 
     //add text input tweak
     $("#serverUrl").change(function() {
@@ -84,6 +92,7 @@ function demo_init(objSetting) {
     hd.protoObj = {};  //clear from last load
     $.each(hd.protoList, function(idx, protoTuple) {     //load relevant protobuf tuples
         protobuf_load.apply(this, protoTuple);      //load each file independently
+        $("#protoSource").prop("disabled",false);
     });
 
     // add buttons to change video
@@ -132,7 +141,10 @@ function protobuf_load(pathProto, forceSelect) {
         var numMethods = domSelect.children().length;
         $.each(root.nested, function(namePackage, objPackage) {    // walk all
             if ('Model' in objPackage && 'methods' in objPackage.Model) {    // walk to model and functions...
-                var typeSummary = {'root':root, 'methods':{} };
+                var typeSummary = {'root':root, 'methods':{}, 'path':pathProto };
+                var fileBase = pathProto.split(/[\\\/]/);       // added 7/11/18 for proto context
+                fileBase = fileBase[fileBase.length - 1];
+                var domGroup = $("<optgroup label='"+fileBase+" - "+namePackage+"' >");
                 $.each(objPackage.Model.methods, function(nameMethod, objMethod) {  // walk methods
                     typeSummary['methods'][nameMethod] = {};
                     typeSummary['methods'][nameMethod]['typeIn'] = namePackage+'.'+objMethod.requestType;
@@ -150,9 +162,10 @@ function protobuf_load(pathProto, forceSelect) {
                     if (forceSelect) {
                         domOpt.attr("selected", 1);
                     }
-                    domSelect.append(domOpt);
+                    domGroup.append(domOpt);
                     numMethods++;
                 });
+                domSelect.append(domGroup);
                 $(document.body).data('hdparams').protoObj[namePackage] = typeSummary;   //save new method set
                 $("#protoContainer").show();
             }
@@ -344,15 +357,11 @@ function doPostImage(srcCanvas, dstDiv, dstImg, imgPlaceholder) {
 
     hd.imageIsWaiting = true;
     var domHeaders = {};
-    dstDiv = $(dstDiv);
-    $("#postSpinner").remove();     //erase previously existing one
-    dstDiv.append($("<div id='postSpinner' class='spinner'>&nbsp;</div>"));
-    if (dstImg)     //convert to jquery dom object
-        dstImg = $(dstImg);
 
     //console.log("[doPostImage]: Selected method ... '"+typeInput+"'");
     if (hd.protoKeys) {     //valid protobuf type?
         var blob = dataURItoBlob(dataURL, true);
+        domHeaders = $.extend({}, hd.domHeaders);       //rewrite with defaults
 
         // fields from .proto file at time of writing...
         // message Image {
@@ -369,7 +378,7 @@ function doPostImage(srcCanvas, dstDiv, dstImg, imgPlaceholder) {
         var errMsg = msgInput.verify(inputPayload);
         if (errMsg) {
             var strErr = "[doPostImage]: Error during type verify for object input into protobuf method. ("+errMsg+")";
-            dstDiv.empty().html(strErr);
+            $(dstDiv).empty().html(strErr);
             console.log(strErr);
             throw Error(strErr);
         }
@@ -384,8 +393,6 @@ function doPostImage(srcCanvas, dstDiv, dstImg, imgPlaceholder) {
         $("#protoInput").prop("disabled",false);
         hd.protoPayloadInput = sendPayload;
 
-        //request.setRequestHeader("Content-type", "application/octet-stream;charset=UTF-8");
-        domHeaders["Content-type"] = "text/plain;charset=UTF-8";
         //request.responseType = 'arraybuffer';
     }
     else if (hd.protoList.length) {
@@ -408,6 +415,43 @@ function doPostImage(srcCanvas, dstDiv, dstImg, imgPlaceholder) {
             sendPayload.append("myList", "5"); // limit the number of classes (max 1000)
         }
     }
+    doPostPayload(sendPayload, domHeaders, dstDiv, dstImg, imgPlaceholder);
+}
+
+
+function doPostBinaryFile(e)  {
+    // https://stackoverflow.com/a/10811427
+    // https://stackoverflow.com/a/17512132
+    var fileReader = new FileReader();
+    fileReader.onload = function(e) {
+        console.log("[doPostBinaryFile]: Sending uploaded binary file of length "+e.target.result.byteLength);
+        doPostBlob(e.target.result);
+    };
+    var fileLocal = $(this)[0].files[0];
+    fileReader.readAsArrayBuffer(fileLocal);
+
+    //usage: $("#ingredient_file").change(doPostBinaryFile);
+}
+
+function doPostBlob(blobData)
+{
+    doPostPayload(blobData, null, '#resultsDiv', '#destImg', null);
+}
+
+
+function doPostPayload(sendPayload, domHeaders, dstDiv, dstImg, imgPlaceholder)
+{
+
+    var hd = $(document.body).data('hdparams');
+    hd.imageIsWaiting = true;
+
+    dstDiv = $(dstDiv);
+    $("#postSpinner").remove();     //erase previously existing one
+    dstDiv.append($("<div id='postSpinner' class='spinner'>&nbsp;</div>"));
+    if (dstImg)     //convert to jquery dom object
+        dstImg = $(dstImg);
+    if (!domHeaders)    //pull existing headers from config
+        domHeaders = $(document.body).data('hdparams').domHeaders;
 
     //$(dstImg).addClaas('workingImage').siblings('.spinner').remove().after($("<span class='spinner'>&nbsp;</span>"));
     $.ajax({
@@ -500,6 +544,17 @@ function downloadBlobIn() {
     return downloadBlob($(document.body).data('hdparams').protoPayloadInput, "protobuf.in.bin");
 }
 
+function downloadBlobProto() {
+    var namePackage = $(document.body).data('hdparams').protoKeys[0];
+    var pathProto = $(document.body).data('hdparams').protoObj[namePackage]['path'];
+    $.get(pathProto, function(data) {
+        var fileBase = pathProto.split(/[\\\/]/);       // added 7/11/18 for proto context
+        fileBase = fileBase[fileBase.length - 1];
+        return downloadBlob(data, fileBase, "text/plain");
+    }, 'text');
+}
+
+
 //  https://stackoverflow.com/a/33622881
 function downloadBlob(data, fileName, mimeType) {
     //if there is no data, filename, or mime provided, make our own
index c0996e3..3fcf7d6 100644 (file)
@@ -92,10 +92,15 @@ Rewrite to utilize simple image-based processing steps.
         <td><input type="text" name="serverUrl" id="serverUrl" size="60" />
         <br /><span class="tiny"><em>Note: The endpoint url may be modified when a new method below is utilized.</em></span></td></tr>
     <tr><td><label for="protoMethod">Protobuf Method:</label></td>
-        <td><select name="protoMethod" id="protoMethod" ><option value="">(disabled, not loaded)</option></select></td></tr>
+        <td><select name="protoMethod" id="protoMethod" ><option value="">(disabled, not loaded)</option></select>
+        <button type="button" name="protoSource" id="protoSource" >Download Protobuf Source</button></td></tr>
     <tr><td><label for="protoButton">Protobuf Message:</label></td>
         <td><button type="button" name="protoInput" id="protoInput" >Download Encoded Input</button> -
         <button type="button" name="protoOutput" id="protoOutput" >Download Encoded Response</button></td></tr>
+    <tr><td><label for="protoButton">Protobuf Payload Input:</label></td>
+        <td><input type="file" id="protoBinary" /> (triggers upload + post on selection)</td></tr>
+
+
     <tr><td><span class="tiny"><strong>PRO TIP:</strong></span></td>
         <td><span class="tiny">Add the query parameter <em><a href="." id="serverLink">url-image</a></em> to auto-load this URL.</span></td></tr>
 </table>
diff --git a/web_demo/protobuf.Image.bin b/web_demo/protobuf.Image.bin
new file mode 100644 (file)
index 0000000..7056fad
Binary files /dev/null and b/web_demo/protobuf.Image.bin differ
diff --git a/web_demo/protobuf.RegionDetectionSet.bin b/web_demo/protobuf.RegionDetectionSet.bin
new file mode 100644 (file)
index 0000000..075b7f0
Binary files /dev/null and b/web_demo/protobuf.RegionDetectionSet.bin differ