Skip to content

Commit

Permalink
move http parseRequest to HttpContext class
Browse files Browse the repository at this point in the history
  • Loading branch information
decimalbell committed Aug 1, 2015
1 parent 90a5866 commit c245ae7
Show file tree
Hide file tree
Showing 5 changed files with 131 additions and 125 deletions.
3 changes: 2 additions & 1 deletion muduo/net/http/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
set(http_SRCS
HttpServer.cc
HttpResponse.cc
HttpContext.cc
)

add_library(muduo_http ${http_SRCS})
Expand All @@ -19,7 +20,7 @@ add_executable(httpserver_test tests/HttpServer_test.cc)
target_link_libraries(httpserver_test muduo_http)

if(BOOSTTEST_LIBRARY)
add_executable(httprequest_unittest tests/HttpRequest_unittest.cc)
add_executable(httprequest_unittest tests/HttpRequest_unittest.cc HttpContext.cc)
target_link_libraries(httprequest_unittest muduo_http boost_unit_test_framework)
endif()

Expand Down
117 changes: 117 additions & 0 deletions muduo/net/http/HttpContext.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
// Copyright 2010, Shuo Chen. All rights reserved.
// http://code.google.com/p/muduo/
//
// Use of this source code is governed by a BSD-style license
// that can be found in the License file.

// Author: Shuo Chen (chenshuo at chenshuo dot com)
//

#include <muduo/net/Buffer.h>
#include <muduo/net/http/HttpContext.h>

using namespace muduo;
using namespace muduo::net;

bool HttpContext::processRequestLine(const char* begin, const char* end)
{
bool succeed = false;
const char* start = begin;
const char* space = std::find(start, end, ' ');
if (space != end && request_.setMethod(start, space))
{
start = space+1;
space = std::find(start, end, ' ');
if (space != end)
{
const char* question = std::find(start, space, '?');
if (question != space)
{
request_.setPath(start, question);
request_.setQuery(question, space);
}
else
{
request_.setPath(start, space);
}
start = space+1;
succeed = end-start == 8 && std::equal(start, end-1, "HTTP/1.");
if (succeed)
{
if (*(end-1) == '1')
{
request_.setVersion(HttpRequest::kHttp11);
}
else if (*(end-1) == '0')
{
request_.setVersion(HttpRequest::kHttp10);
}
else
{
succeed = false;
}
}
}
}
return succeed;
}

