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

request-response.mddocs/

Request and Response Handling

Complete request and response object model with body parsing, headers, status handling, and content type detection. Both classes extend the Body abstract class for consistent body handling across different content types.

Capabilities

Request Class

Represents an HTTP request with URL, headers, body, and other configuration options.

/**
 * HTTP request representation extending Body class
 * Handles request data, headers, method, and body parsing
 */
class Request extends Body {
  /**
   * Creates a new Request instance
   * @param requestOptions - Configuration object for the request
   */
  constructor(requestOptions: RequestArgs);
  
  /** HTTP method for this request */
  method: RequestMethod;
  
  /** Headers collection for this request */
  headers: Headers;
  
  /** Target URL for this request */
  url: string;
  
  /** Whether to include credentials (cookies) with the request */
  withCredentials: boolean;
  
  /** Expected response content type */
  responseType: ResponseContentType;
  
  /**
   * Detects content type of the request body
   * @returns ContentType enum value
   */
  detectContentType(): ContentType;
  
  /**
   * Detects content type specifically from body content
   * @returns ContentType enum value
   */
  detectContentTypeFromBody(): ContentType;
  
  /**
   * Gets the request body
   * @returns Request body in appropriate format
   */
  getBody(): any;
  
  // Inherited from Body class:
  
  /**
   * Parses request body as JSON
   * @returns Parsed JSON object
   * @throws Error if body is not valid JSON
   */
  json(): any;
  
  /**
   * Returns request body as text string
   * @param encodingHint - Text encoding hint ('legacy' or 'iso-8859')
   * @returns String representation of body
   */
  text(encodingHint?: 'legacy' | 'iso-8859'): string;
  
  /**
   * Returns request body as ArrayBuffer
   * @returns ArrayBuffer representation of body
   */
  arrayBuffer(): ArrayBuffer;
  
  /**
   * Returns request body as Blob
   * @returns Blob representation of body
   */
  blob(): Blob;
}

Usage Examples:

import { Request, RequestMethod, Headers, RequestOptions } from '@angular/http';

// Create a basic GET request
const getRequest = new Request({
  method: RequestMethod.Get,
  url: '/api/users',
  headers: new Headers({ 'Accept': 'application/json' })
});

// Create a POST request with JSON body
const postRequest = new Request({
  method: RequestMethod.Post,
  url: '/api/users',
  headers: new Headers({ 
    'Content-Type': 'application/json',
    'Accept': 'application/json'
  }),
  body: JSON.stringify({ name: 'John', email: 'john@example.com' })
});

// Create a request with authentication
const authRequest = new Request({
  method: RequestMethod.Get,
  url: '/api/secure',
  headers: new Headers({ 
    'Authorization': 'Bearer token123',
    'Accept': 'application/json'
  }),
  withCredentials: true
});

// Working with request body
if (postRequest.detectContentType() === ContentType.JSON) {
  const bodyData = postRequest.json();
  console.log('Request body:', bodyData);
}

Response Class

Represents an HTTP response with status, headers, and body content.

/**
 * HTTP response representation extending Body class
 * Contains status information, headers, and parsed body content
 */
class Response extends Body {
  /**
   * Creates a new Response instance
   * @param responseOptions - Configuration object for the response
   */
  constructor(responseOptions: ResponseOptions);
  
  /** Response type based on Fetch API ResponseType */
  type: ResponseType;
  
  /** Whether the response was successful (status 200-299) */
  ok: boolean;
  
  /** Final URL after any redirects */
  url: string;
  
  /** HTTP status code */
  status: number;
  
  /** HTTP status text */
  statusText: string | null;
  
  /** Number of bytes loaded */
  bytesLoaded: number;
  
  /** Total number of bytes expected */
  totalBytes: number;
  
  /** Response headers collection */
  headers: Headers | null;
  
  /**
   * String representation of the response
   * @returns String showing status and URL
   */
  toString(): string;
  
  // Inherited from Body class:
  
  /**
   * Parses response body as JSON
   * @returns Parsed JSON object
   * @throws Error if body is not valid JSON
   */
  json(): any;
  
  /**
   * Returns response body as text string
   * @param encodingHint - Text encoding hint ('legacy' or 'iso-8859')
   * @returns String representation of body
   */
  text(encodingHint?: 'legacy' | 'iso-8859'): string;
  
  /**
   * Returns response body as ArrayBuffer
   * @returns ArrayBuffer representation of body
   */
  arrayBuffer(): ArrayBuffer;
  
  /**
   * Returns response body as Blob
   * @returns Blob representation of body
   */
  blob(): Blob;
}

Usage Examples:

import { Http } from '@angular/http';
import { Observable } from 'rxjs';
import { map, catchError } from 'rxjs/operators';

class ApiService {
  constructor(private http: Http) {}
  
  // Handle JSON response
  getUsers(): Observable<any[]> {
    return this.http.get('/api/users')
      .pipe(
        map(response => {
          console.log('Response status:', response.status);
          console.log('Response ok:', response.ok);
          console.log('Response URL:', response.url);
          
          if (response.ok) {
            return response.json();
          } else {
            throw new Error(`HTTP Error: ${response.status} ${response.statusText}`);
          }
        }),
        catchError(error => {
          console.error('Request failed:', error);
          throw error;
        })
      );
  }
  
