Main Content

RESTful API for MATLAB Function Execution

The MATLAB® Production Server™ RESTful API for MATLAB function execution enables you to evaluate MATLAB functions on remote servers using JSON representation of MATLAB data types and protocol buffers. Protocol buffer support is available only in the Java® and .NET client APIs.

You can write client code that uses the MATLAB Production Server RESTful API in web-based languages such as JavaScript® and embed it in HTML pages. You can then use these web pages to send requests and retrieve responses from a MATLAB Production Server instance. While web-based applications may be more amenable to client code written in JavaScript, you can use any HTTP supported programming language such Java, Python, C++, .NET, and many others to develop client applications.

If client programs make requests from different domains, programmers using JavaScript must verify whether Cross-Origin Resource Sharing (CORS) is enabled on the server. To enable CORS on the server, the server administrator must set the appropriate value for the cors-allowed-origins property in the main_config server configuration file.

Characteristics of RESTful API

The RESTful API for MATLAB function execution uses the HTTP request-response model for communication with MATLAB Production Server. This model includes request methods, response codes, message headers, and message bodies. The RESTful API has the following characteristics:

  • The HTTP methods—POST, GET, and DELETE—form the primary mode of communication between client and server.

  • Unique Uniform Resource Identifiers (URIs) identify the resources that the server creates.

  • Message headers convey metadata such as the Content-Type of a request.

    • The API supports application/json as the HTTP Content-Type header.

    • The RESTful API for MATLAB function execution also supports application/x-google-protobuf as the HTTP Content-Type through the Java and .NET client APIs only.

  • The message body of the request contains information to be sent to the server.

    • If you use JSON as the data serialization format, inputs to the MATLAB function contained within a deployed archive are represented in JSON and encapsulated within the body of a message. For more information, see JSON Representation of MATLAB Data Types.

    • If you use protocol buffers (protobuf) for data serialization, the Java and .NET client libraries provide helper classes to internally create protobuf messages based on a proto format and return the corresponding byte array. Use this byte array in the message body of the request.

  • The message body of the response contains information about a request such as state or results.

    If you use protobuf for data serialization, the Java and .NET client libraries provide methods and classes to deserialize the protobuf responses.

  • The API supports both the synchronous and asynchronous modes of the server.

Note

The examples and graphics that follow use JSON as the data serialization format.

Synchronous Execution

In synchronous mode, after a client posts a request, the worker process of the server blocks all further requests until it has completed processing the original request. After processing is complete, the worker automatically returns a response to the client. Since it is the worker that blocks during request processing, if there are other workers available, the server can accept other synchronous requests for processing. To make a synchronous request to the server and wait for a response, use POST Synchronous Request.

The following graphic illustrates how the RESTful API works in synchronous mode.

When the server receives a request in synchronous mode, it blocks all other requests till it finishes processing the current request.

Example: Synchronous Execution of Magic Square Using RESTful API and JSON

This example shows how to use the RESTful API and JSON by providing three separate implementations—one using MATLAB, one using JavaScript and one using Python®. When you execute this example, the server returns a list of 25 comma-separated values. These values are the output of the deployed MATLAB function mymagic, represented in column-major format. The MATLAB code for the myMagic function follows.

function out = myMagic(in)
out = magic(in);
end

For this example to run, a MATLAB Production Server instance containing the deployed MATLAB function myMagic needs to be running. For more information on how to create a deployable archive, see Create Deployable Archive for MATLAB Production Server. For more information on setting up a server, see Create Server Instance Using Command Line.

HTTP Request

POST /ctfArchiveName/myMagic HTTP/1.1
Host: localhost:9910
Content-Type: application/json
Content-Length: 77

{"rhs":[4,1],"nargout":1, "outputFormat":{"mode":"small","nanType":"string"}}

Use MATLAB to Make a Request

In the code, replace localhost with your hostname, ctfArchiveName with the name of your deployable archive and myMagic with the name of your function. Save the code and run it in MATLAB. The server returns the output of the myMagic function.

