Files
radio/api/_bootstrap.php
T
2026-07-24 05:34:07 -05:00

104 lines
3.2 KiB
PHP

<?php
/**
* api/_bootstrap.php
* ------------------
* Shared setup for every endpoint under /api: loads config, applies error
* settings, and provides small HTTP / JSON helpers.
*/
require_once __DIR__ . '/../config.php';
if (cfg('runtime.show_errors')) {
ini_set('display_errors', '1');
ini_set('display_startup_errors', '1');
error_reporting(E_ALL);
} else {
error_reporting(0);
}
/** Send a JSON response and stop. */
function json_out($data, $status = 200) {
http_response_code($status);
header('Content-Type: application/json; charset=utf-8');
header('Access-Control-Allow-Origin: *');
header('Cache-Control: no-cache, must-revalidate, max-age=0');
echo json_encode($data, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
exit;
}
/** Plain-text response and stop (used by the lyrics endpoint). */
function text_out($text, $status = 200) {
http_response_code($status);
header('Content-Type: text/plain; charset=utf-8');
header('Access-Control-Allow-Origin: *');
header('Cache-Control: no-cache, must-revalidate, max-age=0');
echo $text;
exit;
}
/**
* Perform an HTTP GET and return the body (or null on failure).
* Falls back to file_get_contents when cURL is unavailable.
*/
function http_get($url, $timeout = 5, $headers = []) {
if ($url === '') return null;
if (function_exists('curl_init')) {
$ch = curl_init($url);
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CONNECTTIMEOUT => (int) $timeout,
CURLOPT_TIMEOUT => (int) $timeout,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_MAXREDIRS => 3,
CURLOPT_USERAGENT => 'radio-site/1.0 (+https://github.com)',
]);
if (!empty($headers)) {
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
}
$body = curl_exec($ch);
$code = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
curl_close($ch);
if ($body === false || $code >= 400) return null;
return $body;
}
// Fallback without cURL.
$ctx = stream_context_create([
'http' => [
'timeout' => (int) $timeout,
'header' => implode("\r\n", $headers),
'ignore_errors' => true,
],
'ssl' => ['verify_peer' => true, 'verify_peer_name' => true],
]);
$body = @file_get_contents($url, false, $ctx);
return ($body === false) ? null : $body;
}
/**
* Read a value out of a decoded-JSON structure using dot notation.
* Supports array indexes: "a.b.0.c".
*/
function dot_get($data, $path, $default = null) {
if ($path === '' || $path === null) return $default;
$node = $data;
foreach (explode('.', $path) as $key) {
if (is_array($node) && array_key_exists($key, $node)) {
$node = $node[$key];
} elseif (is_object($node) && isset($node->$key)) {
$node = $node->$key;
} else {
return $default;
}
}
return $node;
}
/** Read the artist/title the browser sends to artwork/lyrics endpoints. */
function request_track() {
$artist = $_POST['artist'] ?? $_GET['artist'] ?? '';
$title = $_POST['title'] ?? $_GET['title'] ?? '';
return [trim((string) $artist), trim((string) $title)];
}