Mat|r enables your application to access external HTTP services easily and quickly. A visual configuration accessible from Model editor links the result of a call to a HTTP service to a model in your application.

Content


Creating and configuring a new Endpoint

To create a new endpoint using the http service configuration menu click “create new endpoint”:

URL Data

By default, the main configuration screen shows the URL Data menu used to configure the following data:

  1. Name: web service call name. It must be a mat|r valid script function name.

  2. HTTP Verb: HTTP request method.

    • GET
    • POST
    • PUT
    • DELETE
    • PATCH


  1. URI: HTTP address of the service we want to consume. Here it is possible to configure parameters to be replaced at runtime using a number that matches the {n} format with n = 0,1,2…n.

Headers

The Headers tab allows you to add, check, and modify information with key/value format in the header of the HTTP request. Values configured using this method will be part of all calls made to the web service, unlike temporary headers, which may be configured using the setHeader method.


Headers encoding request body and response body

HTTP requests have 2 special headers that affect the encoding format of the information sent in the Body Request and the information to interpret from the Body Response. These 2 special headers are as follows:

  1. “Content-Type”, supported values are:
    • application/json (por defecto)
    • application/x-www-form-urlencoded
    • multipart/form-data
  2. “Accept”, supported values are:
    • application/json (por defecto)

Parameters

The Parameters tab allows you to configure parameters sent with the service request from URI or body.

QueryString parameters

Once the URL is configured with the correct format specified in the URI field, we need to use the Parameters tab to add the configuration of each parameter: name and data type. The name is used only for descriptive purposes. Their number and order of addition define the replacement location of the corresponding value in the final URI while running the .call() method .

Request body parameters

The web service may request the information in the body. This information can be sent using a model mapped and sent in the request body encoded according to the “Content-Type” configured in the Endpoint Headers. In this section you can configure the name of the model parameter under “body type”, i.e. the data type expected by the setBody() function.

During execution, it is necessary to pass the pre-call instantiated value of the model as an argument to the setBody() method. For example:

ModelParametro aModelParam = ModelParametro() //info en body request
service.nombreServicio.setBody(aModelParam)
service.nombreServicio.call()

Response

The response of a HTTP service is associated with a defined Array or model in our application. The response message format accepted by Mat|r is JSON.

In this section you can configure the following fields:

  1. Response Type:
    • Array: if the web service returns an array of objects of the same type.
    • Model: if the web service returns a single object.
    • None: if the web service has no return value or the return value must be ignored.
  2. Response Root: path from the root of the structure retrieved by the web service to the result Object/Array. Leave this field empty If the whole Object retrieved is useful.

  3. Response Model: application-defined model that stores HTTP service responses. This model must have an analog structure in the mat|r script of the JSON object returning the call to the web service.

  4. Response Mapping: in this section you can configure the relationship between the web service’s response data and the response model in the application. Just add the model attribute to the corresponding response attribute and click “+ MAP”.


Running an Endpoint

After configuring and adding a HTTP service, we can check its availability on the bar to the right under “My Endpoints”:

After configuring our Endpoints, we can access them using the namespace service, and the name of the Endpoint.
To run a specific service we must use the call(), method and the number of arguments used to configure the URI. At this point, the values of the parameters used in the call will be allocated to the ones configured (following the same order).
For example, for a “nameService” endpoint with a single String-type parameter, the call must be made as follows:

ModeloRespuesta mr = service.nombreServicio.call("aStringParam")

During a call, in the return of a HTTP request, the HTTP Status code is analyzed with two possible results:

  1. HTTP Status within the [200, 299] range**: this indicates the request was successfully received, accepted, and understood by the server. Therefore, the response is mapped to configured data type.

  2. HTTP Status outside [200, 299] range**: exception HTTPServiceError. This exception allows you to find the HTTP return code and description. There is no mapping.

Example of code with HTTP Status check:

try {
    ModeloRespuesta unModelo = service.nombreServicio.call()
    if (unModelo != null) {
        //Petición HTTP exitosa
    }    
} catch (e) {
    //error en la llamada http
    if (e.httpStatusCode() > 0) {
        //excepción http
        broker.ui.showAlert("HTTP ERROR, CODIGO: " + e.httpStatusCode().toString(), "Descripción: " + e.httpErrorMessage())
    } else {
        //Excepción no http
        broker.ui.showAlert("Excepción Inesperada", "Descripción: " + e.reason())
    }
}


PUBLIC METHODS


[Model | Array] call(Basic primerArg, Basic segArg, …)

This method uses as many parameters as used to configure the URI of the run endpoint. In the call, all parameters values will be allocated to configured ones in the same order. Then, the HTTP call is made according to all parameters configured in the Endpoint. This is a blocking call. A busy indicator displays until the call returns a model or an Array, depending on the configuration.

