diff --git a/include/co/http.h b/include/co/http.h index 2a5a49a5a..e649c04ba 100644 --- a/include/co/http.h +++ b/include/co/http.h @@ -273,10 +273,17 @@ class __coapi Res { /** * set body of the response * - The body length will be zero if no body was set. + * @return success or not (If use 'send_body') */ - void set_body(const void* s, size_t n); - void set_body(const char* s) { this->set_body(s, strlen(s)); } - void set_body(const fastring& s) { this->set_body(s.data(), s.size()); } + bool set_body(const void* s, size_t n); + bool set_body(const char* s) { return this->set_body(s, strlen(s)); } + bool set_body(const fastring& s) { return this->set_body(s.data(), s.size()); } + + /** + * complete header generate and send http-body data + * @return 0: no error; -1: not support ; -2: IO error + */ + int send_body(const void* data, size_t n); private: http_res_t* _p; diff --git a/src/so/http.cc b/src/so/http.cc index 62bc5d328..ebf642612 100644 --- a/src/so/http.cc +++ b/src/so/http.cc @@ -471,7 +471,8 @@ const char* http_req_t::header(const char* key) const { } -void http_res_t::set_body(const void* s, size_t n) { +bool http_res_t::set_body(const void* s, size_t n) { + if(header_send>0) return false; body_size = n; if (status == 0) status = 200; buf->clear(); @@ -479,6 +480,25 @@ void http_res_t::set_body(const void* s, size_t n) { << "Content-Length: " << n << "\r\n" << header << "\r\n"; buf->append(s, n); + header_send=-1; // cannot call 'send_body' anymore + return true; +} + +int http_res_t::send_body(const void* data, size_t n) { + assert(pc_); + if(header_send<0) { + //use 'set_body', cannot use long-connection mode + return -1; + } + if(header_send==0) { //headers has not send yet + if (status == 0) status = 200; + (*buf) << version_str(version) << ' ' << status << ' ' << status_str(status) << "\r\n" + << header << "\r\n"; + if(pc_->send(buf->data(),buf->size(),FLG_http_send_timeout)<0) s_err=-1; + header_send=1; + } + if(pc_->send(data,n,FLG_http_send_timeout)<0) s_err=-1; + return s_err==0? 0 : -2; } const char* Req::header(const char* key) const { @@ -506,10 +526,15 @@ void Res::add_header(const char* k, int v) { _p->add_header(k, v); } -void Res::set_body(const void* s, size_t n) { - _p->set_body(s, n); +bool Res::set_body(const void* s, size_t n) { + return _p->set_body(s, n); } +int Res::send_body(const void* s, size_t n) { + return _p->send_body(s, n); +} + + Res::~Res() { if (_p) { _p->header.~fastring(); @@ -872,14 +897,21 @@ void ServerImpl::on_connection(tcp::Connection conn) { s.clear(); pres->buf = &s; + pres->pc_ = &conn; _on_req(req, res); - if (s.empty()) pres->set_body("", 0); + + if(pres->header_send!=1) { //no use http-long-connection Mode. + if (s.empty()) pres->set_body("", 0); - r = conn.send(s.data(), (int)s.size(), FLG_http_send_timeout); - if (r <= 0) goto send_err; + r = conn.send(s.data(), (int)s.size(), FLG_http_send_timeout); + if (r <= 0) goto send_err; + + s.resize(s.size() - pres->body_size); + HTTPLOG << "http send res: " << s; + }else { + need_close=true; + } - s.resize(s.size() - pres->body_size); - HTTPLOG << "http send res: " << s; if (need_close) { conn.close(); goto end; } }; diff --git a/src/so/http.h b/src/so/http.h index c06408067..c9fdc3bc4 100644 --- a/src/so/http.h +++ b/src/so/http.h @@ -2,6 +2,10 @@ #include "co/fastring.h" +namespace tcp{ +struct Connection; +} + namespace http { struct http_req_t { @@ -44,21 +48,35 @@ struct http_res_t { header << k << ": " << v << "\r\n"; } - void set_body(const void* s, size_t n); + bool set_body(const void* s, size_t n); void clear() { status = 0; buf = 0; header.clear(); body_size = 0; + + header_send=0; + s_err=-1; + pc_=nullptr; } + //for http long connection session + //User can call multiple times of 'send_body'. + //The 1st call will also pack response Header data and send! + int send_body(const void* data, size_t n); + // DO NOT change orders of the members here. uint32 status; uint32 version; fastring* buf; fastring header; size_t body_size; + + // new members for http long connection session implementation (like 'send_body') + tcp::Connection* pc_; + int header_send; + int s_err; }; int parse_http_req(fastring* buf, size_t size, http_req_t* req);