or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

app-lifecycle.mddevelopment.mdindex.mdipc.mdmenu-system.mdnetwork-protocols.mdplatform-features.mdsecurity.mdsystem-integration.mdwindow-management.md
tile.json

network-protocols.mddocs/

Network & Protocol Handling

Network requests, custom protocol registration, and session management for handling web resources and custom schemes.

Capabilities

Net

HTTP/HTTPS requests using Chromium's network stack.

/**
 * Issue HTTP/HTTPS requests using Chromium's native networking library
 */
interface Net {
  /** Creates a ClientRequest instance using the provided options */
  request(options: ClientRequestConstructorOptions | string): ClientRequest;
  
  /** A convenience method which creates a ClientRequest and automatically loads the response */
  fetch(input: RequestInfo, init?: RequestInit): Promise<Response>;
  
  /** Whether there is currently internet connection */
  isOnline(): boolean;
  
  /** Resolves with the IP address of the given hostname */
  resolveHost(hostname: string, options?: ResolveHostOptions): Promise<ResolvedHost>;
}

declare const net: Net;

/**
 * ClientRequest implements the Writable Stream interface and is an EventEmitter
 */
interface ClientRequest extends NodeJS.WritableStream {
  /** Adds an HTTP header */
  setHeader(name: string, value: string): void;
  
  /** Returns the value of a previously set header name */
  getHeader(name: string): string | undefined;
  
  /** Removes a previously set header name */
  removeHeader(name: string): void;
  
  /** Adds an HTTP header */
  getHeaders(): Record<string, string>;
  
  /** Finishes sending the request */
  end(chunk?: string | Buffer, encoding?: string): this;
  
  /** Aborts the ongoing HTTP transaction */
  abort(): void;
  
  /** Returns the method of the request */
  getMethod(): string;
  
  /** Returns the URL of the request */
  getURL(): string;
  
  /** Returns an object containing the request headers */
  getRawHeaderList(): Array<{ name: string; value: string }>;
  
  /** Whether the request will use chunked transfer encoding */
  chunkedEncoding: boolean;
}

Usage Examples:

const { net } = require('electron');

// Simple GET request
async function fetchData(url) {
  try {
    const response = await net.fetch(url);
    const data = await response.json();
    console.log('Data:', data);
    return data;
  } catch (error) {
    console.error('Fetch error:', error);
    throw error;
  }
}

// POST request with data
async function postData(url, payload) {
  try {
    const response = await net.fetch(url, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'Authorization': 'Bearer ' + getAuthToken()
      },
      body: JSON.stringify(payload)
    });
    
    if (!response.ok) {
      throw new Error(`HTTP error! status: ${response.status}`);
    }
    
    return await response.json();
  } catch (error) {
    console.error('POST error:', error);
    throw error;
  }
}

// Using ClientRequest directly
function makeRequest(url, options = {}) {
  return new Promise((resolve, reject) => {
    const request = net.request({
      method: options.method || 'GET',
      url: url,
      headers: options.headers || {}
    });
    
    request.on('response', (response) => {
      let data = '';
      
      response.on('data', (chunk) => {
        data += chunk;
      });
      
      response.on('end', () => {
        try {
          const parsed = JSON.parse(data);
          resolve(parsed);
        } catch (error) {
          resolve(data);
        }
      });
    });
    
    request.on('error', (error) => {
      reject(error);
    });
    
    if (options.body) {
      request.write(options.body);
    }
    
    request.end();
  });
}

// Check network connectivity
function checkConnectivity() {
  const isOnline = net.isOnline();
  console.log('Network status:', isOnline ? 'Online' : 'Offline');
  return isOnline;
}

Protocol

Custom protocol scheme handling for app-specific URLs.

/**
 * Register a custom protocol and intercept existing protocol requests
 */
interface Protocol {
  /** Registers the scheme as standard, secure, bypasses content security policy for resources, allows registering ServiceWorker, supports fetch API, streaming video/audio, and V8 code cache */
  registerSchemesAsPrivileged(customSchemes: CustomScheme[]): void;
  
  /** Registers a protocol of scheme that will send a file as the response */
  handle(scheme: string, handler: ProtocolHandler): void;
  
  /** Unregisters the custom scheme of scheme */
  unhandle(scheme: string): void;
  
  /** Whether the scheme is already handled */
  isProtocolHandled(scheme: string): boolean;
}

declare const protocol: Protocol;

type ProtocolHandler = (request: ProtocolRequest) => Promise<ProtocolResponse> | ProtocolResponse;

