eLabSDK.Proxy

Functions

NameDescription
call(URL, [method], [datakeys], callback, [headers])Make a proxied HTTP request to an external URL (legacy callback-based method).

This is the legacy callback-based version of the proxy function, maintained for backward
compatibility with existing code. It sends HTTP requests through the eLab proxy server
using the older proxy.ashx handler (20-second timeout). For new code, use callAsPromise()
instead, which provides better error handling, async/await support, and uses the newer
proxy2.ashx handler with a 50-second timeout.

Key Differences from callAsPromise():

  • Uses callback pattern instead of Promises
  • Uses older proxy handler (proxy.ashx) with 20-second timeout
  • Simpler data format (plain object instead of JSON array)
  • Headers as single object (not array of objects)
  • No built-in authentication support
  • No dataType parameter

Security Note:
The proxy automatically blocks requests to private IP addresses (localhost, 192.168.x.x,
10.x.x.x, 172.16-31.x.x) to prevent Server-Side Request Forgery (SSRF) attacks.

Method Validation:
Invalid HTTP methods are automatically sanitized to 'GET' for security.
callAsPromise(proxyCfg) | Make a proxied HTTP request to an external URL (Promise-based).

This is the modern, recommended method for making cross-origin HTTP requests through the
eLab proxy server. It returns a Promise that resolves with the response data or rejects
on error. The proxy acts as a server-side intermediary, bypassing browser CORS restrictions
while providing security, authentication, and automatic data format conversion.

Key Features:

  • CORS Bypass: Make requests to any external API without CORS issues
  • Security: Automatically blocks requests to private/internal IP addresses (SSRF protection)
  • Data Conversion: Automatically converts JSON arrays to multipart/form-data format
  • Authentication: Optional built-in support for basic authentication
  • Header Forwarding: Response headers from external server are forwarded to client
  • Timeout: 50-second timeout for external requests
  • Custom Header: Adds elab-proxy: Proxied by eLab header to all responses

Data Format Specification:
When sending data with POST/PUT requests, the data parameter must be a JSON stringified
array of objects
. Each object represents a form field and should contain a single key-value
pair. All values must be strings (convert numbers using .toString()).

Example: JSON.stringify([{name: 'test'}, {price: '1'}])

The proxy handler automatically converts this array into multipart/form-data format for
the outgoing request.

Header Format Specification:
Headers must be provided as an array of objects, where each object contains a single
key-value pair representing one HTTP header.

Example: [{'Accept': 'application/json'}, {'Authorization': 'Bearer token'}]

Security Note:
The proxy automatically blocks requests to private IP addresses (localhost, 192.168.x.x,
10.x.x.x, 172.16-31.x.x) to prevent Server-Side Request Forgery (SSRF) attacks.

call(URL, [method], [datakeys], callback, [headers])

Consider using callAsPromise() for new code

Make a proxied HTTP request to an external URL (legacy callback-based method).

This is the legacy callback-based version of the proxy function, maintained for backward
compatibility with existing code. It sends HTTP requests through the eLab proxy server
using the older proxy.ashx handler (20-second timeout). For new code, use callAsPromise()
instead, which provides better error handling, async/await support, and uses the newer
proxy2.ashx handler with a 50-second timeout.

Key Differences from callAsPromise():

  • Uses callback pattern instead of Promises
  • Uses older proxy handler (proxy.ashx) with 20-second timeout
  • Simpler data format (plain object instead of JSON array)
  • Headers as single object (not array of objects)
  • No built-in authentication support
  • No dataType parameter

Security Note:
The proxy automatically blocks requests to private IP addresses (localhost, 192.168.x.x,
10.x.x.x, 172.16-31.x.x) to prevent Server-Side Request Forgery (SSRF) attacks.

Method Validation:
Invalid HTTP methods are automatically sanitized to 'GET' for security.

Kind: global function

ParamTypeDefaultDescription
URLstring | ObjectExternal URL to request, or configuration object for advanced usage
[method]string''GET''HTTP method: "GET", "POST", or "PUT" (invalid methods default to GET)
[datakeys]ObjectObject containing key-value pairs to send as form data with POST/PUT requests
callbackfunctionCallback function executed with the response data
callback.retrievedInfo*The response data from the external URL (format depends on external API)
[headers]ObjectOptional HTTP headers as key-value pairs: {'Header-Name': 'value', 'Another': 'value'}

Example

// GET request to external API
eLabSDK.ready(function() {
  eLabSDK.Proxy.call(
    'https://api.external.com/data',
    'GET',
    null,
    function(response) {
      console.log('Data received:', response);
      displayData(response);
    }
  );
});

Example

// POST request with data and headers
eLabSDK.ready(function() {
  eLabSDK.Proxy.call(
    'https://api.external.com/items',
    'POST',
    { 
      name: 'Sample A',
      price: '99.99',
      category: 'chemicals'
    },
    function(response) {
      console.log('Item created:', response);
      alert('Item ID: ' + response.id);
    },
    {
      'Content-Type': 'application/json',
      'Authorization': 'Bearer your-token-here'
    }
  );
});

