Quellcode durchsuchen

add tc_http auto test

ruanshudong vor 4 Jahren
Ursprung
Commit
e642785516

+ 841 - 0
examples/UtilDemo/demo-util/test_tc_http.cpp

@@ -0,0 +1,841 @@
+//
+// Created by jarod on 2020/2/20.
+//
+
+#include "util/tc_http.h"
+#include "util/tc_common.h"
+#include "util/tc_file.h"
+#include "gtest/gtest.h"
+
+using namespace tars;
+
+class HttpTest : public testing::Test
+{
+public:
+	//添加日志
+	static void SetUpTestCase()
+	{
+		cout<<"SetUpTestCase"<<endl;
+	}
+	static void TearDownTestCase()
+	{
+		cout<<"TearDownTestCase"<<endl;
+	}
+	virtual void SetUp()   //TEST跑之前会执行SetUp
+	{
+		cout<<"SetUp"<<endl;
+	}
+	virtual void TearDown() //TEST跑完之后会执行TearDown
+	{
+		cout<<"TearDown"<<endl;
+	}
+};
+
+TEST_F(HttpTest, testCheckRequestURL)   //此时使用的是TEST_F宏
+{
+	string s = string("GET /a/b?name=value&ccc=ddd HTTP/1.1\r\n")
+		+string("Accept: application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5\r\n")
+		+string("Accept-Charset: utf-8,gb2321;q=0.7,*;q=0.7\r\n")
+		+string("Accept-Encoding: gzip\r\n")
+		+string("Accept-Language: zh-cn,zh;q=0.5\r\n")
+		+string("Connection: close\r\n")
+		+string("Host: www.qq.com\r\n")
+		+string("Q-GUID: 08f0373a192a45778cc8567d1c641475\r\n")
+		+string("Q-UA: SQB12_GA/120450&SMTT_3/020100&SYM3&201514&E71&V2\r\n")
+		+string("User-Agent: E71/SymbianOS/9.1 Series60/3.0\r\n\r\n");
+
+	TC_HttpRequest req;
+	ASSERT_TRUE(req.decode(s));
+	ASSERT_TRUE(req.getRequestUrl() == "/a/b");
+	ASSERT_TRUE(req.getURL().getDomain() == "www.qq.com");
+}
+
+TEST_F(HttpTest, testEncodeString)   //此时使用的是TEST_F宏
+{
+	string s = string("GET /a/b?name=value&ccc=ddd HTTP/1.1\r\n")
+		+string("Accept: application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5\r\n")
+		+string("Accept-Charset: utf-8,gb2321;q=0.7,*;q=0.7\r\n")
+		+string("Accept-Encoding: gzip\r\n")
+		+string("Accept-Language: zh-cn,zh;q=0.5\r\n")
+		+string("Connection: close\r\n")
+		+string("Host: www.qq.com\r\n")
+		+string("Q-GUID: 08f0373a192a45778cc8567d1c641475\r\n")
+		+string("Q-UA: SQB12_GA/120450&SMTT_3/020100&SYM3&201514&E71&V2\r\n")
+		+string("User-Agent: E71/SymbianOS/9.1 Series60/3.0\r\n\r\n");
+
+//	s += string("a", 1024);
+
+	TC_HttpRequest req;
+	req.decode(s);
+	int64_t t = TC_Common::now2us();
+
+	int count = 100000;
+	int i = 0;
+	while(++i<count) {
+		string s;
+		s = req.encode();
+	}
+
+	ASSERT_TRUE(req.decode(s));
+	ASSERT_TRUE(req.getRequestUrl() == "/a/b");
+	ASSERT_TRUE(req.getURL().getDomain() == "www.qq.com");
+
+	cout << "testEncodeString::cost: " << TC_Common::now2us() - t << "us, " << 1.*(TC_Common::now2us() - t)/count << "us" << endl;
+}
+
+TEST_F(HttpTest, testEncodeVector)   //此时使用的是TEST_F宏
+{
+	string s = string("GET /a/b?name=value&ccc=ddd HTTP/1.1\r\n")
+		+string("Accept: application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5\r\n")
+		+string("Accept-Charset: utf-8,gb2321;q=0.7,*;q=0.7\r\n")
+		+string("Accept-Encoding: gzip\r\n")
+		+string("Accept-Language: zh-cn,zh;q=0.5\r\n")
+		+string("Connection: close\r\n")
+		+string("Host: www.qq.com\r\n")
+		+string("Q-GUID: 08f0373a192a45778cc8567d1c641475\r\n")
+		+string("Q-UA: SQB12_GA/120450&SMTT_3/020100&SYM3&201514&E71&V2\r\n")
+		+string("User-Agent: E71/SymbianOS/9.1 Series60/3.0\r\n\r\n");
+
+	s += string("a", 1024);
+
+	TC_HttpRequest req;
+	req.decode(s);
+	int64_t t = TC_Common::now2us();
+
+	int count = 100000;
+	int i = 0;
+
+	while(++i<count) {
+		vector<char> buff;
+
+		req.encode(buff);
+	}
+
+	cout << "testEncodeVector::cost: " << TC_Common::now2us() - t << "us, " << 1.*(TC_Common::now2us() - t)/count << "us" << endl;
+}
+
+TEST_F(HttpTest, testEncodeBuffString)   //此时使用的是TEST_F宏
+{
+	string s = string("GET /a/b?name=value&ccc=ddd HTTP/1.1\\r\n")
+		+string("Accept: application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5\r\n")
+		+string("Accept-Charset: utf-8,gb2321;q=0.7,*;q=0.7\r\n")
+		+string("Accept-Encoding: gzip\r\n")
+		+string("Accept-Language: zh-cn,zh;q=0.5\r\n")
+		+string("Connection: close\r\n")
+		+string("Host: www.qq.com\r\n")
+		+string("Q-GUID: 08f0373a192a45778cc8567d1c641475\r\n")
+		+string("Q-UA: SQB12_GA/120450&SMTT_3/020100&SYM3&201514&E71&V2\r\n")
+		+string("User-Agent: E71/SymbianOS/9.1 Series60/3.0\r\n\r\n");
+
+	int64_t t = TC_Common::now2us();
+
+	TC_HttpRequest req;
+	req.decode(s);
+
+	TC_NetWorkBuffer buff(NULL);
+
+	int count = 100000;
+	int i = 0;
+	while(++i<count) {
+		req.encode(buff);
+	}
+
+	cout << "testEncodeBuffString::cost: " << TC_Common::now2us() - t << "us, " << 1.*(TC_Common::now2us() - t)/count << "us" << endl;
+}
+
+TEST_F(HttpTest, testDecodeString)   //此时使用的是TEST_F宏
+{
+	string s = string("GET /a/b?name=value&ccc=ddd HTTP/1.1\r\n")
+		+string("Accept: application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5\r\n")
+		+string("Accept-Charset: utf-8,gb2321;q=0.7,*;q=0.7\r\n")
+		+string("Accept-Encoding: gzip\r\n")
+		+string("Accept-Language: zh-cn,zh;q=0.5\r\n")
+		+string("Connection: close\r\n")
+		+string("Host: www.qq.com\r\n")
+		+string("Q-GUID: 08f0373a192a45778cc8567d1c641475\r\n")
+		+string("Q-UA: SQB12_GA/120450&SMTT_3/020100&SYM3&201514&E71&V2\r\n")
+		+string("User-Agent: E71/SymbianOS/9.1 Series60/3.0\r\n\r\n");
+
+	int64_t t = TC_Common::now2us();
+
+	int count = 100000;
+	int i = 0;
+	while(++i<count) {
+		TC_HttpRequest req;
+		req.decode(s);
+	}
+
+	cout << "testDecodeString::cost: " << TC_Common::now2us() - t << "us, " << 1.*(TC_Common::now2us() - t)/count << "us" << endl;
+}
+
+TEST_F(HttpTest, testDecodeBuffString)   //此时使用的是TEST_F宏
+{
+	string s = string("HTTP/1.1 200 OK\r\n")
+		+string("Accept: application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5\r\n")
+		+string("Accept-Charset: utf-8,gb2321;q=0.7,*;q=0.7\r\n")
+		+string("Accept-Encoding: gzip\r\n")
+		+string("Accept-Language: zh-cn,zh;q=0.5\r\n")
+		+string("Connection: close\r\n")
+		+string("Host: www.qq.com\r\n")
+		+string("Q-GUID: 08f0373a192a45778cc8567d1c641475\r\n")
+		+string("Q-UA: SQB12_GA/120450&SMTT_3/020100&SYM3&201514&E71&V2\r\n")
+		+string("User-Agent: E71/SymbianOS/9.1 Series60/3.0\r\n\r\n");
+
+	int count = 100000;
+	int i = 0;
+
+	vector<TC_NetWorkBuffer> vbuff;
+	while(i<count) {
+		TC_NetWorkBuffer buff(NULL);
+
+		buff.addBuffer(s);
+
+		vbuff.push_back(buff);
+
+		++i;
+	}
+
+	int64_t t = TC_Common::now2us();
+	i = 0;
+	while(i<count) {
+		TC_HttpResponse req;
+
+		ASSERT_TRUE(req.incrementDecode(vbuff[i]));
+
+		++i;
+	}
+
+	cout << "testDecodeBuffString::cost: " << TC_Common::now2us() - t << "us, " << 1.*(TC_Common::now2us() - t)/count << "us" << endl;
+}
+
+TEST_F(HttpTest, testCheckRequestString)   //此时使用的是TEST_F宏
+{
+	string s = string("GET /a/b?name=value&ccc=ddd HTTP/1.1\r\n")
+		+string("Accept: application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5\r\n")
+		+string("Accept-Charset: utf-8,gb2321;q=0.7,*;q=0.7\r\n")
+		+string("Accept-Encoding: gzip\r\n")
+		+string("Accept-Language: zh-cn,zh;q=0.5\r\n")
+		+string("Connection: close\r\n")
+		+string("Host: www.qq.com\r\n")
+		+string("Q-GUID: 08f0373a192a45778cc8567d1c641475\r\n")
+		+string("Q-UA: SQB12_GA/120450&SMTT_3/020100&SYM3&201514&E71&V2\r\n")
+		+string("User-Agent: E71/SymbianOS/9.1 Series60/3.0\r\n\r\n");
+
+	int64_t t = TC_Common::now2us();
+
+	TC_HttpRequest req;
+	int count = 100000;
+	int i = 0;
+	while(++i<count) {
+		ASSERT_TRUE(req.checkRequest(s.c_str(), s.size()));
+	}
+
+	ASSERT_TRUE(req.decode(s));
+	ASSERT_TRUE(req.getRequestUrl() == "/a/b");
+	cout << req.getURL().getDomain() << endl;
+	ASSERT_TRUE(req.getURL().getDomain() == "www.qq.com");
+
+	cout << "testCheckRequestString::cost: " << TC_Common::now2us() - t << "us, " << 1.*(TC_Common::now2us() - t)/count << "us" << endl;
+}
+
+TEST_F(HttpTest, testCheckRequestBuff)   //此时使用的是TEST_F宏
+{
+	string s = string("GET /a/b?name=value&ccc=ddd HTTP/1.1\r\n")
+		+string("Accept: application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5\r\n")
+		+string("Accept-Charset: utf-8,gb2321;q=0.7,*;q=0.7\r\n")
+		+string("Accept-Encoding: gzip\r\n")
+		+string("Accept-Language: zh-cn,zh;q=0.5\r\n")
+		+string("Connection: close\r\n")
+		+string("Host: www.qq.com\r\n")
+		+string("Q-GUID: 08f0373a192a45778cc8567d1c641475\r\n")
+		+string("Q-UA: SQB12_GA/120450&SMTT_3/020100&SYM3&201514&E71&V2\r\n")
+		+string("User-Agent: E71/SymbianOS/9.1 Series60/3.0\r\n\r\n");
+
+	int64_t t = TC_Common::now2us();
+
+	TC_NetWorkBuffer buff(NULL);
+	buff.addBuffer(s.c_str(), s.size());
+
+	TC_HttpRequest req;
+	int count = 100000;
+	int i = 0;
+	while(++i<count) {
+		ASSERT_TRUE(req.checkRequest(buff));
+	}
+
+	cout << "testCheckRequestBuff::cost: " << TC_Common::now2us() - t << "us, " << 1.*(TC_Common::now2us() - t)/count << "us" << endl;
+}
+
+TEST_F(HttpTest, testHttpFinish)   //此时使用的是TEST_F宏
+{
+	string body = "abdefghigk";
+
+	vector<string> sbuff;
+	sbuff.push_back("GET /a/b?name=value&ccc=ddd HTTP/1.1\r\n");
+	sbuff.push_back("Accept: application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5\r\n");
+	sbuff.push_back("Accept-Charset: utf-8,gb2321;q=0.7,*;q=0.7\r\n");
+	sbuff.push_back("Accept-Encoding: gzip\r\n");
+	sbuff.push_back("Content-Length: " + TC_Common::tostr(body.size()) + "\r\n");
+	sbuff.push_back("Connection: close\r\n");
+	sbuff.push_back("User-Agent: E71/SymbianOS/9.1 Series60/3.0\r\n\r\n");
+
+	string header;
+	for(auto s : sbuff)
+	{
+		header += s;
+	}
+
+	string s = header + body;
+
+	TC_HttpRequest request;
+	ASSERT_TRUE(request.checkRequest(s.c_str(), s.size()));
+
+	TC_NetWorkBuffer buff(NULL);
+	buff.addBuffer(s.c_str(), s.size());
+
+	ASSERT_TRUE(buff.checkHttp() == TC_NetWorkBuffer::PACKET_FULL);
+}
+
+TEST_F(HttpTest, testHttpFinishNoLength)   //此时使用的是TEST_F宏
+{
+	vector<string> sbuff;
+	sbuff.push_back("GET /a/b?name=value&ccc=ddd HTTP/1.1\r\n");
+	sbuff.push_back("Accept: application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5\r\n");
+	sbuff.push_back("Accept-Charset: utf-8,gb2321;q=0.7,*;q=0.7\r\n");
+	sbuff.push_back("Accept-Encoding: gzip\r\n");
+	sbuff.push_back("Connection: close\r\n");
+	sbuff.push_back("User-Agent: E71/SymbianOS/9.1 Series60/3.0\r\n\r\n");
+
+	string header;
+	for(auto s : sbuff)
+	{
+		header += s;
+	}
+
+	string s = header;
+
+	TC_HttpRequest request;
+	ASSERT_TRUE(request.checkRequest(s.c_str(), s.size()));
+
+	TC_NetWorkBuffer buff(NULL);
+	buff.addBuffer(s.c_str(), s.size());
+
+	ASSERT_TRUE(buff.checkHttp() == TC_NetWorkBuffer::PACKET_FULL);
+}
+
+TEST_F(HttpTest, testHttpNoFinish)   //此时使用的是TEST_F宏
+{
+	string body = "abdefghigk";
+
+	vector<string> sbuff;
+	sbuff.push_back("GET /a/b?name=value&ccc=ddd HTTP/1.1\r\n");
+	sbuff.push_back("Accept: application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5\r\n");
+	sbuff.push_back("Accept-Charset: utf-8,gb2321;q=0.7,*;q=0.7\r\n");
+	sbuff.push_back("Accept-Encoding: gzip\r\n");
+	sbuff.push_back("Content-Length: " + TC_Common::tostr(body.size() + 1) + "\r\n");
+	sbuff.push_back("Connection: close\r\n");
+	sbuff.push_back("User-Agent: E71/SymbianOS/9.1 Series60/3.0\r\n\r\n");
+
+	string header;
+	for(auto s : sbuff)
+	{
+		header += s;
+	}
+
+	string s = header + body;
+
+	TC_HttpRequest request;
+	ASSERT_TRUE(!request.checkRequest(s.c_str(), s.size()));
+
+	TC_NetWorkBuffer buff(NULL);
+	buff.addBuffer(s.c_str(), s.size());
+
+	ASSERT_TRUE(buff.checkHttp() == TC_NetWorkBuffer::PACKET_LESS);
+}
+
+TEST_F(HttpTest, testHttpRequestChunked)   //此时使用的是TEST_F宏
+{
+	vector<string> body;
+	body.push_back("abasdfadefghiadfagk1");
+	body.push_back("abdasdfadfaefghigk2");
+	body.push_back("abdsaefghigk3");
+	body.push_back("abdeasdfafasfasfasfasdfasffghigk4");
+
+	vector<string> sbuff;
+	sbuff.push_back("GET /a/b?name=value&ccc=ddd HTTP/1.1\r\n");
+	sbuff.push_back("Accept: application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5\r\n");
+	sbuff.push_back("Accept-Charset: utf-8,gb2321;q=0.7,*;q=0.7\r\n");
+	sbuff.push_back("Accept-Encoding: gzip\r\n");
+	sbuff.push_back("Transfer-Encoding: chunked\r\n");
+	sbuff.push_back("Connection: close\r\n");
+	sbuff.push_back("User-Agent: E71/SymbianOS/9.1 Series60/3.0\r\n\r\n");
+
+	stringstream data;
+	for(auto s : sbuff)
+	{
+		data << s;
+	}
+
+	string sbody;
+	for(auto s : body)
+	{
+		sbody += s;
+		data << hex << s.size() << "\r\n" << s << "\r\n";
+	}
+	data << 0 << "\r\n\r\n";
+
+	string s = data.str();
+
+	TC_HttpRequest request;
+	ASSERT_TRUE(request.checkRequest(s.c_str(), s.size()));
+	ASSERT_TRUE(request.decode(s));
+
+	ASSERT_TRUE(request.getContent() == sbody);
+
+	TC_NetWorkBuffer buff(NULL);
+	buff.addBuffer(s.c_str(), s.size());
+
+	request.reset();
+	ASSERT_TRUE(request.checkRequest(buff));
+
+}
+
+TEST_F(HttpTest, testHttpRequestChunkedNoFinish)   //此时使用的是TEST_F宏
+{
+	vector<string> body;
+	body.push_back("abasdfadefghiadfagk1");
+	body.push_back("abdasdfadfaefghigk2");
+	body.push_back("abdsaefghigk3");
+	body.push_back("abdeasdfafasfasfasfasdfasffghigk4");
+
+	vector<string> sbuff;
+	sbuff.push_back("GET /a/b?name=value&ccc=ddd HTTP/1.1\r\n");
+	sbuff.push_back("Accept: application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5\r\n");
+	sbuff.push_back("Accept-Charset: utf-8,gb2321;q=0.7,*;q=0.7\r\n");
+	sbuff.push_back("Accept-Encoding: gzip\r\n");
+	sbuff.push_back("Transfer-Encoding: chunked\r\n");
+	sbuff.push_back("Connection: close\r\n");
+	sbuff.push_back("User-Agent: E71/SymbianOS/9.1 Series60/3.0\r\n\r\n");
+
+	stringstream data;
+	for(auto s : sbuff)
+	{
+		data << s;
+	}
+
+	data << hex << body[0].size() << "\r\n" << body[0] << "\r\n";
+	data << hex << body[1].size() << "\r\n" << body[1] << "\r\n";
+	data << hex << body[2].size() ;
+
+	string s = data.str();
+
+	TC_HttpRequest request;
+	ASSERT_TRUE(!request.checkRequest(s.c_str(), s.size()));
+
+	TC_NetWorkBuffer buff(NULL);
+	buff.addBuffer(s.c_str(), s.size());
+
+	ASSERT_TRUE(!request.checkRequest(buff));
+
+}
+
+TEST_F(HttpTest, testHttpResponse)   //此时使用的是TEST_F宏
+{
+	string body = "abcdef";
+
+	vector<string> sbuff;
+	sbuff.push_back("HTTP/1.1 200 OK\r\n");
+	sbuff.push_back("Content-Length: " + TC_Common::tostr(body.size()) + "\r\n");
+	sbuff.push_back("\r\n");
+
+	string header;
+	for(auto s : sbuff)
+	{
+		header += s;
+	}
+
+	string s = header + body;
+
+	{
+		TC_HttpResponse response;
+		ASSERT_TRUE(response.decode(s));
+		ASSERT_TRUE(response.getContent() == body);
+
+	}
+
+	{
+		TC_HttpResponse response;
+		TC_NetWorkBuffer buff(NULL);
+		buff.addBuffer(s.c_str(), s.size());
+
+		ASSERT_TRUE(response.incrementDecode(buff));
+		ASSERT_TRUE(response.getContent() == body);
+
+	}
+}
+
+TEST_F(HttpTest, testHttpResponseNoFinish)   //此时使用的是TEST_F宏
+{
+	string body = "abcdef";
+
+	vector<string> sbuff;
+	sbuff.push_back("HTTP/1.1 200 OK\r\n");
+	sbuff.push_back("Content-Length: " + TC_Common::tostr(body.size() + 1) + "\r\n");
+	sbuff.push_back("\r\n");
+
+	string header;
+	for(auto s : sbuff)
+	{
+		header += s;
+	}
+
+	string s = header + body;
+
+	{
+		TC_HttpResponse response;
+		ASSERT_TRUE(!response.decode(s));
+	}
+
+	{
+		TC_HttpResponse response;
+		TC_NetWorkBuffer buff(NULL);
+		buff.addBuffer(s.c_str(), s.size());
+
+		ASSERT_TRUE(!response.incrementDecode(buff));
+	}
+}
+
+TEST_F(HttpTest, testHttpResponseNoLength)   //此时使用的是TEST_F宏
+{
+	vector<string> sbuff;
+	sbuff.push_back("HTTP/1.1 200 OK\r\n");
+	sbuff.push_back("Connection: close\r\n");
+	sbuff.push_back("\r\n");
+
+	string header;
+	for(auto s : sbuff)
+	{
+		header += s;
+	}
+
+	string s = header;
+
+	{
+		TC_HttpResponse response;
+		ASSERT_TRUE(response.decode(s));
+	}
+
+	{
+		TC_HttpResponse response;
+		TC_NetWorkBuffer buff(NULL);
+		buff.addBuffer(s.c_str(), s.size());
+
+		ASSERT_TRUE(response.incrementDecode(buff));
+	}
+}
+
+TEST_F(HttpTest, testHttpResponseIncrementFinish)   //此时使用的是TEST_F宏
+{
+	string body = "abcdeasdfadfsff";
+
+	vector<string> sbuff;
+	sbuff.push_back("HTTP/1.1 200 OK\r\n");
+	sbuff.push_back("Content-Length: " + TC_Common::tostr(body.size()) + "\r\n");
+	sbuff.push_back("\r\n");
+
+	string header;
+	for(auto s : sbuff)
+	{
+		header += s;
+	}
+
+	string s = header;
+
+	{
+		TC_HttpResponse response;
+		ASSERT_TRUE(!response.decode(s));
+	}
+
+	{
+		TC_HttpResponse response;
+		TC_NetWorkBuffer buff(NULL);
+		buff.addBuffer(s.c_str(), s.size());
+
+		ASSERT_TRUE(!response.incrementDecode(buff));
+	}
+
+	s = header + body;
+	{
+		TC_HttpResponse response;
+		ASSERT_TRUE(response.decode(s));
+	}
+
+	{
+		TC_HttpResponse response;
+		TC_NetWorkBuffer buff(NULL);
+		buff.addBuffer(s.c_str(), s.size());
+
+		ASSERT_TRUE(response.incrementDecode(buff));
+	}
+
+}
+
+TEST_F(HttpTest, testHttpResponseChunked)   //此时使用的是TEST_F宏
+{
+	vector<string> body;
+	body.push_back("abdefghiasdfasdfsadfsadfsagk1");
+	body.push_back("abdefghasdfaaigk2");
+	body.push_back("abdefghigadsfadsfk3");
+	body.push_back("abdefgsfagasasdfasfdfdfsdfsfsdfdsffsdfsdfhigk4");
+
+	vector<string> sbuff;
+	sbuff.push_back("HTTP/1.1 200 OK\r\n");
+	sbuff.push_back("Accept: application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5\r\n");
+	sbuff.push_back("Accept-Charset: utf-8,gb2321;q=0.7,*;q=0.7\r\n");
+	sbuff.push_back("Transfer-Encoding: chunked\r\n");
+	sbuff.push_back("Connection: close\r\n\r\n");
+
+	stringstream data;
+	for(auto s : sbuff)
+	{
+		data << s;
+	}
+
+	string sbody;
+	for(auto s : body)
+	{
+		sbody += s;
+
+		data << hex << s.size() << "\r\n" << s << "\r\n";
+	}
+	data << 0 << "\r\n\r\n";
+
+	string s = data.str();
+
+	{
+		TC_HttpResponse response;
+		ASSERT_TRUE(response.decode(s));
+
+		ASSERT_TRUE(response.getContent() == sbody);
+	}
+
+	{
+		TC_HttpResponse response;
+		TC_NetWorkBuffer buff(NULL);
+		buff.addBuffer(s.c_str(), s.size());
+
+		ASSERT_TRUE(response.incrementDecode(buff));
+
+		ASSERT_TRUE(response.getContent() == sbody);
+	}
+}
+
+TEST_F(HttpTest, testHttpResponseChunkedNoFinish)   //此时使用的是TEST_F宏
+{
+	vector<string> body;
+	body.push_back("abdefasdfasfasghigk1");
+	body.push_back("asdfaabdeafghigk2");
+	body.push_back("abasdfasdfasdfasdfasdfasdfasfasdefghigk3");
+	body.push_back("abdefgfasdfasdfasdfasdfadfigk4");
+
+	vector<string> sbuff;
+	sbuff.push_back("HTTP/1.1 200 OK\r\n");
+	sbuff.push_back("Accept: application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5\r\n");
+	sbuff.push_back("Accept-Charset: utf-8,gb2321;q=0.7,*;q=0.7\r\n");
+	sbuff.push_back("Transfer-Encoding: chunked\r\n");
+	sbuff.push_back("Connection: close\r\n\r\n");
+
+	stringstream data;
+	for(auto s : sbuff)
+	{
+		data << s;
+	}
+
+	data << hex << body[0].size() << "\r\n" << body[0] << "\r\n";
+	data << hex << body[1].size() << "\r\n" << body[1] << "\r\n";
+	data << hex << body[2].size() << "\r\n" << "abc";
+
+	string s = data.str();
+
+	{
+		TC_HttpResponse response;
+		ASSERT_TRUE(!response.decode(s));
+
+	}
+
+	{
+		TC_HttpResponse response;
+
+		TC_NetWorkBuffer buff(NULL);
+		buff.addBuffer(s.c_str(), s.size());
+
+		ASSERT_TRUE(!response.incrementDecode(buff));
+	}
+}
+
+TEST_F(HttpTest, testWeb)   //此时使用的是TEST_F宏
+{
+	string url = "www.qq.com";
+	TC_HttpRequest stHttpReq;
+//	stHttpReq.setCacheControl("no-cache");
+//	stHttpReq.setUserAgent("Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.122 Safari/537.36");
+	stHttpReq.setUserAgent("E71/SymbianOS/9.1 Series60/3.0");
+	stHttpReq.setHeader("Connection", "Close");
+	stHttpReq.setAcceptEncoding("gzip, deflate, br");
+	stHttpReq.setGetRequest(url);
+
+	string sSendBuffer = stHttpReq.encode();
+
+	TC_HttpResponse stHttpRsp;
+	int iRet = stHttpReq.doRequest(stHttpRsp, 5000);
+	if(iRet != 0)
+	{
+		cout << iRet << endl;
+	}
+
+	string file = stHttpReq.getURL().getDomain() + ".html";
+
+	auto headers = stHttpRsp.getHeaders();
+
+	cout << "request:" << url << endl;
+	cout << TC_Common::tostr(headers.begin(), headers.end(), "\r\n") << endl;
+	TC_File::save2file(file, stHttpRsp.getContent());
+	
+//	ASSERT_TRUE(stHttpRsp.getContentLength() == TC_File::getFileSize(file));
+}
+
+void testCookie(const string &sRspURL, const string &sReqURL, const vector<string> &vsCookie)
+{
+	cout << sRspURL << "=>" << sReqURL << "-----------------------------------" << endl;
+
+	TC_HttpCookie cookie;
+
+	cookie.addCookie(sRspURL, vsCookie);
+
+	list<TC_HttpCookie::Cookie> vCookie = cookie.getAllCookie();
+
+	cout << "All Cookie:" << sRspURL << "-----------------------------------" << endl;
+
+	list<TC_HttpCookie::Cookie>::iterator it = vCookie.begin();
+
+	while(it != vCookie.end())
+	{
+		cout << TC_Common::tostr(it->_data.begin(), it->_data.end(), "; ") << ", " << it->_expires << ", " << it->_path << endl;
+
+		++it;
+	}
+
+	cout << "-----------------------------------" << endl << endl;
+
+	string sCookie;
+
+	cookie.getCookieForURL(sReqURL, sCookie);
+
+	cout << TC_Common::tostr(sCookie) << endl;
+
+	cout << "-----------------------------------" << endl << endl;
+}
+
+TEST_F(HttpTest, testCookie)   //此时使用的是TEST_F宏
+{
+	ASSERT_TRUE(TC_HttpCookie::matchDomain("qq.com", "www.qq.com") == true);
+	ASSERT_TRUE(TC_HttpCookie::matchDomain(".qq.com", "www.qq.com") == true);
+	ASSERT_TRUE(TC_HttpCookie::matchDomain(".qq.com", "qq.com") == true);
+	ASSERT_TRUE(TC_HttpCookie::matchDomain("t.qq.com", "www.qq.com") == false);
+	ASSERT_TRUE(TC_HttpCookie::matchDomain(".t.qq.com", "www.qq.com") == false);
+	ASSERT_TRUE(TC_HttpCookie::matchDomain(".t.qq.com", "t.qq.com") == true);
+	ASSERT_TRUE(TC_HttpCookie::matchDomain(".com", "www.qq.com") == false);
+	ASSERT_TRUE(TC_HttpCookie::matchDomain(".com", "qq.com") == false);
+	ASSERT_TRUE(TC_HttpCookie::matchDomain(".y.qq.com", "x.y.qq.com") == true);
+	ASSERT_TRUE(TC_HttpCookie::matchDomain(".x.y.qq.com", "x.y.qq.com") == true);
+	ASSERT_TRUE(TC_HttpCookie::matchDomain(".qq.com", "x.y.qq.com") == true);
+	ASSERT_TRUE(TC_HttpCookie::matchDomain(".qq.com", "y.qq.com") == true);
+	ASSERT_TRUE(TC_HttpCookie::matchDomain("qq.com", "y.qq.com") == true);
+
+	cout << TC_Common::now2GMTstr() << endl;
+
+	string gmt = TC_Common::tm2GMTstr(time(NULL) + 10);
+
+	string s = "HTTP/1.1  200  OK\r\n";//  200  Aouut Error\r\n";
+	s += "Set-Cookie: n1=1; a=1; c=d; Path=/; Domain=qq.com; Expires=" + gmt + "\r\n";
+	s += "Set-Cookie: n2=2; a=0; c=d; Path=/abc/def; Domain=.qq.com; Expires=" + gmt + "\r\n";
+	s += "Set-Cookie: n3=3; a=5; c=d; Path=/abc/def/aaa; Domain=.qq.com; Expires=" + gmt + "\r\n";
+	s += "Set-Cookie: n4=4; a=6; c=d; Path=/abc; Domain=.qq.com; Expires=" + gmt + "\r\n";
+	s += "Set-Cookie: n5=5; a=2; c=d; Path=/; Domain=.qq.com; Expires=" + gmt + "\r\n";
+	s += "Set-Cookie: n6=6; c=3; Path=/; Domain=y.qq.com; Expires=" + gmt + "\r\n";
+	s += "Set-Cookie: n7=7; c=3; Path=/abc; Domain=.y.qq.com; Expires=" + gmt + "\r\n";
+	s += "Set-Cookie: n8=6; c=3; Path=/; Domain=x.y.qq.com; Expires=" + gmt + "\r\n";
+	s += "Set-Cookie: n9=7; c=4; Path=/; Domain=.x.y.qq.com; Expires=" + gmt + "\r\n";
+	s += "Set-Cookie: n10=7; c=4; Path=/; Domain=qqq.com; Expires=" + gmt + "\r\n";
+	s += "Set-Cookie: n11=7; c=4; Path=/; Domain=.qqq.com; Expires=" + gmt + "\r\n";
+	s += "Set-Cookie: n12=8; c=4; Expires=" + gmt + "\r\n";
+	s += "Accept-Ranges: bytes\r\n\r\n";
+
+	TC_HttpResponse rsp;
+	rsp.decode(s);
+
+	cout << "-----------------------------------" << endl;
+
+	vector<string> vsCookie = rsp.getSetCookie();
+
+	cout << TC_Common::tostr(vsCookie.begin(), vsCookie.end(), "\r\n") << endl << endl;
+
+	testCookie("http://www.qq.com", "http://www.qq.com", vsCookie);
+	testCookie("http://www.qq.com/abc/def", "http://www.qq.com", vsCookie);
+	testCookie("http://www.qq.com/abc/def", "http://www.qq.com/abc", vsCookie);
+
+	cout << endl;
+	testCookie("http://www.qq.com", "http://qq.com", vsCookie);
+	testCookie("http://www.qq.com/abc/def/aaa", "http://www.qq.com/abc/def/aaa", vsCookie);
+	testCookie("http://www.qq.com/abc/def/aaa", "http://www.qq.com", vsCookie);
+	testCookie("http://www.qq.com", "http://www.qq.com/abc/def", vsCookie);
+	testCookie("http://qq.com", "http://qq.com/abc/def", vsCookie);
+	testCookie("http://qq.com", "http://t.qq.com/abc/def", vsCookie);
+	testCookie("http://qq.com", "http://y.qq.com/", vsCookie);
+	testCookie("http://qq.com", "http://y.qq.com/abc", vsCookie);
+	testCookie("http://x.y.qq.com", "http://x.y.qq.com", vsCookie);
+}
+//
+//void Test_TC_Http::main()
+//{
+//	testCheckRequestURL();
+//
+//	testEncodeString();
+//	testEncodeVector();
+//	testEncodeBuffString();
+//
+//	testDecodeString();
+//
+//	testDecodeBuffString();
+//
+//	testCheckRequestString();
+//	testCheckRequestBuff();
+//
+//	testHttpFinishNoLength();
+//
+//	testHttpFinish();
+//
+//	testHttpNoFinish();
+//
+//	testHttpRequestChunked();
+//
+//	testHttpResponse();
+//
+//	testHttpResponseNoFinish();
+//
+//	testHttpResponseNoLength();
+//
+//	testHttpResponseIncrementFinish();
+//
+//	testHttpResponseChunked();
+//
+//	testHttpRequestChunkedNoFinish();
+//
+//	testHttpResponseChunkedNoFinish();
+//
+////	testWeb("http://www.baidu.com");
+////	testWeb("http://www.httpwatch.com/httpgallery/chunked/chunkedimage.aspx");
+////	testWeb("http://www.qq.com");
+//
+////	testCookie();
+//}

