2018-05-14 16:40:03 +08:00
|
|
|
// 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)
|
|
|
|
//
|
|
|
|
// This is a public header file, it must only include public header files.
|
|
|
|
|
|
|
|
|
|
|
|
//taken from muduo and modified
|
2018-05-31 17:00:31 +08:00
|
|
|
|
|
|
|
/**
|
|
|
|
*
|
|
|
|
* @file
|
|
|
|
* @author An Tao
|
|
|
|
* @section LICENSE
|
|
|
|
*
|
|
|
|
* Copyright 2018, An Tao. All rights reserved.
|
|
|
|
* Use of this source code is governed by a MIT license
|
|
|
|
* that can be found in the License file.
|
|
|
|
*
|
|
|
|
* @section DESCRIPTION
|
|
|
|
*
|
|
|
|
*/
|
2018-05-14 16:40:03 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#pragma once
|
|
|
|
|
|
|
|
#include <drogon/HttpResponse.h>
|
|
|
|
#include <trantor/utils/MsgBuffer.h>
|
2018-06-21 17:44:19 +08:00
|
|
|
#include <trantor/net/InetAddress.h>
|
2018-09-11 16:49:22 +08:00
|
|
|
#include <trantor/utils/Date.h>
|
2018-09-11 17:31:10 +08:00
|
|
|
#include <drogon/utils/Utilities.h>
|
2018-05-14 16:40:03 +08:00
|
|
|
#include <map>
|
|
|
|
#include <string>
|
2018-09-11 16:49:22 +08:00
|
|
|
|
2018-05-14 16:40:03 +08:00
|
|
|
using namespace trantor;
|
|
|
|
namespace drogon
|
|
|
|
{
|
|
|
|
class HttpResponseImpl:public HttpResponse
|
|
|
|
{
|
|
|
|
friend class HttpContext;
|
|
|
|
public:
|
|
|
|
|
|
|
|
explicit HttpResponseImpl()
|
2018-06-21 15:39:11 +08:00
|
|
|
: _statusCode(kUnknown),
|
|
|
|
_closeConnection(false),
|
|
|
|
_left_body_length(0),
|
|
|
|
_current_chunk_length(0)
|
2018-05-14 16:40:03 +08:00
|
|
|
{
|
2018-09-11 17:31:10 +08:00
|
|
|
_headers["Date"]=getHttpFullDate(trantor::Date::date());
|
2018-05-14 16:40:03 +08:00
|
|
|
}
|
2018-08-21 16:02:43 +08:00
|
|
|
virtual HttpStatusCode statusCode() override
|
|
|
|
{
|
|
|
|
return _statusCode;
|
|
|
|
}
|
2018-05-14 16:40:03 +08:00
|
|
|
virtual void setStatusCode(HttpStatusCode code) override
|
|
|
|
{
|
2018-06-21 15:39:11 +08:00
|
|
|
_statusCode = code;
|
2018-05-14 16:40:03 +08:00
|
|
|
setStatusMessage(web_response_code_to_string(code));
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual void setStatusCode(HttpStatusCode code, const std::string& status_message) override
|
|
|
|
{
|
2018-06-21 15:39:11 +08:00
|
|
|
_statusCode = code;
|
2018-05-14 16:40:03 +08:00
|
|
|
setStatusMessage(status_message);
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual void setVersion(const Version v) override
|
|
|
|
{
|
2018-06-21 15:39:11 +08:00
|
|
|
_v = v;
|
2018-05-14 16:40:03 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
virtual void setCloseConnection(bool on) override
|
|
|
|
{
|
2018-06-21 15:39:11 +08:00
|
|
|
_closeConnection = on;
|
2018-05-14 16:40:03 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
virtual bool closeConnection() const override
|
|
|
|
{
|
2018-06-21 15:39:11 +08:00
|
|
|
return _closeConnection;
|
2018-05-14 16:40:03 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
virtual void setContentTypeCode(uint8_t type) override
|
|
|
|
{
|
2018-06-21 15:39:11 +08:00
|
|
|
_contentType=type;
|
2018-05-14 16:40:03 +08:00
|
|
|
setContentType(web_content_type_to_string(type));
|
|
|
|
}
|
2018-09-06 14:45:29 +08:00
|
|
|
|
|
|
|
virtual void setContentTypeCodeAndCharacterSet(uint8_t type,const std::string charSet="utf-8") override
|
|
|
|
{
|
|
|
|
_contentType=type;
|
|
|
|
setContentType(web_content_type_and_charset_to_string(type,charSet));
|
|
|
|
}
|
|
|
|
|
2018-09-03 10:56:11 +08:00
|
|
|
virtual uint8_t getContentTypeCode() override
|
|
|
|
{
|
|
|
|
return _contentType;
|
|
|
|
}
|
2018-08-09 15:35:19 +08:00
|
|
|
// virtual uint8_t contentTypeCode() override
|
|
|
|
// {
|
|
|
|
// return _contentType;
|
|
|
|
// }
|
2018-05-14 16:40:03 +08:00
|
|
|
|
2018-08-09 15:35:19 +08:00
|
|
|
virtual std::string getHeader(const std::string& key) const override
|
2018-05-14 16:40:03 +08:00
|
|
|
{
|
2018-09-10 15:50:44 +08:00
|
|
|
auto field=key;
|
|
|
|
transform(field.begin(), field.end(), field.begin(), ::tolower);
|
|
|
|
auto iter=_headers.find(field);
|
2018-08-09 15:35:19 +08:00
|
|
|
if(iter == _headers.end())
|
2018-05-14 16:40:03 +08:00
|
|
|
{
|
|
|
|
return "";
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2018-08-09 15:35:19 +08:00
|
|
|
return iter->second;
|
2018-05-14 16:40:03 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
virtual void addHeader(const std::string& key, const std::string& value) override
|
|
|
|
{
|
2018-09-10 15:50:44 +08:00
|
|
|
auto field=key;
|
|
|
|
transform(field.begin(), field.end(), field.begin(), ::tolower);
|
|
|
|
_headers[field] = value;
|
2018-05-14 16:40:03 +08:00
|
|
|
}
|
|
|
|
|
2018-09-14 14:59:03 +08:00
|
|
|
virtual void addHeader(const std::string& key, std::string&& value) override
|
|
|
|
{
|
|
|
|
auto field=key;
|
|
|
|
transform(field.begin(), field.end(), field.begin(), ::tolower);
|
|
|
|
_headers[field] = std::move(value);
|
|
|
|
}
|
|
|
|
|
2018-05-14 16:40:03 +08:00
|
|
|
virtual void addHeader(const char* start, const char* colon, const char* end) override
|
|
|
|
{
|
|
|
|
std::string field(start, colon);
|
2018-09-10 15:50:44 +08:00
|
|
|
transform(field.begin(), field.end(), field.begin(), ::tolower);
|
2018-05-14 16:40:03 +08:00
|
|
|
++colon;
|
|
|
|
while (colon < end && isspace(*colon)) {
|
|
|
|
++colon;
|
|
|
|
}
|
|
|
|
std::string value(colon, end);
|
|
|
|
while (!value.empty() && isspace(value[value.size() - 1])) {
|
|
|
|
value.resize(value.size() - 1);
|
|
|
|
}
|
2018-06-21 15:39:11 +08:00
|
|
|
_headers[field] = value;
|
2018-09-10 15:50:44 +08:00
|
|
|
|
|
|
|
//FIXME:reponse cookie should be "Set-Cookie:...."
|
2018-05-14 16:40:03 +08:00
|
|
|
if(field == "cookie") {
|
|
|
|
//LOG_INFO<<"cookies!!!:"<<value;
|
|
|
|
std::string::size_type pos;
|
|
|
|
while((pos = value.find(";")) != std::string::npos) {
|
|
|
|
std::string coo = value.substr(0, pos);
|
|
|
|
auto epos = coo.find("=");
|
|
|
|
if(epos != std::string::npos) {
|
|
|
|
std::string cookie_name = coo.substr(0, epos);
|
|
|
|
std::string::size_type cpos=0;
|
2018-06-01 14:07:34 +08:00
|
|
|
while(cpos<cookie_name.length()&&isspace(cookie_name[cpos]))
|
2018-05-14 16:40:03 +08:00
|
|
|
cpos++;
|
|
|
|
cookie_name=cookie_name.substr(cpos);
|
|
|
|
std::string cookie_value = coo.substr(epos + 1);
|
2018-06-21 15:39:11 +08:00
|
|
|
_cookies.insert(std::make_pair(cookie_name,Cookie(cookie_name,cookie_value)));
|
2018-05-14 16:40:03 +08:00
|
|
|
}
|
|
|
|
value=value.substr(pos+1);
|
|
|
|
}
|
|
|
|
if(value.length()>0)
|
|
|
|
{
|
|
|
|
std::string &coo = value;
|
|
|
|
auto epos = coo.find("=");
|
|
|
|
if(epos != std::string::npos) {
|
|
|
|
std::string cookie_name = coo.substr(0, epos);
|
|
|
|
std::string::size_type cpos=0;
|
2018-06-01 14:07:34 +08:00
|
|
|
while(cpos<cookie_name.length()&&isspace(cookie_name[cpos]))
|
2018-05-14 16:40:03 +08:00
|
|
|
cpos++;
|
|
|
|
cookie_name=cookie_name.substr(cpos);
|
|
|
|
std::string cookie_value = coo.substr(epos + 1);
|
2018-06-21 15:39:11 +08:00
|
|
|
_cookies.insert(std::make_pair(cookie_name,Cookie(cookie_name,cookie_value)));
|
2018-05-14 16:40:03 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual void addCookie(const std::string& key, const std::string& value) override
|
|
|
|
{
|
2018-06-21 15:39:11 +08:00
|
|
|
_cookies.insert(std::make_pair(key,Cookie(key,value)));
|
2018-05-14 16:40:03 +08:00
|
|
|
}
|
2018-06-19 16:55:25 +08:00
|
|
|
|
|
|
|
virtual void addCookie(const Cookie &cookie) override
|
|
|
|
{
|
2018-06-21 15:39:11 +08:00
|
|
|
_cookies.insert(std::make_pair(cookie.key(),cookie));
|
2018-06-19 16:55:25 +08:00
|
|
|
}
|
|
|
|
|
2018-05-14 16:40:03 +08:00
|
|
|
virtual void setBody(const std::string& body) override
|
|
|
|
{
|
2018-06-21 15:39:11 +08:00
|
|
|
_body = body;
|
2018-05-14 16:40:03 +08:00
|
|
|
}
|
|
|
|
virtual void setBody(std::string&& body) override
|
|
|
|
{
|
2018-06-21 15:39:11 +08:00
|
|
|
_body = std::move(body);
|
2018-05-14 16:40:03 +08:00
|
|
|
}
|
2018-06-21 17:44:19 +08:00
|
|
|
|
2018-05-14 16:40:03 +08:00
|
|
|
virtual void redirect(const std::string& url) override
|
|
|
|
{
|
2018-06-21 15:39:11 +08:00
|
|
|
_headers["Location"] = url;
|
2018-05-14 16:40:03 +08:00
|
|
|
}
|
|
|
|
void appendToBuffer(MsgBuffer* output) const;
|
|
|
|
|
|
|
|
virtual void clear() override
|
|
|
|
{
|
2018-06-21 15:39:11 +08:00
|
|
|
_statusCode = kUnknown;
|
|
|
|
_v = kHttp11;
|
|
|
|
_statusMessage.clear();
|
|
|
|
_headers.clear();
|
|
|
|
_cookies.clear();
|
|
|
|
_body.clear();
|
|
|
|
_left_body_length = 0;
|
|
|
|
_current_chunk_length = 0;
|
2018-05-14 16:40:03 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// void setReceiveTime(trantor::Date t)
|
|
|
|
// {
|
|
|
|
// receiveTime_ = t;
|
|
|
|
// }
|
|
|
|
|
2018-09-03 10:56:11 +08:00
|
|
|
virtual const std::string & getBody() const override
|
|
|
|
{
|
|
|
|
return _body;
|
|
|
|
}
|
|
|
|
virtual std::string & getBody() override
|
2018-05-14 16:40:03 +08:00
|
|
|
{
|
2018-06-21 15:39:11 +08:00
|
|
|
return _body;
|
2018-05-14 16:40:03 +08:00
|
|
|
}
|
2018-07-24 18:50:25 +08:00
|
|
|
void swap(HttpResponseImpl &that)
|
|
|
|
{
|
|
|
|
_headers.swap(that._headers);
|
|
|
|
_cookies.swap(that._cookies);
|
|
|
|
std::swap(_statusCode,that._statusCode);
|
|
|
|
std::swap(_v,that._v);
|
|
|
|
_statusMessage.swap(that._statusMessage);
|
|
|
|
std::swap(_closeConnection,that._closeConnection);
|
|
|
|
_body.swap(that._body);
|
|
|
|
std::swap(_left_body_length,that._left_body_length);
|
|
|
|
std::swap(_current_chunk_length,that._current_chunk_length);
|
|
|
|
std::swap(_contentType,that._contentType);
|
2018-08-09 15:44:05 +08:00
|
|
|
_jsonPtr.swap(that._jsonPtr);
|
2018-07-24 18:50:25 +08:00
|
|
|
}
|
2018-08-09 15:44:05 +08:00
|
|
|
void parseJson() const
|
2018-08-09 15:35:19 +08:00
|
|
|
{
|
|
|
|
//parse json data in reponse
|
|
|
|
_jsonPtr=std::make_shared<Json::Value>();
|
|
|
|
Json::CharReaderBuilder builder;
|
|
|
|
builder["collectComments"] = false;
|
|
|
|
JSONCPP_STRING errs;
|
|
|
|
std::unique_ptr<Json::CharReader> reader(builder.newCharReader());
|
|
|
|
if (!reader->parse(_body.data(), _body.data() + _body.size(), _jsonPtr.get() , &errs))
|
|
|
|
{
|
|
|
|
LOG_ERROR<<errs;
|
|
|
|
_jsonPtr.reset();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
virtual const std::shared_ptr<Json::Value> getJsonObject() const override
|
|
|
|
{
|
2018-08-09 15:44:05 +08:00
|
|
|
if(!_jsonPtr){
|
|
|
|
parseJson();
|
|
|
|
}
|
2018-08-09 15:35:19 +08:00
|
|
|
return _jsonPtr;
|
|
|
|
}
|
2018-09-25 18:07:29 +08:00
|
|
|
const std::string &sendfileName() const {
|
|
|
|
return _sendfileName;
|
|
|
|
}
|
|
|
|
void setSendfile(const std::string &filename){
|
|
|
|
_sendfileName=filename;
|
|
|
|
}
|
2018-05-14 16:40:03 +08:00
|
|
|
protected:
|
2018-09-14 14:59:03 +08:00
|
|
|
static std::string web_content_type_to_string(uint8_t contenttype);
|
2018-09-06 14:45:29 +08:00
|
|
|
static const std::string web_content_type_and_charset_to_string(uint8_t contenttype,
|
|
|
|
const std::string &charSet);
|
|
|
|
|
2018-09-14 14:19:43 +08:00
|
|
|
static std::string web_response_code_to_string(int code);
|
2018-05-14 16:40:03 +08:00
|
|
|
|
|
|
|
private:
|
2018-06-21 15:39:11 +08:00
|
|
|
std::map<std::string, std::string> _headers;
|
|
|
|
std::map<std::string, Cookie> _cookies;
|
|
|
|
HttpStatusCode _statusCode;
|
2018-05-14 16:40:03 +08:00
|
|
|
// FIXME: add http version
|
2018-06-21 15:39:11 +08:00
|
|
|
Version _v;
|
|
|
|
std::string _statusMessage;
|
|
|
|
bool _closeConnection;
|
|
|
|
std::string _body;
|
|
|
|
size_t _left_body_length;
|
|
|
|
size_t _current_chunk_length;
|
|
|
|
uint8_t _contentType=CT_TEXT_HTML;
|
2018-06-21 17:44:19 +08:00
|
|
|
|
2018-09-25 18:07:29 +08:00
|
|
|
std::string _sendfileName;
|
2018-08-09 15:44:05 +08:00
|
|
|
mutable std::shared_ptr<Json::Value> _jsonPtr;
|
2018-05-14 16:40:03 +08:00
|
|
|
//trantor::Date receiveTime_;
|
|
|
|
|
|
|
|
void setContentType(const std::string& contentType)
|
|
|
|
{
|
|
|
|
addHeader("Content-Type", contentType);
|
|
|
|
}
|
2018-09-14 14:59:03 +08:00
|
|
|
void setContentType(std::string && contentType)
|
|
|
|
{
|
|
|
|
addHeader("Content-Type", std::move(contentType));
|
|
|
|
}
|
2018-05-14 16:40:03 +08:00
|
|
|
void setStatusMessage(const std::string& message)
|
|
|
|
{
|
2018-06-21 15:39:11 +08:00
|
|
|
_statusMessage = message;
|
2018-05-14 16:40:03 +08:00
|
|
|
}
|
2018-09-14 14:19:43 +08:00
|
|
|
void setStatusMessage(std::string && message)
|
|
|
|
{
|
|
|
|
_statusMessage = std::move(message);
|
|
|
|
}
|
2018-05-14 16:40:03 +08:00
|
|
|
};
|
2018-09-07 14:14:06 +08:00
|
|
|
typedef std::shared_ptr<HttpResponseImpl> HttpResponseImplPtr;
|
2018-05-14 16:40:03 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|