diff options
| -rw-r--r-- | bitbake/lib/bb/fetch2/wget.py | 72 | ||||
| -rw-r--r-- | bitbake/lib/bb/tests/fetch.py | 2 |
2 files changed, 51 insertions, 23 deletions
diff --git a/bitbake/lib/bb/fetch2/wget.py b/bitbake/lib/bb/fetch2/wget.py index c8c6d5ce83..5a31730a4a 100644 --- a/bitbake/lib/bb/fetch2/wget.py +++ b/bitbake/lib/bb/fetch2/wget.py | |||
| @@ -235,38 +235,64 @@ class Wget(FetchMethod): | |||
| 235 | 235 | ||
| 236 | return exported | 236 | return exported |
| 237 | 237 | ||
| 238 | def head_method(self): | 238 | class HTTPMethodFallback(urllib2.BaseHandler): |
| 239 | return "HEAD" | 239 | """ |
| 240 | 240 | Fallback to GET if HEAD is not allowed (405 HTTP error) | |
| 241 | """ | ||
| 242 | def http_error_405(self, req, fp, code, msg, headers): | ||
| 243 | fp.read() | ||
| 244 | fp.close() | ||
| 245 | |||
| 246 | newheaders = dict((k,v) for k,v in req.headers.items() | ||
| 247 | if k.lower() not in ("content-length", "content-type")) | ||
| 248 | return self.parent.open(urllib2.Request(req.get_full_url(), | ||
| 249 | headers=newheaders, | ||
| 250 | origin_req_host=req.get_origin_req_host(), | ||
| 251 | unverifiable=True)) | ||
| 252 | |||
| 253 | """ | ||
| 254 | Some servers (e.g. GitHub archives, hosted on Amazon S3) return 403 | ||
| 255 | Forbidden when they actually mean 405 Method Not Allowed. | ||
| 256 | """ | ||
| 257 | http_error_403 = http_error_405 | ||
| 258 | |||
| 259 | """ | ||
| 260 | Some servers (e.g. FusionForge) returns 406 Not Acceptable when they | ||
| 261 | actually mean 405 Method Not Allowed. | ||
| 262 | """ | ||
| 263 | http_error_406 = http_error_405 | ||
| 264 | |||
| 265 | class FixedHTTPRedirectHandler(urllib2.HTTPRedirectHandler): | ||
| 266 | """ | ||
| 267 | urllib2.HTTPRedirectHandler resets the method to GET on redirect, | ||
| 268 | when we want to follow redirects using the original method. | ||
| 269 | """ | ||
| 270 | def redirect_request(self, req, fp, code, msg, headers, newurl): | ||
| 271 | newreq = urllib2.HTTPRedirectHandler.redirect_request(self, req, fp, code, msg, headers, newurl) | ||
| 272 | newreq.get_method = lambda: req.get_method() | ||
| 273 | return newreq | ||
| 241 | exported_proxies = export_proxies(d) | 274 | exported_proxies = export_proxies(d) |
| 242 | 275 | ||
| 276 | handlers = [FixedHTTPRedirectHandler, HTTPMethodFallback] | ||
| 277 | if export_proxies: | ||
| 278 | handlers.append(urllib2.ProxyHandler()) | ||
| 279 | handlers.append(CacheHTTPHandler()) | ||
| 243 | # XXX: Since Python 2.7.9 ssl cert validation is enabled by default | 280 | # XXX: Since Python 2.7.9 ssl cert validation is enabled by default |
| 244 | # see PEP-0476, this causes verification errors on some https servers | 281 | # see PEP-0476, this causes verification errors on some https servers |
| 245 | # so disable by default. | 282 | # so disable by default. |
| 246 | import ssl | 283 | import ssl |
| 247 | ssl_context = None | ||
| 248 | if hasattr(ssl, '_create_unverified_context'): | 284 | if hasattr(ssl, '_create_unverified_context'): |
| 249 | ssl_context = ssl._create_unverified_context() | 285 | handlers.append(urllib2.HTTPSHandler(context=ssl._create_unverified_context())) |
| 250 | 286 | opener = urllib2.build_opener(*handlers) | |
| 251 | if exported_proxies == True and ssl_context is not None: | ||
| 252 | opener = urllib2.build_opener(urllib2.ProxyHandler, CacheHTTPHandler, | ||
| 253 | urllib2.HTTPSHandler(context=ssl_context)) | ||
| 254 | elif exported_proxies == False and ssl_context is not None: | ||
| 255 | opener = urllib2.build_opener(CacheHTTPHandler, | ||
| 256 | urllib2.HTTPSHandler(context=ssl_context)) | ||
| 257 | elif exported_proxies == True and ssl_context is None: | ||
| 258 | opener = urllib2.build_opener(urllib2.ProxyHandler, CacheHTTPHandler) | ||
| 259 | else: | ||
| 260 | opener = urllib2.build_opener(CacheHTTPHandler) | ||
| 261 | |||
| 262 | urllib2.Request.get_method = head_method | ||
| 263 | urllib2.install_opener(opener) | ||
| 264 | |||
| 265 | uri = ud.url.split(";")[0] | ||
| 266 | 287 | ||
| 267 | try: | 288 | try: |
| 268 | urllib2.urlopen(uri) | 289 | uri = ud.url.split(";")[0] |
| 269 | except: | 290 | r = urllib2.Request(uri) |
| 291 | r.get_method = lambda: "HEAD" | ||
| 292 | opener.open(r) | ||
| 293 | except urllib2.URLError as e: | ||
| 294 | # debug for now to avoid spamming the logs in e.g. remote sstate searches | ||
| 295 | logger.debug(2, "checkstatus() urlopen failed: %s" % e) | ||
| 270 | return False | 296 | return False |
| 271 | return True | 297 | return True |
| 272 | 298 | ||
diff --git a/bitbake/lib/bb/tests/fetch.py b/bitbake/lib/bb/tests/fetch.py index b175a43280..81b22d025f 100644 --- a/bitbake/lib/bb/tests/fetch.py +++ b/bitbake/lib/bb/tests/fetch.py | |||
| @@ -738,6 +738,8 @@ class FetchCheckStatusTest(FetcherTest): | |||
| 738 | "ftp://ftp.gnu.org/gnu/autoconf/autoconf-2.60.tar.gz", | 738 | "ftp://ftp.gnu.org/gnu/autoconf/autoconf-2.60.tar.gz", |
| 739 | "ftp://ftp.gnu.org/gnu/chess/gnuchess-5.08.tar.gz", | 739 | "ftp://ftp.gnu.org/gnu/chess/gnuchess-5.08.tar.gz", |
| 740 | "ftp://ftp.gnu.org/gnu/gmp/gmp-4.0.tar.gz", | 740 | "ftp://ftp.gnu.org/gnu/gmp/gmp-4.0.tar.gz", |
| 741 | # GitHub releases are hosted on Amazon S3, which doesn't support HEAD | ||
| 742 | "https://github.com/kergoth/tslib/releases/download/1.1/tslib-1.1.tar.xz" | ||
| 741 | ] | 743 | ] |
| 742 | 744 | ||
| 743 | if os.environ.get("BB_SKIP_NETTESTS") == "yes": | 745 | if os.environ.get("BB_SKIP_NETTESTS") == "yes": |
