Skip to content

Instantly share code, notes, and snippets.

@CyberShadow
Last active November 14, 2022 02:14
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save CyberShadow/911864f3b0882ec8e8e9bbf75513eef6 to your computer and use it in GitHub Desktop.
Save CyberShadow/911864f3b0882ec8e8e9bbf75513eef6 to your computer and use it in GitHub Desktop.
favicon_ua
// ProxyPassMatch "^/(favicon\.ico)$" http://127.2.146.142:14471/$REAL_UPSTREAM/$1 nocanon
import std.algorithm.searching;
import std.stdio : stderr;
import std.string : split, join;
import ae.net.asockets;
import ae.net.http.client;
import ae.net.http.responseex;
import ae.net.http.server;
import ae.sys.cmd;
import ae.sys.imagemagick;
import ae.utils.graphics.color;
import ae.utils.graphics.image;
class MyClient : HttpClient
{
string realHost; ushort realPort = 81;
override void sendRequest(HttpRequest request)
{
sendRawRequest(request);
}
override void request(HttpRequest request)
{
//debug writefln("New HTTP request: %s", request.url);
currentRequest = request;
currentResponse = null;
conn.handleReadData = &onNewResponse;
expect = 0;
if (conn.state != ConnectionState.disconnected)
{
assert(conn.state == ConnectionState.connected, "Attempting a HTTP request on a %s connection".format(conn.state));
assert(keepAlive, "Attempting a second HTTP request on a connected non-keepalive connection");
sendRequest(request);
}
else
{
connector.connect(realHost, realPort);
}
}
}
void main()
{
auto s = new HttpServer;
s.handleRequest = (HttpRequest request, HttpServerConnection conn) {
stderr.writeln(request.url, " - Request received");
auto client = new MyClient;
client.realHost = request.resource.split("/")[1];
request.resource = "/" ~ request.resource.split("/")[2..$].join("/");
client.handleResponse =
(HttpResponse response, string /*disconnectReason*/)
{
stderr.writeln(request.url, " - Response obtained: ", response.headers.get("Content-Type", null));
if (response.headers.get("Content-Type", null).startsWith("image/"))
{
stderr.writeln(request.url, " - Processing image");
try
{
auto data = response.getContent();
auto image = data.contents.parseViaIMConvert!BGRA(mimeTypeToIMFormat(response.headers["Content-Type"]));
foreach (y; 0 .. image.h)
foreach (ref cell; image.scanline(y))
foreach (ref c; cell)
{
auto g_100 = (
c.r * 7 +
c.g * 72 +
c.b * 21
);
// https://en.wikipedia.org/wiki/Flag_of_Ukraine#Design
if (y < image.h / 2)
{
c.r = 0;
// c.g = cast(ubyte)(g_100 * 87 / (255 * 100));
// c.b = cast(ubyte)(g_100 * 183 / (255 * 100));
c.g = cast(ubyte)(g_100 * 128 / (255 * 100));
c.b = cast(ubyte)(g_100 * 255 / (255 * 100));
}
else
{
c.r = cast(ubyte)(g_100 * 255 / (255 * 100));
c.g = cast(ubyte)(g_100 * 215 / (255 * 100));
c.b = 0;
}
}
response.headers["Content-Type"] = "image/png";
response.headers.remove("Transfer-Encoding");
response.headers.remove("Content-Encoding");
response.headers.remove("Content-Length");
response.data = DataVec(Data(image.colorMap!(c => RGBA(c.r, c.g, c.b, c.a)).toPNG));
foreach (name, value; response.headers)
stderr.writeln(" - ", name, ": ", value);
stderr.writeln(request.url, " - Painted successfully");
}
catch (Exception e)
{
stderr.writeln(request.url, " - ", e);
// oh well
}
}
if (!response.status)
response.setStatus(HttpStatusCode.BadGateway);
conn.sendResponse(response);
};
client.request(request); // TODO sendRawRequest
};
s.listen(14471, "127.2.146.142");
stderr.writeln("Listening on ", s.localAddresses);
socketManager.loop();
}
string mimeTypeToIMFormat(string mimeType)
{
mimeType = mimeType.findSplit(";")[0];
switch (mimeType)
{
case "image/png":
return "png";
case "image/jpeg":
case "image/jpg":
return "jpeg";
case "image/vnd.microsoft.icon":
return "ico";
default:
throw new Exception("Unknown MIME type: " ~ mimeType);
}
}
auto parseViaIMConvert(COLOR)(const(void)[] data, string format)
{
string[] convertFlags;
static if (is(COLOR : BGR))
{
// convertFlags ~= ["-colorspace", "rgb"];
// convertFlags ~= ["-depth", "24"];
convertFlags ~= ["-type", "TrueColor"];
convertFlags ~= ["-alpha", "off"];
}
else
static if (is(COLOR : BGRA))
{
convertFlags ~= ["-type", "TrueColorAlpha"];
convertFlags ~= ["-alpha", "on"];
}
return data
.pipe(["convert".imageMagickBinary()] ~ convertFlags ~ [format ~ ":-[0]", "bmp:-"])
.viewBMP!COLOR();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment