Katakanlah anda membantu menguruskan organisasi atau kelab kecil dan mempunyai pangkalan data yang menyimpan semua butiran ahli (nama, telefon, e-mel...).
Bukankah lebih baik untuk mempunyai akses kepada maklumat terkini ini di mana-mana sahaja anda memerlukannya? Nah, dengan CardDAV anda boleh!
CardDAV ialah standard terbuka yang disokong dengan baik untuk pengurusan hubungan; ia mempunyai integrasi asli dalam Apl Kenalan iOS dan banyak apl tersedia untuk Android.
Sebelah pelayan, melaksanakan CardDAV ialah pelayan http yang bertindak balas kepada kaedah http yang luar biasa (PROPFIND, REPORT dan bukannya GET, POST...). Nasib baik terdapat modul Go untuk memudahkan kerja: github.com/emersion/go-webdav. Pustaka ini menjangkakan Backend yang dilaksanakan dan menyediakan http.Handler standard yang harus menyediakan permintaan HTTP selepas pengesahan.
Menariknya pustaka tidak memberikan sebarang bantuan berkenaan pengesahan pengguna, namun terima kasih kepada kebolehkomposisian Go, ini bukan satu isu.
CardDAV menggunakan bukti kelayakan Pengesahan Asas. Setelah bukti kelayakan disemak, kami boleh menyimpan bukti kelayakan tersebut dalam konteks (akan berguna kemudian):
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)) }) }
Struktur ownBackend mesti melaksanakan antara muka carddav.Backend, yang tidak terlalu nipis, tetapi masih boleh diurus.
CurrentUserPrincipal dan AddressBookHomeSetPath mesti menyediakan URL (bermula dan berakhir dengan garis miring). Biasanya ia akan menjadi nama pengguna/kenalan. Di sinilah anda perlu mengekstrak nama pengguna daripada konteks (yang merupakan satu-satunya hujah yang tersedia):
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 }
Selepas itu keseronokan boleh bermula: anda perlu melaksanakan kaedah AddressBook, GetAddressObject dan ListAddressObjects.
AddressBook mengembalikan struct mudah, di mana laluan harus bermula dengan AddressBookHomeSetPath di atas (dan berakhir dengan garis miring)
GetAddressObject dan ListAddressObjects mesti menyemak laluan semasa (untuk memastikan bahawa pengguna yang sedang disahkan boleh mengakses kenalan tersebut) dan kemudian mengembalikan kenalan sebagai AddressObject.
AddressObject mempunyai berbilang atribut, yang paling penting:
VCard mewakili data kenalan sebenar dan kemungkinan besar mesti disesuaikan bergantung pada cara anda menyimpan kenalan anda. Dalam kes saya, ia berakhir seperti ini:
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 }
Sesetengah kaedah membenarkan untuk mengemas kini kenalan. Memandangkan saya tidak mahu senarai ahli saya dikemas kini melalui CardDAV, saya mengembalikan ralat 403 kepada kaedah Put and Delete: return webdav.NewHTTPError(http.StatusForbidden, errors.New("carddav: operation not supported"))
iOS memerlukan pelayan CardDAV untuk berkhidmat melalui https. Anda boleh menjana sijil yang ditandatangani sendiri secara setempat menggunakan openssl (ganti 192.168.XXX.XXX dengan alamat IP anda) untuk dimasukkan ke dalam 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
Selepas itu anda sepatutnya boleh mencuba secara setempat dengan menambahkan "akaun kenalan CardDAV" yang menunjuk ke Alamat IP dan port anda sendiri.
Melaksanakan pelayan CardDAV dalam Go agak terlibat, tetapi jelas berbaloi: kenalan anda akan disegerakkan secara automatik dengan data yang anda ada pada pelayan organisasi anda!
Adakah anda tahu protokol hebat lain yang membenarkan integrasi asli seperti ini? Jangan ragu untuk berkongsi pengalaman anda!
Atas ialah kandungan terperinci Bagaimana untuk menyegerakkan kenalan anda dengan telefon anda? Melaksanakan CardDAV dalam Go!. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!