Class HarRecorder

java.lang.Object
org.microproxy.extras.HarRecorder
All Implemented Interfaces:
Closeable, AutoCloseable, HttpFiltersSource

public final class HarRecorder extends Object implements HttpFiltersSource, Closeable
Records exchanges as an HTTP Archive (HAR 1.2), as mitmproxy's hardump / save.har do, for browsers' developer tools, HAR viewers and ServerReplay.

 HarRecorder har = HarRecorder.builder(Path.of("flows.har")).build();
 MicroProxy.bootstrap().withFiltersSource(HttpFiltersChain.of(har, otherFilters)).start();
 ...
 har.close();   // writes flows.har
 

Each entry holds the request as the client sent it (method, absolute URL, headers, cookies, query string, postData) and the response as the client received it (status, headers, cookies, content), whoever answered: the server, a filter, the cache, a replay or the proxy (_source says which). Entries also carry the serverIPAddress, the client connection id and timings: dns, connect (including ssl), send, wait and receive; -1 marks phases that did not happen, such as connecting on a reused connection. Bodies are decoded (gzip, deflate, Brotli, zstd) and written as text in their charset, or base64 ("encoding": "base64") for binary content. An exchange that ends without a response is written with status 0 and an _error. CONNECT tunnels are not recorded; the requests inside intercepted sessions are.

Put the recorder first among the filters to record requests before other filters change them. Bodies are captured as they stream past, up to HarRecorder.Builder.maxBodySize each (larger bodies are cut short and marked _truncated), which turns off the proxy's zero-copy body relay; content(false) records heads only and keeps it.

Memory. By default every entry, bodies included, is kept in memory until close() (or save(java.nio.file.Path)) writes the file, as mitmproxy does: a long session can take up to twice maxBodySize per exchange (more for base64). stream(true) writes each entry to the file as it completes instead, holding nothing; the file is valid JSON once closed. A file name ending in .zhar is written zlib-compressed.

  • Method Details

    • builder

      public static HarRecorder.Builder builder(Path path)
      Starts a builder for a recorder that writes path.
      Parameters:
      path - the HAR file to write (.zhar: zlib-compressed)
      Returns:
      a new builder with default settings
    • path

      public Path path()
      Returns the file this recorder writes.
      Returns:
      the file this recorder writes
    • recordedEntries

      public long recordedEntries()
      Returns the number of entries recorded so far.
      Returns:
      the number of entries recorded so far
    • save

      public void save(Path target) throws IOException
      Writes the entries recorded so far to target as a complete HAR file, replacing it atomically. Recording goes on.
      Parameters:
      target - the file to write (.zhar: zlib-compressed)
      Throws:
      IOException - if the file cannot be written
      IllegalStateException - if the recorder streams its entries, and so keeps none
    • close

      public void close() throws IOException
      Writes the HAR file (or finishes the streamed one). Later exchanges are not recorded.
      Specified by:
      close in interface AutoCloseable
      Specified by:
      close in interface Closeable
      Throws:
      IOException
    • filterRequest

      public HttpFilters filterRequest(HttpRequest originalRequest, FlowContext flowContext)
      Description copied from interface: HttpFiltersSource
      Returns the filters for a request, or null to proxy it unfiltered.
      Specified by:
      filterRequest in interface HttpFiltersSource
      Parameters:
      originalRequest - a copy of the request as received from the client
      flowContext - the client connection the request arrived on
      Returns:
      the per-request filters, or null to leave the request unfiltered