AJAX: Difference between revisions

From MidasWiki
Jump to navigation Jump to search
No edit summary
 
(48 intermediate revisions by 3 users not shown)
Line 1: Line 1:
{{Pagelinks}}
= Links =
<div style="column-count:3;-moz-column-count:3;-webkit-column-count:3">
* [[mhttpd]]
* [[mhttpd.js]] Javascript Library
* [[Custom Page]]
</div>
= About =
= About =


Line 4: Line 12:


These AJAX functions are typically accessed from browser javascript using the MIDAS [[mhttpd.js]] library.
These AJAX functions are typically accessed from browser javascript using the MIDAS [[mhttpd.js]] library.
As originally written, code snippets are taken from mhttpd.cxx git commit db4602dc2ed63674413f92cc92f49f183bd14225, 21 Aug 2013.
mhttpd AJAX functions are invoked using the "cmd" parameter with value equal to the name of the AJAX request, for example, to call "jmsg", do:
<pre>
curl "http://localhost:8080?cmd=jmsg&n=5"
</pre>
or where the webserver is using [[mhttpd#HTTPS/SSL server (Mongoose)|HTTPS/SSL (Mongoose)]]
<pre>
$ curl "https://localhost:8443?cmd=jmsg&n=5" -k -u username:passwd --digest
</pre>


= URL percent-encoding =
= URL percent-encoding =
Line 14: Line 33:
* "+" - decoded as " " ("plus" decoded as "space")
* "+" - decoded as " " ("plus" decoded as "space")
* other chars decoded as themselves
* other chars decoded as themselves
<!-- [[AJAX]] [[mhttpd.js|Javascript library]]  -->


This is consistent with URL encoding rules specified by  http://tools.ietf.org/html/rfc3986
This is consistent with URL encoding rules specified by  http://tools.ietf.org/html/rfc3986
Line 68: Line 89:
** ?odb<code>N</code>=<code>ODB path</code>
** ?odb<code>N</code>=<code>ODB path</code>
** ?format<code>N</code>=<code>sprintf format</code>
** ?format<code>N</code>=<code>sprintf format</code>
** ?name=<code>integer</code> - non-zero value enables output of key names
* returns:
* returns:
** single jget returns the text from output_key()
** single jget returns the text from output_key()
** multiple jget returns the values of all given ODB paths (?odb0=path?format0=format?odb1=path?format1=format?...) separated by the string "$#----#$\n".
** multiple jget returns the values of all given ODB paths (?odb0=path?format0=format?odb1=path?format1=format?...) separated by the string "$#----#$\n".
** <DB_NO_KEY> for non-existant ODB paths (db_find_key() != DB_SUCCESS)
** <DB_NO_KEY> for non-existant ODB paths (db_find_key() != DB_SUCCESS)
 
** <DB_OUT_OF_RANGE> for out of bounds array elements
* BUG: some versions of mhttpd do not percent-encode the value of the "format" parameter (see section about URL encoding). Values of "format0", etc are decoded as expected.


* ODB array path encoding:
* ODB array path encoding:
Line 80: Line 101:
** /path/array -> index=0
** /path/array -> index=0
** then it is passed to output_key()
** then it is passed to output_key()
* encoding by mhttpd.cxx output_key():
** TID_KEY: all subkeys are enumerated and passed to output_key() with "index" set to "-1". Output for all subkeys is concatenated without any separators.
** arrays or simple variables (index=-1): "v0\nv1\n...", if "name" is "1", then: "key[0]: v0\nkey[1]: v1\n..."
** array elements or simple variables (index!=-1): "value\n", if "name" is "1", then: "key[i]: valuei\n"
* BUG: output_key() has no check against negative array indices - passed directly to db_sprintf()/db_sprintff() which also has no array bounds check
* BUG: output_key() has no check for db_get_data() success or failure, no handling of DB_TRUNCATED.
* BUG: some versions of mhttpd do not percent-encode the value of the "format" parameter (see section about URL encoding). Values of "format0", etc are decoded as expected.
* BUG: output_key() ignores it's "format" argument except when encoding arrays. Instead, for encoding of simple variables the value of URL "format" parameter is used unconditionally. This means that the ODBMGet() format[] arguments are only applied to arrays, simple variables use the default format.
* example: TBW


= jcopy =
= jcopy =


TBW
* JSONP: yes
* parameters:
** &format=<code>format</code> same as "encoding" but subject to an mhttpd URI percent-encoding bug (it is not URI-decoded)
** &encoding=<code>encoding</code> see below
** &callback=<code>string</code> name of the JSONP callback function
** &odb=<code>ODB path</code> single jcopy function
** &odb0=<code>ODB path</code> multiple jcopy function
** &odb<code>N</code>=<code>ODB path</code> ODB paths for multiple copy
 
* single jcopy returns:
** data encoded according to "encoding" (see below)
** <DB_NO_KEY> is ODB path does not exist (db_find_key() != DB_SUCCESS)
 
* multiple jcopy returns:
** each ODB path is encoded same for single jcopy, with following separators:
** encoding="odb", separator is string "$#----#$\n", non existant keys return <DB_NO_KEY>"
** encoding="xml", outer XML element is <jcopy>, each ODB path is wrapped in a <data> element, non existant keys are encoded as <DB_NO_KEY/>
** encoding="json", data is encoded as a JSON array - "[ path0, path1, ... ]", non existant keys are encoded as "{ "/error" : %d }" with the error return value of db_find_key().
 
* jcopy "encoding" (and "format") parameter:
** encoding="odb" - returns data encoded by db_copy()
** encoding="xml" - returns data encoded by db_copy_xml()
** encoding="json" - returns data encoded by db_copy_json(), with these options:
*** "json-p" - data is wrapped by "callback(data);\n"
*** "json-nofollowlinks" - ODB links are encoded as links not as values pointed to by links
*** "json-nokeys" - only values are encoded, ODB keys are omitted, except for "last_written"
*** "json-nolastwritten" - value of ODB key "last_written" is omitted, too.
*** "json-norecurse" - do not recurse into subdirectories (to implement odb edit "ls -l")
 
* examples:
** single jcopy in ODB format:
 
<pre>
$ curl "http://localhost:8080?cmd=jcopy&odb=/runinfo&encoding=odb"
[.]
State = INT : 1
Online Mode = INT : 1
Run number = INT : 0
Transition in progress = INT : 0
Start abort = INT : 0
Requested transition = INT : 0
Start time = STRING : [32] Tue Sep 09 15:04:42 1997
Start time binary = DWORD : 0
Stop time = STRING : [32] Tue Sep 09 15:04:42 1997
Stop time binary = DWORD : 0
</pre>
* single jcopy in XML format:
<pre>
$ curl "http://localhost:8080?cmd=jcopy&odb=/runinfo&encoding=xml"
<?xml version="1.0" encoding="ISO-8859-1"?>
<!-- created by MXML on Thu Aug 22 09:53:02 2013 -->
<odb root="/Runinfo" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://midas.psi.ch/odb.xsd">
  <key name="State" type="INT">1</key>
  <key name="Online Mode" type="INT">1</key>
  <key name="Run number" type="INT">0</key>
  <key name="Transition in progress" type="INT">0</key>
  <key name="Start abort" type="INT">0</key>
  <key name="Requested transition" type="INT">0</key>
  <key name="Start time" type="STRING" size="32">Tue Sep 09 15:04:42 1997</key>
  <key name="Start time binary" type="DWORD">0</key>
  <key name="Stop time" type="STRING" size="32">Tue Sep 09 15:04:42 1997</key>
  <key name="Stop time binary" type="DWORD">0</key>
</odb>
</pre>
* single jcopy on JSON format:
<pre>
$ curl "http://localhost:8080?cmd=jcopy&odb=/runinfo&encoding=json"
{
  "State/key" : { "type" : 7, "last_written" : 1377182821 },
  "State" : 1,
  "Online Mode/key" : { "type" : 7, "last_written" : 1377182821 },
  "Online Mode" : 1,
  "Run number/key" : { "type" : 7, "last_written" : 1377182821 },
  "Run number" : 0,
  "Transition in progress/key" : { "type" : 7, "last_written" : 1377182821 },
  "Transition in progress" : 0,
  "Start abort/key" : { "type" : 7, "last_written" : 1377182821 },
  "Start abort" : 0,
  "Requested transition/key" : { "type" : 7, "last_written" : 1377182821 },
  "Requested transition" : 0,
  "Start time/key" : { "type" : 12, "item_size" : 32, "last_written" : 1377182821 },
  "Start time" : "Tue Sep 09 15:04:42 1997",
  "Start time binary/key" : { "type" : 6, "last_written" : 1377182821 },
  "Start time binary" : "0x00000000",
  "Stop time/key" : { "type" : 12, "item_size" : 32, "last_written" : 1377182821 },
  "Stop time" : "Tue Sep 09 15:04:42 1997",
  "Stop time binary/key" : { "type" : 6, "last_written" : 1377182821 },
  "Stop time binary" : "0x00000000"
}
</pre>
* multiple jcopy in JSON format:
<pre>
$ curl "http://localhost:8080?cmd=jcopy&odb0=/experiment/name&odb1=/runinfo&encoding=json"
[
{
"Name/key" : { "type" : 12, "item_size" : 32, "last_written" : 1377190203 },
"Name" : "javascript1"
}
,
{
  "State/key" : { "type" : 7, "last_written" : 1377182821 },
  "State" : 1,
  "Online Mode/key" : { "type" : 7, "last_written" : 1377182821 },
  "Online Mode" : 1,
  "Run number/key" : { "type" : 7, "last_written" : 1377182821 },
  "Run number" : 0,
  "Transition in progress/key" : { "type" : 7, "last_written" : 1377182821 },
  "Transition in progress" : 0,
  "Start abort/key" : { "type" : 7, "last_written" : 1377182821 },
  "Start abort" : 0,
  "Requested transition/key" : { "type" : 7, "last_written" : 1377182821 },
  "Requested transition" : 0,
  "Start time/key" : { "type" : 12, "item_size" : 32, "last_written" : 1377182821 },
  "Start time" : "Tue Sep 09 15:04:42 1997",
  "Start time binary/key" : { "type" : 6, "last_written" : 1377182821 },
  "Start time binary" : "0x00000000",
  "Stop time/key" : { "type" : 12, "item_size" : 32, "last_written" : 1377182821 },
  "Stop time" : "Tue Sep 09 15:04:42 1997",
  "Stop time binary/key" : { "type" : 6, "last_written" : 1377182821 },
  "Stop time binary" : "0x00000000"
}
]
</pre>
* multiple jcopy in condensed JSON encoding with JSONP wrapper:
<pre>
$ curl "http://localhost:8080?cmd=jcopy&odb0=/experiment/name&odb1=/runinfo&encoding=json-p-nokeys&callback=mycallback"
mycallback([
{
"Name/last_written" : 1377190203,
"Name" : "javascript1"
}
,
{
  "State/last_written" : 1377182821,
  "State" : 1,
  "Online Mode/last_written" : 1377182821,
  "Online Mode" : 1,
  "Run number/last_written" : 1377182821,
  "Run number" : 0,
  "Transition in progress/last_written" : 1377182821,
  "Transition in progress" : 0,
  "Start abort/last_written" : 1377182821,
  "Start abort" : 0,
  "Requested transition/last_written" : 1377182821,
  "Requested transition" : 0,
  "Start time/last_written" : 1377182821,
  "Start time" : "Tue Sep 09 15:04:42 1997",
  "Start time binary/last_written" : 1377182821,
  "Start time binary" : "0x00000000",
  "Stop time/last_written" : 1377182821,
  "Stop time" : "Tue Sep 09 15:04:42 1997",
  "Stop time binary/last_written" : 1377182821,
  "Stop time binary" : "0x00000000"
}
]
);
</pre>
** multiple jcopy in values-only JSON encoding with JSONP wrapper:
<pre>
$ curl "http://localhost:8080?cmd=jcopy&odb0=/experiment/name&odb1=/runinfo&encoding=json-p-nokeys-nolastwritten&callback=mycallback"
mycallback([
"javascript1"
,
{
1,
1,
186,
0,
0,
0,
"Thu Jan 16 11:56:53 2014",
"0x52d83985",
"Thu Jan 16 11:56:58 2014",
"0x52d8398a"
}
]
);
</pre>


= jkey =
= jkey =
Line 89: Line 299:
* JSONP: no
* JSONP: no
* parameters:
* parameters:
** ?odb=<code>ODB path</code>
** &odb=<code>ODB path</code>
* returns:
* returns:
** "<DB_NO_KEY>" if key does not exist
** MIDAS "KEY" structure (see midas.h)
<pre>
<pre>
  if (equal_ustring(getparam("cmd"), "jkey")) {
      show_text_header();
      if (isparam("odb") && db_find_key(hDB, 0, getparam("odb"), &hkey) == DB_SUCCESS) {
         db_get_key(hDB, hkey, &key);
         db_get_key(hDB, hkey, &key);
         rsprintf("%s\n", key.name);
         rsprintf("%s\n", key.name);
Line 101: Line 310:
         rsprintf("%d\n", key.item_size);
         rsprintf("%d\n", key.item_size);
         rsprintf("%d", key.last_written);
         rsprintf("%d", key.last_written);
      } else
        rsputs("<DB_NO_KEY>");
      return;
  }
</pre>
</pre>
* example: TBW
* example:
<pre>
$ curl "http://localhost:8080?cmd=jkey&odb=/runinfo/run+number"
Run number
TID_INT
1
4
1377182821
</pre>
 
* BUG: last entry is not "\n" terminated
* BUG: there is no check for db_get_key() error return
 
= jcreate =
 
* git branch: feature/ajax
* JSONP: yes
* parameters:
** &encoding=<code>encoding</code> only JSON is implemented
** &callback=<code>string</code> name of the JSONP callback function
** &odb=<code>ODB path</code> single jcreate function
** &odb0=<code>ODB path</code> multiple jcreate function
** &odb<code>N</code>=<code>ODB path</code> ODB paths for multiple copy
** &type=<code>TID_type</code> single jcreate: integer "type" argument to db_create_key()
** &type<code>N</code>=<code>TID_type</code> same for multiple jcreate
** &strlen=<code>int</code> if "type" is TID_STRING, create string of given length. If absent, zero-length string is created
** &strlen<code>N</code>=<code>int</code> same for multiple jcreate
** &arraylen=<code>int</code> is present, use db_set_num_values() to create an array of specified length
** &arraylen<code>N</code>=<code>int</code> same for multiple jcreate
 
* single jcreate returns:
** integer status value from db_create_key()
 
* multiple jcreate returns:
** data encoded as JSON, i.e.: [ 1, 312, 1 ]
 
* examples:
 
** single jcreate:
<pre>
$ curl "http://localhost:8080?cmd=jcreate&odb=/test/foo&type=7"
1
</pre>
 
** multiple jcreate with JSON-P encoding:
(note how /nonexistant is created with an invalid "type")
<pre>
$ curl "http://localhost:8080?cmd=jcreate&odb0=/test/foo&type0=7&odb1=/nonexistant&type1=100&odb2=/test/bar&type2=12&encoding=json&callback=aaa"
aaa([ 1, 309, 1 ]);
</pre>
 
** create an array of integers:
<pre>
curl "http://localhost:8080?cmd=jcreate&odb=/test/foo70&type=7&arraylen=10"
</pre>
 
** create an array of strings:
<pre>
curl "http://localhost:8080?cmd=jcreate&odb=/test/foo12s5&type=12&strlen=32&arraylen=5"
</pre>
 
= jresize =
 
* git branch: feature/ajax
* JSONP: yes
* parameters:
** &encoding=<code>encoding</code> only JSON is implemented
** &callback=<code>string</code> name of the JSONP callback function
** &odb=<code>ODB path</code> single jresize function
** &odb0=<code>ODB path</code> multiple jresize function
** &odb<code>N</code>=<code>ODB path</code> ODB paths for multiple resize
** &strlen=<code>int</code> change string length, including element length of string arrays
** &strlen<code>N</code>=<code>int</code> same for multiple jcreate
** &arraylen=<code>int</code> change array length, including string arrays
** &arraylen<code>N</code>=<code>int</code> same for multiple jcreate
 
* single jresize returns:
** integer status value from db_find_key(), db_get_key(), db_get_data(), db_set_data(), db_set_num_values()
 
* multiple jresize returns:
** data encoded as JSON, i.e.: [ 1, 312, 1 ]
 
* examples: similar to jcreate:
 
** resize integer array: curl "http://localhost:8080?cmd=jresize&odb=/test/foo70&arraylen=5"
** resize string array: curl "http://localhost:8080?cmd=jresize&odb=/test/foo12s5&arraylen=5"
** resize element size of string array: curl "http://localhost:8080?cmd=jresize&odb=/test/foo12s5&strlen=16"
** and change array size at the same time: curl "http://localhost:8080?cmd=jresize&odb=/test/foo12s5&strlen=30&arraylen=10"
 
= jrename =
 
* git branch: feature/ajax
* JSONP: yes
* parameters:
** &encoding=<code>encoding</code> only JSON is implemented
** &callback=<code>string</code> name of the JSONP callback function
** &odb=<code>ODB path</code> single jrename function
** &odb0=<code>ODB path</code> multiple jrename function
** &odb<code>N</code>=<code>ODB path</code> ODB paths for multiple rename
** &name=<code>string</code> single rename: new key "name" argument to db_rename_key()
** &name<code>N</code>=<code>string</code> same for multiple rename
 
* single jrename returns:
** integer status value from db_rename_key()
 
* multiple jrename returns:
** data encoded as JSON, i.e.: [ 1, 312, 1 ]
 
* examples:
 
** single jrename:
<pre>
$ curl "http://localhost:8080?cmd=jrename&odb=/test/foo&name=foofoo"
1
</pre>
 
** multiple jrename:
<pre>
$ curl "http://localhost:8080?cmd=jrename&odb0=/test/foo&name0=foofoo&odb1=/test/bar&name1=barbar"
[ 1, 1 ]
</pre>
 
= jlink =
 
* git branch: feature/ajax
* JSONP: yes
* parameters:
** &encoding=<code>encoding</code> only JSON is implemented
** &callback=<code>string</code> name of the JSONP callback function
** &odb=<code>ODB path</code> single jlink function
** &odb0=<code>ODB path</code> multiple jlink function
** &odb<code>N</code>=<code>ODB path</code> ODB paths for multiple link
** &dest=<code>string</code> single link: destination argument to db_create_link()
** &dest<code>N</code>=<code>string</code> same for multiple rename
 
* single jlink returns:
** integer status value from db_create_link()
 
* multiple jlink returns:
** data encoded as JSON, i.e.: [ 1, 312, 1 ]
 
* examples:
 
** single jlink:
<pre>
$ curl "http://localhost:8080?cmd=jlink&odb=/test/link&dest=/test/foo"
1
</pre>
 
** multiple jlink:
<pre>
$ curl "http://localhost:8080?cmd=jlink&odb0=/test/link0&dest0=/test/foo&odb1=/test/link1&dest1=/test/foo"
[ 1, 1 ]
</pre>
 
= jreorder =
 
* git branch: feature/ajax
* JSONP: yes
* parameters:
** &encoding=<code>encoding</code> only JSON is implemented
** &callback=<code>string</code> name of the JSONP callback function
** &odb=<code>ODB path</code> single jreorder function
** &odb0=<code>ODB path</code> multiple jreorder function
** &odb<code>N</code>=<code>ODB path</code> ODB paths for multiple reorder
** &index=<code>int</code> single link: "index" argument to db_reorder_key(). Special index values are: "0" is top, "-1" is bottom.
** &index<code>N</code>=<code>int</code> same for multiple reorder
 
* single jreorder returns:
** integer status value from db_reorder_key()
 
* multiple jreorder returns:
** data encoded as JSON, i.e.: [ 1, 312, 1 ]
 
* examples:
 
** single jreorder:
<pre>
$ curl "http://localhost:8080?cmd=jreorder&odb=/test/bar&index=0"
1
</pre>
 
** multiple jreorder:
<pre>
$ curl "http://localhost:8080?cmd=jreorder&odb0=/test/foo&index0=0&odb1=/test/bar&index1=1"
[ 1, 1 ]
</pre>
 
= jdelete =
 
* git branch: feature/ajax
* JSONP: yes
* parameters:
** &encoding=<code>encoding</code> only JSON is implemented
** &callback=<code>string</code> name of the JSONP callback function
** &odb=<code>ODB path</code> single jdelete function
** &odb0=<code>ODB path</code> multiple jdelete function
** &odb<code>N</code>=<code>ODB path</code> ODB paths for multiple jdelete
 
* single jdelete returns:
** integer status value from db_delete_key()
 
* multiple jdelete returns:
** data encoded as JSON, i.e.: [ 1, 312, 1 ]
 
* examples:
 
** single jdelete:
<pre>
$ curl "http://localhost:8080?cmd=jdelete&odb=/test/foo"
1
</pre>
 
** multiple jdelete with JSON-P encoding:
<pre>
$ curl "http://localhost:8080?cmd=jdelete&odb0=/test/foo&odb1=/nonexistant&odb2=/test/bar&encoding=json&callback=aaa"
aaa([ 1, 312, 1 ]);
</pre>


= jmsg =
= jmsg =
Line 112: Line 534:
* JSONP: no
* JSONP: no
* parameters:
* parameters:
** ?n=<code>number of messages to return</code>
** &n=<code>number of messages to return</code> return last n messages
* returns: output of cm_msg_retrieve()
** &t=<code>unix timestamp</code> return all messages since time t
::: Note that parameter '''&n=0 must be specified with parameter &t''' (see example 2 below)
* returns: output of midas.c::cm_msg_retrieve()
* example 1: get last 5 messages
:: in this example the webserver is using http
<pre>
$ curl "http://localhost:8080?cmd=jmsg&n=5"
Thu Aug 22 08:05:10 2013 [Logger,TALK] Warning: This is an example alarm
Thu Aug 22 08:06:13 2013 [mhttpd,TALK] Alarm: Run number became too large
Thu Aug 22 08:06:13 2013 [mhttpd,TALK] Warning: This is an example alarm
Thu Aug 22 08:07:15 2013 [fejrpc,TALK] Alarm: Run number became too large
Thu Aug 22 08:07:15 2013 [fejrpc,TALK] Warning: This is an example alarm
</pre>
* example 2: get all messages since a certain date
:: in this example the webserver is using [[mhttpd#HTTPS/SSL server (Mongoose)|HTTPS/SSL (Mongoose)]]
<pre>
<pre>
  if (equal_ustring(getparam("cmd"), "jmsg")) {
$ date -d "Fri Sep 9 16:10:00 PDT 2016" +%s
      i = 1;
1473462600
      if (*getparam("n"))
$ curl "https://localhost:8443?cmd=jmsg&n=0&t=1473462600" -k -u username:passwd --digest
        i = atoi(getparam("n"));
1473462926 16:15:26.119 2016/09/09 [ODBEdit,TALK] Alarm: RF has tripped
     
1473462863 16:14:23.740 2016/09/09 [autorun,TALK] Alarm: RF has tripped
      show_text_header();
1473462799 16:13:19.109 2016/09/09 [mheader,TALK] Alarm: RF has tripped
      cm_msg_retrieve(i, str, sizeof(str));
1473462739 16:12:19.078 2016/09/09 [feEpics,TALK] Alarm: RF has tripped
      rsputs(str);
1473462673 16:11:13.003 2016/09/09 [feEpics,TALK] Alarm: RF has tripped
      return;
1473462607 16:10:07.101 2016/09/09 [ODBEdit,TALK] Alarm: RF has tripped
  }
</pre>
</pre>
* example: TBW
 
* BUG: last message is not "\n" terminated (violation of the HTTP protocol?)


= jgenmsg =
= jgenmsg =
Line 132: Line 568:
* JSONP: no
* JSONP: no
* parameters:
* parameters:
** ?msg=<code>message text</code>
** &msg=<code>message text</code>
* returns: ???
* returns: string "Message successfully created\n"
* example:
<pre>
<pre>
  if (equal_ustring(getparam("cmd"), "jalm")) {
$ curl "http://localhost:8080?cmd=jgenmsg&msg=test+message"
      show_text_header();
Message successfully created
      al_get_alarms(str, sizeof(str));
      rsputs(str);
      return;
  }
</pre>
</pre>
* example: TBW
 
* BUG: "Message successfully created\n" is returned even if the "msg" parameter is missing and regardless of cm_msg() error return code.


= jalm =
= jalm =
Line 148: Line 582:
* JSONP: no
* JSONP: no
* parameters: no
* parameters: no
* returns: text from al_get_alarms()
* returns:
 
** text from alarm.c::al_get_alarms()
** is "\n" separated list of alarms
** alarm format is "class: text", where "class" is the alarm class, "text" is the alarm message from ODB /Alarms/alarms/xxx/
* example:
<pre>
<pre>
  if (equal_ustring(getparam("cmd"), "jalm")) {
$ curl http://localhost:8080?cmd=jalm
      show_text_header();
Alarm: Run number became too large
      al_get_alarms(str, sizeof(str));
Warning: This is an example alarm
      rsputs(str);
      return;
  }
</pre>
</pre>


* example: TBW
* BUG: return text is "\n" terminated, array created by javascript request.responseText.split('\n') will have an extra empty element at the end.
 
[[Category:Ajax]] [[Category:Javascript library]] [[Category:Custom]]

Latest revision as of 16:48, 9 September 2016


Links

About

This page will document the MIDAS AJAX functions accessible through special mhttpd URLs.

These AJAX functions are typically accessed from browser javascript using the MIDAS mhttpd.js library.

As originally written, code snippets are taken from mhttpd.cxx git commit db4602dc2ed63674413f92cc92f49f183bd14225, 21 Aug 2013.

mhttpd AJAX functions are invoked using the "cmd" parameter with value equal to the name of the AJAX request, for example, to call "jmsg", do:

curl "http://localhost:8080?cmd=jmsg&n=5" 

or where the webserver is using HTTPS/SSL (Mongoose)

$ curl "https://localhost:8443?cmd=jmsg&n=5" -k -u username:passwd --digest

URL percent-encoding

All parameter names and parameter values (?name=value) are passed through urlDecode.

Encoding used by urlDecode:

  • %HH - decoded as char value 0xHH (hex encoding)
  • "+" - decoded as " " ("plus" decoded as "space")
  • other chars decoded as themselves


This is consistent with URL encoding rules specified by http://tools.ietf.org/html/rfc3986

On the client side (mhttpd.js), parameter values should be encoded using the JavaScript encodeURIComponent() function.

  • BUG: value of parameter "format" is not passed through urlDecode (git commit db4602dc2ed63674413f92cc92f49f183bd14225, 21 Aug 2013), this is consistent with mhttpd.js which does not urlEncode the values. Values of "format0", etc used by ODBMGet() are decoded as expected.
            urlDecode(pitem);
            if (!equal_ustring(pitem, "format"))
               urlDecode(p);
            setparam(pitem, p);
  • BUG: confirm that values of "format0", etc are decoded correctly.

jset

  • JSONP: no
  • parameters:
    • ?pnam=xxx - cookie_cpwd to match value of ODB /Custon/Pwd/xxx. How is this supposed to work??? How to use it???
      if (*getparam("pnam")) {
         sprintf(ppath, "/Custom/Pwd/%s", getparam("pnam"));
         str[0] = 0;
         db_get_value(hDB, 0, ppath, str, &size, TID_STRING, TRUE);
         if (!equal_ustring(cookie_cpwd, str)) {
            show_text_header();
            rsprintf("Invalid password!");
            return;
         }
      }
    • ?odb=ODB path
    • ?value=data
    • ?type=integer - if ODB path does not exist, it is created, using "type" as the MIDAS TID_xxx data type
    • ?len=integer - when ODB path is created, if "len" is not zero, it is made an array of "len" size, with all values set to "value". Except if "type" is TID_STRING, there is no array created, but "len" is used as the ODB string length.
  • ODB path encoding for arrays:
    • /path/array[i] - write array element [i]
    • /path/array - write array element [0]
    • /path/array[*] - write as many array elements as there are comma-separated entries in "value". There is no check against existing array length - db_set_data_index() will grow the array as neeed.
  • example: TBW

jget

  • JSONP: no
  • parameters:
    • ?odb=ODB path
    • ?format=sprintf format
    • ?odb0=ODB path - activates the multiple jget function
    • ?odbN=ODB path
    • ?formatN=sprintf format
    • ?name=integer - non-zero value enables output of key names
  • returns:
    • single jget returns the text from output_key()
    • multiple jget returns the values of all given ODB paths (?odb0=path?format0=format?odb1=path?format1=format?...) separated by the string "$#----#$\n".
    • <DB_NO_KEY> for non-existant ODB paths (db_find_key() != DB_SUCCESS)
    • <DB_OUT_OF_RANGE> for out of bounds array elements
  • ODB array path encoding:
    • /path/array[i] -> index=i
    • /path/array[*] -> index=-1
    • /path/array -> index=0
    • then it is passed to output_key()
  • encoding by mhttpd.cxx output_key():
    • TID_KEY: all subkeys are enumerated and passed to output_key() with "index" set to "-1". Output for all subkeys is concatenated without any separators.
    • arrays or simple variables (index=-1): "v0\nv1\n...", if "name" is "1", then: "key[0]: v0\nkey[1]: v1\n..."
    • array elements or simple variables (index!=-1): "value\n", if "name" is "1", then: "key[i]: valuei\n"
  • BUG: output_key() has no check against negative array indices - passed directly to db_sprintf()/db_sprintff() which also has no array bounds check
  • BUG: output_key() has no check for db_get_data() success or failure, no handling of DB_TRUNCATED.
  • BUG: some versions of mhttpd do not percent-encode the value of the "format" parameter (see section about URL encoding). Values of "format0", etc are decoded as expected.
  • BUG: output_key() ignores it's "format" argument except when encoding arrays. Instead, for encoding of simple variables the value of URL "format" parameter is used unconditionally. This means that the ODBMGet() format[] arguments are only applied to arrays, simple variables use the default format.
  • example: TBW

jcopy

  • JSONP: yes
  • parameters:
    • &format=format same as "encoding" but subject to an mhttpd URI percent-encoding bug (it is not URI-decoded)
    • &encoding=encoding see below
    • &callback=string name of the JSONP callback function
    • &odb=ODB path single jcopy function
    • &odb0=ODB path multiple jcopy function
    • &odbN=ODB path ODB paths for multiple copy
  • single jcopy returns:
    • data encoded according to "encoding" (see below)
    • <DB_NO_KEY> is ODB path does not exist (db_find_key() != DB_SUCCESS)
  • multiple jcopy returns:
    • each ODB path is encoded same for single jcopy, with following separators:
    • encoding="odb", separator is string "$#----#$\n", non existant keys return <DB_NO_KEY>"
    • encoding="xml", outer XML element is <jcopy>, each ODB path is wrapped in a element, non existant keys are encoded as <DB_NO_KEY/>
    • encoding="json", data is encoded as a JSON array - "[ path0, path1, ... ]", non existant keys are encoded as "{ "/error" : %d }" with the error return value of db_find_key().
  • jcopy "encoding" (and "format") parameter:
    • encoding="odb" - returns data encoded by db_copy()
    • encoding="xml" - returns data encoded by db_copy_xml()
    • encoding="json" - returns data encoded by db_copy_json(), with these options:
      • "json-p" - data is wrapped by "callback(data);\n"
      • "json-nofollowlinks" - ODB links are encoded as links not as values pointed to by links
      • "json-nokeys" - only values are encoded, ODB keys are omitted, except for "last_written"
      • "json-nolastwritten" - value of ODB key "last_written" is omitted, too.
      • "json-norecurse" - do not recurse into subdirectories (to implement odb edit "ls -l")
  • examples:
    • single jcopy in ODB format:
$ curl "http://localhost:8080?cmd=jcopy&odb=/runinfo&encoding=odb"
[.]
State = INT : 1
Online Mode = INT : 1
Run number = INT : 0
Transition in progress = INT : 0
Start abort = INT : 0
Requested transition = INT : 0
Start time = STRING : [32] Tue Sep 09 15:04:42 1997
Start time binary = DWORD : 0
Stop time = STRING : [32] Tue Sep 09 15:04:42 1997
Stop time binary = DWORD : 0
  • single jcopy in XML format:
$ curl "http://localhost:8080?cmd=jcopy&odb=/runinfo&encoding=xml"
<?xml version="1.0" encoding="ISO-8859-1"?>
<!-- created by MXML on Thu Aug 22 09:53:02 2013 -->
<odb root="/Runinfo" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://midas.psi.ch/odb.xsd">
  <key name="State" type="INT">1</key>
  <key name="Online Mode" type="INT">1</key>
  <key name="Run number" type="INT">0</key>
  <key name="Transition in progress" type="INT">0</key>
  <key name="Start abort" type="INT">0</key>
  <key name="Requested transition" type="INT">0</key>
  <key name="Start time" type="STRING" size="32">Tue Sep 09 15:04:42 1997</key>
  <key name="Start time binary" type="DWORD">0</key>
  <key name="Stop time" type="STRING" size="32">Tue Sep 09 15:04:42 1997</key>
  <key name="Stop time binary" type="DWORD">0</key>
</odb>
  • single jcopy on JSON format:
$ curl "http://localhost:8080?cmd=jcopy&odb=/runinfo&encoding=json"
{
  "State/key" : { "type" : 7, "last_written" : 1377182821 },
  "State" : 1,
  "Online Mode/key" : { "type" : 7, "last_written" : 1377182821 },
  "Online Mode" : 1,
  "Run number/key" : { "type" : 7, "last_written" : 1377182821 },
  "Run number" : 0,
  "Transition in progress/key" : { "type" : 7, "last_written" : 1377182821 },
  "Transition in progress" : 0,
  "Start abort/key" : { "type" : 7, "last_written" : 1377182821 },
  "Start abort" : 0,
  "Requested transition/key" : { "type" : 7, "last_written" : 1377182821 },
  "Requested transition" : 0,
  "Start time/key" : { "type" : 12, "item_size" : 32, "last_written" : 1377182821 },
  "Start time" : "Tue Sep 09 15:04:42 1997",
  "Start time binary/key" : { "type" : 6, "last_written" : 1377182821 },
  "Start time binary" : "0x00000000",
  "Stop time/key" : { "type" : 12, "item_size" : 32, "last_written" : 1377182821 },
  "Stop time" : "Tue Sep 09 15:04:42 1997",
  "Stop time binary/key" : { "type" : 6, "last_written" : 1377182821 },
  "Stop time binary" : "0x00000000"
}
  • multiple jcopy in JSON format:
$ curl "http://localhost:8080?cmd=jcopy&odb0=/experiment/name&odb1=/runinfo&encoding=json"
[
{
"Name/key" : { "type" : 12, "item_size" : 32, "last_written" : 1377190203 },
"Name" : "javascript1"
}
,
{
  "State/key" : { "type" : 7, "last_written" : 1377182821 },
  "State" : 1,
  "Online Mode/key" : { "type" : 7, "last_written" : 1377182821 },
  "Online Mode" : 1,
  "Run number/key" : { "type" : 7, "last_written" : 1377182821 },
  "Run number" : 0,
  "Transition in progress/key" : { "type" : 7, "last_written" : 1377182821 },
  "Transition in progress" : 0,
  "Start abort/key" : { "type" : 7, "last_written" : 1377182821 },
  "Start abort" : 0,
  "Requested transition/key" : { "type" : 7, "last_written" : 1377182821 },
  "Requested transition" : 0,
  "Start time/key" : { "type" : 12, "item_size" : 32, "last_written" : 1377182821 },
  "Start time" : "Tue Sep 09 15:04:42 1997",
  "Start time binary/key" : { "type" : 6, "last_written" : 1377182821 },
  "Start time binary" : "0x00000000",
  "Stop time/key" : { "type" : 12, "item_size" : 32, "last_written" : 1377182821 },
  "Stop time" : "Tue Sep 09 15:04:42 1997",
  "Stop time binary/key" : { "type" : 6, "last_written" : 1377182821 },
  "Stop time binary" : "0x00000000"
}
]
  • multiple jcopy in condensed JSON encoding with JSONP wrapper:
$ curl "http://localhost:8080?cmd=jcopy&odb0=/experiment/name&odb1=/runinfo&encoding=json-p-nokeys&callback=mycallback"
mycallback([
{
"Name/last_written" : 1377190203,
"Name" : "javascript1"
}
,
{
  "State/last_written" : 1377182821,
  "State" : 1,
  "Online Mode/last_written" : 1377182821,
  "Online Mode" : 1,
  "Run number/last_written" : 1377182821,
  "Run number" : 0,
  "Transition in progress/last_written" : 1377182821,
  "Transition in progress" : 0,
  "Start abort/last_written" : 1377182821,
  "Start abort" : 0,
  "Requested transition/last_written" : 1377182821,
  "Requested transition" : 0,
  "Start time/last_written" : 1377182821,
  "Start time" : "Tue Sep 09 15:04:42 1997",
  "Start time binary/last_written" : 1377182821,
  "Start time binary" : "0x00000000",
  "Stop time/last_written" : 1377182821,
  "Stop time" : "Tue Sep 09 15:04:42 1997",
  "Stop time binary/last_written" : 1377182821,
  "Stop time binary" : "0x00000000"
}
]
);
    • multiple jcopy in values-only JSON encoding with JSONP wrapper:
$ curl "http://localhost:8080?cmd=jcopy&odb0=/experiment/name&odb1=/runinfo&encoding=json-p-nokeys-nolastwritten&callback=mycallback"
mycallback([
"javascript1"
,
{
1,
1,
186,
0,
0,
0,
"Thu Jan 16 11:56:53 2014",
"0x52d83985",
"Thu Jan 16 11:56:58 2014",
"0x52d8398a"
}
]
);

jkey

  • JSONP: no
  • parameters:
    • &odb=ODB path
  • returns:
    • "<DB_NO_KEY>" if key does not exist
    • MIDAS "KEY" structure (see midas.h)
         db_get_key(hDB, hkey, &key);
         rsprintf("%s\n", key.name);
         rsprintf("TID_%s\n", rpc_tid_name(key.type));
         rsprintf("%d\n", key.num_values);
         rsprintf("%d\n", key.item_size);
         rsprintf("%d", key.last_written);
  • example:
$ curl "http://localhost:8080?cmd=jkey&odb=/runinfo/run+number"
Run number
TID_INT
1
4
1377182821
  • BUG: last entry is not "\n" terminated
  • BUG: there is no check for db_get_key() error return

jcreate

  • git branch: feature/ajax
  • JSONP: yes
  • parameters:
    • &encoding=encoding only JSON is implemented
    • &callback=string name of the JSONP callback function
    • &odb=ODB path single jcreate function
    • &odb0=ODB path multiple jcreate function
    • &odbN=ODB path ODB paths for multiple copy
    • &type=TID_type single jcreate: integer "type" argument to db_create_key()
    • &typeN=TID_type same for multiple jcreate
    • &strlen=int if "type" is TID_STRING, create string of given length. If absent, zero-length string is created
    • &strlenN=int same for multiple jcreate
    • &arraylen=int is present, use db_set_num_values() to create an array of specified length
    • &arraylenN=int same for multiple jcreate
  • single jcreate returns:
    • integer status value from db_create_key()
  • multiple jcreate returns:
    • data encoded as JSON, i.e.: [ 1, 312, 1 ]
  • examples:
    • single jcreate:
$ curl "http://localhost:8080?cmd=jcreate&odb=/test/foo&type=7"
1
    • multiple jcreate with JSON-P encoding:

(note how /nonexistant is created with an invalid "type")

$ curl "http://localhost:8080?cmd=jcreate&odb0=/test/foo&type0=7&odb1=/nonexistant&type1=100&odb2=/test/bar&type2=12&encoding=json&callback=aaa"
aaa([ 1, 309, 1 ]);
    • create an array of integers:
curl "http://localhost:8080?cmd=jcreate&odb=/test/foo70&type=7&arraylen=10"
    • create an array of strings:
curl "http://localhost:8080?cmd=jcreate&odb=/test/foo12s5&type=12&strlen=32&arraylen=5"

jresize

  • git branch: feature/ajax
  • JSONP: yes
  • parameters:
    • &encoding=encoding only JSON is implemented
    • &callback=string name of the JSONP callback function
    • &odb=ODB path single jresize function
    • &odb0=ODB path multiple jresize function
    • &odbN=ODB path ODB paths for multiple resize
    • &strlen=int change string length, including element length of string arrays
    • &strlenN=int same for multiple jcreate
    • &arraylen=int change array length, including string arrays
    • &arraylenN=int same for multiple jcreate
  • single jresize returns:
    • integer status value from db_find_key(), db_get_key(), db_get_data(), db_set_data(), db_set_num_values()
  • multiple jresize returns:
    • data encoded as JSON, i.e.: [ 1, 312, 1 ]
  • examples: similar to jcreate:

jrename

  • git branch: feature/ajax
  • JSONP: yes
  • parameters:
    • &encoding=encoding only JSON is implemented
    • &callback=string name of the JSONP callback function
    • &odb=ODB path single jrename function
    • &odb0=ODB path multiple jrename function
    • &odbN=ODB path ODB paths for multiple rename
    • &name=string single rename: new key "name" argument to db_rename_key()
    • &nameN=string same for multiple rename
  • single jrename returns:
    • integer status value from db_rename_key()
  • multiple jrename returns:
    • data encoded as JSON, i.e.: [ 1, 312, 1 ]
  • examples:
    • single jrename:
$ curl "http://localhost:8080?cmd=jrename&odb=/test/foo&name=foofoo"
1
    • multiple jrename:
$ curl "http://localhost:8080?cmd=jrename&odb0=/test/foo&name0=foofoo&odb1=/test/bar&name1=barbar"
[ 1, 1 ]

jlink

  • git branch: feature/ajax
  • JSONP: yes
  • parameters:
    • &encoding=encoding only JSON is implemented
    • &callback=string name of the JSONP callback function
    • &odb=ODB path single jlink function
    • &odb0=ODB path multiple jlink function
    • &odbN=ODB path ODB paths for multiple link
    • &dest=string single link: destination argument to db_create_link()
    • &destN=string same for multiple rename
  • single jlink returns:
    • integer status value from db_create_link()
  • multiple jlink returns:
    • data encoded as JSON, i.e.: [ 1, 312, 1 ]
  • examples:
    • single jlink:
$ curl "http://localhost:8080?cmd=jlink&odb=/test/link&dest=/test/foo"
1
    • multiple jlink:
$ curl "http://localhost:8080?cmd=jlink&odb0=/test/link0&dest0=/test/foo&odb1=/test/link1&dest1=/test/foo"
[ 1, 1 ]

jreorder

  • git branch: feature/ajax
  • JSONP: yes
  • parameters:
    • &encoding=encoding only JSON is implemented
    • &callback=string name of the JSONP callback function
    • &odb=ODB path single jreorder function
    • &odb0=ODB path multiple jreorder function
    • &odbN=ODB path ODB paths for multiple reorder
    • &index=int single link: "index" argument to db_reorder_key(). Special index values are: "0" is top, "-1" is bottom.
    • &indexN=int same for multiple reorder
  • single jreorder returns:
    • integer status value from db_reorder_key()
  • multiple jreorder returns:
    • data encoded as JSON, i.e.: [ 1, 312, 1 ]
  • examples:
    • single jreorder:
$ curl "http://localhost:8080?cmd=jreorder&odb=/test/bar&index=0"
1
    • multiple jreorder:
$ curl "http://localhost:8080?cmd=jreorder&odb0=/test/foo&index0=0&odb1=/test/bar&index1=1"
[ 1, 1 ]

jdelete

  • git branch: feature/ajax
  • JSONP: yes
  • parameters:
    • &encoding=encoding only JSON is implemented
    • &callback=string name of the JSONP callback function
    • &odb=ODB path single jdelete function
    • &odb0=ODB path multiple jdelete function
    • &odbN=ODB path ODB paths for multiple jdelete
  • single jdelete returns:
    • integer status value from db_delete_key()
  • multiple jdelete returns:
    • data encoded as JSON, i.e.: [ 1, 312, 1 ]
  • examples:
    • single jdelete:
$ curl "http://localhost:8080?cmd=jdelete&odb=/test/foo"
1
    • multiple jdelete with JSON-P encoding:
$ curl "http://localhost:8080?cmd=jdelete&odb0=/test/foo&odb1=/nonexistant&odb2=/test/bar&encoding=json&callback=aaa"
aaa([ 1, 312, 1 ]);

jmsg

  • JSONP: no
  • parameters:
    • &n=number of messages to return return last n messages
    • &t=unix timestamp return all messages since time t
Note that parameter &n=0 must be specified with parameter &t (see example 2 below)
  • returns: output of midas.c::cm_msg_retrieve()
  • example 1: get last 5 messages
in this example the webserver is using http
$ curl "http://localhost:8080?cmd=jmsg&n=5"
Thu Aug 22 08:05:10 2013 [Logger,TALK] Warning: This is an example alarm
Thu Aug 22 08:06:13 2013 [mhttpd,TALK] Alarm: Run number became too large
Thu Aug 22 08:06:13 2013 [mhttpd,TALK] Warning: This is an example alarm
Thu Aug 22 08:07:15 2013 [fejrpc,TALK] Alarm: Run number became too large
Thu Aug 22 08:07:15 2013 [fejrpc,TALK] Warning: This is an example alarm
  • example 2: get all messages since a certain date
in this example the webserver is using HTTPS/SSL (Mongoose)
$ date -d "Fri Sep 9 16:10:00 PDT 2016" +%s
1473462600
$ curl "https://localhost:8443?cmd=jmsg&n=0&t=1473462600" -k -u username:passwd --digest
1473462926 16:15:26.119 2016/09/09 [ODBEdit,TALK] Alarm: RF has tripped
1473462863 16:14:23.740 2016/09/09 [autorun,TALK] Alarm: RF has tripped
1473462799 16:13:19.109 2016/09/09 [mheader,TALK] Alarm: RF has tripped
1473462739 16:12:19.078 2016/09/09 [feEpics,TALK] Alarm: RF has tripped
1473462673 16:11:13.003 2016/09/09 [feEpics,TALK] Alarm: RF has tripped
1473462607 16:10:07.101 2016/09/09 [ODBEdit,TALK] Alarm: RF has tripped
  • BUG: last message is not "\n" terminated (violation of the HTTP protocol?)

jgenmsg

  • JSONP: no
  • parameters:
    • &msg=message text
  • returns: string "Message successfully created\n"
  • example:
$ curl "http://localhost:8080?cmd=jgenmsg&msg=test+message"
Message successfully created
  • BUG: "Message successfully created\n" is returned even if the "msg" parameter is missing and regardless of cm_msg() error return code.

jalm

  • JSONP: no
  • parameters: no
  • returns:
    • text from alarm.c::al_get_alarms()
    • is "\n" separated list of alarms
    • alarm format is "class: text", where "class" is the alarm class, "text" is the alarm message from ODB /Alarms/alarms/xxx/
  • example:
$ curl http://localhost:8080?cmd=jalm
Alarm: Run number became too large
Warning: This is an example alarm
  • BUG: return text is "\n" terminated, array created by javascript request.responseText.split('\n') will have an extra empty element at the end.