あなたが小さな組織やクラブの管理を手伝っており、すべてのメンバーの詳細 (名前、電話番号、電子メールなど) を保存するデータベースがあるとします。
必要なときにどこでもこの最新情報にアクセスできたら便利だと思いませんか? CardDAV を使えばそれが可能です!
CardDAV は、十分にサポートされている連絡先管理のオープン スタンダードです。 iOS の連絡先アプリにネイティブに統合されており、Android では多くのアプリが利用可能です。
サーバー側で CardDAV を実装するのは、通常とは異なる http メソッド (GET、POST の代わりに PROPFIND、REPORT...) に応答する http サーバーです。幸いなことに、作業を大幅に簡素化する Go モジュールが存在します: github.com/emersion/go-webdav。このライブラリは実装されたバックエンドを想定しており、認証後に HTTP リクエストを処理する標準の http.Handler を提供します。
興味深いことに、このライブラリはユーザー認証に関するヘルプを提供していませんが、Go のコンポーザビリティのおかげで、これは問題になりません。
CardDAV は Basic 認証資格情報を使用します。資格情報がチェックされたら、それらの資格情報をコンテキストに保存できます (後で役立ちます):
package main import ( "context" "net/http" "github.com/emersion/go-webdav/carddav" ) type ( ctxKey struct{} ctxValue struct { username string } ) func NewCardDAVHandler() http.Handler { actualHandler := carddav.Handler{ Backend: &ownBackend{}, } return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { username, password, ok := r.BasicAuth() // check username and password: adjust the logic to your system (do NOT store passwords in plaintext) if !ok || username != "admin" || password != "s3cr3t" { // abort the request handling on failure w.Header().Add("WWW-Authenticate", `Basic realm="Please authenticate", charset="UTF-8"`) http.Error(w, "HTTP Basic auth is required", http.StatusUnauthorized) return } // user is authenticated: store this info in the context ctx := context.WithValue(r.Context(), ctxKey{}, ctxValue{username}) // delegate the work to the CardDAV handle actualHandler.ServeHTTP(w, r.WithContext(ctx)) }) }
ownBackend 構造体は、carddav.Backend インターフェイスを実装する必要があります。これはそれほど薄くはありませんが、それでも管理可能です。
CurrentUserPrincipal と AddressBookHomeSetPath は URL (スラッシュで始まりスラッシュで終わる) を提供する必要があります。通常はユーザー名/連絡先になります。ここは、コンテキスト (使用可能な唯一の引数) からユーザー名を抽出する必要がある場所です:
func currentUsername(ctx context.Context) (string, error) { if v, ok := ctx.Value(ctxKey{}).(ctxValue); ok { return v.username, nil } return "", errors.New("not authenticated") } type ownBackend struct{} // must begin and end with a slash func (b *ownBackend) CurrentUserPrincipal(ctx context.Context) (string, error) { username, err := currentUsername(ctx) return "/" + url.PathEscape(username) + "/", err } // must begin and end with a slash as well func (b *ownBackend) AddressBookHomeSetPath(ctx context.Context) (string, error) { principal, err := b.CurrentUserPrincipal(ctx) return principal + "contacts/", err }
その後、楽しい作業が始まります。AddressBook、GetAddressObject、および ListAddressObjects メソッドを実装する必要があります。
AddressBook は単純な構造体を返します。パスは上記の AddressBookHomeSetPath で始まり、スラッシュで終わる必要があります
GetAddressObject と ListAddressObjects は、(現在認証されているユーザーがそれらの連絡先にアクセスできることを確認するために) 現在のパスを確認し、連絡先を AddressObject として返す必要があります。
AddressObject には複数の属性があります。最も重要なことは次のとおりです。
VCard は実際の連絡先データを表すため、連絡先の保存方法に応じて調整する必要がある可能性があります。私の場合、次のように終了しました:
func utf8Field(v string) *vcard.Field { return &vcard.Field{ Value: v, Params: vcard.Params{ "CHARSET": []string{"UTF-8"}, }, } } func vcardFromUser(u graphqlient.User) vcard.Card { c := vcard.Card{} c.Set(vcard.FieldFormattedName, utf8Field(u.Firstname+" "+u.Lastname)) c.SetName(&vcard.Name{ Field: utf8Field(""), FamilyName: u.Lastname, GivenName: u.Firstname, }) c.SetRevision(u.UpdatedAt) c.SetValue(vcard.FieldUID, u.Extid) c.Set(vcard.FieldOrganization, utf8Field(u.Unit)) // addFields sorts the key to ensure a stable order addFields := func(fieldName string, values map[string]string) { for _, k := range slices.Sorted(maps.Keys(values)) { v := values[k] c.Add(fieldName, &vcard.Field{ Value: v, Params: vcard.Params{ vcard.ParamType: []string{k + ";CHARSET=UTF-8"}, // hacky but prevent maps ordering issues // "CHARSET": []string{"UTF-8"}, }, }) } } addFields(vcard.FieldEmail, u.Emails) addFields(vcard.FieldTelephone, u.Phones) vcard.ToV4(c) return c }
一部のメソッドでは連絡先を更新できます。 CardDAV 経由でメンバー リストを更新したくないので、Put メソッドと Delete メソッドに 403 エラーを返します。 return webdav.NewHTTPError(http.StatusForbidden,errors.New("carddav:operation not support"))
iOS では、CardDAV サーバーが https 経由でサービスを提供する必要があります。 openssl (192.168.XXX.XXX を IP アドレスに置き換えます) を使用して自己署名証明書をローカルで生成し、 http.ListenAndServeTLS(addr, "localhost.crt", "localhost.key", NewCardDAVHandler())
openssl req -new -subj "/C=US/ST=Utah/CN=192.168.XXX.XXX" -newkey rsa:2048 -nodes -keyout localhost.key -out localhost.csr openssl x509 -req -days 365 -in localhost.csr -signkey localhost.key -out localhost.crt
結論
この種のネイティブ統合を可能にする他の優れたプロトコルをご存知ですか?あなたの経験をぜひ共有してください!
以上が連絡先を携帯電話と同期するにはどうすればよいですか? Go に CardDAV を実装する!の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。