an atproto pds written in F# (.NET 9) 馃
pds fsharp giraffe dotnet atproto
at main 2.0 kB view raw
1namespace PDSharp.Core 2 3open System 4open System.Net.Http 5open System.Text.Json 6open System.Text.Json.Serialization 7 8module DidResolver = 9 type VerificationMethod = { 10 [<JsonPropertyName("id")>] 11 Id : string 12 [<JsonPropertyName("type")>] 13 Type : string 14 [<JsonPropertyName("controller")>] 15 Controller : string 16 [<JsonPropertyName("publicKeyMultibase")>] 17 PublicKeyMultibase : string option 18 } 19 20 type DidDocument = { 21 [<JsonPropertyName("id")>] 22 Id : string 23 [<JsonPropertyName("verificationMethod")>] 24 VerificationMethod : VerificationMethod list 25 } 26 27 let private httpClient = new HttpClient() 28 29 let private fetchJson<'T> (url : string) : Async<'T option> = async { 30 try 31 let! response = httpClient.GetAsync url |> Async.AwaitTask 32 33 if response.IsSuccessStatusCode then 34 let! stream = response.Content.ReadAsStreamAsync() |> Async.AwaitTask 35 let options = JsonSerializerOptions(PropertyNameCaseInsensitive = true) 36 let! doc = JsonSerializer.DeserializeAsync<'T>(stream, options).AsTask() |> Async.AwaitTask 37 return Some doc 38 else 39 return None 40 with _ -> 41 return None 42 } 43 44 let resolveDidWeb (did : string) : Async<DidDocument option> = async { 45 let parts = did.Split(':') 46 47 if parts.Length < 3 then 48 return None 49 else 50 let domain = parts.[2] 51 52 let url = 53 if domain = "localhost" then 54 "http://localhost:5000/.well-known/did.json" 55 else 56 $"https://{domain}/.well-known/did.json" 57 58 return! fetchJson<DidDocument> url 59 } 60 61 let resolveDidPlc (did : string) : Async<DidDocument option> = async { 62 let url = $"https://plc.directory/{did}" 63 return! fetchJson<DidDocument> url 64 } 65 66 let resolve (did : string) : Async<DidDocument option> = async { 67 if did.StartsWith("did:web:") then 68 return! resolveDidWeb did 69 elif did.StartsWith("did:plc:") then 70 return! resolveDidPlc did 71 else 72 return None 73 }