interface ProtocolRequest {
  url: string;
  referrer: string;
  method: string;
  headers: Record<string, string>;
  uploadData?: UploadData[];
}

interface ProtocolResponse {
  statusCode?: number;
  headers?: Record<string, string>;
  data?: Buffer | string;
  path?: string;
  mimeType?: string;
  charset?: string;
}

Usage Examples:

const { protocol, app } = require('electron');
const path = require('path');
const fs = require('fs');

// Register custom protocol before app is ready
app.whenReady().then(() => {
  // Register a custom protocol for serving app files
  protocol.handle('myapp', (request) => {
    const url = request.url.slice('myapp://'.length);
    const filePath = path.join(__dirname, 'assets', url);
    
    return {
      path: filePath
    };
  });
  
  // Register API protocol
  protocol.handle('myapi', async (request) => {
    const url = new URL(request.url);
    const endpoint = url.pathname;
    
    try {
      switch (endpoint) {
        case '/users':
          const users = await getUsersFromDatabase();
          return {
            statusCode: 200,
            headers: { 'Content-Type': 'application/json' },
            data: JSON.stringify(users)
          };
          
        case '/config':
          const config = getAppConfiguration();
          return {
            statusCode: 200,
            headers: { 'Content-Type': 'application/json' },
            data: JSON.stringify(config)
          };
          
        default:
          return {
            statusCode: 404,
            data: 'Not Found'
          };
      }
    } catch (error) {
      return {
        statusCode: 500,
        data: error.message
      };
    }
  });
});

// Register schemes as privileged (must be done before app ready)
protocol.registerSchemesAsPrivileged([
  {
    scheme: 'myapp',
    privileges: {
      standard: true,
      secure: true,
      supportsFetchAPI: true,
      corsEnabled: true
    }
  },
  {
    scheme: 'myapi',
    privileges: {
      standard: true,
      secure: true,
      supportsFetchAPI: true
    }
  }
]);

// Usage in renderer
// You can now use: myapp://index.html or myapi://users

Session

Browser session management including cookies, cache, and network behavior.

/**
 * Manage browser sessions, cookies, cache, proxy settings, etc.
 */
interface Session extends EventEmitter {
  /** Creates a session instance from partition string */
  static fromPartition(partition: string, options?: FromPartitionOptions): Session;
  
  /** A session instance from the default partition which is used by BrowserWindows by default */
  static readonly defaultSession: Session;
  
  /** The cookies instance for this session */
  readonly cookies: Cookies;
  
  /** The webRequest instance for this session */
  readonly webRequest: WebRequest;
  
  /** The protocol instance for this session */
  readonly protocol: Protocol;
  
  /** The netLog instance for this session */
  readonly netLog: NetLog;
  
  /** A convenience method; creates a ClientRequest and automatically loads the response */
  fetch(input: RequestInfo, init?: RequestInit): Promise<Response>;
  
  /** Sets the proxy settings */
  setProxy(config: ProxyConfig): Promise<void>;
  
  /** Resolves the proxy information for url */
  resolveProxy(url: string): Promise<string>;
  
  /** Sets download saving directory */
  setDownloadPath(path: string): void;
  
  /** Dynamically sets whether to always send credentials for HTTP NTLM or Negotiate authentication */
  enableNetworkEmulation(options: NetworkEmulationOptions): void;
  
  /** Disables any network emulation already active for the session */
  disableNetworkEmulation(): void;
  
  /** Sets the certificate verify proc for session */
  setCertificateVerifyProc(proc: CertificateVerifyProc | null): void;
  
  /** Sets the handler which can be used to respond to permission requests for the session */
  setPermissionRequestHandler(handler: PermissionRequestHandler | null): void;
  
  /** Sets the handler which can be used to respond to permission checks for the session */
  setPermissionCheckHandler(handler: PermissionCheckHandler | null): void;
  
  /** Sets the handler which can be used to respond to display media requests */
  setDisplayMediaRequestHandler(handler: DisplayMediaRequestHandler | null, options?: DisplayMediaRequestHandlerHandlerOptions): void;
  
  /** Clears the session's HTTP cache */
  clearCache(): Promise<void>;
  
  /** Clears the session's HTTP authentication cache */
  clearAuthCache(): Promise<void>;
  
  /** Clears the session's storage data */
  clearStorageData(options?: ClearStorageDataOptions): Promise<void>;
  
