skip to Main Content

I am trying to access the Scryfall API and perform the following request:

https://scryfall.com/docs/api/cards/collection

For this I have set up an Angular project that can be found on a public GitHub:

https://github.com/ProgFroz/scryfall_test_public

I have a NodeJS server running on port :7090 and the Angular frontend running on port :4200.

The request I perform looks like the following:

router.post('/scryfall/collection', (req, res) => {
  const identifiers = req.body.identifiers;
  console.log(identifiers);
  
  let url = 'https://api.scryfall.com/cards/collection';
  fetch(url, {
    method: 'POST',
    headers: {
        "Accept": "application/json",
        "Content-Type": "application/json"
    },
    body: {
      "identifiers": identifiers
    }
  })
    .then(res => res.json()).catch((err) => console.log(err))
    .then((out) => {
      res.json(out);
    })
    .catch(err => console.log(err));
});

I would expect a JSON return, since the request was more or less successful and the documentation states that I simply need to send the header content-type JSON to retrieve a JSON body. Is there anything else I can do to get a JSON body in return?

That is the frontend snippet that calls for my backend:

this.httpClient
.post<any>('/api/posts/scryfall/collection', {
    identifiers: test,
})
.subscribe((x) => {
    console.log(x);
});

The identifiers look the same as in the documentation described:

{
  "identifiers": [
    {
      "id": "683a5707-cddb-494d-9b41-51b4584ded69"
    },
    {
      "name": "Ancient Tomb"
    },
    {
      "set": "mrd",
      "collector_number": "150"
    }
  ]
}

The log tells me the following error:

SyntaxError: Unexpected token < in JSON at position 0
    at JSON.parse (<anonymous>)
    at Response.json (node:internal/deps/undici/undici:6160:23)
    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)

Which is probably caused by the wrong format being returned since it is text/html instead of JSON.

Here is the whole response:

Response {
  [Symbol(realm)]: null,
  [Symbol(state)]: {
    aborted: false,
    rangeRequested: false,
    timingAllowPassed: true,
    requestIncludesCredentials: true,
    type: 'default',
    status: 400,
    timingInfo: {
      startTime: 3919.7346000000834,
      redirectStartTime: 0,
      redirectEndTime: 0,
      postRedirectStartTime: 3919.7346000000834,
      finalServiceWorkerStartTime: 0,
      finalNetworkResponseStartTime: 0,
      finalNetworkRequestStartTime: 0,
      endTime: 0,
      encodedBodySize: 0,
      decodedBodySize: 0,
      finalConnectionTimingInfo: null
    },
    cacheState: '',
    statusText: 'Bad Request',
    headersList: HeadersList {
      [Symbol(headers map)]: [Map],
      [Symbol(headers map sorted)]: null
    },
    urlList: [ [URL] ],
    body: { stream: undefined }
  },
  [Symbol(headers)]: HeadersList {
    [Symbol(headers map)]: Map(14) {
      'date' => 'Wed, 13 Sep 2023 22:03:16 GMT',
      'content-type' => 'text/html',
      'transfer-encoding' => 'chunked',
      'connection' => 'keep-alive',
      'cache-control' => 'no-cache',
      'vary' => 'Accept-Encoding',
      'strict-transport-security' => 'max-age=31536000; includeSubDomains; preload',
      'via' => '1.1 vegur',
      'cf-cache-status' => 'DYNAMIC',
      'report-to' => '{"endpoints":[{"url":"https:\/\/a.nel.cloudflare.com\/report\/v3?s=CeWkpMtXv3v8DKZM6G%2BRIOAVAp7HVweoRp%2B9UcqSsK1oAaVgNAwIHcF7XO2iZPwc2Bb%2BveOCGmktNlaXdiF7zp0CTgsXPtHOXARKsYKjMWp9xDJxc4JlZh76z4cXeUd1G9WVm4x1yxLztQEBw%2Fg%3D"}],"group":"cf-nel","max_age":604800}',
      'nel' => '{"success_fraction":0,"report_to":"cf-nel","max_age":604800}',
      'x-content-type-options' => 'nosniff',
      'server' => 'cloudflare',
      'cf-ray' => '8063addfef6dca89-HAM'
    },
    [Symbol(headers map sorted)]: null
  }
}

I also used Postman to test it, which delivers the same (unavailable) results:
Postman

So the question essentially is, what exactly is wrong with my request, and how can I possible get the desired JSON body as return?

Edit:
The full response is

TypeError: The body has already been consumed.
    at consumeBody (node:internal/deps/undici/undici:6072:19)
    at consumeBody.next (<anonymous>)
    at Response.text (node:internal/deps/undici/undici:6146:28)
    at Response.json (node:internal/deps/undici/undici:6160:40)
    at C:UsersjustiDocumentsVisual Studio Code Projektelotusfield_backendroutesposts.js:28:55
    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)

The identifiers that are put into the body of the fetch are:

[
  { id: '683a5707-cddb-494d-9b41-51b4584ded69' },
  { name: 'Ancient Tomb' },
  { set: 'mrd', collector_number: '150' }
]

Edit2: I tried to change the type of the sent identifiers to a string, which yielded the same results unfortunately.

body: {
   identifiers: JSON.stringify({"identifiers": identifiers})
}

2

Answers


  1. simplify your fetch code

    let url = 'https://api.scryfall.com/cards/collection';
      let response = fetch(url, {
        method: 'POST',
        headers: {
            "Accept": "application/json",
            "Content-Type": "application/json"
        },
        body: {
          "identifiers": identifiers
        }
      })
        .then(res => res.json()).catch((err) => {console.log(err); return null;})
    
    Login or Signup to reply.
  2. Have you tried stringifying the body?

    I think it does not accept the object unlike Axios

    router.post('/scryfall/collection', (req, res) => {
      const url = 'https://api.scryfall.com/cards/collection';
      const identifiers = req.body.identifiers;
      fetch(url, {
        method: 'POST',
        headers: {
          Accept: 'application/json',
          'Content-Type': 'application/json',
        },
        body: JSON.stringify({ identifiers }),  // <== Here
      })
        .then((response) => response.json())
        .then((data) => {
          res.json(data);
        })
        .catch((err) => {
          console.error(err);
          res.status(500).json({ error: 'An error occurred' });
        });
    });
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search