// return false if any error
bool HttpContext::parseRequest(Buffer* buf, Timestamp receiveTime)
{
bool ok = true;
bool hasMore = true;
while (hasMore)
{
if (expectRequestLine())
{
const char* crlf = buf->findCRLF();
if (crlf)
{
ok = processRequestLine(buf->peek(), crlf);
if (ok)
{
request_.setReceiveTime(receiveTime);
buf->retrieveUntil(crlf + 2);
receiveRequestLine();
}
else
{
hasMore = false;
}
}
else
{
hasMore = false;
}
}
else if (expectHeaders())
{
const char* crlf = buf->findCRLF();
if (crlf)
{
const char* colon = std::find(buf->peek(), crlf, ':');
if (colon != crlf)
{
request_.addHeader(buf->peek(), colon, crlf);
}
else
{
// empty line, end of header
receiveHeaders();
hasMore = !gotAll();
}
buf->retrieveUntil(crlf + 2);
}
else
{
hasMore = false;
}
}
else if (expectBody())
{
// FIXME:
}
}
return ok;
}
7 changes: 7 additions & 0 deletions muduo/net/http/HttpContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ namespace muduo
namespace net
{

class Buffer;

class HttpContext : public muduo::copyable
{
public:
Expand All @@ -38,6 +40,11 @@ class HttpContext : public muduo::copyable

// default copy-ctor, dtor and assignment are fine

bool processRequestLine(const char* begin, const char* end);

// return false if any error
bool parseRequest(Buffer* buf, Timestamp receiveTime);

bool expectRequestLine() const
{ return state_ == kExpectRequestLine; }

Expand Down
108 changes: 1 addition & 107 deletions muduo/net/http/HttpServer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -26,112 +26,6 @@ namespace net
namespace detail
{

// FIXME: move to HttpContext class
bool processRequestLine(const char* begin, const char* end, HttpContext* context)
{
bool succeed = false;
const char* start = begin;
const char* space = std::find(start, end, ' ');
HttpRequest& request = context->request();
if (space != end && request.setMethod(start, space))
{
start = space+1;
space = std::find(start, end, ' ');
if (space != end)
{
const char* question = std::find(start, space, '?');
if (question != space)
{
request.setPath(start, question);
request.setQuery(question, space);
}
else
{
request.setPath(start, space);
}
start = space+1;
succeed = end-start == 8 && std::equal(start, end-1, "HTTP/1.");
if (succeed)
{
if (*(end-1) == '1')
{
request.setVersion(HttpRequest::kHttp11);
}
else if (*(end-1) == '0')
{
request.setVersion(HttpRequest::kHttp10);
}
else
{
succeed = false;
}
}
}
}
return succeed;
}

// FIXME: move to HttpContext class
// return false if any error
bool parseRequest(Buffer* buf, HttpContext* context, Timestamp receiveTime)
{
bool ok = true;
bool hasMore = true;
while (hasMore)
{
if (context->expectRequestLine())
{
const char* crlf = buf->findCRLF();
if (crlf)
{
ok = processRequestLine(buf->peek(), crlf, context);
if (ok)
{
context->request().setReceiveTime(receiveTime);
buf->retrieveUntil(crlf + 2);
context->receiveRequestLine();
}
else
{
hasMore = false;
}
}
else
{
hasMore = false;
}
}
else if (context->expectHeaders())
{
const char* crlf = buf->findCRLF();
if (crlf)
{
const char* colon = std::find(buf->peek(), crlf, ':');
if (colon != crlf)
{
context->request().addHeader(buf->peek(), colon, crlf);
}
else
{
// empty line, end of header
context->receiveHeaders();
hasMore = !context->gotAll();
}
buf->retrieveUntil(crlf + 2);
}
else
{
hasMore = false;
}
}
else if (context->expectBody())
{
// FIXME:
}
}
return ok;
}

void defaultHttpCallback(const HttpRequest&, HttpResponse* resp)
{
resp->setStatusCode(HttpResponse::k404NotFound);
Expand Down Expand Up @@ -181,7 +75,7 @@ void HttpServer::onMessage(const TcpConnectionPtr& conn,
{
HttpContext* context = boost::any_cast<HttpContext>(conn->getMutableContext());

if (!detail::parseRequest(buf, context, receiveTime))
if (!context->parseRequest(buf, receiveTime))
{
conn->send("HTTP/1.1 400 Bad Request\r\n\r\n");
conn->shutdown();
Expand Down
21 changes: 4 additions & 17 deletions muduo/net/http/tests/HttpRequest_unittest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -12,19 +12,6 @@ using muduo::net::Buffer;
using muduo::net::HttpContext;
using muduo::net::HttpRequest;

namespace muduo
{
namespace net
{
namespace detail
{
bool parseRequest(Buffer* buf, HttpContext* context, Timestamp receiveTime);
}
}
}

using muduo::net::detail::parseRequest;

BOOST_AUTO_TEST_CASE(testParseRequestAllInOne)
{
HttpContext context;
Expand All @@ -33,7 +20,7 @@ BOOST_AUTO_TEST_CASE(testParseRequestAllInOne)
"Host: www.chenshuo.com\r\n"
"\r\n");

BOOST_CHECK(parseRequest(&input, &context, Timestamp::now()));
BOOST_CHECK(context.parseRequest(&input, Timestamp::now()));
BOOST_CHECK(context.gotAll());
const HttpRequest& request = context.request();
BOOST_CHECK_EQUAL(request.method(), HttpRequest::kGet);
Expand All @@ -54,12 +41,12 @@ BOOST_AUTO_TEST_CASE(testParseRequestInTwoPieces)
HttpContext context;
Buffer input;
input.append(all.c_str(), sz1);
BOOST_CHECK(parseRequest(&input, &context, Timestamp::now()));
BOOST_CHECK(context.parseRequest(&input, Timestamp::now()));
BOOST_CHECK(!context.gotAll());

size_t sz2 = all.size() - sz1;
input.append(all.c_str() + sz1, sz2);
BOOST_CHECK(parseRequest(&input, &context, Timestamp::now()));
BOOST_CHECK(context.parseRequest(&input, Timestamp::now()));
BOOST_CHECK(context.gotAll());
const HttpRequest& request = context.request();
BOOST_CHECK_EQUAL(request.method(), HttpRequest::kGet);
Expand All @@ -80,7 +67,7 @@ BOOST_AUTO_TEST_CASE(testParseRequestEmptyHeaderValue)
"Accept-Encoding: \r\n"
"\r\n");

BOOST_CHECK(parseRequest(&input, &context, Timestamp::now()));
BOOST_CHECK(context.parseRequest(&input, Timestamp::now()));
BOOST_CHECK(context.gotAll());
const HttpRequest& request = context.request();
BOOST_CHECK_EQUAL(request.method(), HttpRequest::kGet);
Expand Down

0 comments on commit c245ae7

Please sign in to comment.