示例#1
0
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
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;
}
示例#4
0
/**
 * Aborts processing current request with given HTTP status code.
 *
 * This method is supposed to be invoked within the Request parsing state.
 * It will reply the current request with the given \p status code and close the connection.
 * This is kind of a soft abort, as the client will be notified about the soft error with a proper reply.
 *
 * \param status the HTTP status code (should be a 4xx client error).
 *
 * \see abort()
 */
void HttpConnection::abort(HttpStatus status)
{
	++requestCount_;

	flags_ |= IsHandlingRequest;
	setStatus(ProcessingRequest);
	setShouldKeepAlive(false);

	request_->status = status;
	request_->finish();
}
示例#5
0
/** processes a (partial) request from buffer's given \p offset of \p count bytes.
 */
bool HttpConnection::process()
{
	TRACE("process: offset=%ld, size=%ld (before processing)", inputOffset_, input_.size());

	while (state() != MESSAGE_BEGIN || status() == ReadingRequest || status() == KeepAliveRead) {
		BufferRef chunk(input_.ref(inputOffset_));
		if (chunk.empty())
			break;

		// ensure status is up-to-date, in case we came from keep-alive-read
		if (status_ == KeepAliveRead) {
			TRACE("process: status=keep-alive-read, resetting to reading-request");
			status_ = ReadingRequest;
			if (request_->isFinished()) {
				TRACE("process: finalizing request");
				request_->finalize();
			}
		}

		TRACE("process: (size: %ld, isHandlingRequest:%d, state:%s status:%s", chunk.size(), (flags_ & IsHandlingRequest) != 0, state_str(), status_str());
		//TRACE("%s", input_.ref(input_.size() - rv).str().c_str());

		HttpMessageProcessor::process(chunk, &inputOffset_);
		TRACE("process: done process()ing; fd=%d, request=%p state:%s status:%s", socket_->handle(), request_, state_str(), status_str());

		if (isAborted())
			return false;

		if (state() == SYNTAX_ERROR) {
			if (!request_->isFinished()) {
				setShouldKeepAlive(false);
				request_->status = HttpError::BadRequest;
				request_->finish();
			}
			return false;
		}
	}

	TRACE("process: offset=%ld, bs=%ld, state=%s (after processing) io.timer:%d",
			inputOffset_, input_.size(), state_str(), socket_->timerActive());

	return true;
}
示例#6
0
void HttpConnection::timeout(Socket *)
{
	TRACE("timedout: status=%s",  status_str());

	switch (status()) {
	case StartingUp:
		TRACE("timeout: BUG. we should have never reached here.");
		break;
	case ReadingRequest:
		// we do not want further out-timing requests on this conn: just close it.
		setShouldKeepAlive(false);

		request_->status = HttpError::RequestTimeout;
		status_ = SendingReply;
		request_->finish();
		break;
	case KeepAliveRead:
		close();
		break;
	case SendingReply:
		abort();
		break;
	}
}