Choosing a Path Without Losing the Workflow

Hoppscotch's request contract and execution paths now support a more useful judgment than “web versus desktop.” The question is what remains invariant when a request moves between boundaries, what changes at the boundary, and how capability, convenience, and trust should be weighed separately. This checkpoint connects those ideas so a reader can diagnose a failure and choose an appropriate path without rebuilding the request or treating the most powerful relay as the universal answer.

What should remain stable

The stable part is the user's API intent. A request still has a method, endpoint, parameters, headers, authentication, body, and expected response semantics. Its collection and environment context still determine how values are resolved. Its scripts still belong to the request workflow, even if a particular execution environment must mediate what those scripts can do. A response still needs to come back as an interpretable status, header set, body, media type, and set of diagnostics.

The variable part is the boundary that carries that intent. The browser relay may be unable to accept a client certificate. A proxy may need to package the request into a service-specific format. An extension may convert binary data to satisfy an older hook. A native relay may attach a certificate or route through an authenticated proxy. The Agent may introduce a local registration and encryption relationship before the native relay sees the request. These are not different meanings of the request; they are different conditions for honoring the same meaning.

That distinction gives the architecture a useful shape:

classDiagram class RequestData { user intent variables and scripts auth and body } class KernelContract { RelayRequest RelayResponse capabilities typed errors } class Interceptor { active execution boundary preflight and cancellation } class RelayImplementation { web or native transport platform limits } class ResponseState { bytes and media type diagnostics and write-back } RequestData --> KernelContract : becomes KernelContract --> Interceptor : selected path Interceptor --> RelayImplementation : executes through RelayImplementation --> ResponseState : returns ResponseState --> RequestData : permitted state changes

The arrows do not mean that every path has identical internal steps. They identify the relationships a reader can preserve while comparing paths. If a request works through one mode and fails through another, ask where the difference appears: did the stored intent change, did the adapter produce a different representation, did the interceptor reject a capability, did the relay fail to reach the target, or did response/state handling fail afterward? That question is more productive than starting with the assumption that the server or the UI is at fault.

Three scenarios, three justified choices

An ordinary public API

Suppose a user is testing a public JSON endpoint with a normal method, common headers, and bearer authentication. Nothing requires a client certificate, custom certificate authority, proxy authentication, local network access, or browser-restricted headers. The browser path is the sensible default. It minimizes installation and local state while still using the shared request preparation, response normalization, and test workflow.

The browser choice is not just a convenience preference. It keeps the trust boundary small. There is no reason to register a local Agent or configure a native certificate store when the browser can carry the request. If the API returns an error response, that response remains useful evidence about the API. If the browser relay rejects the request before sending, the failure is a local capability problem that can be addressed without changing the collection artifact.

A browser-restricted request

Now suppose the same application is testing an endpoint that cannot be called directly because of a cross-origin policy or a header that the browser controls. The request's logical intent may still be valid. The failure occurs because the browser is the wrong execution boundary for that particular interaction.

A proxy or extension may solve this case. The extension keeps execution near the browser and can expose selected capabilities through its hook. The proxy moves the outward call to another service and returns a response that the interceptor translates back into the common model. The choice depends on what the request needs. If the problem is a page-level restriction and the extension is available and compatible, it may be the smaller change. If a configured proxy is the accepted route and its request/body/response format supports the operation, it may be appropriate.

Neither workaround should be described as full native control.