libzypp  17.31.31
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  std::string auth_hint;
93  {
94  long auth_info = CURLAUTH_NONE;
95 
96  CURLcode infoRet =
97  curl_easy_getinfo(req.nativeHandle(), CURLINFO_HTTPAUTH_AVAIL, &auth_info);
98 
99  if(infoRet == CURLE_OK) {
100  extraInfo.insert( { "authHint", zypp::media::CurlAuthData::auth_type_long2str(auth_info) } );
101  }
102  }
103 
104  //if there is already a user:password entry in the settings the auth simply failed
105  //@TODO write a testcase for this
106  if ( !req.transferSettings().userPassword().empty() ) {
108  } else {
110  }
111 
112  break;
113  }
114 
115  case 502: // bad gateway (bnc #1070851)
116  case 503: // service temporarily unavailable (bnc #462545)
118  err = zypp::str::form( _("Location '%s' is temporarily unaccessible."), url.asString().c_str() );
119  break;
120  case 504: // gateway timeout
122  err = zypp::str::form(_("Timeout exceeded when accessing '%s'."), url.asString().c_str() );
123  break;
124  case 403: {
125  std::string msg403;
126  if ( url.getHost().find(".suse.com") != std::string::npos )
127  msg403 = _("Visit the SUSE Customer Center to check whether your registration is valid and has not expired.");
128  else if (url.asString().find("novell.com") != std::string::npos)
129  msg403 = _("Visit the Novell Customer Center to check whether your registration is valid and has not expired.");
130 
132  err = msg403;
133  break;
134  }
135  case 404:
136  case 410:
138  err = zypp::str::form( _("File '%s' not found on medium '%s'"), req.targetFilePath().c_str(), url.asString().c_str() );
139  break;
140 
141  default:
143  err = zypp::str::form(_("Download (curl) error for '%s':\n"
144  "Error code: %s\n"), url.asString().c_str(), zypp::str::numstring( httpReturnCode ).c_str() ) ;
145  break;
146  }
147  } else {
149  err = zypp::str::form(_("Download (curl) error for '%s':\n"
150  "Unable to retrieve HTTP response\n"), url.asString().c_str() ) ;
151  }
152  }
153  break;
154  case CURLE_FTP_COULDNT_RETR_FILE:
155 #if CURLVERSION_AT_LEAST(7,16,0)
156  case CURLE_REMOTE_FILE_NOT_FOUND:
157 #endif
158  case CURLE_FTP_ACCESS_DENIED:
159  case CURLE_TFTP_NOTFOUND:
161  break;
162  case CURLE_BAD_PASSWORD_ENTERED:
163  case CURLE_FTP_USER_PASSWORD_INCORRECT:
165  break;
166  case CURLE_COULDNT_RESOLVE_PROXY:
167  case CURLE_COULDNT_RESOLVE_HOST:
168  case CURLE_COULDNT_CONNECT:
169  case CURLE_FTP_CANT_GET_HOST:
171  break;
172  case CURLE_WRITE_ERROR: {
173  // this error code also handles the cases when a callback returned a error.
175  break;
176  }
177  case CURLE_PARTIAL_FILE:
179  break;
180  case CURLE_OPERATION_TIMEDOUT:
182  break;
183  case CURLE_ABORTED_BY_CALLBACK:
185  break;
186  case CURLE_PEER_FAILED_VERIFICATION:
188  break;
189  case CURLE_HTTP2:
191  break;
192  case CURLE_HTTP2_STREAM:
194  break;
195  default:
197  break;
198  }
199  }
200 
201  if ( err.empty() )
202  err = typeToString( c );
203 
204  err += " Curl error (" + zypp::str::numstring( nativeCode ) + ")";
205 
206  return NetworkRequestError( *new NetworkRequestErrorPrivate(c, std::move(err), std::move(extraInfo)) );
207 }
208 
210 {
211  const char *nativeErr = curl_multi_strerror( static_cast<CURLMcode>(nativeCode) );
212 
213  std::map<std::string, boost::any> extraInfo;
214  extraInfo.insert( { "curlMCode", nativeCode } );
215 
216  std::string err;
217  if ( nativeErr == nullptr )
218  err = "The dispatcher returned an unknown error";
219  else
220  err = std::string( nativeErr );
221 
222  return NetworkRequestError( *new NetworkRequestErrorPrivate(NetworkRequestError::InternalError, std::move(err), std::move(extraInfo)) );
223 }
224 
226  : d_ptr( &d )
227 { }
228 
230  : d_ptr( new NetworkRequestErrorPrivate( NoError, {}, {} ) )
231 { }
232 
234 {
235  return d_func()->_errorCode;
236 }
237 
238 std::string NetworkRequestError::toString() const
239 {
240  return d_func()->_errorMessage;
241 }
242 
244 {
245  return d_func()->_errorCode != NoError;
246 }
247 
248 const std::map<std::string, boost::any> &NetworkRequestError::extraInfo() const
249 {
250  return d_func()->_extraInfo;
251 }
252 
254 {
255  switch ( t ) {
257  return "No error";
259  return "Internal Error";
261  return "The request was cancelled";
263  return "The request exceeded the maximum download size";
265  return "The downloaded data did not result in a valid checksum";
267  return "The peer certificate could not be verified";
269  return "Connection failed";
271  return "Unsupported protocol";
273  return "Bad URL";
275  return "Requested location is temporarily unaccessible.";
277  return "Timeout reached";
279  return "Access to requested URL is forbidden.";
281  return "File not found";
283  return "Authentication required but not provided.";
285  return "Login failed.";
287  return "Server returned an error for the given request.";
289  return "Server did not send all requested ranges.";
291  return "Invalid data from server, multipart was requested but there was no range status code.";
293  return "Server returned a HTTP/2 error.";
295  return "Server returned a HTTP/2 stream error.";
296  }
297  return std::string();
298 }
299 
301 {
302  Z_D();
303 
304  auto it = d->_extraInfo.find(CurlNativeErrorDescKey.data());
305  if ( it != d->_extraInfo.end() ) {
306  try {
307  return boost::any_cast<std::string>( it->second );
308  } catch ( const boost::bad_any_cast &) { }
309  }
310 
311  it = d->_extraInfo.find(CurlNativeErrorCodeDescKey.data());
312  if ( it != d->_extraInfo.end() ) {
313  try {
314  return boost::any_cast<std::string>( it->second );
315  } catch ( const boost::bad_any_cast &) { }
316  }
317 
318  return std::string();
319 }
320 
321 }
bool isError() const
isError Will return true if this is a actual error
void * nativeHandle() const
Definition: request.cc:840
#define _(MSG)
Definition: Gettext.h:37
ZYPP_IMPL_PRIVATE(Provide)
constexpr std::string_view CurlNativeErrorDescKey
const std::string & lastRedirectInfo() const
Definition: request.cc:835
static zyppng::NetworkRequestError fromCurlMError(int nativeCode)
const char * c_str() const
String representation.
Definition: Pathname.h:110
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:36
TransferSettings & transferSettings()
Definition: request.cc:961
static std::string typeToString(NetworkRequestError::Type t)
const std::map< std::string, boost::any > & extraInfo() const
const std::string & asString() const
String representation.
Definition: Pathname.h:91
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:898
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...
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={})