libzypp  17.36.3
networkrequesterror.cc
Go to the documentation of this file.
1 /*---------------------------------------------------------------------\
2 | ____ _ __ __ ___ |
3 | |__ / \ / / . \ . \ |
4 | / / \ V /| _/ _/ |
5 | / /__ | | | | | | |
6 | /_____||_| |_| |_| |
7 | |
8 ----------------------------------------------------------------------*/
12 #include <zypp/base/Gettext.h>
13 #include <zypp-curl/auth/CurlAuthData>
14 #include <curl/curl.h>
15 
16 namespace zyppng {
17 
18 ZYPP_IMPL_PRIVATE(NetworkRequestError);
19 
20 constexpr std::string_view CurlNativeErrorCodeDescKey = "nativeErrorCodeDesc";
21 constexpr std::string_view CurlNativeErrorDescKey = "nativeErrorDesc";
22 
23 NetworkRequestErrorPrivate::NetworkRequestErrorPrivate(NetworkRequestError::Type code, std::string &&msg, std::map<std::string, boost::any> &&extraInfo)
24  : _errorCode(code)
25  , _errorMessage( std::move(msg) )
26 , _extraInfo( std::move(extraInfo) )
27 { }
28 
30 {
31  return new NetworkRequestErrorPrivate( *this );
32 }
33 
34 NetworkRequestError NetworkRequestErrorPrivate::customError( NetworkRequestError::Type t, std::string &&errorMsg, std::map<std::string, boost::any> &&extraInfo )
35 {
36  return NetworkRequestError( *new NetworkRequestErrorPrivate(t, errorMsg.empty() ? typeToString(t) : std::move(errorMsg), std::move(extraInfo)) );
37 }
38 
39 NetworkRequestError NetworkRequestErrorPrivate::fromCurlError(NetworkRequest &req, int nativeCode , const std::string &nativeError )
40 {
41 
42  Url url = req.url();
44  std::string err;
45  std::map<std::string, boost::any> extraInfo;
46 
47  if ( nativeCode != 0 ) {
48 
49  const char *nativeErr = curl_easy_strerror( static_cast<CURLcode>(nativeCode) );
50  if ( nativeErr != nullptr )
51  extraInfo.insert( { CurlNativeErrorCodeDescKey.data(), std::string( nativeErr ) } );
52 
53  if ( !nativeError.empty() )
54  extraInfo.insert( { CurlNativeErrorDescKey.data(), nativeError } );
55 
56  extraInfo.insert( { "requestUrl", url } );
57  extraInfo.insert( { "curlCode", nativeCode } );
58  extraInfo.insert( { "filepath", req.targetFilePath().asString() } );
59  extraInfo.insert( { "lastRedirect", req.lastRedirectInfo() } );
60 
61  switch ( nativeCode )
62  {
63  case CURLE_UNSUPPORTED_PROTOCOL:
65  err = typeToString( c );
66  if ( !req.lastRedirectInfo().empty() )
67  {
68  err += " or redirect (";
69  err += req.lastRedirectInfo();
70  err += ")";
71  }
72  break;
73  case CURLE_URL_MALFORMAT: case CURLE_URL_MALFORMAT_USER:
75  break;
76  case CURLE_LOGIN_DENIED:
78  break;
79  case CURLE_HTTP_RETURNED_ERROR: {
80  long httpReturnCode = 0;
81  CURLcode infoRet = curl_easy_getinfo( req.nativeHandle(),
82  CURLINFO_RESPONSE_CODE,
83  &httpReturnCode );
84 
85  if ( infoRet == CURLE_OK ) {
86  extraInfo.insert( { "responseCode", httpReturnCode } );
87 
88  std::string msg = "HTTP response: " + zypp::str::numstring( httpReturnCode );
89  switch ( httpReturnCode )
90  {
91  case 401: {
92  long auth_info = CURLAUTH_NONE;
93 
94  CURLcode infoRet =
95  curl_easy_getinfo(req.nativeHandle(), CURLINFO_HTTPAUTH_AVAIL, &auth_info);
96 
97  if (infoRet == CURLE_OK) {
98  extraInfo.insert( { "authHint", zypp::media::CurlAuthData::auth_type_long2str(auth_info) } );
99  }
100 
101  //if there is already a user:password entry in the settings the auth simply failed
102  //@TODO write a testcase for this
103  if ( !req.transferSettings().userPassword().empty() ) {
105  } else {
107  }
108 
109  break;
110  }
111 
112  case 502: // bad gateway (bnc #1070851)
113  case 503: // service temporarily unavailable (bnc #462545)
115  err = zypp::str::form( _("Location '%s' is temporarily unaccessible."), url.asString().c_str() );
116  break;
117  case 504: // gateway timeout
119  err = zypp::str::form(_("Timeout exceeded when accessing '%s'."), url.asString().c_str() );
120  break;
121  case 403: {
122  std::string msg403;
123  if ( url.getHost().find(".suse.com") != std::string::npos )
124  msg403 = _("Visit the SUSE Customer Center to check whether your registration is valid and has not expired.");
125  else if (url.asString().find("novell.com") != std::string::npos)
126  msg403 = _("Visit the Novell Customer Center to check whether your registration is valid and has not expired.");
127 
129  err = msg403;
130  break;
131  }
132  case 404:
133  case 410:
135  err = zypp::str::form( _("File '%s' not found on medium '%s'"), req.targetFilePath().c_str(), url.asString().c_str() );
136  break;
137 
138  default:
140  err = zypp::str::form(_("Download (curl) error for '%s':\n"
141  "Error code: %s\n"), url.asString().c_str(), zypp::str::numstring( httpReturnCode ).c_str() ) ;
142  break;
143  }
144  } else {
146  err = zypp::str::form(_("Download (curl) error for '%s':\n"
147  "Unable to retrieve HTTP response\n"), url.asString().c_str() ) ;
148  }
149  }
150  break;
151  case CURLE_FTP_COULDNT_RETR_FILE:
152 #if CURLVERSION_AT_LEAST(7,16,0)
153  case CURLE_REMOTE_FILE_NOT_FOUND:
154 #endif
155  case CURLE_FTP_ACCESS_DENIED:
156  case CURLE_TFTP_NOTFOUND:
158  break;
159  case CURLE_BAD_PASSWORD_ENTERED:
160  case CURLE_FTP_USER_PASSWORD_INCORRECT:
162  break;
163  case CURLE_COULDNT_RESOLVE_PROXY:
164  case CURLE_COULDNT_RESOLVE_HOST:
165  case CURLE_COULDNT_CONNECT:
166  case CURLE_FTP_CANT_GET_HOST:
168  break;
169  case CURLE_WRITE_ERROR: {
170  // this error code also handles the cases when a callback returned a error.
172  break;
173  }
174  case CURLE_PARTIAL_FILE:
176  break;
177  case CURLE_OPERATION_TIMEDOUT:
179  break;
180  case CURLE_ABORTED_BY_CALLBACK:
182  break;
183  case CURLE_PEER_FAILED_VERIFICATION:
185  break;
186  case CURLE_HTTP2:
188  break;
189  case CURLE_HTTP2_STREAM:
191  break;
192  default:
194  break;
195  }
196  }
197 
198  if ( err.empty() )
199  err = typeToString( c );
200 
201  err += " Curl error (" + zypp::str::numstring( nativeCode ) + ")";
202 
203  return NetworkRequestError( *new NetworkRequestErrorPrivate(c, std::move(err), std::move(extraInfo)) );
204 }
205 
207 {
208  const char *nativeErr = curl_multi_strerror( static_cast<CURLMcode>(nativeCode) );
209 
210  std::map<std::string, boost::any> extraInfo;
211  extraInfo.insert( { "curlMCode", nativeCode } );
212 
213  std::string err;
214  if ( nativeErr == nullptr )
215  err = "The dispatcher returned an unknown error";
216  else
217  err = std::string( nativeErr );
218 
219  return NetworkRequestError( *new NetworkRequestErrorPrivate(NetworkRequestError::InternalError, std::move(err), std::move(extraInfo)) );
220 }
221 
223  : d_ptr( &d )
224 { }
225 
227  : d_ptr( new NetworkRequestErrorPrivate( NoError, {}, {} ) )
228 { }
229 
231 {
232  return d_func()->_errorCode;
233 }
234 
235 std::string NetworkRequestError::toString() const
236 {
237  return d_func()->_errorMessage;
238 }
239 
241 {
242  return d_func()->_errorCode != NoError;
243 }
244 
245 const std::map<std::string, boost::any> &NetworkRequestError::extraInfo() const
246 {
247  return d_func()->_extraInfo;
248 }
249 
251 {
252  switch ( t ) {
254  return "No error";
256  return "Internal Error";
258  return "The request was cancelled";
260  return "The request exceeded the maximum download size";
262  return "The downloaded data did not result in a valid checksum";
264  return "The peer certificate could not be verified";
266  return "Connection failed";
268  return "Unsupported protocol";
270  return "Bad URL";
272  return "Requested location is temporarily unaccessible.";
274  return "Timeout reached";
276  return "Access to requested URL is forbidden.";
278  return "File not found";
280  return "Authentication required but not provided.";
282  return "Login failed.";
284  return "Server returned an error for the given request.";
286  return "Server did not send all requested ranges.";
288  return "Invalid data from server, multipart was requested but there was no range status code.";
290  return "Server returned a HTTP/2 error.";
292  return "Server returned a HTTP/2 stream error.";
293  }
294  return std::string();
295 }
296 
298 {
299  Z_D();
300 
301  auto it = d->_extraInfo.find(CurlNativeErrorDescKey.data());
302  if ( it != d->_extraInfo.end() ) {
303  try {
304  return boost::any_cast<std::string>( it->second );
305  } catch ( const boost::bad_any_cast &) { }
306  }
307 
308  it = d->_extraInfo.find(CurlNativeErrorCodeDescKey.data());
309  if ( it != d->_extraInfo.end() ) {
310  try {
311  return boost::any_cast<std::string>( it->second );
312  } catch ( const boost::bad_any_cast &) { }
313  }
314 
315  return std::string();
316 }
317 
318 }
Interface to gettext.
bool isError() const
isError Will return true if this is a actual error
void * nativeHandle() const
Definition: request.cc:861
#define _(MSG)
Definition: Gettext.h:39
constexpr std::string_view CurlNativeErrorDescKey
const std::string & lastRedirectInfo() const
Definition: request.cc:856
static zyppng::NetworkRequestError fromCurlMError(int nativeCode)
const char * c_str() const
String representation.
Definition: Pathname.h:112
std::string toString() const
toString Returns a string representation of the error
Definition: Arch.h:363
std::string nativeErrorString() const
std::string form(const char *format,...) __attribute__((format(printf
Printf style construction of std::string.
Definition: String.cc:37
TransferSettings & transferSettings()
Definition: request.cc:982
#define Z_D()
Definition: zyppglobal.h:105
static std::string typeToString(NetworkRequestError::Type t)
const std::map< std::string, boost::any > & extraInfo() const
std::string asString() const
Returns a default string representation of the Url object.
Definition: Url.cc:515
const std::string & asString() const
String representation.
Definition: Pathname.h:93
static zyppng::NetworkRequestError fromCurlError(NetworkRequest &req, int nativeCode, const std::string &nativeError)
NetworkRequestErrorPrivate(NetworkRequestError::Type code, std::string &&msg, std::map< std::string, boost::any > &&extraInfo)
The NetworkRequestError class Represents a error that occured in.
std::string numstring(char n, int w=0)
Definition: String.h:289
const zypp::Pathname & targetFilePath() const
Returns the target filename path.
Definition: request.cc:919
static std::string auth_type_long2str(long auth_type)
Converts a long of ORed CURLAUTH_* identifiers into a string of comma separated list of authenticatio...
std::string getHost(EEncoding eflag=zypp::url::E_DECODED) const
Returns the hostname or IP from the URL authority.
Definition: Url.cc:606
ZYPP_IMPL_PRIVATE(UnixSignalSource)
constexpr std::string_view CurlNativeErrorCodeDescKey
Type type() const
type Returns the type of the error
std::string userPassword() const
returns the user and password as a user:pass string
NetworkRequestErrorPrivate * clone() const
static zyppng::NetworkRequestError customError(NetworkRequestError::Type t, std::string &&errorMsg="", std::map< std::string, boost::any > &&extraInfo={})
Url manipulation class.
Definition: Url.h:92