Skip to content

Instantly share code, notes, and snippets.

@win-t
Created July 6, 2020 04:58
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save win-t/d41e7bae17f7d8b13c8874bfb50df30f to your computer and use it in GitHub Desktop.
Save win-t/d41e7bae17f7d8b13c8874bfb50df30f to your computer and use it in GitHub Desktop.
<?php
namespace main;
define("BACKEND_SOCKET", '<where the unix socket>');
define("BASE_URL", '<where this file located>');
function exit_500($msg) {
$msg = rtrim($msg, "\n") . "\nDebug trace:\n";
foreach(debug_backtrace() as $trace) {
if(isset($trace['file']) && isset($trace['line'])) {
$msg .= '- ' . $trace['file'] . ':' . $trace['line'] . "\n";
}
}
error_log(substr($msg, 0, 2048));
if(!headers_sent()) {
http_response_code(500);
header('Content-Type: text/plain');
$level = ob_get_level();
for($i = 0; $i < $level; $i++) ob_end_clean();
echo "500 Internal Server error\n\n$msg";
}
exit();
}
set_error_handler(function($no, $msg) { exit_500("error: level errno $no: msg: $msg"); });
set_exception_handler(function($exception) { exit_500("exception: $exception"); });
ini_set('display_errors', 0);
error_reporting(0);
$stat = stat(BACKEND_SOCKET);
if(($stat !== FALSE) && (!(($stat['mode'] & 0170000) == 0140000))) {
exit_500("gateway error: " . BACKEND_SOCKET . " is not a unix socket");
}
$method = strtoupper($_SERVER['REQUEST_METHOD']);
$uri = isset($_SERVER['PATH_INFO']) ? $_SERVER['PATH_INFO'] : "/";
if(isset($_SERVER['QUERY_STRING']) && strlen($_SERVER['QUERY_STRING']) > 0) {
$uri .= "?{$_SERVER['QUERY_STRING']}";
}
$header_in = apache_request_headers();
$header_tobe_removed = array(
'connection', 'keep-alive', 'proxy-authenticate', 'proxy-authorization', 'proxy-connection'
'te', 'trailer', 'transfer-encoding', 'upgrade',
'host', 'x-real-ip', 'x-forwarded-for'
);
foreach($header_in as $k => $v) {
if(strtolower($k) == 'connection') {
foreach(explode(",", $v) as $h) array_push($header_tobe_removed, strtolower(trim($h)));
}
}
$header_out = array();
foreach($header_in as $k => $v) {
if(!in_array(strtolower($k), $header_tobe_removed)) {
array_push($header_out, "$k: $v");
};
}
array_push($header_out, "Host: " . 'service');
array_push($header_out, "X-Real-IP: " . $_SERVER['REMOTE_ADDR']);
array_push($header_out, "X-Forwarded-For: " . $_SERVER['REMOTE_ADDR']);
array_push($header_out, "X-Base-Url: " . BASE_URL);
$stdin = fopen('php://input', 'rb');
$stdout = fopen('php://output', 'wb');
$curl = curl_init();
curl_setopt($curl, CURLOPT_UNIX_SOCKET_PATH, BACKEND_SOCKET);
curl_setopt($curl, CURLOPT_CUSTOMREQUEST, $method);
curl_setopt($curl, CURLOPT_URL, "http://service$uri");
curl_setopt($curl, CURLOPT_HTTPHEADER, $header_out);
if (
$method == "POST" ||
$method == "PUT" ||
$method == "PATCH" ||
$method == "OPTIONS" ||
isset($_SERVER['HTTP_TRANSFER_ENCODING']) ||
isset($_SERVER['CONTENT_LENGTH'])
) {
curl_setopt($curl, CURLOPT_UPLOAD, TRUE);
curl_setopt($curl, CURLOPT_INFILE, $stdin);
}
curl_setopt($curl, CURLOPT_HEADERFUNCTION, function($curl, $data) {
// TODO(win-t): remove hop-by-hop response header
header($data);
return strlen($data);
});
curl_setopt($curl, CURLOPT_FILE, $stdout);
$curl_result = curl_exec($curl);
$curl_errno = curl_errno($curl);
if(($curl_result === FALSE) || ($curl_errno != 0)) {
$errstr = curl_strerror($curl_errno);
exit_500("curl error: $errstr");
}
curl_close($curl);
fclose($stdout);
fclose($stdin);
// TODO(win-t): handle response 101 Switching Protocol
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment