Community discussions

MikroTik App
 
sssuperman
just joined
Topic Author
Posts: 2
Joined: Fri May 18, 2018 3:54 pm

Feature Request : OpenAPI for REST API

Thu May 27, 2021 11:10 am

Hi

It is glad to have REST API for new RouterOS beta v7.

We are trying to implement REST API automation for RouterOS V7 but we found there is a lot of effort to research API usage to map with command interface.

I was wondering if we can have OpenAPI specification json document to speed up development for user.



Chang
 
User avatar
Amm0
Forum Guru
Forum Guru
Posts: 3169
Joined: Sun May 01, 2016 7:12 pm
Location: California

Re: Feature Request : OpenAPI for REST API

Mon Feb 28, 2022 7:34 pm

Did you ever find one OpenAPI or swagger doc for the REST API? Has someone already built one already?
 
User avatar
stevenjacobs
just joined
Posts: 7
Joined: Wed Nov 04, 2015 5:14 pm
Contact:

Re: Feature Request : OpenAPI for REST API

Mon Oct 31, 2022 3:44 pm

+1. Also looking for this. Any news yet?
 
User avatar
mrz
MikroTik Support
MikroTik Support
Posts: 7038
Joined: Wed Feb 07, 2007 12:45 pm
Location: Latvia
Contact:

Re: Feature Request : OpenAPI for REST API

Tue Nov 01, 2022 9:32 am

Maybe this is useful? You can get the list by calling:
http://ros_adrese/webfig/list
 
User avatar
Amm0
Forum Guru
Forum Guru
Posts: 3169
Joined: Sun May 01, 2016 7:12 pm
Location: California

Re: Feature Request : OpenAPI for REST API

Tue Nov 08, 2022 5:43 pm

Maybe this is useful? You can get the list by calling:
http://ros_adrese/webfig/list
Thanks @mrz – that's useful. More so for pragmatically creating skins (since /webfig/list seems to match values that go in the a "skin" file).

But it's a bit away from being usable in REST tools like Postman, etc.....

Still helpful however: the files referenced by the /webfig/list actually list all the attributes, which is useful. But the JG file output seems to use the "Webfig" names (make sense given context), but doesn't seem to contain anywhere the equivalent CLI/REST name (e.g. "DHCP Client" vs. "dhcp-client") so any transformation need to map those, somehow. That seems like a big project.

If this helps anyone, I wrote some JavaScript code to parse the output – since /webfig/list doesn't seem to be modern JSON (but similar to the "webfig skin JSON" format) you need eval() to parse the output. I don't do anything with it, but you can at least view it more reasonably. OR, perhaps collect some from various versions to compare the schema deltas release to release.


Image

function webfiglist(ip) {
  if (typeof window === "object" && !ip) {
    ip = (new URL(window.location.href)).host
  }
  return new Promise((done) => {
    fetch(`http://${ip}/webfig/list`)
      .then((req) => req.text())
      .then((txt) => {
        var results = {};
        /* this is critical... 
               the /webfig/list is not valid JSON document, it's a JS "fragment" 
               ...so we need eval() to "convert it" to a variable to then return */
        eval(`results = [${txt}]`);
        done(results);
      });
  });
}

function webfigschemas(ip) {
    if (typeof window === "object" && !ip) {
        ip = (new URL(window.location.href)).host
   }  
   return webfiglist(ip).then((list) =>
    Promise.all(
      list
        .filter((i) => i.unique)
        .map((i) => {
          return new Promise((done) => {
            let file = i.name
            fetch(`http://${ip}/webfig/${file}`)
              .then((req) => req.text())
              .then((txt) => {
                /* same eval() trick as the webfiglist, except return a "tuple" with [filename, data] */
                var results
                eval(`results = ${txt}`)
                done([ file, results ])
              })
          })
        })
    )
  )
}


webfiglist().then(console.log)
webfigschemas().then(console.log)

// NODE.JS save to file
// let ip = "192.168.88.1"
// const fs = require('fs');
// webfigschemas(ip).then(d => fs.writeFileSync("./webfig-list-schema.json", JSON.stringify(d)))




If you paste that into JavaScript console from a browser "Inspect" option while on webfig page, it should show the "schema data" in the console output. If you use nodeJS, you should be able pass an ip address to the webfiglist("192.168.88.1") to get it from any RouterOS device (might be possible in browser, but cross-site scripting checks would need tweaks).
 
User avatar
mrz
MikroTik Support
MikroTik Support
Posts: 7038
Joined: Wed Feb 07, 2007 12:45 pm
Location: Latvia
Contact:

Re: Feature Request : OpenAPI for REST API

Tue Nov 08, 2022 5:59 pm

Another useful tool could be /console/inspect.
You can request completion, the list of child menu commands and parameters
 
User avatar
Larsa
Forum Guru
Forum Guru
Posts: 1025
Joined: Sat Aug 29, 2015 7:40 pm
Location: The North Pole, Santa's Workshop

