Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add HTTP long-conn-session support #239

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 10 additions & 3 deletions include/co/http.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
48 changes: 40 additions & 8 deletions src/so/http.cc
Original file line number Diff line number Diff line change
Expand Up @@ -471,14 +471,34 @@ 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();
(*buf) << version_str(version) << ' ' << status << ' ' << status_str(status) << "\r\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 {
Expand Down Expand Up @@ -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();
Expand Down Expand Up @@ -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; }
};

Expand Down
20 changes: 19 additions & 1 deletion src/so/http.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

#include "co/fastring.h"

namespace tcp{
struct Connection;
}

namespace http {

struct http_req_t {
Expand Down Expand Up @@ -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);
Expand Down