// File: DMLfor[P]TinyWebServer/./Handler.hpp
// Function: void start_server<WebServer::Server<boost::asio::ssl::stream<boost::asio::basic_stream_socket<boost::asio::ip::tcp, boost::asio::execution::any_executor<boost::asio::execution::context_as_t<boost::asio::execution_context&>, boost::asio::execution::detail::blocking::never_t<0>, boost::asio::execution::prefer_only<boost::asio::execution::detail::blocking::possibly_t<0>>, boost::asio::execution::prefer_only<boost::asio::execution::detail::outstanding_work::tracked_t<0>>, boost::asio::execution::prefer_only<boost::asio::execution::detail::outstanding_work::untracked_t<0>>, boost::asio::execution::prefer_only<boost::asio::execution::detail::relationship::fork_t<0>>, boost::asio::execution::prefer_only<boost::asio::execution::detail::relationship::continuation_t<0>>>>>>>(WebServer::Server<boost::asio::ssl::stream<boost::asio::basic_stream_socket<boost::asio::ip::tcp, boost::asio::execution::any_executor<boost::asio::execution::context_as_t<boost::asio::execution_context&>, boost::asio::execution::detail::blocking::never_t<0>, boost::asio::execution::prefer_only<boost::asio::execution::detail::blocking::possibly_t<0>>, boost::asio::execution::prefer_only<boost::asio::execution::detail::outstanding_work::tracked_t<0>>, boost::asio::execution::prefer_only<boost::asio::execution::detail::outstanding_work::untracked_t<0>>, boost::asio::execution::prefer_only<boost::asio::execution::detail::relationship::fork_t<0>>, boost::asio::execution::prefer_only<boost::asio::execution::detail::relationship::continuation_t<0>>>>>>&)
void start_server(SERVER_TYPE &server)
{
	// 向服务器增加请求资源的处理方法
	//
	// 处理访问 /string 的 POST 请求, 返回 POST 的字符串
	server.resource["^/string/?$"]["POST"] = [](std::ostream &response, Request &request)
	{
		// 从 istream 中获得字符串(*request.content)
		stringstream ss;
		// 将请求内容读取到 stringstream
		*request.content >> ss.rdbuf();
		string content = ss.str();
		// 直接返回请求结果
		response << "HTTP/1.1 200 Ok\r\nContent-Length: "<< content.length() << "\r\n\r\n" <<content;
	};
	// 处理访问 /info GET 的请求，返回请求的信息
	server.resource["^/info/?$"]["GET"] = [](ostream &response, Request &request)
	{
		stringstream content_stream;
		content_stream << "<h1>Request:</h1>";
		content_stream << request.method << " " <<request.path << " HTTP/" << request.http_version << "<br>";
		for(auto &header: request.header){
			content_stream << header.first << ": "<<header.second << "<br>";
		}
		//　获得 content_stream 的长度(使用 content.tellp()　获得)
		content_stream.seekp(0, ios::end);

		response << "HTTP/1.1 200 ok\r\nContent-Length: "<< content_stream.tellp() << "\r\n\r\n" << content_stream.rdbuf();
	};
	// 处理访问 /match/[字母+数字组成的字符串] 的 GET 请求，　例如执行 GET /match/abc123,　将返回 abc123
	server.resource["^/match/([0-9a-zA-Z]+)/?$"]["GET"] = [](ostream &response, Request & request)
	{
		string number = request.path_match[1];
		response << "HTTP/1.1 200 OK\r\nContent-Length: " << number.length() << "\r\n\r\n" << number;
	};
	
	// 处理默认的 GET请求,如果没有其他匹配成功, 则这个匿名函数会被调用
	// 将应答 web/ 目录及其子目录中的文件
	// 默认文件 : index.html
	server.default_resource["^/?(.*)$"]["GET"] = [](ostream &response, Request & request)
	{
		string filename = "web/";

		string path = request.path_match[1];
		
		//　防止使用'..' 来访问 web/　目录外的内容
		size_t last_pos = path.rfind(".");
		size_t current_pos = 0;
		size_t pos;
		while((pos=path.find('.', current_pos)) != string::npos && pos != last_pos)
		{
			current_pos = pos;
			path.erase(pos, 1);
			last_pos --;
		}

		filename += path;
		ifstream ifs;
		//　简单的平台无关的文件或目录检查
		if(filename.find('.') == string::npos)
		{
			if(filename[filename.length()-1] != '/')
				filename += '/';
			filename += "index.html";
		}

		ifs.open(filename, ifstream::in);

		if(ifs)
		{
			ifs.seekg(0, ios::end);
			size_t length = ifs.tellg();

			ifs.seekg(0, ios::beg);
			
			//　文件内容将拷贝到 response-stream 中，不应该用较大的文件
			response << "HTTP/1.1 200 OK\r\nContent-Length: " << length << "\r\n\r\n" << ifs.rdbuf();
			ifs.close();
		}
		else
		{
			// 文件不存在时，返回无法打开文件
			string content = "Could not open file" + filename;

			response << "HTTP/1.1 400 Bad Request\r\nContent-Length: " << content.length() << "\r\n\r\n" << content;
		}
	};
	// 运行 HTTP 服务器
	server.start();
}

// Assembly:
subq $0x208, %rsp            # imm = 0x208
movq %rdi, 0x200(%rsp)
movq 0x200(%rsp), %rax
addq $0x8, %rax
movq %rax, 0x98(%rsp)
leaq 0x1d7(%rsp), %rdi
movq %rdi, 0xa0(%rsp)
callq 0xcca0
movq 0xa0(%rsp), %rdx
leaq 0x6c618(%rip), %rsi     # 0x7a4ff
leaq 0x1d8(%rsp), %rdi
callq 0xcae0
jmp 0xdef6
movq 0x98(%rsp), %rdi
leaq 0x1d8(%rsp), %rsi
callq 0x73490
movq %rax, 0x90(%rsp)
jmp 0xdf15
leaq 0x19f(%rsp), %rdi
movq %rdi, 0x88(%rsp)
callq 0xcca0
movq 0x88(%rsp), %rdx
leaq 0x6c5d2(%rip), %rsi     # 0x7a50b
leaq 0x1a0(%rsp), %rdi
callq 0xcae0
jmp 0xdf48
movq 0x90(%rsp), %rdi
leaq 0x1a0(%rsp), %rsi
callq 0x73580
movq %rax, 0x80(%rsp)
jmp 0xdf67
movq 0x80(%rsp), %rdi
leaq 0x1ff(%rsp), %rsi
callq 0x735b0
leaq 0x1a0(%rsp), %rdi
callq 0xc9e0
leaq 0x19f(%rsp), %rdi
callq 0xcfa0
leaq 0x1d8(%rsp), %rdi
callq 0xc9e0
leaq 0x1d7(%rsp), %rdi
callq 0xcfa0
movq 0x200(%rsp), %rax
addq $0x8, %rax
movq %rax, 0x70(%rsp)
leaq 0x177(%rsp), %rdi
movq %rdi, 0x78(%rsp)
callq 0xcca0
movq 0x78(%rsp), %rdx
leaq 0x6c531(%rip), %rsi     # 0x7a510
leaq 0x178(%rsp), %rdi
callq 0xcae0
jmp 0xdfee
movq 0x70(%rsp), %rdi
leaq 0x178(%rsp), %rsi
callq 0x73490
movq %rax, 0x68(%rsp)
jmp 0xe007
leaq 0x14f(%rsp), %rdi
movq %rdi, 0x60(%rsp)
callq 0xcca0
movq 0x60(%rsp), %rdx
leaq 0x6c4f5(%rip), %rsi     # 0x7a51a
leaq 0x150(%rsp), %rdi
callq 0xcae0
jmp 0xe034
movq 0x68(%rsp), %rdi
leaq 0x150(%rsp), %rsi
callq 0x73580
movq %rax, 0x58(%rsp)
jmp 0xe04d
movq 0x58(%rsp), %rdi
leaq 0x19e(%rsp), %rsi
callq 0x73600
leaq 0x150(%rsp), %rdi
callq 0xc9e0
leaq 0x14f(%rsp), %rdi
callq 0xcfa0
leaq 0x178(%rsp), %rdi
callq 0xc9e0
leaq 0x177(%rsp), %rdi
callq 0xcfa0
movq 0x200(%rsp), %rax
addq $0x8, %rax
movq %rax, 0x48(%rsp)
leaq 0x127(%rsp), %rdi
movq %rdi, 0x50(%rsp)
callq 0xcca0
movq 0x50(%rsp), %rdx
leaq 0x6c45c(%rip), %rsi     # 0x7a51e
leaq 0x128(%rsp), %rdi
callq 0xcae0
jmp 0xe0d1
movq 0x48(%rsp), %rdi
leaq 0x128(%rsp), %rsi
callq 0x73490
movq %rax, 0x40(%rsp)
jmp 0xe0ea
leaq 0xff(%rsp), %rdi
movq %rdi, 0x38(%rsp)
callq 0xcca0
movq 0x38(%rsp), %rdx
leaq 0x6c412(%rip), %rsi     # 0x7a51a
leaq 0x100(%rsp), %rdi
callq 0xcae0
jmp 0xe117
movq 0x40(%rsp), %rdi
leaq 0x100(%rsp), %rsi
callq 0x73580
movq %rax, 0x30(%rsp)
jmp 0xe130
movq 0x30(%rsp), %rdi
leaq 0x14e(%rsp), %rsi
callq 0x73650
leaq 0x100(%rsp), %rdi
callq 0xc9e0
leaq 0xff(%rsp), %rdi
callq 0xcfa0
leaq 0x128(%rsp), %rdi
callq 0xc9e0
leaq 0x127(%rsp), %rdi
callq 0xcfa0
movq 0x200(%rsp), %rax
addq $0x38, %rax
movq %rax, 0x20(%rsp)
leaq 0xd7(%rsp), %rdi
movq %rdi, 0x28(%rsp)
callq 0xcca0
movq 0x28(%rsp), %rdx
leaq 0x6c393(%rip), %rsi     # 0x7a538
leaq 0xd8(%rsp), %rdi
callq 0xcae0
jmp 0xe1b4
movq 0x20(%rsp), %rdi
leaq 0xd8(%rsp), %rsi
callq 0x73490
movq %rax, 0x18(%rsp)
jmp 0xe1cd
leaq 0xaf(%rsp), %rdi
movq %rdi, 0x10(%rsp)
callq 0xcca0
movq 0x10(%rsp), %rdx
leaq 0x6c32f(%rip), %rsi     # 0x7a51a
leaq 0xb0(%rsp), %rdi
callq 0xcae0
jmp 0xe1fa
movq 0x18(%rsp), %rdi
leaq 0xb0(%rsp), %rsi
callq 0x73580
movq %rax, 0x8(%rsp)
jmp 0xe213
movq 0x8(%rsp), %rdi
leaq 0xfe(%rsp), %rsi
callq 0x736a0
leaq 0xb0(%rsp), %rdi
callq 0xc9e0
leaq 0xaf(%rsp), %rdi
callq 0xcfa0
leaq 0xd8(%rsp), %rdi
callq 0xc9e0
leaq 0xd7(%rsp), %rdi
callq 0xcfa0
movq 0x200(%rsp), %rdi
callq 0x736f0
addq $0x208, %rsp            # imm = 0x208
retq
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x1c8(%rsp)
movl %eax, 0x1c4(%rsp)
jmp 0xe2eb
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x1c8(%rsp)
movl %eax, 0x1c4(%rsp)
jmp 0xe2de
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x1c8(%rsp)
movl %eax, 0x1c4(%rsp)
jmp 0xe2d1
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x1c8(%rsp)
movl %eax, 0x1c4(%rsp)
leaq 0x1a0(%rsp), %rdi
callq 0xc9e0
leaq 0x19f(%rsp), %rdi
callq 0xcfa0
leaq 0x1d8(%rsp), %rdi
callq 0xc9e0
leaq 0x1d7(%rsp), %rdi
callq 0xcfa0
jmp 0xe4a5
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x1c8(%rsp)
movl %eax, 0x1c4(%rsp)
jmp 0xe37a
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x1c8(%rsp)
movl %eax, 0x1c4(%rsp)
jmp 0xe36d
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x1c8(%rsp)
movl %eax, 0x1c4(%rsp)
jmp 0xe360
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x1c8(%rsp)
movl %eax, 0x1c4(%rsp)
leaq 0x150(%rsp), %rdi
callq 0xc9e0
leaq 0x14f(%rsp), %rdi
callq 0xcfa0
leaq 0x178(%rsp), %rdi
callq 0xc9e0
leaq 0x177(%rsp), %rdi
callq 0xcfa0
jmp 0xe4a5
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x1c8(%rsp)
movl %eax, 0x1c4(%rsp)
jmp 0xe409
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x1c8(%rsp)
movl %eax, 0x1c4(%rsp)
jmp 0xe3fc
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x1c8(%rsp)
movl %eax, 0x1c4(%rsp)
jmp 0xe3ef
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x1c8(%rsp)
movl %eax, 0x1c4(%rsp)
leaq 0x100(%rsp), %rdi
callq 0xc9e0
leaq 0xff(%rsp), %rdi
callq 0xcfa0
leaq 0x128(%rsp), %rdi
callq 0xc9e0
leaq 0x127(%rsp), %rdi
callq 0xcfa0
jmp 0xe4a5
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x1c8(%rsp)
movl %eax, 0x1c4(%rsp)
jmp 0xe498
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x1c8(%rsp)
movl %eax, 0x1c4(%rsp)
jmp 0xe48b
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x1c8(%rsp)
movl %eax, 0x1c4(%rsp)
jmp 0xe47e
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x1c8(%rsp)
movl %eax, 0x1c4(%rsp)
leaq 0xb0(%rsp), %rdi
callq 0xc9e0
leaq 0xaf(%rsp), %rdi
callq 0xcfa0
leaq 0xd8(%rsp), %rdi
callq 0xc9e0
leaq 0xd7(%rsp), %rdi
callq 0xcfa0
movq 0x1c8(%rsp), %rdi
callq 0xc900
nopw %cs:(%rax,%rax)
nopl (%rax)