Home > other >  Why do I have the message 'Transfer Encoding is not implementing by AWS (Use with CURL)'?
Why do I have the message 'Transfer Encoding is not implementing by AWS (Use with CURL)'?

Time:01-07

I try to create an application for use the AWS API. For this, i programme in c with the library CURL. I test my application with "GET" request and it's work. After, i test with the "PUT" request but, i have an error :

<?xml version="1.0" encoding="UTF-8"?>
<Error><Code>NotImplemented</Code>
<Message>A header you provided implies functionality that is not implemented</Message>
<Header>Transfer-Encoding</Header>
<RequestId> *** </RequestId>
<HostId> ***</HostId>
</Error>

my code :


   

    #include <stdio.h>
       #include <curl/curl.h>
    
    #include <iostream>
    #include "sha256_calc.h"
    #include <ctime>
    #include <hmac_sha256/hmac_sha256.h>
    #include <vector>
    
    using std::string;
    using std::cout;
    using std::endl;
    
    
    #define BUCKET_NAME "<my bucket>"
    #define REGION "eu-west-3"
    #define METHODE_PUT "PUT"
    #define SERVICE_S3 "s3"
    #define ALGORITHM "AWS4-HMAC-SHA256"
    
    #define ACCESS_KEY "<My access Key>"
    #define SECRET_KEY "<My secret access Key>"
    
    #define SHA256_HASH_SIZE 32
    
    size_t write_data(void *ptr, size_t size, size_t nmemb, FILE *stream) {
        size_t written = fwrite(ptr, size, nmemb, stream);
        return written;
    }
    
    
    string vector_to_string (std::vector<uint8_t> val)
    {
        string retour = "";
    
        char res[2048];
        char intermedaire[2];
    
        for (int i = 0; i < SHA256_HASH_SIZE; i  )
        {
            //sprintf(intermedaire,"%x",val[i]);
            retour  = val[i];
        }
        return retour;
    }
    
    std::vector<uint8_t> sign(string key,string msg)
    {
         std::vector<uint8_t> out(SHA256_HASH_SIZE);
         hmac_sha256(key.data(), key.size(), msg.data(), msg.size(),out.data(), out.size());
         return out;
    }
    
    
    std::vector<uint8_t> getSignatureKey(string key,string dateStamp,string regionName,string 
    serviceName)
    {
        printf("key : %s \n" , key.c_str());
    
        std::vector<uint8_t> kDate = sign("AWS4"   key, dateStamp);
        for (int i = 0; i < SHA256_HASH_SIZE; i  )
        {
            printf("%d\n",kDate[i]);
        }
        printf("\n");
    
        string buff = vector_to_string (kDate);
        std::vector<uint8_t> kRegion = sign(buff, regionName);
        for (int i = 0; i < SHA256_HASH_SIZE; i  )
        {
            printf("%d\n",kRegion[i]);
        }
        printf("\n");
    
        buff = vector_to_string (kRegion);
        std::vector<uint8_t> kService = sign(buff, serviceName);
        for (int i = 0; i < SHA256_HASH_SIZE; i  )
        {
            printf("%d\n",kService[i]);
        }
        printf("\n");
    
        buff = vector_to_string (kService);
    
    
        std::vector<uint8_t> kSigning = sign(buff, "aws4_request");
        for (int i = 0; i < SHA256_HASH_SIZE; i  )
        {
            printf("%d\n",kSigning[i]);
        }
        printf("\n");
    
         return kSigning;
    }
    
    
    int main(void)
    {
      CURL *curl;
      CURLcode res;
      curl_slist *chunk=NULL;
    
      char *file = (char*)"fichier/CR1-12_11.pdf";
      char end_point[2048];
      char host[1024];
      sprintf(host,"%s.s3.%s.amazonaws.com",BUCKET_NAME,REGION);
      sprintf(end_point,"https://%s/fichier/CR1-12_11.pdf",host);
    
    
      time_t now = time(0);
      tm *gmtm = gmtime(&now);
    
      char amzdate[32];
      char datestamp[32];
      sprintf(amzdate,"dddTdddZ",gmtm->tm_year 1900,gmtm->tm_mon 1,gmtm- 
      >tm_mday,gmtm->tm_hour,gmtm->tm_min,gmtm->tm_sec);
      //sprintf(amzdate,"dddTdddZ",1900 gmtm->tm_year,gmtm->tm_mon 1,gmtm- 
      >tm_mday,8,45,25);
      sprintf(datestamp,"ddd",1900 gmtm->tm_year,gmtm->tm_mon 1,gmtm->tm_mday);
    
      cout << gmtm->tm_hour << endl;
    
    
      string canonical_uri;
      canonical_uri = (string)"/"   file;
    
      string test = "";
      string payload_hash = sha256(test);
    
      string canonical_headers;
      canonical_headers = (string)"host:"   host   "\nx-amz-content-sha256:"   payload_hash   
      "\nx-amz-date:"   amzdate   "\n";
    
      string signed_header = "host;x-amz-content-sha256;x-amz-date";
    
      string canonicale_request;
      canonicale_request = (string) METHODE_PUT   "\n"   canonical_uri   "\n\n"   
      canonical_headers   "\n"   signed_header   "\n"   payload_hash;
    
      printf ("%s\n",canonicale_request.c_str());
    
      string credential_scope;
      credential_scope = (string) datestamp   "/"   REGION   "/"   SERVICE_S3   "/aws4_request";
    
    
      string string_to_sign;
      string_to_sign = (string) ALGORITHM    "\n"   amzdate   "\n"   credential_scope   "\n"   
      sha256(canonicale_request);
    
      char *pCACertFile = (char*)"<file>";
    
      std::vector<uint8_t> signing_key ;
      signing_key  = getSignatureKey(SECRET_KEY,datestamp,REGION,SERVICE_S3);
      string buff = vector_to_string(signing_key);
    
      std::vector<uint8_t> signature(SHA256_HASH_SIZE);
      string string_to_sign_buff = string_to_sign;
    
      hmac_sha256(buff.data(), buff.size(), string_to_sign_buff.data(), 
      string_to_sign_buff.size(),signature.data(), signature.size());
    
      printf("\n");
      for (int i = 0; i < SHA256_HASH_SIZE; i  )
      {
          printf("%d\n",signing_key[i]);
      }
      printf("\n");
    
    
      printf("\n %s \n",string_to_sign_buff.c_str());
    
      for (int i = 0; i < SHA256_HASH_SIZE; i  )
      {
          printf("%d\n",signature[i]);
      }
    
    
      FILE *fileOpen = fopen("<file>","rb");
      FILE *fileOpenWrite = fopen("<file>","wb");
      if (fileOpen)
      {
          printf("fichier ok \n");
      }
      else
      {
          printf("erreur\n");
      }
    
      FILE *f = fopen(pCACertFile,"r");
    
    
      if (f)
      {
          fclose(f);
      }
      else
      {
          printf("certificat abscent");
      }
    
      string buffUser="";
      curl=curl_easy_init();
      //curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0);
      curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0);
    
      curl_easy_setopt(curl, CURLOPT_URL, end_point);
      curl_easy_setopt(curl, CURLOPT_PUT, 1);
    
      buff = credential_scope;
      buff = ACCESS_KEY   string("/")   buff;
      printf("%s\n",buff.c_str());
    
    
      string test_val = "";
      char tampon[8];
      for (int i = 0; i < SHA256_HASH_SIZE; i  )
      {
          sprintf(tampon,"x",signature[i]);
          test_val  = tampon;
      }
    
      buffUser = (string) "Authorization:"  ALGORITHM  " Credential="  ACCESS_KEY   "/"   
      credential_scope   ",SignedHeaders="   signed_header   ",Signature="   test_val;
      chunk = curl_slist_append(chunk,buffUser.c_str());
    
      buffUser = "x-amz-content-sha256:"   payload_hash;
      chunk = curl_slist_append(chunk,buffUser.c_str());
    
      buff = amzdate;
      buffUser = "x-amz-date:"   buff;
      chunk = curl_slist_append(chunk,buffUser.c_str());
    
      buffUser = "x-amz-decoded-content-length: 1024";
      chunk = curl_slist_append(chunk,buffUser.c_str());
    
      curl_easy_setopt(curl,CURLOPT_HTTPHEADER,chunk);
    
      curl_easy_setopt(curl,CURLOPT_READDATA,fileOpen);
    
        res = curl_easy_perform(curl);
    
    
        if(res != CURLE_OK)
          fprintf(stderr, "curl_easy_perform() failed: %s\n",
                  curl_easy_strerror(res));
    
        curl_easy_cleanup(curl);
     // }
        fclose (fileOpen);
      printf("Fin programme \n");
      return 0;
    }

