Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions EhPanda/App/Tools/Defaults.swift
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,21 @@ struct Defaults {
struct Regex {
static let tagSuggestion: NSRegularExpression? = try? .init(pattern: "(\\S+:\".+?\"|\".+?\"|\\S+:\\S+|\\S+)")
}
struct Network {
/// 普通请求超时时间(秒)
static let normalRequestTimeout: TimeInterval = 30.0
/// 普通请求资源超时时间(秒)
static let normalResourceTimeout: TimeInterval = 60.0

/// 图片请求超时时间(秒)
static let imageRequestTimeout: TimeInterval = 60.0
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[imo]
It doesn't seem helpful for your situation since the default value is already 60.

The default value is 60.
https://developer.apple.com/documentation/foundation/urlsessionconfiguration/timeoutintervalforrequest

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The default timeout is indeed set to 60 seconds. A configuration option for the image download timeout has been added, which can be dynamically adjusted based on your network conditions when you compile and install it yourself. I personally use 120 seconds, and this resolves the issue of image loading timeouts.

/// 图片请求资源超时时间(秒)
static let imageResourceTimeout: TimeInterval = 120.0

/// 重试次数
static let retryCount: Int = 3
}

struct URL {
static var host: Foundation.URL { AppUtil.galleryHost == .exhentai ? exhentai : ehentai }
static let ehentai: Foundation.URL = .init(string: "https://e-hentai.org/").forceUnwrapped
Expand Down
34 changes: 34 additions & 0 deletions EhPanda/Network/DFExtensions.swift
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,40 @@ extension URLSessionConfiguration {
config.protocolClasses = [DFURLProtocol.self]
return config
}

/// 为普通请求配置的URLSession
static var normalRequest: URLSessionConfiguration {
let config = URLSessionConfiguration.default
config.timeoutIntervalForRequest = Defaults.Network.normalRequestTimeout
config.timeoutIntervalForResource = Defaults.Network.normalResourceTimeout
return config
}

/// 为图片请求配置的URLSession
static var imageRequest: URLSessionConfiguration {
let config = URLSessionConfiguration.default
config.timeoutIntervalForRequest = Defaults.Network.imageRequestTimeout
config.timeoutIntervalForResource = Defaults.Network.imageResourceTimeout
return config
}

#if DEBUG
/// 验证网络配置的调试方法
static func validateNetworkConfiguration() {
print("=== 网络配置验证 ===")

let normalConfig = URLSessionConfiguration.normalRequest
print("普通请求超时: \(normalConfig.timeoutIntervalForRequest)秒")
print("普通资源超时: \(normalConfig.timeoutIntervalForResource)秒")

let imageConfig = URLSessionConfiguration.imageRequest
print("图片请求超时: \(imageConfig.timeoutIntervalForRequest)秒")
print("图片资源超时: \(imageConfig.timeoutIntervalForResource)秒")

print("重试次数: \(Defaults.Network.retryCount)次")
print("=== 配置验证完成 ===")
}
#endif
}

// MARK: CFHTTPMessage
Expand Down
20 changes: 12 additions & 8 deletions EhPanda/Network/Request.swift
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ extension Request {

private extension Publisher {
func genericRetry() -> Publishers.Retry<Self> {
retry(3)
retry(Defaults.Network.retryCount)
}

func async() async -> Result<Output, Failure> where Failure == AppError {
Expand Down Expand Up @@ -408,7 +408,7 @@ struct GalleryReverseRequest: Request {
func galleryURL(url: URL) -> AnyPublisher<URL, AppError> {
switch isGalleryImageURL {
case true:
return URLSession.shared.dataTaskPublisher(for: url)
return URLSession(configuration: .imageRequest).dataTaskPublisher(for: url)
.tryMap { try Kanna.HTML(html: $0.data, encoding: .utf8) }
.tryMap(Parser.parseGalleryURL)
.mapError(mapAppError)
Expand All @@ -422,7 +422,7 @@ struct GalleryReverseRequest: Request {
}

func gallery(url: URL) -> AnyPublisher<Gallery, AppError> {
URLSession.shared.dataTaskPublisher(for: url)
URLSession(configuration: .normalRequest).dataTaskPublisher(for: url)
.tryMap { try Kanna.HTML(html: $0.data, encoding: .utf8) }
.compactMap {
guard let (detail, _) = try? Parser.parseGalleryDetail(doc: $0, gid: url.pathComponents[2])
Expand Down Expand Up @@ -545,7 +545,7 @@ struct GalleryNormalImageURLsRequest: Request {
var publisher: AnyPublisher<([Int: URL], [Int: URL]), AppError> {
thumbnailURLs.publisher
.flatMap { index, url in
URLSession.shared.dataTaskPublisher(for: url)
URLSession(configuration: .imageRequest).dataTaskPublisher(for: url)
.genericRetry()
.tryMap { try Kanna.HTML(html: $0.data, encoding: .utf8) }
.tryMap { try Parser.parseGalleryNormalImageURL(doc: $0, index: index) }
Expand Down Expand Up @@ -589,7 +589,7 @@ struct GalleryNormalImageURLRefetchRequest: Request {
.setFailureType(to: AppError.self)
.eraseToAnyPublisher()
} else {
return URLSession.shared.dataTaskPublisher(for: URLUtil.detailPage(url: galleryURL, pageNum: pageNum))
return URLSession(configuration: .normalRequest).dataTaskPublisher(for: URLUtil.detailPage(url: galleryURL, pageNum: pageNum))
.tryMap { try Kanna.HTML(html: $0.data, encoding: .utf8) }
.tryMap(Parser.parseThumbnailURLs)
.compactMap({ thumbnailURLs in thumbnailURLs[index] })
Expand All @@ -599,7 +599,7 @@ struct GalleryNormalImageURLRefetchRequest: Request {
}

func renewThumbnailURL(stored: URL) -> AnyPublisher<(URL, URL), AppError> {
URLSession.shared.dataTaskPublisher(for: stored)
URLSession(configuration: .imageRequest).dataTaskPublisher(for: stored)
.tryMap { try Kanna.HTML(html: $0.data, encoding: .utf8) }
.tryMap {
let identifier = try Parser.parseSkipServerIdentifier(doc: $0)
Expand All @@ -612,7 +612,7 @@ struct GalleryNormalImageURLRefetchRequest: Request {

func imageURL(thumbnailURL: URL, anotherImageURL: URL)
-> AnyPublisher<(URL, URL, HTTPURLResponse?), AppError> {
URLSession.shared.dataTaskPublisher(for: thumbnailURL)
URLSession(configuration: .imageRequest).dataTaskPublisher(for: thumbnailURL)
.tryMap {
(try Kanna.HTML(html: $0.data, encoding: .utf8), $0.response as? HTTPURLResponse)
}
Expand Down Expand Up @@ -687,7 +687,11 @@ struct DataRequest: Request {
let url: URL

var publisher: AnyPublisher<Data, AppError> {
URLSession.shared.dataTaskPublisher(for: url)
let urlString = url.absoluteString.lowercased()
let isImageURL = ["jpg", "jpeg", "png", "gif", "bmp", "webp"].contains { urlString.contains($0) }
let session = isImageURL ? URLSession(configuration: .imageRequest) : URLSession(configuration: .normalRequest)

return session.dataTaskPublisher(for: url)
.genericRetry()
.map(\.data)
.mapError(mapAppError)
Expand Down