Using clients
The public interfaces use the
\Netresearch\ namespace and
are provided through TYPO3 services. Applications should inject bound
PSR-18 clients or Public Fetch. The internal Guzzle client and its
progress and cancellation driver belong together; they do not provide
an additional public credential API.
Ordinary Core requests
The registered Core path uses the public default policy. Existing supported Core middleware and context restrictions remain effective in addition. An ordinary call can look like this:
$response = $requestFactory->request(
'https://www.example.org/document.json',
'GET',
['timeout' => 10, 'http_errors' => false],
);
$request is an injected
\TYPO3\. For public content from
untrusted URLs, Public Fetch provides a narrower API.
Configuring an endpoint profile does not grant internal access to
RequestFactory requests.
Bound integration clients
-
class
EndpointClientFactoryInterface -
- Fully qualified name
-
\Netresearch\Http Guard\ Endpoint Client Factory Interface
The profile ID belongs in trusted service code or dependency injection configuration. It is not taken from the current user request. The following example uses the profile from Internal endpoint example:
<?php
declare (strict_types=1);
namespace Vendor\SitePackage\Service;
use GuzzleHttp\Psr7\Request;
use Netresearch\HttpGuard\EndpointClientFactoryInterface;
use Psr\Http\Client\ClientInterface;
use Psr\Http\Message\ResponseInterface;
final readonly class ErpClient
{
private ClientInterface $client;
public function __construct(EndpointClientFactoryInterface $factory)
{
$this->client = $factory->forEndpoint('erp-orders');
}
public function sendOrder(array $order): ResponseInterface
{
return $this->client->sendRequest(
new Request(
'POST',
'https://erp.internal.example:8443/orders',
['Content-Type' => 'application/json'],
json_encode($order, JSON_THROW_ON_ERROR)
)
);
}
}
The client checks the origin, method and all resolved addresses on
every send. PSR-18
send does not follow redirects and
returns HTTP error responses such as 404 or 500 as response objects.
Network errors and policy denials remain exceptions. Never bypass a
policy error with an unprotected replacement client.
Public Fetch
-
class
PublicFetchClientInterface -
- Fully qualified name
-
\Netresearch\Http Guard\ Public Fetch Client Interface
Public Fetch does not inherit authentication, cookies, client certificates,
SSL keys, custom headers, bodies or query defaults from another client.
Its fixed header list consists of Accept,
Accept- and User-. The query of an
accepted target URI remains part of that URI and is not logged.
Permitted public redirects can reach another origin without forwarding
the secrets of an original integration request.
<?php
declare (strict_types=1);
namespace Vendor\SitePackage\Service;
use GuzzleHttp\Psr7\Uri;
use Netresearch\HttpGuard\PublicFetchClientInterface;
use Netresearch\HttpGuard\TargetNormalizer;
use Psr\Http\Message\ResponseInterface;
final readonly class PublicDocument
{
public function __construct(private PublicFetchClientInterface $client)
{
}
public function fetch(string $rawUrl): ResponseInterface
{
(new TargetNormalizer())->assertRawUri($rawUrl);
return $this->client->fetch(new Uri($rawUrl));
}
}
No endpoint ID is accepted for a user-driven fetch. Private targets remain blocked even when the project has an internal endpoint profile with the same hostname.
Raw URLs and PSR-7
Target checks forbidden syntax
while the original string is still available. Reject fragments,
including an empty #, backslashes, control characters and
invalid raw forms before constructing a URI object.
A PSR-7 URI object may already have discarded an empty fragment marker or encoded input. A later PSR-18 client cannot reconstruct that information. The TYPO3 RequestFactory adapter therefore checks raw strings before Guzzle. Custom PSR-18 applications validate the original URL themselves, as shown in the Public Fetch example. The same boundary applies to raw Vault resource URLs before constructing a RequestInterface object.
Handling policy errors
Policy implements
Outbound. Its
reason method
returns a stable code from Understanding denials. Exception messages
contain no URLs, credentials or request bodies. Applications can use
the code for an understandable error message; do not include secrets
or complete requests in supplementary error logs.
SDK options and streaming
Ordinary request bodies, headers and supported authentication remain
available in the controlled RequestFactory and SDK path.
timeout and connect_ accept finite,
non-negative numbers, including zero. verify accepts a
boolean or a readable CA bundle, subject to the TLS policy. Readable
client certificates and SSL keys enable mTLS. sink can
write to a file path, resource or PSR-7 stream without creating an
additional response copy inside the guard.
Supported callbacks such as on_, on_
and progress remain available; exceptions terminate the
associated transfer. HTTP 1.0, 1.1 and 2 are qualified; HTTP/3 is not.
The IP-family option can select only v4 or v6
and does not expand address permissions.
Raw curl or cURL-multi options, stream_,
Unix sockets, proxy routes, custom handlers, transport sharing,
delayed transport sends, debug dumps, unknown options and
stream=true are rejected in the protected path. A response
sink file does not provide an alternative stream HTTP handler.
Guzzle-internal Digest and NTLM control options, inspected at source
level for Guzzle 7, are distinguished from arbitrary raw cURL options.
Cancellation and incremental streaming require an adapter that uses the associated internal progress driver. The recorded nr-vault reference adapter does this for its existing APIs. Returning an arbitrary Guzzle client alone does not guarantee that lifecycle binding.
Optional nr-vault migration
The extension does not read Vault secrets or automatically integrate Vault. The historical reference patch targets its recorded nr-vault source revision and requires deliberate integration in that project. Resource and OAuth token origins require their own bound clients and, where needed, their own profiles. A private token origin does not inherit a public resource permission, or vice versa.
Secret retrieval, auditing, masking, size limits and Vault's existing cancellation and streaming semantics remain the adapter's responsibility. The reference migration and recorded evidence remain attached to that historical revision. This extension ships no Vault overlay and does not deploy or freshly qualify nr-vault. Ordinary TYPO3 RequestFactory protection requires no Vault migration.