2020-01-18 11:38:21 +03:00
|
|
|
/*
|
|
|
|
* Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
|
|
|
|
*
|
2021-04-22 11:24:48 +03:00
|
|
|
* SPDX-License-Identifier: BSD-2-Clause
|
2020-01-18 11:38:21 +03:00
|
|
|
*/
|
|
|
|
|
2020-04-21 00:25:25 +03:00
|
|
|
#include <LibHTTP/HttpResponse.h>
|
2019-04-10 23:28:10 +03:00
|
|
|
|
2020-04-21 00:25:25 +03:00
|
|
|
namespace HTTP {
|
2020-02-02 14:34:39 +03:00
|
|
|
|
ProtocolServer: Stream the downloaded data if possible
This patchset makes ProtocolServer stream the downloads to its client
(LibProtocol), and as such changes the download API; a possible
download lifecycle could be as such:
notation = client->server:'>', server->client:'<', pipe activity:'*'
```
> StartDownload(GET, url, headers, {})
< Response(0, fd 8)
* {data, 1024b}
< HeadersBecameAvailable(0, response_headers, 200)
< DownloadProgress(0, 4K, 1024)
* {data, 1024b}
* {data, 1024b}
< DownloadProgress(0, 4K, 2048)
* {data, 1024b}
< DownloadProgress(0, 4K, 1024)
< DownloadFinished(0, true, 4K)
```
Since managing the received file descriptor is a pain, LibProtocol
implements `Download::stream_into(OutputStream)`, which can be used to
stream the download into any given output stream (be it a file, or
memory, or writing stuff with a delay, etc.).
Also, as some of the users of this API require all the downloaded data
upfront, LibProtocol also implements `set_should_buffer_all_input()`,
which causes the download instance to buffer all the data until the
download is complete, and to call the `on_buffered_download_finish`
hook.
2020-12-26 16:44:12 +03:00
|
|
|
HttpResponse::HttpResponse(int code, HashMap<String, String, CaseInsensitiveStringTraits>&& headers)
|
|
|
|
: m_code(code)
|
2019-04-10 23:28:10 +03:00
|
|
|
, m_headers(move(headers))
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2020-02-02 14:34:39 +03:00
|
|
|
HttpResponse::~HttpResponse()
|
2019-04-10 23:28:10 +03:00
|
|
|
{
|
|
|
|
}
|
2020-02-02 14:34:39 +03:00
|
|
|
|
2021-06-05 15:28:11 +03:00
|
|
|
StringView HttpResponse::reason_phrase_for_code(int code)
|
|
|
|
{
|
|
|
|
VERIFY(code >= 100 && code <= 599);
|
|
|
|
|
|
|
|
static HashMap<int, StringView> s_reason_phrases = {
|
|
|
|
{ 100, "Continue"sv },
|
|
|
|
{ 101, "Switching Protocols"sv },
|
|
|
|
{ 200, "OK"sv },
|
|
|
|
{ 201, "Created"sv },
|
|
|
|
{ 202, "Accepted"sv },
|
|
|
|
{ 203, "Non-Authoritative Information"sv },
|
|
|
|
{ 204, "No Content"sv },
|
|
|
|
{ 205, "Reset Content"sv },
|
|
|
|
{ 206, "Partial Content"sv },
|
|
|
|
{ 300, "Multiple Choices"sv },
|
|
|
|
{ 301, "Moved Permanently"sv },
|
|
|
|
{ 302, "Found"sv },
|
|
|
|
{ 303, "See Other"sv },
|
|
|
|
{ 304, "Not Modified"sv },
|
|
|
|
{ 305, "Use Proxy"sv },
|
|
|
|
{ 307, "Temporary Redirect"sv },
|
|
|
|
{ 400, "Bad Request"sv },
|
|
|
|
{ 401, "Unauthorized"sv },
|
|
|
|
{ 402, "Payment Required"sv },
|
|
|
|
{ 403, "Forbidden"sv },
|
|
|
|
{ 404, "Not Found"sv },
|
|
|
|
{ 405, "Method Not Allowed"sv },
|
|
|
|
{ 406, "Not Acceptable"sv },
|
|
|
|
{ 407, "Proxy Authentication Required"sv },
|
|
|
|
{ 408, "Request Timeout"sv },
|
|
|
|
{ 409, "Conflict"sv },
|
|
|
|
{ 410, "Gone"sv },
|
|
|
|
{ 411, "Length Required"sv },
|
|
|
|
{ 412, "Precondition Failed"sv },
|
|
|
|
{ 413, "Payload Too Large"sv },
|
|
|
|
{ 414, "URI Too Long"sv },
|
|
|
|
{ 415, "Unsupported Media Type"sv },
|
|
|
|
{ 416, "Range Not Satisfiable"sv },
|
|
|
|
{ 417, "Expectation Failed"sv },
|
|
|
|
{ 426, "Upgrade Required"sv },
|
|
|
|
{ 500, "Internal Server Error"sv },
|
|
|
|
{ 501, "Not Implemented"sv },
|
|
|
|
{ 502, "Bad Gateway"sv },
|
|
|
|
{ 503, "Service Unavailable"sv },
|
|
|
|
{ 504, "Gateway Timeout"sv },
|
|
|
|
{ 505, "HTTP Version Not Supported"sv }
|
|
|
|
};
|
|
|
|
|
|
|
|
if (s_reason_phrases.contains(code))
|
|
|
|
return s_reason_phrases.ensure(code);
|
|
|
|
|
|
|
|
// NOTE: "A client MUST understand the class of any status code, as indicated by the first
|
|
|
|
// digit, and treat an unrecognized status code as being equivalent to the x00 status
|
|
|
|
// code of that class." (RFC 7231, section 6)
|
|
|
|
auto generic_code = (code / 100) * 100;
|
|
|
|
VERIFY(s_reason_phrases.contains(generic_code));
|
|
|
|
return s_reason_phrases.ensure(generic_code);
|
|
|
|
}
|
|
|
|
|
2020-02-02 14:34:39 +03:00
|
|
|
}
|