# 3lvis/Networking for Swift apps with mocking and caching

> 3lvis/Networking wraps URLSession in an actor-based Swift API for requests, authentication, stubbing, cancellation, image caching, and request observation. It suits Apple-platform developers who want these facilities without adopting a broader networking stack.

**3lvis/Networking** — Swift HTTP Networking with stubbing and caching support

- Repository: https://github.com/3lvis/Networking
- Stars: 1,379 · Forks: 112
- Language: Swift
- License: MIT
- Published: 2026-10-16 · Updated: 2026-10-16 · Language: en
- Canonical page: https://hysenlabs.com/projects/3lvis-networking

## Networking’s Swift request and response design

3lvis/Networking addresses HTTP client work in Swift applications that need a compact API around URLSession while also requiring request stubbing, image caching, cancellation, authentication, and request observation. Its stated audience is not limited to one application architecture: the README emphasizes a singleton-free API, minimal implementation, dependency-free operation, and unit testing. The library uses Foundation networking concepts rather than introducing a separate protocol stack. Callers select a URLSessionConfiguration, initialize a Networking instance with a base URL, set headers or authentication state, and then issue requests such as GET operations.

The current API uses Swift concurrency directly. Networking is an actor, so one instance can be shared across tasks, and its members are called with await. This is a meaningful design constraint. A call site cannot use the older, apparently synchronous style throughout an actor-isolated application. It must accommodate suspension at configuration and request boundaries. The instance also cannot be subclassed, which limits extension through inheritance but keeps the documented API centered on configuration and composition.

Results are exposed as Result<JSONResponse, NetworkingError> in the authentication examples. That makes success and failure explicit at the type level. The README also documents typed request bodies and several body encodings, including JSON, URL encoding, multipart, raw data, and query items. The repository layout includes Sources/ and Tests/, while the Makefile identifies offline or faked suites and integration tests backed by go-httpbin. Those entries support the stated test and mocking capabilities, but the README does not provide every type declaration or validation rule.

## Configuring URLSession and shared authentication state

Construction begins by choosing how URLSession manages caching, credentials, session data, and background transfers. The README names .default, .ephemeral, and .background. A default configuration provides the ordinary disk-backed cache and keychain credential storage. An ephemeral configuration keeps its cache, credentials, and session data in memory. A background configuration transfers data under system control and can continue while an iOS application is suspended or terminated.

The following code creates the ordinary client used by the README examples:

```swift
let networking = Networking(baseURL: "http://example.com")
```

Because Networking is an actor, mutations are asynchronous:

```swift
await networking.setHeaderFields(["User-Agent": "your new user agent"])
```

Headers already present on a request are replaced, while absent headers are added. Authentication has separate helpers for basic credentials, bearer tokens, a complete Authorization value, or an arbitrary header key and value. This covers common schemes without requiring every caller to assemble raw headers. It also centralizes sensitive state on the actor, although the README does not describe token persistence or automatic credential removal.

The README documents an AuthRefreshInterceptor for expired credentials. It watches for unauthorized responses, runs an asynchronous refresh closure, updates the Networking instance, and replays the failed request once. Concurrent requests that encounter an unauthorized response share one in-flight refresh, so they wait for that operation rather than each starting another refresh. Returning nil ends the attempt and leaves the original failure visible. The replay is limited to once according to the documentation. Calling the same request again in a custom interceptor, or building a refresh mechanism without coalescing, could therefore produce different traffic patterns.

## A first GET request with Networking

The README does not include its Installing section, so it does not establish whether an application should use Swift Package Manager, CocoaPods, Carthage, or another supported route. The repository contains Package.swift and lists Swift Package Manager, CocoaPods, and Carthage among its topics, but no package manifest contents appear in the README. Selecting an installation command from those names alone would be guesswork. No install command is therefore shown here.

Once Networking is available to the target, the first real operation can follow the authentication example. This request uses the example service from the README and stores the typed result:

```swift
let networking = Networking(baseURL: "http://example.com")
await networking.setAuthorizationHeader(token: "AAAFFAAAA3DAAAAAA")
let result: Result<JSONResponse, NetworkingError> = await networking.get("/get")
```

The token helper establishes the Authorization header, and the GET call resolves to either a JSONResponse or a NetworkingError. An application must inspect that Result rather than assuming that a returned request object represents a successful HTTP exchange. The README says that observing a 401 without replaying it can instead be handled through events(), where it appears as a completed failure with error.statusCode == 401.

For developers working on the library itself, the Makefile documents a different workflow. The test target starts a local go-httpbin container, passes its address to Swift Package Manager’s test command, and removes the container afterward. The documented setup requires Docker and exposes the local backend at port 8080:

```bash
make test
```

The Makefile also supports keeping that local service running while tests are repeated. The command below starts go-httpbin, while `make httpbin-stop` removes the named container. Offline and faked suites do not require this server according to the Makefile comments.

## Interceptors, retries, and request observation

Interceptor support provides the library’s extension point around every verb request. The README describes HTTPInterceptor as an asynchronous intercept(_:next:) hook. Calling next enters the remainder of the interceptor chain, whose innermost operation is the real network call. Calling next again replays the request. This mechanism explains both authentication recovery and transient failure handling in terms of the same execution model.

