3
$\begingroup$

I am having trouble making POST requests from JavaScript to Wolfram Cloud APIs.

Here is a minimal example to reproduce the issue:

<!DOCTYPE html>
<html lang="en" dir="ltr">
  <head>
    <meta charset="utf-8">
    <title>Test API</title>
    <script type="text/javascript">

    // Wolfram API
    fetch('https://www.wolframcloud.com/objects/c11abdbe-d203-406d-a6d3-a212d900c273', {
      method: 'POST',
      body: JSON.stringify({city1: 'London', city2:'Paris'}),
    })
    .then(response => response.json())
    .then(json => console.log(json))

    // Other Test API
    fetch('https://httpbin.org/post', {
      method: 'POST',
      body: JSON.stringify({city1: 'London', city2:'Paris'}),
    })
    .then(response => response.json())
    .then(json => console.log(json))

    </script>
  </head>
  <body>
    Testing the wolframcloud API
  </body>
</html>

The top fetch attempt is trying to call the Wolfram API introduced here https://reference.wolfram.com/language/workflow/DeployAWebAPI.html, but I get the error:

Failure: "The API could not be evaluated because there is no input for fields: \"city1\", \"city2\"."

However, the second fetch attempt with a different Test API succeeds with no issues.

Also, by comparison I have no problems calling the API from Python:

import urllib3

http = urllib3.PoolManager()

# Wolfram API
r1 = http.request('POST',
    'https://www.wolframcloud.com/objects/c11abdbe-d203-406d-a6d3-a212d900c273',
    fields={'city1': 'London', 'city2':'Paris'})
r1.status
r1.data

# Other Test API
r2 = http.request('POST',
    'http://httpbin.org/post',
    fields={'city1': 'London', 'city2':'Paris'})
r2.status
r2.data

So I wonder whether this is an issue specific to the interaction between JavaScript and Wolfram APIs? Thanks!

$\endgroup$

1 Answer 1

3
$\begingroup$

You have the wrong content type header in your request. Apparently, it expects 'application/x-www-form-urlencoded', so this will work:

const url = "https://www.wolframcloud.com/objects/c11abdbe-d203-406d-a6d3-a212d900c273";

const params = {city1: 'London', city2:'Paris'}

const encodeBody = params => Object
  .keys(params)
  .map((key) => encodeURIComponent(key) + '=' + encodeURIComponent(params[key]))
  .join('&');


fetch(url, {
  method: 'POST',
  headers: {
    'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8'
  },
  body: encodeBody(params)
})
.then(response => response.json())
.then(json => console.log(json))

You can look e.g. here for more details.

$\endgroup$
6
  • $\begingroup$ Amazing, thank you for your quick reply! :) $\endgroup$ Commented Apr 9, 2020 at 14:35
  • $\begingroup$ @AndreaDimitracopoulos Was glad to help. Thanks for the accept. $\endgroup$ Commented Apr 9, 2020 at 15:12
  • $\begingroup$ just in case you know, would this work also for sending an image (instead of text) or would I need something different? Thank you again! $\endgroup$ Commented Apr 9, 2020 at 17:25
  • 1
    $\begingroup$ @AndreaDimitracopoulos If you want to send an image as a file to the server / cloud, you would need to sent a multi-part request. The server should be prepared to handle it. Here is a simple example that might get you started. I have not done that myself for the cloud, so can't tell what kind of possible obstacles you may face on the server / cloud side. I actually would recommend to ask this as a separate question, after you try a few things yourself, in case if you encounter problems. $\endgroup$ Commented Apr 9, 2020 at 17:52
  • $\begingroup$ OK thank you again for your help! :) $\endgroup$ Commented Apr 9, 2020 at 18:11

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.