  /** Allows resuming cancelled or interrupted downloads from previous Session */
  createInterruptedDownload(options: CreateInterruptedDownloadOptions): void;
  
  /** Clears the host resolver cache */
  clearHostResolverCache(): Promise<void>;
  
  /** Dynamically sets whether to always send credentials for HTTP NTLM or Negotiate authentication */
  allowNTLMCredentialsForDomains(domains: string): void;
  
  /** Sets the proxy settings */
  setUserAgent(userAgent: string, acceptLanguages?: string): void;
  
  /** Returns the user agent for this session */
  getUserAgent(): string;
  
  /** Returns all extension that are loaded in this session */
  getAllExtensions(): Record<string, Extension>;
  
  /** Returns the extension with the given ID */
  getExtension(extensionId: string): Extension | null;
  
  /** Removes an extension */
  removeExtension(extensionId: string): void;
  
  /** Loads an extension */
  loadExtension(path: string, options?: LoadExtensionOptions): Promise<Extension>;
  
  /** Sets the BrowserWindow to be used for DevTools inspection */
  setDevToolsWebContents(webContents: WebContents): void;
  
  /** Sets the proxy settings */
  getBlobData(identifier: string): Promise<Buffer>;
  
  /** Downloads the file from url to targetPath */
  downloadURL(url: string): void;
  
  /** Sets code cache directory */
  setCodeCachePath(path: string): void;
  
  /** Returns path to the code cache directory if available */
  getCodeCachePath(): string | null;
  
  /** Returns availablility of spellchecker */
  availableSpellCheckerLanguages: string[];
  
  /** A boolean indicating whether builtin spell checker is enabled */
  spellCheckerEnabled: boolean;
  
  /** An array of language codes the spell checker is set to */
  listWordsInSpellCheckerDictionary(): Promise<string[]>;
  
  /** Adds a word to the custom dictionary */
  addWordToSpellCheckerDictionary(word: string): boolean;
  
  /** Removes a word from the custom dictionary */
  removeWordFromSpellCheckerDictionary(word: string): boolean;
  
  /** Loads a Hunspell dictionary for the language defined by languageCode */
  loadExtension(path: string): Promise<Extension>;
  
  /** Sets the spellchecker provider */
  setSpellCheckerDictionaryDownloadURL(url: string): void;
  
  /** Returns path where Hunspell dictionaries are stored */
  getSpellCheckerDictionaryDownloadURL(): string;
  
  /** A string indicating the absolute file system path where data for this session is persisted on disk */
  readonly storagePath: string | null;
  
  /** A boolean indicating whether the session is persistent or temporary */
  readonly isPersistent: boolean;
}

Usage Examples:

const { session, BrowserWindow } = require('electron');

// Work with default session
const defaultSession = session.defaultSession;

// Create custom session
const customSession = session.fromPartition('custom-session', {
  cache: false // In-memory session
});

// Set proxy
async function setupProxy() {
  await defaultSession.setProxy({
    proxyRules: 'http://proxy.example.com:8080',
    proxyBypassRules: 'localhost,127.0.0.1'
  });
}

// Handle downloads
defaultSession.on('will-download', (event, item, webContents) => {
  // Set download path
  item.setSavePath('/tmp/' + item.getFilename());
  
  item.on('updated', (event, state) => {
    if (state === 'interrupted') {
      console.log('Download is interrupted but can be resumed');
    } else if (state === 'progressing') {
      if (item.isPaused()) {
        console.log('Download is paused');
      } else {
        console.log(`Received bytes: ${item.getReceivedBytes()}`);
      }
    }
  });
  
  item.once('done', (event, state) => {
    if (state === 'completed') {
      console.log('Download successfully');
    } else {
      console.log(`Download failed: ${state}`);
    }
  });
});

// Handle permissions
defaultSession.setPermissionRequestHandler((webContents, permission, callback) => {
  const allowedPermissions = ['notifications', 'microphone', 'camera'];
  
  if (allowedPermissions.includes(permission)) {
    callback(true);
  } else {
    callback(false);
  }
});

// Cookie management
async function manageCookies() {
  const cookies = defaultSession.cookies;
  
  // Set a cookie
  await cookies.set({
    url: 'https://example.com',
    name: 'session_id',
    value: 'abc123',
    secure: true,
    httpOnly: true
  });
  
  // Get cookies
  const allCookies = await cookies.get({});
  console.log('All cookies:', allCookies);
  
  // Remove cookie
  await cookies.remove('https://example.com', 'session_id');
}