AuthRefreshInterceptor applies that seam to 401 and 403 responses. RetryInterceptor is documented for transient failures such as dropped connections, timeouts, and qualifying HTTP status responses, although the README text stops before listing its complete policy or configuration options. Retry counts and backoff behavior should not be inferred from that partial section.

Request observation is separate from replay. According to the README, events() reports completed requests as either successes or failures, including the HTTP status code on a failed 401 response. This can support logging, UI state, or analytics without requiring the authentication interceptor to refresh and resend anything. The README does not document buffering, subscriber lifetime, ordering, or delivery guarantees, so applications with strict event accounting need those details from the full API documentation.

Cancellation is listed as a simple request capability, but the displayed README section does not show the returned handle, method name, or guarantees about work already handed to URLSession. Likewise, the network activity indicator is listed in the table of contents, but no update API appears in the displayed text. Those omissions matter when designing interface behavior around abandoned requests or global connectivity state.

## Stubbing, image caching, and URLSession trade-offs

Request faking is a central reason to use 3lvis/Networking instead of writing every client operation directly against URLSession. The README describes mocking and stubbing as easy, and the Makefile distinguishes offline or faked suites from tests that need go-httpbin. This favors test code that can exercise success paths without depending on a live service. However, the displayed README does not show stub registration syntax, matching rules, failure injection, or how an active Networking instance is switched from fake to real transport. Those details require checking before designing a test harness.

Image downloading and caching are also built in. The README advertises flexible caching and image downloading, but its image-specific section is not displayed. It is therefore not possible to confirm cache keys, storage location, invalidation API, disk policy, or interaction with URLSessionConfiguration caching. This is a concrete evaluation boundary, since “caching support” alone does not tell an engineer whether image responses share the session cache or use a separate store.

The real alternative is direct URLSession configuration and request construction. Foundation supplies URLSession, URLRequest, URLSessionConfiguration, cancellation, credential storage, persistent caching, and background transfer behavior without a third-party wrapper. Direct URLSession produces less project-specific API surface, but the developer must assemble authentication headers, typed results, interceptors, request observation, fakes, and image-cache behavior where needed. 3lvis/Networking moves those decisions into a Swift actor and supplies common implementations, at the cost of adopting its API and dependency on the library’s behavior. It is a better fit when those included facilities remove recurring application code; it is unnecessary when the app only needs a few ordinary data requests.

## Networking maintenance, upgrades, and MIT terms

The repository is not archived, and its last push was on 2026-09-17. Release 8.0.0 is dated 2026-06-18, following 7.0.0 on 2025-05-15 and 6.15.0 on 2024-10-13. These dates show recent repository activity and a sequence of major version changes. They do not by themselves describe compatibility between Swift versions, source compatibility across releases, or the size of each upgrade. The current actor-based member calls and interceptor features make release notes an important part of an upgrade review.

The repository is licensed under MIT. That permits use, modification, distribution, and inclusion in larger works under the license’s conditions, including preservation of the copyright and license notice and disclaimer of warranty. This is a license summary, not legal advice. The README does not document a separate warranty, support policy, semantic-versioning promise, or long-term support window.

Upgrade cost should be estimated against application usage rather than release count. A project using only a Networking instance, headers, and GET requests has a smaller surface than one built around interceptors, custom request bodies, image caching, and event observation. Before changing major versions, inspect the APIs called by the app, then run the faked suites and the Docker-backed integration workflow. The repository’s `Package.swift` and `Tests/` are the first project-specific places to verify those concerns, while the README does not document migration instructions.

## Conclusion

Adopt 3lvis/Networking when an Apple-platform project needs a small Swift HTTP layer with stubbing and caching rather than a broad third-party networking framework. Do not choose it solely for features absent from its documentation, such as multipart upload policy details or background completion handling. Before adoption, verify package installation for the intended integration, actor-isolated call sites, interceptor replay behavior, cache expectations, and whether URLSession used directly would be simpler.

## FAQ

### How do I install 3lvis/Networking in a Swift project?

The README does not include its Installing section or an installation command. The repository contains `Package.swift`, but its manifest contents are not documented, so the supported dependency setup cannot be confirmed from the README.

### Does 3lvis/Networking support stubbing HTTP requests?

Yes. The README lists mocking and stubbing as built-in features, and the Makefile refers to offline or faked test suites. The README does not document the stubbing API or matching rules.

### Can 3lvis/Networking refresh an expired token and replay a request?

Yes, according to the README. `AuthRefreshInterceptor` runs a refresh closure after an unauthorized response, updates the credential, and replays the request once; concurrent unauthorized requests share a single in-flight refresh.

## Sources

- [3lvis/Networking on GitHub](https://github.com/3lvis/Networking)
- [Issues](https://github.com/3lvis/Networking/issues)
- [License: MIT](https://github.com/3lvis/Networking/blob/master/LICENSE)
- [README](https://github.com/3lvis/Networking/blob/master/README.md)
- [Releases](https://github.com/3lvis/Networking/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/3lvis-networking