Example

// Fetch weather data from third-party API
eLabSDK.ready(function() {
  eLabSDK.Proxy.call(
    'https://api.weather.com/current?city=Amsterdam',
    'GET',
    null,
    function(weatherData) {
      if (weatherData && weatherData.temperature) {
        var temp = weatherData.temperature;
        $('#temperature').text(temp + '°C');
        $('#conditions').text(weatherData.conditions);
      } else {
        console.error('Invalid weather data received');
      }
    }
  );
});

Example

// PUT request to update existing resource
eLabSDK.ready(function() {
  eLabSDK.Proxy.call(
    'https://api.external.com/items/123',
    'PUT',
    {
      name: 'Updated Sample Name',
      status: 'active'
    },
    function(response) {
      console.log('Update successful:', response);
      refreshDisplayedData();
    },
    {
      'Authorization': 'Bearer your-token'
    }
  );
});

Example

// Migration example - old call() vs new callAsPromise()
// Old way (callback-based):
eLabSDK.Proxy.call(
  'https://api.example.com/data',
  'GET',
  null,
  function(data) {
    console.log(data);
    processData(data);
  }
);

// New recommended way (Promise-based):
eLabSDK.Proxy.callAsPromise({
  proxyUrl: 'https://api.example.com/data',
  method: 'GET'
}).then(function(data) {
  console.log(data);
  processData(data);
}).catch(function(error) {
  console.error('Error:', error);
});

callAsPromise(proxyCfg)

Make a proxied HTTP request to an external URL (Promise-based).

This is the modern, recommended method for making cross-origin HTTP requests through the
eLab proxy server. It returns a Promise that resolves with the response data or rejects
on error. The proxy acts as a server-side intermediary, bypassing browser CORS restrictions
while providing security, authentication, and automatic data format conversion.

Key Features:

  • CORS Bypass: Make requests to any external API without CORS issues
  • Security: Automatically blocks requests to private/internal IP addresses (SSRF protection)
  • Data Conversion: Automatically converts JSON arrays to multipart/form-data format
  • Authentication: Optional built-in support for basic authentication
  • Header Forwarding: Response headers from external server are forwarded to client
  • Timeout: 50-second timeout for external requests
  • Custom Header: Adds elab-proxy: Proxied by eLab header to all responses

Data Format Specification:
When sending data with POST/PUT requests, the data parameter must be a JSON stringified
array of objects
. Each object represents a form field and should contain a single key-value
pair. All values must be strings (convert numbers using .toString()).

Example: JSON.stringify([{name: 'test'}, {price: '1'}])

The proxy handler automatically converts this array into multipart/form-data format for
the outgoing request.

Header Format Specification:
Headers must be provided as an array of objects, where each object contains a single
key-value pair representing one HTTP header.

Example: [{'Accept': 'application/json'}, {'Authorization': 'Bearer token'}]

Security Note:
The proxy automatically blocks requests to private IP addresses (localhost, 192.168.x.x,
10.x.x.x, 172.16-31.x.x) to prevent Server-Side Request Forgery (SSRF) attacks.

Kind: global function
Returns: Promise.<*> - Promise that resolves with the response data from the external server,
or rejects with error message "Internal server error." on failure

ParamTypeDefaultDescription
proxyCfgObjectConfiguration object for the proxy request
proxyCfg.proxyUrlstringThe target external URL to proxy the request to (private IPs blocked)
proxyCfg.methodstringHTTP method: "GET", "POST", or "PUT" (invalid methods default to GET)
[proxyCfg.data]stringRequest body data as JSON stringified array: '[{key: "value"}, {key2: "value2"}]'
[proxyCfg.headers]Array.<Object>Array of header objects: [{'Header-Name': 'value'}, {'Another-Header': 'value'}]
[proxyCfg.dataType]string'&#x27;form-data&#x27;'Data encoding type: - "form-data" (default) - Converts data array to multipart/form-data - "raw" - Sends data as application/x-www-form-urlencoded without conversion
[proxyCfg.authentication]ObjectOptional basic authentication credentials
proxyCfg.authentication.authTypestringAuthentication type (currently only "basic" supported)
proxyCfg.authentication.usernamestringUsername for basic authentication
proxyCfg.authentication.passwordstringPassword for basic authentication

Example

// POST request with form data (multipart/form-data)
// This is the most common use case for sending structured data
eLabSDK.ready(function() {
  var headers = [
    { 'Accept': 'application/json' },
    { 'Authorization': 'Bearer your-token-here' }
  ];
  
  var data = [
    { 'name': 'Sample A' },
    { 'price': '99.99' },  // Note: Must be string, not number
    { 'quantity': '5' }
  ];
  
  var proxyCfg = {
    proxyUrl: 'https://api.external.com/items',
    method: 'POST',
    headers: headers,
    data: JSON.stringify(data)  // Must stringify the array
  };
  
  eLabSDK.Proxy.callAsPromise(proxyCfg)
    .then(function(response) {
      console.log('Success:', response);
      alert('Item created with ID: ' + response.id);
    })
    .catch(function(error) {
      console.error('Error:', error);
      alert('Failed to create item');
    });
});

