Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -111,3 +111,5 @@ fabric.properties

# Android studio 3.1+ serialized cache file
.idea/caches/build_file_checksums.ser

webserv
28 changes: 26 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,4 +1,28 @@
all:
NAME := webserv
SRC_DIR := src
SRCS := $(shell find $(SRC_DIR) -name '*.cpp')
BUILD_DIR := dist
OBJS := $(addprefix $(BUILD_DIR)/,$(SRCS:.cpp=.o))
CXXFLAGS := -std=c++98 -I$(SRC_DIR)/lib -Wall -Wextra -Werror

all: $(NAME)

$(NAME): $(OBJS)
$(CXX) $(CXXFLAGS) -o $(NAME) $(OBJS)

$(BUILD_DIR)/%.o: %.cpp
@mkdir -p $(dir $@)
$(CXX) $(CXXFLAGS) -c $< -o $@

clean:
rm -rf $(BUILD_DIR)

fclean: clean
rm -rf $(NAME)

re: fclean all

format:
clang-format -i $$(git ls-files '*.cpp' '*.hpp')
clang-format -i $$(git ls-files '*.cpp' '*.hpp')

.PHONY: all clean fclean re format
2 changes: 1 addition & 1 deletion src/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
set(CMAKE_CXX_STANDARD 11) # TODO: C++98 にする
set(CMAKE_CXX_STANDARD 98) # TODO: C++98 にする
# 実行ファイルを /bin に出力
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/bin)

Expand Down
2 changes: 2 additions & 0 deletions src/cmd/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ int main(const int argc, char *argv[]) {
return 1;
}

SET_LOG_LEVEL(Logger::kInfo);