Arguments  
primerArg [Integer | Double | Boolean | String]: first parameter to replace to build final URI.
segArg [Integer | Double | Boolean | String]: second parameter to replace to build final URI.
Excepctions  
WrongTypeOfArgumentsInCall – Wrong {argumentNumber} argument type. Found ‘{paramType}‘, required; ‘{expectedType}’ in call of method ‘call’. It occurs when an argument in the call does not match the configured argument.
WrongNumberOfArgumentsInCall – Wrong number of arguments in call of method ‘call’. It occurs when the number of arguments in the call does not match the number of configured arguments.
ModelNotFound – Model ‘{modelName}’ not found. The name of the model configured in the response does not exist.
HTTPServiceResponseRootNotFound – Root JSON object ‘{root key}’ not found in response when calling HTTP service ‘{serviceName}’. It occurs when the “root” configured in the Response tab is not found in the web service response.
HTTPServiceResponseTypeMismatch – Type mismatch when parsing json response of HTTP service ‘{serviceName}’. It occurs when there is a mismatch between the web service response and the one expected in the attribute of the model to be mapped.
HTTPServiceError – Error when executing HTTP service ‘{serviceName}’. HTTP Code: ‘{httpCode}’, details: ‘{reason}’. HTTP response code outside [200,299] range. HTTP request not received, accepted, or understood.


void setBody(Model modelBody)

Configure the model that will be mapped and sent in the request body encoded according to the “Content-Type” configured in the Endpoint Headers.

Arguments  
modelBody Model: model to encode as information in the body of the endpoint.
Exceptions  
WrongTypeOfArgumentsInCall – Wrong {argumentNumber} argument type. Found ‘{paramType}‘, required; ‘{expectedType}’ in call of method ‘setBody’. The modelBody argument is not the Model type..


void setHeader(String key, String value)

Add parameters key/value pair to header of the request. Headers configured using this method are temporary: they will be present in the next call to the web service using the call() method and will be removed afterwards.

Arguments  
key String: key of the header.
value String: value for the key.


void removeHeader(String key)

It removes key/value pair configured in the header of the request for parameter key.

Arguments  
key String: header key.


void setDateFormatter(DateFormatter format)

Date format configured to map dates between HTTP service results and the related sofia model. If no format is configured, the following format is used by default: DateFormatter(format: “yyyy-MM-dd’T’HH:mm:ss Z”, utcTimeZoneOffset: 0 )

Arguments  
format DateFormatter: configured date format.


void addMediaFile(MediaFile media, String name, String fileName)

It adds the binary configured in the media argument to the request body to send a file to the HTTP service. The following header is added by default: “content-type”,”multipart/form-data”.

Arguments  
media MediaFile: media file configured with the binary that we want to send.
name String: name associated with the binary.
fileName String: server suggested file name.

Examples of HTTP service Configuration


GET:

The following steps show how to configure a HTTP service using the GET method to access our public ip. For this purpose, we will use the following URL: https://api.ipify.org/?format={0}, whose parameter is the format type of the response.

  1. URL Data: fill in the following fields: name, HTTP Verb, and URI.

  1. Headers: No headers are necessary in this example.

  2. Parameters: only one parameter is used (format={0})—a string called format. After its configuration in QueryString parameters we accept by clicking “+ add”:

  1. Response: to configure response type we need to analyze how the JSON response will be mapped to a Mat|r model. Example of JSON Response:
{
  "ip": "152.231.62.170"
}

We create a model that adapts to and represents json’s structure:

Model MyIp {
    String ip
}

In Response Type we fill in the following fields: type and model:

In the Response Mapping section we configure response mapping to our model, i.e. the “ip” response attribute is associated with the attribute with the same name than the response model:

Once the service is added we can consume it from our app:


Experience Main {
    String userIp label("My ip")
    Decision getMyIp action("MainContext.firstRule") label("Run")
}

Model MyIp {
    String ip
}

RuleContext MainContext {

    Rule getMyIp {

        Main m = broker.ui.getDataSource()

        //HTTP service call with just one query string param configured of type String.
        MyIp mi = service.myIp.call("json")
        m.userIp = mi.ip   //successfully HTTP request
    }
}


POST

The following steps show how to configure a HTTP service using the POST method to post an image.

For illustrative purposes, we will use a non-existent URL: http://myserver.com/upload and assume that the web service returns the final URL of the uploaded file, like the following JSON response:

{
  "filename": "saved file name"
}
  1. URL Data: fill in the following fields: name, HTTP Verb, and URI.

  1. Headers: we need to add the “content-type” / “multipart/form-data” pair, but we will do it programmatically.

  2. Parameters: we do not need to configure parameters.

  3. Response: to configure the response type we need to analyze how the JSON response will be mapped to a Mat|r model. By observing the JSON response we will define a model that adapts to and represents json’s structure:

Model Response {
    String filename
}

In Response Type we fill in the following fields: type and model:

And, then, in the Response Mapping section, we configure response mapping to our model, i.e. the “ip” response attribute is associated with the attribute with the same name than the response model:

Once the service is added, we can consume it from our app as follows:

Experience Main {
    String filename label("File name")
    Decision uploadImage action("MainContext.uploadImage") label("Upload Image")
}

//Response Model to post_image endpoint
Model Response {
    String filename
}

RuleContext MainContext {

    Rule uploadImage  {
        MediaGalleryConfigure mgc = MediaGalleryConfigure()
        MediaFile mf = broker.media.open(mgc)

        if(mf != null) {
            service.post_image.addMediaFile(mf,"image",mf.getURL())
            service.post_image.setHeader("content-type","multipart/form-data")
            Response res = Response()
            try {
                res = service.post_image.call()                
                Main m = broker.ui.getDataSource()
                m.filename = res.filename
            } catch(e) {
                broker.ui.showAlert("Ops, an exception has occurred: ", e.reason())
            }
        }
    }
}