Skip to content
This repository was archived by the owner on Jan 18, 2025. It is now read-only.

Commit 45d9531

Browse files
Merge branch '127' into release-candidate/3.3.0
2 parents 3a25df2 + 83676c6 commit 45d9531

File tree

1 file changed

+61
-5
lines changed

1 file changed

+61
-5
lines changed

Sources/SwiftLinkPreview.swift

Lines changed: 61 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -252,6 +252,9 @@ extension SwiftLinkPreview {
252252
request.httpMethod = "HEAD"
253253

254254
task = session.dataTask(with: request, completionHandler: { data, response, error in
255+
guard !cancellable.isCancelled
256+
else { return }
257+
255258
if error != nil {
256259
self.workQueue.async {
257260
if !cancellable.isCancelled {
@@ -262,12 +265,57 @@ extension SwiftLinkPreview {
262265
} else {
263266
if let finalResult = response?.url {
264267
if (finalResult.absoluteString == url.absoluteString) {
265-
self.workQueue.async {
266-
if !cancellable.isCancelled {
267-
completion(url)
268+
if response?.mimeType?.contains( "/html" ) ?? false {
269+
var request = URLRequest( url: url )
270+
request.addValue( "text/html,application/xhtml+xml,application/xml", forHTTPHeaderField: "Accept" )
271+
self.session.dataTask( with: request, completionHandler: { data, response, error in
272+
guard !cancellable.isCancelled
273+
else { return }
274+
275+
if error != nil {
276+
self.workQueue.async {
277+
if !cancellable.isCancelled {
278+
onError( .cannotBeOpened( "\(url.absoluteString): \(error.debugDescription)" ) )
279+
}
280+
}
281+
return
282+
}
283+
284+
if let response = response, let data = data {
285+
let encoding = response.textEncodingName.flatMap {
286+
String.Encoding( rawValue: CFStringConvertEncodingToNSStringEncoding(
287+
CFStringConvertIANACharSetNameToEncoding( $0 as CFString ) ) )
288+
} ?? .utf8
289+
if let html = String( data: data, encoding: encoding ) {
290+
for meta in Regex.pregMatchAll( html, regex: Regex.metatagPattern, index: 1 ) {
291+
if (meta.contains( "http-equiv=\"refresh\"" ) || meta.contains( "http-equiv='refresh'" )),
292+
let value = Regex.pregMatchFirst( meta, regex: Regex.metatagContentPattern, index: 2 )?.decoded.extendedTrim,
293+
let redirectString = value.split( separator: ";" )
294+
.first( where: { $0.lowercased().starts( with: "url=" ) } )?
295+
.split( separator: "=", maxSplits: 1 ).last,
296+
let redirectURL = URL( string: self.addImagePrefixIfNeeded( String( redirectString ), url: url ) ) {
297+
self.unshortenURL( redirectURL, cancellable: cancellable, completion: completion, onError: onError )
298+
return
299+
}
300+
}
301+
}
302+
}
303+
304+
self.workQueue.async {
305+
if !cancellable.isCancelled {
306+
completion( url )
307+
}
308+
}
309+
} ).resume()
310+
}
311+
else {
312+
self.workQueue.async {
313+
if !cancellable.isCancelled {
314+
completion( url )
315+
}
268316
}
317+
task = nil
269318
}
270-
task = nil
271319
} else {
272320
task?.cancel()
273321
task = nil
@@ -603,11 +651,19 @@ extension SwiftLinkPreview {
603651
}
604652

605653
// Add prefix image if needed
654+
fileprivate func addImagePrefixIfNeeded(_ image: String, url: URL) -> String {
655+
addImagePrefixIfNeeded( image, canonicalUrl: self.extractCanonicalURL( url ), finalUrl: self.extractInURLRedirectionIfNeeded( url ).absoluteString )
656+
}
657+
606658
fileprivate func addImagePrefixIfNeeded(_ image: String, result: Response) -> String {
659+
addImagePrefixIfNeeded( image, canonicalUrl: result.canonicalUrl, finalUrl: result.finalUrl?.absoluteString )
660+
}
607661

662+
fileprivate func addImagePrefixIfNeeded(_ image: String, canonicalUrl: String?, finalUrl: String?) -> String {
608663
var image = image
609664

610-
if let canonicalUrl = result.canonicalUrl, let finalUrl = result.finalUrl?.absoluteString {
665+
// TODO: account for HTML <base>
666+
if let canonicalUrl = canonicalUrl, let finalUrl = finalUrl {
611667
if finalUrl.hasPrefix("https:") {
612668
if image.hasPrefix("//") {
613669
image = "https:" + image

0 commit comments

Comments
 (0)