Время от времени на форумах рунета появляются люди, которые собираются писать веб приложение, restful api.
И тут подумал, а почему бы и нет?
Согласен, что иногда бывает неплохо иметь веб интерфейс к существующей программе. Пример таких программ Transmission, EiskaltDC++.
Существующие решения на Qt(которые нагуглил):
Не могу не упомянуть:
Почему не libqxt, QHttpServer? Потому что они асинхронные и не такие удобные как slim и mojolicious(видно сказывается сидение под Zenwalk).
Как выглядит Hello World:
Hello World- это скучно, поэтому сделаем приложение рисующее множество Мандельброта, что бы хоть как-нибудь оправдать использования потоков.
Установка обработчиков:
Выдача страницы с формой:
Рисование картинки штука простая, и не стоит особого внимания:
Для REST не хватает реализации маршрутов в таком виде в каком они существуют в slim и mojolicious(Задачка непростая и требует много времени).
П. С.
Не отношусь к теме написанию веб приложений и rest api на Qt серьезно. Код.
И тут подумал, а почему бы и нет?
Согласен, что иногда бывает неплохо иметь веб интерфейс к существующей программе. Пример таких программ Transmission, EiskaltDC++.
Существующие решения на Qt(которые нагуглил):
Не могу не упомянуть:
Почему не libqxt, QHttpServer? Потому что они асинхронные и не такие удобные как slim и mojolicious(видно сказывается сидение под Zenwalk).
Как выглядит Hello World:
Gwido::Server server;
server.setThreadPool(Gwido::Server::ThreadPoolPtr(new QThreadPool()));
server.get("/hello_world.html",
[](const Gwido::Request& request,
Gwido::Response& response)
{
response.header().set("Content-type", "text/html");
auto& stream = response.stream();
stream<<"<html><head><title>Gwido Hello Worl example</title></head><body>";
stream<<"<h1>Hello World!</h1>";
stream<<"</body></html>";
});
server.listen(QHostAddress::Any, 8080)
Hello World- это скучно, поэтому сделаем приложение рисующее множество Мандельброта, что бы хоть как-нибудь оправдать использования потоков.
Вид приложения
Установка обработчиков:
server.get("/", titlePage);
server.post("/", titlePage);
server.get("/mandelbrod.png", mandelbrodImage);
server.get("/icon32.png", [&](const Gwido::Request& request,
Gwido::Response& response)
{
response.setType(Gwido::Response::Binary);
response.header().set("Content-type", "image/png");
response.setOutBinaryData(icon);
});
Выдача страницы с формой:
auto titlePage =
[](const Gwido::Request& request,
Gwido::Response& response)
{
response.header().set("Content-type", "text/html");
auto& stream = response.stream();
int width = extractInt(request.param("width"), 512);
int height = extractInt(request.param("heght"), 512);
double qmin = extractDouble(request.param("qmin"),-1.5);
double qmax = extractDouble(request.param("qmax"), 1.5);
double pmin = extractDouble(request.param("pmin"), -2.75);
double pmax = extractDouble(request.param("pmax"), 0.75);
stream<<"<html><head><title>Qt Web - Mandelbrot Example</title>";
stream<<"<link rel='icon' type='image/png' href='/icon32.png' /></head><body>";
stream<<"<h1>Qt Web - Mandelbrot Example</h1>";
stream<<"<form action='/' method='post'>";
stream<<" pMin: <input name='pmin' value='"<<pmin<<"'>";
stream<<" pMax: <input name='pmax' value='"<<pmax<<"'><br>";
stream<<" qMin: <input name='qmin' value='"<<qmin<<"'>";
stream<<" qMax: <input name='qmax' value='"<<qmax<<"'><br>";
stream<<" width(min 512): <input type='number' name='width' min=512 value='"<<width<<"'>";
stream<<" height(min 512): <input type='number' name='heght' min=512 value='"<<height<<"'>";
stream<< "<br><input type='submit' value='draw'>";
stream<< "</form><image src='mandelbrod.png?"<<QString("width=%1&height=%2&qmin=%3&qmax=%4&pmin=%5&pmax=%6")
.arg(width).arg(height)
.arg(qmin).arg(qmax)
.arg(pmin).arg(pmax)<<"'><br>";
stream<<"</body></html>";
};
Рисование картинки штука простая, и не стоит особого внимания:
код
void mandelbrodImage(const Gwido::Request& request,
Gwido::Response& response)
{
response.setType(Gwido::Response::Binary);
response.header().set("Content-type", "image/png");
int width = extractInt(request.param("width"), 512);
int heght = extractInt(request.param("heght"), 512);
QSize resultSize(width, heght);
QImage image(resultSize, QImage::Format_RGB32);
image.fill(Qt::black);
double pMin = extractDouble(request.param("pmin"), -2.75);
double pMax = extractDouble(request.param("pmax"), 0.75);
double dp = (pMax - pMin) / (width);
double qMin = extractDouble(request.param("qmin"), -1.5);
double qMax = extractDouble(request.param("qmax"), 1.5);
double dq = (qMax - qMin) / (heght);
int M = 4;
for (int h = 0; h < heght; ++h)
{
quint32 *scanLine = reinterpret_cast<quint32*>(image.scanLine(h));
for (int w = 0; w < width; ++w)
{
std::complex<double> z0(0, 0);
std::complex<double> c(pMin + w * dp, qMin + h * dq);
double r = 0;
int k = 0;
std::complex<double> z;
do
{
z = z0 * z0 + c;
r = std::norm(z);
++k;
z0 = z;
} while ((r <= M) && (k < COLOR_MAP_SIZE));
if (r > M)
{
scanLine[w] = COLOR_MAP[k];
}
else if (k == COLOR_MAP_SIZE)
{
scanLine[w] = qRgb(0, 0, 0);
}
}
}
{
QBuffer buff;
buff.open(QIODevice::ReadWrite);
image.save(&buff, "PNG");
buff.seek(0);
response.setOutBinaryData(buff.readAll());
}
}
Для REST не хватает реализации маршрутов в таком виде в каком они существуют в slim и mojolicious(Задачка непростая и требует много времени).
П. С.
Не отношусь к теме написанию веб приложений и rest api на Qt серьезно. Код.