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 returns 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 two separate implementations—one using JavaScript and the other 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.

JavaScript Implementation

With the JavaScript implementation of the RESTful API, you include the script within the <script> </script> tags of an HTML page. When you open this HTML page in a web browser, the server returns the values of the mymagic function. Note that the server needs to have CORS enabled for JavaScript code to work. For more information on how to enable CORS, see cors-allowed-origins.

A sample HTML code with embedded JavaScript follows.

<!DOCTYPE html>
<html>
    <head>
        <title>Magic Square</title>
        <script>
            var request = new XMLHttpRequest();
            //MPS RESTful API: Specify URL
            var url = "http://localhost:9910/ctfArchiveName/mymagic";
            //MPS RESTful API: Specify HTTP POST method
            request.open("POST",url);
            //MPS RESTful API: Specify Content-Type to application/json
            request.setRequestHeader("Content-Type", "application/json");
            var params = { "nargout": 1,
                           "rhs": [5] };
            request.send(JSON.stringify(params));
            request.onreadystatechange = function() {
                 if(request.readyState == 4) 
                 {	 //MPS RESTful API: Check for HTTP Status Code 200
                    if(request.status == 200) 
                    {	  result = JSON.parse(request.responseText);
                       if(result.hasOwnProperty("lhs")) {
                       //MPS RESTful API: Index into "lhs" to retrieve response from server
                       document.getElementById("demo").innerHTML = '<p>' + result.lhs[0].mwdata; }
                    }
                       else if(result.hasOwnProperty("error")) {
                       alert("Error: " + result.error.message); }
                 }
            };
        </script>
    </head>
    <body>
        <p>MPS RESTful API and JSON EXAMPLE</p>
        <p> >> mymagic(5)</p>
        <p id="demo"></p>
        <p> # output from server returned in column-major format </p>
    </body>
</html>

Python Implementation

This example uses Python 2.x. If you are using Python 3.x, you must change some portions of the code.

Sample Python code follows.

#!/usr/bin/python
#This example uses Python 2.x
#In Python 3.x use:
#import http.client
#conn = http.client.HTTPConnection("localhost:9910") 

import httplib
import json
 
conn = httplib.HTTPConnection("localhost:9910")
headers = { "Content-Type": "application/json"}
body = json.dumps({"nargout": 1, "rhs" : [5]})
conn.request("POST", "/ctfArchiveName/mymagic", body, headers)
response = conn.getresponse()
if response.status == 200:
   result = json.loads(response.read())
   if "lhs" in result:
     print("Result of magic(5) is " + str(result["lhs"][0]["mwdata"]))
   elif "error" in result:
     print("Error: " + str(result["error"]["message"]))

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 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.

A sample HTML code with embedded JavaScript 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