उमामी API के लिए एक C# क्लाइंट जोड़ना (हिन्दी (Hindi))

उमामी API के लिए एक C# क्लाइंट जोड़ना

Wednesday, 14 August 2024

//

7 minute read

परिचय

इस पोस्ट में मैं आपको दिखाऊँगा कि कैसे हममी रिपोर्टिंग API के लिए एक सी क्लाइंट बनाया जा सकता है

आप इस के लिए सभी स्रोत कोड ढूंढ सकते हैं मेरी GitHub रिपो पर.

पूर्व आवश्यकताएं

संस्थापित करें Umami. आप संस्थापना अनुदेश मिल सकते हैं यहाँ यह जानकारी देता है कि मैं इस साइट के लिए विश्लेषण प्रदान करने के लिए उमामी को कैसे स्थापित और उपयोग करता हूँ

पुनः, यह Umami Website Stats API अंतबिंदुओं में से कुछ के सरल कार्यान्वयन है यहाँ.

इस में मैंने निम्नलिखित अंतबिंदुओं को लागू करने का निर्णय लिया है

  • GET /api/websites/:websiteId/pageviews नाम के अनुसार यह अंतिम बिंदु एक निश्चित वेबसाइट के लिए एक समयावधि में पृष्ठ दृश्य और सत्रों को लौटाता है
{
  "pageviews": [
    { "x": "2020-04-20 01:00:00", "y": 3 },
    { "x": "2020-04-20 02:00:00", "y": 7 }
  ],
  "sessions": [
    { "x": "2020-04-20 01:00:00", "y": 2 },
    { "x": "2020-04-20 02:00:00", "y": 4 }
  ]
}
  • GET /api/websites/:websiteId/stats यह दिए गए वेबसाइट के लिए बुनियादी सांख्यिकी बताता है
{
  "pageviews": { "value": 5, "change": 5 },
  "visitors": { "value": 1, "change": 1 },
  "visits": { "value": 3, "change": 2 },
  "bounces": { "value": 0, "change": 0 },
  "totaltime": { "value": 4, "change": 4 }
}
  • GET /api/websites/:websiteId/metrics - यह दिए गए वेबसाइट URL आदि के लिए मापदंड लौटाता है
[
  { "x": "/", "y": 46 },
  { "x": "/docs", "y": 17 },
  { "x": "/download", "y": 14 }
]

जैसा कि आप Docs से देख सकते हैं, यह सभी पैरामीटरों की एक संख्या स्वीकार करता है (और मैं इन को क्वेरी पैरामीटरों के रूप में नीचे कोड में प्रस्तुत किया है

राइडर में परीक्षण

मैं हमेशा राइडर में API के परीक्षण से आरंभ करता हूँ

### Login Request and Store Token
POST https://{{umamiurl}}/api/auth/login
Content-Type: application/json

{
  "username": "{{username}}",

  "password": "{{password}}"
}
> {% client.global.set("auth_token", response.body.token);
    client.global.set("endAt", Math.round(new Date().getTime()).toString() );
    client.global.set("startAt", Math.round(new Date().getTime() - 7 * 24 * 60 * 60 * 1000).toString());
%}


### Use Token in Subsequent Request
GET https://{{umamiurl}}/api/websites/{{websiteid}}/stats?endAt={{endAt}}&startAt={{startAt}}
Authorization: Bearer {{auth_token}}

### Use Token in Subsequent Request
GET https://{{umamiurl}}/api/websites/{{websiteid}}/pageviews?endAt={{endAt}}&startAt={{startAt}}&unit=day
Authorization: Bearer {{auth_token}}


###
GET https://{{umamiurl}}}}/api/websites/{{websiteid}}/metrics?endAt={{endAt}}&startAt={{startAt}}&type=url
Authorization: Bearer {{auth_token}}

यह ' में चल नामों को रखने के लिए अच्छा अभ्यास है {{}} एक env.json फ़ाइल जिसे आप नीचे के रूप में निर्दिष्ट कर सकते हैं

{
  "local": {
    "umamiurl":"umamilocal.mostlylucid.net",
    "username": "admin",
    "password": "<password{>",
    "websiteid" : "32c2aa31-b1ac-44c0-b8f3-ff1f50403bee"
  }
}

सेटअप

पहले हम HttpClient और सेवाओं को कॉन्फ़िगर करने की जरूरत है कि हम अनुरोध करने के लिए उपयोग करेंगे


public static class UmamiSetup
{
    public static void SetupUmamiServices(this IServiceCollection services, IConfiguration config)
    {
        var umamiSettings = services.ConfigurePOCO<UmamiSettings>(config.GetSection(UmamiSettings.Section));
        services.AddHttpClient<AuthService>(options =>
        {
            options.BaseAddress = new Uri(umamiSettings.BaseUrl);
            
        }) .SetHandlerLifetime(TimeSpan.FromMinutes(5))  //Set lifetime to five minutes
        .AddPolicyHandler(GetRetryPolicy());;
        services.AddScoped<UmamiService>();
        services.AddScoped<AuthService>();

    }
    static IAsyncPolicy<HttpResponseMessage> GetRetryPolicy()
    {
        return HttpPolicyExtensions
            .HandleTransientHttpError()
            .OrResult(msg =>  msg.StatusCode == HttpStatusCode.ServiceUnavailable)
            .WaitAndRetryAsync(6, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)));
    }

}

