Search code examples
c++windowscurlgithub-apilibcurl

How to download a file from a private repository using curl?


I'm trying to download a file from a private GitHub repository, current code:

   #include <curl/curl.h>
 
   static size_t WriteMemoryCallback(void* contents, size_t size, size_t nmemb, void* userp) {
        size_t realsize = size * nmemb;
        auto& mem = *static_cast<std::string*>(userp);
        mem.append(static_cast<char*>(contents), realsize);
        return realsize;
    }
    
    
    
    void Download(std::string& data, char* url)
    {
        CURL* curl_handle;
        CURLcode res;
        struct curl_slist* slist{};
    
        curl_handle = curl_easy_init();
    
        curl_easy_setopt(curl_handle, CURLOPT_URL, url);
        SecureZeroMemory(url, strlen(url));        

        slist = curl_slist_append(slist, "Authorization: token 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");
        slist = curl_slist_append(slist, "Content-Type: application/json");
        curl_easy_setopt(curl_handle, CURLOPT_HTTPHEADER, slist);
    
        curl_easy_setopt(curl_handle, CURLOPT_TCP_KEEPALIVE, 0);
        curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, WriteMemoryCallback);
        curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, &data);
        curl_easy_setopt(curl_handle, CURLOPT_USERAGENT, "libcurl-agent/1.0");
        curl_easy_setopt(curl_handle, CURLOPT_FOLLOWLOCATION, 1L);  // redirects
       
        //curl_easy_setopt(curl_handle, CURLOPT_VERBOSE, 1L); // only to debug
    
        res = curl_easy_perform(curl_handle);
    
        if(res != CURLE_OK)
           std::cerr << "curl_easy_perform() failed: " << curl_easy_strerror(res) << '\n';
    
        curl_easy_cleanup(curl_handle);
        curl_global_cleanup();
    }


    int main(int argc, char* argv[]) {
         std::string data;
         Download(data, /* link */);
    }

This is what being downloaded to data:

<!DOCTYPE html>
<html lang="en" data-color-mode="auto" data-light-theme="light" data-dark-theme="dark" data-a11y-animated-images="system">
  <head>
    <meta charset="utf-8">
  <link rel="dns-prefetch" href="https://github.githubassets.com">
  <link rel="dns-prefetch" href="https://avatars.githubusercontent.com">
  <link rel="dns-prefetch" href="https://github-cloud.s3.amazonaws.com">
  <link rel="dns-prefetch" href="https://user-images.githubusercontent.com/">
  <link rel="preconnect" href="https://github.githubassets.com" crossorigin>
  <link rel="preconnect" href="https://avatars.githubusercontent.com">
...

I think the problem is setting the authorization token, i also tried:

slist = curl_slist_append(slist, "Authorization: Bearer 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");
slist = curl_slist_append(slist, "Content-Type: application/json");

Solution

  • Add Authorization and Accept headers like this:

    slist = curl_slist_append(slist, "Authorization: token <Your Token>");
    slist = curl_slist_append(slist, "Accept: application/vnd.github.v3+raw");
    

    then call

    curl_easy_setopt(curl_handle, CURLOPT_HTTPHEADER, slist);
    

    and provide the link to the file in this form:

    https://api.github.com/repos/<owner>/<repository>/contents/<path>