]> git.proxmox.com Git - ceph.git/blobdiff - ceph/src/rgw/rgw_asio_frontend.cc
import ceph quincy 17.2.6
[ceph.git] / ceph / src / rgw / rgw_asio_frontend.cc
index d6001a67f16ca26aa12dc34c770d1854297b8997..dac47d36a7bfe6c5b7289a66c178293d5813df7a 100644 (file)
@@ -72,6 +72,7 @@ class StreamIO : public rgw::asio::ClientIO {
   timeout_timer& timeout;
   yield_context yield;
   parse_buffer& buffer;
+  boost::system::error_code fatal_ec;
  public:
   StreamIO(CephContext *cct, Stream& stream, timeout_timer& timeout,
            rgw::asio::parser_type& parser, yield_context yield,
@@ -83,6 +84,8 @@ class StreamIO : public rgw::asio::ClientIO {
         buffer(buffer)
   {}
 
+  boost::system::error_code get_fatal_error_code() const { return fatal_ec; }
+
   size_t write_data(const char* buf, size_t len) override {
     boost::system::error_code ec;
     timeout.start();
@@ -95,6 +98,9 @@ class StreamIO : public rgw::asio::ClientIO {
         boost::system::error_code ec_ignored;
         stream.lowest_layer().shutdown(tcp_socket::shutdown_both, ec_ignored);
       }
+      if (!fatal_ec) {
+        fatal_ec = ec;
+      }
       throw rgw::io::Exception(ec.value(), std::system_category());
     }
     return bytes;
@@ -116,6 +122,9 @@ class StreamIO : public rgw::asio::ClientIO {
       }
       if (ec) {
         ldout(cct, 4) << "failed to read body: " << ec.message() << dendl;
+        if (!fatal_ec) {
+          fatal_ec = ec;
+        }
         throw rgw::io::Exception(ec.value(), std::system_category());
       }
     }
@@ -228,6 +237,8 @@ void handle_connection(boost::asio::io_context& context,
       return;
     }
 
+    bool expect_continue = (message[http::field::expect] == "100-continue");
+
     {
       auto lock = pause_mutex.async_lock_shared(yield[ec]);
       if (ec == boost::asio::error::operation_aborted) {
@@ -283,6 +294,17 @@ void handle_connection(boost::asio::io_context& context,
             << log_header{message, http::field::range} << " latency="
             << latency << dendl;
       }
+
+      // process_request() can't distinguish between connection errors and
+      // http/s3 errors, so check StreamIO for fatal connection errors
+      ec = real_client.get_fatal_error_code();
+      if (ec) {
+        return;
+      }
+
+      if (real_client.sent_100_continue()) {
+        expect_continue = false;
+      }
     }
 
     if (!parser.keep_alive()) {
@@ -291,7 +313,7 @@ void handle_connection(boost::asio::io_context& context,
 
     // if we failed before reading the entire message, discard any remaining
     // bytes before reading the next
-    while (!parser.is_done()) {
+    while (!expect_continue && !parser.is_done()) {
       static std::array<char, 1024> discard_buffer;
 
       auto& body = parser.get().body();
@@ -330,6 +352,8 @@ struct Connection : boost::intrusive::list_base_hook<>,
   void close(boost::system::error_code& ec) {
     socket.close(ec);
   }
+
+  tcp_socket& get_socket() { return socket; }
 };
 
 class ConnectionList {