यहाँ हम सेटिंग वर्ग कॉन्फ़िगर करें UmamiSettings और जोड़ें AuthService और UmamiService सेवा संग्रह के लिए हम भी एक पुनः प्रयास नीति HttpClient में अस्थायी त्रुटियों को संभालने के लिए जोड़ें

अगले हम बनाने के लिए आवश्यक है UmamiService और AuthService वर्ग

AuthService सिर्फ API से JWT टोकन प्राप्त करने के लिए जिम्मेदार है

public class AuthService(HttpClient httpClient, UmamiSettings umamiSettings, ILogger<AuthService> logger)
{
    private string _token;
    public HttpClient HttpClient => httpClient;

    public async Task<bool> LoginAsync()
    {
        var loginData = new
        {
            username = umamiSettings.Username,
            password = umamiSettings.Password
        };

        var content = new StringContent(JsonSerializer.Serialize(loginData), Encoding.UTF8, "application/json");
        var response = await httpClient.PostAsync("/api/auth/login", content);

        if (response.IsSuccessStatusCode)
        {
            var authResponse = await response.Content.ReadFromJsonAsync<AuthResponse>();


            _token = authResponse.Token;
            httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", _token);
            logger.LogInformation("Login successful");
            return true;
        }

        logger.LogError("Login failed");
        return false;
    }
}

यहाँ हम एक सरल विधि है LoginAsync जो एक POST अनुरोध को भेजता है /api/auth/login उपयोक्ता नाम और कूटशब्द के साथ अंतिम बिंदु _token क्षेत्र और सेट Authorization हेडर पर HttpClient.

UmamiService API को अनुरोध करने के लिए जिम्मेदार है प्रत्येक मुख्य विधि के लिए I'ने अनुरोध वस्तुओं को परिभाषित किया है जो प्रत्येक अंतबिंदु के लिए सभी पैरामीटर स्वीकार करते हैं

वे सब एक सिमीयार पैटर्न पर चलते हैं

