Skip to content

Instantly share code, notes, and snippets.

@banjun
Created December 28, 2016 07:33
Show Gist options
  • Save banjun/da559f37b742cba79a13df3a748767fc to your computer and use it in GitHub Desktop.
Save banjun/da559f37b742cba79a13df3a748767fc to your computer and use it in GitHub Desktop.
App Transport Security (ATS) connection test & report
import Eureka
import SVProgressHUD
import BrightFutures
class ViewController: FormViewController {
init() {
super.init(style: .grouped)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func viewDidLoad() {
super.viewDidLoad()
edgesForExtendedLayout = [] // for screenshot
navigationItem.rightBarButtonItem = UIBarButtonItem(barButtonSystemItem: .action, target: self, action: #selector(share))
func urlRow(_ url: String) -> LabelRow {
return LabelRow() {
$0.title = url
$0.cellStyle = .value1
$0.cell.selectionStyle = .default
$0.onCellSelection { cell, row in
row.deselect(animated: true)
self.connect(URL(string: url)!)
.onSuccess { status in
row.value = "Status: \(status)"
cell.detailTextLabel?.textColor = #colorLiteral(red: 0.2745098174, green: 0.4862745106, blue: 0.1411764771, alpha: 1)
}.onFailure { error in
switch error {
case .ats:
row.value = "Blocked by ATS"
cell.detailTextLabel?.textColor = #colorLiteral(red: 0.521568656, green: 0.1098039225, blue: 0.05098039284, alpha: 1)
case let .ssl(e):
row.value = e.localizedDescription
cell.detailTextLabel?.textColor = #colorLiteral(red: 0.521568656, green: 0.1098039225, blue: 0.05098039284, alpha: 1)
case let .other(e):
row.value = e?.localizedDescription
cell.detailTextLabel?.textColor = #colorLiteral(red: 0.7254902124, green: 0.4784313738, blue: 0.09803921729, alpha: 1)
}
}.onComplete {_ in row.reload()}
}
}
}
form +++ Section("Current ATS Settings")
<<< TextAreaRow() {
$0.value = Bundle.main.infoDictionary!["NSAppTransportSecurity"].map {String(describing: $0)} ?? "nothing"
$0.disabled = true
}
+++ Section("Connection Tests")
<<< urlRow("https://google.com/")
<<< urlRow("http://google.com/")
<<< urlRow("http://banjun.local/")
<<< urlRow("http://banjun.local./")
<<< urlRow("http://banjun/")
<<< urlRow("http://127.0.0.1/")
}
enum ConnectionError: Error {
case ats
case ssl(Error)
case other(Error?)
}
func connect(_ url: URL) -> Future<Int, ConnectionError> {
let p = Promise<Int, ConnectionError>()
SVProgressHUD.show(withStatus: url.absoluteString)
let task = URLSession.shared.dataTask(with: url) { data, response, error in
SVProgressHUD.dismiss()
let status = (response as? HTTPURLResponse)?.statusCode
if let s = status {
p.success(s)
} else {
let e = error as? NSError
switch (e?.domain, e?.code) {
case (NSURLErrorDomain?, NSURLErrorAppTransportSecurityRequiresSecureConnection?):
p.failure(.ats)
case (NSURLErrorDomain?, (NSURLErrorCannotLoadFromNetwork...NSURLErrorSecureConnectionFailed)?):
p.failure(.ssl(e!) default:
p.failure(.other(e))
}
}
}
task.resume()
return p.future
}
func share() {
guard let tv = tableView else { return }
let prevFrame = tv.frame
tv.frame = CGRect(origin: .zero, size: tv.contentSize)
tv.reloadData()
DispatchQueue.main.asyncAfter(deadline: .now() + 0.2) { // 遅らせる(為念)
UIGraphicsBeginImageContextWithOptions(tv.contentSize, false, 0)
tv.layer.render(in: UIGraphicsGetCurrentContext()!)
let image = UIGraphicsGetImageFromCurrentImageContext()!
UIGraphicsEndImageContext()
let ac = UIActivityViewController(activityItems: [image], applicationActivities: nil)
ac.completionWithItemsHandler = { _ in
tv.frame = prevFrame
}
self.present(ac, animated: true)
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment