# Route

Routes are overridden by name and weight, and sorted by priority (desc), then by weight (desc).

```javascript
class MyRoute {

  @route('GET c_340_ping', {
    name: 'c_340_get',
    weight: 1
  })
  static get({ req, res, body, next, runtime }) {

    return true

  }

  @route({
    weight: 1,
    method: 'POST',
    name: 'c_340_post',
    path: 'c_340_ping',
    acl: 'role.administrator'
  })
  post({ req, res, body, next, runtime }) {

    return body('myData')

  }

}
```

#### @route(options)

*Arguments*

* `options` { Object } Options object
  * `name` { String }
  * `type` { String }
  * `principal` { String }
  * `environment` { String = *"\*"* }
  * `weight` { Number = *0* }
  * `method` { String }
  * `path` { String }
  * `authValidation` { Object }
  * `urlEncoded` { String }
  * `plainText` { String }
  * `apiKey` { String }
  * `priority` { Number }

#### @route(routeIdentity, options)

*Arguments*

* `routeIdentity` { String } A string defining the route method using the format `"<method> <path>"`
* `options` { Object } Options object
  * `name` { String }
  * `type` { String }
  * `principal` { String }
  * `environment` { String = *"\*"* }
  * `weight` { Number = *0* }
  * `authValidation` { Object }
  * `urlEncoded` { String }
  * `plainText` { String }
  * `apiKey` { String }
  * `priority` { Number }

#### Method Options

* `methodOptions` { Object } Options passed to the method
  * `req` { Object }
  * `res` { Object }
  * `body` { Object }
  * `next` { Function }
  * `runtime` { Object }
    * `name` { String }
    * `type` { String }
    * `principal` { String }
    * `environment` { String = *"\*"* }
    * `weight` { Number = *0* }
    * `configuration` { Object }
      * `method` { String }
      * `path` { String }
      * `authValidation` { Object }
      * `urlEncoded` { String }
      * `plainText` { String }
      * `apiKey` { String }
      * `priority` { Number }
      * `acl` { String }
    * `metadata` { Object }
      * `resource` { String }
      * `className` { String }
      * `methodName` { String }
      * `static` { Boolean }
      * `loc` { Object }
        * `line` { String }
        * `column` { String }

**body(key, value)**

Accessor for the script API's body

* `key` { string } Key associated to a useful value
* `value` { Object | number | string | boolean = *undefined* } If defined, will create an association between the key and value

**Example**

```javascript
const data = body('myData')
```

**next(err)**

Calls the API route's next method.

```javascript
script.api.route.next(err)
```

* `err` { Object = *null* } Error object

## Route Layering

```javascript
class Ping extends CortexObject {
​
  // run first no api key set, will use that of the caller.
  @log({ traceError: true })
  @route('* *', { priority: 999 })
  static count({ req, res, next, runtime }) {

    try {  
        res.setHeader('Content-Type', 'application/x-ndjson')
    } catch(err) {}

    res.write(JSON.stringify({
        route: `${runtime.configuration.method} /routes/${runtime.configuration.path}`,
        key: req.client.key,
        principal: script.principal.email,
        resource: runtime.metadata.resource
    })+'\n')

    next()    
  }

  // run second, but only if pingCount is 1. pins the app to c_dashboard
  @log({ traceError: true })
  @route('POST pingCount/1', {
    apiKey: 'c_dashboard',
    priority: 2
  })
  static countAgain({ req, res, next, runtime }) {

    try {  
        res.setHeader('Content-Type', 'application/x-ndjson')
    } catch(err) {}

    res.write(JSON.stringify({
        route: `${runtime.configuration.method} /routes/${runtime.configuration.path}`,
        key: req.client.key,
        principal: script.principal.email,
        resource: runtime.metadata.resource
    })+'\n')

    next()    

  }
​
  // run last
  @log({ traceError: true })
  @route('POST pingCount/:num', { priority: 1  })
  static countOnceMore({ req, res, runtime }) {

    try {  
        res.setHeader('Content-Type', 'application/x-ndjson')
    } catch(err) {}

    res.write(JSON.stringify({
        route: `${runtime.configuration.method} /routes/${runtime.configuration.path}`,
        key: req.client.key,
        principal: script.principal.email,
        resource: runtime.metadata.resource
    })+'\n')

  }

}
```

### Result

{% tabs %}
{% tab title="mdctl ndjson" %}

```bash
$> mdctl api POST /routes/pingCount --ndjson
{"route":"* /routes/*","key":"MedableWebAppClientKey","principal":"james@medable.com","resource":"script#type(library).name(c_ping_library).runtime.@route 57:2"}
{"route":"post /routes/pingCount/1","key":"kw30gTF8kXDIiPJYemlDBj","principal":"james@medable.com","resource":"script#type(library).name(c_ping_library).runtime.@route 71:2"}
{"route":"post /routes/pingCount/:num","key":"kw30gTF8kXDIiPJYemlDBj","principal":"james@medable.com","resource":"script#type(library).name(c_ping_library).runtime.@route 86:2"}
```

{% endtab %}

{% tab title="mdctl tail" %}

```bash
$> mdctl tail
{"timestamp":"2020-01-28T23:46:45.398Z","level":"info","message":[{"className":"Ping","methodName":"countAgain","lineNumber":70,"ms":6.93505859375}]}
{"timestamp":"2020-01-28T23:46:45.618Z","level":"info","message":[{"className":"Ping","methodName":"count","lineNumber":56,"ms":6.615966796875}]}
{"timestamp":"2020-01-28T23:46:45.828Z","level":"info","message":[{"className":"Ping","methodName":"countOnceMore","lineNumber":85,"ms":3.302001953125}]}
```

{% endtab %}
{% endtabs %}
