/** * OpenAPI Petstore * This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters. * * The version of the OpenAPI document: 1.0.0 * * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). * https://openapi-generator.tech * Do not edit the class manually. */ #include #include #include #include #include #include #include #include #include "PFXHttpRequest.h" namespace test_namespace { PFXHttpRequestInput::PFXHttpRequestInput() { initialize(); } PFXHttpRequestInput::PFXHttpRequestInput(QString v_url_str, QString v_http_method) { initialize(); url_str = v_url_str; http_method = v_http_method; } void PFXHttpRequestInput::initialize() { var_layout = NOT_SET; url_str = ""; http_method = "GET"; } void PFXHttpRequestInput::add_var(QString key, QString value) { vars[key] = value; } void PFXHttpRequestInput::add_file(QString variable_name, QString local_filename, QString request_filename, QString mime_type) { PFXHttpFileElement file; file.variable_name = variable_name; file.local_filename = local_filename; file.request_filename = request_filename; file.mime_type = mime_type; files.append(file); } PFXHttpRequestWorker::PFXHttpRequestWorker(QObject *parent, QNetworkAccessManager *_manager) : QObject(parent), manager(_manager), timeOutTimer(this), isResponseCompressionEnabled(false), isRequestCompressionEnabled(false), httpResponseCode(-1) { qsrand(QDateTime::currentDateTime().toTime_t()); if (manager == nullptr) { manager = new QNetworkAccessManager(this); } workingDirectory = QDir::currentPath(); timeOutTimer.setSingleShot(true); } PFXHttpRequestWorker::~PFXHttpRequestWorker() { QObject::disconnect(&timeOutTimer, &QTimer::timeout, nullptr, nullptr); timeOutTimer.stop(); for (const auto &item : multiPartFields) { if (item != nullptr) { delete item; } } } QMap PFXHttpRequestWorker::getResponseHeaders() const { return headers; } PFXHttpFileElement PFXHttpRequestWorker::getHttpFileElement(const QString &fieldname) { if (!files.isEmpty()) { if (fieldname.isEmpty()) { return files.first(); } else if (files.contains(fieldname)) { return files[fieldname]; } } return PFXHttpFileElement(); } QByteArray *PFXHttpRequestWorker::getMultiPartField(const QString &fieldname) { if (!multiPartFields.isEmpty()) { if (fieldname.isEmpty()) { return multiPartFields.first(); } else if (multiPartFields.contains(fieldname)) { return multiPartFields[fieldname]; } } return nullptr; } void PFXHttpRequestWorker::setTimeOut(int timeOutMs) { timeOutTimer.setInterval(timeOutMs); if(timeOutTimer.interval() == 0) { QObject::disconnect(&timeOutTimer, &QTimer::timeout, nullptr, nullptr); } } void PFXHttpRequestWorker::setWorkingDirectory(const QString &path) { if (!path.isEmpty()) { workingDirectory = path; } } void PFXHttpRequestWorker::setResponseCompressionEnabled(bool enable) { isResponseCompressionEnabled = enable; } void PFXHttpRequestWorker::setRequestCompressionEnabled(bool enable) { isRequestCompressionEnabled = enable; } int PFXHttpRequestWorker::getHttpResponseCode() const{ return httpResponseCode; } QString PFXHttpRequestWorker::http_attribute_encode(QString attribute_name, QString input) { // result structure follows RFC 5987 bool need_utf_encoding = false; QString result = ""; QByteArray input_c = input.toLocal8Bit(); char c; for (int i = 0; i < input_c.length(); i++) { c = input_c.at(i); if (c == '\\' || c == '/' || c == '\0' || c < ' ' || c > '~') { // ignore and request utf-8 version need_utf_encoding = true; } else if (c == '"') { result += "\\\""; } else { result += c; } } if (result.length() == 0) { need_utf_encoding = true; } if (!need_utf_encoding) { // return simple version return QString("%1=\"%2\"").arg(attribute_name, result); } QString result_utf8 = ""; for (int i = 0; i < input_c.length(); i++) { c = input_c.at(i); if ((c >= '0' && c <= '9') || (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z')) { result_utf8 += c; } else { result_utf8 += "%" + QString::number(static_cast(input_c.at(i)), 16).toUpper(); } } // return enhanced version with UTF-8 support return QString("%1=\"%2\"; %1*=utf-8''%3").arg(attribute_name, result, result_utf8); } void PFXHttpRequestWorker::execute(PFXHttpRequestInput *input) { // reset variables QNetworkReply *reply = nullptr; QByteArray request_content = ""; response = ""; error_type = QNetworkReply::NoError; error_str = ""; bool isFormData = false; // decide on the variable layout if (input->files.length() > 0) { input->var_layout = MULTIPART; } if (input->var_layout == NOT_SET) { input->var_layout = input->http_method == "GET" || input->http_method == "HEAD" ? ADDRESS : URL_ENCODED; } // prepare request content QString boundary = ""; if (input->var_layout == ADDRESS || input->var_layout == URL_ENCODED) { // variable layout is ADDRESS or URL_ENCODED if (input->vars.count() > 0) { bool first = true; isFormData = true; foreach (QString key, input->vars.keys()) { if (!first) { request_content.append("&"); } first = false; request_content.append(QUrl::toPercentEncoding(key)); request_content.append("="); request_content.append(QUrl::toPercentEncoding(input->vars.value(key))); } if (input->var_layout == ADDRESS) { input->url_str += "?" + request_content; request_content = ""; } } } else { // variable layout is MULTIPART boundary = QString("__-----------------------%1%2") .arg(QDateTime::currentDateTime().toTime_t()) .arg(qrand()); QString boundary_delimiter = "--"; QString new_line = "\r\n"; // add variables foreach (QString key, input->vars.keys()) { // add boundary request_content.append(boundary_delimiter); request_content.append(boundary); request_content.append(new_line); // add header request_content.append("Content-Disposition: form-data; "); request_content.append(http_attribute_encode("name", key)); request_content.append(new_line); request_content.append("Content-Type: text/plain"); request_content.append(new_line); // add header to body splitter request_content.append(new_line); // add variable content request_content.append(input->vars.value(key)); request_content.append(new_line); } // add files for (QList::iterator file_info = input->files.begin(); file_info != input->files.end(); file_info++) { QFileInfo fi(file_info->local_filename); // ensure necessary variables are available if (file_info->local_filename == nullptr || file_info->local_filename.isEmpty() || file_info->variable_name == nullptr || file_info->variable_name.isEmpty() || !fi.exists() || !fi.isFile() || !fi.isReadable()) { // silent abort for the current file continue; } QFile file(file_info->local_filename); if (!file.open(QIODevice::ReadOnly)) { // silent abort for the current file continue; } // ensure filename for the request if (file_info->request_filename == nullptr || file_info->request_filename.isEmpty()) { file_info->request_filename = fi.fileName(); if (file_info->request_filename.isEmpty()) { file_info->request_filename = "file"; } } // add boundary request_content.append(boundary_delimiter); request_content.append(boundary); request_content.append(new_line); // add header request_content.append( QString("Content-Disposition: form-data; %1; %2").arg(http_attribute_encode("name", file_info->variable_name), http_attribute_encode("filename", file_info->request_filename))); request_content.append(new_line); if (file_info->mime_type != nullptr && !file_info->mime_type.isEmpty()) { request_content.append("Content-Type: "); request_content.append(file_info->mime_type); request_content.append(new_line); } request_content.append("Content-Transfer-Encoding: binary"); request_content.append(new_line); // add header to body splitter request_content.append(new_line); // add file content request_content.append(file.readAll()); request_content.append(new_line); file.close(); } // add end of body request_content.append(boundary_delimiter); request_content.append(boundary); request_content.append(boundary_delimiter); } if (input->request_body.size() > 0) { qDebug() << "got a request body"; request_content.clear(); if(!isFormData && (input->var_layout != MULTIPART) && isRequestCompressionEnabled){ request_content.append(compress(input->request_body, 7, PFXCompressionType::Gzip)); } else { request_content.append(input->request_body); } } // prepare connection QNetworkRequest request = QNetworkRequest(QUrl(input->url_str)); if (PFXHttpRequestWorker::sslDefaultConfiguration != nullptr) { request.setSslConfiguration(*PFXHttpRequestWorker::sslDefaultConfiguration); } request.setRawHeader("User-Agent", "OpenAPI-Generator/1.0.0/cpp-qt5"); foreach (QString key, input->headers.keys()) { request.setRawHeader(key.toStdString().c_str(), input->headers.value(key).toStdString().c_str()); } if (request_content.size() > 0 && !isFormData && (input->var_layout != MULTIPART)) { if (!input->headers.contains("Content-Type")) { request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); } else { request.setHeader(QNetworkRequest::ContentTypeHeader, input->headers.value("Content-Type")); } if(isRequestCompressionEnabled){ request.setRawHeader("Content-Encoding", "gzip"); } } else if (input->var_layout == URL_ENCODED) { request.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded"); } else if (input->var_layout == MULTIPART) { request.setHeader(QNetworkRequest::ContentTypeHeader, "multipart/form-data; boundary=" + boundary); } if(isResponseCompressionEnabled){ request.setRawHeader("Accept-Encoding", "gzip"); } else { request.setRawHeader("Accept-Encoding", "identity"); } if (input->http_method == "GET") { reply = manager->get(request); } else if (input->http_method == "POST") { reply = manager->post(request, request_content); } else if (input->http_method == "PUT") { reply = manager->put(request, request_content); } else if (input->http_method == "HEAD") { reply = manager->head(request); } else if (input->http_method == "DELETE") { reply = manager->deleteResource(request); } else { #if (QT_VERSION >= 0x050800) reply = manager->sendCustomRequest(request, input->http_method.toLatin1(), request_content); #else QBuffer *buffer = new QBuffer; buffer->setData(request_content); buffer->open(QIODevice::ReadOnly); reply = manager->sendCustomRequest(request, input->http_method.toLatin1(), buffer); buffer->setParent(reply); #endif } if (reply != nullptr) { reply->setParent(this); connect(reply, &QNetworkReply::finished, [this, reply] { on_reply_finished(reply); }); } if (timeOutTimer.interval() > 0) { QObject::connect(&timeOutTimer, &QTimer::timeout, [this, reply] { on_reply_timeout(reply); }); timeOutTimer.start(); } } void PFXHttpRequestWorker::on_reply_finished(QNetworkReply *reply) { bool codeSts = false; if(timeOutTimer.isActive()) { QObject::disconnect(&timeOutTimer, &QTimer::timeout, nullptr, nullptr); timeOutTimer.stop(); } error_type = reply->error(); error_str = reply->errorString(); if (reply->rawHeaderPairs().count() > 0) { for (const auto &item : reply->rawHeaderPairs()) { headers.insert(item.first, item.second); } } auto rescode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(&codeSts); if(codeSts){ httpResponseCode = rescode; } else{ httpResponseCode = -1; } process_response(reply); reply->deleteLater(); emit on_execution_finished(this); } void PFXHttpRequestWorker::on_reply_timeout(QNetworkReply *reply) { error_type = QNetworkReply::TimeoutError; response = ""; error_str = "Timed out waiting for response"; disconnect(reply, nullptr, nullptr, nullptr); reply->abort(); reply->deleteLater(); emit on_execution_finished(this); } void PFXHttpRequestWorker::process_response(QNetworkReply *reply) { if (getResponseHeaders().contains(QString("Content-Disposition"))) { auto contentDisposition = getResponseHeaders().value(QString("Content-Disposition").toUtf8()).split(QString(";"), QString::SkipEmptyParts); auto contentType = getResponseHeaders().contains(QString("Content-Type")) ? getResponseHeaders().value(QString("Content-Type").toUtf8()).split(QString(";"), QString::SkipEmptyParts).first() : QString(); if ((contentDisposition.count() > 0) && (contentDisposition.first() == QString("attachment"))) { QString filename = QUuid::createUuid().toString(); for (const auto &file : contentDisposition) { if (file.contains(QString("filename"))) { filename = file.split(QString("="), QString::SkipEmptyParts).at(1); break; } } PFXHttpFileElement felement; felement.saveToFile(QString(), workingDirectory + QDir::separator() + filename, filename, contentType, reply->readAll()); files.insert(filename, felement); } } else if (getResponseHeaders().contains(QString("Content-Type"))) { auto contentType = getResponseHeaders().value(QString("Content-Type").toUtf8()).split(QString(";"), QString::SkipEmptyParts); if ((contentType.count() > 0) && (contentType.first() == QString("multipart/form-data"))) { // TODO : Handle Multipart responses } else { if(headers.contains("Content-Encoding")){ auto encoding = headers.value("Content-Encoding").split(QString(";"), QString::SkipEmptyParts); if(encoding.count() > 0){ auto compressionTypes = encoding.first().split(',', QString::SkipEmptyParts); if(compressionTypes.contains("gzip", Qt::CaseInsensitive) || compressionTypes.contains("deflate", Qt::CaseInsensitive)){ response = decompress(reply->readAll()); } else if(compressionTypes.contains("identity", Qt::CaseInsensitive)){ response = reply->readAll(); } } } else { response = reply->readAll(); } } } } QByteArray PFXHttpRequestWorker::decompress(const QByteArray& data){ Q_UNUSED(data); return QByteArray(); } QByteArray PFXHttpRequestWorker::compress(const QByteArray& input, int level, PFXCompressionType compressType) { Q_UNUSED(input); Q_UNUSED(level); Q_UNUSED(compressType); return QByteArray(); } QSslConfiguration *PFXHttpRequestWorker::sslDefaultConfiguration; } // namespace test_namespace