Re: Feature Request : OpenAPI for REST API

Tue Nov 08, 2022 8:16 pm

Interesting, are inspect request=child and other related features documented anywhere?
 
User avatar
mrz
MikroTik Support
MikroTik Support
Posts: 7038
Joined: Wed Feb 07, 2007 12:45 pm
Location: Latvia
Contact:

Re: Feature Request : OpenAPI for REST API

Tue Nov 08, 2022 9:03 pm

It's an easter egg :)
 
User avatar
Amm0
Forum Guru
Forum Guru
Posts: 3169
Joined: Sun May 01, 2016 7:12 pm
Location: California

Re: Feature Request : OpenAPI for REST API

Wed Nov 09, 2022 3:47 pm

It's an easter egg :)
Except now we can find them ;)

It's not critical for my needs, but I wrote some code to pull out all the "chicks" ( request=child) in the /console/inspect.

It uses recursion with a ROS function to walk the tree of "child" and returns a ROS ::array (& shoves it into a :global variable called "$ast" too). Surprisingly this DOES NOT get ANY stack overflow or memory limits, at least in v7.6. In fact, after walking the tree, even on a little cAP ac, there are 4329 unique "cmd", "args", and "path" branches, with a few leafs each.
:global ast [:toarray ""]

:global mkast do={
    :global mkast
    :global ast
    :local path "" 
    :if ([:typeof $1] ~ "str|array") do={ :set path $1 }
    :local pchild [/console/inspect as-value request=child path=$path]
    :foreach k,v in=$pchild do={
        :if (($v->"type") = "child") do={
            :local astkey ""
            :local arrpath [:toarray $path]
            :foreach part in=$arrpath do={
                :set astkey "$astkey/$part"
            }
            :set ($ast->$astkey->($v->"name")) $v
            :put "Processing: $astkey $($v->"name") $($v->"node-type")"
            :local newpath "$($path),$($v->"name")"
    		# TODO use [/console/inspect as-value request=syntax path=$path]
            [$mkast $newpath]
        }
    }
    return $ast
}

# & this call start the recursion 
:put [$mkast]

$ast will also contain the schema as an nested array, reflecting the parent/child relationships... so can use like this:
 :put ($ast->"/ip/address")
 
add=.id=*2;name=add;node-type=cmd;type=child;comment=.id=*3;name=comment;node-type
=cmd;type=child;disable=.id=*4;name=disable;node-type=cmd;type=child;edit=.id=*5;n
ame=edit;node-type=cmd;type=child;enable=.id=*6;name=enable;node-type=cmd;type=chi
ld;export=.id=*7;name=export;node-type=cmd;type=child;find=.id=*8;name=find;node-t
ype=cmd;type=child;get=.id=*9;name=get;node-type=cmd;type=child;print=.id=*a;name=
print;node-type=cmd;type=child;remove=.id=*b;name=remove;node-type=cmd;type=child;
reset=.id=*c;name=reset;node-type=cmd;type=child;set=.id=*d;name=set;node-type=cmd
;type=child

Another example, this is one part of the output $ast array above in YAML-ized style output:
/zerotier/edit:
    number:
      .id: *2
      name: number
      node-type: arg
      type: child
    value-name:
      .id: *3
      name: value-name
      node-type: arg
      type: child
  /zerotier/enable:
    numbers:
      .id: *2
      name: numbers
      node-type: arg
      type: child

I don't do it here, but adding another call to "/console/inspect request=syntax ..." for each child with same path would get a description (e.g. type of "explanation"). With that you'd have all the info for a REST schema. My thought is RAML might be easier to generate from ROS script, since it uses "YAML format", not JSON, and YAML is easier to generate in ROS script. I think the keys from my code are close to the REST POST things, so that be easiest to model into RAML. And I believe some tools can use or convert from the RAML schema format to swagger / OpenAPI.

But /console/inspect does seem to have the info for a REST schema, now converting is still more work.

One note is /console/inspect seems to know about ALL of the packages (e.g. "extra-packages"), even if not installed – so you'll see child entries for calea, iot, etc. even if not available.
 
User avatar
Larsa
Forum Guru
Forum Guru
Posts: 1025
Joined: Sat Aug 29, 2015 7:40 pm
Location: The North Pole, Santa's Workshop

Re: Feature Request : OpenAPI for REST API

Wed Nov 09, 2022 4:07 pm

Great info, thanks! It seems that the metadata proxy-repository is pretty coherent and well worth exploring for building a command tree for automatic integration. I concur regarding RAML.
 
User avatar
Amm0
Forum Guru
Forum Guru
Posts: 3169
Joined: Sun May 01, 2016 7:12 pm
Location: California

Re: Feature Request : OpenAPI for REST API

Mon Nov 14, 2022 12:34 am

Took another look at this today, thought it be easy to get the "explanation".

