Stroika Library 3.0d16
 
Loading...
Searching...
No Matches
IO/Network/Transfer/Exception.cpp
1/*
2 * Copyright(c) Sophist Solutions, Inc. 1990-2025. All rights reserved
3 */
4#include "Stroika/Foundation/StroikaPreComp.h"
5
8#include "Stroika/Foundation/Containers/Set.h"
10#include "Stroika/Foundation/IO/Network/HTTP/Headers.h"
12
13#include "Exception.h"
14
15using namespace Stroika::Foundation;
21
22namespace {
23 String ExtractReasonFromResponse_NonPlainText_ (const String& responseBody, bool atEOF)
24 {
25 // The sample JSON - I have in mind:
26 // { "error": "unsupported_grant_type", "error_description": "Invalid grant_type: "
27 // Try to just grab the first few 'words', and hope it makes some sense in an error message
28
29 //static const RegularExpression kBunchaWords_{"([\\w]+)"};
30 static const RegularExpression kBunchaWordsOrTags_{"(<?/?[\\w]+/?>?)"sv};
31 auto words = responseBody.FindEachMatch (kBunchaWordsOrTags_);
32 if (atEOF) {
33 if (words.size () > 2) {
34 words.Remove (words.size () - 1); // last word cut-off, so don't include
35 }
36 }
38 Iterable<String> wordText = words.Map<Iterable<String>> ([] (const auto& i) { return i.GetFullMatch (); });
39 for (const String& w : wordText) {
40 // remove html tags
41 if (not w.StartsWith ("<"sv)) {
42 sb << w << " ";
43 }
44 }
45 sb = sb.str ().RTrim ();
46 if (not atEOF) {
47 sb += "..."sv;
48 }
49 return sb;
50 }
51 String ExtractReasonFromResponse_ (const Response& response)
52 {
53 using namespace Streams;
54 //DbgTrace ("response headers={}"_f, response.GetHeaders ());
55 //DbgTrace ("response body={}"_f, Streams::BinaryToText::Reader::New (response.GetData()).ReadAll());
56 if (auto ctHdr = response.GetHeaders ().Lookup ("Content-Type"sv)) {
57 InternetMediaType ct{*ctHdr};
58 if (InternetMediaTypeRegistry::sThe->IsA (InternetMediaTypes::Wildcards::kText, ct)) {
59 if (ct == InternetMediaTypes::kText_PLAIN) {
61 }
62 else {
63 Character buf[512];
64 InputStream::Ptr<Character> textStream = BinaryToText::Reader::New (response.GetData ());
65 String roughText = textStream.ReadAll (span{buf});
66 return ExtractReasonFromResponse_NonPlainText_ (roughText, textStream.IsAtEOF ());
67 }
68 }
69 }
70 return String{};
71 }
72
73 // Would like to test in regression tests, but not easy due to API taking Response&
74 constexpr bool kIncludeTest_ = false;
75 struct Test_ {
76 Test_ ()
77 {
78 if constexpr (kIncludeTest_) {
79 Assert (ExtractReasonFromResponse_NonPlainText_ ("<html> <head> <title>502 Bad Gateway</title></head><body><center> <h1> "
80 "502 Bad Gateway </h1></center></body></html>",
81 true) == "502 Bad Gateway 502 Bad Gateway");
82 Assert (ExtractReasonFromResponse_NonPlainText_ ("<html> <head> <title>502 Bad Gateway</title></head><body><center> <h1> "
83 "502 Bad Gateway </h1></center></body></html>",
84 false) == "502 Bad Gateway 502 Bad Gateway...");
85 Assert (ExtractReasonFromResponse_NonPlainText_ (
86 "{ \"error\": \"unsupported_grant_type\", \"error_description\": \"Invalid grant_type\", ", false) ==
87 "error unsupported_grant_type error_description Invalid grant_type...");
88 }
89 }
90 } _RegTest;
91}
92
93/*
94 ********************************************************************************
95 ***************************** Transfer::Exception ******************************
96 ********************************************************************************
97 */
98Exception::Exception (const Response& response)
99 : HTTP::Exception{response.GetStatus (), ExtractReasonFromResponse_ (response)}
100 , fResponse_{response}
101{
102}
103
104Response Exception::GetResponse () const
105{
106 return fResponse_;
107}
RegularExpression is a compiled regular expression which can be used to match on a String class.
Similar to String, but intended to more efficiently construct a String. Mutable type (String is large...
String is like std::u32string, except it is much easier to use, often much more space efficient,...
Definition String.h:201
nonvirtual Containers::Sequence< RegularExpressionMatch > FindEachMatch(const RegularExpression &regEx) const
Definition String.cpp:984
nonvirtual String RTrim(bool(*shouldBeTrimmed)(Character)=Character::IsWhitespace) const
Definition String.cpp:1508
static Execution::Synchronized< InternetMediaTypeRegistry > sThe
Iterable<T> is a base class for containers which easily produce an Iterator<T> to traverse them.
Definition Iterable.h:237
nonvirtual RESULT_CONTAINER Map(ELEMENT_MAPPER &&elementMapper) const
functional API which iterates over all members of an Iterable, applies a map function to each element...
Ptr New(const InputStream::Ptr< byte > &src, optional< AutomaticCodeCvtFlags > codeCvtFlags={}, optional< SeekableFlag > seekable={}, ReadAhead readAhead=eReadAheadAllowed)
Create an InputStream::Ptr<Character> from the arguments (usually binary source) - which can be used ...