pub async fn guarded_post_json(
client: &Client,
url: &str,
extra_headers: &[(HeaderName, HeaderValue)],
body: Vec<u8>,
) -> Result<Response>Expand description
POST a JSON body to a user-influenced URL through the SSRF guard.
The write-side counterpart to guarded_get_no_privacy, and the only way
crate::atproto::PdsClient is allowed to reach a PDS host it did not
choose. It runs the same scheme allow-list, the same IP allow-list, and the
same connect-pinning (via pinned_client), so the DNS-rebinding window
between “assert_public_target said this host is public” and “the TCP
handshake happens” is closed for writes exactly as it is for reads.
Content-Type: application/json is set here rather than by the caller, so
the one header the XRPC wire format requires cannot be forgotten; the caller
passes only its credential header(s).
Redirects are refused, not followed — the single deliberate divergence
from guarded_get. A 307/308 re-sends the method and the body
verbatim, and reqwest’s cross-origin header sanitisation only strips
headers: an app password or a record body lives in the JSON payload, so a
hostile PDS answering 307 Location: https://evil.example/collect would
exfiltrate it however carefully the headers were handled. There is no
legitimate reason for a PDS to redirect an com.atproto.repo.* write, so the
safe behaviour and the correct behaviour coincide: Err, loudly.