Datei-Diff unterdrückt, da er zu groß ist
+ 439 - 328
tools/tarsgrammar/tars.tab.cpp


+ 35 - 32
tools/tarsparse/tars.lex.cpp

@@ -9,7 +9,7 @@
 #define FLEX_SCANNER
 #define YY_FLEX_MAJOR_VERSION 2
 #define YY_FLEX_MINOR_VERSION 5
-#define YY_FLEX_SUBMINOR_VERSION 37
+#define YY_FLEX_SUBMINOR_VERSION 35
 #if YY_FLEX_SUBMINOR_VERSION > 0
 #define FLEX_BETA
 #endif
@@ -47,6 +47,7 @@ typedef int16_t flex_int16_t;
 typedef uint16_t flex_uint16_t;
 typedef int32_t flex_int32_t;
 typedef uint32_t flex_uint32_t;
+typedef uint64_t flex_uint64_t;
 #else
 typedef signed char flex_int8_t;
 typedef short int flex_int16_t;
@@ -54,6 +55,7 @@ typedef int flex_int32_t;
 typedef unsigned char flex_uint8_t; 
 typedef unsigned short int flex_uint16_t;
 typedef unsigned int flex_uint32_t;
+#endif /* ! C99 */
 
 /* Limits of integral types. */
 #ifndef INT8_MIN
@@ -84,8 +86,6 @@ typedef unsigned int flex_uint32_t;
 #define UINT32_MAX             (4294967295U)
 #endif
 
-#endif /* ! C99 */
-
 #endif /* ! FLEXINT_H */
 
 #ifdef __cplusplus
