Snakking REST Pub

Snakking

Interacting with 3rd party REST services can quickly be done via "snakking".

Easy way to snakk json/xml

You can snakk content from sockets or HTTP servers directly by calling these:

$msg snakk.json (url,verb,body,headers,result) : (payload)
$msg snakk.xml (url,verb,body,headers,result) : (payload)
$msg snakk.text (url,verb,body,headers,result) : (payload)

`result` is an optional name of a variable you want the result in, otherwise it goes to `payload`

Here's a sample POST (using oauth to get a token):

$when api.getAccessToken
=> snakk.json(
    url="${AUTH_URL}", 
    verb="POST", 
    'Content-type'="application/x-www-form-urlencoded",
    body="grant_type=client_credentials&client_id=${CLIENT_ID}&client_secret=${CLIENT_SECRET_ENC}&resource=${RESOURCE}/"
    )
=> (accessToken=payload.access_token)

The payload result of snakk.json is of type JSON and you can see the last expression extracts something from it (the access_token) - see Structural expressions++ for details.

Obsolete: Any parameter other than url/verb/body/result will be sent as a header value - you can send headers like Content-Type or Authorization and others.

You should now use the headers i.e. snakk.json(..., headers={Authorization:"nobody"})

Here's a sample GET (no verb or body needed):

$when annoy.the.googlenauts
=> snakk.json(
    url="https://www.google.ca"
    )

This is a very straight-forward way to send content to HTTP servers and receive and use content from them. For more advanced template based snakking, see below.

Snakk results

The main response from snakk is available as payload with the appropriate type (string or json) and other details in this structure:

  • snakk.response
    • headers
    • code

So that you can check response headers with snakk.response.headers.myHeader.

Obsolete: in older versions you also had these values populated: snakkHttpResponse, snakkHttpHeaders, snakkHttpCode.

Snakk options

Codes

Snakk will create errors if the response is not 200. To allow for specific codes, use:

=> snakk.json(
    url="https://www.google.ca",
    snakkHttpOptions={responseCode:"201"}
    )

Or:

=> snakk.json(
    url="https://www.google.ca",
    snakkHttpOptions={responseCode:"*"}
    )

timeout

The default timeout is 30 seconds. To change it, use readTimeout:

=> snakk.json(
    url="https://www.google.ca",
    snakkHttpOptions={responseCode:"*",readTimeout:"60000"}
    )

Note that readTimeout is restricted and may require a paid plan.

Template-based snakking

This includes stuff like templates for sending and receiving content, automatically parsing values and other. Read on...

Use templates for custom URL and content

Alternatively, to control how the URL looks like, as well as the header attributes and content of the call, define a template with the same name as the message:

$msg subDb.load (subId) : (payload)
{{template subDb.load:request}}
GET http://localhost:9000/diesel/fiddle/react/subDb/load?subId=${subId}&resultMode=json
sso_token : joe 123456
{{/template}}

OR a POST

{{template subDb.load:request}}
POST http://localhost:9000/diesel/fiddle/react/subDb/load?subId=${subId}&resultMode=json
sso_token : joe 123456

body of post
{{/template}}

In the templates:

  • you can use values with ${subId}
  • you can add request parms
  • you can add header attributes like sso_token

Identifying JSON or XML content

For sending, you specify the Content-Type as a template attribute. Also as a header attribute.

For receiving: first, the content-type will be inspected, for known associations. If no content-type was available, the content itself will be inspected to look for either "{..." or "<?xml...".

Snakking JSON/XML content (on the response path)

You can use xpath/jsonpath to introspect the replies, given:

$msg myservice.auth(account) : (success,msg)

These work:

{{template myservice.auth:response,content-type="application/xml",success=RESPONSE.TRANSUCCESS,msg=RESPONSE.TRANRESPMESSAGE}}
{{/template}}

or

{{template myservice.auth:response,content-type="application/xml",success=RESPONSE/TRANSUCCESS,msg=RESPONSE/TRANRESPMESSAGE}}
{{/template}}

