| 3480 | if (ret == 0) continue; // poll timeout, retry until deadline |
| 3481 | |
| 3482 | ssize_t n = send(fd, p + sent, len - sent, MSG_NOSIGNAL); |
| 3483 | if (n < 0) { |
| 3484 | if (errno == EINTR) continue; |
| 3485 | if (errno == EAGAIN || errno == EWOULDBLOCK) continue; |
| 3486 | return false; // EPIPE, ECONNRESET, etc. |
| 3487 | } |
| 3488 | sent += n; |
| 3489 | deadline = std::chrono::steady_clock::now() + std::chrono::seconds(30); |
| 3490 | } |
| 3491 | return true; |
| 3492 | } |
| 3493 | |
| 3494 | bool HttpServer::send_response(int fd, int status, const std::string & content_type, |
| 3495 | const std::string & body) { |
| 3496 | const char * reason = "OK"; |
| 3497 | switch (status) { |
| 3498 | case 200: reason = "OK"; break; |
| 3499 | case 204: reason = "No Content"; break; |
| 3500 | case 400: reason = "Bad Request"; break; |
| 3501 | case 404: reason = "Not Found"; break; |
| 3502 | case 405: reason = "Method Not Allowed"; break; |
| 3503 | case 413: reason = "Payload Too Large"; break; |
| 3504 | case 500: reason = "Internal Server Error"; break; |
| 3505 | case 503: reason = "Service Unavailable"; break; |
| 3506 | } |
| 3507 | std::string header = "HTTP/1.1 " + std::to_string(status) + " " + reason + "\r\n"; |
| 3508 | if (config_.enable_cors) { |
| 3509 | header += "Access-Control-Allow-Origin: *\r\n" |
| 3510 | "Access-Control-Allow-Methods: GET, POST, OPTIONS\r\n" |
| 3511 | "Access-Control-Allow-Headers: *\r\n"; |