While "request=child" works with issue, some "request=syntax" (e.g. "path=ip,address,add,interface", see below), cause the entire terminal to terminate ("Console has crashed; please log in again.") – most things seem to work with request=syntax.
[user@router] > /console/inspect request=syntax path=ip,address,add
Columns: TYPE, SYMBOL, SYMBOL-TYPE, NESTED, NONORM, TEXT
TYPE    SYMBOL     SYMBOL-TYPE  NESTED  NONORM  TEXT                                   
syntax             collection        0  yes                                            
syntax  address    explanation       1  no      Local IP address                       
syntax  broadcast  explanation       1  no      Broadcast address                      
syntax  comment    explanation       1  no      Short description of the item          
syntax  copy-from  explanation       1  no      Item number                            
syntax  disabled   explanation       1  no      Defines whether item is ignored or used
syntax  interface  explanation       1  no      Interface name                         
syntax  netmask    explanation       1  no      Network mask                           
syntax  network    explanation       1  no      Network prefix                         
[user@router] > /console/inspect request=syntax path=ip,address,add,address
Columns: TYPE, SYMBOL, SYMBOL-TYPE, NESTED, NONORM, TEXT
TYPE    SYMBOL   SYMBOL-TYPE  NESTED  NONORM  TEXT                   
syntax  Address  definition        0  no      A.B.C.D    (IP address)
[user@router] > /console/inspect request=syntax path=ip,address,add,interface

Console has crashed; please log in again.
Even wrapping it a ":do {} on-error={}" does NOT catch the crash so that didn't work to avoid the issue.
:do {
   /console/inspect request=syntax path=ip,address,add,interface
} on-error={:put "got error"}

While that would not be critical for schema per-se, it does have a description to set, and there is some "collection" node-type that likely indicates an possible array (instead of just string) as JSON param.


FWIW you can call the same /console/inspect via REST API too. But the same params in REST "{ "request": "syntax", "path": "ip,address,add,interface" } while don't "crash" it timeouts with no data (empty JSON array).

In fact, here the RAML for just the /console/inspect:
#%RAML 1.0
title: ROS.RAML sample
version: 7.6
protocols: [HTTPS]
mediaType: [application/json]
securitySchemes:
  basic:
    description: |
      Mikrotik REST API only supports Basic Authentication, secured by HTTPS
    type: Basic Authentication
securedBy: [basic]
baseUri: https://{host}:{port}/rest
baseUriParameters:
  host:
    description: RouterOS device IP or host name
    default: "192.168.88.1"
  port:
    description: RouterOS https port to use
    default: "443"
documentation:
  - title: RouterOS RAML Schema
    content: |
      Schema is generated using `/console/inspect` on a RouterOS devices and
      interpreted into a schema based on the rules in
      [Mikrotik REST documentation](https://help.mikrotik.com)
  - title: Demo Only
    content: We just try a few commands 

/console:
  /inspect:
    post:
      description: Inspects the RouterOS AST
      body:
        application/json:
          type: object
          properties:
            .proplist?:
              type: string
              description: List of properties to return (see RouterOS docs)
            .query?:
              type: string
              description: List of properties to return (see RouterOS docs)
            path?:
              type: string
              description: Comma-seperated string of RouterOS path
              example: 
            input?:
              type: string
            request:
              type: string
              enum: [self|child|completion|highlight|syntax|error]
          example:
              path: "ip,address,add,interface"
              request: syntax
      responses:
        200:
          body:
            application/json:
              type: array
 
User avatar
Amm0
Forum Guru
Forum Guru
Posts: 3169
Joined: Sun May 01, 2016 7:12 pm
Location: California

REST API schema in RAML 1.0 format

Mon Sep 11, 2023 6:00 am

I kinda forgot about this one. But I do have a JavaScript implementation that using /system/console via REST, and generate a RAML 1.0 scheme.

See viewtopic.php?t=199476 for RAML-based alternative.

edit: I noticed this was the beta forum, so moved the RAML approach to new thread in Scripting topic
 
User avatar
Amm0
Forum Guru
Forum Guru
Posts: 3169
Joined: Sun May 01, 2016 7:12 pm
Location: California

Re: Feature Request : OpenAPI for REST API

Mon Sep 11, 2023 8:49 pm

Here is an OpenAPI schema I generated from above RAML schema.

OpenAPI 3.0 / swagger schema
https://tikoci.github.io/restraml/route ... napi3.json

It may have some calls that aren't allowed, and other things may not have translated perfectly. But it loads:
 
brotherdust
Member Candidate
Member Candidate
Posts: 130
Joined: Tue Jun 05, 2007 1:31 am

Re: Feature Request : OpenAPI for REST API

Thu Dec 14, 2023 10:55 pm

Here is an OpenAPI schema I generated from above RAML schema.

OpenAPI 3.0 / swagger schema
https://tikoci.github.io/restraml/route ... napi3.json

It may have some calls that aren't allowed, and other things may not have translated perfectly. But it loads:
Wow! Thank you nice work!

Who is online

Users browsing this forum: No registered users and 21 guests