// Clear data
async function clearSessionData() {
  await defaultSession.clearStorageData({
    storages: ['cookies', 'localStorage', 'sessionStorage', 'caches'],
    quotas: ['temporary', 'persistent', 'syncable']
  });
  
  await defaultSession.clearCache();
}

Types

interface ClientRequestConstructorOptions {
  method?: string;
  url?: string;
  session?: Session;
  partition?: string;
  credentials?: 'include' | 'omit' | 'same-origin';
  useSessionCookies?: boolean;
  protocol?: string;
  host?: string;
  hostname?: string;
  port?: number;
  path?: string;
  redirect?: 'follow' | 'error' | 'manual';
  origin?: string;
  cache?: 'default' | 'no-store' | 'reload' | 'no-cache' | 'force-cache' | 'only-if-cached';
}

interface CustomScheme {
  scheme: string;
  privileges?: {
    standard?: boolean;
    secure?: boolean;
    bypassCSP?: boolean;
    allowServiceWorkers?: boolean;
    supportsFetchAPI?: boolean;
    corsEnabled?: boolean;
    stream?: boolean;
    codeCache?: boolean;
  };
}

interface UploadData {
  contentType: string;
  data: string | Buffer;
  encoding?: string;
  boundary?: string;
}

interface ResolveHostOptions {
  queryType?: 'A' | 'AAAA';
  source?: 'any' | 'system' | 'dns' | 'mdns' | 'localOnly';
  cacheUsage?: 'allowed' | 'staleAllowed' | 'disallowed';
  secureDnsPolicy?: 'allow' | 'disable';
}

interface ResolvedHost {
  addresses: string[];
  canonicalName?: string;
}

interface FromPartitionOptions {
  cache?: boolean;
}

interface ProxyConfig {
  mode?: 'direct' | 'auto_detect' | 'pac_script' | 'fixed_servers' | 'system';
  pacScript?: string;
  proxyRules?: string;
  proxyBypassRules?: string;
}

interface NetworkEmulationOptions {
  offline?: boolean;
  latency?: number;
  downloadThroughput?: number;
  uploadThroughput?: number;
}

interface ClearStorageDataOptions {
  origin?: string;
  storages?: string[];
  quotas?: string[];
}

interface CreateInterruptedDownloadOptions {
  path: string;
  urlChain: string[];
  mimeType?: string;
  offset: number;
  length: number;
  lastModified?: string;
  eTag?: string;
  startTime?: number;
}

interface LoadExtensionOptions {
  allowFileAccess?: boolean;
}

interface Extension {
  id: string;
  name: string;
  url: string;
  version: string;
  path?: string;
}

interface DisplayMediaRequestHandlerHandlerOptions {
  useSystemPicker?: boolean;
}

type CertificateVerifyProc = (request: CertificateVerifyProcRequest, callback: (verificationResult: number) => void) => void;

type PermissionRequestHandler = (webContents: WebContents, permission: Permission, callback: (permissionGranted: boolean) => void, details: PermissionRequestHandlerHandlerDetails) => void;

type PermissionCheckHandler = (webContents: WebContents | null, permission: string, requestingOrigin: string, details: PermissionCheckHandlerHandlerDetails) => boolean;

type DisplayMediaRequestHandler = (request: DisplayMediaRequestHandlerRequest, callback: (streams: Streams) => void) => void;

interface CertificateVerifyProcRequest {
  hostname: string;
  certificate: Certificate;
  validatedCertificate: Certificate;
  isIssuedByKnownRoot: boolean;
  verificationResult: string;
  errorCode: number;
}

type Permission = 'clipboard-read' | 'media' | 'mediaKeySystem' | 'geolocation' | 'notifications' | 'midi' | 'midiSysex' | 'pointerLock' | 'fullscreen' | 'openExternal' | 'unknown';

interface PermissionRequestHandlerHandlerDetails {
  externalURL?: string;
  mediaTypes?: Array<'video' | 'audio'>;
  requestingUrl: string;
  isMainFrame: boolean;
}

interface PermissionCheckHandlerHandlerDetails {
  requestingUrl: string;
  isMainFrame: boolean;
  securityOrigin: string;
  mediaType?: 'video' | 'audio';
}

interface DisplayMediaRequestHandlerRequest {
  frame: WebFrameMain;
  securityOrigin: string;
  videoRequested: boolean;
  audioRequested: boolean;
  userGesture: boolean;
}

interface Streams {
  video?: {
    id: string;
    name: string;
  };
  audio?: {
    id: string;
    name: string;
  };
}