url = 'http://localhost:9910/ctfArchiveName/myMagic';
payload = mps.json.encoderequest({[5]});
options = weboptions;
options.ContentType = 'text';
options.MediaType = 'application/json';
response = webwrite(url, payload, options);
result = mps.json.decoderesponse(response);
result{1}

Use JavaScript to Make a Request

You can run this JavaScript implementation of the RESTful API using Node.js®. In the code, replace localhost with your hostname, ctfArchiveName with the name of your deployable archive and myMagic with the name of your function. Save the code below as a file with the extension .js and run it with Node.js. The server returns the output of the myMagic function.

const myHeaders = new Headers();
myHeaders.append("Content-Type", "application/json");

const raw = JSON.stringify({
  "rhs": [4,1],
  "nargout": 1,
  "outputFormat": {"mode": "small","nanType": "string"}
});

const requestOptions = {method: "POST", headers: myHeaders, body: raw, redirect: "follow"};

fetch("http://localhost:9910/ctfArchiveName/myMagic", requestOptions)
  .then((response) => response.text())
  .then((result) => console.log(result))
  .catch((error) => console.error(error));

Use Python to Make a Request

You can run the following code in the Python environment of your choice. In the code, change the name of the CTF archive and function in the URL to match yours. By default, the archive name is ctfArchiveName and the function is myMagic. The code returns the output of the myMagic function running on the server.

import requests
import json

url = "http://localhost:9910/ctfArchiveName/myMagic"

payload = json.dumps({
  "rhs": [4,1],
  "nargout": 1,
  "outputFormat": {"mode": "small","nanType": "string"}
})
headers = {'Content-Type': 'application/json'}

response = requests.request("POST", url, headers=headers, data=payload)

print(response.text)

For an end-to-end workflow example of deploying a MATLAB function to MATLAB Production Server and invoking it using RESTful API and JSON, see Create Web-Based Tool Using RESTful API, JSON, and JavaScript.

Asynchronous Execution

In asynchronous mode, a client is able to post multiple requests, and in each case the server responds by creating a new resource and returning a unique URI corresponding to each request. The URI is encapsulated within the body of the response message. The client can use the URI that the server returns for querying and retrieving results among other uses.

The RESTful API calls for asynchronous mode are listed in the following table:

CallPurpose
POST Asynchronous Request

Make an asynchronous request to the server

GET Representation of Asynchronous Request

View how an asynchronous request made to the server is represented

GET Collection of Requests

View a collection of requests

GET State Information

Get state information of a request

GET Result of Request

Retrieve the results of a request

POST Cancel Request

Cancel a request

DELETE Request

Delete a request

The following graphic illustrates how the RESTful API works in asynchronous mode. The graphic does not cover all the RESTful API calls. For a complete list of calls, see the preceding table.

Asynchronous request processing

Example: Asynchronous Execution of Magic Square Using RESTful API and JSON

This example shows how to use the RESTful API and JSON for asynchronous execution using JavaScript. When you execute this example, the server returns a list of 100 comma-separated values. These values are the output of the deployed MATLAB function myMagic, represented in column-major format. The MATLAB code for the mymagic function follows.

function out = myMagic(in)
out = magic(in);
end

For this example to run, a MATLAB Production Server instance containing the deployed MATLAB function myMagic needs to be running. For more information on how to create a deployable archive, see Create Deployable Archive for MATLAB Production Server. For more information on setting up a server, see Create Server Instance Using Command Line.

Sample JavaScript code follows.

