"यदि कोई कर्मचारी अपना काम अच्छी तरह से करना चाहता है, तो उसे पहले अपने औजारों को तेज करना होगा।" - कन्फ्यूशियस, "द एनालेक्ट्स ऑफ कन्फ्यूशियस। लू लिंगगोंग"
मुखपृष्ठ > प्रोग्रामिंग > अपने संपर्कों को अपने फ़ोन के साथ कैसे सिंक्रनाइज़ करें? गो में कार्डडीएवी लागू करना!

अपने संपर्कों को अपने फ़ोन के साथ कैसे सिंक्रनाइज़ करें? गो में कार्डडीएवी लागू करना!

2024-11-07 को प्रकाशित
ब्राउज़ करें:439

How to synchronize your contacts with your phone? Implemeting CardDAV in Go!

मान लीजिए कि आप एक छोटे संगठन या क्लब को प्रबंधित करने में मदद करते हैं और आपके पास सभी सदस्यों के विवरण (नाम, फोन, ईमेल...) संग्रहीत करने वाला एक डेटाबेस है।
क्या यह अच्छा नहीं होगा कि आपको यह अद्यतन जानकारी हर उस जगह उपलब्ध हो जिसकी आपको आवश्यकता है? खैर, कार्डडीएवी के साथ आप यह कर सकते हैं!

कार्डडीएवी संपर्क प्रबंधन के लिए एक अच्छी तरह से समर्थित खुला मानक है; इसका iOS संपर्क ऐप और Android के लिए उपलब्ध कई ऐप्स में एक मूल एकीकरण है।

सर्वर-साइड, कार्डडीएवी को लागू करना एक http-सर्वर है जो असामान्य http-विधियों (PROPFIND, GET के बजाय रिपोर्ट, पोस्ट...) पर प्रतिक्रिया करता है। सौभाग्य से काम को बहुत सरल बनाने के लिए एक गो मॉड्यूल मौजूद है: github.com/emersion/go-webdav। यह लाइब्रेरी एक कार्यान्वित बैकएंड की अपेक्षा करती है और एक मानक http.Handler प्रदान करती है जिसे प्रमाणीकरण के बाद HTTP अनुरोधों को पूरा करना चाहिए।

प्रमाणीकरण

दिलचस्प बात यह है कि लाइब्रेरी उपयोगकर्ता प्रमाणीकरण के संबंध में कोई सहायता प्रदान नहीं करती है, हालांकि गो कंपोज़बिलिटी के लिए धन्यवाद, यह कोई मुद्दा नहीं है।
कार्डडीएवी बेसिक ऑथ क्रेडेंशियल्स का उपयोग करता है। एक बार क्रेडेंशियल्स की जांच हो जाने के बाद, हम उन क्रेडेंशियल्स को संदर्भ में सहेज सकते हैं (बाद में उपयोगी होंगे):

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 संरचना को कार्डडेव.बैकएंड इंटरफ़ेस लागू करना होगा, जो बहुत पतला नहीं है, लेकिन फिर भी प्रबंधनीय है।

करंटयूजरप्रिंसिपल और एड्रेसबुकहोमसेटपाथ को यूआरएल (स्लैश से शुरू और खत्म) प्रदान करना होगा। आमतौर पर यह उपयोगकर्ता नाम/संपर्क होगा. यह वह जगह है जहां आपको संदर्भ से उपयोगकर्ता नाम निकालने की आवश्यकता है (जो एकमात्र उपलब्ध तर्क है):

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
}

उसके बाद मज़ा शुरू हो सकता है: आपको एड्रेसबुक, गेटएड्रेसऑब्जेक्ट और लिस्टएड्रेसऑब्जेक्ट्स विधियों को लागू करने की आवश्यकता है।

एड्रेसबुक एक सरल संरचना लौटाता है, जहां पथ ऊपर दिए गए एड्रेसबुकहोमसेटपाथ से शुरू होना चाहिए (और एक स्लैश के साथ समाप्त होना चाहिए)

