#include "http.h"

#include <util/stream/output.h>

namespace NSrvKernel {

    TError TRequestLine::SetURL(TString url) noexcept {
        Path.Clear();
        CGI.Clear();

        Path = TStringStorage(std::move(url));
        TChunksOutputStream s(EncodedSize());
        Unparse(s);
        // This is for TMessageHeadEndingScanner to be able to find a request ending.
        s << CRLF;

        TRequest tmp;
        Y_PROPAGATE_ERROR(tmp.Parse(TString(StrInplace(s.Chunks()))));
        Swap(tmp.RequestLine());
        return {};
    }

    bool IsHttp(const TChunkList& lst) noexcept {
        char c;

        if (!lst.CopyDataTo(&c, 1)) {
            return false;
        }

        switch (c) {
        case 'g':
        case 'G':
        case 'p':
        case 'P':
        case 'h':
        case 'H':
        case 'd':
        case 'D':
        case 't':
        case 'T':
        case 'c':
        case 'C':
        case 'o':
        case 'O':
            return true;
        default:
            return false;
        }
    }

    bool IsHTTP2(const TRequest* mess) noexcept {
        return mess && mess->Props().HTTP2;
    }

    bool IsHTTP2CancelledByClient(const TRequest* mess) noexcept {
        if (const auto* h2 = mess ? mess->Props().HTTP2 : nullptr) {
            return h2->IsCancelledByClient();
        } else {
            return false;
        }
    }

    bool IsHTTP2ClosedByClient(const TRequest* mess) noexcept {
        if (const auto* h2 = mess ? mess->Props().HTTP2 : nullptr) {
            return h2->IsClosedByClient();
        } else {
            return false;
        }
    }

    bool NullResponseBody(ui16 status) noexcept {
        return status / 100 == 1 || IsIn({HTTP_NO_CONTENT, HTTP_NOT_MODIFIED}, status);
    }

}


template <>
void Out<NSrvKernel::TRequest>(IOutputStream& out, const NSrvKernel::TRequest& req) {
    req.BuildTo(out);
}