<!DOCTYPE html>
<html>
    <head>
        <title>Magic Square</title>
        <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
        <script>
            // MPS RESTful API (Asynchronous): Specify URL
            var hostname = "http://localhost:9910";
            var mode = "async";
            var clientID = "client100";
            var ctfName = "myMagic";
            var matlabFuncName = "myMagic"
            var url = hostname + "/" + ctfName + "/" + matlabFuncName + "?mode=" + mode + "&client=" + clientID;
            // Specify arguments
            var params = {
                "nargout": 1,
                "rhs": [100],
                "outputFormat": {"mode": "small"}
            };
            $.ajax(url, {
                data: JSON.stringify(params),
                //MPS RESTful API (Asynchronous): Specify Content-Type to application/json and Specify HTTP POST method
                contentType: 'application/json',
                method: 'POST',
                dataType: 'json',
                success: function(response) {
                    // Print Request URI to webpage
                    $("#requestURI").html('<strong>Request URI: </strong>' + hostname + response.self);
                    pollUsingUp(response);
                }
            });
            // Polling Server using UP
            function pollUsingUp(request) {
                setTimeout(function() {
                    var newSeq = parseInt(request.lastModifiedSeq) + 1;
                    var queryURI = hostname + request.up + "?since=" + newSeq + "&ids=" + request.id;
                    $.ajax({
                        url: queryURI,
                        method: 'GET',
                        dataType: 'json',
                        success: function(response) {
                            //Poll again if no data about the request was received.
                            if (response.data.length == 0) {
                                pollUsingUp(request);
                                return;
                            }

                            var requestResource = response.data[0];
                            // Print "state" of request
                            $("#state").html('<strong>State: </strong>' + requestResource.state);


                            if (requestResource.state != "READY" && requestResource.state != "ERROR") {
                                //Keep polling if the request is not done yet.
                                pollUsingUp(requestResource);
                            } else {
                                var requestURI = hostname + requestResource.self;
                                var responseURI = hostname + requestResource.self + "/result";
                                // Get result.
                                $.ajax({
                                    url: responseURI,
                                    // MPS RESTful API (Asynchronous): Specify HTTP GET method
                                    method: 'GET',
                                    dataType: 'json',
                                    success: function(response) {
                                        if (response.hasOwnProperty("lhs")) {
                                            $("#demo").html('<p>' +
                                                response.lhs[0] + '</p>');
                                            //Uncomment the next line if using JSON large representation
                                            //response.lhs[0].mwdata + '</p>');

                                        } else if (response.hasOwnProperty("error")) {
                                            alert("Error: " + response.error.message);
                                        }
                                        // MPS RESTful API (Asynchronous): Specify HTTP DELETE method
                                        $.ajax({
                                            url: requestURI,
                                            method: 'DELETE'
                                        });
                                    }
                                });
                            }
                        }
                    });
                }, 200);
            }
        </script>
    </head>
    <body>
        <p><strong>MPS RESTful API and JSON EXAMPLE</strong></p>
        <p> >> myMagic(5)</p>
        <p id="requestURI"></p>
        <p id="state"></p>
        <p id="demo"></p>
        <p> # output from server returned in column-major format </p>
    </body>
</html>

Manage HTTP Cookie

A MATLAB Production Server deployment on Azure® provides an HTTPS endpoint URL to invoke MATLAB functions deployed to the server. The Azure application gateway provides cookie-based session affinity, where it uses cookies to keep a user session on the same server. On receiving a request from a client program, the application gateway sets the Set-Cookie HTTP response header with information about the server virtual machine (VM) that processes the request.

Asynchronous Request Execution

A client program that uses asynchronous requests to execute a MATLAB function deployed to the server must set the Cookie HTTP request header with the value of the Set-Cookie header for all subsequent requests. This ensures that same server VM that processes the first request processes all subsequent requests for that session.

Synchronous Request Execution

A client program that uses synchronous requests to execute a MATLAB function deployed to the server must not set the Cookie HTTP request header with the value of the Set-Cookie header, and must clear the value of the Cookie header if it has been previously set. This ensures that the synchronous requests are load balanced and the same server VM does not process them.

For more information about the architecture and resources for MATLAB Production Server on Azure, see Architecture and Resources on Azure and Architecture and Resources on Azure.

Related Topics