or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

angular-modules.mdbackend-implementation.mdconfiguration-options.mdheaders-parameters.mdhttp-services.mdindex.mdrequest-response.mdtesting.md
tile.json

backend-implementation.mddocs/

Backend Implementation

Backend system supporting XMLHttpRequest and JSONP with XSRF protection and connection management. Provides pluggable backend architecture for different HTTP transport mechanisms.

Capabilities

Connection Management

Abstract classes defining the connection interface for HTTP operations.

/**
 * Abstract base class for HTTP connections
 * Defines the interface for HTTP connection implementations
 */
abstract class Connection {
  /** Current state of the connection */
  readyState: ReadyState;
  
  /** The HTTP request associated with this connection */
  request: Request;
  
  /** Observable stream of the HTTP response */
  response: Observable<Response>;
}

/**
 * Abstract factory for creating HTTP connections
 * Provides pluggable backend architecture
 */
abstract class ConnectionBackend {
  /**
   * Creates a new connection for the given request
   * @param request - HTTP request to create connection for
   * @returns Connection instance for handling the request
   */
  abstract createConnection(request: any): Connection;
}

XMLHttpRequest Backend

Backend implementation using XMLHttpRequest for standard HTTP operations.

/**
 * Factory for creating XMLHttpRequest instances
 * Injectable service for browser XMLHttpRequest creation
 */
class BrowserXhr {
  /**
   * Creates a new XMLHttpRequest instance
   * @returns New XMLHttpRequest object
   */
  build(): XMLHttpRequest;
}

/**
 * XMLHttpRequest-based HTTP connection implementation
 * Handles XMLHttpRequest lifecycle and response processing
 */
class XHRConnection implements Connection {
  /**
   * Creates a new XHR connection
   * @param req - HTTP request to execute
   * @param browserXHR - XMLHttpRequest factory
   * @param baseResponseOptions - Default response options
   */
  constructor(req: Request, browserXHR: BrowserXhr, baseResponseOptions?: ResponseOptions);
  
  /** HTTP request for this connection */
  request: Request;
  
  /** Observable response stream */
  response: Observable<Response>;
  
  /** Current connection state */
  readyState: ReadyState;
  
  /**
   * Sets detected content type on request
   * @param req - Request to modify
   * @param _xhr - XMLHttpRequest instance
   */
  setDetectedContentType(req: any, _xhr: any): void;
}

/**
 * Backend that creates XMLHttpRequest connections
 * Injectable service for XMLHttpRequest-based HTTP operations
 */
class XHRBackend implements ConnectionBackend {
  /**
   * Creates a new XHR backend
   * @param _browserXHR - XMLHttpRequest factory
   * @param _baseResponseOptions - Default response options
   * @param _xsrfStrategy - XSRF protection strategy
   */
  constructor(
    private _browserXHR: BrowserXhr,
    private _baseResponseOptions: ResponseOptions,
    private _xsrfStrategy: XSRFStrategy
  );
  
  /**
   * Creates a new XMLHttpRequest connection
   * @param request - HTTP request to execute
   * @returns XHRConnection instance
   */
  createConnection(request: Request): XHRConnection;
}

Usage Examples:

import { XHRBackend, BrowserXhr, BaseResponseOptions, CookieXSRFStrategy } from '@angular/http';

class XHRBackendService {
  
  // Create XHR backend with dependencies
  createXHRBackend(): XHRBackend {
    const browserXhr = new BrowserXhr();
    const responseOptions = new BaseResponseOptions();
    const xsrfStrategy = new CookieXSRFStrategy();
    
    return new XHRBackend(browserXhr, responseOptions, xsrfStrategy);
  }
  
  // Make request using XHR backend
  makeXHRRequest(): Observable<Response> {
    const backend = this.createXHRBackend();
    const request = new Request({
      method: RequestMethod.Get,
      url: '/api/data',
      headers: new Headers({ 'Accept': 'application/json' })
    });
    
    const connection = backend.createConnection(request);
    return connection.response;
  }
}

JSONP Backend

Backend implementation using JSONP (JSON with Padding) for cross-domain requests.

JSONP Constants:

/** Global namespace for JSONP callbacks */
const JSONP_HOME: string; // '__ng_jsonp__'
/**
 * DOM manipulation service for JSONP requests
 * Handles script injection and cleanup for JSONP operations
 */
class BrowserJsonp {
  constructor();
  
  /**
   * Creates a script element for JSONP request
   * @param url - URL for the JSONP request
   * @returns Script element configured for JSONP
   */
  build(url: string): HTMLScriptElement;
  
  /**
   * Generates next unique request ID
   * @returns Unique string identifier for request
   */
  nextRequestID(): string;
  
  /**
   * Gets callback function name for request ID
   * @param id - Request identifier
   * @returns Callback function name
   */
  requestCallback(id: string): string;
  