The signature fonction, i can verify this with an other programme and, the GET methode use this.

CodePudding user response:

If you use CURLOPT_PUT, you should also use CURLOPT_INFILESIZE or similar to tell libcurl how big the body of the request is that you are going to send (in your case, the number of bytes in <file>).

If the size is known in advance, there is no longer a need to use chunked encoding, therefore no longer a need to send a Transfer-Encoding header, and this error should go away.

Unrelated to your question, consider the CURLOPT_AWS_SIGV4 libcurl option if you haven't already.

CodePudding user response:

I fixe the bug, i use CURLOPT_INFILESIZE and i add new line for calculate the flux.

[NEW CODE]


    #include <stdio.h>
    #include <curl/curl.h>
    #include <iostream>
    #include "sha256_calc.h"
    #include <ctime>
    #include <hmac_sha256/hmac_sha256.h>
    #include <vector>
    
    using std::string;
    using std::cout;
    using std::endl;
    
    
    #define BUCKET_NAME "<bucket>"
    #define REGION "eu-west-3"
    #define METHODE_PUT "PUT"
    #define SERVICE_S3 "s3"
    #define ALGORITHM "AWS4-HMAC-SHA256"
    
    #define ACCESS_KEY "<access_key>"
    #define SECRET_KEY "<secret_key>"
    
    #define SHA256_HASH_SIZE 32
    
    
    string vector_to_string (std::vector<uint8_t> val)
    {
        string retour = "";
    
        char res[2048];
        char intermedaire[2];
    
        for (int i = 0; i < SHA256_HASH_SIZE; i  )
        {
            //sprintf(intermedaire,"%x",val[i]);
            retour  = val[i];
        }
        return retour;
    }
    
    std::vector<uint8_t> sign(string key,string msg)
    {
         std::vector<uint8_t> out(SHA256_HASH_SIZE);
         hmac_sha256(key.data(), key.size(), msg.data(), msg.size(),out.data(), out.size());
         return out;
    }
    
    
    std::vector<uint8_t> getSignatureKey(string key,string dateStamp,string regionName,string serviceName)
    {
        printf("key : %s \n" , key.c_str());
    
        std::vector<uint8_t> kDate = sign("AWS4"   key, dateStamp);
    
        string buff = vector_to_string (kDate);
        std::vector<uint8_t> kRegion = sign(buff, regionName);
    
        buff = vector_to_string (kRegion);
        std::vector<uint8_t> kService = sign(buff, serviceName);
    
        buff = vector_to_string (kService);
    
    
        std::vector<uint8_t> kSigning = sign(buff, "aws4_request");
    
         return kSigning;
    }
  
    
    
    int main(void)
    {
      CURL *curl;
      CURLcode res;
      curl_slist *chunk=NULL;
    
      char *file = (char*)"<file>";
      char end_point[2048];
      char host[1024];
      sprintf(host,"%s.s3.%s.amazonaws.com",BUCKET_NAME,REGION);
      sprintf(end_point,"https://%s/<file>",host);
    
    
      time_t now = time(0);
      tm *gmtm = gmtime(&now);
    
      char amzdate[32];
      char datestamp[32];
      sprintf(amzdate,"dddTdddZ",gmtm->tm_year 1900,gmtm->tm_mon 1,gmtm->tm_mday,gmtm->tm_hour,gmtm->tm_min,gmtm->tm_sec);
      //sprintf(amzdate,"dddTdddZ",1900 gmtm->tm_year,gmtm->tm_mon 1,gmtm->tm_mday,8,45,25);
      sprintf(datestamp,"ddd",1900 gmtm->tm_year,gmtm->tm_mon 1,gmtm->tm_mday);
    
      cout << gmtm->tm_hour << endl;
    
    
      string canonical_uri;
      canonical_uri = (string)"/"   file;
      string test = "";
      char val;
    
      FILE *fileTest = fopen("<file_local>","rb");
    
      if (fileTest)
      {
          val = fgetc(fileTest);
          while (!feof(fileTest))
          {
            test  = val;
            val = fgetc(fileTest);
    
          }
          fclose(fileTest);
      }
      else
      {
          printf("fichier introuvable");
      }
    
      printf("taille test : %d",test.length());
    
      string payload_hash = sha256(test);
    
      string canonical_headers;
      canonical_headers = (string)"host:"   host   "\nx-amz-content-sha256:"   payload_hash   "\nx-amz-date:"   amzdate   "\n";
    
      string signed_header = "host;x-amz-content-sha256;x-amz-date";
    
      string canonicale_request;
      canonicale_request = (string) METHODE_PUT   "\n"   canonical_uri   "\n\n"   canonical_headers   "\n"   signed_header   "\n"   payload_hash;
    
      printf ("%s\n",canonicale_request.c_str());
    
      string credential_scope;
      credential_scope = (string) datestamp   "/"   REGION   "/"   SERVICE_S3   "/aws4_request";
    
    
      string string_to_sign;
      string_to_sign = (string) ALGORITHM    "\n"   amzdate   "\n"   credential_scope   "\n"   sha256(canonicale_request);
    
      char *pCACertFile = (char*)"C:/Users/merop/Documents/build-test_api-Desktop_Qt_5_15_2_MinGW_32_bit-Debug/debug/cacert.pem";
    
      std::vector<uint8_t> signing_key ;
      signing_key  = getSignatureKey(SECRET_KEY,datestamp,REGION,SERVICE_S3);
      string buff = vector_to_string(signing_key);
    
      std::vector<uint8_t> signature(SHA256_HASH_SIZE);
      string string_to_sign_buff = string_to_sign;
    
      hmac_sha256(buff.data(), buff.size(), string_to_sign_buff.data(), string_to_sign_buff.size(),signature.data(), signature.size());
    
      printf("\n");
      for (int i = 0; i < SHA256_HASH_SIZE; i  )
      {
          printf("%d\n",signing_key[i]);
      }
      printf("\n");
    
    
      printf("\n %s \n",string_to_sign_buff.c_str());
    
      for (int i = 0; i < SHA256_HASH_SIZE; i  )
      {
          printf("%d\n",signature[i]);
      }
    
    
      FILE *fileOpen = fopen("<file_local>","rb");
      if (fileOpen)
      {
          printf("fichier ok \n");
      }
      else
      {
          printf("erreur\n");
      }
    
      FILE *f = fopen(pCACertFile,"r");
    
    
      if (f)
      {
          fclose(f);
      }
      else
      {
          printf("certificat abscent");
      }
    
      string buffUser="";
      curl=curl_easy_init();
      curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0);
      curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0);
    
      curl_easy_setopt(curl, CURLOPT_URL, end_point);
      curl_easy_setopt(curl, CURLOPT_PUT, 1L);
    
      buff = credential_scope;
      buff = ACCESS_KEY   string("/")   buff;
      printf("%s\n",buff.c_str());
    
    
      string test_val = "";
      char tampon[8];
      for (int i = 0; i < SHA256_HASH_SIZE; i  )
      {
          sprintf(tampon,"x",signature[i]);
          test_val  = tampon;
      }
    
      buffUser = (string) "Authorization:"  ALGORITHM  " Credential="  ACCESS_KEY   "/"   credential_scope   ",SignedHeaders="   signed_header   ",Signature="   test_val;
      chunk = curl_slist_append(chunk,buffUser.c_str());
    
      buffUser = "x-amz-content-sha256:"   payload_hash;
      chunk = curl_slist_append(chunk,buffUser.c_str());
    
      buff = amzdate;
      buffUser = "x-amz-date:"   buff;
      chunk = curl_slist_append(chunk,buffUser.c_str());
    
    
              buffUser = "Content-Length: 80512 ";
              chunk = curl_slist_append(chunk,buffUser.c_str());
    
              buffUser="Connection: keep-alive";
              chunk = curl_slist_append(chunk,buffUser.c_str());
    
              buffUser="Expect: 100-continue";
              chunk = curl_slist_append(chunk,buffUser.c_str());
    
              buffUser="Content-Type: text/plain";
              chunk = curl_slist_append(chunk,buffUser.c_str());
    
      curl_easy_setopt (curl,CURLOPT_HTTP_TRANSFER_DECODING,1);
    
      curl_easy_setopt(curl,CURLOPT_INFILESIZE,1);
    
      curl_easy_setopt(curl,CURLOPT_HTTPHEADER,chunk);
      curl_easy_setopt(curl, CURLOPT_READDATA, fileOpen);
    
        res = curl_easy_perform(curl);
    
    
        if(res != CURLE_OK)
          fprintf(stderr, "curl_easy_perform() failed: %s\n",
                  curl_easy_strerror(res));
    
        curl_easy_cleanup(curl);
        fclose (fileOpen);
      printf("Fin programme \n");
      return 0;
    }

WARNING it's a dev code, it's possible it don't work, take care. (and we can clean the code)

  •  Tags:  
  • Related