Beispiel #1
0
bool logger_servlet::doPost(acl::HttpServletRequest& req,
	acl::HttpServletResponse&)
{
	const char* uri = req.getRequestUri();
	if (uri == NULL || *uri == 0)
	{
		logger_debug(DEBUG_HTTP, 1, "getRequestUri null");
		return false;
	}

	const char* host = req.getRemoteHost();
	if (host == NULL || *host == 0)
	{
		logger_debug(DEBUG_HTTP, 1, "no Host");
		return false;
	}

	acl::string url;
	url.format("http://%s/%s", host, uri);
	logger("%s", url.c_str());

	int   n;
	char  buf[8192];
	acl::http_client* conn = req.getClient();
	while (true)
	{
		n = conn->read_body(buf, sizeof(buf));
		if (n < 0)
			return false;
		else if (n == 0)
			break;
	}

	return true;
}
Beispiel #2
0
bool http_servlet::doPost(acl::HttpServletRequest& req,
	acl::HttpServletResponse& res)
{
	// 如果需要 http session 控制,请打开下面注释,且需要保证
	// 在 master_service.cpp 的函数 thread_on_read 中设置的
	// memcached 服务正常工作
	/*
	const char* sid = req.getSession().getAttribute("sid");
	if (*sid == 0)
		req.getSession().setAttribute("sid", "xxxxxx");
	sid = req.getSession().getAttribute("sid");
	*/

	// 如果需要取得浏览器 cookie 请打开下面注释
	/*
	const char* mycookie = req.getCookieValue("mycookie");
	if (mycookie == NULL)
		res.addCookie("mycookie", "{xxx}");
	*/

	bool keep_alive = req.isKeepAlive();

	res.setContentType("text/xml; charset=utf-8")	// 设置响应字符集
		.setKeepAlive(keep_alive)		// 设置是否保持长连接
		.setChunkedTransferEncoding(true);	// 采用 chunk 传输方式

	const char* param1 = req.getParameter("name1");
	const char* param2 = req.getParameter("name2");

	// 创建 xml 格式的数据体
	acl::xml body;
	body.get_root()
		.add_child("root", true)
			.add_child("params", true)
				.add_child("param", true)
					.add_attr("name1", param1 ? param1 : "null")
				.get_parent()
				.add_child("param", true)
					.add_attr("name2", param2 ? param2 : "null");
	acl::string buf;
	body.build_xml(buf);

	// 发送 http 响应体,因为设置了 chunk 传输模式,所以需要多调用一次
	// res.write 且两个参数均为 0 以表示 chunk 传输数据结束
	return res.write(buf) && res.write(NULL, 0) && keep_alive;
}
Beispiel #3
0
void http_servlet::logger_request(acl::HttpServletRequest& req)
{
	acl::string req_hdr;
	acl::http_client* client = req.getClient();
	client->sprint_header(req_hdr, NULL);
	out_.format("\r\n>>>request header<<<\r\n");
	out_.write(req_hdr);
	out_.format("\r\n");
}
Beispiel #4
0
bool http_servlet::doPost(acl::HttpServletRequest& req,
	acl::HttpServletResponse& res)
{
	handled_ = true;
	acl::http_client* conn = req.getClient();
	conn->header_disable("Accept-Encoding");
	logger_request(req);

	// 生成完整的 url,以备下面使用
	const char* host = req.getRemoteHost();
	const char* uri = req.getRequestUri();
	if (host == NULL || *host == 0)
		host = req.getLocalAddr();

	url_.format("http://%s%s", host, uri ? uri : "/");
	out_.format(">>> request url: %s\r\n", url_.c_str());

	https_client client(out_, client_ssl_conf_);
	return client.http_request(req, res);
}
bool WebsocketServlet_impl::doPost(acl::HttpServletRequest& req,
	acl::HttpServletResponse& res)
{
	res.setContentType("text/html; charset=utf-8")	// 设置响应字符集
		.setContentEncoding(false)		// 设置是否压缩数据
		.setChunkedTransferEncoding(true);	// 采用 chunk 传输方式

	const char* ip = req.getLocalAddr();
	if (ip == NULL || *ip == 0)
	{
		logger_error("getLocalAddr error");
		return false;
	}
	unsigned short port = req.getLocalPort();
	if (port == 0)
	{
		logger_error("getLocalPort error");
		return false;
	}

	acl::string local_addr;
	local_addr << ip << ":" << port;

	printf("getLocalAddr: %s\r\n", local_addr.c_str());

	acl::string html_file;
	html_file << "www/upload.html";
	acl::string buf;
	if (acl::ifstream::load(html_file, &buf) == false)
	{
		logger_error("load %s error %s",
			html_file.c_str(), acl::last_serror());
		return doError(req, res);
	}

	buf << "<script>g_url='ws://" << local_addr << "/'</script>";

	// 发送 http 响应体,因为设置了 chunk 传输模式,所以需要多调用一次
	// res.write 且两个参数均为 0 以表示 chunk 传输数据结束
	return res.write(buf) && res.write(NULL, 0);
}
Beispiel #6
0
bool http_servlet::doGet(acl::HttpServletRequest& req,
	acl::HttpServletResponse& res)
{
	res.setContentType("text/plain")
		.setKeepAlive(req.isKeepAlive());

	acl::string body;
	body.format("%s version: %s; %s %s %s\r\n",
		MASTER_NAME, MASTER_VERSION,
		MASTER_CTLD_CMD, MASTER_CTLD_VERSION, MASTER_CTLD_DATE);

	return reply(req, res, 200, body);
}
Beispiel #7
0
bool http_servlet::doPost(acl::HttpServletRequest& req,
	acl::HttpServletResponse& res)
{
	// 如果需要 http session 控制,请打开下面注释,且需要保证
	// 在 master_service.cpp 的函数 thread_on_read 中设置的
	// memcached 服务正常工作
	/*
	const char* sid = req.getSession().getAttribute("sid");
	if (*sid == 0)
		req.getSession().setAttribute("sid", "xxxxxx");
	sid = req.getSession().getAttribute("sid");
	*/

	res.setCharacterEncoding("utf-8")		// 设置响应字符集
		.setKeepAlive(req.isKeepAlive())	// 设置是否保持长连接
		.setContentEncoding(false)		// 自动支持压缩传输
		.setChunkedTransferEncoding(false);	// 采用 chunk 传输方式

	acl::string path;
	path = req.getPathInfo();
	if (path.empty())
	{
		logger_error("getPathInfo NULL");
		return doReply(req, res, 400, "%s", "no PathInfo");
	}
	path.strip("..");
	if (path.empty())
	{
		logger_error("path empty");
		return doReply(req, res, 400, "%s", "path empty");
	}

	const std::vector<acl::string>& tokens = path.split2("/");
	// printf(">>>path: %s, size: %ld\r\n", path.c_str(), tokens.size());
	if (tokens.size() < 2 || !tokens[1].equal("website", false))
		return doApp(req, res);
	else
		return doDoc(req, res, path);
}
Beispiel #8
0
bool http_servlet::doPost(acl::HttpServletRequest& req,
	acl::HttpServletResponse& res)
{
	// 如果需要 http session 控制,请打开下面注释,且需要保证
	// 在 master_service.cpp 的函数 thread_on_read 中设置的
	// memcached 服务正常工作
	/*
	const char* sid = req.getSession().getAttribute("sid");
	if (*sid == 0)
		req.getSession().setAttribute("sid", "xxxxxx");
	sid = req.getSession().getAttribute("sid");
	*/

	// 如果需要取得浏览器 cookie 请打开下面注释
	/*
	
	*/

	res.setContentType("text/xml; charset=utf-8")	// 设置响应字符集
		.setKeepAlive(req.isKeepAlive())	// 设置是否保持长连接
		.setContentEncoding(true)		// 自动支持压缩传输
		.setChunkedTransferEncoding(false);	// chunk 传输方式

	const char* cmd = req.getParameter("cmd");
	if (cmd == NULL || *cmd == 0)
	{
		logger_error("cmd not found");
		return replyf(req, res, 400, "%s", "no cmd");
	}

#define EQ	!strcasecmp

	acl::string buf;
	commands_action action(addr_, req, res, cmd);
	action.set_conf(conf_);
	int status = action.run(buf);
	return reply_json(req, res, status, buf);
}
Beispiel #9
0
bool http_servlet::doReply(acl::HttpServletRequest& req,
	acl::HttpServletResponse& res, int status, acl::json& json)
{
	res.setStatus(status);
	res.setContentType("text/json");
	if (1)
		res.setKeepAlive(req.isKeepAlive());
	else
		res.setKeepAlive(false);
	const acl::string& data = json.to_string();
	res.setContentLength(data.size());

	return res.write(data) && res.write(NULL, 0);
}
Beispiel #10
0
bool http_servlet::doWebsocket(acl::HttpServletRequest& req,
	acl::HttpServletResponse&)
{
	acl::socket_stream& ss = req.getSocketStream();
	acl::websocket in(ss), out(ss);

	while (true)
	{
		if (in.read_frame_head() == false)
		{
			printf("read_frame_head error\r\n");
			return false;
		}

		bool ret;
		unsigned char opcode = in.get_frame_opcode();

		printf("opcode: 0x%x\r\n", opcode);

		switch (opcode)
		{
		case acl::FRAME_PING:
			ret = doPing(in, out);
			break;
		case acl::FRAME_PONG:
			ret = doPong(in, out);
			break;
		case acl::FRAME_CLOSE:
			ret = doClose(in, out);
			break;
		case acl::FRAME_TEXT:
		case acl::FRAME_BINARY:
			ret = doMsg(in, out);
			break;
		case acl::FRAME_CONTINUATION:
			ret = false;
			break;
		default:
			ret = false;
			break;
		}

		if (ret == false)
			return false;
	}

	// XXX: NOT REACHED
	return false;
}
Beispiel #11
0
bool http_servlet::doUpload(acl::HttpServletRequest& req,
	acl::HttpServletResponse& res)
{
	// 获得输入流
	acl::istream& in = req.getInputStream();
	acl::string buf;
	bool  finish = false;

	//logger(">>>>>>>>>>read: %lld, total: %lld<<<<<",
	//	read_length_, content_length_);

	// 读取 HTTP 客户端请求数据
	while (content_length_ > read_length_)
	{
		if (in.read_peek(buf, true) == false)
			break;
		//if (buf.empty())
		//	break;
//		printf(">>>size: %ld, space: %ld\r\n",
//			(long) buf.size(), (long) buf.capacity());

		if (fp_.write(buf) == -1)
		{
			logger_error("write error %s", acl::last_serror());
			(void) doReply(req, res, "write error");
			return false;
		}

		read_length_ += buf.size();

		// 将读得到的数据输入至解析器进行解析
		if (!finish && mime_->update(buf, buf.size()) == true)
			finish = true;
	}

	if (in.eof())
	{
		logger_error("read error");
		return false;
	}

	return true;
}
Beispiel #12
0
bool http_servlet::doReply(acl::HttpServletRequest& req,
	acl::HttpServletResponse& res, const char* info)
{
	// 创建 xml 格式的数据体
	acl::xml1 body;

	body.get_root().add_child("root", true)
		.add_child("content_type", true)
			.add_attr("type", (int) req.getRequestType())
			.get_parent()
		.add_child("info", true)
			.set_text(info)
			.get_parent()
		.add_child("params", true)
			.add_child("param", true)
				.add_attr("name1", param1_)
			.get_parent()
			.add_child("param", true)
				.add_attr("name2", param2_)
			.get_parent()
			.add_child("param", true)
				.add_attr("name3", param3_)
			.get_parent()
		.add_child("files", true)
			.add_child("file", true)
				.add_attr("filename", file1_)
				.add_attr("fsize", fsize1_)
				.get_parent()
			.add_child("file", true)
				.add_attr("filename", file2_)
				.add_attr("fsize", fsize2_)
				.get_parent()
			.add_child("file", true)
				.add_attr("filename", file3_)
				.add_attr("fsize", fsize3_);
	acl::string buf;
	body.build_xml(buf);

	logger(">>%s<<", buf.c_str());
	return res.write(buf) && res.write(NULL, 0);
}
Beispiel #13
0
bool http_servlet::doParse(acl::HttpServletRequest& req,
	acl::HttpServletResponse& res)
{
	const char* ptr = req.getParameter("name1");
	if (ptr)
		param1_ = ptr;
	ptr = req.getParameter("name2");
	if (ptr)
		param2_ = ptr;
	ptr = req.getParameter("name3");
	if (ptr)
		param3_ = ptr;

	acl::string path;

	// 遍历所有的 MIME 结点,找出其中为文件结点的部分进行转储
	const std::list<acl::http_mime_node*>& nodes = mime_->get_nodes();
	std::list<acl::http_mime_node*>::const_iterator cit = nodes.begin();
	for (; cit != nodes.end(); ++cit)
	{
		const char* name = (*cit)->get_name();
		if (name == NULL)
			continue;

		acl::http_mime_t mime_type = (*cit)->get_mime_type();
		if (mime_type == acl::HTTP_MIME_FILE)
		{
			const char* filename = (*cit)->get_filename();
			if (filename == NULL)
			{
				logger("filename null");
				continue;
			}

			// 有的浏览器(如IE)上传文件时会带着文件路径,所以
			// 需要先将路径去掉
			filename = acl_safe_basename(filename);
#if defined(_WIN32) || defined(_WIN64)
			path.format("%s\\%s", var_cfg_var_path, filename);
#else
			path.format("%s/%s", var_cfg_var_path, filename);
#endif
			(void) (*cit)->save(path.c_str());

			if (strcmp(name, "file1") == 0)
			{
				file1_ = filename;
				fsize1_ = get_fsize(var_cfg_var_path, filename);
			}
			else if (strcmp(name, "file2") == 0)
			{
				file2_ = filename;
				fsize2_ = get_fsize(var_cfg_var_path, filename);
			}
			else if (strcmp(name, "file3") == 0)
			{
				file3_ = filename;
				fsize3_ = get_fsize(var_cfg_var_path, filename);
			}
		}
	}

	// 查找上载的某个文件并转储
	const acl::http_mime_node* node = mime_->get_node("file1");
	if (node && node->get_mime_type() == acl::HTTP_MIME_FILE)
	{
		ptr = node->get_filename();
		if (ptr)
		{
			// 有的浏览器(如IE)上传文件时会带着文件路径,所以
			// 需要先将路径去掉
			ptr = acl_safe_basename(ptr);
#if defined(_WIN32) || defined(_WIN64)
			path.format("%s\\1_%s", var_cfg_var_path, ptr);
#else
			path.format("%s/1_%s", var_cfg_var_path, ptr);
#endif
			(void) node->save(path.c_str());
		}
	}

	return doReply(req, res, "OK");
}
Beispiel #14
0
bool http_servlet::doPost(acl::HttpServletRequest& req,
	acl::HttpServletResponse& res)
{
#if 0
	const char* session_name = req.getSession().getAttribute("session_name");
	if (*session_name == 0)
	{
		req.getSession().setAttribute("session_name", "name");
		req.getSession().setMaxAge(100);
	}
	session_name = req.getSession().getAttribute("session_name");

	const char* session_user = req.getSession().getAttribute("session_user");
	if (*session_user == 0)
		req.getSession().setAttribute("session_user", "user");
	session_user = req.getSession().getAttribute("session_user");
#else
	const char* session_name = "name", *session_user = "******";
#endif

	// 取得浏览器 cookie
	const char* cookie_name = req.getCookieValue("cookie_name");

	bool keep_alive = req.isKeepAlive();

	const char* param1 = req.getParameter("name1");
	const char* param2 = req.getParameter("name2");

	// 创建 xml 格式的数据体
	acl::xml body;
	body.get_root()
		.add_child("root", true)
			.add_child("session", true)
				.add_child("session_name", true)
					.set_text(session_name)
				.get_parent()
				.add_child("session_user", true)
					.set_text(session_user)
				.get_parent()
			.get_parent()
			.add_child("cookie", true)
				.add_child("cookie_name", true)
					.set_text(cookie_name ? cookie_name : "")
				.get_parent()
			.get_parent()
			.add_child("params", true)
				.add_child("param", true)
					.add_attr("name1", param1 ? param1 : "null")
				.get_parent()
				.add_child("param", true)
					.add_attr("name2", param2 ? param2 : "null");
	acl::string buf;
	body.build_xml(buf);

#if 0
	res.setContentType("text/xml; charset=utf-8")	// 设置响应字符集
		.setKeepAlive(keep_alive)		// 设置是否保持长连接
		//.setContentLength(buf.length());
#else
	res.setContentType("text/xml; charset=utf-8")	// 设置响应字符集
		.setKeepAlive(keep_alive)		// 设置是否保持长连接
		.setContentEncoding(true)		// 设置是否压缩数据
		.setChunkedTransferEncoding(true);	// 采用 chunk 传输方式
#endif

	//logger("access http://%s%s", req.getRemoteAddr(), req.getRequestUri());

	// 发送 http 响应体,因为设置了 chunk 传输模式,所以需要多调用一次
	// res.write 且两个参数均为 0 以表示 chunk 传输数据结束
	return res.write(buf) && res.write(NULL, 0);
}
Beispiel #15
0
bool https_client::http_request(acl::HttpServletRequest& req,
	acl::HttpServletResponse& res)
{
	const char* host = req.getRemoteHost();
	if (host == NULL || *host == 0)
		host = req.getLocalAddr();

	acl::string server_addr;
	if (ssl_conf_ == NULL)
		server_addr.format("%s:80", host);
	else
		server_addr.format("%s:443", host);

	std::auto_ptr<acl::http_client> backend(new acl::http_client);

	// 连接服务器
	if (connect_server(server_addr, *backend) == false)
		return false;

	acl::http_client* front = req.getClient();

	// 取得  HTTP 请求头数据
	acl::string req_hdr;
	front->sprint_header(req_hdr, NULL);

	// 转发 HTTP 请求头至服务器
	if (backend->get_ostream().write(req_hdr) == -1)
	{
		out_.puts(">>>>write header error");
		return false;
	}
	if (backend->get_ostream().write("\r\n") == -1)
	{
		out_.puts(">>>>write CRLF error");
		return false;
	}

	// 如果还有数据体,则转发请求的数据体给服务器
	long long int len = req.getContentLength();

	if (len > 0)
	{
		char req_body[8192];
		int ret;

		while (true)
		{
			ret = front->read_body(req_body, sizeof(req_body) - 1);
			if (ret < 0)
			{
				out_.puts(">>> read req body error");
				return false;
			}
			if (ret == 0)
				break;

			req_body[ret] = 0;
			out_.write(req_body, ret);
			if (backend->get_ostream().write(req_body, ret) == -1)
			{
				out_.puts(">>> write body to server error");
				return false;
			}
		}
	}
	out_.puts("");

	// 开始从后端服务器读取响应头和响应体数据

	out_.puts(">>>> begin read res header<<<<<");
	if (backend->read_head() == false)
	{
		out_.puts(">>>>>>>>read header error<<<<<<<<<<");
		return false;
	}

	acl::string res_hdr;
	backend->sprint_header(res_hdr, NULL);
	if (res.getOutputStream().write(res_hdr) == -1)
	{
		out_.puts(">>>>>write res hdr error<<<<<<");
		return false;
	}

	if (res.getOutputStream().write("\r\n") == -1)
	{
		out_.puts(">>>write CRLF error");
		return false;
	}

	out_.puts("------------------res hdr----------------");
	out_.write(res_hdr);
	out_.puts("------------------res hdr end------------");

	char buf[8192];

	while (true)
	{
		int ret = backend->read_body(buf, sizeof(buf) - 1);
		if (ret < 0)
		{
			logger_error(">>> read body error");
			return false;
		}
		else if (ret == 0)
			break;

		buf[ret] = 0;
		out_.write(buf, ret);
		if (res.getOutputStream().write(buf, ret) == -1)
		{
			out_.puts(">>> write res body error");
			return false;
		}
	}

	const char* ptr = backend->header_value("Transfer-Encoding");
	if (ptr == NULL || *ptr == 0 || strcasecmp(ptr, "chunked") != 0)
		return backend->keep_alive();

	// 发送 http 响应体,因为设置了 chunk 传输模式,所以需要多调用一次
	// res.write 且两个参数均为 0 以表示 chunk 传输数据结束
	return res.write(NULL, 0);
}
Beispiel #16
0
bool http_servlet::doPost(acl::HttpServletRequest& req,
	acl::HttpServletResponse& res)
{
	bool keep_alive = req.isKeepAlive();

	res.setContentType("text/html; charset=utf-8")	// 设置响应字符集
		.setKeepAlive(keep_alive)		// 设置是否保持长连接
		.setChunkedTransferEncoding(true);	// chunked 传输模式

	// 发送 http 响应体

	if (res.write("first line\r\nsecond line\r\nthird line\r\n\r\n") == false)
	{
		logger_error("write error!");
		return false;
	}

	for (int i = 0; i < 10; i++)
	{
		if (res.write("hello") == false)
		{
			logger_error("write error!");
			return false;
		}
		if (res.write(" ") == false)
		{
			logger_error("write error!");
			return false;
		}
		if (res.write("world") == false)
		{
			logger_error("write error!");
			return false;
		}
		if (res.write("\r\n") == false)
		{
			logger_error("write error!");
			return false;
		}
	}

	for (int j = 0; j < 10; j++)
	{
		for (int i = 0; i < 10; i++)
		{
			if (res.write("X") == false)
			{
				logger_error("write error!");
				return false;
			}
		}

		if (res.write("\r\n") == false)
		{
			logger_error("write error!");
			return false;
		}
	}

	// 最后一行不写 \r\n
	if (res.write("Bye") == false)
	{
		logger_error("write error!");
		return false;
	}

	return res.write(NULL, 0) && keep_alive;
}
Beispiel #17
0
bool http_servlet::doPost(acl::HttpServletRequest& req,
	acl::HttpServletResponse& res)
{
	res.setContentType("text/xml; charset=gbk")	// 设置响应字符集
		.setKeepAlive(req.isKeepAlive())	// 设置是否保持长连接
		.setContentEncoding(true)		// 自动支持压缩传输
		.setChunkedTransferEncoding(true);	// 采用 chunk 传输方式

	// 获得 HTTP 请求的数据类型,正常的参数类型,即 name&value 方式
	// 还是 MIME 数据类型,还是数据流类型
	acl::http_request_t request_type = req.getRequestType();
	if (request_type != acl::HTTP_REQUEST_MULTIPART_FORM)
	{
		acl::string buf;
		buf.format("<root error='should acl::HTTP_REQUEST_MULTIPART_FORM' />\r\n");
		(void) res.write(buf);
		(void) res.write(NULL, 0);
		return false;
	}

	// 先获得 Content-Type 对应的 http_ctype 对象
	mime_ = req.getHttpMime();
	if (mime_ == NULL)
	{
		logger_error("http_mime null");
		(void) doReply(req, res, "http_mime null");
		return false;
	}

	// 获得数据体的长度
	content_length_ = req.getContentLength();
	if (content_length_ <= 0)
	{
		logger_error("body empty");
		(void) doReply(req, res, "body empty");
		return false;
	}

	acl::string filepath;
#if defined(_WIN32) || defined(_WIN64)
	filepath.format("%s\\mime_file", var_cfg_var_path);
#else
	filepath.format("%s/mime_file", var_cfg_var_path);
#endif

	if (fp_.open_write(filepath) == false)
	{
		logger_error("open %s error %s",
			filepath.c_str(), acl::last_serror());
		(void) doReply(req, res, "open file error");
		return false;
	}

	// 设置原始文件存入路径
	mime_->set_saved_path(filepath);

	req_ = &req;
	res_ = &res;
	read_body_ = true;

	// 直接返回,从而触发异步读 HTTP 数据体过程
	return true;
}