Change in the way model name is encoded in URI

2 minute read

Using model names as-is (without modification) when bound to ExpressJS API has been deprecated since the API Builder - Osaka release.

Beginning in the Osaka release, model names will be percent-encoded according to RFC-3986 for auto-generated Model API.

Why we are making this change

Currently, model names are bound to auto-generated Model API paths for ExpressJS without any encoding. According to RFC-3986, characters not in A-Z a-z 0-9 - _ . ~, should be percent-encoded when included in a URI. So, for example, currently a model named “employee’s” will be bound to an ExpressJS API as /api/employee's. Many NodeJS libraries will automatically encode requests to /api/employee's, as /api/employee%27s, which can make calling the API difficult from NodeJS applications (API Builder will return 404 because it is not listening on /api/employee%27s). However, some HTTP clients, such as cURL, are less strict and permit non-RFC-3986 URI. To make API Builder standards compliant and consistent with respect to model names, when API Builder needs to encode model names into a URI, they will be encoded as per RFC-3986.

How does this impact my service

Models that have auto-generated API can potentially have a different API, and clients that would previously succeed in calling affected API will fail. This is especially true for models that are generated from the database connectors. For example, “oracle/employee” will be bound to API /api/oracle%2Femployee. Most manually created model names are probably generally safe. You can test your model names with the encodeURIComponentRFC3986 function below:

// Encode URI Component RFC-3986

/**
 * Encodes a URI component using a more strict RFC3986 encoding.
 *
 * @param {string} str - The string to encode.
 * @return {string} The RFC3986 encoded component.
 */
function encodeURIComponentRFC3986(str) {
  return encodeURIComponent(str).replace(/[!'()*]/g, function (c) {
    return `%${c.charCodeAt(0).toString(16)}`;
  });
}

If the function produces a different name, then your model API will be affected. For example:

// Example RFC-3986
console.log(encodeURIComponentRFC3986("oracle/employee")); // "oracle%2Femployee"

Upgrading the existing configuration

// Enable model name URI encoding
flags: {
    enableModelNameEncoding: true
}

After upgrading your configuration, you may also need to upgrade your clients to use the new API.