예제 #1
0
파일: HttpConnection.cpp 프로젝트: crnt/x0
bool HttpConnection::onMessageBegin(const BufferRef& method, const BufferRef& uri, int versionMajor, int versionMinor)
{
	TRACE("onMessageBegin: '%s', '%s', HTTP/%d.%d", method.str().c_str(), uri.str().c_str(), versionMajor, versionMinor);

	request_->method = method;
	request_->uri = uri;
	url_decode(input_, request_->uri);

	std::size_t n = request_->uri.find("?");
	if (n != std::string::npos) {
		request_->path = request_->uri.ref(0, n);
		request_->query = request_->uri.ref(n + 1);
	} else {
		request_->path = request_->uri;
	}

	request_->httpVersionMajor = versionMajor;
	request_->httpVersionMinor = versionMinor;

	if (request_->supportsProtocol(1, 1))
		// FIXME? HTTP/1.1 is keeping alive by default. pass "Connection: close" to close explicitely
		setShouldKeepAlive(true);
	else
		setShouldKeepAlive(false);

	// limit request uri length
	if (request_->uri.size() > worker().server().maxRequestUriSize()) {
		request_->status = HttpError::RequestUriTooLong;
		request_->finish();
		return false;
	}

	return true;
}
예제 #2
0
bool HttpConnection::onMessageBegin(const BufferRef& method, const BufferRef& uri, int versionMajor, int versionMinor)
{
	TRACE(1, "onMessageBegin: '%s', '%s', HTTP/%d.%d", method.str().c_str(), uri.str().c_str(), versionMajor, versionMinor);

	request_->method = method;

	if (!request_->setUri(uri)) {
		abort(HttpStatus::BadRequest);
		return false;
	}

	request_->httpVersionMajor = versionMajor;
	request_->httpVersionMinor = versionMinor;

	if (request_->supportsProtocol(1, 1))
		// FIXME? HTTP/1.1 is keeping alive by default. pass "Connection: close" to close explicitely
		setShouldKeepAlive(true);
	else
		setShouldKeepAlive(false);

	// limit request uri length
	if (request_->unparsedUri.size() > worker().server().maxRequestUriSize()) {
		request_->status = HttpStatus::RequestUriTooLong;
		request_->finish();
		return false;
	}

	return true;
}
예제 #3
0
/**
 * Callback, invoked on each successfully parsed response header key/value pair.
 */
bool HealthMonitor::onMessageHeader(const BufferRef& name, const BufferRef& value)
{
	TRACE("onResponseHeader(name:%s, value:%s)", name.str().c_str(), value.str().c_str());

	if (x0::iequals(name, "Status")) {
		int status = value.ref(0, value.find(' ')).toInt();
		responseCode_ = static_cast<x0::HttpStatus>(status);
	}

	return true;
}
예제 #4
0
bool HttpFileMgr::Settings::openMimeTypes(const std::string& path)
{
	Buffer input;
	if (!readFile(path, &input))
		return false;

	auto lines = Tokenizer<BufferRef, Buffer>::tokenize(input, "\n");

	mimetypes.clear();

	for (auto line: lines) {
		line = line.trim();
		auto columns = Tokenizer<BufferRef, BufferRef>::tokenize(line, " \t");

		auto ci = columns.begin(), ce = columns.end();
		BufferRef mime = ci != ce ? *ci++ : BufferRef();

		if (!mime.empty() && mime[0] != '#') {
			for (; ci != ce; ++ci) {
				mimetypes[ci->str()] = mime.str();
			}
		}
	}

	return true;
}
예제 #5
0
/**
 * Callback, invoked on successfully parsed response status line.
 */
