CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-rest

RESTful HTTP client library with composable interceptor architecture for Node.js and browsers

76

1.28x
Overview
Eval results
Files

url-building.mddocs/

URL Building

rest.js provides powerful URL construction and manipulation capabilities through the UrlBuilder class and URI template support. This enables dynamic URL generation with parameter substitution, query string building, and cross-origin detection.

Capabilities

UrlBuilder Class

Main URL construction and manipulation utility.

const UrlBuilder = require('rest/UrlBuilder');

/**
 * Create a URL builder instance
 * @param {string|UrlBuilder} template - Base URL template or another UrlBuilder
 * @param {object} [params] - Default parameters
 * @returns {UrlBuilder} URL builder instance
 */
function UrlBuilder(template, params)

/**
 * URL builder methods
 */
interface UrlBuilder {
  /**
   * Append path and parameters to current URL
   * @param {string} [template] - Path template to append
   * @param {object} [params] - Parameters to merge
   * @returns {UrlBuilder} New UrlBuilder instance
   */
  append(template?: string, params?: object): UrlBuilder;

  /**
   * Create fully qualified URL (browser only)
   * @returns {UrlBuilder} New UrlBuilder with fully qualified URL
   */
  fullyQualify(): UrlBuilder;

  /**
   * Check if URL is absolute (has protocol or starts with /)
   * @returns {boolean} True if URL is absolute
   */
  isAbsolute(): boolean;

  /**
   * Check if URL is fully qualified (has protocol and host)
   * @returns {boolean} True if URL is fully qualified
   */
  isFullyQualified(): boolean;

  /**
   * Check if URL is cross-origin (different protocol, host, or port)
   * @returns {boolean} True if URL is cross-origin
   */
  isCrossOrigin(): boolean;

  /**
   * Parse URL into component parts
   * @returns {UrlParts} URL components similar to window.location
   */
  parts(): UrlParts;

  /**
   * Build final URL string with parameter substitution
   * @param {object} [params] - Additional parameters to merge
   * @returns {string} Final URL string
   */
  build(params?: object): string;

  /**
   * Convert to string (alias for build)
   * @returns {string} URL string
   */
  toString(): string;
}

/**
 * URL component parts (similar to window.location)
 */
interface UrlParts {
  href: string;         // Complete URL
  protocol: string;     // Protocol (http:, https:, etc.)
  host: string;         // Hostname and port
  hostname: string;     // Hostname only
  port: string;         // Port number
  pathname: string;     // Path portion
  search: string;       // Query string (including ?)
  hash: string;         // Fragment (including #)
  origin: string;       // Protocol + host
}

Basic Usage Examples:

const UrlBuilder = require('rest/UrlBuilder');

// Simple URL building
const url = new UrlBuilder('/api/users');
console.log(url.build()); // "/api/users"

// URL with parameters
const userUrl = new UrlBuilder('/api/users/{id}', { id: 123 });
console.log(userUrl.build()); // "/api/users/123"

// Query string parameters
const searchUrl = new UrlBuilder('/api/users');
console.log(searchUrl.build({ limit: 10, offset: 20 })); 
// "/api/users?limit=10&offset=20"

// Template and query combination
const complexUrl = new UrlBuilder('/api/users/{id}/posts', { id: 123 });
console.log(complexUrl.build({ status: 'published', limit: 5 }));
// "/api/users/123/posts?status=published&limit=5"

URL Manipulation:

const UrlBuilder = require('rest/UrlBuilder');

// Base URL
const baseUrl = new UrlBuilder('https://api.example.com/v1');

// Extend URL
const usersUrl = baseUrl.append('/users/{id}', { id: 456 });
console.log(usersUrl.build()); // "https://api.example.com/v1/users/456"

// Further extension
const postsUrl = usersUrl.append('/posts');
console.log(postsUrl.build({ limit: 10 })); 
// "https://api.example.com/v1/users/456/posts?limit=10"

// Original URLs are unchanged
console.log(baseUrl.build()); // "https://api.example.com/v1"

URL Analysis:

const UrlBuilder = require('rest/UrlBuilder');

const url = new UrlBuilder('https://api.example.com:8080/v1/users?limit=10#top');

// Check URL properties
console.log(url.isAbsolute());       // true
console.log(url.isFullyQualified()); // true
console.log(url.isCrossOrigin());    // depends on current origin

