Merge pull request #1198 from johnno1962e/NSLocalizedDescription
diff --git a/CoreFoundation/URL.subproj/CFURLSessionInterface.c b/CoreFoundation/URL.subproj/CFURLSessionInterface.c
index f44f44d..887b4f2 100644
--- a/CoreFoundation/URL.subproj/CFURLSessionInterface.c
+++ b/CoreFoundation/URL.subproj/CFURLSessionInterface.c
@@ -19,6 +19,7 @@
//===----------------------------------------------------------------------===//
#include "CFURLSessionInterface.h"
+#include <CoreFoundation/CFString.h>
#include <curl/curl.h>
FILE* aa = NULL;
@@ -31,6 +32,11 @@
return (CFURLSessionMultiCode) { value };
}
+CFStringRef CFURLSessionCreateErrorDescription(int value) {
+ const char *description = curl_easy_strerror(value);
+ return CFStringCreateWithBytes(kCFAllocatorSystemDefault,
+ (const uint8_t *)description, strlen(description), kCFStringEncodingUTF8, NO);
+}
CFURLSessionEasyHandle _Nonnull CFURLSessionEasyHandleInit() {
return curl_easy_init();
@@ -135,6 +141,7 @@
return MakeEasyCode(curl_global_init(CURL_GLOBAL_SSL));
}
+int const CFURLSessionEasyErrorSize = { CURL_ERROR_SIZE + 1 };
CFURLSessionEasyCode const CFURLSessionEasyCodeOK = { CURLE_OK };
CFURLSessionEasyCode const CFURLSessionEasyCodeUNSUPPORTED_PROTOCOL = { CURLE_UNSUPPORTED_PROTOCOL };
diff --git a/CoreFoundation/URL.subproj/CFURLSessionInterface.h b/CoreFoundation/URL.subproj/CFURLSessionInterface.h
index 6dc29bc..131b576 100644
--- a/CoreFoundation/URL.subproj/CFURLSessionInterface.h
+++ b/CoreFoundation/URL.subproj/CFURLSessionInterface.h
@@ -48,6 +48,10 @@
int value;
} CFURLSessionEasyCode;
+CF_EXPORT CFStringRef _Nonnull CFURLSessionCreateErrorDescription(int value);
+
+CF_EXPORT int const CFURLSessionEasyErrorSize;
+
/// CURLcode
CF_EXPORT CFURLSessionEasyCode const CFURLSessionEasyCodeOK; // CURLE_OK
CF_EXPORT CFURLSessionEasyCode const CFURLSessionEasyCodeUNSUPPORTED_PROTOCOL; // CURLE_UNSUPPORTED_PROTOCOL
diff --git a/Foundation/NSString.swift b/Foundation/NSString.swift
index f17d469..79fcaa5 100644
--- a/Foundation/NSString.swift
+++ b/Foundation/NSString.swift
@@ -20,7 +20,7 @@
}
}
-// Placeholder for a future implementation
+/// Returns a localized string, using the main bundle if one is not specified.
public
func NSLocalizedString(_ key: String,
tableName: String? = nil,
diff --git a/Foundation/URLSession/http/EasyHandle.swift b/Foundation/URLSession/http/EasyHandle.swift
index ea0356d..b7b7550 100644
--- a/Foundation/URLSession/http/EasyHandle.swift
+++ b/Foundation/URLSession/http/EasyHandle.swift
@@ -56,6 +56,7 @@
fileprivate var headerList: _CurlStringList?
fileprivate var pauseState: _PauseState = []
internal var timeoutTimer: _TimeoutSource!
+ internal lazy var errorBuffer = [UInt8](repeating: 0, count: Int(CFURLSessionEasyErrorSize))
#if os(Android)
static fileprivate var _CAInfoFile: UnsafeMutablePointer<Int8>?
#endif
@@ -89,8 +90,8 @@
}
internal extension _EasyHandle {
- func completedTransfer(withErrorCode errorCode: Int?) {
- delegate?.transferCompleted(withErrorCode: errorCode)
+ func completedTransfer(withError error: NSError?) {
+ delegate?.transferCompleted(withError: error)
}
}
internal protocol _EasyHandleDelegate: class {
@@ -107,7 +108,7 @@
func fill(writeBuffer buffer: UnsafeMutableBufferPointer<Int8>) -> _EasyHandle._WriteBufferResult
/// The transfer for this handle completed.
/// - parameter errorCode: An NSURLError code, or `nil` if no error occured.
- func transferCompleted(withErrorCode errorCode: Int?)
+ func transferCompleted(withError error: NSError?)
/// Seek the input stream to the given position
func seekInputStream(to position: UInt64) throws
/// Gets called during the transfer to update progress.
@@ -146,7 +147,8 @@
/// Set error buffer for error messages
/// - SeeAlso: https://curl.haxx.se/libcurl/c/CURLOPT_ERRORBUFFER.html
func set(errorBuffer buffer: UnsafeMutableBufferPointer<UInt8>?) {
- try! CFURLSession_easy_setopt_ptr(rawHandle, CFURLSessionOptionERRORBUFFER, buffer?.baseAddress ?? nil).asError()
+ let buffer = buffer ?? errorBuffer.withUnsafeMutableBufferPointer { $0 }
+ try! CFURLSession_easy_setopt_ptr(rawHandle, CFURLSessionOptionERRORBUFFER, buffer.baseAddress).asError()
}
/// Request failure on HTTP response >= 400
func set(failOnHTTPErrorCode flag: Bool) {
diff --git a/Foundation/URLSession/http/HTTPURLProtocol.swift b/Foundation/URLSession/http/HTTPURLProtocol.swift
index 78aff84..7371889 100644
--- a/Foundation/URLSession/http/HTTPURLProtocol.swift
+++ b/Foundation/URLSession/http/HTTPURLProtocol.swift
@@ -134,7 +134,9 @@
// NSURLErrorNoPermissionsToReadFile
// NSURLErrorFileDoesNotExist
self.internalState = .transferFailed
- failWith(errorCode: errorCode(fileSystemError: e), request: request)
+ let error = NSError(domain: NSURLErrorDomain, code: errorCode(fileSystemError: e),
+ userInfo: [NSLocalizedDescriptionKey: "File system error"])
+ failWith(error: error, request: request)
return
}
@@ -328,17 +330,19 @@
case stream(InputStream)
}
- func failWith(errorCode: Int, request: URLRequest) {
+ func failWith(error: NSError, request: URLRequest) {
//TODO: Error handling
let userInfo: [String : Any]? = request.url.map {
[
+ NSUnderlyingErrorKey: error,
NSURLErrorFailingURLErrorKey: $0,
NSURLErrorFailingURLStringErrorKey: $0.absoluteString,
+ NSLocalizedDescriptionKey: NSLocalizedString(error.localizedDescription, comment: "N/A")
]
}
- let error = URLError(_nsError: NSError(domain: NSURLErrorDomain, code: errorCode, userInfo: userInfo))
- completeTask(withError: error)
- self.client?.urlProtocol(self, didFailWithError: error)
+ let urlError = URLError(_nsError: NSError(domain: NSURLErrorDomain, code: error.code, userInfo: userInfo))
+ completeTask(withError: urlError)
+ self.client?.urlProtocol(self, didFailWithError: urlError)
}
}
@@ -528,16 +532,16 @@
}
}
- func transferCompleted(withErrorCode errorCode: Int?) {
+ func transferCompleted(withError error: NSError?) {
// At this point the transfer is complete and we can decide what to do.
// If everything went well, we will simply forward the resulting data
// to the delegate. But in case of redirects etc. we might send another
// request.
guard case .transferInProgress(let ts) = internalState else { fatalError("Transfer completed, but it wasn't in progress.") }
guard let request = task?.currentRequest else { fatalError("Transfer completed, but there's no current request.") }
- guard errorCode == nil else {
+ guard error == nil else {
internalState = .transferFailed
- failWith(errorCode: errorCode!, request: request)
+ failWith(error: error!, request: request)
return
}
@@ -555,7 +559,9 @@
completeTask()
case .failWithError(let errorCode):
internalState = .transferFailed
- failWith(errorCode: errorCode, request: request)
+ let error = NSError(domain: NSURLErrorDomain, code: errorCode,
+ userInfo: [NSLocalizedDescriptionKey: "Completion failure"])
+ failWith(error: error, request: request)
case .redirectWithRequest(let newRequest):
redirectFor(request: newRequest)
}
diff --git a/Foundation/URLSession/http/MultiHandle.swift b/Foundation/URLSession/http/MultiHandle.swift
index 506c9a9..4998899 100644
--- a/Foundation/URLSession/http/MultiHandle.swift
+++ b/Foundation/URLSession/http/MultiHandle.swift
@@ -202,12 +202,20 @@
}
let easyHandle = easyHandles[idx]
// Find the NSURLError code
- let errorCode = easyHandle.urlErrorCode(for: easyCode)
- completedTransfer(forEasyHandle: easyHandle, errorCode: errorCode)
+ var error: NSError?
+ if let errorCode = easyHandle.urlErrorCode(for: easyCode) {
+ let errorDescription = easyHandle.errorBuffer[0] != 0 ?
+ String(cString: easyHandle.errorBuffer) :
+ CFURLSessionCreateErrorDescription(easyCode.value)._swiftObject
+ error = NSError(domain: NSURLErrorDomain, code: errorCode, userInfo: [
+ NSLocalizedDescriptionKey: errorDescription
+ ])
+ }
+ completedTransfer(forEasyHandle: easyHandle, error: error)
}
/// Transfer completed.
- func completedTransfer(forEasyHandle handle: _EasyHandle, errorCode: Int?) {
- handle.completedTransfer(withErrorCode: errorCode)
+ func completedTransfer(forEasyHandle handle: _EasyHandle, error: NSError?) {
+ handle.completedTransfer(withError: error)
}
}