  /**
   * Exposes connection in global scope for callback
   * @param id - Request identifier
   * @param connection - Connection to expose
   */
  exposeConnection(id: string, connection: any): void;
  
  /**
   * Removes connection from global scope
   * @param id - Request identifier
   */
  removeConnection(id: string): void;
  
  /**
   * Appends script element to DOM to initiate request
   * @param node - Script element to append
   */
  send(node: HTMLScriptElement): void;
  
  /**
   * Removes script element from DOM
   * @param node - Script element to remove
   */
  cleanup(node: HTMLScriptElement): void;
}

/**
 * JSONP connection implementation using script injection
 * Handles JSONP request lifecycle and response processing
 */
class JSONPConnection implements Connection {
  /**
   * Creates a new JSONP connection
   * @param req - HTTP request to execute
   * @param _dom - DOM manipulation service
   * @param baseResponseOptions - Default response options
   */
  constructor(req: Request, private _dom: BrowserJsonp, private baseResponseOptions?: ResponseOptions);
  
  /** Current connection state */
  readyState: ReadyState;
  
  /** HTTP request for this connection */
  request: Request;
  
  /** Observable response stream */
  response: Observable<Response>;
  
  /**
   * Handles completion of JSONP request
   * @param data - Response data from JSONP callback
   */
  finished(data?: any): void;
}

/**
 * Backend that creates JSONP connections
 * Injectable service for JSONP-based HTTP operations
 */
class JSONPBackend extends ConnectionBackend {
  /**
   * Creates a new JSONP backend
   * @param _browserJSONP - DOM manipulation service
   * @param _baseResponseOptions - Default response options
   */
  constructor(private _browserJSONP: BrowserJsonp, private _baseResponseOptions: ResponseOptions);
  
  /**
   * Creates a new JSONP connection
   * @param request - HTTP request to execute
   * @returns JSONPConnection instance
   */
  createConnection(request: Request): JSONPConnection;
}

Usage Examples:

import { JSONPBackend, BrowserJsonp, BaseResponseOptions } from '@angular/http';

class JSONPBackendService {
  
  // Create JSONP backend
  createJSONPBackend(): JSONPBackend {
    const browserJsonp = new BrowserJsonp();
    const responseOptions = new BaseResponseOptions();
    
    return new JSONPBackend(browserJsonp, responseOptions);
  }
  
  // Make JSONP request
  makeJSONPRequest(): Observable<Response> {
    const backend = this.createJSONPBackend();
    const request = new Request({
      method: RequestMethod.Get,
      url: 'https://api.external.com/data?callback=JSONP_CALLBACK'
    });
    
    const connection = backend.createConnection(request);
    return connection.response;
  }
  
  // Handle JSONP with error handling
  safeJSONPRequest(url: string): Observable<any> {
    const backend = this.createJSONPBackend();
    const request = new Request({
      method: RequestMethod.Get,
      url: url
    });
    
    const connection = backend.createConnection(request);
    
    return connection.response.pipe(
      map(response => response.json()),
      timeout(10000), // 10 second timeout
      catchError(error => {
        console.error('JSONP request failed:', error);
        return throwError('JSONP request timeout or failed');
      })
    );
  }
}

XSRF Protection

Cross-Site Request Forgery protection strategies for secure HTTP operations.

/**
 * Abstract base class for XSRF protection strategies
 * Defines interface for configuring XSRF protection on requests
 */
abstract class XSRFStrategy {
  /**
   * Configures XSRF protection on HTTP request
   * @param req - Request to configure with XSRF protection
   */
  abstract configureRequest(req: Request): void;
}

/**
 * Cookie-based XSRF protection strategy
 * Reads XSRF token from cookie and adds it to request headers
 */
class CookieXSRFStrategy implements XSRFStrategy {
  /**
   * Creates cookie-based XSRF strategy
   * @param _cookieName - Name of cookie containing XSRF token (default: 'XSRF-TOKEN')
   * @param _headerName - Name of header to add token to (default: 'X-XSRF-TOKEN')
   */
  constructor(private _cookieName: string = 'XSRF-TOKEN', private _headerName: string = 'X-XSRF-TOKEN');
  
  /**
   * Configures request with XSRF token from cookie
   * @param req - Request to configure
   */
  configureRequest(req: Request): void;
}

Usage Examples:

import { CookieXSRFStrategy, XSRFStrategy } from '@angular/http';

class XSRFService {
  
  // Create default XSRF strategy
  createDefaultXSRFStrategy(): CookieXSRFStrategy {
    return new CookieXSRFStrategy();
  }
  
  // Create custom XSRF strategy
  createCustomXSRFStrategy(): CookieXSRFStrategy {
    return new CookieXSRFStrategy('MY_XSRF_TOKEN', 'X-MY-XSRF-TOKEN');
  }
  
  // Apply XSRF protection to request
  protectRequest(request: Request): void {
    const xsrfStrategy = this.createDefaultXSRFStrategy();
    xsrfStrategy.configureRequest(request);
  }
}