Example

// GET request with async/await
eLabSDK.ready(function() {
  async function fetchWeatherData() {
    try {
      var response = await eLabSDK.Proxy.callAsPromise({
        proxyUrl: 'https://api.weather.com/current?city=Amsterdam',
        method: 'GET',
        headers: [
          { 'API-Key': 'your-api-key' }
        ]
      });
      
      console.log('Weather data:', response);
      $('#temperature').text(response.temperature + '°C');
      $('#conditions').text(response.conditions);
    } catch (error) {
      console.error('Failed to fetch weather:', error);
      $('#weather').text('Weather data unavailable');
    }
  }
  
  fetchWeatherData();
});

Example

// POST with raw data (application/x-www-form-urlencoded)
// Use this when the API expects URL-encoded form data
eLabSDK.ready(function() {
  var proxyCfg = {
    proxyUrl: 'https://api.external.com/legacy-endpoint',
    method: 'POST',
    dataType: 'raw',  // Don't convert to multipart/form-data
    data: 'name=test&price=1&category=samples',  // URL-encoded string
    headers: [
      { 'Content-Type': 'application/x-www-form-urlencoded' }
    ]
  };
  
  eLabSDK.Proxy.callAsPromise(proxyCfg)
    .then(function(response) {
      console.log('Response:', response);
    })
    .catch(function(error) {
      console.error('Error:', error);
    });
});

Example

// With basic authentication
// Use this when the external API requires HTTP Basic Auth
eLabSDK.ready(function() {
  async function fetchSecureData() {
    try {
      var response = await eLabSDK.Proxy.callAsPromise({
        proxyUrl: 'https://api.secure-service.com/data',
        method: 'GET',
        authentication: {
          authType: 'basic',
          username: 'your-username',
          password: 'your-password'
        }
      });
      
      console.log('Secure data retrieved:', response);
      displayData(response);
    } catch (error) {
      console.error('Authentication failed:', error);
    }
  }
  
  fetchSecureData();
});

Example

// OAuth workflow - authenticate then use token
// Common pattern for APIs requiring OAuth-style authentication
eLabSDK.ready(function() {
  async function syncWithExternalService() {
    try {
      // Step 1: Authenticate and get token
      var authResponse = await eLabSDK.Proxy.callAsPromise({
        proxyUrl: 'https://api.external.com/oauth/token',
        method: 'POST',
        data: JSON.stringify([
          { 'grant_type': 'client_credentials' },
          { 'client_id': 'your-client-id' },
          { 'client_secret': 'your-client-secret' }
        ])
      });
      
      var accessToken = authResponse.access_token;
      console.log('Authenticated, token received');
      
      // Step 2: Use token to make authenticated request
      var dataResponse = await eLabSDK.Proxy.callAsPromise({
        proxyUrl: 'https://api.external.com/data/export',
        method: 'POST',
        headers: [
          { 'Authorization': 'Bearer ' + accessToken },
          { 'Content-Type': 'application/json' }
        ],
        data: JSON.stringify([
          { 'startDate': '2024-01-01' },
          { 'endDate': '2024-12-31' },
          { 'format': 'json' }
        ])
      });
      
      console.log('Data exported:', dataResponse);
      processExportedData(dataResponse);
      
    } catch (error) {
      console.error('Sync failed:', error);
      alert('Failed to sync with external service');
    }
  }
  
  syncWithExternalService();
});

Example

// Error handling with specific actions
eLabSDK.ready(function() {
  async function robustApiCall() {
    var maxRetries = 3;
    var retryDelay = 2000;
    
    for (var attempt = 1; attempt <= maxRetries; attempt++) {
      try {
        var response = await eLabSDK.Proxy.callAsPromise({
          proxyUrl: 'https://api.sometimes-unreliable.com/data',
          method: 'GET'
        });
        
        console.log('Success on attempt ' + attempt);
        return response;
        
      } catch (error) {
        console.warn('Attempt ' + attempt + ' failed:', error);
        
        if (attempt === maxRetries) {
          alert('Failed after ' + maxRetries + ' attempts');
          throw error;
        }
        
        // Wait before retrying
        await new Promise(resolve => setTimeout(resolve, retryDelay));
      }
    }
  }
  
  robustApiCall();
});

Example

// Common mistake - incorrect header format (DO NOT DO THIS)
// ❌ WRONG - Headers as single object:
var wrongConfig = {
  proxyUrl: 'https://api.example.com',
  method: 'POST',
  headers: {
    'Accept': 'application/json',        // ❌ Wrong format!
    'Authorization': 'Bearer token'      // ❌ This won't work!
  }
};

// ✅ CORRECT - Headers as array of objects:
var correctConfig = {
  proxyUrl: 'https://api.example.com',
  method: 'POST',
  headers: [
    { 'Accept': 'application/json' },    // ✅ Each header is separate object
    { 'Authorization': 'Bearer token' }  // ✅ This will work!
  ]
};

© 2023 eLabNext