or 

$msg myservice.auth(account) : (success=xp:RESPONSE/TRANSUCCESS,msg)

or

$msg myservice.auth(account) : (success=RESPONSE.TRANSUCCESS,msg)

The response, as long as it can be identified as JSON or XML, will be parsed and the expression will be resolved, if possible.

Diesel snakking

Let's say we have a simple service which will add two numbers:

This is the actual service:

$mock demo.sum(p1,p2) => (sum=p1+p2)

And this is a new message, which will snakk the previous service, when invoked:

$msg <GET> demo.getsum(url="/diesel/wreact/Topic:Snakking_REST/react/demo/sum?resultMode=value&dfiddle=snak1&p1=a&p2=b", regex="/(?<sum>.*)/") : (sum)

This is another version, where we use a domain-level message, decomposed into a snakk:

$when demo.getsum2(p1,p2) 
=> demo.getsum(url="/diesel/wreact/Topic:Snakking_REST/react/demo/sum?resultMode=value&dfiddle=snak1&p1="+p1+"&p2="+p2)

We will define a message to get the sum, which will "snakk" it from its url and then a test to actually run it and test the resulting sum.

Invoke the snakking message and verify results:

$send demo.getsum ()
$expect (sum is "ab")


$send demo.getsum2 (p1="c",p2="d")
$expect (sum is "cd")

When the test ran, it actually made a REST call to the backend to invoke demo.snakking.getsum which in turn made another REST call to snakk the demo.snakking.sum.

Easy?

$msg <GET> demo.snakking.sum(p1,p2,url="http://localhost:9000/diesel/fcall/func/Spec:fiddle?p1=aa&p2=b") : (sum)
$msg <GET> snakking.func(p1,p2,url="http://localhost:9000/diesel/fcall/func/Spec:fiddle?p1=aa&p2=b") : (sum)

This works for interacting with other diesel services, or any service that returns a simple json:

  • the url parm
  • the return parm name "sum"

JSON content is default. The content must contain a normal diesel output and values will be located under values. For instance, the result subId could be found in this reply:

{
 "values": {
  "subId":"sub123456",
  "name":"$name",
  "address":"$address"
 },
 "failureCount":"0",
 "errors": [  "Can't find the spec for rest.mcreate"],
 "dieselTrace": {
  "root":  {
   "children":   [
...

as well as in this one:

{
  "subId":"sub123456",
  "name":"$name",
  "address":"$address"
 }

Snakking any content

If the two methods above fail, you can use regex to identify output values. Use group names to identify value names. Pass the one regex via a parameter called surely enough, regex.

The regex must match the entire reply (use lots of . and *) and have named capture groups and the names of the capture groups must match the return parms defined in the message signature. Here's a regex example with named group subId: (?<subId>\w+)

$msg<GET> c.op(url="http://localhost:9000/diesel/wiki/Spec:rest_spec/react/rest/mcreate?name=$name&address=$address&resultMode=json") : (subId, regex="/.*subId...(?<subId>\w+).,.*/")

With templates, use a regex template parm, which contains the regex, using the same named groups:

{{template ifttt.event1 regex=/(?<res>.*)/}}

These parms must also be listed as the result of the message, in the message spec.

Parsing content

If you already have some content and need to just parse it, these can help.

Parsing json:

$send snakk.parse.json

This will parse a string payload into a JSON payload.

Parsing regex:

$send ctx.set(payload="{\"status\":\"Failed\"}")
$send snakk.parse.regex (regex=/(?s)\{.*status":"(?<status>[^"]*)".*/)
$expect (status is "Failed")

This will attempt to parse the named groups into values with the same name and put them back in the same context.


Was this useful?    

By: Razie | 2017-08-28 .. 2023-07-09 | Tags: academy , reference , dsl , story


Viewed 1015 times ( | History | Print ) this page.

You need to log in to post a comment!

© Copyright DieselApps, 2012-2024, all rights reserved.