<commit_before>#include "private/qhttpserverconnection_private.hpp"

///////////////////////////////////////////////////////////////////////////////
namespace qhttp {
namespace server {
///////////////////////////////////////////////////////////////////////////////
QHttpConnection::QHttpConnection(QObject *parent)
    : QTcpSocket(parent), d_ptr(new QHttpConnectionPrivate(this)) {
    d_ptr->initialize();
    QHTTP_LINE_LOG
}

QHttpConnection::QHttpConnection(QHttpConnectionPrivate& dd, QObject* parent)
    : QTcpSocket(parent), d_ptr(&dd) {
    d_ptr->initialize();
    QHTTP_LINE_LOG
}

QHttpConnection::~QHttpConnection() {
    QHTTP_LINE_LOG
}

void
QHttpConnection::setTimeOut(quint32 miliSeconds) {
    if ( miliSeconds != 0 )
        d_func()->itimer.start(miliSeconds, Qt::CoarseTimer, this);
}

void
QHttpConnection::killConnection() {
    disconnectFromHost();
}

void
QHttpConnection::onHandler(const TServerHandler &handler) {
    d_func()->ihandler = handler;
}

void
QHttpConnection::timerEvent(QTimerEvent *) {
    disconnectFromHost();
}

///////////////////////////////////////////////////////////////////////////////

int
QHttpConnectionPrivate::messageBegin(http_parser*) {
    itempUrl.clear();
    itempUrl.reserve(128);

    QTcpSocket* sok = static_cast<QTcpSocket*>(q_ptr);
    Q_ASSERT(sok);
    irequest = new QHttpRequest(sok);
    return 0;
}

int
QHttpConnectionPrivate::url(http_parser*, const char* at, size_t length) {
    Q_ASSERT(irequest);

    itempUrl.append(at, length);
    return 0;
}

int
QHttpConnectionPrivate::headerField(http_parser*, const char* at, size_t length) {
    Q_ASSERT(irequest);

    // insert the header we parsed previously
    // into the header map
    if ( !itempHeaderField.isEmpty() && !itempHeaderValue.isEmpty() ) {
        // header names are always lower-cased
        irequest->d_func()->iheaders.insert(
                    itempHeaderField.toLower(),
                    itempHeaderValue.toLower()
                    );
        // clear header value. this sets up a nice
        // feedback loop where the next time
        // HeaderValue is called, it can simply append
        itempHeaderField.clear();
        itempHeaderValue.clear();
    }

    itempHeaderField.append(at, length);
    return 0;
}

int
QHttpConnectionPrivate::headerValue(http_parser*, const char* at, size_t length) {
    Q_ASSERT(irequest);

    itempHeaderValue.append(at, length);
    return 0;
}

int
QHttpConnectionPrivate::headersComplete(http_parser* parser) {
    Q_ASSERT(irequest);

#if defined(USE_CUSTOM_URL_CREATOR)
    // get parsed url
    struct http_parser_url urlInfo;
    int r = http_parser_parse_url(itempUrl.constData(),
                                  itempUrl.size(),
                                  parser->method == HTTP_CONNECT,
                                  &urlInfo);
    Q_ASSERT(r == 0);
    Q_UNUSED(r);

    irequest->d_func()->iurl = createUrl(
                                 itempUrl.constData(),
                                 urlInfo
                                 );
#else
    irequest->d_func()->iurl = QUrl(itempUrl);
#endif // defined(USE_CUSTOM_URL_CREATOR)

    // set method
    irequest->d_func()->imethod =
            static_cast<THttpMethod>(parser->method);

    // set version
    irequest->d_func()->iversion = QString("%1.%2")
                                 .arg(parser->http_major)
                                 .arg(parser->http_minor);

    // Insert last remaining header
    irequest->d_func()->iheaders.insert(
                itempHeaderField.toLower(),
                itempHeaderValue.toLower()
                );

    // set client information
    irequest->d_func()->iremoteAddress = isocket->peerAddress().toString();
    irequest->d_func()->iremotePort    = isocket->peerPort();



    iresponse = new QHttpResponse(isocket);

    if ( parser->http_major < 1 || parser->http_minor < 1  ) {

        iresponse->d_func()->ikeepAlive = false;
    }

    // we are good to go!
    if ( ihandler )
        ihandler(irequest, iresponse);
    else
        emit q_ptr->newRequest(irequest, iresponse);

    return 0;
}

int
QHttpConnectionPrivate::body(http_parser*, const char* at, size_t length) {
    Q_ASSERT(irequest);

    if ( irequest->idataHandler )
        irequest->idataHandler(QByteArray(at, length));
    else
        emit irequest->data(QByteArray(at, length));

    return 0;
}

int
QHttpConnectionPrivate::messageComplete(http_parser*) {
    Q_ASSERT(irequest);<commit_msg>fix a bug in qhttpserverconnection.<commit_after>#include "private/qhttpserverconnection_private.hpp"

///////////////////////////////////////////////////////////////////////////////
namespace qhttp {
namespace server {
///////////////////////////////////////////////////////////////////////////////
QHttpConnection::QHttpConnection(QObject *parent)
    : QTcpSocket(parent), d_ptr(new QHttpConnectionPrivate(this)) {
    d_ptr->initialize();
    QHTTP_LINE_LOG
}

QHttpConnection::QHttpConnection(QHttpConnectionPrivate& dd, QObject* parent)
    : QTcpSocket(parent), d_ptr(&dd) {
    d_ptr->initialize();
    QHTTP_LINE_LOG
}

QHttpConnection::~QHttpConnection() {
    QHTTP_LINE_LOG
}

void
QHttpConnection::setTimeOut(quint32 miliSeconds) {
    if ( miliSeconds != 0 )
        d_func()->itimer.start(miliSeconds, Qt::CoarseTimer, this);
}

void
QHttpConnection::killConnection() {
    disconnectFromHost();
}

void
QHttpConnection::onHandler(const TServerHandler &handler) {
    d_func()->ihandler = handler;
}

void
QHttpConnection::timerEvent(QTimerEvent *) {
    disconnectFromHost();
}

///////////////////////////////////////////////////////////////////////////////

// if user closes the connection, ends the response or by any other reason
//  the socket be disconnected, then the irequest and iresponse instances may bhave been deleted.
//  In these situations reading more http body or emitting end() for incoming request
//  are not possible.
#define CHECK_FOR_DISCONNECTED  if ( irequest == nullptr ) \
    return 0;


int
QHttpConnectionPrivate::messageBegin(http_parser*) {
    itempUrl.clear();
    itempUrl.reserve(128);

    QTcpSocket* sok = static_cast<QTcpSocket*>(q_ptr);
    Q_ASSERT(sok);
    irequest = new QHttpRequest(sok);
    return 0;
}

int
QHttpConnectionPrivate::url(http_parser*, const char* at, size_t length) {
    Q_ASSERT(irequest);

    itempUrl.append(at, length);
    return 0;
}

int
QHttpConnectionPrivate::headerField(http_parser*, const char* at, size_t length) {
    CHECK_FOR_DISCONNECTED

    // insert the header we parsed previously
    // into the header map
    if ( !itempHeaderField.isEmpty() && !itempHeaderValue.isEmpty() ) {
        // header names are always lower-cased
        irequest->d_func()->iheaders.insert(
                    itempHeaderField.toLower(),
                    itempHeaderValue.toLower()
                    );
        // clear header value. this sets up a nice
        // feedback loop where the next time
        // HeaderValue is called, it can simply append
        itempHeaderField.clear();
        itempHeaderValue.clear();
    }

    itempHeaderField.append(at, length);
    return 0;
}

int
QHttpConnectionPrivate::headerValue(http_parser*, const char* at, size_t length) {
    CHECK_FOR_DISCONNECTED

    itempHeaderValue.append(at, length);
    return 0;
}

int
QHttpConnectionPrivate::headersComplete(http_parser* parser) {
    CHECK_FOR_DISCONNECTED

#if defined(USE_CUSTOM_URL_CREATOR)
    // get parsed url
    struct http_parser_url urlInfo;
    int r = http_parser_parse_url(itempUrl.constData(),
                                  itempUrl.size(),
                                  parser->method == HTTP_CONNECT,
                                  &urlInfo);
    Q_ASSERT(r == 0);
    Q_UNUSED(r);

    irequest->d_func()->iurl = createUrl(
                                 itempUrl.constData(),
                                 urlInfo
                                 );
#else
    irequest->d_func()->iurl = QUrl(itempUrl);
#endif // defined(USE_CUSTOM_URL_CREATOR)

    // set method
    irequest->d_func()->imethod =
            static_cast<THttpMethod>(parser->method);

    // set version
    irequest->d_func()->iversion = QString("%1.%2")
                                 .arg(parser->http_major)
                                 .arg(parser->http_minor);

    // Insert last remaining header
    irequest->d_func()->iheaders.insert(
                itempHeaderField.toLower(),
                itempHeaderValue.toLower()
                );

    // set client information
    irequest->d_func()->iremoteAddress = isocket->peerAddress().toString();
    irequest->d_func()->iremotePort    = isocket->peerPort();



    iresponse = new QHttpResponse(isocket);

    if ( parser->http_major < 1 || parser->http_minor < 1  ) {

        iresponse->d_func()->ikeepAlive = false;
    }

    // we are good to go!
    if ( ihandler )
        ihandler(irequest, iresponse);
    else
        emit q_ptr->newRequest(irequest, iresponse);

    return 0;
}

int
QHttpConnectionPrivate::body(http_parser*, const char* at, size_t length) {
    CHECK_FOR_DISCONNECTED

    if ( irequest->idataHandler )
        irequest->idataHandler(QByteArray(at, length));
    else
        emit irequest->data(QByteArray(at, length));

    return 0;
}

int
QHttpConnectionPrivate::messageComplete(http_parser*) {
    CHECK_FOR_DISCONNECTED
{'fraction_non_alphanumeric': 0.15703530908705335, 'fraction_numerical': 0.0037111653059060546, 'mean_word_length': 2.2445820433436534, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 75, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 14, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4866599', 'n_tokens_mistral': 2782, 'n_tokens_neox': 2690, 'n_words': 529}