// Parse URL parts
const parts = url.parts();
console.log(parts.protocol);  // "https:"
console.log(parts.hostname);  // "api.example.com"
console.log(parts.port);      // "8080"
console.log(parts.pathname);  // "/v1/users"
console.log(parts.search);    // "?limit=10"
console.log(parts.hash);      // "#top"
console.log(parts.origin);    // "https://api.example.com:8080"

URI Template Support

Advanced URI template processing using the template interceptor.

const template = require('rest/interceptor/template');

/**
 * URI template interceptor for RFC 6570 template expansion
 * Supports complex parameter expansion patterns
 */

Usage with Template Interceptor:

const rest = require('rest');
const template = require('rest/interceptor/template');

const client = rest.wrap(template);

// RFC 6570 URI template expansion
client({
  path: '/api/users{/id}{?limit,offset}',
  params: {
    id: 123,
    limit: 10,
    offset: 20
  }
}).then(function(response) {
  // Request made to: /api/users/123?limit=10&offset=20
  console.log(response.entity);
});

URI Template Utility

Direct URI template processing utilities.

const uriTemplate = require('rest/util/uriTemplate');

/**
 * URI template expansion utilities
 * Implements RFC 6570 URI Template specification
 */

URI Encoding Utilities

URL encoding utilities with section-aware encoding.

const uriEncoder = require('rest/util/uriEncoder');

/**
 * URI encoding utilities
 * Provides section-aware URI encoding for different URL parts
 */

Integration with Interceptors

Path Prefix Interceptor

Automatically add prefixes to all request paths:

const rest = require('rest');
const pathPrefix = require('rest/interceptor/pathPrefix');

const client = rest.wrap(pathPrefix, { prefix: '/api/v2' });

client('/users').then(function(response) {
  // Request made to: /api/v2/users
});

// Works with UrlBuilder objects too
const userUrl = new UrlBuilder('/users/{id}', { id: 123 });
client(userUrl.build()).then(function(response) {
  // Request made to: /api/v2/users/123
});

Template Interceptor

Advanced URI template expansion:

const rest = require('rest');
const template = require('rest/interceptor/template');

const client = rest.wrap(template);

// Complex template expansion
client({
  path: '/search{/category*}{?q,limit,sort*}',
  params: {
    category: ['electronics', 'phones'],
    q: 'smartphone',
    limit: 20,
    sort: ['price', 'rating']
  }
}).then(function(response) {
  // Request made to: /search/electronics/phones?q=smartphone&limit=20&sort=price&sort=rating
});

Browser Considerations

In browser environments, UrlBuilder provides additional capabilities:

// Browser-only: fully qualify relative URLs
const url = new UrlBuilder('/api/users');
const fullyQualified = url.fullyQualify();
console.log(fullyQualified.build()); 
// "https://current-domain.com/api/users"

// Cross-origin detection
const externalUrl = new UrlBuilder('https://external-api.com/data');
console.log(externalUrl.isCrossOrigin()); // true (if different from current origin)

Advanced URL Building Patterns

Dynamic Base URLs

const UrlBuilder = require('rest/UrlBuilder');

function createApiClient(baseUrl, version) {
  const base = new UrlBuilder(baseUrl).append(`/v${version}`);
  
  return {
    users: (id) => base.append('/users/{id}', { id }),
    posts: (userId) => base.append('/users/{userId}/posts', { userId }),
    search: (type) => base.append('/search/{type}', { type })
  };
}

const api = createApiClient('https://api.example.com', 2);
console.log(api.users(123).build()); // "https://api.example.com/v2/users/123"
console.log(api.posts(123).build({ limit: 5 })); 
// "https://api.example.com/v2/users/123/posts?limit=5"

URL Templates with Defaults

const UrlBuilder = require('rest/UrlBuilder');

const apiTemplate = new UrlBuilder('/api/{resource}/{id}', {
  resource: 'users'  // default resource
});

// Use default resource
console.log(apiTemplate.build({ id: 123 })); // "/api/users/123"

// Override resource
console.log(apiTemplate.build({ resource: 'posts', id: 456 })); 
// "/api/posts/456"

Install with Tessl CLI

npx tessl i tessl/npm-rest

docs

index.md

interceptors.md

mime-system.md

url-building.md

tile.json