Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Every handler connect signal data(QByteArray) and end() of every request #59

Closed
tnm0113 opened this issue Dec 27, 2014 · 6 comments
Closed
Labels

Comments

@tnm0113
Copy link

tnm0113 commented Dec 27, 2014

Hi everyone,
I have many handlers inherit Tufao::AbstractHttpServerRequestHandler. In each handler, I have slots: onData(QByteArray) connect with signal data(QByteArray) and onEndRequest() connect with signal end() of each request comes to handler.
I also have router to route request to right handler.
But every time new request comes, it emits signal data(QByteArray), signal end() and all of my handlers catch these signal and connect to their slots.
Can you have a try to give an answer? thanks a lot.
Edited: I use Tufao on branch 0.x for Qt 4.7

@tnm0113 tnm0113 changed the title Every handler connect signal data(QByteArray) and end() Every handler connect signal data(QByteArray) and end() of every request Dec 27, 2014
@vinipsmaker
Copy link
Owner

Can you have a try to give an answer?

I didn't quite understand what is the question. Can you elaborate a little more?

Even if I didn't understand the question, it reminds me of the differences between Tufão 0.x and 1.x.

@tnm0113
Copy link
Author

tnm0113 commented Dec 29, 2014

Tks for reply me !!, I have an example here with 2 handlers: Handler1, Handler2

class Handler1 : public Tufao::AbstractHttpServerRequestHandler
{
.......
public slots:
bool handleRequest(Tufao::HttpServerRequest *request,
Tufao::HttpServerResponse *response,
const QStringList &args);
void onEndRequest();
};

class Handler2 : public Tufao::AbstractHttpServerRequestHandler
{
..........
public slots:
bool handleRequest(Tufao::HttpServerRequest *request,
Tufao::HttpServerResponse *response,
const QStringList &args);
void onEndRequest();
};

In slot handleRequest, I have:
connect(request, SIGNAL(end()), this, SLOT(onEndRequest()));

In slot onEndRequest(), I log this:
handler1.cpp: qDebug() << "END ACCESS HANDLER 1";
handler2.cpp: qDebug() << "END ACCESS HANDLER 2";

In main:
router.map(QRegExp("^/handler1"), &hand1)
.map(QRegExp("^/handler2"), &hand2);

So every request comes to handler will go through handleRequest, right? Request to /handler1 comes to handleRequest of Handler1, and request to /handler2 comes to handleRequest of Handler2. And when request ends, it will go to onEndRequest().

First time I request to /handler1. it logs:
"END ACCESS HANDLER 1";

Second time, it logs double:
"END ACCESS HANDLER 1";
"END ACCESS HANDLER 1";

Third time, it becomes trible:
"END ACCESS HANDLER 1";
"END ACCESS HANDLER 1";
"END ACCESS HANDLER 1";

And request to /handler2, it logs:
"END ACCESS HANDLER 1";
"END ACCESS HANDLER 1";
"END ACCESS HANDLER 1";
"END ACCESS HANDLER 2";

It seems the previous requests haven't ended yet. They still emit the signal end() and the handlers still catch this signal.

Can you explain for me this situation ? Tks alot

@vinipsmaker
Copy link
Owner

Can you explain for me this situation ? Tks alot

Well, this is one of the differences between Tufão 0.x and Tufão 1.x and I used an alternative approach in Tufão 1.x because I acknowledged the lack of intuitiveness:

[In Tufão 1.x] HttpServerRequest::ready signal auto-disconnects all slots connected to the HttpServerRequest::data and HttpServerRequest::end slots before being emitted.

To understand what it is happening, you just need to realize that HttpServerRequest will NOT abstract a single session (i.e. a pair of request and reply). HttpServerRequest will abstract a whole connection. The object is reused for other pairs of requests and replies within the same connection. So, before you're done with the object, you need to unglue all callbacks that you configured before.

Currently, this is what is happening to your code:

  1. A connection is initiated, then a HttpServerRequest object is created.
  2. A request on this connection is ready, so the ready signal is emitted.
  3. On the onReady slot, you add a connection on the data signal.
  4. (Whatever, a lot happens)
  5. A new request is ready on the same connection, so, for the same object, the ready signal is once again emitted.
  6. On the onReady slot, you add a new and fresh connection on the data signal. But this new signal-slot connection is redundant, because there was a previous connection that is identical to the new one. Now, you have two connections and the slot will be called two times.

Was I clear?

Fix: On the onEnd slot, clear all connections that you have made on the onReady slot.

Alternative fix: Use Tufão 1.x, as it will automatically disconnects all slots connected to the HttpServerRequest::data and HttpServerRequest::end slots before emitting the ready signal. I cannot backport these changes to Tufão 0.x because I have a compromise on API stability and the change would break how you use the API.

@tnm0113
Copy link
Author

tnm0113 commented Dec 29, 2014

Thank you so so much. Unfortunately, I must use Qt 4.7 so I can't use Tufao 1.x. But if I don't handle the ready signal, how can I clear all previous connections ? Can you give me an example

@vinipsmaker
Copy link
Owner

But if I don't handle the ready signal, how can I clear all previous connections ?

There isn't much secret here. The trick is to ensure there is only one signal-slot connection. You can even use Qt::UniqueConnection, but I cannot recommend this as a general case because it's very easy to create bugs. You must be careful and understand what you're doing because HTTP is stateless and data artifacts from one pair of request and response must not escape to another unrelated pair of request and response.

Anyway, in handleRequest, just clear all slots connected to the data and end signals before doing anything. But this must be done for the whole project.

Can you give me an example

I'm on the middle of a timeline now, so I cannot give much resources to this issue now. If you remind me on January 2 (or later), I believe I'll have the time to elaborate an example.

@tnm0113
Copy link
Author

tnm0113 commented Dec 29, 2014

Thank you, I appreciate it a lot

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants