From 22e251ac35b54b81732566378fc8d336c6dac0bb Mon Sep 17 00:00:00 2001 From: Justin Karneges Date: Fri, 6 Sep 2024 14:07:04 -0700 Subject: [PATCH] add support for gone links --- src/handler/httpsession.cpp | 51 ++++++++++++++++++++++++++++++++++++- src/handler/instruct.cpp | 6 +++++ src/handler/instruct.h | 1 + src/proxy/proxyutil.cpp | 2 +- 4 files changed, 58 insertions(+), 2 deletions(-) diff --git a/src/handler/httpsession.cpp b/src/handler/httpsession.cpp index 84b3cf2b..d96d2f91 100644 --- a/src/handler/httpsession.cpp +++ b/src/handler/httpsession.cpp @@ -115,7 +115,8 @@ class HttpSession::Private : public QObject Proxying, SendingQueue, Holding, - Closing + Closing, + SendingGone, }; enum Priority @@ -165,6 +166,7 @@ class HttpSession::Private : public QObject QString errorMessage; QUrl currentUri; QUrl nextUri; + QUrl goneUri; bool needUpdate; Priority needUpdatePriority; UpdateAction *pendingAction; @@ -231,6 +233,12 @@ class HttpSession::Private : public QObject if(!instruct.nextLink.isEmpty()) nextUri = currentUri.resolved(instruct.nextLink); + + // only work with a gone link provided at initialization time. this + // way each request can have a unique gone link, and still share + // instructions from next link fetches + if(!instruct.goneLink.isEmpty()) + goneUri = currentUri.resolved(instruct.goneLink); } ~Private() @@ -1168,6 +1176,23 @@ class HttpSession::Private : public QObject stats->removeConnection(cid, false); } + if(!goneUri.isEmpty()) + { + state = SendingGone; + prepareOutReq(goneUri); + outReq->start("POST", goneUri, HttpHeaders()); + outReq->endBody(); + return; + } + + finished(); + } + + void finished() + { + ZhttpRequest::Rid rid = req->rid(); + QByteArray cid = rid.first + ':' + rid.second; + log_debug("httpsession: cleaning up %s", cid.data()); cleanup(); @@ -1361,6 +1386,25 @@ class HttpSession::Private : public QObject } } } + else if(state == SendingGone) + { + // response should be empty + if(outReq->bytesAvailable() > 0) + { + outReq_error(); + return; + } + + if(outReq->isFinished()) + { + logRequest(outReq->requestMethod(), outReq->requestUri(), outReq->requestHeaders(), outReq->responseCode(), 0); + + cleanupOutReq(); + + finished(); + return; + } + } else { // unexpected state @@ -1558,6 +1602,11 @@ private slots: doError(); } } + else if(state == SendingGone) + { + log_debug("httpsession: failed to request gone link"); + finished(); + } else { // unexpected state diff --git a/src/handler/instruct.cpp b/src/handler/instruct.cpp index adeee4ba..5b2c5c0d 100644 --- a/src/handler/instruct.cpp +++ b/src/handler/instruct.cpp @@ -287,6 +287,7 @@ Instruct Instruct::fromResponse(const HttpResponseData &response, bool *ok, QStr QUrl nextLink; int nextLinkTimeout = -1; + QUrl goneLink; foreach(const HttpHeaderParameters ¶ms, response.headers.getAllAsParameters("Grip-Link")) { if(params.count() < 2) @@ -332,6 +333,10 @@ Instruct Instruct::fromResponse(const HttpResponseData &response, bool *ok, QStr nextLinkTimeout = DEFAULT_NEXTLINK_TIMEOUT; } } + else if(rel == "gone") + { + goneLink = link; + } } newResponse.headers.clear(); @@ -806,6 +811,7 @@ Instruct Instruct::fromResponse(const HttpResponseData &response, bool *ok, QStr i.response = newResponse; i.nextLink = nextLink; i.nextLinkTimeout = nextLinkTimeout; + i.goneLink = goneLink; if(ok) *ok = true; diff --git a/src/handler/instruct.h b/src/handler/instruct.h index 71bac159..b6b5730a 100644 --- a/src/handler/instruct.h +++ b/src/handler/instruct.h @@ -67,6 +67,7 @@ class Instruct HttpResponseData response; QUrl nextLink; int nextLinkTimeout; + QUrl goneLink; Instruct() : holdMode(NoHold), diff --git a/src/proxy/proxyutil.cpp b/src/proxy/proxyutil.cpp index 9191e7d3..ec39ee2a 100644 --- a/src/proxy/proxyutil.cpp +++ b/src/proxy/proxyutil.cpp @@ -177,7 +177,7 @@ void manipulateRequestHeaders(const char *logprefix, void *object, HttpRequestDa requestData->headers.removeAll("Grip-Feature"); requestData->headers += HttpHeader("Grip-Feature", - "status, session, link:next, filter:skip-self, filter:skip-users, filter:require-sub, filter:build-id, filter:var-subst"); + "status, session, link:next, link:gone, filter:skip-self, filter:skip-users, filter:require-sub, filter:build-id, filter:var-subst"); if(!idata.sid.isEmpty()) {