// Custom XSRF strategy implementation
class CustomXSRFStrategy implements XSRFStrategy {
  
  configureRequest(req: Request): void {
    // Custom XSRF token logic
    const token = this.getXSRFToken();
    if (token) {
      req.headers.set('X-CSRF-Token', token);
    }
  }
  
  private getXSRFToken(): string | null {
    // Custom token retrieval logic
    return localStorage.getItem('csrfToken');
  }
}

Advanced Backend Configuration

Custom Backend Implementation

import { ConnectionBackend, Connection, Request, Response } from '@angular/http';
import { Observable } from 'rxjs';

// Custom backend for special requirements
class CustomBackend extends ConnectionBackend {
  
  constructor(private config: any) {
    super();
  }
  
  createConnection(request: Request): Connection {
    return new CustomConnection(request, this.config);
  }
}

class CustomConnection implements Connection {
  readyState: ReadyState;
  request: Request;
  response: Observable<Response>;
  
  constructor(request: Request, private config: any) {
    this.request = request;
    this.readyState = ReadyState.Unsent;
    this.response = this.createResponse();
  }
  
  private createResponse(): Observable<Response> {
    // Custom response creation logic
    return new Observable(observer => {
      // Custom HTTP handling logic
      this.performCustomRequest()
        .then(result => {
          const response = new Response({
            body: result,
            status: 200,
            statusText: 'OK',
            url: this.request.url
          });
          observer.next(response);
          observer.complete();
        })
        .catch(error => {
          observer.error(error);
        });
    });
  }
  
  private async performCustomRequest(): Promise<any> {
    // Custom request implementation
    return fetch(this.request.url)
      .then(response => response.json());
  }
}

Backend Factory Configuration

import { Injectable, NgModule } from '@angular/core';
import { Http, ConnectionBackend, RequestOptions } from '@angular/http';

// Custom HTTP factory with backend selection
export function httpFactory(
  xhrBackend: XHRBackend,
  jsonpBackend: JSONPBackend,
  requestOptions: RequestOptions
): Http {
  // Choose backend based on environment or configuration
  const backend = shouldUseJSONP() ? jsonpBackend : xhrBackend;
  return new Http(backend, requestOptions);
}

function shouldUseJSONP(): boolean {
  // Logic to determine if JSONP should be used
  return window.location.protocol === 'file:';
}

@NgModule({
  providers: [
    {
      provide: Http,
      useFactory: httpFactory,
      deps: [XHRBackend, JSONPBackend, RequestOptions]
    }
  ]
})
export class CustomHttpModule {}

Connection State Management

class ConnectionStateService {
  private connections: Map<string, Connection> = new Map();
  
  trackConnection(id: string, connection: Connection): void {
    this.connections.set(id, connection);
    
    // Monitor connection state
    this.monitorConnection(id, connection);
  }
  
  private monitorConnection(id: string, connection: Connection): void {
    // Log state changes
    console.log(`Connection ${id} state:`, ReadyState[connection.readyState]);
    
    connection.response.subscribe({
      next: response => {
        console.log(`Connection ${id} received response:`, response.status);
      },
      error: error => {
        console.error(`Connection ${id} error:`, error);
        this.connections.delete(id);
      },
      complete: () => {
        console.log(`Connection ${id} completed`);
        this.connections.delete(id);
      }
    });
  }
  
  getActiveConnections(): Connection[] {
    return Array.from(this.connections.values())
      .filter(conn => conn.readyState !== ReadyState.Done);
  }
  
  cancelAllConnections(): void {
    this.connections.forEach((connection, id) => {
      if (connection.readyState !== ReadyState.Done) {
        // Implementation would need cancellation logic
        console.log(`Cancelling connection ${id}`);
      }
    });
    this.connections.clear();
  }
}

Error Handling in Backends

class ErrorHandlingBackend extends ConnectionBackend {
  
  constructor(private wrappedBackend: ConnectionBackend) {
    super();
  }
  
  createConnection(request: Request): Connection {
    const originalConnection = this.wrappedBackend.createConnection(request);
    
    return new ErrorHandlingConnection(originalConnection);
  }
}

class ErrorHandlingConnection implements Connection {
  readyState: ReadyState;
  request: Request;
  response: Observable<Response>;
  
  constructor(private originalConnection: Connection) {
    this.readyState = originalConnection.readyState;
    this.request = originalConnection.request;
    
    this.response = originalConnection.response.pipe(
      retry(3), // Retry failed requests
      catchError(this.handleError),
      timeout(30000) // 30 second timeout
    );
  }
  
  private handleError = (error: any): Observable<Response> => {
    console.error('HTTP request failed:', error);
    
    // Create error response
    const errorResponse = new Response({
      body: JSON.stringify({ error: 'Request failed' }),
      status: error.status || 500,
      statusText: error.statusText || 'Internal Server Error',
      url: this.request.url
    });
    
    return Observable.of(errorResponse);
  }
}