GetAddressObject और ListAddressObjects को वर्तमान पथ की जांच करनी चाहिए (यह सुनिश्चित करने के लिए कि वर्तमान में प्रमाणित उपयोगकर्ता उन संपर्कों तक पहुंच सकता है) और फिर संपर्कों को एड्रेसऑब्जेक्ट के रूप में लौटाएं।

एड्रेसऑब्जेक्ट

एड्रेसऑब्जेक्ट में कई विशेषताएं हैं, सबसे महत्वपूर्ण:

  • इस विशेष संपर्क को पहचानने का पथ (मनमाना हो सकता है, स्लैश से शुरू करें)
  • ईटैग क्लाइंट को तुरंत जांचने की अनुमति देता है कि क्या कोई अपडेट हुआ है (यदि आप इसे भूल जाते हैं, तो आईओएस कुछ भी नहीं दिखाएगा)
  • वह कार्ड जो वीकार्ड की अपेक्षा करता है

वीकार्ड वास्तविक संपर्क डेटा का प्रतिनिधित्व करता है और संभवतः आप अपने संपर्कों को कैसे संग्रहीत करते हैं इसके आधार पर इसे अनुकूलित किया जाना चाहिए। मेरे मामले में, यह इस तरह समाप्त हुआ:

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
}

रीडओनली-शॉर्टकट अपनाना

कुछ विधियां किसी संपर्क को अपडेट करने की अनुमति देती हैं। चूँकि मैं नहीं चाहता कि मेरी सदस्य सूची को कार्डडीएवी के माध्यम से अपडेट किया जाए, मैं पुट और डिलीट तरीकों में 403 त्रुटि लौटाता हूँ: return webdav.NewHTTPError(http.StatusForbidden,Errors.New("carddav: कार्रवाई समर्थित नहीं है"))

स्थानीय स्तर पर परीक्षण

आईओएस को https पर सेवा देने के लिए कार्डडीएवी सर्वर की आवश्यकता होती है। आप 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

उसके बाद आपको अपने स्वयं के आईपी-पते और पोर्ट की ओर इशारा करते हुए एक "कार्डडीएवी संपर्क खाता" जोड़कर स्थानीय रूप से प्रयोग करने में सक्षम होना चाहिए।

निष्कर्ष

गो में कार्डडीएवी सर्वर को लागू करना थोड़ा जटिल है, लेकिन स्पष्ट रूप से इसके लायक है: आपके संपर्क स्वचालित रूप से आपके संगठन के सर्वर पर मौजूद डेटा के साथ सिंक हो जाएंगे!

क्या आप अन्य अच्छे प्रोटोकॉल जानते हैं जो इस तरह के मूल एकीकरण की अनुमति देते हैं? बेझिझक अपने अनुभव साझा करें!

विज्ञप्ति वक्तव्य इस लेख को पुन: प्रस्तुत किया गया है: https://dev.to/cmdscale/how-to-synchronize-your-contacts-with-yth-your-phone-phone-implementing-carddav-in-go-9ia?1 यदि कोई उल्लंघन है, तो कृपया इसे हटाने के लिए [email protected] पर संपर्क करें।
नवीनतम ट्यूटोरियल अधिक>

चीनी भाषा का अध्ययन करें

अस्वीकरण: उपलब्ध कराए गए सभी संसाधन आंशिक रूप से इंटरनेट से हैं। यदि आपके कॉपीराइट या अन्य अधिकारों और हितों का कोई उल्लंघन होता है, तो कृपया विस्तृत कारण बताएं और कॉपीराइट या अधिकारों और हितों का प्रमाण प्रदान करें और फिर इसे ईमेल पर भेजें: [email protected] हम इसे आपके लिए यथाशीघ्र संभालेंगे।

Copyright© 2022 湘ICP备2022001581号-3