Skip to content

Instantly share code, notes, and snippets.

@rjindael
Last active September 19, 2020 04:25
Show Gist options
  • Save rjindael/d1666ee528d7219c5378877212aeeb70 to your computer and use it in GitHub Desktop.
Save rjindael/d1666ee528d7219c5378877212aeeb70 to your computer and use it in GitHub Desktop.
Get Roblox assets in PHP, can be used as passthrough function
<?php
function parse_response_headers($headers)
{
$head = [];
foreach ($headers as $key => $value)
{
$type = explode(":", $value, 2);
if (isset($type[1]))
{
$head[trim($type[0])] = trim($type[1]);
}
else
{
$head[] = $value;
if (preg_match("#HTTP/[0-9\.]+\s+([0-9]+)#", $value, $out))
{
$head["reponse_code"] = intval($out[1]);
}
}
}
return $head;
}
if (!isset($_GET["id"]) || strlen($_GET["id"]) <= 0 || !is_int((int)$_GET["id"])) // I use strlen instead of empty because empty returns "false" if it's "falsey", e.g asset id "0"
{
http_response_code(404);
exit();
}
$id = filter_var($_GET["id"], FILTER_SANITIZE_NUMBER_INT, FILTER_NULL_ON_FAILURE);
$version = isset($_GET["version"]) ? filter_var($_GET["version"], FILTER_SANITIZE_NUMBER_INT, FILTER_NULL_ON_FAILURE) : -1; // -1 is the latest version internally.
if (!isset($id) || empty($id) || $id == NULL)
{
// We at least need an asset id
http_response_code(404);
exit();
}
$url = "https://assetdelivery.roblox.com/v1/assetId/$id";
if ($version != -1 || $version != NULL) // Get specific version
{
$url .= "/version/$version";
}
$options = ["http" => ["user_agent" => "Roblox"]]; // Set user agent because of KTX
$context = stream_context_create($options);
$asset = @file_get_contents($url, false, $context);
if ($asset)
{
$asset = json_decode($asset, true);
if (isset($asset["errors"]))
{
if ((int)$asset["errors"][0]["code"] == 0)
{
// We messed up something
http_response_code(400);
exit();
}
http_response_code((int)$asset["errors"][0]["code"]); // handles 404, 409, etc.
exit();
}
// Required for conflict between "Location" and "location"
foreach ($asset as $key => $value)
{
$asset[trim(strtolower($key))] = trim($value);
}
// Deliver Roblox asset
$file = file_get_contents($asset["location"]);
$headers = parse_response_headers($http_response_header); // $http_response_header materializes out of thin air. parse_response_headers is our own function
header("Content-Length: " . $headers["Content-Length"]);
header("Content-Type: " . $headers["Content-Type"]);
exit($file); // Return it
}
else
{
// Internal error
http_response_code(400);
exit();
}
// We fell through literally everything. This shouldn't ever happen, but if this is the case, then lets not leave holes open
http_response_code(404);
exit();
?>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment