1 /* 2 * Copyright (c) Facebook, Inc. and its affiliates. 3 * All rights reserved. 4 * 5 * This source code is licensed under the BSD-style license found in the 6 * LICENSE file in the root directory of this source tree. 7 */ 8 9 #pragma once 10 11 #include <folly/Memory.h> 12 #include <folly/io/async/DestructorCheck.h> 13 #include <proxygen/lib/http/session/HTTPTransaction.h> 14 15 namespace proxygen { 16 17 static const std::string kMessageFilterDefaultName_ = "Unknown"; 18 19 class HTTPMessageFilter 20 : public HTTPTransaction::Handler 21 , public folly::DestructorCheck { 22 public: setNextTransactionHandler(HTTPTransaction::Handler * next)23 void setNextTransactionHandler(HTTPTransaction::Handler* next) { 24 nextTransactionHandler_ = CHECK_NOTNULL(next); 25 } setPrevFilter(HTTPMessageFilter * prev)26 virtual void setPrevFilter(HTTPMessageFilter* prev) noexcept { 27 prev_ = CHECK_NOTNULL(prev); 28 } setPrevTxn(HTTPTransaction * prev)29 virtual void setPrevTxn(HTTPTransaction* prev) noexcept { 30 prev_ = CHECK_NOTNULL(prev); 31 } getNextTransactionHandler()32 HTTPTransaction::Handler* getNextTransactionHandler() { 33 return nextTransactionHandler_; 34 } 35 36 virtual std::unique_ptr<HTTPMessageFilter> clone() noexcept = 0; 37 38 // This function is used to validate whether a request could be DSRed. 39 // The function is called pre-delegation. For body mutating filters, 40 // allowDSR should return false. Other examples, beside body mutating, 41 // is a filter which rate limit the response delivery 42 // Note that allowDSR is a pure virtual to make the filter author 43 // aware of it 44 virtual bool allowDSR() const noexcept = 0; 45 46 // These HTTPTransaction::Handler callbacks may be overwritten 47 // The default behavior is to pass the call through. onHeadersComplete(std::unique_ptr<HTTPMessage> msg)48 void onHeadersComplete(std::unique_ptr<HTTPMessage> msg) noexcept override { 49 nextTransactionHandler_->onHeadersComplete(std::move(msg)); 50 } onBody(std::unique_ptr<folly::IOBuf> chain)51 void onBody(std::unique_ptr<folly::IOBuf> chain) noexcept override { 52 nextTransactionHandler_->onBody(std::move(chain)); 53 } onChunkHeader(size_t length)54 void onChunkHeader(size_t length) noexcept override { 55 nextTransactionHandler_->onChunkHeader(length); 56 } onChunkComplete()57 void onChunkComplete() noexcept override { 58 nextTransactionHandler_->onChunkComplete(); 59 } onTrailers(std::unique_ptr<HTTPHeaders> trailers)60 void onTrailers(std::unique_ptr<HTTPHeaders> trailers) noexcept override { 61 nextTransactionHandler_->onTrailers(std::move(trailers)); 62 } onEOM()63 void onEOM() noexcept override { 64 nextTransactionHandler_->onEOM(); 65 } onUpgrade(UpgradeProtocol protocol)66 void onUpgrade(UpgradeProtocol protocol) noexcept override { 67 nextTransactionHandler_->onUpgrade(protocol); 68 } onError(const HTTPException & error)69 void onError(const HTTPException& error) noexcept override { 70 nextTransactionHandler_->onError(error); 71 } 72 73 // These HTTPTransaction::Handler callbacks cannot be overrwritten setTransaction(HTTPTransaction * txn)74 void setTransaction(HTTPTransaction* txn) noexcept final { 75 nextTransactionHandler_->setTransaction(txn); 76 } detachTransaction()77 void detachTransaction() noexcept final { 78 if (prev_.which() == 1) { 79 // After detachTransaction(), the HTTPTransaction will destruct itself. 80 // Set it to nullptr to avoid holding a stale pointer. 81 prev_ = static_cast<HTTPTransaction*>(nullptr); 82 } 83 if (nextTransactionHandler_) { 84 nextTransactionHandler_->detachTransaction(); 85 } 86 } onEgressPaused()87 void onEgressPaused() noexcept final { 88 nextTransactionHandler_->onEgressPaused(); 89 } onEgressResumed()90 void onEgressResumed() noexcept final { 91 nextTransactionHandler_->onEgressResumed(); 92 } onPushedTransaction(HTTPTransaction * txn)93 void onPushedTransaction(HTTPTransaction* txn) noexcept final { 94 nextTransactionHandler_->onPushedTransaction(txn); 95 } onExTransaction(HTTPTransaction * txn)96 void onExTransaction(HTTPTransaction* txn) noexcept final { 97 nextTransactionHandler_->onExTransaction(txn); 98 } 99 getFilterName()100 virtual const std::string& getFilterName() const noexcept { 101 return kMessageFilterDefaultName_; 102 } 103 104 virtual void pause() noexcept; 105 106 virtual void resume(uint64_t offset) noexcept; 107 108 // This is called by the handler when it wants to detach from the transaction. 109 // After this call, the handler and the transaction can be destroyed without 110 // notifying each other. We pass the call through the filter chain to 111 // avoid holding a stale pointer to the transaction. detachHandlerFromTransaction()112 void detachHandlerFromTransaction() noexcept { 113 if (prev_.which() == 0) { 114 auto prev = boost::get<HTTPMessageFilter*>(prev_); 115 if (prev) { 116 // prev points to another filter, popagate the call. 117 prev->detachHandlerFromTransaction(); 118 } 119 } else { 120 auto prev = boost::get<HTTPTransaction*>(prev_); 121 if (prev) { 122 // prev points to the transaction, detach the handler from the 123 // transaction. 124 prev->setHandler(nullptr); 125 // Set the pointer to nullptr. It is not safe to use the pointer since 126 // after this the transaction can be destroyed without notifying the 127 // filter. 128 prev_ = static_cast<HTTPTransaction*>(nullptr); 129 } 130 } 131 } 132 133 protected: nextOnHeadersComplete(std::unique_ptr<HTTPMessage> msg)134 virtual void nextOnHeadersComplete(std::unique_ptr<HTTPMessage> msg) { 135 nextTransactionHandler_->onHeadersComplete(std::move(msg)); 136 } nextOnBody(std::unique_ptr<folly::IOBuf> chain)137 virtual void nextOnBody(std::unique_ptr<folly::IOBuf> chain) { 138 nextTransactionHandler_->onBody(std::move(chain)); 139 } nextOnChunkHeader(size_t length)140 virtual void nextOnChunkHeader(size_t length) { 141 nextTransactionHandler_->onChunkHeader(length); 142 } nextOnChunkComplete()143 virtual void nextOnChunkComplete() { 144 nextTransactionHandler_->onChunkComplete(); 145 } nextOnTrailers(std::unique_ptr<HTTPHeaders> trailers)146 virtual void nextOnTrailers(std::unique_ptr<HTTPHeaders> trailers) { 147 nextTransactionHandler_->onTrailers(std::move(trailers)); 148 } nextOnEOM()149 virtual void nextOnEOM() { 150 nextTransactionHandler_->onEOM(); 151 } nextOnError(const HTTPException & ex)152 virtual void nextOnError(const HTTPException& ex) { 153 nextTransactionHandler_->onError(ex); 154 } 155 HTTPTransaction::Handler* nextTransactionHandler_{nullptr}; 156 157 boost::variant<HTTPMessageFilter*, HTTPTransaction*> prev_ = 158 static_cast<HTTPTransaction*>(nullptr); 159 160 bool nextElementIsPaused_{false}; 161 }; 162 163 } // namespace proxygen 164