  // Handle text response
  getTextData(): Observable<string> {
    return this.http.get('/api/text-data')
      .pipe(
        map(response => {
          if (response.ok) {
            return response.text();
          }
          throw new Error(`HTTP Error: ${response.status}`);
        })
      );
  }
  
  // Handle binary response
  downloadFile(): Observable<Blob> {
    return this.http.get('/api/download')
      .pipe(
        map(response => {
          if (response.ok) {
            return response.blob();
          }
          throw new Error(`Download failed: ${response.status}`);
        })
      );
  }
  
  // Check response headers
  checkCacheHeaders(): Observable<any> {
    return this.http.get('/api/cached-data')
      .pipe(
        map(response => {
          const cacheControl = response.headers?.get('Cache-Control');
          const etag = response.headers?.get('ETag');
          
          return {
            data: response.json(),
            cacheControl,
            etag,
            isCached: !!cacheControl
          };
        })
      );
  }
}

Body Abstract Class

Base class providing body parsing functionality for both Request and Response.

/**
 * Abstract base class for HTTP message body handling
 * Provides methods for parsing body content in different formats
 */
abstract class Body {
  /** Protected body content */
  protected _body: any;
  
  /**
   * Parses body as JSON
   * @returns Parsed JSON object
   * @throws Error if body is not valid JSON
   */
  json(): any;
  
  /**
   * Returns body as text string
   * @param encodingHint - Encoding hint for text conversion ('legacy' or 'iso-8859')
   * @returns String representation of body
   */
  text(encodingHint?: 'legacy' | 'iso-8859'): string;
  
  /**
   * Returns body as ArrayBuffer
   * @returns ArrayBuffer representation of body
   */
  arrayBuffer(): ArrayBuffer;
  
  /**
   * Returns body as Blob
   * @returns Blob representation of body
   */
  blob(): Blob;
}

Response Status Handling

import { Http } from '@angular/http';
import { Observable, throwError } from 'rxjs';
import { map, catchError } from 'rxjs/operators';

class StatusHandlingService {
  constructor(private http: Http) {}
  
  getData(): Observable<any> {
    return this.http.get('/api/data')
      .pipe(
        map(response => {
          // Check different status codes
          switch (response.status) {
            case 200:
              return response.json();
            case 204:
              return null; // No content
            case 304:
              return this.getCachedData(); // Not modified
            default:
              if (response.ok) {
                return response.json();
              }
              throw new Error(`Unexpected status: ${response.status}`);
          }
        }),
        catchError(error => {
          if (error.status === 404) {
            return this.handleNotFound();
          } else if (error.status >= 500) {
            return this.handleServerError(error);
          }
          return throwError(error);
        })
      );
  }
  
  private handleNotFound(): Observable<any> {
    console.log('Resource not found, returning default data');
    return Observable.of({ message: 'No data available' });
  }
  
  private handleServerError(error: any): Observable<any> {
    console.error('Server error:', error);
    return throwError('Server temporarily unavailable');
  }
  
  private getCachedData(): any {
    // Return cached data logic
    return { cached: true };
  }
}

Content Type Detection

import { Request, RequestMethod } from '@angular/http';

class ContentTypeService {
  
  createTypedRequest(data: any): Request {
    let body: any;
    let contentType: string;
    
    // Detect and set appropriate content type
    if (typeof data === 'string') {
      body = data;
      contentType = 'text/plain';
    } else if (data instanceof FormData) {
      body = data;
      // Don't set Content-Type, let browser set boundary
    } else if (data instanceof ArrayBuffer) {
      body = data;
      contentType = 'application/octet-stream';
    } else {
      body = JSON.stringify(data);
      contentType = 'application/json';
    }
    
    const headers = new Headers();
    if (contentType) {
      headers.set('Content-Type', contentType);
    }
    
    const request = new Request({
      method: RequestMethod.Post,
      url: '/api/upload',
      headers,
      body
    });
    
    // Check detected content type
    console.log('Detected content type:', request.detectContentType());
    
    return request;
  }
}

Advanced Body Handling

class AdvancedBodyService {
  constructor(private http: Http) {}
  
  // Handle different response types
  handleMultipleFormats(): Observable<any> {
    return this.http.get('/api/mixed-content')
      .pipe(
        map(response => {
          const contentType = response.headers?.get('Content-Type') || '';
          
          if (contentType.includes('application/json')) {
            return { type: 'json', data: response.json() };
          } else if (contentType.includes('text/')) {
            return { type: 'text', data: response.text() };
          } else if (contentType.includes('image/')) {
            return { type: 'blob', data: response.blob() };
          } else {
            return { type: 'buffer', data: response.arrayBuffer() };
          }
        })
      );
  }
  
  // Upload file with progress tracking
  uploadWithProgress(file: File): Observable<any> {
    const formData = new FormData();
    formData.append('file', file);
    
    return this.http.post('/api/upload', formData)
      .pipe(
        map(response => {
          console.log('Upload progress:', {
            loaded: response.bytesLoaded,
            total: response.totalBytes,
            percentage: (response.bytesLoaded / response.totalBytes) * 100
          });
          
          return response.json();
        })
      );
  }
}