file_service.cc 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. #include "file_service.h"
  2. SubTask *FileService::create_error_task(int code,
  3. struct FileService::ModuleCtx *ctx)
  4. {
  5. if (ctx->is_error_set == false)
  6. {
  7. ctx->resp->set_status_code(std::to_string(code));
  8. ctx->is_error_set = true;
  9. const auto it = this->error_page.find(code);
  10. if (it != this->error_page.end())
  11. return this->create_file_task(it->second, ctx);
  12. }
  13. return WFTaskFactory::create_empty_task();
  14. }
  15. void FileService::pread_callback(WFFileIOTask *task)
  16. {
  17. FileIOArgs *args = task->get_args();
  18. long ret = task->get_retval();
  19. struct ModuleCtx *ctx = (struct ModuleCtx *)series_of(task)->get_context();
  20. protocol::HttpResponse *resp = ctx->resp;
  21. if (task->get_state() == WFT_STATE_SUCCESS)
  22. {
  23. resp->append_output_body_nocopy(args->buf, ret);
  24. }
  25. else
  26. {
  27. auto *error_task = this->create_error_task(503, ctx);
  28. series_of(task)->push_back(error_task);
  29. }
  30. }
  31. SubTask *FileService::create_file_task(const std::string& path,
  32. struct FileService::ModuleCtx *ctx)
  33. {
  34. SubTask *task;
  35. struct stat st;
  36. std::string abs_path = this->root + path;
  37. if (abs_path.back() == '/')
  38. abs_path += "index.html";
  39. if (stat(abs_path.c_str(), &st) >= 0)
  40. {
  41. size_t size = st.st_size;
  42. void *buf = malloc(size);
  43. if (buf)
  44. {
  45. ctx->buf = buf;
  46. auto&& cb = std::bind(&FileService::pread_callback,
  47. this, std::placeholders::_1);
  48. task = WFTaskFactory::create_pread_task(abs_path, buf, size, 0, cb);
  49. }
  50. else
  51. {
  52. task = this->create_error_task(503, ctx);
  53. }
  54. }
  55. else
  56. {
  57. task = this->create_error_task(404, ctx);
  58. }
  59. return task;
  60. }
  61. WFModuleTask *FileService::create_module(WFHttpTask *server_task,
  62. const std::string& path)
  63. {
  64. fprintf(stderr, "file service get request: %s\n", path.c_str());
  65. struct ModuleCtx *ctx = new ModuleCtx(server_task->get_resp());
  66. SubTask *next = this->create_file_task(path, ctx);
  67. WFModuleTask *module = WFTaskFactory::create_module_task(next,
  68. [server_task](const WFModuleTask *mod)
  69. {
  70. struct ModuleCtx *ctx;
  71. ctx = (struct ModuleCtx *)mod->sub_series()->get_context();
  72. void *buf = ctx->buf;
  73. server_task->set_callback([buf](WFHttpTask *t){ free(buf); });
  74. delete ctx;
  75. });
  76. module->sub_series()->set_context(ctx);
  77. return module;
  78. }
  79. void FileService::process(WFHttpTask *server_task)
  80. {
  81. protocol::HttpRequest *req = server_task->get_req();
  82. protocol::HttpResponse *resp = server_task->get_resp();
  83. std::string path = req->get_request_uri();
  84. auto pos = path.find_first_of('?');
  85. if (pos != std::string::npos)
  86. path = path.substr(0, pos);
  87. resp->add_header_pair("Server", "SRPC HTTP File Server");
  88. WFModuleTask *module = this->create_module(server_task, path);
  89. series_of(server_task)->push_back(module);
  90. }