diff options
-rw-r--r-- | .gitignore | 3 | ||||
-rw-r--r-- | .htaccess | 9 | ||||
-rw-r--r-- | Dockerfile | 15 | ||||
-rw-r--r-- | composer.json | 24 | ||||
-rw-r--r-- | composer.lock | 47 | ||||
-rw-r--r-- | docker-compose.yml | 5 | ||||
-rw-r--r-- | index.php | 83 | ||||
-rw-r--r-- | test/router.php | 3 |
8 files changed, 189 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..2879d3b --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +/vendor/ + +.env diff --git a/.htaccess b/.htaccess new file mode 100644 index 0000000..d025b2b --- /dev/null +++ b/.htaccess @@ -0,0 +1,9 @@ +RewriteEngine On +# Redirect /index.php to / (optional, but recommended I guess) +RewriteCond %{THE_REQUEST} ^[A-Z]{3,9}\ /.*index\.php +RewriteRule ^index.php/?(.*)$ $1 [R=301,L] + +# Run everything else but real files through index.php +RewriteCond %{REQUEST_FILENAME} !-d +RewriteCond %{REQUEST_FILENAME} !-f +RewriteRule ^(.*)$ index.php/$1?%{QUERY_STRING} [L] diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..bdb70e1 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,15 @@ +FROM php:apache + +COPY --from=composer /usr/bin/composer /usr/bin/composer + +WORKDIR /var/www/html + +RUN apt-get update && apt-get -y install git + +COPY composer* . +RUN composer install + +RUN a2enmod rewrite + +COPY index.php . +COPY .htaccess . diff --git a/composer.json b/composer.json new file mode 100644 index 0000000..4393981 --- /dev/null +++ b/composer.json @@ -0,0 +1,24 @@ +{ + "name": "dweipert/gemini-http-proxy", + "authors": [ + { + "name": "Daniel Weipert", + "email": "code@drogueronin.de" + } + ], + "require": { + "dweipert/gemini-foundation": "dev-main" + }, + "repositories": [ + { + "type": "vcs", + "url": "https://git.dweipert.de/gemini-foundation" + } + ], + "minimum-stability": "dev", + "autoload": { + "psr-4": { + "Dweipert\\GeminiHttpProxy\\": "src/" + } + } +} diff --git a/composer.lock b/composer.lock new file mode 100644 index 0000000..c6f6310 --- /dev/null +++ b/composer.lock @@ -0,0 +1,47 @@ +{ + "_readme": [ + "This file locks the dependencies of your project to a known state", + "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", + "This file is @generated automatically" + ], + "content-hash": "5402a4c52a05baa8de485a52ec6532cc", + "packages": [ + { + "name": "dweipert/gemini-foundation", + "version": "dev-main", + "source": { + "type": "git", + "url": "https://git.dweipert.de/gemini-foundation", + "reference": "bc4d0071d7a0726e08b44795ff29cc1d0262dfe4" + }, + "default-branch": true, + "type": "library", + "autoload": { + "psr-4": { + "GeminiFoundation\\": "src/" + }, + "files": [ + "src/functions.php" + ] + }, + "authors": [ + { + "name": "Daniel Weipert", + "email": "code@drogueronin.de" + } + ], + "time": "2023-11-13T12:15:40+00:00" + } + ], + "packages-dev": [], + "aliases": [], + "minimum-stability": "dev", + "stability-flags": { + "dweipert/gemini-foundation": 20 + }, + "prefer-stable": false, + "prefer-lowest": false, + "platform": [], + "platform-dev": [], + "plugin-api-version": "2.6.0" +} diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..8dd6e04 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,5 @@ +services: + proxy: + build: . + environment: + - "GEMINI_HOST=${GEMINI_HOST}" diff --git a/index.php b/index.php new file mode 100644 index 0000000..23c314f --- /dev/null +++ b/index.php @@ -0,0 +1,83 @@ +<?php + +use GeminiFoundation\Client; +use GeminiFoundation\Gemtext; + +require __DIR__ . '/vendor/autoload.php'; + +$geminiHost = $_ENV['GEMINI_HOST']; + +$url = parse_url( + "//$_SERVER[HTTP_HOST]$_SERVER[REQUEST_URI]" +); +$url['query'] ??= ''; + +$client = new Client($geminiHost); +$response = $client->request("$url[path]$url[query]"); + +ob_start(); +$mime = explode(';', $response->getMeta())[0]; +if (strpos($mime, 'text/gemini') === 0) { + $parser = new Gemtext($response->getBody()); + $lines = $parser->parse(); + + $wasListItem = false; + $currentListItems = []; + foreach ($lines as $line) { + if ($wasListItem && $line['type'] !== 'listitem') { + echo "<ul>"; + foreach ($currentListItems as $listItem) { + echo "<li>$listItem[text]</li>"; + } + echo "</ul>"; + $wasListItem = false; + $currentListItems = []; + } + + if ($line['type'] === 'preformatted_on') { + echo "<div>$line[alt]</div><pre>"; + } + else if ($line['type'] === 'preformatted') { + echo htmlentities($line['raw']); + } + else if ($line['type'] === 'preformatted_off') { + echo "</pre>"; + } + else if ($line['type'] === 'heading') { + echo "<h$line[size]>$line[text]</h$line[size]>"; + } + else if ($line['type'] === 'listitem') { + $currentListItems[] = $line; + $wasListItem = true; + } + else if ($line['type'] === 'quote') { + echo "<blockquote>$line[text]</blockquote>"; + } + else if ($line['type'] === 'link') { + $line['link'] = str_replace(["gemini://$geminiHost", $geminiHost], "https://$geminiHost", $line['link']); + $line['text'] = $line['text'] ?: $line['link']; + echo "<a href=\"$line[link]\">$line[text]</a>"; + } + else if ($line['type'] === 'text') { + echo "<p>$line[text]</p>"; + } + } +} + +else if (strpos($mime, 'image') === 0) { + echo "<img src=\"data:{$mime};base64," . base64_encode($response->getBody()) . "\">"; +} + +echo "<hr>"; +echo "Proxied from <a href=\"gemini://$geminiHost$url[path]$url[query]\">gemini://$geminiHost$url[path]$url[query]</a>"; +$content = ob_get_clean(); + +?> +<!doctype html> +<html> + <head> + </head> + <body> + <?php echo $content; ?> + </body> +</html> diff --git a/test/router.php b/test/router.php new file mode 100644 index 0000000..cead5ee --- /dev/null +++ b/test/router.php @@ -0,0 +1,3 @@ +<?php + +include dirname(__DIR__) . '/index.php'; |