AJAX

From MidasWiki
Jump to navigation Jump to search


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.