Home > Enterprise >  curl to fetch with digest flag
curl to fetch with digest flag

Time:02-20

There has been other questions on the subject, but nothing seems working for me.
I have a functional CURL, but I want to translate to JS (with Node).

CURL

curl --user "uername:pass" --digest \
 --header "Content-Type: application/json" \
 --include \
 --request POST "https://cloud.mongodb.com/api/atlas/v1.0/groups/MY_GROUP/clusters/MY_CLUSTER/fts/indexes?pretty=true" \
 --data '{
     "collectionName": "collname",
     "database": "myDB",
     "mappings": {
       "dynamic": true
     },
     "name": "default"
   }'

Response

HTTP/2 401 www-authenticate: Digest realm="MMS Public API", domain="", nonce="OtwBmcu89QuyVMLW6FP1W/ZjD3preQl0", algorithm=MD5, qop="auth", stale=false content-type: application/json content-length: 106 x-envoy-upstream-service-time: 2 date: Wed, 16 Feb 2022 17:05:37 GMT server: envoy

HTTP/2 200 date: Wed, 16 Feb 2022 17:05:37 GMT strict-transport-security: max-age=31536000; includeSubdomains; referrer-policy: strict-origin-when-cross-origin x-permitted-cross-domain-policies: none x-content-type-options: nosniff x-mongodb-service-version: gitHash=8284a4ea05955cb13c38df5489a3794b9a691d4f; versionString=v20220216 content-type: application/json x-frame-options: DENY content-length: 216 x-envoy-upstream-service-time: 154 server: envoy

I'm not sure why there is a 401 and a 200, but it works. However I get a 401 without the --digest flag, and none of the solutions below seems to include the digest?

Below are all the ways I tried, which all return 401 "You are not authorized for this resource.":

Fetch

fetch(url,
  {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      Authorization:
        'Basic '  
        Buffer.from(
          'user:pass'
        ).toString('base64'),
    },
    body: dataString,
  }
)

Same result with

Request

const headers = {
  'Content-Type': 'application/json',
};

var options = {
  url: url,
  method: 'POST',
  headers: headers,
  body: dataString,
  auth: {
    user: 'user',
    pass: 'pass',
  },
};

request(options, (error: any, response: any, body: any) => {
    ...
});

node-libcurl

  const curl = new Curl();
  curl.setOpt(Curl.option.HTTPHEADER, [
    'Content-Type: application/json',
  ]);
  curl.setOpt(Curl.option.URL, url);
  curl.setOpt(Curl.option.POST, true);
  curl.setOpt(Curl.option.USERPWD, 'user:pass');
  curl.setOpt(Curl.option.POSTFIELDS, dataString);

Even

PHP

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, "...");
curl_setopt($ch, CURLOPT_USERPWD, 'user:pass');
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json']);

$result = curl_exec($ch);
curl_close($ch);

Edit for the package request-digest

digestRequest
  .requestAsync({
    host: url,
    path: urlPath,
    port: 80,
    method: 'POST',
    json: true,
    headers: {
      'Content-Type': 'application/json',
    },
    body: body,
  })
  .then(function (response: any) {
    console.log(response);
  })
  .catch(function (error: any) {
    console.log(error);
  });

Response

Error: Bad request, answer is empty

CodePudding user response:

PHP

You need to specify that it's a digest:

curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_DIGEST);

Node Fetch

This is what I have found here:

fetch(url, {
    ... 
    headers: {
        'Authorization': 'Basic '   Buffer.from(`${username}:${password}`, 'binary').toString('base64')
    }
    ...
})

Comparing your code with the proposed code above I see that , 'binary' is missing from yours.

request-digest

There is a request-digest package that may help you. Examples (taken from the link shared in this paragraph):

Callback

var digestRequest = require('request-digest')('username', 'password');
digestRequest.request({
  host: 'http://test.com',
  path: '/api/v1/test.json',
  port: 80,
  method: 'GET',
  headers: {
    'Custom-Header': 'OneValue',
    'Other-Custom-Header': 'OtherValue'
  }
}, function (error, response, body) {
  if (error) {
    throw error;
  }
 
  console.log(body);
});

Promise-only

var digestRequest = require('request-digest')('username', 'password');
digestRequest.requestAsync({
  host: 'http://test.com',
  path: '/api/v1/test.json',
  port: 80,
  method: 'GET',
  excludePort: false,
  headers: {
    'Custom-Header': 'OneValue',
    'Other-Custom-Header': 'OtherValue'
  }
})
.then(function (response) {
  console.log(response.body);
})
.catch(function (error) {
  console.log(error.statusCode);
  console.log(error.body);
});
  • Related