Code/Storage/NetworkStorageDocuments.cs
using System;
using System.Text.Json;
using System.Threading.Tasks;

namespace Sandbox;

public static partial class NetworkStorage
{
	// ── Collections ──

	/// <summary>
	/// Read a document from a collection.
	/// If documentId is null, uses the current player's Steam ID.
	/// </summary>
	public static async Task<JsonElement?> GetDocument( string collectionId, string documentId = null )
	{
		EnsureConfigured();
		ClearLastEndpointError( "storage" );

		// If proxy mode is active and we're not the host, route through the host
		if ( ProxyEnabled && !IsHost && DocumentProxy != null )
		{
			return await GetDocumentViaProxy( collectionId, documentId );
		}
		try
		{
			var docId = documentId ?? Game.SteamId.ToString();
			var path = $"/storage/{EscapeRouteSegment( ProjectId )}/{EscapeRouteSegment( collectionId )}/{EscapeRouteSegment( docId )}";
			var usesDedicatedSecret = TryBuildDedicatedStorageHeaders( out var headers );
			if ( !usesDedicatedSecret )
			{
				if ( TryRejectDedicatedServerPlayerAuth( "storage" ) )
					return null;
				headers = await BuildAuthHeaders();
			}
			var url = BuildUrl( path );

			if ( NetworkStorageLogConfig.LogRequests )
				NetLog.Request( "storage", $"GET {collectionId}/{docId}" );
			var result = await Http.RequestStringAsync( url, "GET", null, headers );
			if ( NetworkStorageLogConfig.LogResponses )
				Log.Info( $"[NetworkStorage] storage → {TruncateJson( result, 300 )}" );
			var parsed = ParseResponse( "storage", result );
			if ( parsed.HasValue && NetworkStorageLogConfig.LogResponses )
				NetLog.Response( "storage", $"OK ({result.Length} bytes)" );
			return parsed;
		}
		catch ( Exception ex )
		{
			if ( IsHttpNotFoundException( ex ) )
			{
				RecordStorageNotFound( $"{collectionId}/{documentId ?? Game.SteamId.ToString()}" );
				return null;
			}

			if ( NetworkStorageLogConfig.LogErrors )
			{
				Log.Warning( $"[NetworkStorage] GetDocument: {ex.Message}" );
				NetLog.Error( "storage", ex.Message );
			}
			RecordEndpointError( "storage", "REQUEST_FAILED", ex.Message );
			return null;
		}
	}

}