154 lines
4.3 KiB
C++
154 lines
4.3 KiB
C++
//
|
|
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2022
|
|
//
|
|
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
|
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
|
//
|
|
#pragma once
|
|
|
|
#include "td/utils/logging.h"
|
|
#include "td/utils/Slice.h"
|
|
#include "td/utils/SliceBuilder.h"
|
|
#include "td/utils/Status.h"
|
|
#include "td/utils/StringBuilder.h"
|
|
|
|
namespace td {
|
|
|
|
class HttpHeaderCreator {
|
|
public:
|
|
static constexpr size_t MAX_HEADER = 4096;
|
|
HttpHeaderCreator() : sb_(MutableSlice{header_, MAX_HEADER}) {
|
|
}
|
|
void init_ok() {
|
|
sb_ = StringBuilder(MutableSlice{header_, MAX_HEADER});
|
|
sb_ << "HTTP/1.1 200 OK\r\n";
|
|
}
|
|
void init_get(Slice url) {
|
|
sb_ = StringBuilder(MutableSlice{header_, MAX_HEADER});
|
|
sb_ << "GET " << url << " HTTP/1.1\r\n";
|
|
}
|
|
void init_post(Slice url) {
|
|
sb_ = StringBuilder(MutableSlice{header_, MAX_HEADER});
|
|
sb_ << "POST " << url << " HTTP/1.1\r\n";
|
|
}
|
|
void init_error(int code, Slice reason) {
|
|
sb_ = StringBuilder(MutableSlice{header_, MAX_HEADER});
|
|
sb_ << "HTTP/1.1 " << code << " " << reason << "\r\n";
|
|
}
|
|
void init_status_line(int http_status_code) {
|
|
init_error(http_status_code, get_status_line(http_status_code));
|
|
}
|
|
void add_header(Slice key, Slice value) {
|
|
sb_ << key << ": " << value << "\r\n";
|
|
}
|
|
void set_content_type(Slice type) {
|
|
add_header("Content-Type", type);
|
|
}
|
|
void set_content_size(size_t size) {
|
|
add_header("Content-Length", PSLICE() << size);
|
|
}
|
|
void set_keep_alive() {
|
|
add_header("Connection", "keep-alive");
|
|
}
|
|
|
|
Result<Slice> finish(Slice content = {}) TD_WARN_UNUSED_RESULT {
|
|
sb_ << "\r\n";
|
|
if (!content.empty()) {
|
|
sb_ << content;
|
|
}
|
|
if (sb_.is_error()) {
|
|
return Status::Error("Too many headers");
|
|
}
|
|
return sb_.as_cslice();
|
|
}
|
|
|
|
private:
|
|
static CSlice get_status_line(int http_status_code) {
|
|
if (http_status_code == 200) {
|
|
return CSlice("OK");
|
|
}
|
|
switch (http_status_code) {
|
|
case 201:
|
|
return CSlice("Created");
|
|
case 202:
|
|
return CSlice("Accepted");
|
|
case 204:
|
|
return CSlice("No Content");
|
|
case 206:
|
|
return CSlice("Partial Content");
|
|
case 301:
|
|
return CSlice("Moved Permanently");
|
|
case 302:
|
|
return CSlice("Found");
|
|
case 303:
|
|
return CSlice("See Other");
|
|
case 304:
|
|
return CSlice("Not Modified");
|
|
case 307:
|
|
return CSlice("Temporary Redirect");
|
|
case 308:
|
|
return CSlice("Permanent Redirect");
|
|
case 400:
|
|
return CSlice("Bad Request");
|
|
case 401:
|
|
return CSlice("Unauthorized");
|
|
case 403:
|
|
return CSlice("Forbidden");
|
|
case 404:
|
|
return CSlice("Not Found");
|
|
case 405:
|
|
return CSlice("Method Not Allowed");
|
|
case 406:
|
|
return CSlice("Not Acceptable");
|
|
case 408:
|
|
return CSlice("Request Timeout");
|
|
case 409:
|
|
return CSlice("Conflict");
|
|
case 410:
|
|
return CSlice("Gone");
|
|
case 411:
|
|
return CSlice("Length Required");
|
|
case 412:
|
|
return CSlice("Precondition Failed");
|
|
case 413:
|
|
return CSlice("Request Entity Too Large");
|
|
case 414:
|
|
return CSlice("Request-URI Too Long");
|
|
case 415:
|
|
return CSlice("Unsupported Media Type");
|
|
case 416:
|
|
return CSlice("Range Not Satisfiable");
|
|
case 417:
|
|
return CSlice("Expectation Failed");
|
|
case 418:
|
|
return CSlice("I'm a teapot");
|
|
case 421:
|
|
return CSlice("Misdirected Request");
|
|
case 426:
|
|
return CSlice("Upgrade Required");
|
|
case 429:
|
|
return CSlice("Too Many Requests");
|
|
case 431:
|
|
return CSlice("Request Header Fields Too Large");
|
|
case 480:
|
|
return CSlice("Temporarily Unavailable");
|
|
case 501:
|
|
return CSlice("Not Implemented");
|
|
case 502:
|
|
return CSlice("Bad Gateway");
|
|
case 503:
|
|
return CSlice("Service Unavailable");
|
|
case 505:
|
|
return CSlice("HTTP Version Not Supported");
|
|
default:
|
|
LOG_IF(ERROR, http_status_code != 500) << "Unsupported status code " << http_status_code << " returned";
|
|
return CSlice("Internal Server Error");
|
|
}
|
|
}
|
|
|
|
char header_[MAX_HEADER];
|
|
StringBuilder sb_;
|
|
};
|
|
|
|
} // namespace td
|