const Option<Config> config = Config::loadConfigFromFile(argv[1]);
if (config.isNone()) {
return 1;
Expand Down
2 changes: 1 addition & 1 deletion src/lib/cgi/factory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ namespace cgi {
http::Headers headers(res.getHeaders());

// 200 がデフォルト、Status ヘッダーがあればそれを使う
const http::Headers::const_iterator statusHeader = headers.find("Status");
const http::Headers::iterator statusHeader = headers.find("Status");
http::HttpStatusCode status = http::kStatusOk;
if (statusHeader != headers.end()) {
status = TRY(HttpResponseFactory::statusFromHeader(statusHeader->second)).unwrapOr(http::kStatusOk);
Expand Down
10 changes: 4 additions & 6 deletions src/lib/config/config.cpp
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
#include "config.hpp"

#include "http/handler/middleware/logger.hpp"
#include "toml/parser.hpp"
#include "toml/value.hpp"
#include "utils/logger.hpp"

#include <cstdlib>
#include <fstream>
#include <iostream>

namespace config {
/* Config */
Expand All @@ -27,7 +25,7 @@ namespace config {

Option<Config> Config::loadConfigFromFile(const std::string &path) {
try {
std::ifstream configFile(path);
std::ifstream configFile(path.c_str());
if (!configFile.is_open()) {
LOG_ERRORF("cannot open config file: %s", path.c_str());
return None;
Expand Down Expand Up @@ -117,7 +115,7 @@ namespace config {
toml::Table errorPageTable = serverTable.getValue("error_page").unwrap().getTable().unwrap();
std::vector<std::string> keys = errorPageTable.getKeys();
for (size_t j = 0; j < keys.size(); ++j) {
int statusCode = std::stoi(keys[j]);
int statusCode = static_cast<int>(std::strtol(keys[j].c_str(), NULL, 10));
Option<http::HttpStatusCode> httpStatusCode = http::httpStatusCodeFromInt(statusCode);
if (httpStatusCode.isNone()) {
LOG_WARNF("invalid HTTP status code: %d", statusCode);
Expand Down Expand Up @@ -242,7 +240,7 @@ namespace config {
for (size_t k = 0; k < methodValues.size(); ++k) {
std::string methodStr = methodValues[k].getString().unwrap();
http::HttpMethod method = http::httpMethodFromString(methodStr);
if (method == http::HttpMethod::kMethodUnknown) {
if (method == http::kMethodUnknown) {
LOG_ERRORF("unknown http method: %s", methodStr.c_str());
throw std::runtime_error("unknown method: " + methodStr);
}
Expand Down
23 changes: 14 additions & 9 deletions src/lib/config/toml/parser.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
#include "parser.hpp"

#include "utils/fd.hpp"
#include "utils/string.hpp"
#include "utils/types/try.hpp"

#include <cstdlib>

namespace toml {
TomlParser::TomlParser(const Tokenizer::Tokens &tokens)
: tokens_(tokens), pos_(0), nextPos_(0), token_(kUnknown, "") {
Expand Down Expand Up @@ -34,7 +39,7 @@ namespace toml {
return Ok(t);
}

return Err(error::AppError::kParseUnknown);
return Err(error::kParseUnknown);
}

void TomlParser::consumeNewlines() {
Expand Down Expand Up @@ -80,7 +85,7 @@ namespace toml {
TRY(expect(kRBracket));

if (keys.empty()) {
return Err(error::AppError::kParseUnknown);
return Err(error::kParseUnknown);
}

Table *currentTable = TRY(table.findOrCreateTablePath(keys));
Expand All @@ -93,12 +98,12 @@ namespace toml {
if (value.getType() == Value::kArray) {
Array &array = value.getArrayRef();
if (array.size() == 0) {
return Err(error::AppError::kParseUnknown);
return Err(error::kParseUnknown);
}
array.addElement(Value(newTable));
currentTable = &array.getElementRef(array.size() - 1).getTableRef();
} else {
return Err(error::AppError::kParseUnknown);
return Err(error::kParseUnknown);
}
} else {
Array array;
Expand All @@ -116,15 +121,15 @@ namespace toml {
TRY(expect(kRBracket));

if (keys.empty()) {
return Err(error::AppError::kParseUnknown);
return Err(error::kParseUnknown);
}

Table *currentTable = TRY(table.findOrCreateTablePath(keys));
const std::string &lastKey = keys.back();
const Table newTable;

if (currentTable->getValue(lastKey).isSome()) {
return Err(error::AppError::kParseUnknown);
return Err(error::kParseUnknown);
}

currentTable->setValue(lastKey, Value(newTable));
Expand All @@ -140,7 +145,7 @@ namespace toml {
Value val = TRY(parseVal());

if (keys.empty()) {
return Err(error::AppError::kParseUnknown);
return Err(error::kParseUnknown);
}

if (keys.size() == 1) {
Expand Down Expand Up @@ -200,7 +205,7 @@ namespace toml {
value = Value(token_.getValue());
nextToken();
} else if (peek(kNum)) {
value = Value(std::stol(token_.getValue()));
value = Value(std::strtol(token_.getValue().c_str(), NULL, 10));
nextToken();
} else if (peek(kLBracket)) {
nextToken();
Expand Down Expand Up @@ -246,7 +251,7 @@ namespace toml {
table = table.readOnly();
value = Value(table);
} else {
return Err(error::AppError::kParseUnknown);
return Err(error::kParseUnknown);
}

return Ok(value);
Expand Down
6 changes: 3 additions & 3 deletions src/lib/config/toml/value.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -246,7 +246,7 @@ namespace toml {

Result<Table *, error::AppError> Table::findOrCreateTablePath(const std::vector<std::string> &keys) {
if (keys.empty()) {
return Err(error::AppError::kParseUnknown);
return Err(error::kParseUnknown);
}

const size_t endIndex = keys.size() - 1;
Expand All @@ -271,11 +271,11 @@ namespace toml {
if (lastElement.getType() == Value::kTable) {
currentTable = &lastElement.getTableRef();
} else {
return Err(error::AppError::kParseUnknown);
return Err(error::kParseUnknown);
}
}
} else {
return Err(error::AppError::kParseUnknown);
return Err(error::kParseUnknown);
}
} else {
Table newTable;
Expand Down
4 changes: 3 additions & 1 deletion src/lib/core/action/run_cgi_action.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include "utils/fd.hpp"
#include "utils/time.hpp"
#include "utils/logger.hpp"
#include <cstdlib>

void RunCgiAction::execute(ActionContext &ctx) {
int pair[2];
Expand Down Expand Up @@ -135,6 +136,7 @@ void RunCgiAction::parentRoutine(const ActionContext &ctx, const int socketFd, c
ctx.getState().getEventNotifier().unregisterEvent(Event(clientFd_, Event::kWrite));
ctx.getState().getEventHandlerRepository().remove(clientFd_, Event::kRead);
ctx.getState().getEventHandlerRepository().remove(clientFd_, Event::kWrite);
CgiProcessRepository::Data data = {clientFd_, socketFd, utils::Time::getCurrentTime()};

const CgiProcessRepository::Data data = {clientFd_, socketFd, utils::Time::getCurrentTime()};
ctx.getState().getCgiProcessRepository().set(childPid, data);
}
2 changes: 1 addition & 1 deletion src/lib/core/action/serve_http_action.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ void ServeHttpAction::execute(ActionContext &actionCtx) {
const Option<Ref<VirtualServer> > vs = eventCtx_.getResolver().unwrap().resolve(hostHeader);

// accept したので Connection, VirtualServer は存在するはず
const http::RequestContext reqContext(req_, eventCtx_.getConnection().unwrap());
const http::RequestContext reqContext(req_, eventCtx_.getConnection().unwrap().toConst());
const Either<IAction *, http::Response> resOrAction = vs.unwrap().get().getRouter().serve(reqContext);
if (resOrAction.isLeft()) {
LOG_DEBUG("ServeHttpAction: action is returned");
Expand Down
4 changes: 3 additions & 1 deletion src/lib/core/child_reaper.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#include "child_reaper.hpp"
#include <sys/wait.h>
#include <cerrno>

void ChildReaper::attachToEventNotifier(IEventNotifier *notifier) const {
selfPipe_.registerWithEventNotifier(notifier);
Expand All @@ -12,7 +13,8 @@ std::vector<ChildReaper::ReapedProcess> ChildReaper::onSignalEvent() const {
while (true) {
int status = 0;
const pid_t pid = waitpid(-1, &status, WNOHANG);
result.push_back({pid, WEXITSTATUS(status)});
const ReapedProcess rp = {pid, WEXITSTATUS(status)};
result.push_back(rp);

if (pid > 0) {
continue;
Expand Down
9 changes: 5 additions & 4 deletions src/lib/core/handler/read_cgi_response_handler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ IEventHandler::InvokeResult ReadCgiResponseHandler::invoke(const Context &ctx) {
const ssize_t bytesRead = read(conn.getFd(), buffer, sizeof(buffer));
if (bytesRead == -1) {
LOG_WARN("failed to read CGI response");
return Err(error::AppError::kUnknown);
return Err(error::kUnknown);
}

if (bytesRead != 0) {
Expand All @@ -36,7 +36,8 @@ IEventHandler::InvokeResult ReadCgiResponseHandler::invoke(const Context &ctx) {
}

IEventHandler::ErrorHandleResult ReadCgiResponseHandler::onErrorEvent(const Context &, const Event &event) {
LOG_WARNF("ReadCgiResponseHandler received an error event %d", event.getTypeFlags());
// 結構うるさいので debug にする
LOG_DEBUGF("ReadCgiResponseHandler received an error event %d", event.getTypeFlags());

if (event.getTypeFlags() & Event::kHangUp) {
return ErrorHandleResult(false, std::vector<IAction *>());
Expand Down Expand Up @@ -115,8 +116,8 @@ Result<cgi::Response, error::AppError> ReadCgiResponseHandler::createCgiResponse
std::istringstream headerStream(headerPart);
std::string line;
while (std::getline(headerStream, line)) {
if (!line.empty() && line.back() == '\r') {
line.pop_back();
if (!line.empty() && line[line.length() - 1] == '\r') {
line = line.substr(0, line.length() - 1);
}
const http::RequestParser::ParseHeaderFieldLineResult result = http::RequestParser::parseHeaderFieldLine(line);
if (result.isOk()) {
Expand Down
2 changes: 1 addition & 1 deletion src/lib/core/handler/read_request_handler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ ReadRequestHandler::ReadRequestHandler(const VirtualServerResolver &vsResolver)

IEventHandler::InvokeResult ReadRequestHandler::invoke(const Context &ctx) {
LOG_DEBUG("start ReadRequestHandler");
const auto conn = ctx.getConnection().unwrap();
const Ref<Connection> conn = ctx.getConnection().unwrap();

// アクティビティを更新
ctx.getConnection().unwrap().get().updateActivity();
Expand Down
1 change: 1 addition & 0 deletions src/lib/core/handler/write_cgi_request_handler.cpp
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#include <cerrno>
#include <unistd.h>
#include <sys/socket.h>
#include "write_cgi_request_handler.hpp"
Expand Down
5 changes: 4 additions & 1 deletion src/lib/core/server.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include <map>
#include <signal.h>
#include <cstring>
#include <cerrno>

Server::Server(const config::Config &config) : config_(config) {
const config::ServerContextList &servers = config_.getServers();
Expand Down Expand Up @@ -125,7 +126,9 @@ void Server::start() {
void Server::invokeHandlers(const Context &ctx) {
const Event &event = ctx.getEvent();

const std::vector<Event::EventType> types = {Event::kRead, Event::kWrite};
std::vector<Event::EventType> types;
types.push_back(Event::kRead);
types.push_back(Event::kWrite);
// TODO: handler の呼び方が壊れてる
for (std::vector<Event::EventType>::const_iterator it = types.begin(); it != types.end(); ++it) {
const Event::EventType type = *it;
Expand Down
2 changes: 1 addition & 1 deletion src/lib/core/virtual_server_resolver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,5 +51,5 @@ VirtualServerResolverFactory::VirtualServerResolverFactory(const VirtualServerLi
: virtualServers_(virtualServers) {}

VirtualServerResolver VirtualServerResolverFactory::create(const Ref<Connection> &conn) {
return VirtualServerResolver(virtualServers_, conn);
return VirtualServerResolver(virtualServers_, conn.toConst());
}
3 changes: 2 additions & 1 deletion src/lib/event/event_notifier.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,8 @@ IEventNotifier::WaitEventsResult PollEventNotifier::waitEvents(int timeoutMs) {

const int result = poll(fds.data(), fds.size(), timeoutMs);
if (result == -1) {
LOG_ERRORF("poll failed: %s", std::strerror(errno));
// EINTR が起こりがちなので、debug にしておく
LOG_DEBUGF("poll failed: %s", std::strerror(errno));
return Err(error::kUnknown);
}

Expand Down
2 changes: 1 addition & 1 deletion src/lib/http/handler/cgi_handler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
// めんどくさくてメソッドにしてない
static bool fileExistsUnderRoot(const std::string &docRoot, const std::string &urlPath) {
std::string fsPath = docRoot;
if (!fsPath.empty() && fsPath.back() != '/') fsPath += '/';
if (!fsPath.empty() && fsPath[fsPath.length() - 1] != '/') fsPath += '/';
if (!urlPath.empty() && urlPath[0] == '/')
fsPath += urlPath.substr(1);
else
Expand Down
2 changes: 2 additions & 0 deletions src/lib/http/handler/delete_file_handler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
#include "http/response/response_builder.hpp"
#include "utils/logger.hpp"
#include <sys/stat.h>
#include <cerrno>
#include <cstdio>

namespace http {
DeleteFileHandler::DeleteFileHandler(const config::LocationContext::DocumentRootConfig &docRootConfig)
Expand Down
2 changes: 1 addition & 1 deletion src/lib/http/handler/middleware/error_page.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ Either<IAction *, http::Response> http::ErrorPage::intercept(const RequestContex
config::ServerContext::ErrorPageMap::iterator customErrorPage = errorPage_.find(status);

if (customErrorPage != errorPage_.end()) {
std::ifstream file(customErrorPage->second);
std::ifstream file(customErrorPage->second.c_str());
std::stringstream buf;
buf << file.rdbuf();
body = buf.str();
Expand Down
8 changes: 5 additions & 3 deletions src/lib/http/handler/upload_file_handler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -230,7 +230,8 @@ http::UploadFileHandler::processMultipartPart(const std::string &headers, std::s
// ヘッダーをCRLFで分割
const std::vector<std::string> headerLines = splitHeadersByNewline(headers);

for (const std::string &headerLine : headerLines) {
for (size_t i = 0; i < headerLines.size(); i++) {
const std::string &headerLine = headerLines[i];
// 空行や不正な形式の行はスキップ
if (headerLine.empty()) {
continue;
Expand Down Expand Up @@ -286,7 +287,8 @@ void http::UploadFileHandler::processContentDispositionHeader(
// 各パラメータをセミコロンで分割
const std::vector<std::string> params = utils::split(headerValue, ';');

for (const std::string &param : params) {
for (size_t i = 0; i < params.size(); i++) {
const std::string &param = params[i];
std::string trimmedParam = utils::trim(param);

// name属性の処理
Expand Down Expand Up @@ -317,7 +319,7 @@ http::Response
http::UploadFileHandler::saveUploadedFile(const std::string &filename, const std::string &content) const {
const std::string filePath = docConfig_.getRoot() + "/" + filename;

std::ofstream outFile(filePath, std::ios::binary);
std::ofstream outFile(filePath.c_str(), std::ios::binary);
if (!outFile) {
return ResponseBuilder().status(kStatusConflict).text("Failed to open file for writing: " + filename).build();
}
Expand Down
Loading
Loading