public async Task<UmamiResult<StatsResponseModels>> GetStatsAsync(StatsRequest statsRequest)
{
    // Start building the query string
    var queryParams = new List<string>
    {
        $"start={statsRequest.StartAt}",
        $"end={statsRequest.EndAt}"
    };

    // Add optional parameters if they are not null
    if (!string.IsNullOrEmpty(statsRequest.Url)) queryParams.Add($"url={statsRequest.Url}");
    if (!string.IsNullOrEmpty(statsRequest.Referrer)) queryParams.Add($"referrer={statsRequest.Referrer}");
    if (!string.IsNullOrEmpty(statsRequest.Title)) queryParams.Add($"title={statsRequest.Title}");
    if (!string.IsNullOrEmpty(statsRequest.Query)) queryParams.Add($"query={statsRequest.Query}");
    if (!string.IsNullOrEmpty(statsRequest.Event)) queryParams.Add($"event={statsRequest.Event}");
    if (!string.IsNullOrEmpty(statsRequest.Host)) queryParams.Add($"host={statsRequest.Host}");
    if (!string.IsNullOrEmpty(statsRequest.Os)) queryParams.Add($"os={statsRequest.Os}");
    if (!string.IsNullOrEmpty(statsRequest.Browser)) queryParams.Add($"browser={statsRequest.Browser}");
    if (!string.IsNullOrEmpty(statsRequest.Device)) queryParams.Add($"device={statsRequest.Device}");
    if (!string.IsNullOrEmpty(statsRequest.Country)) queryParams.Add($"country={statsRequest.Country}");
    if (!string.IsNullOrEmpty(statsRequest.Region)) queryParams.Add($"region={statsRequest.Region}");
    if (!string.IsNullOrEmpty(statsRequest.City)) queryParams.Add($"city={statsRequest.City}");

    // Combine the query parameters into a query string
    var queryString = string.Join("&", queryParams);

    // Make the HTTP request
    var response = await authService.HttpClient.GetAsync($"/api/websites/{WebsiteId}/stats?{queryString}");

    if (response.IsSuccessStatusCode)
    {
        var content = await response.Content.ReadFromJsonAsync<StatsResponseModels>();
        return new UmamiResult<StatsResponseModels>(response.StatusCode, response.ReasonPhrase ?? "Success", content ?? new StatsResponseModels());
    }

    if (response.StatusCode == HttpStatusCode.Unauthorized)
    {
        await authService.LoginAsync();
        return await GetStatsAsync(statsRequest);
    }

    logger.LogError("Failed to get stats");
    return new UmamiResult<StatsResponseModels>(response.StatusCode, response.ReasonPhrase ?? "Failed to get stats", null);
}

यहाँ आप देख सकते हैं मैं अनुरोध वस्तु लेता हूँ

public class BaseRequest
{
    public long StartAt => StartAtDate.ToMilliseconds(); // Timestamp (in ms) of starting date
    public long EndAt => EndAtDate.ToMilliseconds(); // Timestamp (in ms) of end date
    public DateTime StartAtDate { get; set; }
    public DateTime EndAtDate { get; set; }
}
public class StatsRequest : BaseRequest
{
    // Optional properties
    public string? Url { get; set; } // Name of URL
    public string? Referrer { get; set; } // Name of referrer
    public string? Title { get; set; } // Name of page title
    public string? Query { get; set; } // Name of query
    public string? Event { get; set; } // Name of event
    public string? Host { get; set; } // Name of hostname
    public string? Os { get; set; } // Name of operating system
    public string? Browser { get; set; } // Name of browser
    public string? Device { get; set; } // Name of device (e.g., Mobile)
    public string? Country { get; set; } // Name of country
    public string? Region { get; set; } // Name of region/state/province
    public string? City { get; set; } // Name of city
}

और पैरामीटरों से क्वेरी स्ट्रिंग बनाएँ UmamiResult ऑब्जेक्ट. यदि अनुरोध के साथ एक 401 स्थिति कोड से असफल होता है तो हम कॉल करें LoginAsync विधि और अनुरोध को पुनः प्रयास करें. यह सुनिश्चित करता है कि हम |' | elegantly | ' | टोकन समाप्ति को संभालें

निष्कर्ष

यह उमामी API के लिए एक सी# क्लाइंट बनाने का एक सरल उदाहरण है। आप इसे अधिक जटिल क्लाइन्ट बनाने या अपने अनुप्रयोगों में API को एकीकृत करने के लिए प्रारंभिक बिंदु के रूप में उपयोग कर सकते हैं

Finding related posts...
logo

© 2026 Scott Galloway — Unlicense — All content and source code on this site is free to use, copy, modify, and sell.