HTTP Service
The HTTP Service is responsible for making outgoing HTTP requests as defined by the user. It primarily resides in the main process, leveraging Node.js capabilities for network operations.
Main Process HttpService
- Location:
src/main/network/service/http-service.ts - Core Library: Uses
undici, a fast and spec-compliant HTTP/1.1 client for Node.js. - Singleton:
HttpService.instanceprovides a global instance. An optionalDispatchercan be passed to the constructor, primarily for testing withMockAgentfromundici.
Key Method: fetchAsync(request: TrufosRequest)
This is the primary method for sending requests.
- Timing: Records a timestamp before starting the request using
getSteadyTimestamp()for accurate duration measurement. - Request Body Processing:
- Calls
readBody(request)to prepare the request body:- If
request.bodyisnull, no body is sent. - If
request.body.typeis'text':- Loads the text body content using
PersistenceService.loadTextBodyOfRequest(request). This returns aReadablestream. - The stream is then piped through
EnvironmentService.setVariablesInStream()to substitute any template variables (e.g., ``).
- Loads the text body content using
- If
request.body.typeis'file':- Uses
FileSystemService.readFile(request.body.filePath)to get aReadablestream for the specified file.
- Uses
- If
- Determines the
Content-Typeheader based onrequest.body.mimeTypeor defaults (e.g.,text/plain,application/octet-stream).
- Calls
- Making the Request:
- Uses
undici.request(url, options)to send the HTTP request. - Options include:
dispatcher: Uses the internal_dispatcher(if provided, for tests) orundici’s default.method: Fromrequest.method.headers: Merges the determinedContent-Typewith headers fromrequest.headers(converted fromTrufosHeader[]toundici’s expected format). Inactive headers are skipped.body: The processedReadablestream from step 2.
- Uses
- Response Handling:
responseData(fromundici.request) containsstatusCode,headers, andbody(anundiciReadablestream).- Calculates the request
durationusinggetDurationFromNow(). - Response Body Storage:
- Creates a temporary file using
FileSystemService.temporaryFile(). - If
responseData.bodyis not null, it’s piped to afs.WriteStreamassociated with the temporary file. This efficiently saves large response bodies to disk instead of keeping them in memory.
- Creates a temporary file using
- Result Construction:
- Creates a
TrufosResponseobject:metaInfo:status: FromresponseData.statusCode.duration: Calculated duration.size: Calculated usingcalculateResponseSize(responseData.headers, bodyFile.name). This utility (src/main/util/size-calculation.ts) estimates header size and reads body size (either fromContent-Lengthheader or temporary file stats).
headers:responseData.headers(frozen for immutability).bodyFilePath: Path to the temporary file containing the response body, ornullif no body.
- Logs and returns the
TrufosResponse.
- Creates a
Helper Methods:
readBody(request): As described above, prepares the request body stream.getContentType(request): Determines theContent-Typefor the request.trufosHeadersToUndiciHeaders(trufosHeaders): Converts the application’sTrufosHeader[]format to theRecord<string, string[]>format expected byundici.
Renderer Process HttpService
- Location:
src/renderer/services/http/http-service.ts - Purpose: This is a very thin wrapper around
RendererEventService.sendRequest. sendRequest(request: TrufosRequest):- Calls
RendererEventService.instance.sendRequest(request). - Catches errors (including
MainProcessErrorfrom the event service). - If the error is already a
DisplayableError, it re-throws it. - Otherwise, it attempts to create a more user-friendly
DisplayableErrorbased on common network error messages (e.g., “invalid url”, “getaddrinfo ENOTFOUND”) or falls back to a generic error message.
- Calls
The main HTTP logic resides in the main process to leverage Node.js’s networking capabilities and to handle potentially large data streams efficiently without blocking the UI. The renderer-side service primarily acts as an error-handling and presentation layer.