true, CURLOPT_FOLLOWLOCATION => true, CURLOPT_CONNECTTIMEOUT => 20, CURLOPT_TIMEOUT => $timeout, CURLOPT_USERAGENT => $userAgent, CURLOPT_FAILONERROR => false, CURLOPT_HTTPHEADER => $requestHeaders, CURLOPT_HEADERFUNCTION => function ($ch, $line) use (&$responseHeaders) { $pos = strpos($line, ':'); if ($pos !== false) { $name = catalog_http_normalize_header_name(substr($line, 0, $pos)); $value = trim(substr($line, $pos + 1)); $responseHeaders[$name] = $value; } return strlen($line); }, )); $body = curl_exec($ch); if ($body === false) { $err = curl_error($ch); curl_close($ch); throw new RuntimeException('Catalogus ophalen mislukt: ' . $err); } $status = curl_getinfo($ch, CURLINFO_HTTP_CODE); curl_close($ch); if ($status !== 304 && ($status < 200 || $status >= 300)) { throw new RuntimeException('Catalogus gaf HTTP status ' . $status . ' voor ' . $url); } return array( 'status' => $status, 'headers' => $responseHeaders, 'body' => $body, ); } $headerLines = array('User-Agent: ' . $userAgent); foreach ($requestHeaders as $header) { $headerLines[] = $header; } $ctx = stream_context_create(array( 'http' => array( 'method' => 'GET', 'timeout' => $timeout, 'header' => implode("\r\n", $headerLines) . "\r\n", 'ignore_errors' => true, ), )); $body = @file_get_contents($url, false, $ctx); if ($body === false) { throw new RuntimeException('Catalogus ophalen mislukt: ' . $url); } $status = 0; $responseHeaders = array(); $rawHeaders = isset($http_response_header) && is_array($http_response_header) ? $http_response_header : array(); foreach ($rawHeaders as $line) { if (preg_match('/^HTTP\/\S+\s+(\d+)/', $line, $m)) { $status = (int)$m[1]; continue; } $pos = strpos($line, ':'); if ($pos !== false) { $name = catalog_http_normalize_header_name(substr($line, 0, $pos)); $value = trim(substr($line, $pos + 1)); $responseHeaders[$name] = $value; } } if ($status !== 304 && ($status < 200 || $status >= 300)) { throw new RuntimeException('Catalogus gaf HTTP status ' . $status . ' voor ' . $url); } return array( 'status' => $status, 'headers' => $responseHeaders, 'body' => $body, ); } function catalog_http_fetch_cached($url, $cacheFile, $metaFile, $ttl, $userAgent, $timeout = 180) { catalog_http_ensure_dir(dirname($cacheFile)); if (is_file($cacheFile)) { $mtime = filemtime($cacheFile); if ($mtime !== false && $mtime >= time() - $ttl) { $data = file_get_contents($cacheFile); if ($data !== false && $data !== '') { return $data; } } } $meta = catalog_http_read_meta($metaFile); $requestHeaders = is_file($cacheFile) ? catalog_http_validator_headers($meta) : array(); $response = catalog_http_fetch($url, $requestHeaders, $userAgent, $timeout); if ($response['status'] === 304) { $data = file_get_contents($cacheFile); if ($data !== false && $data !== '') { touch($cacheFile); $meta['checked_at'] = time(); catalog_http_write_meta($metaFile, $meta); return $data; } } $data = $response['body']; if (file_put_contents($cacheFile, $data, LOCK_EX) === false) { throw new RuntimeException('Kan catalogus-cache niet schrijven: ' . $cacheFile); } $headers = $response['headers']; $now = time(); $meta = array( 'url' => $url, 'fetched_at' => $now, 'checked_at' => $now, ); if (!empty($headers['etag'])) { $meta['etag'] = $headers['etag']; } if (!empty($headers['last-modified'])) { $meta['last_modified'] = $headers['last-modified']; } catalog_http_write_meta($metaFile, $meta); return $data; }