Google APIs Client Library for C++
|
00001 /* 00002 * \copyright Copyright 2013 Google Inc. All Rights Reserved. 00003 * \license @{ 00004 * 00005 * Licensed under the Apache License, Version 2.0 (the "License"); 00006 * you may not use this file except in compliance with the License. 00007 * You may obtain a copy of the License at 00008 * 00009 * http://www.apache.org/licenses/LICENSE-2.0 00010 * 00011 * Unless required by applicable law or agreed to in writing, software 00012 * distributed under the License is distributed on an "AS IS" BASIS, 00013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00014 * See the License for the specific language governing permissions and 00015 * limitations under the License. 00016 * 00017 * @} 00018 */ 00019 00020 #ifndef APISERVING_CLIENTS_CPP_TRANSPORT_HTTP_SCRIBE_H_ 00021 #define APISERVING_CLIENTS_CPP_TRANSPORT_HTTP_SCRIBE_H_ 00022 00023 #include <map> 00024 using std::map; 00025 #include <queue> 00026 using std::queue; 00027 #include <set> 00028 using std::multiset; 00029 using std::set; 00030 #include <string> 00031 using std::string; 00032 #include "googleapis/base/integral_types.h" 00033 #include "googleapis/base/macros.h" 00034 #include "googleapis/base/mutex.h" 00035 #include "googleapis/base/scoped_ptr.h" 00036 #include "googleapis/base/thread_annotations.h" 00037 #include "googleapis/strings/stringpiece.h" 00038 #include "googleapis/util/status.h" 00039 namespace googleapis { 00040 00041 namespace client { 00042 class HttpRequest; 00043 class ParsedUrl; 00044 00045 /* 00046 * Determines what is appropriate for scribes to record. 00047 * @ingroup TransportLayerCore 00048 * 00049 * The base class performs standard censoring 00050 * - Authorization headers are scrubbed 00051 */ 00052 class HttpScribeCensor { 00053 public: 00054 /* 00055 * Standard constructor. 00056 */ 00057 HttpScribeCensor(); 00058 00059 /* 00060 * Standard destructor. 00061 */ 00062 virtual ~HttpScribeCensor(); 00063 00064 /* 00065 * Returns a scribbed url for the request. 00066 */ 00067 virtual string GetCensoredUrl( 00068 const HttpRequest& request, bool* censored) const; 00069 00070 /* 00071 * Returns a scrubbed request payload. 00072 * 00073 * The method should reset request->content_reader after reading 00074 * the contents. 00075 * 00076 * @param[in] request The request to censor. 00077 * @param[in] max_len The maximum length of body to keep. 00078 * @param[out] original_size The original uncensored size. 00079 * @param[out] censored Set to true if the result was censored. 00080 * 00081 * @return The censored request payload. 00082 */ 00083 // TODO(ewiseblatt): 20130520 00084 // Really this should return a DataReader of either the original 00085 // reader or censored content but ownership cases are tricky and is 00086 // more vulnerable to rewind bugs so am leaving this as a string for now. 00087 virtual string GetCensoredRequestContent( 00088 const HttpRequest& request, 00089 int64 max_len, 00090 int64* original_size, 00091 bool* censored) const; 00092 00093 /* 00094 * Returns a scrubbed responze payload. 00095 * 00096 * The method should reset response->body_reader after reading the contents. 00097 * 00098 * @param[in] request The request with the response to censor. 00099 * @param[in] max_len The maximum length of body to keep. 00100 * @param[out] original_size The original uncensored size. 00101 * @param[out] censored Set to true if the result was censored. 00102 * 00103 * @return The censored response payload. 00104 */ 00105 // TODO(ewiseblatt): 20130520 00106 // Really this should return a DataReader of either the original 00107 // reader or censored content but ownership cases are tricky and is 00108 // more vulnerable to rewind bugs so am leaving this as a string for now. 00109 virtual string GetCensoredResponseBody( 00110 const HttpRequest& request, int64 max_len, 00111 int64* original_size, bool* censored) const; 00112 00113 /* 00114 * Returns a censored request header value. 00115 * 00116 * @param[in] request The request with the header. 00117 * @param[in] name The request header name. 00118 * @param[in] value The original value. 00119 * @param[out] censored True if the value was censored. 00120 * 00121 * @return The censored header value. 00122 */ 00123 virtual string GetCensoredRequestHeaderValue( 00124 const HttpRequest& request, 00125 const StringPiece& name, const StringPiece& value, 00126 bool* censored) const; 00127 00128 /* 00129 * Returns a censored response header value. 00130 * 00131 * @param[in] request The request with response having the header. 00132 * @param[in] name The response header name. 00133 * @param[in] value The original value. 00134 * @param[out] censored True if the value was censored. 00135 * 00136 * @return The censored header value. 00137 */ 00138 virtual string GetCensoredResponseHeaderValue( 00139 const HttpRequest& request, 00140 const StringPiece& name, const StringPiece& value, 00141 bool* censored) const; 00142 00143 /* 00144 * Returns the set of censored URL prefixes. 00145 * 00146 * These include the protocol (e.g. https://accounts.google.com) 00147 */ 00148 const set<string>& censored_url_prefixes() const { 00149 return censored_url_prefixes_; 00150 } 00151 00152 /* 00153 * Returns a mutable set of censored URL prefixes. 00154 * 00155 * These include the protocol (e.g. https://accounts.google.com). 00156 * You can add additional prefixes into the set. 00157 */ 00158 set<string>* mutable_censored_url_prefixes() { 00159 return &censored_url_prefixes_; 00160 } 00161 00162 /* 00163 * Returns a set of censored query parameter names. 00164 */ 00165 const set<string>& censored_query_param_names() const { 00166 return censored_query_param_names_; 00167 } 00168 00169 /* 00170 * Returns a mutable set of censored URL query parameters. 00171 * 00172 * You can add additional query parameter names into the set. 00173 */ 00174 set<string>* mutable_censored_query_param_names() { 00175 return &censored_query_param_names_; 00176 } 00177 00178 /* 00179 * Returns a set of censored HTTP request header names. 00180 */ 00181 const set<string>& censored_request_header_names() const { 00182 return censored_request_header_names_; 00183 } 00184 00185 /* 00186 * Returns a mutable set of censored HTTP request header names. 00187 * 00188 * You can add additional request header names into the set. 00189 */ 00190 set<string>* mutable_censored_request_header_names() { 00191 return &censored_request_header_names_; 00192 } 00193 00194 /* 00195 * Returns a set of censored HTTP response header names. 00196 */ 00197 const set<string>& censored_response_header_names() const { 00198 return censored_response_header_names_; 00199 } 00200 00201 /* 00202 * Returns a mutable set of censored HTTP reponse header names. 00203 * 00204 * You can add additional response header names into the set. 00205 */ 00206 set<string>* mutable_censored_response_header_names() { 00207 return &censored_response_header_names_; 00208 } 00209 00210 protected: 00211 /* 00212 * Censor the query part of a URL. 00213 * 00214 * @param[in] parsed_url The parsed url to extract from. 00215 * @param[out] censored Set to true if some values were censored. 00216 * @return censored query string. 00217 */ 00218 string GetCensoredUrlQuery( 00219 const ParsedUrl& parsed_url, bool* censored) const; 00220 00221 private: 00222 set<string> censored_url_prefixes_; 00223 set<string> censored_query_param_names_; 00224 set<string> censored_request_header_names_; 00225 set<string> censored_response_header_names_; 00226 00227 bool IsSensitiveContent(const string& url) const; 00228 DISALLOW_COPY_AND_ASSIGN(HttpScribeCensor); 00229 }; 00230 00231 /* 00232 * Base class for scribe to log HTTP message activity. 00233 * @ingroup TransportLayerCore 00234 * 00235 * This is intended for debugging and diagnostics. A transport permits 00236 * binding a scribe to it to monitor transport activity. This class 00237 * provides the interface for the interaction between the HTTP requests 00238 * and scribes. 00239 * 00240 * Scribes should be thread-safe. 00241 * 00242 * @see HttpTransport::set_scribe 00243 */ 00244 class HttpScribe { 00245 public: 00246 /* 00247 * Standard destructor. 00248 */ 00249 virtual ~HttpScribe(); 00250 00251 /* 00252 * Specifies the max size for captured content snippets. 00253 * 00254 * The default is unbounded so the whole message will be kept. 00255 * If you only need part of the payload then you can use this attribute 00256 * to restrict the size. 00257 * 00258 * @param[in] n most bytes to capture. 00259 */ 00260 void set_max_snippet(int64 n) { max_snippet_ = n; } 00261 00262 /* 00263 * Returns the max size for captured snippets. 00264 * 00265 * @return bytes to capture. 00266 */ 00267 int64 max_snippet() const { return max_snippet_; } 00268 00269 /* 00270 * Notification that the request is about to be sent to the transport. 00271 * 00272 * Since the scribe is used in the flow of normal sending activities, 00273 * it will be the caller's responsibility to reset the requset->body_reader. 00274 * after invoking this method. 00275 * 00276 * @param[in] request The request being sent. 00277 */ 00278 virtual void AboutToSendRequest(const HttpRequest* request) = 0; 00279 00280 /* 00281 * Notification that a request has received a response. 00282 * 00283 * Since the scribe is used in the flow of normal sending activities, 00284 * it will be the caller's responsibility to reset the 00285 * request->response->body_reader after invoking this method. 00286 * 00287 * @param[in] request The request holds its response. 00288 */ 00289 virtual void ReceivedResponseForRequest(const HttpRequest* request) = 0; 00290 00291 /* 00292 * Notification that a sent request has encountered a transport error. 00293 * 00294 * Transport errors are not HTTP errors. This is a timeout or network-level 00295 * error. 00296 * 00297 * @param[in] request The request that will never receive a response. 00298 * @param[in] error The transport error. 00299 */ 00300 virtual void RequestFailedWithTransportError( 00301 const HttpRequest* request, const util::Status& error) = 0; 00302 00303 void reset_censor(HttpScribeCensor* censor) { 00304 censor_.reset(censor); 00305 } 00306 00307 const HttpScribeCensor* censor() { return censor_.get(); } 00308 00309 /* 00310 * Checkpoint the scribe data into the writer if it 00311 * hasnt been done so already. 00312 */ 00313 virtual void Checkpoint() = 0; 00314 00315 protected: 00316 /* 00317 * Class is abstract so needs to be specialized to construct. 00318 * 00319 * @param[in] censor Provides policy for censoring data. Ownership is passed. 00320 */ 00321 explicit HttpScribe(HttpScribeCensor* censor); 00322 00323 private: 00324 scoped_ptr<HttpScribeCensor> censor_; 00325 int64 max_snippet_; 00326 DISALLOW_COPY_AND_ASSIGN(HttpScribe); 00327 }; 00328 00329 /* 00330 * A high level but still abstract class for intercepting HTTP requests. 00331 * @ingroup TransportLayerCore 00332 * 00333 * This class manages a collection of active HttpEntryScribe::Entry 00334 * instances with activity associated with them. This might be a more useful 00335 * starting point for viewing a collection of independent encapsulated 00336 * messages as opposed to a stream of interleaved events. 00337 */ 00338 class HttpEntryScribe : public HttpScribe { 00339 public: 00340 class Entry { 00341 public: 00342 /* 00343 * Standard constructor. 00344 * 00345 * @param[in] scribe The scribe constructing the entry. 00346 * @param[in] request The request that the entry is for. 00347 * 00348 * Caller should call either CancelAndDestroy or FlushAndDestroy when done. 00349 */ 00350 Entry(HttpEntryScribe* scribe, const HttpRequest* request); 00351 00352 /* 00353 * Finish recording the entry instance and destroy it. 00354 * 00355 * The entry has finished so should finish recording. Ownershp is passed 00356 * so that it can be destroyed. The entry is no longer in the scribe's 00357 * map or queue. 00358 * 00359 * This is called from the scribe within a critical section so does 00360 * not have to worry about threads. 00361 */ 00362 virtual void FlushAndDestroy() = 0; 00363 00364 /* 00365 * Destroys instance without flushing it so may forget about it. 00366 * 00367 * Intended to destory an instance without recording it. 00368 */ 00369 virtual void CancelAndDestroy(); 00370 00371 /* 00372 * Hook for recording that the request was sent. 00373 * 00374 * @param[in] request The request is about to be executed. 00375 */ 00376 virtual void Sent(const HttpRequest* request) = 0; 00377 00378 /* 00379 * Hook for recording that the request received a response. 00380 * 00381 * @param[in] request The request has a response. The response 00382 * might be an HTTP failure. 00383 */ 00384 virtual void Received(const HttpRequest* request) = 0; 00385 00386 /* 00387 * Hook for recording that the request encountered a transport error. 00388 * 00389 * @param[in] request The request encountered a transport error so will 00390 * never receive a response. It might have been previously sent 00391 * but might not have. 00392 * @param[in] status Explains te error. 00393 */ 00394 virtual void Failed( 00395 const HttpRequest* request, const util::Status& status) = 0; 00396 00397 /* 00398 * Returns the age of this intance. 00399 * 00400 * @return microseconds since constructed. 00401 */ 00402 int64 MicrosElapsed() const; 00403 00404 /* 00405 * Returns bound scribe. 00406 * 00407 * @return scribe bound in constructor. 00408 */ 00409 HttpEntryScribe* scribe() const { return scribe_; } 00410 00411 /* 00412 * Returns bound request. 00413 * 00414 * @return request bound in constructor. 00415 */ 00416 const HttpRequest* request() const { return request_; } 00417 00418 /* 00419 * Returns time instance was constructed. 00420 */ 00421 const struct timeval& timeval() const { return timeval_; } 00422 00423 /* 00424 * Returns true if the request has completed. 00425 * If this is true then the request might have been destroyed already. 00426 * 00427 * The request will always be valid in the Sent, Received, and Failed 00428 * methods. 00429 * 00430 * @return true If the request is known to have finished. 00431 */ 00432 bool done() const { return done_; } 00433 00434 /* 00435 * Informs the entry that the reqeust has finished. 00436 * 00437 * This method is called internally so you do not need to call this.. 00438 */ 00439 void set_done(bool is_done) { done_ = is_done; } 00440 00441 protected: 00442 /* 00443 * Do not explicitly call this destructor. 00444 * 00445 * @see FlushAndDestroy 00446 * @see CancelAndDestroy 00447 */ 00448 virtual ~Entry(); // Called by FlushAndDestroy or CancelAndDestroy 00449 00450 private: 00451 HttpEntryScribe* scribe_; 00452 const HttpRequest* request_; 00453 struct timeval timeval_; 00454 bool done_; 00455 00456 DISALLOW_COPY_AND_ASSIGN(Entry); 00457 }; 00458 00459 /* 00460 * Implements the HttpScribe::AboutToSendRequest method. 00461 * 00462 * This maps the request to an entry and calls the Entry::Sent method. 00463 * 00464 * @param[in] request The request that was sent. 00465 */ 00466 virtual void AboutToSendRequest(const HttpRequest* request); 00467 00468 /* 00469 * Implements the HttpScribe::ReceivedResponseForRequest method. 00470 * 00471 * This maps the request to an entry and calls the 00472 * Entry::Received method. 00473 * 00474 * @param[in] request The request whose response was received. 00475 */ 00476 virtual void ReceivedResponseForRequest(const HttpRequest* request); 00477 00478 /* 00479 * Implements the HttpScribe::RequestFailedWithTransportError method. 00480 * 00481 * This maps the request to an entry and calls the 00482 * Entry::Failed method. 00483 * 00484 * @param[in] request The request that had a transport failure. 00485 * @param[in] error An explanation of the failure. 00486 */ 00487 virtual void RequestFailedWithTransportError( 00488 const HttpRequest* request, const util::Status& error); 00489 00490 protected: 00491 /* 00492 * Standard constructor. 00493 * 00494 * @param[in] censor Ownership to the censorship policy is passed. 00495 */ 00496 explicit HttpEntryScribe(HttpScribeCensor* censor); 00497 00498 /* 00499 * Standard destructor. 00500 */ 00501 virtual ~HttpEntryScribe(); 00502 00503 /* 00504 * Maps the request into a logical entry. 00505 * 00506 * @param[in] request The intercepted request. 00507 * @return the scribe maintains ownership for the entry consolidating 00508 * activity for the request 00509 * 00510 * @see NewEntry 00511 * @see DiscardEntry 00512 */ 00513 Entry* GetEntry(const HttpRequest* request) LOCKS_EXCLUDED(mutex_); 00514 00515 /* 00516 * Unmaps and destroys the logical entry. 00517 * 00518 * This can be called to forget about the entry, but is normally handled 00519 * automatically by this scribe instance. 00520 * 00521 * @param[in,out] entry The entry will be destroyed. 00522 */ 00523 void DiscardEntry(Entry* entry) LOCKS_EXCLUDED(mutex_); 00524 00525 /* 00526 * Discard all the entries in the queue. 00527 * 00528 * Discarding the entries notifies the entry that it is done so it can 00529 * flush and remove itself. This method is here so that derived 00530 * destructors can call it if they need to finish the entry before 00531 * they destruct. 00532 * 00533 * The base class will call this to discard anything remaining in its 00534 * destructor. 00535 */ 00536 void DiscardQueue(); 00537 00538 /* 00539 * Create a new entry instance for the request. 00540 * 00541 * This is called from within a critical section so does not have to 00542 * worry about threads. 00543 * 00544 * This lets specialized scribes return specialized entries that 00545 * drive the particular specialized behavior. It is called by 00546 * GetEntry. 00547 * 00548 * @return ownership of the entry. 00549 */ 00550 virtual Entry* NewEntry(const HttpRequest* request) 00551 EXCLUSIVE_LOCKS_REQUIRED(mutex_) 00552 = 0; 00553 00554 /* 00555 * Returns the entries that have not yet been unmapped. 00556 * 00557 * These are in the order they were created, which is probably 00558 * the order in which they were sent (minus race conditions). 00559 */ 00560 queue<Entry*>* outstanding_queue() { return &queue_; } 00561 00562 private: 00563 typedef map<const HttpRequest*, Entry*> EntryMap; 00564 typedef queue<Entry*> EntryQueue; 00565 00566 void UnsafeDiscardEntry(Entry* entry) EXCLUSIVE_LOCKS_REQUIRED(mutex_); 00567 00568 Mutex mutex_; 00569 int64 sequence_number_ GUARDED_BY(mutex_); 00570 EntryMap map_ GUARDED_BY(mutex_); 00571 EntryQueue queue_ GUARDED_BY(mutex_); 00572 00573 DISALLOW_COPY_AND_ASSIGN(HttpEntryScribe); 00574 }; 00575 00576 } // namespace client 00577 00578 } // namespace googleapis 00579 #endif // APISERVING_CLIENTS_CPP_TRANSPORT_HTTP_SCRIBE_H_