bool HealthMonitor::onMessageBegin(int versionMajor, int versionMinor, int code, const BufferRef& text)
{
	TRACE("onMessageBegin: (HTTP/%d.%d, %d, '%s')", versionMajor, versionMinor, code, text.str().c_str());

	responseCode_ = static_cast<HttpStatus>(code);

	return true;
}
예제 #6
0
파일: HttpConnection.cpp 프로젝트: crnt/x0
bool HttpConnection::onMessageHeader(const BufferRef& name, const BufferRef& value)
{
	if (request_->isFinished()) {
		// this can happen when the request has failed some checks and thus,
		// a client error message has been sent already.
		// we need to "parse" the remaining content anyways.
		TRACE("onMessageHeader() skip \"%s\": \"%s\"", name.str().c_str(), value.str().c_str());
		return true;
	}

	TRACE("onMessageHeader() \"%s\": \"%s\"", name.str().c_str(), value.str().c_str());

	if (iequals(name, "Host")) {
		auto i = value.find(':');
		if (i != BufferRef::npos)
			request_->hostname = value.ref(0, i);
		else
			request_->hostname = value;
		TRACE(" -- hostname set to \"%s\"", request_->hostname.str().c_str());
	} else if (iequals(name, "Connection")) {
		if (iequals(value, "close"))
			setShouldKeepAlive(false);
		else if (iequals(value, "keep-alive"))
			setShouldKeepAlive(true);
	}

	// limit the size of a single request header
	if (name.size() + value.size() > worker().server().maxRequestHeaderSize()) {
		TRACE("header too long. got %ld / %ld", name.size() + value.size(), worker().server().maxRequestHeaderSize());
		request_->status = HttpError::RequestEntityTooLarge;
		request_->finish();
		return false;
	}

	// limit the number of request headers
	if (request_->requestHeaders.size() > worker().server().maxRequestHeaderCount()) {
		TRACE("header count exceeded. got %ld / %ld", request_->requestHeaders.size(), worker().server().maxRequestHeaderCount());
		request_->status = HttpError::RequestEntityTooLarge;
		request_->finish();
		return false;
	}

	request_->requestHeaders.push_back(HttpRequestHeader(name, value));
	return true;
}
예제 #7
0
void print(const BufferRef& v, const char *msg = 0)
{
	char prefix[64];
	if (msg && *msg)
		snprintf(prefix, sizeof(prefix), "\nbuffer.view(%s)", msg);
	else
		snprintf(prefix, sizeof(prefix), "\nbuffer.view");

	if (v)
		printf("\n%s: '%s' (size=%zu)\n", prefix, v.str().c_str(), v.size());
	else
		printf("\n%s: NULL\n", prefix);
}
예제 #8
0
/** callback, invoked on every successfully parsed response header.
 *
 * We will pass this header directly to the client's response,
 * if that is NOT a connection-level header.
 */
bool HttpProxy::ProxyConnection::onMessageHeader(const BufferRef& name, const BufferRef& value)
{
	TRACE("ProxyConnection(%p).onHeader('%s', '%s')", (void*)this, name.str().c_str(), value.str().c_str());

	// XXX do not allow origin's connection-level response headers to be passed to the client.
	if (iequals(name, "Connection"))
		goto skip;

	if (iequals(name, "Transfer-Encoding"))
		goto skip;

	if (cloak_ && iequals(name, "Server")) {
		TRACE("skipping \"Server\"-header");
		goto skip;
	}

	request_->responseHeaders.push_back(name.str(), value.str());
	return true;

skip:
	TRACE("skip (connection-)level header");

	return true;
}
예제 #9
0
void FileInfoService::Config::loadMimetypes(const std::string& filename)
{
	Buffer input(x0::read_file(filename));
	auto lines = Tokenizer<BufferRef, Buffer>::tokenize(input, "\n");

	mimetypes.clear();

	for (auto line: lines) {
		line = line.trim();
		auto columns = Tokenizer<BufferRef, BufferRef>::tokenize(line, " \t");

		auto ci = columns.begin(), ce = columns.end();
		BufferRef mime = ci != ce ? *ci++ : BufferRef();

		if (!mime.empty() && mime[0] != '#') {
			for (; ci != ce; ++ci) {
				mimetypes[ci->str()] = mime.str();
			}
		}
	}
}
예제 #10
0
/** callback, invoked when the origin server has passed us the response status line.
 *
 * We will use the status code only.
 * However, we could pass the text field, too - once x0 core supports it.
 */
bool HttpProxy::ProxyConnection::onMessageBegin(int major, int minor, int code, const BufferRef& text)
{
	TRACE("ProxyConnection(%p).status(HTTP/%d.%d, %d, '%s')", (void*)this, major, minor, code, text.str().c_str());

	request_->status = static_cast<HttpError>(code);
	TRACE("status: %d", (int)request_->status);
	return true;
}