49 lines
1.9 KiB
Text
49 lines
1.9 KiB
Text
|
|
// SPDX-License-Identifier: AGPL-3.0-only
|
||
|
|
// SPDX-FileCopyrightText: Copyright (C) 2026 Catcrafts®
|
||
|
|
|
||
|
|
export module Crafter.Review:Http;
|
||
|
|
import std;
|
||
|
|
import :Json;
|
||
|
|
|
||
|
|
// The HTTP the driver needs: app_ready's preflight, the OpenRouter catalogue
|
||
|
|
// and key probe. On Crafter.Network's FetchHTTP1, which follows redirects; on
|
||
|
|
// top of it a status outside 2xx thrown as HttpError, and every other failure
|
||
|
|
// as Error with a fixed text, because those texts reach the run log and
|
||
|
|
// app_ready's detail. Proxies are not consulted (AGENTS.md).
|
||
|
|
export namespace Crafter::Review::Http {
|
||
|
|
struct Response {
|
||
|
|
std::int32_t status = 0;
|
||
|
|
std::string body;
|
||
|
|
};
|
||
|
|
|
||
|
|
// A status outside 2xx. what(): "HTTP Error 404: Not Found", with the
|
||
|
|
// standard reason phrase rather than the server's.
|
||
|
|
class HttpError : public std::runtime_error {
|
||
|
|
public:
|
||
|
|
HttpError(std::int32_t code, const std::string& message);
|
||
|
|
explicit HttpError(std::int32_t code);
|
||
|
|
std::int32_t Code() const;
|
||
|
|
|
||
|
|
private:
|
||
|
|
std::int32_t code;
|
||
|
|
};
|
||
|
|
|
||
|
|
// Every other failure. What fails while the request goes out reads
|
||
|
|
// "<urlopen error [Errno 111] Connection refused>" or "<urlopen error
|
||
|
|
// timed out>"; what fails while the response comes in reads as it is:
|
||
|
|
// "timed out".
|
||
|
|
class Error : public std::runtime_error {
|
||
|
|
public:
|
||
|
|
using std::runtime_error::runtime_error;
|
||
|
|
};
|
||
|
|
|
||
|
|
// A GET of `url`, read whole. Header names in any case; Accept-Encoding:
|
||
|
|
// identity and Connection: close always go out, and a User-Agent unless
|
||
|
|
// one is given.
|
||
|
|
Response UrlOpen(std::string_view url, const std::map<std::string, std::string>& headers, double timeout);
|
||
|
|
// The body as JSON: Dyn::Error JSONDecodeError (or UnicodeDecodeError)
|
||
|
|
// with the scanner's message for a body that is not.
|
||
|
|
Json JsonBody(const Response& response);
|
||
|
|
// http.HTTPStatus(code).phrase, "" for a code it does not know.
|
||
|
|
std::string_view Reason(std::int32_t code);
|
||
|
|
}
|