@@ -176,7 +176,7 @@ extern FILE *yyin, *yyout;
      */
     #define  YY_LESS_LINENO(n) \
             do { \
-                int yyl;\
+                yy_size_t yyl;\
                 for ( yyl = n; yyl < yyleng; ++yyl )\
                     if ( yytext[yyl] == '\n' )\
                         --yylineno;\
@@ -369,7 +369,7 @@ static void yy_fatal_error (yyconst char msg[]  );
  */
 #define YY_DO_BEFORE_ACTION \
 	(yytext_ptr) = yy_bp; \
-	yyleng = (size_t) (yy_cp - yy_bp); \
+	yyleng = (yy_size_t) (yy_cp - yy_bp); \
 	(yy_hold_char) = *yy_cp; \
 	*yy_cp = '\0'; \
 	(yy_c_buf_p) = yy_cp;
@@ -513,7 +513,7 @@ int yy_flex_debug = 0;
 #define YY_MORE_ADJ 0
 #define YY_RESTORE_YY_MORE_OFFSET
 char *yytext;
-#line 1 "/home/jarod/TarsFramework/tarscpp/tools/tarsgrammar/tars.l"
+#line 1 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.l"
 /**
  * Tencent is pleased to support the open source community by making Tars available.
  *
@@ -529,7 +529,7 @@ char *yytext;
  * CONDITIONS OF ANY KIND, either express or implied. See the License for the 
  * specific language governing permissions and limitations under the License.
  */
-#line 20 "/home/jarod/TarsFramework/tarscpp/tools/tarsgrammar/tars.l"
+#line 20 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.l"
 #include <map>
 #include <string>
 #include <sstream>
@@ -649,7 +649,7 @@ static int input (void );
 /* This used to be an fputs(), but since the string might contain NUL's,
  * we now use fwrite().
  */
-#define ECHO do { if (fwrite( yytext, yyleng, 1, yyout )) {} } while (0)
+#define ECHO fwrite( yytext, yyleng, 1, yyout )
 #endif
 
 /* Gets input and stuffs it into "buf".  number of characters read, or YY_NULL,
@@ -660,7 +660,7 @@ static int input (void );
 	if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \
 		{ \
 		int c = '*'; \
-		size_t n; \
+		yy_size_t n; \
 		for ( n = 0; n < max_size && \
 			     (c = getc( yyin )) != EOF && c != '\n'; ++n ) \
 			buf[n] = (char) c; \
@@ -742,7 +742,7 @@ YY_DECL
 	register char *yy_cp, *yy_bp;
 	register int yy_act;
     
-#line 67 "/home/jarod/TarsFramework/tarscpp/tools/tarsgrammar/tars.l"
+#line 67 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.l"
 
 
 #line 749 "tars.lex.cpp"
@@ -840,12 +840,12 @@ do_action:	/* This label is used only to access EOF actions. */
 
 case 1:
 YY_RULE_SETUP
-#line 69 "/home/jarod/TarsFramework/tarscpp/tools/tarsgrammar/tars.l"
+#line 69 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.l"
 { BEGIN(INCL); }
 	YY_BREAK
 case 2:
 YY_RULE_SETUP
-#line 71 "/home/jarod/TarsFramework/tarscpp/tools/tarsgrammar/tars.l"
+#line 71 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.l"
 {
     if ( include_file_stack_ptr >= MAX_INCLUDE_DEPTH )
     {
@@ -878,7 +878,7 @@ YY_RULE_SETUP
 	YY_BREAK
 case YY_STATE_EOF(INITIAL):
 case YY_STATE_EOF(INCL):
-#line 101 "/home/jarod/TarsFramework/tarscpp/tools/tarsgrammar/tars.l"
+#line 101 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.l"
 {
     --include_file_stack_ptr;
     if ( include_file_stack_ptr < 0 )
@@ -897,14 +897,14 @@ case YY_STATE_EOF(INCL):
 	YY_BREAK
 case 3:
 YY_RULE_SETUP
-#line 117 "/home/jarod/TarsFramework/tarscpp/tools/tarsgrammar/tars.l"
+#line 117 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.l"
 {
     return TARS_SCOPE_DELIMITER;
 }
 	YY_BREAK
 case 4:
 YY_RULE_SETUP
-#line 121 "/home/jarod/TarsFramework/tarscpp/tools/tarsgrammar/tars.l"
+#line 121 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.l"
 {
     // C++ comment
     bool e = false;
@@ -925,7 +925,7 @@ YY_RULE_SETUP
 	YY_BREAK
 case 5:
 YY_RULE_SETUP
-#line 139 "/home/jarod/TarsFramework/tarscpp/tools/tarsgrammar/tars.l"
+#line 139 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.l"
 {
     // C comment
     bool e = false;
@@ -976,7 +976,7 @@ YY_RULE_SETUP
 	YY_BREAK
 case 6:
 YY_RULE_SETUP
-#line 187 "/home/jarod/TarsFramework/tarscpp/tools/tarsgrammar/tars.l"
+#line 187 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.l"
 {
     StringGrammarPtr ident  = new StringGrammar;
     ident->v            = yytext;
@@ -987,7 +987,7 @@ YY_RULE_SETUP
 case 7:
 /* rule 7 can match eol */
 YY_RULE_SETUP
-#line 194 "/home/jarod/TarsFramework/tarscpp/tools/tarsgrammar/tars.l"
+#line 194 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.l"
 {
     StringGrammarPtr ident  = new StringGrammar;
     ident->v            = yytext;
@@ -1000,7 +1000,7 @@ YY_RULE_SETUP
 	YY_BREAK
 case 8:
 YY_RULE_SETUP
-#line 204 "/home/jarod/TarsFramework/tarscpp/tools/tarsgrammar/tars.l"
+#line 204 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.l"
 {
     StringGrammarPtr str = new StringGrammar;
     bool e = false;
@@ -1115,7 +1115,7 @@ YY_RULE_SETUP
 	YY_BREAK
 case 9:
 YY_RULE_SETUP
-#line 316 "/home/jarod/TarsFramework/tarscpp/tools/tarsgrammar/tars.l"
+#line 316 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.l"
 {
     errno = 0;
     IntergerGrammarPtr ptr = new IntergerGrammar;
@@ -1140,7 +1140,7 @@ YY_RULE_SETUP
 	YY_BREAK
 case 10:
 YY_RULE_SETUP
-#line 338 "/home/jarod/TarsFramework/tarscpp/tools/tarsgrammar/tars.l"
+#line 338 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.l"
 {
     errno = 0;
     FloatGrammarPtr ptr = new FloatGrammar;
@@ -1175,7 +1175,7 @@ YY_RULE_SETUP
 case 11:
 /* rule 11 can match eol */
 YY_RULE_SETUP
-#line 369 "/home/jarod/TarsFramework/tarscpp/tools/tarsgrammar/tars.l"
+#line 369 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.l"
 {
     if(yytext[0] == '\n')
     {
@@ -1185,7 +1185,7 @@ YY_RULE_SETUP
 	YY_BREAK
 case 12:
 YY_RULE_SETUP
-#line 376 "/home/jarod/TarsFramework/tarscpp/tools/tarsgrammar/tars.l"
+#line 376 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.l"
 {
     if(yytext[0] < 32 || yytext[0] > 126)
     {
@@ -1204,7 +1204,7 @@ YY_RULE_SETUP
 	YY_BREAK
 case 13:
 YY_RULE_SETUP
-#line 392 "/home/jarod/TarsFramework/tarscpp/tools/tarsgrammar/tars.l"
+#line 392 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.l"
 ECHO;
 	YY_BREAK
 #line 1211 "tars.lex.cpp"
@@ -1398,7 +1398,7 @@ static int yy_get_next_buffer (void)
 			{ /* Not enough room in the buffer - grow it. */
 
 			/* just a shorter name for the current buffer */
-			YY_BUFFER_STATE b = YY_CURRENT_BUFFER_LVALUE;
+			YY_BUFFER_STATE b = YY_CURRENT_BUFFER;
 
 			int yy_c_buf_p_offset =
 				(int) ((yy_c_buf_p) - b->yy_ch_buf);
@@ -1531,7 +1531,7 @@ static int yy_get_next_buffer (void)
 	yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
 	yy_is_jam = (yy_current_state == 51);
 
-		return yy_is_jam ? 0 : yy_current_state;
+	return yy_is_jam ? 0 : yy_current_state;
 }
 
     static void yyunput (int c, register char * yy_bp )
@@ -1623,7 +1623,7 @@ static int yy_get_next_buffer (void)
 				case EOB_ACT_END_OF_FILE:
 					{
 					if ( yywrap( ) )
-						return EOF;
+						return 0;
 
 					if ( ! (yy_did_buffer_switch_on_eof) )
 						YY_NEW_FILE;
@@ -1764,6 +1764,10 @@ static void yy_load_buffer_state  (void)
 	yyfree((void *) b  );
 }
 
+#ifndef __cplusplus
+extern int isatty (int );
+#endif /* __cplusplus */
+    
 /* Initializes or reinitializes a buffer.
  * This function is sometimes called more than once on the same buffer,
  * such as during a yyrestart() or at EOF.
@@ -1968,8 +1972,8 @@ YY_BUFFER_STATE yy_scan_string (yyconst char * yystr )
 
 /** Setup the input buffer state to scan the given bytes. The next call to yylex() will
  * scan from a @e copy of @a bytes.
- * @param yybytes the byte buffer to scan
- * @param _yybytes_len the number of bytes in the buffer pointed to by @a bytes.
+ * @param bytes the byte buffer to scan
+ * @param len the number of bytes in the buffer pointed to by @a bytes.
  * 
  * @return the newly allocated buffer state object.
  */
@@ -1977,8 +1981,7 @@ YY_BUFFER_STATE yy_scan_bytes  (yyconst char * yybytes, yy_size_t  _yybytes_len
 {
 	YY_BUFFER_STATE b;
 	char *buf;
-	yy_size_t n;
-	yy_size_t i;
+	yy_size_t n, i;
     
 	/* Get memory for full buffer, including space for trailing EOB's. */
 	n = _yybytes_len + 2;
@@ -2211,7 +2214,7 @@ void yyfree (void * ptr )
 
 #define YYTABLES_NAME "yytables"
 
-#line 392 "/home/jarod/TarsFramework/tarscpp/tools/tarsgrammar/tars.l"
+#line 392 "/Volumes/MyData/centos/TarsCloud/framework/tarscpp/tools/tarsgrammar/tars.l"
 
 
 

Datei-Diff unterdrückt, da er zu groß ist
+ 439 - 328
tools/tarsparse/tars.tab.cpp


+ 83 - 58
tools/tarsparse/tars.tab.hpp

@@ -1,13 +1,14 @@
-/* A Bison parser, made by GNU Bison 3.0.4.  */
+/* A Bison parser, made by GNU Bison 2.3.  */
 
-/* Bison interface for Yacc-like parsers in C
+/* Skeleton interface for Bison's Yacc-like parsers in C
 
-   Copyright (C) 1984, 1989-1990, 2000-2015 Free Software Foundation, Inc.
+   Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
+   Free Software Foundation, Inc.
 
-   This program is free software: you can redistribute it and/or modify
+   This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
-   the Free Software Foundation, either version 3 of the License, or
-   (at your option) any later version.
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
 
    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -15,7 +16,9 @@
    GNU General Public License for more details.
 
    You should have received a copy of the GNU General Public License
-   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin Street, Fifth Floor,
+   Boston, MA 02110-1301, USA.  */
 
 /* As a special exception, you may create a larger work that contains
    part or all of the Bison parser skeleton and distribute that work
@@ -30,65 +33,87 @@
    This special exception was added by the Free Software Foundation in
    version 2.2 of Bison.  */
 
-#ifndef YY_YY_TARS_TAB_HPP_INCLUDED
-# define YY_YY_TARS_TAB_HPP_INCLUDED
-/* Debug traces.  */
-#ifndef YYDEBUG
-# define YYDEBUG 1
-#endif
-#if YYDEBUG
-extern int yydebug;
-#endif
-
-/* Token type.  */
+/* Tokens.  */
 #ifndef YYTOKENTYPE
 # define YYTOKENTYPE
-  enum yytokentype
-  {
-    TARS_VOID = 258,
-    TARS_STRUCT = 259,
-    TARS_BOOL = 260,
-    TARS_BYTE = 261,
-    TARS_SHORT = 262,
-    TARS_INT = 263,
-    TARS_DOUBLE = 264,
-    TARS_FLOAT = 265,
-    TARS_LONG = 266,
-    TARS_STRING = 267,
-    TARS_VECTOR = 268,
-    TARS_MAP = 269,
-    TARS_NAMESPACE = 270,
-    TARS_INTERFACE = 271,
-    TARS_IDENTIFIER = 272,
-    TARS_OUT = 273,
-    TARS_OP = 274,
-    TARS_KEY = 275,
-    TARS_ROUTE_KEY = 276,
-    TARS_REQUIRE = 277,
-    TARS_OPTIONAL = 278,
-    TARS_CONST_INTEGER = 279,
-    TARS_CONST_FLOAT = 280,
-    TARS_FALSE = 281,
-    TARS_TRUE = 282,
-    TARS_STRING_LITERAL = 283,
-    TARS_SCOPE_DELIMITER = 284,
-    TARS_CONST = 285,
-    TARS_ENUM = 286,
-    TARS_UNSIGNED = 287,
-    BAD_CHAR = 288
-  };
+   /* Put the tokens into the symbol table, so that GDB and other debuggers
+      know about them.  */
+   enum yytokentype {
+     TARS_VOID = 258,
+     TARS_STRUCT = 259,
+     TARS_BOOL = 260,
+     TARS_BYTE = 261,
+     TARS_SHORT = 262,
+     TARS_INT = 263,
+     TARS_DOUBLE = 264,
+     TARS_FLOAT = 265,
+     TARS_LONG = 266,
+     TARS_STRING = 267,
+     TARS_VECTOR = 268,
+     TARS_MAP = 269,
+     TARS_NAMESPACE = 270,
+     TARS_INTERFACE = 271,
+     TARS_IDENTIFIER = 272,
+     TARS_OUT = 273,
+     TARS_OP = 274,
+     TARS_KEY = 275,
+     TARS_ROUTE_KEY = 276,
+     TARS_REQUIRE = 277,
+     TARS_OPTIONAL = 278,
+     TARS_CONST_INTEGER = 279,
+     TARS_CONST_FLOAT = 280,
+     TARS_FALSE = 281,
+     TARS_TRUE = 282,
+     TARS_STRING_LITERAL = 283,
+     TARS_SCOPE_DELIMITER = 284,
+     TARS_CONST = 285,
+     TARS_ENUM = 286,
+     TARS_UNSIGNED = 287,
+     BAD_CHAR = 288
+   };
 #endif
+/* Tokens.  */
+#define TARS_VOID 258
+#define TARS_STRUCT 259
+#define TARS_BOOL 260
+#define TARS_BYTE 261
+#define TARS_SHORT 262
+#define TARS_INT 263
+#define TARS_DOUBLE 264
+#define TARS_FLOAT 265
+#define TARS_LONG 266
+#define TARS_STRING 267
+#define TARS_VECTOR 268
+#define TARS_MAP 269
+#define TARS_NAMESPACE 270
+#define TARS_INTERFACE 271
+#define TARS_IDENTIFIER 272
+#define TARS_OUT 273
+#define TARS_OP 274
+#define TARS_KEY 275
+#define TARS_ROUTE_KEY 276
+#define TARS_REQUIRE 277
+#define TARS_OPTIONAL 278
+#define TARS_CONST_INTEGER 279
+#define TARS_CONST_FLOAT 280
+#define TARS_FALSE 281
+#define TARS_TRUE 282
+#define TARS_STRING_LITERAL 283
+#define TARS_SCOPE_DELIMITER 284
+#define TARS_CONST 285
+#define TARS_ENUM 286
+#define TARS_UNSIGNED 287
+#define BAD_CHAR 288
+
+
+
 
-/* Value type.  */
 #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
 typedef int YYSTYPE;
-# define YYSTYPE_IS_TRIVIAL 1
+# define yystype YYSTYPE /* obsolescent; will be withdrawn */
 # define YYSTYPE_IS_DECLARED 1
+# define YYSTYPE_IS_TRIVIAL 1
 #endif
 
-
 extern YYSTYPE yylval;
 
-int yyparse (void);
-
-#endif /* !YY_YY_TARS_TAB_HPP_INCLUDED  */

+ 2229 - 2579
util/src/tc_http.cpp

@@ -1,2579 +1,2229 @@
-/**
- * Tencent is pleased to support the open source community by making Tars available.
- *
- * Copyright (C) 2016THL A29 Limited, a Tencent company. All rights reserved.
- *
- * Licensed under the BSD 3-Clause License (the "License"); you may not use this file except 
- * in compliance with the License. You may obtain a copy of the License at
- *
- * https://opensource.org/licenses/BSD-3-Clause
- *
- * Unless required by applicable law or agreed to in writing, software distributed 
- * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 
- * CONDITIONS OF ANY KIND, either express or implied. See the License for the 
- * specific language governing permissions and limitations under the License.
- */
-
-#include "util/tc_http.h"
-#include "util/tc_port.h"
-#include "util/tc_common.h"
-#include "util/tc_clientsocket.h"
-#include "util/tc_network_buffer.h"
-#include <string.h>
-
-namespace tars
-{
-
-const char* strnstr(const char* s1, const char* s2, int pos1)
-{
-	int l1, l2;
-
-	l2 = strlen(s2);
-	if (!l2)
-		return (char *)s1;
-	l1 = strlen(s1);
-
-	pos1 = (pos1 > l1)?l1:pos1;
-
-	while (pos1 >= l2) {
-		pos1--;
-		if (!memcmp(s1, s2, l2))
-			return (char *)s1;
-		s1++;
-	}
-	return NULL;
-}
-
-unordered_map<string, int> TC_Http::HEADER = {
-	{"GET", TC_HttpRequest::REQUEST_GET},
-	{"POST", TC_HttpRequest::REQUEST_POST},
-	{"PUT", TC_HttpRequest::REQUEST_PUT},
-	{"PATCH", TC_HttpRequest::REQUEST_PATCH},
-	{"OPTIONS", TC_HttpRequest::REQUEST_OPTIONS},
-	{"PRI", TC_HttpRequest::REQUEST_PRI},
-	{"DELETE", TC_HttpRequest::REQUEST_DELETE},
-	{"HEAD", TC_HttpRequest::REQUEST_HEAD},
-};
-
-unordered_map<int, string> TC_Http::HEADER_REVERSE = {
-	{TC_HttpRequest::REQUEST_GET, "GET"},
-	{TC_HttpRequest::REQUEST_POST, "POST"},
-	{TC_HttpRequest::REQUEST_PUT, "PUT"},
-	{TC_HttpRequest::REQUEST_PATCH, "PATCH"},
-	{TC_HttpRequest::REQUEST_OPTIONS, "OPTIONS"},
-	{TC_HttpRequest::REQUEST_PRI, "PRI"},
-	{TC_HttpRequest::REQUEST_DELETE, "DELETE"},
-	{TC_HttpRequest::REQUEST_HEAD, "HEAD"},
-};
-
-
-bool TC_Http::CmpCase::operator()(const string &s1, const string &s2) const
-{
-    if (TC_Port::strcasecmp(s1.c_str(), s2.c_str()) < 0)
-    {
-        return true;
-    }
-    else
-    {
-        return false;
-    }
-}
-
-bool TC_URL::isValid() const
-{
-    return !_sURL.empty();
-}
-
-string TC_URL::getURL() const
-{
-    return _sURL;
-}
-
-string TC_URL::type2String() const
-{
-    switch (_iURLType)
-    {
-    case HTTP:
-        return "http";
-    case HTTPS:
-        return "https";
-    case FTP:
-        return "ftp";
-    }
-
-    return "http";
-}
-
-string TC_URL::getDefaultPort() const
-{
-    switch (_iURLType)
-    {
-    case HTTP:
-        return "80";
-    case HTTPS:
-        return "443";
-    case FTP:
-        return "21";
-    }
-
-    return "80";
-}
-
-bool TC_URL::isDefaultPort() const
-{
-    return _sPort == getDefaultPort();
-}
-
-string TC_URL::toURL()
-{
-    _sURL.clear();
-
-    _sURL = _sScheme;
-    _sURL += "://";
-
-    if (!_sUser.empty())
-        _sURL += _sUser;
-
-    if (!_sUser.empty() && !_sPass.empty())
-    {
-        _sURL += ":";
-        _sURL += _sPass;
-    }
-
-    if (!_sUser.empty())
-        _sURL += "@";
-
-    _sURL += _sDomain;
-
-    if (!isDefaultPort())
-    {
-        _sURL += ":";
-        _sURL += _sPort;
-    }
-
-    _sURL += getRequest();
-
-    return _sURL;
-}
-
-string TC_URL::getRequest() const
-{
-    string sURL;
-
-    if (!_sPath.empty())
-        sURL += _sPath;
-
-    if (!_sQuery.empty())
-        sURL += "?" + _sQuery;
-
-    if (!_sRef.empty())
-        sURL += "#" + _sRef;
-
-    return sURL;
-}
-
-bool TC_URL::parseURL(const string &originRequest)
-{
-    // string originRequest  = TC_Common::trim(sURL, " ");
-
-    if (originRequest.empty())
-    {
-        return false;
-    }
-
-    clear();
-
-    int iPos = 0;
-
-    if (TC_Port::strncasecmp(originRequest.c_str(), "http://" , 7) == 0)
-    {
-        //http开头
-        _iURLType  = HTTP;
-        iPos = 7;
-        _sScheme = "http";
-    }
-    else if (TC_Port::strncasecmp(originRequest.c_str(), "https://" , 8) == 0)
-    {
-        //https开头
-        _iURLType  = HTTPS;
-        iPos = 8;
-        _sScheme = "https";
-    }
-    else if (TC_Port::strncasecmp(originRequest.c_str(), "ftp://", 6) == 0)
-    {
-        //ftps开头
-        _iURLType  = FTP;
-        iPos = 6;
-        _sScheme = "ftp";
-    }
-    else
-    {
-        //默认用http
-        _iURLType  = HTTP;
-        iPos = 0;
-        _sScheme = "http";
-    }
-
-    string::size_type index            = originRequest.find("/", iPos);
-    string::size_type nQuestionIndex   = originRequest.find("?", iPos);
-    string::size_type nNumbersignIndex = originRequest.find("#", iPos);
-
-    string  sUrlAuthority;
-    string  sUrlPath;
-
-    if (nQuestionIndex < index)
-    {
-		sUrlAuthority = originRequest.substr(iPos, nQuestionIndex - iPos);
-
-//		string sTemp = originRequest.substr(nQuestionIndex);
-
-        sUrlPath += '/';
-        sUrlPath += originRequest.substr(nQuestionIndex);
-    }
-    else if (nNumbersignIndex < index)
-    {
-		sUrlAuthority = originRequest.substr(iPos, nNumbersignIndex - iPos);
-
-//		string sTemp = originRequest.substr(nNumbersignIndex);
-
-        sUrlPath += '/';
-        sUrlPath += originRequest.substr(nNumbersignIndex);
-    }
-    else
-    {
-        if (index == string::npos)
-        {
-			sUrlAuthority = originRequest.substr(iPos, index);
-            sUrlPath = "";
-        }
-        else
-        {
-			sUrlAuthority = originRequest.substr(iPos, index - iPos);
-			sUrlPath = originRequest.substr(index);
-        }
-    }
-
-    //////解析Authority
-    index = sUrlAuthority.find("@");
-    if (index != string::npos)
-    {
-		_sUser = sUrlAuthority.substr(0, index);
-		_sDomain = sUrlAuthority.substr(index + 1);
-    }
-    else
-    {
-        _sDomain    = sUrlAuthority;
-    }
-
-    //////解析User:Pass
-    index = _sUser.find(":");
-    if (index != string::npos)
-    {
-		_sPass = _sUser.substr(index + 1);
-		_sUser = _sUser.substr(0, index);
-    }
-
-    //////解析Host:Port
-    index = _sDomain.find(":");
-    if (index != string::npos)
-    {
-		_sPort = _sDomain.substr(index + 1);
-
-		_sDomain = _sDomain.substr(0, index);
-    }
-    else
-    {
-        _sPort      = getDefaultPort();
-    }
-
-    //////解析Path Query Ref
-    index = sUrlPath.find("?");
-    if (index != string::npos)
-    {
-		_sPath = sUrlPath.substr(0, index);
-		_sQuery = sUrlPath.substr(index + 1);
-
-        index = _sQuery.rfind("#");
-        if (index != string::npos)
-        {
-			_sRef = _sQuery.substr(index + 1);
-			_sQuery = _sQuery.substr(0, index);
-        }
-    }
-    else
-    {
-        _sPath      = sUrlPath;
-        _sQuery     = "";
-
-        index = _sPath.rfind("#");
-        if (index != string::npos)
-        {
-			_sRef = _sPath.substr(index + 1);
-			_sPath = _sPath.substr(0, index);
-        }
-    }
-
-    if (_sPath.empty())
-    {
-        _sPath = "/";
-    }
-
-    toURL();
-
-    //域名或者IP必须包含一个点
-    if (_sDomain.find(".") == string::npos)
-    {
-        return false;
-    }
-
-    return true;
-}
-
-void TC_URL::specialize()
-{
-    //规整化路径
-    /*string sUrlPath = simplePath(getPath());
-
-    _fragment["path"]   = sUrlPath;*/
-    _sPath = simplePath(getPath());
-
-    _sURL = toURL();
-}
-
-void TC_URL::clear()
-{
-    _sScheme = "";
-    _sUser = "";
-    _sPass = "";
-    _sDomain = "";
-    _sPort = "";
-    _sPath = "";
-    _sQuery = "";
-    _sRef = "";
-
-    _sURL.clear();
-}
-
-string TC_URL::getScheme() const
-{
-    return _sScheme;
-}
-
-string TC_URL::getUserName() const
-{
-    return _sUser;
-}
-
-string TC_URL::getPassword() const
-{
-    return _sPass;
-}
-
-string TC_URL::getDomain() const
-{
-    return _sDomain;
-}
-
-string TC_URL::getPort() const
-{
-    return _sPort;
-}
-
-string TC_URL::getPath() const
-{
-    return _sPath;
-}
-
-string TC_URL::getQuery() const
-{
-    return _sQuery;
-}
-
-string TC_URL::getRef() const
-{
-    return _sRef;
-}
-
-string TC_URL::getRelativePath() const
-{
-    string sURL = getPath();
-
-    string::size_type pos;
-
-
-    pos   = sURL.rfind("/");
-
-    if (pos == string::npos)
-    {
-        return "/";
-    }
-    else
-    {
-		return sURL.substr(0, pos + 1);
-    }
-}
-
-string TC_URL::getRootPath() const
-{
-    string sURL = _sScheme;
-    sURL += "://";
-
-    if (!_sUser.empty())
-        sURL += _sUser;
-
-    if (!_sUser.empty() && !_sPass.empty())
-    {
-        sURL += ":";
-        sURL += _sPass;
-    }
-
-    if (!_sUser.empty())
-        sURL += "@";
-
-    sURL += _sDomain;
-
-    if (!isDefaultPort())
-    {
-        sURL += ":";
-        sURL += _sPort;
-    }
-
-    sURL += "/";
-
-	return sURL;
-}
-
-TC_URL TC_URL::buildWithRelativePath(const string &sRelativePath) const
-{
-    string sURL;
-
-    if (!sRelativePath.empty() && sRelativePath[0] == '/')
-    {
-        //如果链接是用"/"开头的相对地址,那么应该用Host+相对地址
-		sURL = sRelativePath.substr(1); 
-    }
-    else if (sRelativePath[0] == '#')
-    {
-        //#
-		sURL = getPath().substr(1);
-
-        if (!getQuery().empty())
-            sURL += "?" + getQuery();
-
-        sURL += sRelativePath;
-
-    }
-    else
-    {
-        //相对地址
-        sURL = getRelativePath().substr(1) + sRelativePath;
-    }
-
-    sURL = getRootPath() + simplePath("/" + sURL).substr(1);
-
-    TC_URL url;
-
-    url.parseURL(sURL);
-
-	return url;
-}
-
-string TC_URL::simplePath(const string &sPath) const
-{
-    //所有./都去掉
-    size_t pos      = 0;
-    string sNewPath = sPath;
-
-    while (true)
-    {
-        size_t dotPos = sNewPath.find("./", pos);
-
-        if (dotPos != string::npos)
-        {
-            if ((dotPos == 0) || (sNewPath.at(dotPos - 1) == '/'))
-            {
-                sNewPath.erase(dotPos, 2);
-            }
-            else
-            {
-                pos = dotPos + 2;
-            }
-        }
-        else
-        {
-            break;
-        }
-    }
-
-    //如果路径是以.结尾的, 则.去掉
-    if (((sNewPath.length() >= 2) && (sNewPath.substr(sNewPath.length() - 2) == "/.")) || (sNewPath == "."))
-    {
-        sNewPath.erase(sNewPath.length() - 1);
-    }
-
-    //处理/../的形式
-    pos = 0;
-    size_t startPos = 0;
-
-    while (1)
-    {
-        size_t slashDot = sNewPath.find("/../", pos);
-
-        if (slashDot != string::npos)
-        {
-            if (0 == slashDot)
-            {
-                sNewPath.erase(0, 3);
-                continue;
-            }
-
-            if ( (slashDot > 1) && (sNewPath.substr(slashDot - 2, 2) == "..") )
-            {
-                pos = slashDot + 4;
-                continue;
-            }
-
-            startPos = sNewPath.rfind('/', slashDot - 1);
-
-            if (startPos == string::npos) startPos = 0;
-
-            sNewPath.erase(startPos, slashDot + 4 - startPos - 1);
-        }
-        else
-        {
-            break;
-        }
-    }
-
-    //处理/..结尾的情况
-    if ((sNewPath.size() >= 3) && (sNewPath.substr(sNewPath.size() - 3, 3) == "/.."))
-    {
-        size_t slashDot = sNewPath.size() - 3;
-        if (!((slashDot > 1) && (sNewPath.substr(slashDot - 2, 2) == "..")))
-        {
-            startPos = sNewPath.rfind ('/', slashDot - 1);
-            if (startPos == string::npos) startPos = 0;
-            sNewPath.erase (startPos + 1);
-        }
-    }
-
-	return sNewPath;
-}
-
-////////////////////////////////////////////////////////////////////
-
-void TC_Http::setHeader(const string &sHeadName, const string &sHeadValue)
-{
-    //Set-Cookie和Cookie可以有多个头
-    const char * pStr1 = "SET-COOKIE";
-    const char * pStr2 = "COOKIE";//原则上COOKIE只有一个,担心有兼容性问题,保留
-    if ((TC_Port::strcasecmp(sHeadName.c_str(), pStr1) != 0) && (TC_Port::strcasecmp(sHeadName.c_str(), pStr2) != 0))
-    {
-        _headers.erase(sHeadName);
-    }
-
-    _headers.insert(multimap<string, string>::value_type(sHeadName, sHeadValue));
-}
-
-bool TC_Http::hasHeader(const char *sHeader) const
-{
-	http_header_type::const_iterator it = _headers.find(sHeader);
-	if (it == _headers.end())
-	{
-		return false;
-	}
-
-	return true;
-}
-
-bool TC_Http::checkHeader(const char *sHeader, const char *value) const
-{
-	http_header_type::const_iterator it = _headers.find(sHeader);
-	if (it == _headers.end())
-	{
-		return false;
-	}
-
-	return TC_Port::strcasecmp(it->second.c_str(), value) == 0;
-}
-
-string TC_Http::getHeader(const string& sHeader) const
-{
-    http_header_type::const_iterator it = _headers.find(sHeader);
-    if (it == _headers.end())
-    {
-        return "";
-    }
-
-    return it->second;
-}
-
-string TC_Http::getContentType() const
-{
-    return getHeader("Content-Type");
-}
-
-string TC_Http::getHost() const
-{
-    return getHeader("Host");
-}
-
-size_t TC_Http::getContentLength() const
-{
-    string s = getHeader("Content-Length");
-    if (s.empty())
-    {
-        return 0;
-    }
-
-    return TC_Common::strto<size_t>(s);
-}
-
-string TC_Http::genHeader() const
-{
-	string sHttpHeader;
-
-	for (http_header_type::const_iterator it = _headers.begin(); it != _headers.end(); ++it)
-	{
-		if (it->second != "")
-		{
-			sHttpHeader += it->first;
-			sHttpHeader += ": ";
-			sHttpHeader += it->second;
-			sHttpHeader += "\r\n";
-		}
-	}
-
-	return sHttpHeader;
-}
-
-void TC_Http::genHeader(string &sHttpHeader) const
-{
-    for (http_header_type::const_iterator it = _headers.begin(); it != _headers.end(); ++it)
-    {
-        if (it->second != "")
-        {
-            sHttpHeader += it->first;
-            sHttpHeader += ": ";
-            sHttpHeader += it->second;
-            sHttpHeader += "\r\n";
-        }
-    }
-}
-
-vector<string> TC_Http::getHeaderMulti(const string &sHeadName) const
-{
-    vector<string> v;
-
-    http_header_type::const_iterator itEnd = _headers.end();
-
-    for ( http_header_type::const_iterator it = _headers.begin(); it != itEnd; ++it)
-    {
-        if (TC_Port::strcasecmp(it->first.c_str(), sHeadName.c_str()) == 0)
-        {
-            v.push_back(it->second);
-        }
-    }
-
-	return v;
-}
-
-void TC_Http::reset()
-{
-    _headers.clear();
-    _version.clear();
-    _headLength = 0;
-    _content.clear();
-    _bIsChunked = false;
-}
-
-void TC_Http::getHeaders(map<string, string> &header)
-{
-	for(auto it = _headers.begin(); it != _headers.end(); ++it)
-	{
-		header.insert(map<string, string>::value_type(it->first, it->second));
-	}
-}
-
-/********************* TC_HttpCookie ***********************/
-
-bool TC_HttpCookie::matchDomain(const string &sCookieDomain, const string &sDomain)
-{
-    string sCookieDomainNew = TC_Common::lower(sCookieDomain);
-
-    //没有点的自动加点
-    if (sCookieDomainNew.find(".") != 0)
-    {
-        sCookieDomainNew = "." + sCookieDomainNew;
-    }
-
-    string::size_type pos = sCookieDomainNew.find(".");
-
-    //sCookieDomain串至少有两个点
-    if (pos == string::npos || (pos == 0 && sCookieDomainNew.rfind(".") == 0))
-    {
-        return false;
-    }
-
-    string sLowerDomain = TC_Common::lower(sDomain);
-
-    //后边是子域名
-    if (sDomain.length() >= sCookieDomainNew.length() &&
-            sLowerDomain.compare(sDomain.length() - sCookieDomainNew.length(), sCookieDomainNew.length(), sCookieDomainNew) == 0)
-    {
-        return true;
-    }
-
-    //去掉.相等
-    if (sLowerDomain == sCookieDomainNew.substr(1))
-    {
-        return true;
-    }
-
-    return false;
-}
-
-size_t TC_HttpCookie::matchPath(const string &sCookiePath, const string &sPath)
-{
-    if (sCookiePath.empty() || sPath.empty()) return 0;
-
-    //都在最后加/再匹配
-    string sCookiePath1 = (sCookiePath.at(sCookiePath.length() - 1) == '/') ? sCookiePath : sCookiePath + "/";
-
-    string sPath1 = (sPath.at(sPath.length() - 1) == '/') ? sPath : sPath + "/";
-
-    if (sPath1.find(sCookiePath1) == 0)
-    {
-        return sCookiePath1.length();
-    }
-
-    return 0;
-}
-
-void TC_HttpCookie::clear()
-{
-    _cookies.clear();
-}
-
-bool TC_HttpCookie::fixDomain(const string &sDomain, string &sFixDomain)
-{
-    if (sDomain.empty())
-    {
-        return false;
-    }
-
-    sFixDomain = sDomain;
-
-    //自动加.
-    if (sDomain.at(0) != '.')
-    {
-        sFixDomain = "." + sDomain;
-    }
-
-    //domain至少两段
-    if (sFixDomain.find(".") == sFixDomain.rfind("."))
-        return false;
-
-    return true;
-}
-
-void TC_HttpCookie::addCookie(const Cookie &cookie, list<Cookie> &cookies)
-{
-    string sDomain;
-
-    Cookie cookieNew = cookie;
-
-    if (!fixDomain(cookieNew._domain, sDomain))
-        return;
-
-    cookieNew._domain = sDomain;
-
-    if (cookieNew._path.empty())
-        return;
-
-    list<Cookie>::iterator it = cookies.begin();
-
-    string sName;
-    if (cookieNew._data.size() >= 1)
-    {
-        sName = cookieNew._data.begin()->first;
-    }
-
-    while (it != cookies.end())
-    {
-        //检查Cookie是否过期
-        if (isCookieExpires(*it))
-        {
-            cookies.erase(it++);
-        }
-        else if (TC_Port::strcasecmp(it->_domain.c_str(), cookieNew._domain.c_str()) == 0
-                 && strcmp(it->_path.c_str(), cookieNew._path.c_str()) == 0
-                 && it->_isSecure == cookieNew._isSecure)
-        {
-            if (it->_expires == cookieNew._expires)
-            {
-                //domain/path/expires都匹配的情况下, 覆盖老cookie的数据
-                cookieNew._data.insert(it->_data.begin(), it->_data.end());
-
-                cookies.erase(it++);
-            }
-            else
-            {
-                //超时间不一样,但存在同样的key,需删除
-                if (it->_data.find(sName) != it->_data.end())
-                {
-                    it->_data.erase(sName);
-                }
-                ++it;
-            }
-        }
-        else
-        {
-            ++it;
-        }
-    }
-
-    cookies.push_back(cookieNew);
-}
-
-void TC_HttpCookie::addCookie(const Cookie &cookie)
-{
-    addCookie(cookie, _cookies);
-}
-
-void TC_HttpCookie::addCookie(const list<Cookie> &cookie)
-{
-    list<Cookie>::const_iterator it = cookie.begin();
-
-    while (it != cookie.end())
-    {
-        addCookie(*it);
-
-        ++it;
-    }
-}
-
-void TC_HttpCookie::addCookie(const string &sRspURL, const vector<string> &vCookies)
-{
-    TC_URL cURL;
-
-    cURL.parseURL(sRspURL);
-
-    string sRspURLDomain = TC_Common::lower(cURL.getDomain());
-
-    string sRspURLPath  = cURL.getPath();
-
-    for (size_t i = 0; i < vCookies.size(); i++)
-    {
-        //处理一行SetCookie
-        vector<string> v = TC_Common::sepstr<string>(vCookies[i], ";");
-
-        Cookie cookie;
-
-        cookie._isSecure = false;
-        cookie._expires  = 0;
-
-        //解析Cookie数据
-        for (size_t j = 0; j < v.size(); ++j)
-        {
-            string::size_type index = v[j].find("=");
-
-            string name;
-
-            string value;
-
-            if (index != string::npos)
-            {
-                name  = TC_Common::trim(v[j].substr(0, index), " ");
-
-                value = TC_Common::trim(v[j].substr(index + 1));
-            }
-            else
-            {
-                name  = TC_Common::trim(v[j]);
-            }
-            if (TC_Port::strcasecmp(name.c_str(), "secure") == 0)
-            {
-                cookie._isSecure = true;
-            }
-            else if (TC_Port::strcasecmp(name.c_str(), "expires") == 0)
-            {
-                struct tm stTm;
-                //兼容时间格式
-                //expires=Mon, 09-May-41 08:39:32 GMT
-                //expires=Thu, 01-Jan-1970 01:00:00 GMT
-                value = TC_Common::replace(value, "-", " ");
-                if (value.length() == 27  && value.at(11) == ' ' && value.at(14) == ' ')
-                {
-                    int year = TC_Common::strto<int> (value.substr(12, 2));
-                    if (year >= 69 && year <= 99)
-                        value = value.substr(0, 12) + "19" + value.substr(12);
-                    else
-                        value = value.substr(0, 12) + "20" + value.substr(12);
-                }
-
-                TC_Common::strgmt2tm(value, stTm);
-
-                cookie._expires = TC_Port::timegm(&stTm);
-            }
-            else if (TC_Port::strcasecmp(name.c_str(), "path") == 0)
-            {
-                cookie._path = value;
-            }
-            else if (TC_Port::strcasecmp(name.c_str(), "domain") == 0)
-            {
-                cookie._domain = value;
-            }
-            else if (TC_Port::strcasecmp(name.c_str(), "httponly") == 0)
-            {
-                //TODO
-                //cookie._isHttpOnly = true;
-            }
-            else
-                cookie._data.insert(http_cookie_data::value_type(name, value));
-        }
-
-        ///修正和匹配domain/////////////////////////////////////////
-        if (cookie._domain.empty())
-            cookie._domain = sRspURLDomain;
-
-        if (!fixDomain(cookie._domain, cookie._domain))
-            continue;
-
-        //匹配域名
-        if (!matchDomain(cookie._domain, sRspURLDomain))
-            continue;
-
-        //修改和匹配path/////////////////////////////
-        if (cookie._path.empty())
-        {
-            string sCookiePath;
-
-            //缺省是全路径
-            string sRequest = sRspURLPath;
-
-            string::size_type pos = sRequest.rfind("/");
-
-            if (pos == string::npos)
-                sCookiePath = "/";
-            else
-				sCookiePath = sRequest.substr(0, pos + 1);
-
-            cookie._path = sCookiePath;
-        }
-
-        //URL在Path范围内,Cookie 有效
-        if (!matchPath(cookie._path, sRspURLPath))
-            continue;
-
-        //添加Cookie
-        addCookie(cookie);
-    }
-}
-
-bool TC_HttpCookie::isCookieExpires(const Cookie &cookie) const
-{
-    //过期了
-    if (cookie._expires != 0 && cookie._expires < time(NULL))
-        return true;
-
-    return false;
-}
-
-size_t TC_HttpCookie::isCookieMatch(const Cookie &cookie, const TC_URL &tURL) const
-{
-    //域名没有匹配
-    if (!matchDomain(cookie._domain, tURL.getDomain()))
-        return 0;
-
-    //路径没有匹配
-    size_t len = matchPath(cookie._path, tURL.getPath());
-    if (len == 0)
-        return 0;
-
-    //安全的cookie,不安全的URL
-    if (cookie._isSecure && (tURL.getType() != TC_URL::HTTPS))
-        return 0;
-
-    return len;
-}
-
-void TC_HttpCookie::getCookieForURL(const string &sReqURL, list<TC_HttpCookie::Cookie> &cookies)
-{
-    TC_URL tURL;
-
-    tURL.parseURL(sReqURL);
-
-    cookies.clear();
-
-    list<Cookie>::iterator it = _cookies.begin();
-
-    while (it != _cookies.end())
-    {
-        //检查Cookie是否过期
-        if (isCookieExpires(*it))
-        {
-            _cookies.erase(it++);
-            continue;
-        }
-
-        size_t len = isCookieMatch(*it, tURL);
-        if (len == 0)
-        {
-            ++it;
-            continue;
-        }
-
-        cookies.push_back(*it);
-
-        ++it;
-    }
-}
-
-void TC_HttpCookie::getCookieForURL(const string &sReqURL, string &sCookie)
-{
-    list<Cookie> cookies;
-
-    sCookie.clear();
-
-    getCookieForURL(sReqURL, cookies);
-
-    list<Cookie>::iterator it = cookies.begin();
-    while (it != cookies.end())
-    {
-        http_cookie_data::iterator itd = it->_data.begin();
-
-        while (itd != it->_data.end())
-        {
-            //被删除的cookie不输出
-            if (itd->first != "" && itd->second != "" && TC_Common::lower(itd->second) != "null"
-                    && TC_Common::lower(itd->second) != "deleted")
-                sCookie += itd->first + "=" + itd->second + "; ";
-
-            ++itd;
-        }
-
-        ++it;
-    }
-
-    //去掉末尾的 "; "
-    if (sCookie.length() >= 2)
-		sCookie = sCookie.substr(0, sCookie.length() - 2);
-}
-
-list<TC_HttpCookie::Cookie> TC_HttpCookie::getSerializeCookie(time_t t)
-{
-    list<Cookie> cookies;
-
-    list<Cookie>::iterator it = _cookies.begin();
-
-    while (it != _cookies.end())
-    {
-        if (isCookieExpires(*it))
-        {
-            _cookies.erase(it++);
-            continue;
-        }
-        else if (it->_expires != 0) //非当前会话的
-        {
-            cookies.push_back(*it);
-
-            ++it;
-        }
-        else
-            ++it;
-    }
-
-	return cookies;
-}
-
-const list<TC_HttpCookie::Cookie> & TC_HttpCookie::getAllCookie()
-{
-    deleteExpires(time(NULL));
-
-    return _cookies;
-}
-
-void TC_HttpCookie::deleteExpires(time_t t, bool bErase)
-{
-    list<Cookie>::iterator it = _cookies.begin();
-
-    while (it != _cookies.end())
-    {
-        if (bErase && it->_expires == 0)
-        {
-            _cookies.erase(it++);
-            continue;
-        }
-        else if (isCookieExpires(*it))
-        {
-            _cookies.erase(it++);
-            continue;
-        }
-        else
-            ++it;
-    }
-}
-
-/********************* TC_HttpResponse ***********************/
-//
-//void TC_HttpResponse::parseResponseHeader(const char* szBuffer, const char* header)
-//{
-//	auto it = strstr(szBuffer, "\r\n");
-//
-//	assert(it != NULL);
-//
-//	string sep = " ";
-//
-//	auto f1 = std::search(szBuffer, it, sep.c_str(), sep.c_str() + sep.size());
-//	if(f1 == it)
-//	{
-//		throw TC_HttpResponse_Exception("[TC_HttpResponse_Exception::parseResponeHeader] http response parse version format error : " + string(szBuffer, it-szBuffer));
-//	}
-//
-//	auto f2 = std::search(f1 + 1, it, sep.c_str(), sep.c_str() + sep.size());
-//	if(f1 == it)
-//	{
-//		throw TC_HttpResponse_Exception("[TC_HttpResponse_Exception::parseResponeHeader] http response parse status format error : " + string(szBuffer, it-szBuffer));
-//	}
-//
-//	_headerLine = string(szBuffer, it-szBuffer);
-//
-//	if(TC_Port::strncasecmp(_headerLine.c_str(), "HTTP/", 5) != 0)
-//	{
-//		throw TC_HttpResponse_Exception("[TC_HttpResponse_Exception::parseResponeHeader] http response version is not start with 'HTTP/' : " + _headerLine);
-//	}
-//
-//	_version    = string(szBuffer, f1);
-//
-//	_status     = TC_Common::strto<int>(string(f1 + 1, f2));
-//
-//	_about      = TC_Common::trim(string(f2 + 1, it));
-//
-//	parseHeader(szBuffer, header, _headers);
-//}
-//
-//void TC_HttpResponse::parseResponseHeader(TC_NetWorkBuffer &buff, TC_NetWorkBuffer::buffer_iterator &headerIt)
-//{
-//	string line = "\r\n";
-//	auto it = buff.find(line.c_str(), line.size());
-//
-//	assert(it != buff.end());
-//
-//	string sep = " ";
-//
-//	auto f1 = std::search(buff.begin(), it, sep.c_str(), sep.c_str() + sep.size());
-//	if(f1 == it)
-//	{
-//	    throw TC_HttpResponse_Exception("[TC_HttpResponse_Exception::parseResponeHeader] http response parse version format error : " + buff.iteratorToIterator<string>(buff.begin(), it));
-//	}
-//
-//	auto f2 = std::search(f1 + 1, it, sep.c_str(), sep.c_str() + sep.size());
-//	if(f1 == it)
-//	{
-//		throw TC_HttpResponse_Exception("[TC_HttpResponse_Exception::parseResponeHeader] http response parse status format error : " + buff.iteratorToIterator<string>(buff.begin(), it));
-//	}
-//
-//	_headerLine = buff.iteratorToIterator<string>(buff.begin(), it);
-//
-//	if(TC_Port::strncasecmp(_headerLine.c_str(), "HTTP/", 5) != 0)
-//	{
-//		throw TC_HttpResponse_Exception("[TC_HttpResponse_Exception::parseResponeHeader] http response version is not start with 'HTTP/' : " + _headerLine);
-//	}
-//
-//	_version    = buff.iteratorToIterator<string>(buff.begin(), f1);
-//
-//	_status     = TC_Common::strto<int>(buff.iteratorToIterator<string>(f1 + 1, f2));
-//
-//	_about      = TC_Common::trim(buff.iteratorToIterator<string>(f2 + 1, it));
-//
-//	parseHeader(buff.begin(), headerIt, _headers);
-//
-//}
-
-void TC_HttpResponse::reset()
-{
-    TC_Http::reset();
-
-    _status = 200;
-    _about  = "OK";
-    _version = "HTTP/1.1";
-
-    _iTmpContentLength = 0;
-
-    _iRecvContentLength = 0;
-}
-
-vector<string> TC_HttpResponse::getSetCookie() const
-{
-	return getHeaderMulti("Set-Cookie");
-}
-
-void TC_HttpResponse::addContent(const string &sBuffer)
-{
-    _content += sBuffer;
-
-    _iRecvContentLength += sBuffer.length();
-}
-
-void TC_HttpResponse::addContent(const char *buffer, size_t length)
-{
-	_content.append(buffer, length);
-
-	_iRecvContentLength += length;
-}
-
-size_t TC_HttpResponse::parseResponseHeaderString(const char *beginIt, const char *headerIt)
-{
-	auto it = strnstr(beginIt, "\r\n", headerIt - beginIt);
-
-	assert(it != NULL);
-
-	auto f1 = strnstr(beginIt, " ", it - beginIt);
-	if(f1 == NULL)
-	{
-		throw TC_HttpResponse_Exception("[TC_HttpResponse_Exception::parseResponeHeader] http response parse version format error : " + string(beginIt, headerIt - beginIt));
-	}
-
-	auto f2 = strnstr(f1 + 1, " ", it - (f1 + 1));
-	if(f1 == NULL)
-	{
-		throw TC_HttpResponse_Exception("[TC_HttpResponse_Exception::parseResponeHeader] http response parse status format error : " + string(beginIt, headerIt - beginIt));
-	}
-
-	_headerLine = string(beginIt, it - beginIt);
-
-	if(TC_Port::strncasecmp(_headerLine.c_str(), "HTTP/", 5) != 0)
-	{
-		throw TC_HttpResponse_Exception("[TC_HttpResponse_Exception::parseResponeHeader] http response version is not start with 'HTTP/' : " + _headerLine);
-	}
-
-	_version    = string(beginIt, f1 - beginIt);
-
-	_status     = TC_Common::strto<int>(string(f1 + 1, f2));
-
-	_about      = string(f2 + 1, it);
-
-	return parseHeaderString(beginIt, headerIt, _headers);
-}
-
-bool TC_HttpResponse::incrementDecode(TC_NetWorkBuffer &buff)
-{
-	if(buff.empty())
-		return false;
-	//解析头部
-	if (_headLength == 0)
-	{
-		//至少把header合并成一个buff
-		buff.mergeBuffers();
-
-		auto data = buff.getBufferPointer();
-
-		const char * p = strnstr(data.first, "\r\n\r\n", data.second);
-		if(p == NULL)
-		{
-			return false;
-		}
-
-		_headLength = p - data.first + 4;
-
-		_iTmpContentLength = parseResponseHeaderString(data.first, data.first + data.second + 2);
-
-		//304的返回码中头里本来就没有Content-Length,也不会有数据体,头收全了就是真正的收全了
-		if ( (204 == _status) || (304 == _status) )
-		{
-			return true;
-		}
-//
-//		http_header_type::const_iterator it = _headers.find("Content-Length");
-//		if (it != _headers.end())
-//		{
-//			_iTmpContentLength = getContentLength();
-//		}
-//		else
-//		{
-//			//没有指明ContentLength, 接收到服务器关闭连接
-//			_iTmpContentLength = -1;
-//		}
-
-		buff.moveHeader(_headLength);
-
-		//重定向就认为成功了
-		if ((_status == 301 || _status == 302) && hasHeader("Location"))
-		{
-			return true;
-		}
-//		return true;
-
-		//是否是chunk编码
-		_bIsChunked = checkHeader("Transfer-Encoding", "chunked");
-//		_bIsChunked = (getHeader("Transfer-Encoding") == "chunked");
-		if(_bIsChunked) {
-			//删除头部里面
-			eraseHeader("Transfer-Encoding");
-		}
-	}
-
-	if (_bIsChunked)
-	{
-		while (true)
-		{
-			const static string sep = "\r\n";
-
-			auto sit = std::search(buff.begin(), buff.end(), sep.c_str(), sep.c_str() + sep.size());
-
-			if (sit == buff.end())
-			{
-				return false;
-			}
-
-			string header = buff.iteratorToIterator<string>(buff.begin(), sit);
-
-			int iChunkSize    = strtol(header.c_str(), NULL, 16);
-
-			if (iChunkSize <= 0)
-			{
-				break;     //所有chunk都接收完毕
-			}
-
-			if (buff.getBufferLength() < header.size() + 2 + (size_t)iChunkSize + 2)
-			{
-				//没有接收完整的chunk
-				return false;
-			}
-
-			//接收到一个完整的chunk了
-			buff.moveHeader(header.size() + 2);
-			addContent(buff.getHeader<string>(iChunkSize));
-
-			//删除一个chunk
-			buff.moveHeader(iChunkSize + 2);
-		}
-
-		buff.clearBuffers();
-
-		//接收到buffer长度设置好
-		setContentLength(_iRecvContentLength);
-
-		return true;
-	}
-	else
-	{
-		if (_iTmpContentLength == 0)
-		{
-			//header长度为0, 但是有body数据
-			addContent(buff.getBuffersString());
-
-			buff.clearBuffers();
-
-			setContentLength(_iRecvContentLength);
-
-			return true;
-		}
-		else if (_iTmpContentLength == (size_t) - 1)
-		{
-			//304的返回码中头没有Content-Length,不会有数据体
-			if (_status == 304 || _status == 302)
-			{
-				return true;
-			}
-
-			//header中没长度, 但是有body数据
-			addContent(buff.getBuffersString());
-
-			buff.clearBuffers();
-
-			setContentLength(_iRecvContentLength);
-
-			return true;
-		}
-		else
-		{
-			//头部有长度, 接收到长度大于头部为止
-			addContent(buff.getBuffersString());
-
-			buff.clearBuffers();
-
-			//头部的长度小于接收的内容, 还需要继续增加解析后续的buffer
-			if (_iTmpContentLength > _iRecvContentLength)
-				return false;
-
-			return true;
-		}
-	}
-
-	return true;
-}
-
-bool TC_HttpResponse::decode(const string &sBuffer)
-{
-	return decode(sBuffer.c_str(), sBuffer.length());
-}
-
-bool TC_HttpResponse::decode(const char *sBuffer, size_t iLength)
-{
-    assert(sBuffer != NULL);
-
-	const char *p = strstr(sBuffer, "\r\n\r\n");
-    if ( p == NULL)
-    {
-        return false;
-    }
-
-    //解析头部
-//    parseResponseHeader(sBuffer, p + 2);
-	_iTmpContentLength = parseResponseHeaderString(sBuffer, p + 2);
-
-	//304的返回码中头里本来就没有Content-Length,也不会有数据体,头收全了就是真正的收全了
-    if ( (204 == _status) || (304 == _status) )
-    {
-        return true;
-    }
-//
-//    http_header_type::const_iterator it = _headers.find("Content-Length");
-//    if (it != _headers.end())
-//    {
-//        _iTmpContentLength = getContentLength();
-//    }
-//    else
-//    {
-//        //没有指明ContentLength, 接收到服务器关闭连接
-//        _iTmpContentLength = -1;
-//    }
-
-    _headLength = p - sBuffer + 4;
-
-	sBuffer += _headLength;
-
-    //重定向就认为成功了
-    if ((_status == 301 || _status == 302) && hasHeader("Location"))
-    {
-        return true;
-    }
-
-    //是否是chunk编码
-	_bIsChunked = checkHeader("Transfer-Encoding", "chunked");
-    if(_bIsChunked) {
-	    //删除头部里面
-	    eraseHeader("Transfer-Encoding");
-    }
-
-//	_bIsChunked = (getHeader("Transfer-Encoding") == "chunked");
-
-    //删除头部里面
-//    eraseHeader("Transfer-Encoding");
-
-    if (_bIsChunked)
-    {
-        while (true)
-        {
-	        p = strstr(sBuffer, "\r\n");
-            if (p == NULL)
-                return false;
-
-            size_t pos = p - sBuffer;
-
-            //查找当前chunk的大小
-			string sChunkSize;
-	        sChunkSize.insert(sChunkSize.end(), sBuffer, p);
-            int iChunkSize    = strtol(sChunkSize.c_str(), NULL, 16);
-
-            if (iChunkSize <= 0)     break;     //所有chunk都接收完毕
-
-            if (strlen(sBuffer) < pos + 2 + (size_t)iChunkSize + 2)
-            {
-                //没有接收完整的chunk
-                return false;
-            }
-
-            //接收到一个完整的chunk了
-            addContent(p + 2, iChunkSize);
-
-            //删除一个chunk
-            sBuffer += pos + 2 + iChunkSize + 2;
-        }
-
-        //接收到buffer长度设置好
-        setContentLength(_iRecvContentLength);
-
-        return true;
-    }
-    else
-    {
-        if (_iTmpContentLength == 0)
-        {
-            //header长度为0, 但是有body数据
-            addContent(sBuffer);
-
-            setContentLength(_iRecvContentLength);
-
-            return true;
-        }
-        else if (_iTmpContentLength == (size_t) - 1)
-        {
-            //304的返回码中头没有Content-Length,不会有数据体
-            if (_status == 304 || _status == 302)
-            {
-                return true;
-            }
-
-            //header中没长度, 但是有body数据
-            addContent(sBuffer);
-
-            setContentLength(_iRecvContentLength);
-        }
-        else
-        {
-            //头部有长度, 接收到长度大于头部为止
-            addContent(sBuffer);
-
-            //头部的长度小于接收的内容, 还需要继续增加解析后续的buffer
-            if (_iTmpContentLength <= _iRecvContentLength)
-                return true;
-        }
-    }
-
-    //body内容长度为0或者没有content-length  且 非chunk模式, 则认为包收全了, 直接返回
-    if ((_iTmpContentLength == 0 || _iTmpContentLength == (size_t) - 1) && !_bIsChunked)
-        return true;
-
-    return (getContentLength() + getHeadLength() <= iLength);
-}
-
-string TC_HttpResponse::encode() const
-{
-	string sRet;
-	sRet.reserve(128);
-
-    sRet += _version;
-    sRet += " ";
-    sRet += TC_Common::tostr(_status);
-    sRet += " ";
-    sRet += _about;
-    sRet += "\r\n";
-    genHeader(sRet);
-    sRet += "\r\n";
-    sRet += _content;
-
-	return sRet;
-}
-
-void TC_HttpResponse::encode(vector<char> &buffer) const
-{
-    buffer.clear();
-
-	string s = encode();
-
-    buffer.resize(s.length());
-    memcpy(buffer.data(), s.c_str(), s.length());
-}
-
-void TC_HttpResponse::setResponse(int status, const string& about, const string& body)
-{
-    _status = status;
-    _about  = about;
-    _content = body;
-
-    /*stringstream os;
-
-    os << _version << " " << _status << " " << _about;
-
-    _headerLine = os.str();*/
-    _headerLine = "";
-    _headerLine += _version;
-    _headerLine += " ";
-    _headerLine += TC_Common::tostr(_status);
-    _headerLine += " ";
-    _headerLine += _about;
-
-    setHeader("Content-Length", TC_Common::tostr(_content.length()));
-}
-
-void TC_HttpResponse::setResponse(int status, const string& about, const char *sBuffer, size_t iLength)
-{
-    _status = status;
-    _about  = about;
-
-    /*stringstream os;
-
-    os << _version << " " << _status << " " << _about;
-
-    _headerLine = os.str();*/
-    _headerLine = "";
-    _headerLine += _version;
-    _headerLine += " ";
-    _headerLine += TC_Common::tostr(_status);
-    _headerLine += " ";
-    _headerLine += _about;
-
-    if (sBuffer != NULL && iLength > 0)
-    {
-        _content.assign(sBuffer, iLength);
-    }
-    else
-    {
-        _content.clear();
-    }
-
-
-    setHeader("Content-Length", TC_Common::tostr(_content.length()));
-}
-
-void TC_HttpResponse::setResponse(const char *sBuffer, size_t iLength)
-{
-    setResponse(200, "OK", sBuffer, iLength);
-}
-
-/********************* TC_HttpRequest ***********************/
-
-void TC_HttpRequest::reset()
-{
-    TC_Http::reset();
-
-    _httpURL.clear();
-}
-//
-//const char * TC_HttpRequest::requestType2str(int iRequestType) const
-//{
-//    if(iRequestType == REQUEST_GET)
-//    {
-//        return "GET";
-//    }
-//    else if(iRequestType == REQUEST_HEAD)
-//    {
-//        return "HEAD";
-//    }
-//    else if(iRequestType == REQUEST_POST)
-//    {
-//        return "POST";
-//    }
-//    else if(iRequestType == REQUEST_OPTIONS)
-//    {
-//        return "OPTIONS";
-//    }
-//    else if(iRequestType == REQUEST_PUT)
-//    {
-//        return "PUT";
-//    }
-//    else if(iRequestType == REQUEST_DELETE)
-//    {
-//        return "DELETE";
-//    }
-//    else if(iRequestType == REQUEST_PATCH)
-//    {
-//        return "PATCH";
-//    }
-////    assert(true);
-//    return "";
-//}
-
-vector<string> TC_HttpRequest::getCookie()
-{
-    vector<string> v;
-
-    http_header_type::const_iterator itEnd = _headers.end();
-
-    for ( http_header_type::const_iterator it = _headers.begin(); it != itEnd; ++it)
-    {
-        if (it->first == "Cookie")
-        {
-            v.push_back(it->second);
-        }
-    }
-
-	return v;
-}
-
-void TC_HttpRequest::parseURL(const string& sUrl)
-{
-    _httpURL.parseURL(sUrl);
-
-    //设置Host
-    if (!hasHeader("Host"))
-    {
-        string sPort = _httpURL.isDefaultPort() ? "" : ":" + _httpURL.getPort();
-
-        //缺省端口可以不用放进去
-        setHost(_httpURL.getDomain() + sPort);
-    }
-}
-
-void TC_HttpRequest::setRequest(const string& method, const string &sUrl, const std::string& body, bool bNewCreateHost)
-{
-    // std::string lowMethod(method);
-    // std::transform(method.begin(), method.end(), lowMethod.begin(), ::tolower);
-
-    if (TC_Port::strncasecmp(method.c_str(), "GET", 3) == 0)
-        setGetRequest(sUrl, bNewCreateHost);
-    else if (TC_Port::strncasecmp(method.c_str(), "HEAD", 4) == 0)
-        setHeadRequest(sUrl, bNewCreateHost);
-    else if (TC_Port::strncasecmp(method.c_str(),  "POST", 4) == 0)
-        setPostRequest(sUrl, body, bNewCreateHost);
-    else if (TC_Port::strncasecmp(method.c_str(),  "PUT", 3) == 0)
-        setPutRequest(sUrl, body, bNewCreateHost);
-    else if (TC_Port::strncasecmp(method.c_str(),  "DELETE", 6) == 0)
-        setDeleteRequest(sUrl, body, bNewCreateHost);
-    else if (TC_Port::strncasecmp(method.c_str(),  "PATH", 5) == 0)
-        setPatchRequest(sUrl, body, bNewCreateHost);
-}
-
-void TC_HttpRequest::setGetRequest(const string &sUrl, bool bNewCreateHost)
-{
-    if (bNewCreateHost)
-    {
-        eraseHeader("Host");
-    }
-
-    parseURL(sUrl);
-
-    _requestType    = REQUEST_GET;
-
-    _content        = "";
-
-    eraseHeader("Content-Length");
-}
-
-void TC_HttpRequest::setHeadRequest(const string &sUrl, bool bNewCreateHost)
-{
-    if (bNewCreateHost)
-    {
-        eraseHeader("Host");
-    }
-
-    parseURL(sUrl);
-
-    _requestType    = REQUEST_HEAD;
-
-    _content        = "";
-
-    eraseHeader("Content-Length");
-}
-
-void TC_HttpRequest::setPostRequest(const string &sUrl, const string &sPostBody, bool bNewCreateHost)
-{
-    if (bNewCreateHost)
-    {
-        eraseHeader("Host");
-    }
-
-    parseURL(sUrl);
-
-    _requestType    = REQUEST_POST;
-
-    _content        = sPostBody;
-
-    setHeader("Content-Length", TC_Common::tostr(_content.length()));
-}
-
-void TC_HttpRequest::setOptionsRequest(const string &sUrl, bool bNewCreateHost)
-{
-    if (bNewCreateHost)
-    {
-        eraseHeader("Host");
-    }
-
-    parseURL(sUrl);
-
-    _requestType    = REQUEST_OPTIONS;
-
-    _content        = "";
-
-    eraseHeader("Content-Length");
-}
-
-void TC_HttpRequest::setPostRequest(const string &sUrl, const char *sBuffer, size_t iLength, bool bNewCreateHost)
-{
-    assert(sBuffer != NULL);
-
-    if (bNewCreateHost)
-    {
-        eraseHeader("Host");
-    }
-
-    parseURL(sUrl);
-
-    _requestType    = REQUEST_POST;
-
-    if (iLength > 0)
-    {
-        _content.assign(sBuffer, iLength);
-    }
-    else
-    {
-        _content.clear();
-    }
-
-    setHeader("Content-Length", TC_Common::tostr(_content.length()));
-}
-
-
-void TC_HttpRequest::setPutRequest(const string &sUrl, const string &sPostBody, bool bNewCreateHost )
-{
-    if(bNewCreateHost)
-    {
-        eraseHeader("Host");
-    }
-
-    parseURL(sUrl);
-
-    _requestType    = REQUEST_PUT;
-
-    _content        = sPostBody;
-
-    setHeader("Content-Length", TC_Common::tostr(_content.length()));
-}
-
-void TC_HttpRequest::setPatchRequest(const string &sUrl, const string &sPostBody, bool bNewCreateHost )
-{
-    if(bNewCreateHost)
-    {
-        eraseHeader("Host");
-    }
-
-    parseURL(sUrl);
-
-    _requestType    = REQUEST_PATCH;
-
-    _content        = sPostBody;
-
-    setHeader("Content-Length", TC_Common::tostr(_content.length()));
-}
-
-
-void TC_HttpRequest::setDeleteRequest(const string &sUrl, const string &sPostBody, bool bNewCreateHost )
-{
-    if(bNewCreateHost)
-    {
-        eraseHeader("Host");
-    }
-
-    parseURL(sUrl);
-
-    _requestType    = REQUEST_DELETE;
-
-    _content        = sPostBody;
-
-    setHeader("Content-Length", TC_Common::tostr(_content.length()));
-
-}
-
-string TC_HttpRequest::encode()
-{
-	string sRet;
-	sRet.reserve(128);
-	if(_requestType == REQUEST_GET || _requestType == REQUEST_OPTIONS || _requestType == REQUEST_HEAD)
-    {
-        sRet += getMethod();//(_requestType);
-        sRet += " ";
-        sRet += _httpURL.getRequest();
-        sRet += " HTTP/1.1\r\n";
-        genHeader(sRet);
-        sRet += "\r\n";
-    }
-    else if(_requestType == REQUEST_POST || _requestType == REQUEST_PUT || _requestType == REQUEST_PATCH || _requestType == REQUEST_DELETE)
-    {
-        setContentLength(_content.length());
-        sRet += getMethod();//requestType2str(_requestType);
-        sRet += " ";
-        sRet += _httpURL.getRequest();
-        sRet += " HTTP/1.1\r\n";
-	    genHeader(sRet);
-        sRet += "\r\n";
-        sRet += _content;
-    }
-	return sRet;
-}
-
-void TC_HttpRequest::encode(vector<char> &sRet)
-{
-	string s = encode();
-	sRet.resize(s.length());
-    memcpy(sRet.data(), s.c_str(), s.length());
-}
-
-void TC_HttpRequest::encode(TC_NetWorkBuffer &buff)
-{
-	buff.addBuffer(std::move(encode()));
-}
-
-bool TC_HttpRequest::decode(const string &sBuffer)
-{
-    return decode(sBuffer.c_str(), sBuffer.length());
-}
-
-bool TC_HttpRequest::decode(const vector<char> &sBuffer)
-{
-	return decode(sBuffer.data(), sBuffer.size());
-}
-
-bool TC_HttpRequest::decode(const char *sBuffer, size_t iLength)
-{
-    assert(sBuffer != NULL);
-
-	const char *p = strnstr(sBuffer, " ", 10);
-	if(p == NULL)
-	{
-		throw runtime_error("[TC_HttpRequest::decode] http protocol parse error");
-	}
-
-	auto it = TC_Http::HEADER.find(string(sBuffer, p - sBuffer));
-    if(it == TC_Http::HEADER.end())
-    {
-        throw runtime_error("[TC_HttpRequest::decode] protocol not support ");
-    }
-
-    p = strstr(sBuffer, "\r\n\r\n");
-    if (p == NULL)
-    {
-        return false;
-    }
-
-	_requestType = it->second;
-
-    parseRequestHeader(sBuffer, p);
-
-	_headLength = p - sBuffer + 4;
-
-    bool bChunk = checkHeader("Transfer-Encoding", "chunked"); //(getHeader("Transfer-Encoding") == "chunked");
-
-    int iChunkSuffixLen = 0;
-
-    if (bChunk)
-    {
-        p = sBuffer + _headLength;
-//        string sTmp(sBuffer + _headLength, iLength - _headLength);
-        while (true)
-        {
-//            string::size_type pos   = sTmp.find("\r\n");
-	        const char *pos = strstr(p, "\r\n");
-            if (pos == NULL)
-                return false;
-
-            //查找当前chunk的大小
-//			string sChunkSize = sTmp.substr(0, pos);
-	        string sChunkSize(p, pos - p);
-//	        sTmp.substr(0, pos);
-            int iChunkSize    = strtol(sChunkSize.c_str(), NULL, 16);
-
-            iChunkSuffixLen = iChunkSuffixLen + sChunkSize.length();
-            if (iChunkSize <= 0)
-            {
-                iChunkSuffixLen = iChunkSuffixLen + 4;
-                break;      //所有chunk都接收完毕
-            }
-//            if (sTmp.length() >= pos + 2 + (size_t)iChunkSize + 2)  //接收到一个完整的chunk了
-            if ((sBuffer+iLength-p) >= (pos - p) + 2 + iChunkSize + 2)  //接收到一个完整的chunk了
-            {
-                //获取一个chunk的内容
-//                _content += sTmp.substr(pos + 2, iChunkSize);
-	            _content.append(pos + 2, iChunkSize);
-
-	            //删除一个chunk
-//				sTmp = sTmp.substr(pos + 2 + iChunkSize + 2);
-				p = pos + 2 + iChunkSize + 2;
-                iChunkSuffixLen = iChunkSuffixLen + 4;
-            }
-            else
-            {
-                //没有接收完整的chunk
-                return false;
-            }
-
-            setContentLength(getContent().length());
-        }
-    }
-    else
-    {
-        _content.assign((sBuffer + _headLength), iLength - _headLength);
-    }
-
-    return (getContentLength() + getHeadLength() + iChunkSuffixLen == iLength);
-}
-
-bool TC_HttpRequest::checkRequest(TC_NetWorkBuffer &buff)
-{
-	buff.mergeBuffers();
-
-	return checkRequest(buff.getBufferPointer().first, buff.getBufferLength());
-//
-//	size_t *headerLength = (size_t *)buff.getContextData();
-//
-//	if(headerLength == NULL)
-//	{
-//		headerLength = new size_t(0);
-//
-//		buff.setContextData(headerLength, [=]{ delete headerLength;});
-//	}
-//
-//	if(*headerLength == 0)
-//	{
-//		//header还没有解析出来, 合并buffer
-//		buff.mergeBuffers();
-//
-//		auto data = buff.getBufferPointer();
-//
-//		const char *p = strnstr(data.first, " ", 10);
-//		if(p == NULL)
-//		{
-//			throw runtime_error("[TC_HttpRequest::checkRequest] http protocol parse error");
-//		}
-//
-//		auto it = TC_Http::HEADER.find(string(data.first, p - data.first));
-//		if(it == TC_Http::HEADER.end())
-//		{
-//			throw runtime_error("[TC_HttpRequest::checkRequest] protocol not support");
-//		}
-//
-////		if (buff.getBufferLength() < 10)
-////			return false;
-//
-////		auto data = buff.getBufferPointer();
-////		if (TC_Port::strncasecmp(data.first, "GET ", 4) != 0 &&
-////			TC_Port::strncasecmp(data.first, "POST ", 5) != 0 &&
-////			TC_Port::strncasecmp(data.first, "PUT ", 4) != 0 &&
-////			TC_Port::strncasecmp(data.first, "PATCH ", 6) != 0 &&
-////			TC_Port::strncasecmp(data.first, "OPTIONS ", 8) != 0 &&
-////			TC_Port::strncasecmp(data.first, "PRI ", 4) != 0 &&
-////			TC_Port::strncasecmp(data.first, "DELETE ", 7) != 0 &&
-////			TC_Port::strncasecmp(data.first, "HEAD ", 5)) {
-////			throw runtime_error(
-////				"[TC_HttpRequest::decode] protocol not support, only support GET HEAD POST PUT PATCH DELETE and OPTIONS ");
-////		}
-//
-////		string sep = "\r\n\r\n";
-////
-////		auto sit = buff.find(sep.c_str(), sep.size());
-////		if (sit == buff.end()) {
-////			return false;
-////		}
-//
-//		p = strnstr(data.first, "\r\n\r\n", data.second);
-//		if(p == NULL) {
-//			return false;
-//		}
-//
-////		size_t pos = p ;
-//
-//		*headerLength = p - data.first + 4;
-//
-////		bool bChunk = false;
-//
-////		sep = "\r\n";
-//
-//		p = strnstr(data.first, "\r\n", data.second);
-//
-//		assert(p != NULL);
-////		if(p == NULL) {
-////			return false;
-////		}
-////
-////		auto it = std::search(buff.begin(), buff.end(), sep.c_str(), sep.c_str() + sep.size());
-////		if (it == buff.end()) {
-////			//first line
-////			return false;
-////		}
-//
-////		it = it + sep.size();
-//		//move to next line
-//		p += 2;
-//	}
-//
-//	bool bChunk = false;
-//
-//	size_t len = 0;
-//
-//	//找到\r\n\r\n之前的长度表示
-//	while (true)
-//	{
-//		size_t iMoveLen = it - buff.begin();
-//		if (iMoveLen >= iHeadLen)
-//		{
-//			break;
-//		}
-//
-//		auto lineItStart = it;
-//
-//		auto lineItEnd = std::search(lineItStart, buff.end(), sep.c_str(), sep.c_str() + sep.size());
-//
-//		if (lineItEnd != buff.end())
-//		{
-//			it = lineItEnd + sep.size();
-//
-//			std::function<bool(char, char)> cmp = [](char i, char j)
-//			{
-//				return toupper(i) == toupper(j);
-//			};
-//
-//			const char *TE = "Transfer-Encoding:";
-//
-//			auto itTE = std::search(lineItStart, lineItEnd, TE, TE + strlen(TE), cmp);
-//
-//			if (itTE != lineItEnd)
-//			{
-//				const char *CH = "chunked";
-//
-//				auto itCH = std::search(lineItStart + strlen(TE), lineItEnd, CH, CH + strlen(CH), cmp);
-//
-//				if (itCH != lineItEnd)
-//				{
-//					bChunk = true;
-//					break;
-//				}
-//			}
-//
-//			const char *CL = "Content-Length:";
-//
-//			auto itCL = std::search(lineItStart, lineItEnd, CL, CL + strlen(CL), cmp);
-//			if (itCL == lineItEnd)
-//			{
-//				continue;
-//			}
-//
-//			string contentLength;
-//			contentLength.resize(lineItEnd - lineItStart - strlen(CL));
-//			std::copy(lineItStart + strlen(CL), lineItEnd, contentLength.begin());
-//
-//			len = taf::TC_Common::strto<size_t>(TC_Common::trim(contentLength, " "));
-//		}
-//
-//	}
-//
-//	if (bChunk)
-//	{
-//		int remain_len = buff.getBufferLength() - iHeadLen;
-//		int move_len = 0;
-//
-//		auto it = sit + 4;
-//		while (true)
-//		{
-//			auto lineIt = std::search(it, buff.end(), sep.c_str(), sep.c_str() + sep.size());
-//			if ( lineIt == buff.end() )
-//			{
-//				return false;
-//			}
-//
-//			//查找当前chunk的大小
-//			string contentLength;
-//			contentLength.resize(lineIt - it);
-//			std::copy(it, lineIt, contentLength.begin());
-//
-//			int iChunkSize = strtol(contentLength.c_str(), NULL, 16);
-//			if (iChunkSize <= 0)
-//			{
-//				return true; //所有chunk都接收完毕
-//			}
-//
-//			move_len = (lineIt - it) + 2 + iChunkSize + 2;
-//			if ( remain_len >= move_len )  //接收到一个完整的chunk了
-//			{
-//				//移动到下一个chunk
-//				remain_len -= move_len;
-//				it = lineIt + 2 + iChunkSize + 2;
-//			}
-//			else
-//			{
-//				return false;
-//			}
-//		}
-//	}
-//	else if (len + pos + 4 <= buff.getBufferLength())
-//	{
-//		return true;
-//	}
-//
-//	return false;
-}
-
-bool TC_HttpRequest::checkRequest(const char* sBuffer, size_t iLen)
-{
-	if(iLen < 10)
-		return false;
-
-	const char *p = strnstr(sBuffer, " ", 10);
-	if(p == NULL)
-	{
-		throw runtime_error("[TC_HttpRequest::checkRequest] http protocol parse error");
-	}
-
-	auto it = TC_Http::HEADER.find(string(sBuffer, p - sBuffer));
-	if(it == TC_Http::HEADER.end())
-	{
-		throw runtime_error("[TC_HttpRequest::checkRequest] protocol not support: " + string(sBuffer, 8));
-	}
-//
-//    if(TC_Port::strncasecmp(sBuffer, "GET " ,4) !=0 &&
-//		TC_Port::strncasecmp(sBuffer, "POST " ,5) !=0 &&
-//		TC_Port::strncasecmp(sBuffer, "PUT " ,4) !=0 &&
-//		TC_Port::strncasecmp(sBuffer, "PATCH " ,6) !=0 &&
-//		TC_Port::strncasecmp(sBuffer, "OPTIONS " ,8) !=0 &&
-//		TC_Port::strncasecmp(sBuffer, "PRI " , 4) !=0 &&
-//		TC_Port::strncasecmp(sBuffer, "DELETE " , 7) !=0 &&
-//		TC_Port::strncasecmp(sBuffer, "HEAD " ,5))
-//   {
-//       throw runtime_error("[TC_HttpRequest::decode] protocol not support:" + string(sBuffer, 8));
-//   }
-
-    const char *header = strstr(sBuffer, "\r\n\r\n");
-    if ( header == NULL)
-    {
-        return false;
-    }
-
-	size_t pos = header - sBuffer;
-
-    size_t iHeadLen = pos + 4;
-
-	p =  strstr(sBuffer, "\r\n");
-	if(p == NULL)
-	{
-		//first line
-		return false;
-	}
-
-	p += 2;
-
-    bool bChunk = false;
-
-	size_t len  = 0;
-
-    //找到\r\n\r\n之前的长度表示
-    while (true)
-    {
-        size_t iMoveLen = p - sBuffer;
-        if ( iMoveLen >= iHeadLen )
-        {
-            break;
-        }
-
-        const char *line    = p;
-        const char *lineEnd = strstr(line, "\r\n");
-        if (lineEnd != NULL)
-        {
-	        p = lineEnd + 2;
-
-	        if (TC_Port::strncasecmp(line, "Transfer-Encoding:", 18) == 0)
-	        {
-		        string chunked = TC_Common::trim(string(line + 18, lineEnd));
-		        bChunk = (chunked == "chunked");
-		        if (bChunk) break;
-	        }
-	        else if (TC_Port::strncasecmp(line, "Content-Length:", 15) != 0)
-	        {
-		        continue;
-	        }
-	        else
-            {
-		        len = TC_Common::strto<size_t>(TC_Common::trim(string(line + 15, lineEnd), " "));
-	        }
-        }
-    }
-
-    if (bChunk)
-    {
-        int remain_len = iLen - iHeadLen;
-        int move_len = 0;
-        const char * pCur = header + 4;
-        while (true)
-        {
-            p = strstr(pCur , "\r\n");
-            if ( p == NULL )
-            {
-                return false;
-            }
-
-            //查找当前chunk的大小
-            int iChunkSize = strtol(string(pCur, p - pCur).c_str(), NULL, 16);
-            if (iChunkSize <= 0)
-            {
-                return true; //所有chunk都接收完毕
-            }
-
-            move_len = (p - pCur) + 2 + iChunkSize + 2;
-            if ( remain_len >= move_len )  //接收到一个完整的chunk了
-            {
-                //移动到下一个chunk
-                remain_len -= move_len;
-                pCur = p + 2 + iChunkSize + 2;
-            }
-            else
-            {
-                return false;
-            }
-        }
-    }
-    else  if (len + pos + 4 <= iLen)
-	{
-		return true;
-	}
-
-    return false;
-}
-
-size_t TC_Http::parseHeaderString(const char *beginIt, const char *headerIt, TC_Http::http_header_type &sHeader)
-{
-	size_t contentLength = -1;
-
-	sHeader.clear();
-
-	bool first      = true;
-	auto lineStartIt= beginIt;
-	bool isLastLine = false;
-
-	while (true)
-	{
-		auto it = strnstr(lineStartIt, "\r\n", headerIt - lineStartIt);
-		if(it == NULL)
-		{
-			it = headerIt;
-			isLastLine = true;
-		}
-
-		//first line ignore
-		if(!first)
-		{
-			auto itF = strnstr(lineStartIt, ":", it - lineStartIt);
-			if (itF != NULL)
-			{
-				while(*lineStartIt == ' ')
-					++lineStartIt;
-
-				const char *s = itF;
-				while(*s == ' ')
-					--s;
-
-				string name(lineStartIt, s - lineStartIt);
-
-				++itF;
-				while(*itF == ' ')
-					++itF;
-
-				s = it;
-				while(*s == ' ')
-					--s;
-
-				string value(itF, s-itF);
-
-				if (TC_Port::strncasecmp(name.c_str(), "Content-Length", 14) == 0)
-				{
-					contentLength = TC_Common::strto<size_t>(value);
-				}
-
-				sHeader.insert(multimap<string, string>::value_type(std::move(name), std::move(value)));
-			}
-		}
-		else
-		{
-			first = false;
-		}
-
- 		if (isLastLine)
-		{
-			break;
-		}
-
-		lineStartIt = it + 2;//sep.size();
-	}
-
-	return contentLength;
-}
-
-void TC_HttpRequest::parseRequestHeader(const char* szBuffer, const char *header)
-{
-	const char *p = strstr(szBuffer, "\r\n");
-
-	assert(p != NULL);
-
-//	string sep = " ";
-//	auto f1 = std::search(szBuffer, p, sep.c_str(), sep.c_str() + sep.size());
-	auto f1 = strnstr(szBuffer, " ", p - szBuffer);
-	if (f1 == p)
-	{
-		throw TC_HttpRequest_Exception("[TC_HttpRequest::parseRequestHeader] http request format error: " + string(szBuffer, p - szBuffer));
-	}
-
-//	auto f2 = std::search(f1 + 1, p, sep.c_str(), sep.c_str() + sep.size());
-	auto f2 = strnstr(f1 + 1, " ", p - f1 + 1);//std::search(f1 + 1, p, sep.c_str(), sep.c_str() + sep.size());
-	if (f2 == p || f1 >= f2)
-	{
-		throw TC_HttpRequest_Exception("[TC_HttpRequest::parseRequestHeader] http request format error: " + string(szBuffer, p - szBuffer));
-	}
-
-    //URL地址
-    string sURL(f1 + 1, f2 - f1 - 1 );
-
-    //HTTP协议版本
-	_version.assign(f2 + 1, p - f2 - 1);
-
-	parseHeaderString(szBuffer, header, _headers);
-
-    if (TC_Port::strncasecmp(f1 + 1, "https://", 8) != 0 )
-    {
-        if (TC_Port::strncasecmp(f1 + 1, "http://", 7) != 0 )
-        {
-            sURL = "http://" + getHost() + sURL;
-        }
-    }
-
-    parseURL(sURL);
-}
-
-void TC_HttpRequest::getHostPort(string &sDomain, uint32_t &iPort)
-{
-    sDomain = _httpURL.getDomain();
-
-    iPort   = TC_Common::strto<uint32_t>(_httpURL.getPort());
-}
-
-const string &TC_HttpRequest::getMethod() const
-{
-	auto it = TC_Http::HEADER_REVERSE.find(_requestType);
-	if(it != TC_Http::HEADER_REVERSE.end())
-	{
-		return it->second;
-	}
-	else
-	{
-		throw TC_HttpRequest_Exception("[TC_HttpRequest::setMethod] http request command error: " + TC_Common::tostr(_requestType));
-	}
-}
-
-void TC_HttpRequest::setMethod(const char * sMethod)
-{
-	auto it = TC_Http::HEADER.find(sMethod);
-	if(it != TC_Http::HEADER.end())
-	{
-		_requestType = it->second;
-	}
-	else
-	{
-		throw TC_HttpRequest_Exception("[TC_HttpRequest::setMethod] http request command error: " + string(sMethod));
-	}
-}
-
-void TC_HttpRequest::setPath(const char *path)
-{
-	_httpURL._sPath = path;
-}
-
-void TC_HttpRequest::setDomain(const char * sDomain)
-{
-	_httpURL._sDomain = sDomain;
-}
-
-void TC_HttpRequest::setScheme(const char * sScheme)
-{
-	_httpURL._sScheme = sScheme;
-}
-
-int TC_HttpRequest::doRequest(TC_TCPClient& tcpClient, TC_HttpResponse& stHttpRsp)
-{
-    //只支持短连接模式
-    setConnection("close");
-
-    string sSendBuffer = encode();
-
-    int iRet = tcpClient.send(sSendBuffer.c_str(), sSendBuffer.length());
-    if (iRet != TC_ClientSocket::EM_SUCCESS)
-    {
-        return iRet;
-    }
-
-    stHttpRsp.reset();
-
-    TC_NetWorkBuffer recvBuffer(NULL);
-
-    while (true)
-    {
-    	char buffer[8*1024];
-        size_t iRecvLen = sizeof(buffer);
-
-        iRet = tcpClient.recv(buffer, iRecvLen);
-
-        if (iRet == TC_ClientSocket::EM_SUCCESS)
-        {
-	        recvBuffer.addBuffer(buffer, iRecvLen);
-        }
-
-        switch (iRet)
-        {
-        case TC_ClientSocket::EM_SUCCESS:
-            if (stHttpRsp.incrementDecode(recvBuffer))
-            {
-                return TC_ClientSocket::EM_SUCCESS;
-            }
-            continue;
-        case TC_ClientSocket::EM_CLOSE:
-            stHttpRsp.incrementDecode(recvBuffer);
-            return TC_ClientSocket::EM_SUCCESS;
-        default:
-            return iRet;
-        }
-    }
-
-    assert(true);
-
-    return 0;
-
-}
-
-int TC_HttpRequest::doRequest(TC_HttpResponse &stHttpRsp, int iTimeout)
-{
-    //只支持短连接模式
-    setConnection("close");
-
-    string sSendBuffer = encode();
-
-    string sHost;
-    uint32_t iPort;
-
-    getHostPort(sHost, iPort);
-
-    TC_TCPClient tcpClient;
-    tcpClient.init(sHost, iPort, iTimeout);
-
-    int iRet = tcpClient.send(sSendBuffer.c_str(), sSendBuffer.length());
-    if (iRet != TC_ClientSocket::EM_SUCCESS)
-    {
-        return iRet;
-    }
-
-    stHttpRsp.reset();
-
-	TC_NetWorkBuffer recvBuffer(NULL);
-
-    while (true)
-    {
-	    char buffer[8*1024];
-	    size_t iRecvLen = sizeof(buffer);
-
-        iRet = tcpClient.recv(buffer, iRecvLen);
-
-        if (iRet == TC_ClientSocket::EM_SUCCESS)
-        {
-	        recvBuffer.addBuffer(buffer, iRecvLen);
-        }
-
-        switch (iRet)
-        {
-        case TC_ClientSocket::EM_SUCCESS:
-            if (stHttpRsp.incrementDecode(recvBuffer))
-            {
-                return TC_ClientSocket::EM_SUCCESS;
-            }
-            continue;
-        case TC_ClientSocket::EM_CLOSE:
-            stHttpRsp.incrementDecode(recvBuffer);
-            return TC_ClientSocket::EM_SUCCESS;
-        default:
-            return iRet;
-        }
-    }
-
-    assert(true);
-
-    return 0;
-}
-
-}
-
-
+#include "util/tc_http.h"
+#include "util/tc_port.h"
+#include "util/tc_common.h"
+#include "util/tc_clientsocket.h"
+#include "util/tc_network_buffer.h"
+#include <string.h>
+
+namespace tars
+{
+
+const char* strnstr(const char* s1, const char* s2, int pos1)
+{
+	int l1, l2;
+
+	l2 = strlen(s2);
+	if (!l2)
+		return (char *)s1;
+	l1 = strlen(s1);
+
+	pos1 = (pos1 > l1)?l1:pos1;
+
+	while (pos1 >= l2) {
+		pos1--;
+		if (!memcmp(s1, s2, l2))
+			return (char *)s1;
+		s1++;
+	}
+	return NULL;
+}
+
+unordered_map<string, int> TC_Http::HEADER = {
+	{"GET", TC_HttpRequest::REQUEST_GET},
+	{"POST", TC_HttpRequest::REQUEST_POST},
+	{"PUT", TC_HttpRequest::REQUEST_PUT},
+	{"PATCH", TC_HttpRequest::REQUEST_PATCH},
+	{"OPTIONS", TC_HttpRequest::REQUEST_OPTIONS},
+	{"PRI", TC_HttpRequest::REQUEST_PRI},
+	{"DELETE", TC_HttpRequest::REQUEST_DELETE},
+	{"HEAD", TC_HttpRequest::REQUEST_HEAD},
+};
+
+unordered_map<int, string> TC_Http::HEADER_REVERSE = {
+	{TC_HttpRequest::REQUEST_GET, "GET"},
+	{TC_HttpRequest::REQUEST_POST, "POST"},
+	{TC_HttpRequest::REQUEST_PUT, "PUT"},
+	{TC_HttpRequest::REQUEST_PATCH, "PATCH"},
+	{TC_HttpRequest::REQUEST_OPTIONS, "OPTIONS"},
+	{TC_HttpRequest::REQUEST_PRI, "PRI"},
+	{TC_HttpRequest::REQUEST_DELETE, "DELETE"},
+	{TC_HttpRequest::REQUEST_HEAD, "HEAD"},
+};
+
+
+bool TC_Http::CmpCase::operator()(const string &s1, const string &s2) const
+{
+    if (TC_Port::strcasecmp(s1.c_str(), s2.c_str()) < 0)
+    {
+        return true;
+    }
+    else
+    {
+        return false;
+    }
+}
+
+bool TC_URL::isValid() const
+{
+    return !_sURL.empty();
+}
+
+string TC_URL::getURL() const
+{
+    return _sURL;
+}
+
+string TC_URL::type2String() const
+{
+    switch (_iURLType)
+    {
+    case HTTP:
+        return "http";
+    case HTTPS:
+        return "https";
+    case FTP:
+        return "ftp";
+    }
+
+    return "http";
+}
+
+string TC_URL::getDefaultPort() const
+{
+    switch (_iURLType)
+    {
+    case HTTP:
+        return "80";
+    case HTTPS:
+        return "443";
+    case FTP:
+        return "21";
+    }
+
+    return "80";
+}
+
+bool TC_URL::isDefaultPort() const
+{
+    return _sPort == getDefaultPort();
+}
+
+string TC_URL::toURL()
+{
+    _sURL.clear();
+
+    _sURL = _sScheme;
+    _sURL += "://";
+
+    if (!_sUser.empty())
+        _sURL += _sUser;
+
+    if (!_sUser.empty() && !_sPass.empty())
+    {
+        _sURL += ":";
+        _sURL += _sPass;
+    }
+
+    if (!_sUser.empty())
+        _sURL += "@";
+
+    _sURL += _sDomain;
+
+    if (!isDefaultPort())
+    {
+        _sURL += ":";
+        _sURL += _sPort;
+    }
+
+    _sURL += getRequest();
+
+    return _sURL;
+}
+
+string TC_URL::getRequest() const
+{
+    string sURL;
+
+    if (!_sPath.empty())
+        sURL += _sPath;
+
+    if (!_sQuery.empty())
+        sURL += "?" + _sQuery;
+
+    if (!_sRef.empty())
+        sURL += "#" + _sRef;
+
+    return sURL;
+}
+
+bool TC_URL::parseURL(const string &originRequest)
+{
+//    string originRequest  = TC_Common::trim(sURL, " ");
+
+    if (originRequest.empty())
+    {
+        return false;
+    }
+
+    clear();
+
+    int iPos = 0;
+
+    if (TC_Port::strncasecmp(originRequest.c_str(), "http://" , 7) == 0)
+    {
+        //http开头
+        _iURLType  = HTTP;
+        iPos = 7;
+        _sScheme = "http";
+    }
+    else if (TC_Port::strncasecmp(originRequest.c_str(), "https://" , 8) == 0)
+    {
+        //https开头
+        _iURLType  = HTTPS;
+        iPos = 8;
+        _sScheme = "https";
+    }
+    else if (TC_Port::strncasecmp(originRequest.c_str(), "ftp://", 6) == 0)
+    {
+        //ftps开头
+        _iURLType  = FTP;
+        iPos = 6;
+        _sScheme = "ftp";
+    }
+    else
+    {
+        //默认用http
+        _iURLType  = HTTP;
+        iPos = 0;
+        _sScheme = "http";
+    }
+
+    string::size_type index            = originRequest.find("/", iPos);
+    string::size_type nQuestionIndex   = originRequest.find("?", iPos);
+    string::size_type nNumbersignIndex = originRequest.find("#", iPos);
+
+    string  sUrlAuthority;
+    string  sUrlPath;
+
+    if (nQuestionIndex < index)
+    {
+		sUrlAuthority = originRequest.substr(iPos, nQuestionIndex - iPos);
+
+        sUrlPath += '/';
+        sUrlPath += originRequest.substr(nQuestionIndex);
+    }
+    else if (nNumbersignIndex < index)
+    {
+		sUrlAuthority = originRequest.substr(iPos, nNumbersignIndex - iPos);
+
+        sUrlPath += '/';
+        sUrlPath += originRequest.substr(nNumbersignIndex);
+    }
+    else
+    {
+        if (index == string::npos)
+        {
+			sUrlAuthority = originRequest.substr(iPos, index);
+            sUrlPath = "";
+        }
+        else
+        {
+			sUrlAuthority = originRequest.substr(iPos, index - iPos);
+			sUrlPath = originRequest.substr(index);
+        }
+    }
+
+    //////解析Authority
+    index = sUrlAuthority.find("@");
+    if (index != string::npos)
+    {
+		_sUser = sUrlAuthority.substr(0, index);
+		_sDomain = sUrlAuthority.substr(index + 1);
+    }
+    else
+    {
+        _sDomain    = sUrlAuthority;
+    }
+
+    //////解析User:Pass
+    index = _sUser.find(":");
+    if (index != string::npos)
+    {
+		_sPass = _sUser.substr(index + 1);
+		_sUser = _sUser.substr(0, index);
+    }
+
+    //////解析Host:Port
+    index = _sDomain.find(":");
+    if (index != string::npos)
+    {
+		_sPort = _sDomain.substr(index + 1);
+
+		_sDomain = _sDomain.substr(0, index);
+    }
+    else
+    {
+        _sPort      = getDefaultPort();
+    }
+
+    //////解析Path Query Ref
+    index = sUrlPath.find("?");
+    if (index != string::npos)
+    {
+		_sPath = sUrlPath.substr(0, index);
+		_sQuery = sUrlPath.substr(index + 1);
+
+        index = _sQuery.rfind("#");
+        if (index != string::npos)
+        {
+			_sRef = _sQuery.substr(index + 1);
+			_sQuery = _sQuery.substr(0, index);
+        }
+    }
+    else
+    {
+        _sPath      = sUrlPath;
+        _sQuery     = "";
+
+        index = _sPath.rfind("#");
+        if (index != string::npos)
+        {
+			_sRef = _sPath.substr(index + 1);
+			_sPath = _sPath.substr(0, index);
+        }
+    }
+
+    if (_sPath.empty())
+    {
+        _sPath = "/";
+    }
+
+    toURL();
+
+    //域名或者IP必须包含一个点
+    if (_sDomain.find(".") == string::npos)
+    {
+        return false;
+    }
+
+    return true;
+}
+
+void TC_URL::specialize()
+{
+    //规整化路径
+    /*string sUrlPath = simplePath(getPath());
+
+    _fragment["path"]   = sUrlPath;*/
+    _sPath = simplePath(getPath());
+
+    _sURL = toURL();
+}
+
+void TC_URL::clear()
+{
+    _sScheme = "";
+    _sUser = "";
+    _sPass = "";
+    _sDomain = "";
+    _sPort = "";
+    _sPath = "";
+    _sQuery = "";
+    _sRef = "";
+
+    _sURL.clear();
+}
+
+string TC_URL::getScheme() const
+{
+    return _sScheme;
+}
+
+string TC_URL::getUserName() const
+{
+    return _sUser;
+}
+
+string TC_URL::getPassword() const
+{
+    return _sPass;
+}
+
+string TC_URL::getDomain() const
+{
+    return _sDomain;
+}
+
+string TC_URL::getPort() const
+{
+    return _sPort;
+}
+
+string TC_URL::getPath() const
+{
+    return _sPath;
+}
+
+string TC_URL::getQuery() const
+{
+    return _sQuery;
+}
+
+string TC_URL::getRef() const
+{
+    return _sRef;
+}
+
+string TC_URL::getRelativePath() const
+{
+    string sURL = getPath();
+
+    string::size_type pos;
+
+
+    pos   = sURL.rfind("/");
+
+    if (pos == string::npos)
+    {
+        return "/";
+    }
+    else
+    {
+		return sURL.substr(0, pos + 1);
+    }
+}
+
+string TC_URL::getRootPath() const
+{
+    string sURL = _sScheme;
+    sURL += "://";
+
+    if (!_sUser.empty())
+        sURL += _sUser;
+
+    if (!_sUser.empty() && !_sPass.empty())
+    {
+        sURL += ":";
+        sURL += _sPass;
+    }
+
+    if (!_sUser.empty())
+        sURL += "@";
+
+    sURL += _sDomain;
+
+    if (!isDefaultPort())
+    {
+        sURL += ":";
+        sURL += _sPort;
+    }
+
+    sURL += "/";
+
+	return sURL;
+}
+
+TC_URL TC_URL::buildWithRelativePath(const string &sRelativePath) const
+{
+    string sURL;
+
+    if (!sRelativePath.empty() && sRelativePath[0] == '/')
+    {
+        //如果链接是用"/"开头的相对地址,那么应该用Host+相对地址
+		sURL = sRelativePath.substr(1); 
+    }
+    else if (sRelativePath[0] == '#')
+    {
+        //#
+		sURL = getPath().substr(1);
+
+        if (!getQuery().empty())
+            sURL += "?" + getQuery();
+
+        sURL += sRelativePath;
+
+    }
+    else
+    {
+        //相对地址
+        sURL = getRelativePath().substr(1) + sRelativePath;
+    }
+
+    sURL = getRootPath() + simplePath("/" + sURL).substr(1);
+
+    TC_URL url;
+
+    url.parseURL(sURL);
+
+	return url;
+}
+
+string TC_URL::simplePath(const string &sPath) const
+{
+    //所有./都去掉
+    size_t pos      = 0;
+    string sNewPath = sPath;
+
+    while (true)
+    {
+        size_t dotPos = sNewPath.find("./", pos);
+
+        if (dotPos != string::npos)
+        {
+            if ((dotPos == 0) || (sNewPath.at(dotPos - 1) == '/'))
+            {
+                sNewPath.erase(dotPos, 2);
+            }
+            else
+            {
+                pos = dotPos + 2;
+            }
+        }
+        else
+        {
+            break;
+        }
+    }
+
+    //如果路径是以.结尾的, 则.去掉
+    if (((sNewPath.length() >= 2) && (sNewPath.substr(sNewPath.length() - 2) == "/.")) || (sNewPath == "."))
+    {
+        sNewPath.erase(sNewPath.length() - 1);
+    }
+
+    //处理/../的形式
+    pos = 0;
+    size_t startPos = 0;
+
+    while (1)
+    {
+        size_t slashDot = sNewPath.find("/../", pos);
+
+        if (slashDot != string::npos)
+        {
+            if (0 == slashDot)
+            {
+                sNewPath.erase(0, 3);
+                continue;
+            }
+
+            if ( (slashDot > 1) && (sNewPath.substr(slashDot - 2, 2) == "..") )
+            {
+                pos = slashDot + 4;
+                continue;
+            }
+
+            startPos = sNewPath.rfind('/', slashDot - 1);
+
+            if (startPos == string::npos) startPos = 0;
+
+            sNewPath.erase(startPos, slashDot + 4 - startPos - 1);
+        }
+        else
+        {
+            break;
+        }
+    }
+
+    //处理/..结尾的情况
+    if ((sNewPath.size() >= 3) && (sNewPath.substr(sNewPath.size() - 3, 3) == "/.."))
+    {
+        size_t slashDot = sNewPath.size() - 3;
+        if (!((slashDot > 1) && (sNewPath.substr(slashDot - 2, 2) == "..")))
+        {
+            startPos = sNewPath.rfind ('/', slashDot - 1);
+            if (startPos == string::npos) startPos = 0;
+            sNewPath.erase (startPos + 1);
+        }
+    }
+
+	return sNewPath;
+}
+
+////////////////////////////////////////////////////////////////////
+
+void TC_Http::setHeader(const string &sHeadName, const string &sHeadValue)
+{
+    //Set-Cookie和Cookie可以有多个头
+    const char * pStr1 = "SET-COOKIE";
+    const char * pStr2 = "COOKIE";//原则上COOKIE只有一个,担心有兼容性问题,保留
+    if ((TC_Port::strcasecmp(sHeadName.c_str(), pStr1) != 0) && (TC_Port::strcasecmp(sHeadName.c_str(), pStr2) != 0))
+    {
+        _headers.erase(sHeadName);
+    }
+
+    _headers.insert(multimap<string, string>::value_type(sHeadName, sHeadValue));
+}
+
+bool TC_Http::hasHeader(const char *sHeader) const
+{
+	http_header_type::const_iterator it = _headers.find(sHeader);
+	if (it == _headers.end())
+	{
+		return false;
+	}
+
+	return true;
+}
+
+bool TC_Http::checkHeader(const char *sHeader, const char *value) const
+{
+	http_header_type::const_iterator it = _headers.find(sHeader);
+	if (it == _headers.end())
+	{
+		return false;
+	}
+
+	return TC_Port::strcasecmp(it->second.c_str(), value) == 0;
+}
+
+string TC_Http::getHeader(const string& sHeader) const
+{
+    http_header_type::const_iterator it = _headers.find(sHeader);
+    if (it == _headers.end())
+    {
+        return "";
+    }
+
+    return it->second;
+}
+
+string TC_Http::getContentType() const
+{
+    return getHeader("Content-Type");
+}
+
+string TC_Http::getHost() const
+{
+    return getHeader("Host");
+}
+
+size_t TC_Http::getContentLength() const
+{
+    string s = getHeader("Content-Length");
+    if (s.empty())
+    {
+        return 0;
+    }
+
+    return TC_Common::strto<size_t>(s);
+}
+
+string TC_Http::genHeader() const
+{
+	string sHttpHeader;
+
+	for (http_header_type::const_iterator it = _headers.begin(); it != _headers.end(); ++it)
+	{
+		if (it->second != "")
+		{
+			sHttpHeader += it->first;
+			sHttpHeader += ": ";
+			sHttpHeader += it->second;
+			sHttpHeader += "\r\n";
+		}
+	}
+
+	return sHttpHeader;
+}
+
+void TC_Http::genHeader(string &sHttpHeader) const
+{
+    for (http_header_type::const_iterator it = _headers.begin(); it != _headers.end(); ++it)
+    {
+        if (it->second != "")
+        {
+            sHttpHeader += it->first;
+            sHttpHeader += ": ";
+            sHttpHeader += it->second;
+            sHttpHeader += "\r\n";
+        }
+    }
+}
+
+vector<string> TC_Http::getHeaderMulti(const string &sHeadName) const
+{
+    vector<string> v;
+
+    http_header_type::const_iterator itEnd = _headers.end();
+
+    for ( http_header_type::const_iterator it = _headers.begin(); it != itEnd; ++it)
+    {
+        if (TC_Port::strcasecmp(it->first.c_str(), sHeadName.c_str()) == 0)
+        {
+            v.push_back(it->second);
+        }
+    }
+
+	return v;
+}
+
+void TC_Http::reset()
+{
+    _headers.clear();
+    _version.clear();
+    _headLength = 0;
+    _content.clear();
+    _bIsChunked = false;
+}
+
+void TC_Http::getHeaders(map<string, string> &header)
+{
+	for(auto it = _headers.begin(); it != _headers.end(); ++it)
+	{
+		header.insert(map<string, string>::value_type(it->first, it->second));
+	}
+}
+
+/********************* TC_HttpCookie ***********************/
+
+bool TC_HttpCookie::matchDomain(const string &sCookieDomain, const string &sDomain)
+{
+    string sCookieDomainNew = TC_Common::lower(sCookieDomain);
+
+    //没有点的自动加点
+    if (sCookieDomainNew.find(".") != 0)
+    {
+        sCookieDomainNew = "." + sCookieDomainNew;
+    }
+
+    string::size_type pos = sCookieDomainNew.find(".");
+
+    //sCookieDomain串至少有两个点
+    if (pos == string::npos || (pos == 0 && sCookieDomainNew.rfind(".") == 0))
+    {
+        return false;
+    }
+
+    string sLowerDomain = TC_Common::lower(sDomain);
+
+    //后边是子域名
+    if (sDomain.length() >= sCookieDomainNew.length() &&
+            sLowerDomain.compare(sDomain.length() - sCookieDomainNew.length(), sCookieDomainNew.length(), sCookieDomainNew) == 0)
+    {
+        return true;
+    }
+
+    //去掉.相等
+    if (sLowerDomain == sCookieDomainNew.substr(1))
+    {
+        return true;
+    }
+
+    return false;
+}
+
+size_t TC_HttpCookie::matchPath(const string &sCookiePath, const string &sPath)
+{
+    if (sCookiePath.empty() || sPath.empty()) return 0;
+
+    //都在最后加/再匹配
+    string sCookiePath1 = (sCookiePath.at(sCookiePath.length() - 1) == '/') ? sCookiePath : sCookiePath + "/";
+
+    string sPath1 = (sPath.at(sPath.length() - 1) == '/') ? sPath : sPath + "/";
+
+    if (sPath1.find(sCookiePath1) == 0)
+    {
+        return sCookiePath1.length();
+    }
+
+    return 0;
+}
+
+void TC_HttpCookie::clear()
+{
+    _cookies.clear();
+}
+
+bool TC_HttpCookie::fixDomain(const string &sDomain, string &sFixDomain)
+{
+    if (sDomain.empty())
+    {
+        return false;
+    }
+
+    sFixDomain = sDomain;
+
+    //自动加.
+    if (sDomain.at(0) != '.')
+    {
+        sFixDomain = "." + sDomain;
+    }
+
+    //domain至少两段
+    if (sFixDomain.find(".") == sFixDomain.rfind("."))
+        return false;
+
+    return true;
+}
+
+void TC_HttpCookie::addCookie(const Cookie &cookie, list<Cookie> &cookies)
+{
+    string sDomain;
+
+    Cookie cookieNew = cookie;
+
+    if (!fixDomain(cookieNew._domain, sDomain))
+        return;
+
+    cookieNew._domain = sDomain;
+
+    if (cookieNew._path.empty())
+        return;
+
+    list<Cookie>::iterator it = cookies.begin();
+
+    string sName;
+    if (cookieNew._data.size() >= 1)
+    {
+        sName = cookieNew._data.begin()->first;
+    }
+
+    while (it != cookies.end())
+    {
+        //检查Cookie是否过期
+        if (isCookieExpires(*it))
+        {
+            cookies.erase(it++);
+        }
+        else if (TC_Port::strcasecmp(it->_domain.c_str(), cookieNew._domain.c_str()) == 0
+                 && strcmp(it->_path.c_str(), cookieNew._path.c_str()) == 0
+                 && it->_isSecure == cookieNew._isSecure)
+        {
+            if (it->_expires == cookieNew._expires)
+            {
+                //domain/path/expires都匹配的情况下, 覆盖老cookie的数据
+                cookieNew._data.insert(it->_data.begin(), it->_data.end());
+
+                cookies.erase(it++);
+            }
+            else
+            {
+                //超时间不一样,但存在同样的key,需删除
+                if (it->_data.find(sName) != it->_data.end())
+                {
+                    it->_data.erase(sName);
+                }
+                ++it;
+            }
+        }
+        else
+        {
+            ++it;
+        }
+    }
+
+    cookies.push_back(cookieNew);
+}
+
+void TC_HttpCookie::addCookie(const Cookie &cookie)
+{
+    addCookie(cookie, _cookies);
+}
+
+void TC_HttpCookie::addCookie(const list<Cookie> &cookie)
+{
+    list<Cookie>::const_iterator it = cookie.begin();
+
+    while (it != cookie.end())
+    {
+        addCookie(*it);
+
+        ++it;
+    }
+}
+
+void TC_HttpCookie::addCookie(const string &sRspURL, const vector<string> &vCookies)
+{
+    TC_URL cURL;
+
+    cURL.parseURL(sRspURL);
+
+    string sRspURLDomain = TC_Common::lower(cURL.getDomain());
+
+    string sRspURLPath  = cURL.getPath();
+
+    for (size_t i = 0; i < vCookies.size(); i++)
+    {
+        //处理一行SetCookie
+        vector<string> v = TC_Common::sepstr<string>(vCookies[i], ";");
+
+        Cookie cookie;
+
+        cookie._isSecure = false;
+        cookie._expires  = 0;
+
+        //解析Cookie数据
+        for (size_t j = 0; j < v.size(); ++j)
+        {
+            string::size_type index = v[j].find("=");
+
+            string name;
+
+            string value;
+
+            if (index != string::npos)
+            {
+                name  = TC_Common::trim(v[j].substr(0, index), " ");
+
+                value = TC_Common::trim(v[j].substr(index + 1));
+            }
+            else
+            {
+                name  = TC_Common::trim(v[j]);
+            }
+            if (TC_Port::strcasecmp(name.c_str(), "secure") == 0)
+            {
+                cookie._isSecure = true;
+            }
+            else if (TC_Port::strcasecmp(name.c_str(), "expires") == 0)
+            {
+                struct tm stTm;
+                //兼容时间格式
+                //expires=Mon, 09-May-41 08:39:32 GMT
+                //expires=Thu, 01-Jan-1970 01:00:00 GMT
+                value = TC_Common::replace(value, "-", " ");
+                if (value.length() == 27  && value.at(11) == ' ' && value.at(14) == ' ')
+                {
+                    int year = TC_Common::strto<int> (value.substr(12, 2));
+                    if (year >= 69 && year <= 99)
+                        value = value.substr(0, 12) + "19" + value.substr(12);
+                    else
+                        value = value.substr(0, 12) + "20" + value.substr(12);
+                }
+
+                TC_Common::strgmt2tm(value, stTm);
+
+                cookie._expires = TC_Port::timegm(&stTm);
+            }
+            else if (TC_Port::strcasecmp(name.c_str(), "path") == 0)
+            {
+                cookie._path = value;
+            }
+            else if (TC_Port::strcasecmp(name.c_str(), "domain") == 0)
+            {
+                cookie._domain = value;
+            }
+            else if (TC_Port::strcasecmp(name.c_str(), "httponly") == 0)
+            {
+                //TODO
+                //cookie._isHttpOnly = true;
+            }
+            else
+                cookie._data.insert(http_cookie_data::value_type(name, value));
+        }
+
+        ///修正和匹配domain/////////////////////////////////////////
+        if (cookie._domain.empty())
+            cookie._domain = sRspURLDomain;
+
+        if (!fixDomain(cookie._domain, cookie._domain))
+            continue;
+
+        //匹配域名
+        if (!matchDomain(cookie._domain, sRspURLDomain))
+            continue;
+
+        //修改和匹配path/////////////////////////////
+        if (cookie._path.empty())
+        {
+            string sCookiePath;
+
+            //缺省是全路径
+            string sRequest = sRspURLPath;
+
+            string::size_type pos = sRequest.rfind("/");
+
+            if (pos == string::npos)
+                sCookiePath = "/";
+            else
+				sCookiePath = sRequest.substr(0, pos + 1);
+
+            cookie._path = sCookiePath;
+        }
+
+        //URL在Path范围内,Cookie 有效
+        if (!matchPath(cookie._path, sRspURLPath))
+            continue;
+
+        //添加Cookie
+        addCookie(cookie);
+    }
+}
+
+bool TC_HttpCookie::isCookieExpires(const Cookie &cookie) const
+{
+    //过期了
+    if (cookie._expires != 0 && cookie._expires < time(NULL))
+        return true;
+
+    return false;
+}
+
+size_t TC_HttpCookie::isCookieMatch(const Cookie &cookie, const TC_URL &tURL) const
+{
+    //域名没有匹配
+    if (!matchDomain(cookie._domain, tURL.getDomain()))
+        return 0;
+
+    //路径没有匹配
+    size_t len = matchPath(cookie._path, tURL.getPath());
+    if (len == 0)
+        return 0;
+
+    //安全的cookie,不安全的URL
+    if (cookie._isSecure && (tURL.getType() != TC_URL::HTTPS))
+        return 0;
+
+    return len;
+}
+
+void TC_HttpCookie::getCookieForURL(const string &sReqURL, list<TC_HttpCookie::Cookie> &cookies)
+{
+    TC_URL tURL;
+
+    tURL.parseURL(sReqURL);
+
+    cookies.clear();
+
+    list<Cookie>::iterator it = _cookies.begin();
+
+    while (it != _cookies.end())
+    {
+        //检查Cookie是否过期
+        if (isCookieExpires(*it))
+        {
+            _cookies.erase(it++);
+            continue;
+        }
+
+        size_t len = isCookieMatch(*it, tURL);
+        if (len == 0)
+        {
+            ++it;
+            continue;
+        }
+
+        cookies.push_back(*it);
+
+        ++it;
+    }
+}
+
+void TC_HttpCookie::getCookieForURL(const string &sReqURL, string &sCookie)
+{
+    list<Cookie> cookies;
+
+    sCookie.clear();
+
+    getCookieForURL(sReqURL, cookies);
+
+    list<Cookie>::iterator it = cookies.begin();
+    while (it != cookies.end())
+    {
+        http_cookie_data::iterator itd = it->_data.begin();
+
+        while (itd != it->_data.end())
+        {
+            //被删除的cookie不输出
+            if (itd->first != "" && itd->second != "" && TC_Common::lower(itd->second) != "null"
+                    && TC_Common::lower(itd->second) != "deleted")
+                sCookie += itd->first + "=" + itd->second + "; ";
+
+            ++itd;
+        }
+
+        ++it;
+    }
+
+    //去掉末尾的 "; "
+    if (sCookie.length() >= 2)
+		sCookie = sCookie.substr(0, sCookie.length() - 2);
+}
+
+list<TC_HttpCookie::Cookie> TC_HttpCookie::getSerializeCookie(time_t t)
+{
+    list<Cookie> cookies;
+
+    list<Cookie>::iterator it = _cookies.begin();
+
+    while (it != _cookies.end())
+    {
+        if (isCookieExpires(*it))
+        {
+            _cookies.erase(it++);
+            continue;
+        }
+        else if (it->_expires != 0) //非当前会话的
+        {
+            cookies.push_back(*it);
+
+            ++it;
+        }
+        else
+            ++it;
+    }
+
+	return cookies;
+}
+
+const list<TC_HttpCookie::Cookie> & TC_HttpCookie::getAllCookie()
+{
+    deleteExpires(time(NULL));
+
+    return _cookies;
+}
+
+void TC_HttpCookie::deleteExpires(time_t t, bool bErase)
+{
+    list<Cookie>::iterator it = _cookies.begin();
+
+    while (it != _cookies.end())
+    {
+        if (bErase && it->_expires == 0)
+        {
+            _cookies.erase(it++);
+            continue;
+        }
+        else if (isCookieExpires(*it))
+        {
+            _cookies.erase(it++);
+            continue;
+        }
+        else
+            ++it;
+    }
+}
+
+/********************* TC_HttpResponse ***********************/
+void TC_HttpResponse::reset()
+{
+    TC_Http::reset();
+
+    _status = 200;
+    _about  = "OK";
+    _version = "HTTP/1.1";
+
+    _iTmpContentLength = 0;
+
+    _iRecvContentLength = 0;
+}
+
+vector<string> TC_HttpResponse::getSetCookie() const
+{
+	return getHeaderMulti("Set-Cookie");
+}
+
+void TC_HttpResponse::addContent(const string &sBuffer)
+{
+    _content += sBuffer;
+
+    _iRecvContentLength += sBuffer.length();
+}
+
+void TC_HttpResponse::addContent(const char *buffer, size_t length)
+{
+	_content.append(buffer, length);
+
+	_iRecvContentLength += length;
+}
+
+size_t TC_HttpResponse::parseResponseHeaderString(const char *beginIt, const char *headerIt)
+{
+	auto it = strnstr(beginIt, "\r\n", headerIt - beginIt);
+
+	assert(it != NULL);
+
+	auto f1 = strnstr(beginIt, " ", it - beginIt);
+	if(f1 == NULL)
+	{
+		throw TC_HttpResponse_Exception("[TC_HttpResponse_Exception::parseResponeHeader] http response parse version format error : " + string(beginIt, headerIt - beginIt));
+	}
+
+	auto f2 = strnstr(f1 + 1, " ", it - (f1 + 1));
+	if(f1 == NULL)
+	{
+		throw TC_HttpResponse_Exception("[TC_HttpResponse_Exception::parseResponeHeader] http response parse status format error : " + string(beginIt, headerIt - beginIt));
+	}
+
+	_headerLine = string(beginIt, it - beginIt);
+
+	if(TC_Port::strncasecmp(_headerLine.c_str(), "HTTP/", 5) != 0)
+	{
+		throw TC_HttpResponse_Exception("[TC_HttpResponse_Exception::parseResponeHeader] http response version is not start with 'HTTP/' : " + _headerLine);
+	}
+
+	_version    = string(beginIt, f1 - beginIt);
+
+	_status     = TC_Common::strto<int>(string(f1 + 1, f2));
+
+	_about      = string(f2 + 1, it);
+
+	return parseHeaderString(beginIt, headerIt, _headers);
+}
+
+bool TC_HttpResponse::incrementDecode(TC_NetWorkBuffer &buff)
+{
+	if(buff.empty())
+		return false;
+	//解析头部
+	if (_headLength == 0)
+	{
+		//至少把header合并成一个buff
+		buff.mergeBuffers();
+
+		auto data = buff.getBufferPointer();
+
+		const char * p = strnstr(data.first, "\r\n\r\n", data.second);
+		if(p == NULL)
+		{
+			return false;
+		}
+
+		_headLength = p - data.first + 4;
+
+		_iTmpContentLength = parseResponseHeaderString(data.first, data.first + data.second);
+
+		//304的返回码中头里本来就没有Content-Length,也不会有数据体,头收全了就是真正的收全了
+		if ( (204 == _status) || (304 == _status) )
+		{
+			return true;
+		}
+
+		buff.moveHeader(_headLength);
+
+		//重定向就认为成功了
+		if ((_status == 301 || _status == 302) && hasHeader("Location"))
+		{
+			return true;
+		}
+
+		//是否是chunk编码
+		_bIsChunked = checkHeader("Transfer-Encoding", "chunked");
+		if(_bIsChunked) {
+			//删除头部里面
+			eraseHeader("Transfer-Encoding");
+		}
+	}
+
+	if (_bIsChunked)
+	{
+		while (true)
+		{
+			const static string sep = "\r\n";
+
+			auto sit = std::search(buff.begin(), buff.end(), sep.c_str(), sep.c_str() + sep.size());
+
+			if (sit == buff.end())
+			{
+				return false;
+			}
+
+			string header = buff.iteratorToIterator<string>(buff.begin(), sit);
+
+			int iChunkSize    = strtol(header.c_str(), NULL, 16);
+
+			if (iChunkSize <= 0)
+			{
+				break;     //所有chunk都接收完毕
+			}
+
+			if (buff.getBufferLength() < header.size() + 2 + (size_t)iChunkSize + 2)
+			{
+				//没有接收完整的chunk
+				return false;
+			}
+
+			//接收到一个完整的chunk了
+			buff.moveHeader(header.size() + 2);
+			addContent(buff.getHeader<string>(iChunkSize));
+
+			//删除一个chunk
+			buff.moveHeader(iChunkSize + 2);
+		}
+
+		buff.clearBuffers();
+
+		//接收到buffer长度设置好
+		setContentLength(_iRecvContentLength);
+
+		return true;
+	}
+	else
+	{
+		if (_iTmpContentLength == 0)
+		{
+			//header长度为0, 但是有body数据
+			addContent(buff.getBuffersString());
+
+			buff.clearBuffers();
+
+			if(_iRecvContentLength > 0) {
+				setContentLength(_iRecvContentLength);
+			}
+
+			return true;
+		}
+		else if (_iTmpContentLength == (size_t) - 1)
+		{
+			//304的返回码中头没有Content-Length,不会有数据体
+			if (_status == 304 || _status == 302)
+			{
+				return true;
+			}
+
+			//header中没长度, 但是有body数据
+			addContent(buff.getBuffersString());
+
+			buff.clearBuffers();
+
+			if(_iRecvContentLength > 0) {
+				setContentLength(_iRecvContentLength);
+			}
+
+			return true;
+		}
+		else
+		{
+			//头部有长度, 接收到长度大于头部为止
+			addContent(buff.getBuffersString());
+
+			buff.clearBuffers();
+
+			//头部的长度小于接收的内容, 还需要继续增加解析后续的buffer
+			if (_iTmpContentLength > _iRecvContentLength)
+				return false;
+
+			return true;
+		}
+	}
+
+	return true;
+}
+
+bool TC_HttpResponse::decode(const string &sBuffer)
+{
+	return decode(sBuffer.c_str(), sBuffer.length());
+}
+
+bool TC_HttpResponse::decode(const char *sBuffer, size_t iLength)
+{
+    assert(sBuffer != NULL);
+
+    const char *pHeader = sBuffer;
+
+	const char *p = strnstr(sBuffer, "\r\n\r\n", iLength);
+    if ( p == NULL)
+    {
+        return false;
+    }
+
+    //解析头部
+	_iTmpContentLength = parseResponseHeaderString(sBuffer, p + 2);
+
+	//304的返回码中头里本来就没有Content-Length,也不会有数据体,头收全了就是真正的收全了
+    if ( (204 == _status) || (304 == _status) )
+    {
+        return true;
+    }
+
+    _headLength = p - sBuffer + 4;
+
+	sBuffer += _headLength;
+
+    //重定向就认为成功了
+    if ((_status == 301 || _status == 302) && hasHeader("Location"))
+    {
+        return true;
+    }
+
+    //是否是chunk编码
+	_bIsChunked = checkHeader("Transfer-Encoding", "chunked");
+    if(_bIsChunked) {
+	    //删除头部里面
+	    eraseHeader("Transfer-Encoding");
+    }
+
+//	_bIsChunked = (getHeader("Transfer-Encoding") == "chunked");
+
+    //删除头部里面
+//    eraseHeader("Transfer-Encoding");
+
+    if (_bIsChunked)
+    {
+        while (true)
+        {
+	        p = strnstr(sBuffer, "\r\n", iLength - (sBuffer - pHeader));
+            if (p == NULL)
+                return false;
+
+            size_t pos = p - sBuffer;
+
+            //查找当前chunk的大小
+			string sChunkSize;
+	        sChunkSize.insert(sChunkSize.end(), sBuffer, p);
+            int iChunkSize    = strtol(sChunkSize.c_str(), NULL, 16);
+
+            if (iChunkSize <= 0)     break;     //所有chunk都接收完毕
+
+            if (strlen(sBuffer) < pos + 2 + (size_t)iChunkSize + 2)
+            {
+                //没有接收完整的chunk
+                return false;
+            }
+
+            //接收到一个完整的chunk了
+            addContent(p + 2, iChunkSize);
+
+            //删除一个chunk
+            sBuffer += pos + 2 + iChunkSize + 2;
+        }
+
+        //接收到buffer长度设置好
+        setContentLength(_iRecvContentLength);
+
+        return true;
+    }
+    else
+    {
+        if (_iTmpContentLength == 0)
+        {
+            //header长度为0, 但是有body数据
+            addContent(sBuffer);
+
+            setContentLength(_iRecvContentLength);
+
+            return true;
+        }
+        else if (_iTmpContentLength == (size_t) - 1)
+        {
+            //304的返回码中头没有Content-Length,不会有数据体
+            if (_status == 304 || _status == 302)
+            {
+                return true;
+            }
+
+            //header中没长度, 但是有body数据
+            addContent(sBuffer);
+
+            setContentLength(_iRecvContentLength);
+        }
+        else
+        {
+            //头部有长度, 接收到长度大于头部为止
+            addContent(sBuffer);
+
+            //头部的长度小于接收的内容, 还需要继续增加解析后续的buffer
+            if (_iTmpContentLength <= _iRecvContentLength)
+                return true;
+        }
+    }
+
+    //body内容长度为0或者没有content-length  且 非chunk模式, 则认为包收全了, 直接返回
+    if ((_iTmpContentLength == 0 || _iTmpContentLength == (size_t) - 1) && !_bIsChunked)
+        return true;
+
+    return (getContentLength() + getHeadLength() <= iLength);
+}
+
+string TC_HttpResponse::encode() const
+{
+	string sRet;
+	sRet.reserve(128);
+
+    sRet += _version;
+    sRet += " ";
+    sRet += TC_Common::tostr(_status);
+    sRet += " ";
+    sRet += _about;
+    sRet += "\r\n";
+    genHeader(sRet);
+    sRet += "\r\n";
+    sRet += _content;
+
+	return sRet;
+}
+
+void TC_HttpResponse::encode(vector<char> &buffer) const
+{
+    buffer.clear();
+
+	string s = encode();
+
+    buffer.resize(s.length());
+    memcpy(buffer.data(), s.c_str(), s.length());
+}
+
+void TC_HttpResponse::setResponse(int status, const string& about, const string& body)
+{
+    _status = status;
+    _about  = about;
+    _content = body;
+
+    /*stringstream os;
+
+    os << _version << " " << _status << " " << _about;
+
+    _headerLine = os.str();*/
+    _headerLine = "";
+    _headerLine += _version;
+    _headerLine += " ";
+    _headerLine += TC_Common::tostr(_status);
+    _headerLine += " ";
+    _headerLine += _about;
+
+    setHeader("Content-Length", TC_Common::tostr(_content.length()));
+}
+
+void TC_HttpResponse::setResponse(int status, const string& about, const char *sBuffer, size_t iLength)
+{
+    _status = status;
+    _about  = about;
+
+    /*stringstream os;
+
+    os << _version << " " << _status << " " << _about;
+
+    _headerLine = os.str();*/
+    _headerLine = "";
+    _headerLine += _version;
+    _headerLine += " ";
+    _headerLine += TC_Common::tostr(_status);
+    _headerLine += " ";
+    _headerLine += _about;
+
+    if (sBuffer != NULL && iLength > 0)
+    {
+        _content.assign(sBuffer, iLength);
+    }
+    else
+    {
+        _content.clear();
+    }
+
+
+    setHeader("Content-Length", TC_Common::tostr(_content.length()));
+}
+
+void TC_HttpResponse::setResponse(const char *sBuffer, size_t iLength)
+{
+    setResponse(200, "OK", sBuffer, iLength);
+}
+
+/********************* TC_HttpRequest ***********************/
+
+void TC_HttpRequest::reset()
+{
+    TC_Http::reset();
+
+    _httpURL.clear();
+}
+
+vector<string> TC_HttpRequest::getCookie()
+{
+    vector<string> v;
+
+    http_header_type::const_iterator itEnd = _headers.end();
+
+    for ( http_header_type::const_iterator it = _headers.begin(); it != itEnd; ++it)
+    {
+        if (it->first == "Cookie")
+        {
+            v.push_back(it->second);
+        }
+    }
+
+	return v;
+}
+
+void TC_HttpRequest::parseURL(const string& sUrl)
+{
+    _httpURL.parseURL(sUrl);
+
+    //设置Host
+    if (!hasHeader("Host"))
+    {
+        string sPort = _httpURL.isDefaultPort() ? "" : ":" + _httpURL.getPort();
+
+        //缺省端口可以不用放进去
+        setHost(_httpURL.getDomain() + sPort);
+    }
+}
+
+void TC_HttpRequest::setRequest(const string& method, const string &sUrl, const std::string& body, bool bNewCreateHost)
+{
+    if (TC_Port::strncasecmp(method.c_str(), "GET", 3) == 0)
+        setGetRequest(sUrl, bNewCreateHost);
+    else if (TC_Port::strncasecmp(method.c_str(), "HEAD", 4) == 0)
+        setHeadRequest(sUrl, bNewCreateHost);
+    else if (TC_Port::strncasecmp(method.c_str(),  "POST", 4) == 0)
+        setPostRequest(sUrl, body, bNewCreateHost);
+    else if (TC_Port::strncasecmp(method.c_str(),  "PUT", 3) == 0)
+        setPutRequest(sUrl, body, bNewCreateHost);
+    else if (TC_Port::strncasecmp(method.c_str(),  "DELETE", 6) == 0)
+        setDeleteRequest(sUrl, body, bNewCreateHost);
+    else if (TC_Port::strncasecmp(method.c_str(),  "PATH", 5) == 0)
+        setPatchRequest(sUrl, body, bNewCreateHost);
+}
+
+void TC_HttpRequest::setGetRequest(const string &sUrl, bool bNewCreateHost)
+{
+    if (bNewCreateHost)
+    {
+        eraseHeader("Host");
+    }
+
+    parseURL(sUrl);
+
+    _requestType    = REQUEST_GET;
+
+    _content        = "";
+
+    eraseHeader("Content-Length");
+}
+
+void TC_HttpRequest::setHeadRequest(const string &sUrl, bool bNewCreateHost)
+{
+    if (bNewCreateHost)
+    {
+        eraseHeader("Host");
+    }
+
+    parseURL(sUrl);
+
+    _requestType    = REQUEST_HEAD;
+
+    _content        = "";
+
+    eraseHeader("Content-Length");
+}
+
+void TC_HttpRequest::setPostRequest(const string &sUrl, const string &sPostBody, bool bNewCreateHost)
+{
+    if (bNewCreateHost)
+    {
+        eraseHeader("Host");
+    }
+
+    parseURL(sUrl);
+
+    _requestType    = REQUEST_POST;
+
+    _content        = sPostBody;
+
+    setHeader("Content-Length", TC_Common::tostr(_content.length()));
+}
+
+void TC_HttpRequest::setOptionsRequest(const string &sUrl, bool bNewCreateHost)
+{
+    if (bNewCreateHost)
+    {
+        eraseHeader("Host");
+    }
+
+    parseURL(sUrl);
+
+    _requestType    = REQUEST_OPTIONS;
+
+    _content        = "";
+
+    eraseHeader("Content-Length");
+}
+
+void TC_HttpRequest::setPostRequest(const string &sUrl, const char *sBuffer, size_t iLength, bool bNewCreateHost)
+{
+    assert(sBuffer != NULL);
+
+    if (bNewCreateHost)
+    {
+        eraseHeader("Host");
+    }
+
+    parseURL(sUrl);
+
+    _requestType    = REQUEST_POST;
+
+    if (iLength > 0)
+    {
+        _content.assign(sBuffer, iLength);
+    }
+    else
+    {
+        _content.clear();
+    }
+
+    setHeader("Content-Length", TC_Common::tostr(_content.length()));
+}
+
+
+void TC_HttpRequest::setPutRequest(const string &sUrl, const string &sPostBody, bool bNewCreateHost )
+{
+    if(bNewCreateHost)
+    {
+        eraseHeader("Host");
+    }
+
+    parseURL(sUrl);
+
+    _requestType    = REQUEST_PUT;
+
+    _content        = sPostBody;
+
+    setHeader("Content-Length", TC_Common::tostr(_content.length()));
+}
+
+void TC_HttpRequest::setPatchRequest(const string &sUrl, const string &sPostBody, bool bNewCreateHost )
+{
+    if(bNewCreateHost)
+    {
+        eraseHeader("Host");
+    }
+
+    parseURL(sUrl);
+
+    _requestType    = REQUEST_PATCH;
+
+    _content        = sPostBody;
+
+    setHeader("Content-Length", TC_Common::tostr(_content.length()));
+}
+
+
+void TC_HttpRequest::setDeleteRequest(const string &sUrl, const string &sPostBody, bool bNewCreateHost )
+{
+    if(bNewCreateHost)
+    {
+        eraseHeader("Host");
+    }
+
+    parseURL(sUrl);
+
+    _requestType    = REQUEST_DELETE;
+
+    _content        = sPostBody;
+
+    setHeader("Content-Length", TC_Common::tostr(_content.length()));
+
+}
+
+string TC_HttpRequest::encode()
+{
+	string sRet;
+	sRet.reserve(128);
+	if(_requestType == REQUEST_GET || _requestType == REQUEST_OPTIONS || _requestType == REQUEST_HEAD)
+    {
+        sRet += getMethod();//(_requestType);
+        sRet += " ";
+        sRet += _httpURL.getRequest();
+        sRet += " HTTP/1.1\r\n";
+        genHeader(sRet);
+        sRet += "\r\n";
+    }
+    else if(_requestType == REQUEST_POST || _requestType == REQUEST_PUT || _requestType == REQUEST_PATCH || _requestType == REQUEST_DELETE)
+    {
+        setContentLength(_content.length());
+        sRet += getMethod();//requestType2str(_requestType);
+        sRet += " ";
+        sRet += _httpURL.getRequest();
+        sRet += " HTTP/1.1\r\n";
+	    genHeader(sRet);
+        sRet += "\r\n";
+        sRet += _content;
+    }
+	return sRet;
+}
+
+void TC_HttpRequest::encode(vector<char> &sRet)
+{
+	string s = encode();
+	sRet.resize(s.length());
+    memcpy(sRet.data(), s.c_str(), s.length());
+}
+
+void TC_HttpRequest::encode(TC_NetWorkBuffer &buff)
+{
+	buff.addBuffer(std::move(encode()));
+}
+
+bool TC_HttpRequest::decode(const string &sBuffer)
+{
+    return decode(sBuffer.c_str(), sBuffer.length());
+}
+
+bool TC_HttpRequest::decode(const vector<char> &sBuffer)
+{
+	return decode(sBuffer.data(), sBuffer.size());
+}
+
+bool TC_HttpRequest::decode(const char *sBuffer, size_t iLength)
+{
+    assert(sBuffer != NULL);
+
+	const char *p = strnstr(sBuffer, " ", 10);
+	if(p == NULL)
+	{
+		throw runtime_error("[TC_HttpRequest::decode] http protocol parse error");
+	}
+
+	auto it = TC_Http::HEADER.find(string(sBuffer, p - sBuffer));
+    if(it == TC_Http::HEADER.end())
+    {
+        throw runtime_error("[TC_HttpRequest::decode] protocol not support ");
+    }
+
+    p = strnstr(sBuffer, "\r\n\r\n", iLength);
+    if (p == NULL)
+    {
+        return false;
+    }
+
+	_requestType = it->second;
+
+    parseRequestHeader(sBuffer, p);
+
+	_headLength = p - sBuffer + 4;
+
+    bool bChunk = checkHeader("Transfer-Encoding", "chunked"); //(getHeader("Transfer-Encoding") == "chunked");
+
+    int iChunkSuffixLen = 0;
+
+    if (bChunk)
+    {
+        p = sBuffer + _headLength;
+        while (true)
+        {
+	        const char *pos  = strnstr(p, "\r\n", iLength - (p - sBuffer));
+
+//	        const char *pos = strstr(p, "\r\n");
+            if (pos == NULL)
+                return false;
+
+            //查找当前chunk的大小
+	        string sChunkSize(p, pos - p);
+            int iChunkSize    = strtol(sChunkSize.c_str(), NULL, 16);
+
+            iChunkSuffixLen = iChunkSuffixLen + sChunkSize.length();
+            if (iChunkSize <= 0)
+            {
+                iChunkSuffixLen = iChunkSuffixLen + 4;
+                break;      //所有chunk都接收完毕
+            }
+            if ((sBuffer+iLength-p) >= (pos - p) + 2 + iChunkSize + 2)  //接收到一个完整的chunk了
+            {
+                //获取一个chunk的内容
+	            _content.append(pos + 2, iChunkSize);
+
+	            //删除一个chunk
+				p = pos + 2 + iChunkSize + 2;
+                iChunkSuffixLen = iChunkSuffixLen + 4;
+            }
+            else
+            {
+                //没有接收完整的chunk
+                return false;
+            }
+
+            setContentLength(getContent().length());
+        }
+    }
+    else
+    {
+        _content.assign((sBuffer + _headLength), iLength - _headLength);
+    }
+
+    return (getContentLength() + getHeadLength() + iChunkSuffixLen == iLength);
+}
+
+bool TC_HttpRequest::checkRequest(TC_NetWorkBuffer &buff)
+{
+	buff.mergeBuffers();
+
+	return checkRequest(buff.getBufferPointer().first, buff.getBufferLength());
+}
+
+bool TC_HttpRequest::checkRequest(const char* sBuffer, size_t iLen)
+{
+	if(iLen < 10)
+		return false;
+
+	const char *p = strnstr(sBuffer, " ", 10);
+	if(p == NULL)
+	{
+		throw runtime_error("[TC_HttpRequest::checkRequest] http protocol parse error");
+	}
+
+	auto it = TC_Http::HEADER.find(string(sBuffer, p - sBuffer));
+	if(it == TC_Http::HEADER.end())
+	{
+		throw runtime_error("[TC_HttpRequest::checkRequest] protocol not support: " + string(sBuffer, 8));
+	}
+
+    const char *header = strnstr(sBuffer, "\r\n\r\n", iLen);
+    if ( header == NULL)
+    {
+        return false;
+    }
+
+	size_t pos = header - sBuffer;
+
+    size_t iHeadLen = pos + 4;
+
+	p =  strnstr(sBuffer, "\r\n", iHeadLen);
+	if(p == NULL)
+	{
+		//first line
+		return false;
+	}
+
+	p += 2;
+
+    bool bChunk = false;
+
+	size_t len  = 0;
+
+    //找到\r\n\r\n之前的长度表示
+    while (true)
+    {
+        size_t iMoveLen = p - sBuffer;
+        if ( iMoveLen >= iHeadLen )
+        {
+            break;
+        }
+
+        const char *line    = p;
+//	    const char *lineEnd  = strnstr(line, "\r\n", iLen - (line - sBuffer));
+
+	    const char *lineEnd = strstr(line, "\r\n");
+        if (lineEnd != NULL)
+        {
+	        p = lineEnd + 2;
+
+	        if (TC_Port::strncasecmp(line, "Transfer-Encoding:", 18) == 0)
+	        {
+		        string chunked = TC_Common::trim(string(line + 18, lineEnd));
+		        bChunk = (chunked == "chunked");
+		        if (bChunk) break;
+	        }
+	        else if (TC_Port::strncasecmp(line, "Content-Length:", 15) != 0)
+	        {
+		        continue;
+	        }
+	        else
+            {
+		        len = TC_Common::strto<size_t>(TC_Common::trim(string(line + 15, lineEnd), " "));
+	        }
+        }
+    }
+
+    if (bChunk)
+    {
+        int remain_len = iLen - iHeadLen;
+        int move_len = 0;
+        const char * pCur = header + 4;
+        while (true)
+        {
+	        p  = strnstr(pCur, "\r\n", remain_len);
+
+//	        p = strstr(pCur , "\r\n");
+            if ( p == NULL )
+            {
+                return false;
+            }
+
+            //查找当前chunk的大小
+            int iChunkSize = strtol(string(pCur, p - pCur).c_str(), NULL, 16);
+            if (iChunkSize <= 0)
+            {
+                return true; //所有chunk都接收完毕
+            }
+
+            move_len = (p - pCur) + 2 + iChunkSize + 2;
+            if ( remain_len >= move_len )  //接收到一个完整的chunk了
+            {
+                //移动到下一个chunk
+                remain_len -= move_len;
+                pCur = p + 2 + iChunkSize + 2;
+            }
+            else
+            {
+                return false;
+            }
+        }
+    }
+    else  if (len + pos + 4 <= iLen)
+	{
+		return true;
+	}
+
+    return false;
+}
+
+size_t TC_Http::parseHeaderString(const char *beginIt, const char *headerIt, TC_Http::http_header_type &sHeader)
+{
+	size_t contentLength = -1;
+
+	sHeader.clear();
+
+	bool first      = true;
+	auto lineStartIt= beginIt;
+    bool isLastLine = false;
+
+	while (true)
+	{
+		auto it = strnstr(lineStartIt, "\r\n", headerIt - lineStartIt);
+		if(it == NULL)
+		{
+            it = headerIt;
+            isLastLine = true;
+		}
+
+		//first line ignore
+		if(!first)
+		{
+			auto itF = strnstr(lineStartIt, ":", it - lineStartIt);
+			if (itF != NULL)
+			{
+				while(*lineStartIt == ' ')
+					++lineStartIt;
+
+				const char *s = itF;
+				while(*s == ' ')
+					--s;
+
+				string name(lineStartIt, s - lineStartIt);
+
+				++itF;
+				while(*itF == ' ')
+					++itF;
+
+				s = it;
+				while(*s == ' ')
+					--s;
+
+				string value(itF, s-itF);
+
+				if (TC_Port::strncasecmp(name.c_str(), "Content-Length", 14) == 0)
+				{
+					contentLength = TC_Common::strto<size_t>(value);
+				}
+
+				if(name.empty())
+				{
+					assert(false);
+				}
+				sHeader.insert(multimap<string, string>::value_type(std::move(name), std::move(value)));
+			}
+		}
+		else
+		{
+			first = false;
+		}
+
+        if (isLastLine)
+        {
+            break;
+        }
+
+		lineStartIt = it + 2;//sep.size();
+	}
+
+	return contentLength;
+}
+
+void TC_HttpRequest::parseRequestHeader(const char* szBuffer, const char *header)
+{
+	const char *p = strstr(szBuffer, "\r\n");
+
+	assert(p != NULL);
+
+	auto f1 = strnstr(szBuffer, " ", p - szBuffer);
+	if (f1 == p)
+	{
+		throw TC_HttpRequest_Exception("[TC_HttpRequest::parseRequestHeader] http request format error: " + string(szBuffer, p - szBuffer));
+	}
+
+	auto f2 = strnstr(f1 + 1, " ", p - f1 + 1);//std::search(f1 + 1, p, sep.c_str(), sep.c_str() + sep.size());
+	if (f2 == p || f1 >= f2)
+	{
+		throw TC_HttpRequest_Exception("[TC_HttpRequest::parseRequestHeader] http request format error: " + string(szBuffer, p - szBuffer));
+	}
+
+    //URL地址
+    string sURL(f1 + 1, f2 - f1 - 1 );
+
+    //HTTP协议版本
+	_version.assign(f2 + 1, p - f2 - 1);
+
+	parseHeaderString(szBuffer, header, _headers);
+
+    if (TC_Port::strncasecmp(f1 + 1, "https://", 8) != 0 )
+    {
+        if (TC_Port::strncasecmp(f1 + 1, "http://", 7) != 0 )
+        {
+            sURL = "http://" + getHost() + sURL;
+        }
+    }
+
+    parseURL(sURL);
+}
+
+void TC_HttpRequest::getHostPort(string &sDomain, uint32_t &iPort)
+{
+    sDomain = _httpURL.getDomain();
+
+    iPort   = TC_Common::strto<uint32_t>(_httpURL.getPort());
+}
+
+const string &TC_HttpRequest::getMethod() const
+{
+	auto it = TC_Http::HEADER_REVERSE.find(_requestType);
+	if(it != TC_Http::HEADER_REVERSE.end())
+	{
+		return it->second;
+	}
+	else
+	{
+		throw TC_HttpRequest_Exception("[TC_HttpRequest::setMethod] http request command error: " + TC_Common::tostr(_requestType));
+	}
+}
+
+void TC_HttpRequest::setMethod(const char * sMethod)
+{
+	auto it = TC_Http::HEADER.find(sMethod);
+	if(it != TC_Http::HEADER.end())
+	{
+		_requestType = it->second;
+	}
+	else
+	{
+		throw TC_HttpRequest_Exception("[TC_HttpRequest::setMethod] http request command error: " + string(sMethod));
+	}
+}
+
+void TC_HttpRequest::setPath(const char *path)
+{
+	_httpURL._sPath = path;
+}
+
+void TC_HttpRequest::setDomain(const char * sDomain)
+{
+	_httpURL._sDomain = sDomain;
+}
+
+void TC_HttpRequest::setScheme(const char * sScheme)
+{
+	_httpURL._sScheme = sScheme;
+}
+
+int TC_HttpRequest::doRequest(TC_TCPClient& tcpClient, TC_HttpResponse& stHttpRsp)
+{
+    //只支持短连接模式
+    setConnection("close");
+
+    string sSendBuffer = encode();
+
+    int iRet = tcpClient.send(sSendBuffer.c_str(), sSendBuffer.length());
+    if (iRet != TC_ClientSocket::EM_SUCCESS)
+    {
+        return iRet;
+    }
+
+    stHttpRsp.reset();
+
+    TC_NetWorkBuffer recvBuffer(NULL);
+
+    while (true)
+    {
+    	char buffer[8*1024];
+        size_t iRecvLen = sizeof(buffer);
+
+        iRet = tcpClient.recv(buffer, iRecvLen);
+
+        if (iRet == TC_ClientSocket::EM_SUCCESS)
+        {
+	        recvBuffer.addBuffer(buffer, iRecvLen);
+        }
+
+        switch (iRet)
+        {
+        case TC_ClientSocket::EM_SUCCESS:
+            if (stHttpRsp.incrementDecode(recvBuffer))
+            {
+                return TC_ClientSocket::EM_SUCCESS;
+            }
+            continue;
+        case TC_ClientSocket::EM_CLOSE:
+            stHttpRsp.incrementDecode(recvBuffer);
+            return TC_ClientSocket::EM_SUCCESS;
+        default:
+            return iRet;
+        }
+    }
+
+    assert(true);
+
+    return 0;
+
+}
+
+int TC_HttpRequest::doRequest(TC_HttpResponse &stHttpRsp, int iTimeout)
+{
+    //只支持短连接模式
+    setConnection("close");
+
+    string sSendBuffer = encode();
+
+    string sHost;
+    uint32_t iPort;
+
+    getHostPort(sHost, iPort);
+
+    TC_TCPClient tcpClient;
+    tcpClient.init(sHost, iPort, iTimeout);
+
+    int iRet = tcpClient.send(sSendBuffer.c_str(), sSendBuffer.length());
+    if (iRet != TC_ClientSocket::EM_SUCCESS)
+    {
+        return iRet;
+    }
+
+    stHttpRsp.reset();
+
+	TC_NetWorkBuffer recvBuffer(NULL);
+
+    while (true)
+    {
+	    char buffer[8*1024];
+	    size_t iRecvLen = sizeof(buffer);
+
+        iRet = tcpClient.recv(buffer, iRecvLen);
+
+        if (iRet == TC_ClientSocket::EM_SUCCESS)
+        {
+	        recvBuffer.addBuffer(buffer, iRecvLen);
+        }
+
+        switch (iRet)
+        {
+        case TC_ClientSocket::EM_SUCCESS:
+            if (stHttpRsp.incrementDecode(recvBuffer))
+            {
+                return TC_ClientSocket::EM_SUCCESS;
+            }
+            continue;
+        case TC_ClientSocket::EM_CLOSE:
+            stHttpRsp.incrementDecode(recvBuffer);
+            return TC_ClientSocket::EM_SUCCESS;
+        default:
+            return iRet;
+        }
+    }
+
+    assert(true);
+
+    return 0;
+}
+
+}
+
+

+ 3 - 3
util/src/tc_spin_lock.cpp

@@ -35,9 +35,9 @@ bool TC_SpinLock::tryLock() const
     int trys = 100;
     for (; trys > 0 && _flag.test_and_set(std::memory_order_acquire); --trys)
     {
-#if TARGET_PLATFORM_LINUX
-        asm volatile("rep; nop" ::: "memory");
-#endif
+//#if TARGET_PLATFORM_LINUX
+//        asm volatile("rep; nop" ::: "memory");
+//#endif
 
     }
 

Einige Dateien werden nicht angezeigt, da zu viele Dateien in diesem Diff geändert wurden.