HttpResponseWriter.cpp 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  1. #include "HttpResponseWriter.h"
  2. namespace hv {
  3. int HttpResponseWriter::EndHeaders(const char* key /* = NULL */, const char* value /* = NULL */) {
  4. if (state != SEND_BEGIN) return -1;
  5. if (key && value) {
  6. response->SetHeader(key, value);
  7. }
  8. std::string headers = response->Dump(true, false);
  9. // erase Content-Length: 0\r\n
  10. std::string content_length_0("Content-Length: 0\r\n");
  11. auto pos = headers.find(content_length_0);
  12. if (pos != std::string::npos) {
  13. headers.erase(pos, content_length_0.size());
  14. }
  15. state = SEND_HEADER;
  16. return write(headers);
  17. }
  18. int HttpResponseWriter::WriteChunked(const char* buf, int len /* = -1 */) {
  19. int ret = 0;
  20. if (len == -1) len = strlen(buf);
  21. if (state == SEND_BEGIN) {
  22. EndHeaders("Transfer-Encoding", "chunked");
  23. }
  24. char chunked_header[64];
  25. int chunked_header_len = snprintf(chunked_header, sizeof(chunked_header), "%x\r\n", len);
  26. write(chunked_header, chunked_header_len);
  27. if (buf && len) {
  28. state = SEND_CHUNKED;
  29. ret = write(buf, len);
  30. } else {
  31. state = SEND_CHUNKED_END;
  32. }
  33. write("\r\n", 2);
  34. return ret;
  35. }
  36. int HttpResponseWriter::WriteBody(const char* buf, int len /* = -1 */) {
  37. if (response->IsChunked()) {
  38. return WriteChunked(buf, len);
  39. }
  40. if (len == -1) len = strlen(buf);
  41. if (state == SEND_BEGIN) {
  42. response->body.append(buf, len);
  43. return len;
  44. } else {
  45. state = SEND_BODY;
  46. return write(buf, len);
  47. }
  48. }
  49. int HttpResponseWriter::WriteResponse(HttpResponse* resp) {
  50. if (resp == NULL) {
  51. response->status_code = HTTP_STATUS_INTERNAL_SERVER_ERROR;
  52. return 0;
  53. }
  54. bool is_dump_headers = state == SEND_BEGIN ? true : false;
  55. std::string msg = resp->Dump(is_dump_headers, true);
  56. state = SEND_BODY;
  57. return write(msg);
  58. }
  59. int HttpResponseWriter::SSEvent(const std::string& data, const char* event /* = "message" */) {
  60. if (state == SEND_BEGIN) {
  61. EndHeaders("Content-Type", "text/event-stream");
  62. }
  63. std::string msg;
  64. if (event) {
  65. msg = "event: "; msg += event; msg += "\n";
  66. }
  67. msg += "data: "; msg += data; msg += "\n\n";
  68. state = SEND_BODY;
  69. return write(msg);
  70. }
  71. int HttpResponseWriter::End(const char* buf /* = NULL */, int len /* = -1 */) {
  72. if (end == SEND_END) return 0;
  73. end = SEND_END;
  74. if (!isConnected()) {
  75. return -1;
  76. }
  77. int ret = 0;
  78. bool keepAlive = response->IsKeepAlive();
  79. if (state == SEND_CHUNKED) {
  80. if (buf) {
  81. ret = WriteChunked(buf, len);
  82. }
  83. if (state == SEND_CHUNKED) {
  84. EndChunked();
  85. }
  86. } else {
  87. if (buf) {
  88. ret = WriteBody(buf, len);
  89. }
  90. bool is_dump_headers = true;
  91. bool is_dump_body = true;
  92. if (state == SEND_HEADER) {
  93. is_dump_headers = false;
  94. } else if (state == SEND_BODY) {
  95. is_dump_headers = false;
  96. is_dump_body = false;
  97. }
  98. if (is_dump_body) {
  99. std::string msg = response->Dump(is_dump_headers, is_dump_body);
  100. state = SEND_BODY;
  101. ret = write(msg);
  102. }
  103. }
  104. if (!keepAlive) {
  105. close(true);
  106. }
  107. return ret;
  108. }
  109. }