virtual int send_status(const char *status, const char *status_name) = 0;
virtual int send_100_continue() = 0;
virtual int complete_header() = 0;
+ virtual int complete_request() = 0;
+ virtual int send_content_length(uint64_t len) = 0;
RGWEnv& get_env() { return env; }
val = "";
env_map[name] = val;
- dout(0) << "RGWEnv::set(): " << name << ": " << val << dendl;
+ dout(20) << "RGWEnv::set(): " << name << ": " << val << dendl;
}
void RGWEnv::init(CephContext *cct, char **envp)
return r;
}
+int RGWFCGX::send_content_length(uint64_t len)
+{
+ char buf[21];
+ snprintf(buf, sizeof(buf), "%"PRIu64, len);
+ return print("Content-Length: %s\n", buf);
+}
+
int RGWFCGX::complete_header()
{
return print("\r\n");
int send_status(const char *status, const char *status_name);
int send_100_continue();
int complete_header();
+ int complete_request() { return 0; }
+ int send_content_length(uint64_t len);
public:
RGWFCGX(FCGX_Request *_fcgx) : fcgx(_fcgx) {}
void flush();
op->execute();
op->complete();
done:
+ ret = client_io.complete_request();
+ if (ret < 0) {
+ dout(0) << "ERROR: client_io.complete_request() returned " << ret << dendl;
+ }
if (should_log) {
rgw_log_op(store, s, (op ? op->name() : "unknown"), olog);
}
}
struct mg_context *ctx;
- const char *options[] = {"listening_ports", "8080", NULL};
+ const char *options[] = {"listening_ports", "8080", "enable_keep_alive", "yes", NULL};
RGWProcessEnv pe = { store, &rest, olog };
int RGWMongoose::write_data(const char *buf, int len)
{
- if (!sent_header) {
+ if (!header_done) {
header_data.append(buf, len);
return 0;
}
- dout(0) << buf << dendl;
+ if (!sent_header) {
+ data.append(buf, len);
+ return 0;
+ }
return mg_write(event->conn, buf, len);
}
-RGWMongoose::RGWMongoose(mg_event *_event) : event(_event), sent_header(false) {
+RGWMongoose::RGWMongoose(mg_event *_event) : event(_event), header_done(false), sent_header(false), has_content_length(false) {
}
int RGWMongoose::read_data(char *buf, int len)
{
}
+int RGWMongoose::complete_request()
+{
+ if (!sent_header) {
+ if (!has_content_length) {
+ header_done = false; /* let's go back to writing the header */
+ int r = send_content_length(data.length());
+ if (r < 0)
+ return r;
+ }
+
+ complete_header();
+ }
+
+ if (data.length()) {
+ int r = write_data(data.c_str(), data.length());
+ if (r < 0)
+ return r;
+ data.clear();
+ }
+
+ return 0;
+}
+
void RGWMongoose::init_env(CephContext *cct)
{
env.init(cct);
int RGWMongoose::complete_header()
{
+ header_done = true;
+
+ if (!has_content_length) {
+ return 0;
+ }
+
header_data.append("\r\n");
sent_header = true;
return write_data(header_data.c_str(), header_data.length());
}
+
+int RGWMongoose::send_content_length(uint64_t len)
+{
+ has_content_length = true;
+ char buf[21];
+ snprintf(buf, sizeof(buf), "%"PRIu64, len);
+ return print("Content-Length: %s\n", buf);
+}
mg_event *event;
bufferlist header_data;
+ bufferlist data;
+ bool header_done;
bool sent_header;
+ bool has_content_length;
-protected:
+public:
void init_env(CephContext *cct);
int write_data(const char *buf, int len);
int send_status(const char *status, const char *status_name);
int send_100_continue();
int complete_header();
+ int complete_request();
+ int send_content_length(uint64_t len);
-public:
RGWMongoose(mg_event *_event);
void flush();
};
virtual int verify_op_mask();
virtual void execute() = 0;
virtual void send_response() {}
- virtual void complete() { send_response(); }
+ virtual void complete() {
+ send_response();
+ }
virtual const string name() = 0;
virtual uint32_t op_mask() { return 0; }
void dump_content_length(struct req_state *s, uint64_t len)
{
- char buf[21];
- snprintf(buf, sizeof(buf), "%"PRIu64, len);
- int r = s->cio->print("Content-Length: %s\n", buf);
+ int r = s->cio->send_content_length(len);
if (r < 0) {
ldout(s->cct, 0) << "ERROR: s->cio->print() returned err=" << r << dendl;
}
s->err.message = err_msg;
set_req_state_err(s, ret);
dump_errno(s);
- dump_content_length(s, s->formatter->get_len());
+ if (ret >= 0) {
+ dump_content_length(s, s->formatter->get_len());
+ }
end_header(s, this);
if (ret != STATUS_CREATED)
return;