How Apollo’s HTTP Client Manages Cache and Fetches Data from the Online Database
Apollo’s HTTP client uses libcurl to download remote resources into a local cache directory at /data/apollo/cache/, then reads files locally to support offline access and database queries.
The Apollo PS4 save-tool, maintained by bucanero, relies on a lightweight HTTP client to communicate with online databases and download updates. This article examines how the Apollo HTTP client cache system stores fetched data and manages local resources using libcurl, based on the implementation in the bucanero/apollo-ps4 repository.
Initializing the HTTP Client with libcurl
Apollo’s network stack begins with http_init() in source/http.c:18-33. This function loads the PS4 networking sysmodules, initializes the NetCtl service, and invokes curl_global_init() to prepare libcurl for transfers.
If any initialization step fails, the function returns HTTP_FAILED, preventing the application from attempting network operations when the system is not ready.
Downloading Resources into the Apollo HTTP Client Cache
The core fetch operation is http_download() in source/http.c. This function constructs the full request URL, opens the destination file, and configures libcurl options through set_curl_opts() before executing the transfer with curl_easy_perform().
When the download succeeds, the file persists in the destination path. On failure, the function calls unlink_secure() to remove partially written files, ensuring the cache does not contain corrupted data.
Cache Directory Structure and Configuration
The cache location is defined in include/saves.h:
#define APOLLO_PATH "/data/apollo/"
#define APOLLO_LOCAL_CACHE APOLLO_PATH "cache/"
This expands to /data/apollo/cache/ on the PS4 filesystem. Common cached files include:
games.ftp– Downloaded game database listsver.check– Version information for update checksappdata.zip– Patch archives for application updatesusers.ftp– User index files from FTP servers
Managing the Apollo HTTP Client Cache Lifecycle
Apollo creates the cache directory at startup in source/main.c using mkdirs(APOLLO_LOCAL_CACHE). The application provides several mechanisms to maintain cache integrity.
The clean_directory() function in source/common.c:222-240 recursively deletes files matching a specific suffix filter. This utility supports:
- Selective cleaning: Removing only
.txtfiles when the database URL changes - Complete purging: Removing all cached content via the manual "Clear cache" menu entry
When users modify the FTP or online database URL in source/settings.c, the system calls clean_directory(APOLLO_LOCAL_CACHE, ".txt") to invalidate stale database lists while preserving other cached resources.
Fetching Data from the Online Database
Apollo retrieves database information through a two-step cache-then-read pattern.
First, the user configures the database URL through db_url_callback() in source/settings.c, which stores the endpoint in apollo_config.save_db.
To fetch the game list, the system calls:
http_download(apollo_config.save_db, "games.txt",
APOLLO_LOCAL_CACHE "games.ftp", 0);
This downloads games.txt from the remote server and saves it as games.ftp in the local cache. Subsequent operations read the file locally using readTextFile(APOLLO_LOCAL_CACHE "games.ftp"), enabling offline access to the database.
Checking for Updates
The update mechanism follows the same cached approach. The update_callback() function in source/settings.c downloads version information from APOLLO_UPDATE_URL to APOLLO_LOCAL_CACHE "ver.check".
After reading the cached version file, Apollo compares it against APOLLO_VERSION. If a newer version exists, the system can trigger a patch download:
http_download(ONLINE_PATCH_URL, "apollo-ps4-update.zip",
APOLLO_LOCAL_CACHE "appdata.zip", 1);
Practical Code Examples
Initializing the Client and Downloading a Database
#include "http.h"
#include "common.h"
int main(void)
{
if (http_init() == HTTP_FAILED) {
LOG("Network init failed");
return -1;
}
/* Download the online game list */
const char *url = "https://example.com/apollo/";
const char *dst = APOLLO_LOCAL_CACHE "games.ftp";
if (http_download(url, "games.txt", dst, 1) == HTTP_SUCCESS) {
LOG("Games list cached to %s", dst);
}
http_end();
return 0;
}
Clearing the Local Cache Programmatically
/* Callback for Settings → Clear Cache menu entry */
static void clearcache_callback(int sel)
{
LOG("Cleaning folder '%s'...", APOLLO_LOCAL_CACHE);
clean_directory(APOLLO_LOCAL_CACHE, ""); // Empty suffix = delete all
show_message("%s\n%s",
_("Local cache folder cleaned:"),
APOLLO_LOCAL_CACHE);
}
Checking for Application Updates
/* Excerpt from settings.c update_callback() */
if (!http_download(APOLLO_UPDATE_URL, NULL,
APOLLO_LOCAL_CACHE "ver.check", 0)) {
LOG("Failed to fetch version file");
return;
}
char *buffer = readTextFile(APOLLO_LOCAL_CACHE "ver.check");
if (buffer && strcasecmp(APOLLO_VERSION, buffer) != 0) {
LOG("New version available: %s", buffer);
/* Trigger download of apollo-ps4-update.zip */
}
Summary
- Apollo’s HTTP client is a libcurl wrapper implemented in
source/http.cthat handles network initialization, file transfers, and cleanup. - All remote resources are cached to
/data/apollo/cache/(defined asAPOLLO_LOCAL_CACHEininclude/saves.h) to enable offline access and reduce network load. - The
http_download()function writes files atomically, removing partial downloads on failure viaunlink_secure(). - Cache maintenance is handled by
clean_directory()insource/common.c:222-240, supporting both selective purging by file extension and complete clearing. - Online database queries follow a cache-then-read pattern: the client downloads
games.txttogames.ftp, then parses the local file for game listings.
Frequently Asked Questions
Where does Apollo store cached HTTP downloads?
Apollo stores all cached files in /data/apollo/cache/, defined by the APOLLO_LOCAL_CACHE macro in include/saves.h. This directory is created at application startup in source/main.c using mkdirs().
What library does Apollo use for HTTP requests?
Apollo uses libcurl for all HTTP and FTP operations. The wrapper functions http_init(), http_download(), and http_end() in source/http.c manage libcurl’s global state, perform transfers, and handle PS4-specific networking sysmodules.
How does Apollo check for software updates?
The update_callback() function in source/settings.c downloads a version file from APOLLO_UPDATE_URL to APOLLO_LOCAL_CACHE "ver.check". It compares the cached version string against the compiled APOLLO_VERSION using strcasecmp(). If they differ, Apollo can download apollo-ps4-update.zip to the cache and apply the patch.
Can users manually clear the HTTP cache?
Yes. The settings menu provides a "Clear cache" option that triggers clearcache_callback() in source/settings.c. This calls clean_directory(APOLLO_LOCAL_CACHE, "") from source/common.c:222-240, which recursively deletes all files in the cache directory. Users can also trigger selective clearing when changing database URLs, which removes only .txt files while preserving other cached data.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →