-
Notifications
You must be signed in to change notification settings - Fork 3
/
WebServer.cc
111 lines (102 loc) · 2.51 KB
/
WebServer.cc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
#include "WebServer.hh"
#include <unistd.h>
#include <dirent.h>
#include <fstream>
#include <regex>
#include <algorithm>
#include <typeinfo>
using namespace ahttpd;
namespace {
/**
* \biref 查找index文件,目前仅支持index.html和index.php
*/
std::string
find_index(const std::string& path)
{
if(access((path + "index.html").c_str(), 0) == 0) {
return "index.html";
} else if(access((path + "index.php").c_str(), 0) == 0) {
return "index.php";
} else {
return "";
}
}
/**
* \brief 判断给定文件是否为目录
*/
bool
is_dir(const std::string& path)
{
if(opendir(path.c_str()) == nullptr)
return false;
return true;
}
}
void
WebServer::handleRequest(RequestPtr req, ResponsePtr res)
{
std::string file_name = doc_root;
std::string path = req->getPath();
std::string* host = req->getHeader("Host");
if(!host) {
res->setStatus(400);
return;
}
if(is_dir(doc_root + path) && path[path.size()-1] != '/') {
res->setStatus(302);
if(strcmp(res->connectionType(), "ssl") == 0) {
res->addHeader("Location", "https://" + *host + path + "/");
} else {
res->addHeader("Location", "http://" + *host + path + "/");
}
return;
}
if(path[path.size()-1] == '/') {
std::string index = find_index(doc_root + path);
if(index == "") {
res->setStatus(403);
return;
}
path += index;
}
if(path.rfind(".php") == path.size() - 4) { /**< 如果是php文件 */
req->setPath(path);
/** 就交给php-fpm处理 */
fcgi(server_->service(), "localhost", "9000", doc_root, req, res);
return;
}
/** 否则就直接发送请求的文件 */
file_name += path;
Log("DEBUG") << file_name;
std::ifstream file(file_name);
if(!file) {
/** 打不开(无论何种原因导致)都视为不存在 */
res->setStatus(Response::Not_Found);
return;
}
/** 同股后缀猜Mime */
std::string mime = guessMimeType(file_name);
if(mime.find("text") != mime.npos) /**< 比如text/plain, text/html */
mime += "; charset='utf-8'"; /**< 这样防止乱码 */
res->setMimeType(mime);
res->out() << file.rdbuf();
}
int
main(int argc, char* argv[])
{
try {
std::stringstream config("{\"http port\":\"8888\"}");
Server server(config);
if(argc < 2) {
/** 必须给出绝对路径,不然会出错 */
std::cout << "useage: ./webserver abs_doc_root" << std::endl;
return 0;
} else {
server.addHandler("/", new WebServer(&server, argv[1]));
}
server.run(10); /**< 给io_service 10个线程 */
} catch(std::exception& e) {
std::cerr << "exception: " << e.what() << "\n";
}
return 0;
}