Una classe Swift per un client WebService

Una breve classe da cui prendere spunto:


// MARK: - WebServiceError

public enum WebServiceError: Error {
    case badURL
    case error
    case nodata
    case jsonError
    // ...
}

// MARK: - WebService

public class WebService {
    let baseUrl: String
    public enum HttpMethod: String {
        case GET
        case POST
        case PUT
        case TRACE
        case DELETE
    }

    public init?(baseUrl: String) {
        guard !baseUrl.isEmpty else {
            return nil
        }
        if baseUrl.last! == "/" {
            self.baseUrl = baseUrl
        } else {
            self.baseUrl = baseUrl+"/"
        }
    }

    public func request<T>(with httpMethod: HttpMethod = .GET,
                    of _: T.Type,
                    on path: String, _ completion: @escaping (Result<T, WebServiceError>) -> Void) -> Void where T: Codable
    {
        guard let url = URL(string: baseUrl + path) else {
            completion(.failure(.badURL))
            return
        }
        var request = URLRequest(url: url)
        request.httpMethod = httpMethod.rawValue
        request.setValue("application/json; charset=utf-8", forHTTPHeaderField: "Content-Type")
        request.setValue("application/json; charset=utf-8", forHTTPHeaderField: "Accept")

        let task = URLSession.shared.dataTask(with: request) { data, response, error in

            var result: Result<T, WebServiceError>

            defer {
                completion(result)
            }

            guard error == nil else {
                result = .failure(.error)
                return
            }

            guard let data = data else {
                result = .failure(.nodata)
                return
            }

            let decoder = JSONDecoder()
            decoder.dateDecodingStrategy = .iso8601

            guard let response = try? decoder.decode(T.self, from: data) else {
                result = .failure(.jsonError)
                return
            }
            result = .success(response)
        }

        task.resume()
    }
}

QRCode con CoreImage e Swift

Breve antefatto: mi chiedono di generare dei qrCode 600×600 per una lista di URL. Apro Xcode, creo un nuovo Playground e in dieci minuti preparo un programmino in Swift 😚

Generare un qrCode con CoreImage è questioni di pochi minuti:

import CoreImage
import CoreImage.CIFilterBuiltins

let qrCodeFilter = CIFilter.qrCodeGenerator()
qrCodeFilter.setValue("Hello,World!".data(using: .utf8, allowLossyConversion: false), forKey: "inputMessage")

if let rawQRCode = qrCodeFilter.outputImage {
    let scale = 600 / rawQRCode.extent.width
    let qrCodeOutput = rawQRCode.transformed(by: CGAffineTransform(scaleX: scale, y: scale))

    //salviamo un png nella home dell'utente
    //per iOS utilizzare un percorso diverso... homeDirectoryForCurrentUser è disponibile solo su macOS
    try! CIContext().writePNGRepresentation(of: qrCodeOutput, to: FileManager.default.homeDirectoryForCurrentUser.appendingPathComponent("qrcode.png"), format: CIFormat.RGBA16, colorSpace: CGColorSpace(name: CGColorSpace.sRGB)!, options: [:])
}

SQL – select record dell’anno passato

Immaginiamo una tabella con un campo datetime. Se volessimo filtrare la nostra query select per i record dell’anno passato possiamo procedere nel seguente modo:

select * from table t where YEAR(t.date) = YEAR(current_date - INTERVAL 1 YEAR);

Abbiamo utilizzato le seguenti funzioni:

  • YEAR(dt) questa funzione restituisce un intero rappresentante l’anno del paremetro date o datetime dt
  • CURRENT_DATE() questa funzione restituisce la data corrente nel formato 'YYYY-MM-DD'
  • INTERVAL questa funzione meriterebbe un articolo intero. È usata per effettuare calcoli con DATE e TIME. La sintassi è la seguente: INTERVAL expr unit

Naturalmente, modificando il valore dell’espressione INTERVAL 1 YEAR è possibile selezionare anche record con anni precedenti.

NB: è possibile anche fare a meno di INTERVAL e usare una semplice sottrazione:

select * from table t where YEAR(t.date) = YEAR(current_date)-1;

ma volevo approfittarne per introdurre l’espressione INTERVAL di cui parlerò con maggiori dettagli in un prossimo articolo.

Fetch del certificato SSL di un sito web

Alcune volte, per effettuare delle verifiche, ho necessità di recuperare il certificato SSL di un sito WEB. Per effettuare questa operazione velocemente, ho scritto un piccolo script bash che mi permette di recuperare tutte le informazioni del certificato SSL da linea di comando:

#!/bin/bash
# usage: ./fetchSSL.sh domain.tld

echo | openssl s_client -showcerts -servername $1  -connect $1:443 2>/dev/null | openssl x509 -inform pem -noout -text

Salvando questo piccolo script in un file (ad esempio) fetchSSL.sh, da linea di comando posso recuperare il certificato SSL di un sito:

$~: ./fetchSSL.sh google.it

Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number:
            41:fc:ce:96:9b:12:b3:b4:08:00:00:00:00:43:56:56
    Signature Algorithm: sha256WithRSAEncryption
        Issuer: C=US, O=Google Trust Services, CN=GTS CA 1O1
        Validity
            Not Before: May 26 15:38:08 2020 GMT
            Not After : Aug 18 15:38:08 2020 GMT
        Subject: C=US, ST=California, L=Mountain View, O=Google LLC, CN=*.google.it
        Subject Public Key Info:
            Public Key Algorithm: id-ecPublicKey
                Public-Key: (256 bit)
                pub:
                    04:30:7e:8b:21:f1:df:78:b9:25:14:7d:c4:3c:5d:
[...]