diff --git a/libraries/http_server/http_server/http_ctx.hh b/libraries/http_server/http_server/http_ctx.hh index 4321e68..85ceee2 100644 --- a/libraries/http_server/http_server/http_ctx.hh +++ b/libraries/http_server/http_server/http_ctx.hh @@ -361,15 +361,24 @@ template struct generic_http_ctx { close(fd); #else // Windows impl with basic read write. + size_t ext_pos = std::string_view(path).rfind('.'); + std::string_view content_type; + if (ext_pos != std::string::npos) { + auto type_itr = content_types.find(std::string_view(path).substr(ext_pos + 1).data()); + if (type_itr != content_types.end()) { + content_type = type_itr->second; set_header("Content-Type", content_type); + set_header("Cache-Control", "max-age=54000,immutable"); + } + } // Open file. - FILE* fd = fopen(path, "r"); - if (fd == nullptr) - throw http_error::not_found("File not found."); + FILE* fd; + if( (fd = fopen(path, "r" )) == NULL ) // C4996 + throw http_error::not_found("File not found."); + fseek(fd, 0L, SEEK_END); // Get file size. - DWORD file_size = 0; - GetFileSize(fd, &file_size); + long file_size = ftell(fd); // Writing the http headers. response_written_ = true; format_top_headers(output_stream); @@ -377,17 +386,22 @@ template struct generic_http_ctx { output_stream << "Content-Length: " << file_size << "\r\n\r\n"; // Add body output_stream.flush(); + rewind(fd); // Read the file and write it to the socket. size_t nread = 1; size_t offset = 0; while (nread != 0) { char buffer[4096]; - nread = _fread_nolock(buffer, sizeof(buffer), file_size - offset, fd); - offset += nread; - this->fiber.write(buffer, nread); + nread = _fread_nolock(buffer, sizeof(buffer), 1, fd); + offset += sizeof(buffer); + this->fiber.write(buffer, sizeof(buffer)); } - if (!feof(fd)) - throw http_error::not_found("Internal error: Could not reach the end of file."); + char buffer[4096]; + nread = _fread_nolock(buffer, file_size - offset, 1, fd); + this->fiber.write(buffer, file_size - offset); + fclose(fd); + // if (!feof(fd)) + // throw http_error::not_found("Internal error: Could not reach the end of file."); #endif } diff --git a/libraries/http_server/http_server/serve_directory.hh b/libraries/http_server/http_server/serve_directory.hh index a728f16..e090726 100644 --- a/libraries/http_server/http_server/serve_directory.hh +++ b/libraries/http_server/http_server/serve_directory.hh @@ -52,6 +52,7 @@ inline auto serve_file(const std::string& root, std::string_view path, http_resp if (!path.empty() && path[0] == slash) { path = std::string_view(path.data() + 1, path.size() - 1); // erase(0, 1); } + if (path[0] == ' ') path = "index.html"; // Directory listing not supported. std::string full_path(root + std::string(path)); @@ -87,9 +88,15 @@ inline auto serve_directory(const std::string& root) { // Ensure the root ends with a / std::string real_root(realpath_out); +#if _WIN32 + if (real_root.back() != '\\') { + real_root.push_back('\\'); + } +#else if (real_root.back() != '/') { real_root.push_back('/'); } +#endif http_api api; api.get("/{{path...}}") = [real_root](http_request& request, http_response& response) { diff --git a/libraries/http_server/http_server/tcp_server.hh b/libraries/http_server/http_server/tcp_server.hh index e9d6634..3e6dec2 100644 --- a/libraries/http_server/http_server/tcp_server.hh +++ b/libraries/http_server/http_server/tcp_server.hh @@ -285,6 +285,7 @@ struct async_reactor { #if defined _WIN32 typedef HANDLE epoll_handle_t; + u_long iMode = 0; #else typedef int epoll_handle_t; #endif @@ -445,8 +446,9 @@ struct async_reactor { } // Handle new connections. else if (listen_fd == event_fd) { +#ifndef _WIN32 while (true) { - +#endif // ============================================ // ACCEPT INCOMMING CONNECTION sockaddr_storage in_addr_storage; @@ -466,6 +468,13 @@ struct async_reactor { } // ============================================ + // ============================================ + // Subscribe epoll to the socket file descriptor. +#if _WIN32 + if (ioctlsocket(socket_fd, FIONBIO, &iMode) != NO_ERROR) continue; +#else + if (-1 == ::fcntl(socket_fd, F_SETFL, fcntl(socket_fd, F_GETFL, 0) | O_NONBLOCK)) continue; +#endif // ============================================ // Find a free fiber for this new connection. int fiber_idx = 0; @@ -475,12 +484,6 @@ struct async_reactor { fibers.resize((fibers.size() + 1) * 2); assert(fiber_idx < fibers.size()); // ============================================ - - // ============================================ - // Subscribe epoll to the socket file descriptor. - // FIXME Duplicate ?? - // if (-1 == fcntl(socket_fd, F_SETFL, fcntl(socket_fd, F_GETFL, 0) | O_NONBLOCK)) - // continue; #if __linux__ this->epoll_add(socket_fd, EPOLLIN | EPOLLOUT | EPOLLRDHUP | EPOLLET, fiber_idx); #elif _WIN32 @@ -528,7 +531,9 @@ struct async_reactor { return std::move(ctx.sink); }); // ============================================= - } +#ifndef _WIN32 + } +#endif } else // Data available on existing sockets. Wake up the fiber associated with // event_fd. {