#!/usr/bin/env-Sdotnetfsi--langversion:8.0--optimize--warnaserror+:25,26#nowarn"60"(* Override implementations in augmentations are now deprecated. Override
implementations should be given as part of the initial declaration of a type.
*)#time"on"[<RequireQualifiedAccess>]moduleHTTP=[<RequireQualifiedAccess>]modulePEM=openSystemopenSystem.Net.HttpopenSystem.Net.SecurityopenSystem.Security.Cryptography.X509CertificatesopenSystem.Threadingletget(domain:string)=letmutableb64=String.Emptyletsem=ref0useh=newHttpClientHandler()h.ServerCertificateCustomValidationCallback<-(fun_cert_errs->(* Update mutable value with base64 encoded certificate *)b64<-Convert.ToBase64String(cert.Export(X509ContentType.Cert),Base64FormattingOptions.None)(* Set semaphore to ONE *)let_=Interlocked.Exchange(sem,1)errs=SslPolicyErrors.None)useweb=newHttpClient(handler=h)letrecwait()=async{(* Wait 10 milliseconds and check if semaphore is ONE *)do!Async.Sleep(10)(* Lock and check for value not ZERO *)if(0=Interlocked.Exchange(sem,1))then(* If still ZERO, unlock and release inmediatly *)let_=Interlocked.Exchange(sem,0)return!wait()else(* Once value is set to ONE by other thread
we are done *)return()}async{let!_=(* Make a HTTPS HEAD request to the provided to trigger the
`ServerCertificateCustomValidationCallback` and wait for it to
update the mutable b64 value *)web.SendAsync(newHttpRequestMessage(HttpMethod.Head,sprintf"https://%s"domain))|>Async.AwaitTaskreturn!wait()}|>Async.RunSynchronously(* Once the b64 mutable value has been updated, return the PEM base64
encoded in lines of 64 chars pre- and post- fixed with BEGIN and END
tags *)letls=seq{yield"-----BEGIN CERTIFICATE-----"yield(b64|>Seq.chunkBySize64|>Seq.map(Array.mapstring>>Array.reduce(+))|>Seq.reduce(funxy->sprintf"%s%s%s"xEnvironment.NewLiney))yield"-----END CERTIFICATE-----"}String.Join(separator=Environment.NewLine,values=ls)let_="spisemisu.com"|>HTTP.PEM.get|>printfn"%s"00