libzypp 17.37.17
MediaHandlerFactory.cc
Go to the documentation of this file.
2
3#include <zypp-core/APIConfig.h>
6#include <zypp/base/Logger.h>
7#include <zypp/base/Env.h>
8
9#include <zypp-media/MediaException>
11
12#include <zypp/media/MediaNFS.h>
13#include <zypp/media/MediaCD.h>
14#include <zypp/media/MediaDIR.h>
19#include <zypp/media/MediaISO.h>
22
23#include <optional>
24
25namespace zypp::media {
26
31
32 std::optional<MediaHandlerFactory::MediaHandlerType> MediaHandlerFactory::handlerType(const Url &url)
33 {
34 std::string scheme = url.getScheme();
35 if (scheme == "cd" || scheme == "dvd")
36 return MediaCDType;
37 else if (scheme == "nfs" || scheme == "nfs4")
38 return MediaNFSType;
39 else if (scheme == "iso")
40 return MediaISOType;
41 else if (scheme == "file" || scheme == "dir")
42 return MediaFileType;
43 else if (scheme == "hd" )
44 return MediaDISKType;
45 else if (scheme == "cifs" || scheme == "smb")
46 return MediaCIFSType;
47 else if (scheme == "ftp" || scheme == "tftp" || scheme == "http" || scheme == "https")
48 return MediaCURLType;
49 else if (scheme == "plugin" )
50 return MediaPluginType;
51 return {};
52 }
53
54 std::unique_ptr<MediaHandler> MediaHandlerFactory::createHandler( const MirroredOrigin &origin, const Pathname &preferred_attach_point )
55 {
56 using namespace zyppng::operators;
57
58 if ( !origin.isValid() ) {
59 MIL << "MirroredOrigin is invalid" << std::endl;
60 ZYPP_THROW(MediaException("Can not create a MediaHandler without a authority Url."));
61 }
62
63 std::optional<MirroredOrigin> resolvedOrigin;
64 std::optional<MediaHandlerFactory::MediaHandlerType> hdlType; // Handler type as detected from primary
65
66 const auto &resolveEndpoint = [&]( const OriginEndpoint &u ) {
67 if( !u.isValid() ) {
68 MIL << "OriginEndpoint is not valid" << std::endl;
70 }
71
72 UrlResolverPlugin::HeaderList custom_headers;
73 if ( u.hasConfig("http-headers") )
74 custom_headers = u.getConfig<UrlResolverPlugin::HeaderList>( "http-headers" );
75
76 Url url = UrlResolverPlugin::resolveUrl(u.url(), custom_headers);
77 MIL << "Trying scheme '" << url.getScheme() << "'" << std::endl;
78
79 if ( !handlerType( url ) ) {
81 }
82
83 OriginEndpoint resolvedEndpoint( url, u.config() ); // keep settings that were passed in
84 if ( !custom_headers.empty () ) {
85 resolvedEndpoint.setConfig ( "http-headers", std::move(custom_headers) );
86 }
87
88 return zyppng::expected<OriginEndpoint>::success(resolvedEndpoint);
89 };
90
91 using zyppng::operators::operator |;
92 (resolveEndpoint( origin.authority() ) // first resolve the authority, that one needs to work always
93 | and_then([&]( OriginEndpoint ep ) {
94 hdlType = handlerType ( ep.url() );
95 resolvedOrigin = MirroredOrigin( std::move(ep) );
96
97 // we have a valid origin, now resolve everything else
98 return zyppng::transform_collect( std::vector<OriginEndpoint>(origin.mirrors ()), resolveEndpoint );
99
100 })
101 | and_then([&]( std::vector<OriginEndpoint> resolvedMirrs ) {
102 std::for_each( resolvedMirrs.begin (), resolvedMirrs.end(), [&]( const OriginEndpoint &rEp ){
103
104 if ( handlerType (rEp.url()) != hdlType ) {
105 // we ignore if we have a Url handler different than the primary one
106 // Urls should be grouped by type already from the calling code
107 MIL << "Different handler type than primary URL, ignoring" << std::endl;
108 return;
109 }
110 resolvedOrigin->addMirror(rEp);
111
112 });
114
115 })).unwrap(); // throw on error
116
117
118 // should not happen, we will at least always have the primary Url here.
119 // But for completeness we check
120 if ( !resolvedOrigin ) {
121 ZYPP_THROW(MediaException("No valid Url left after resolving."));
122 }
123
124 if ( resolvedOrigin->endpointCount() > 1 && *hdlType != MediaCURLType )
125 ERR << "Got mirrors for handler type: " << *hdlType << " they will be ignored!" << std::endl;
126
127 std::unique_ptr<MediaHandler> _handler;
128 switch(*hdlType) {
129 case MediaCDType: {
130 _handler = std::make_unique<MediaCD> (*resolvedOrigin,preferred_attach_point);
131 break;
132 }
133 case MediaNFSType: {
134 _handler = std::make_unique<MediaNFS> (*resolvedOrigin,preferred_attach_point);
135 break;
136 }
137 case MediaISOType: {
138 _handler = std::make_unique<MediaISO> (*resolvedOrigin,preferred_attach_point);
139 break;
140 }
141 case MediaFileType: {
142 _handler = std::make_unique<MediaDIR> (*resolvedOrigin,preferred_attach_point);
143 break;
144 }
145 case MediaDISKType: {
146 _handler = std::make_unique<MediaDISK> (*resolvedOrigin,preferred_attach_point);
147 break;
148 }
149 case MediaCIFSType: {
150 _handler = std::make_unique<MediaCIFS> (*resolvedOrigin,preferred_attach_point);
151 break;
152 }
153 case MediaCURLType: {
154 enum WhichHandler { choose, curl, curl2 };
155 WhichHandler which = choose;
156 // Leagcy: choose handler in Url query
157 if ( const std::string & queryparam = resolvedOrigin->authority().url().getQueryParam("mediahandler"); ! queryparam.empty() ) {
158 if ( queryparam == "curl" )
159 which = curl;
160 else if ( queryparam == "curl2" )
161 which = curl2;
162 else if ( queryparam == "network" || queryparam == "multicurl" )
163 which = choose; // old backends, choose default
164 else
165 WAR << "Unknown mediahandler='" << queryparam << "' in URL; Choosing the default" << std::endl;
166 }
167 // Otherwise choose handler through ENV
168 if ( which == choose ) {
169 TriBool envstate = env::getenvBool( "ZYPP_CURL2" );
170 if ( indeterminate(envstate) ) {
171#if APIConfig(LIBZYPP_CONFIG_USE_LEGACY_CURL_BACKEND_BY_DEFAULT)
172 which = curl;
173#else
174 which = curl2;
175#endif
176 } else {
177 which = bool(envstate) ? curl2 : curl;
178 }
179 }
180 // Finally use the default
181 std::unique_ptr<MediaNetworkCommonHandler> handler;
182 switch ( which ) {
183 default:
184 case curl2:
185 handler = std::make_unique<MediaCurl2>( *resolvedOrigin, preferred_attach_point );
186 break;
187 case curl:
188 handler = std::make_unique<MediaCurl>( *resolvedOrigin, preferred_attach_point );
189 break;
190 }
191 _handler = std::move(handler);
192 break;
193 }
194 case MediaPluginType: {
195 // bsc#1228208: MediaPluginType must be resolved to a valid schema by the
196 // above UrlResolverPlugin::resolveUrl call. MediaPlugin exists as a stub,
197 // but is not a usable handler type.
198 ZYPP_THROW(MediaUnsupportedUrlSchemeException(resolvedOrigin->authority().url()));
199 break;
200 }
201 }
202
203 if ( !_handler ) {
204 ZYPP_THROW(MediaUnsupportedUrlSchemeException(resolvedOrigin->authority().url()));
205 }
206
207 // check created handler
208 if ( !_handler ){
209 ERR << "Failed to create media handler" << std::endl;
210 ZYPP_THROW(MediaSystemException(resolvedOrigin->authority().url(), "Failed to create media handler"));
211 }
212
213 MIL << "Opened: " << *_handler << std::endl;
214 return _handler;
215 }
216
217}
Manages a data source characterized by an authoritative URL and a list of mirror URLs.
const std::vector< OriginEndpoint > & mirrors() const
const OriginEndpoint & authority() const
Represents a single, configurable network endpoint, combining a URL with specific access settings.
const zypp::Url & url() const
Url manipulation class.
Definition Url.h:93
Just inherits Exception to separate media exceptions.
static std::optional< MediaHandlerType > handlerType(const Url &url)
static std::unique_ptr< MediaHandler > createHandler(const MirroredOrigin &origin, const Pathname &preferred_attach_point)
std::multimap< std::string, std::string > HeaderList
static Url resolveUrl(const Url &url, HeaderList &headers)
Resolves an url using the installed plugins If no plugin is found the url is resolved as its current ...
static expected success(ConsParams &&...params)
Definition expected.h:115
boost::logic::tribool TriBool
3-state boolean logic (true, false and indeterminate).
Definition String.h:31
TriBool getenvBool(const C_Str &var_r)
If the environment variable var_r is set to a legal true or false string return bool,...
Definition Env.h:32
Url details namespace.
Definition UrlBase.cc:58
auto and_then(Fun &&function)
Definition expected.h:623
auto transform_collect(Container< Msg, CArgs... > &&in, Transformation &&f)
Definition expected.h:666
#define ZYPP_EXCPT_PTR(EXCPT)
Drops a logline and returns Exception as a std::exception_ptr.
Definition Exception.h:463
#define ZYPP_THROW(EXCPT)
Drops a logline and throws the Exception.
Definition Exception.h:459
#define MIL
Definition Logger.h:100
#define ERR
Definition Logger.h:102
#define WAR
Definition Logger.h:101