Skip to content

Code-on-Demand in REST — The Optional Constraint for Extensible APIs

DodaTech Updated 2026-06-28 4 min read

In this tutorial, you will learn about Code. We cover key concepts, practical examples, and best practices to help you master this topic.

Code-on-demand is the only optional REST constraint, allowing servers to transfer executable code or scripts to clients to extend functionality dynamically, as seen in JavaScript, Java applets, and WebAssembly.

What You'll Learn

  • What code-on-demand means in REST
  • When and why to use code-on-demand
  • Security considerations for executable code transfer

Why It Matters

Code-on-demand lets you update client behavior without deploying new client software. A form validation script, a chart rendering library, or a business rule can be fetched from the server at runtime, enabling continuous deployment to browser-based clients.

Real-World Use

DodaTech's dashboard API includes code-on-demand for chart rendering. The API returns data plus a reference to a client-side JavaScript library for rendering. When the rendering logic changes, only the server-side script is updated. All clients automatically get the new behavior.

flowchart LR
    A["Client\nBrowser"] -->|"GET /api/dashboard"| B["API Server"]
    B -->|"JSON data\n+ script URL"| A
    A -->|"GET /scripts/chart.js"| C["Script Server"]
    C -->|"Rendering\nlibrary"| A
    A --> D["Browser renders\nchart locally"]
    style B fill:#dbeafe,stroke:#2563eb
    style C fill:#fef3c7,stroke:#d97706

Server-Side Script Provision

from flask import Flask, jsonify, send_file, request

app = Flask(__name__)

# API endpoint that returns data and a script reference
@app.route('/api/dashboard')
def get_dashboard():
    user_id = get_authenticated_user()
    data = get_dashboard_data(user_id)

    return jsonify({
        "data": data,
        "scripts": [
            {
                "url": "/scripts/chart-renderer.js",
                "version": "2.1.0",
                "integrity": "sha384-abc123...",
                "type": "text/javascript"
            },
            {
                "url": "/scripts/data-transformer.js",
                "version": "1.0.5",
                "integrity": "sha384-def456..."
            }
        ],
        "styles": [
            {
                "url": "/styles/dashboard.css",
                "version": "1.0.0"
            }
        ]
    })

# Serve the executable scripts
@app.route('/scripts/<path:script_name>')
def get_script(script_name):
    script_path = f"/opt/app/scripts/{script_name}"
    response = send_file(script_path, mimetype='text/javascript')
    response.headers['Cache-Control'] = 'public, max-age=3600'
    response.headers['Content-Security-Policy'] = "script-src 'self'"
    return response

Client-Side Script Loading

// Client dynamically loads scripts from the API
async function renderDashboard() {
  const response = await fetch('/api/dashboard');
  const dashboard = await response.json();

  // Load required scripts dynamically
  for (const script of dashboard.scripts) {
    await loadScript(script.url, script.integrity);
  }

  // Load styles
  for (const style of dashboard.styles) {
    await loadStyle(style.url);
  }

  // Execute chart rendering (code-on-demand)
  if (typeof renderChart !== 'undefined') {
    renderChart(dashboard.data, '#chart-container');
  }
}

function loadScript(url, integrity) {
  return new Promise((resolve, reject) => {
    const script = document.createElement('script');
    script.src = url;
    script.integrity = integrity;
    script.crossOrigin = 'anonymous';
    script.onload = resolve;
    script.onerror = reject;
    document.head.appendChild(script);
  });
}

Security with Subresource Integrity

import hashlib
import base64

def compute_integrity(filepath):
    """Compute SHA-384 hash for subresource integrity"""
    with open(filepath, 'rb') as f:
        content = f.read()
    digest = hashlib.sha384(content).digest()
    b64_hash = base64.b64encode(digest).decode()
    return f"sha384-{b64_hash}"

# Generate integrity hashes for all scripts
scripts = {
    "chart-renderer.js": compute_integrity("/opt/app/scripts/chart-renderer.js"),
    "data-transformer.js": compute_integrity("/opt/app/scripts/data-transformer.js")
}

for name, integrity in scripts.items():
    print(f"{name}: {integrity}")

Common Mistakes

1. Requiring JavaScript for API Functionality

Code-on-demand is optional. Your API must work without executing any transferred code. Only enhance functionality with scripts.

2. Not Using Subresource Integrity

Without SRI hashes, an attacker who compromises the script server can inject malicious code. Always include integrity hashes.

3. Mixing Code and Data in Responses

Returning executable code mixed with JSON data creates security risks. Separate data (JSON) from scripts (JavaScript files).

4. Ignoring CSP (Content Security Policy)

If your clients use CSP, transferred scripts must be allowed by the policy. Set appropriate script-src directives.

5. Not Versioning Scripts

Without versioning in script URLs, cached scripts may conflict with updated API responses. Use versioned URLs.

Practice Questions

  1. Is code-on-demand a mandatory REST constraint?
  2. What is subresource integrity and why is it important?
  3. How do you separate code from data in a REST response?
  4. Why must the API work without executing transferred code?
  5. How do you version scripts for code-on-demand?

Answers

  1. No, it is the only optional REST constraint. 2. A hash that verifies the script hasn't been tampered with. 3. Return data in JSON, script URLs as metadata, not embedded code. 4. Because code-on-demand is optional and may not be supported by all clients. 5. Include version identifiers in script URLs or use content-based hashes.

Challenge

Build an API that demonstrates code-on-demand: a report generation endpoint returns data plus a reference to a client-side rendering script. The script version is determined by the API, and different API versions may return different script versions. Include SRI hashes and CSP headers.

FAQ

What is code-on-demand in REST?

The optional constraint that allows servers to transfer executable code to clients to extend functionality.

Is code-on-demand commonly used in REST APIs?

Less common than the other constraints, but used in web applications that serve JavaScript rendering code.

What is subresource integrity?

A security feature that lets browsers verify fetched scripts haven't been modified using cryptographic hashes.

Can code-on-demand be used with mobile apps?

Yes, through mechanisms like JavaScriptCore (iOS) or WebView-based scripting.

Why is code-on-demand optional?

Because not all clients can execute code, and REST must work for all clients.

Mini Project

Build a dynamic dashboard API that uses code-on-demand: the API endpoint returns dashboard data and references to chart rendering scripts, scripts are served with versioned URLs and SRI hashes, clients dynamically load and execute scripts, and the API continues to work without executing any scripts (returns raw data for non-JS clients).

What's Next

  • Learn about resource naming conventions for consistent URI design
  • Explore resource relationships and sub-resources
  • Continue to HTTP methods reference for RESTful CRUD operations

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro