This article is about PyScript and the MongoDB Data API. I have not used the MongoDB Data API before. I know MongoDB and PyScript fairly well, so I thought I would document my journey to see if they will work together. My only real concern is CORS. The HTTP REST portion should be easy to work with.
Prerequisites
- Basic understanding of Python and PyScript
- Basic understanding of MongoDB
- MongoDB Atlas account. Sign up link.
Recommended
I am using the MongoDB sample dataset. The MongoDB Atlas GUI has an option on the Database Deployments page “Load Sample Dataset”. Load Sample Data
Enable the MongoDB Data API
Once you have your MongoDB Atlas account configured, enable the Data API. In the MongoDB Web GUI, click on Data API in the left column.
Select the data source(s) and click Enable the Data API.
Once the Data API is enabled, save the URL Endpoint.
For each Data Source, select the Data API Access permissions, such as Read Only or Read and Write. For my work, I selected Read and Write.
You will need an API Key. Click the Create API Key button. Name your key and click the Generate API Key button.
The panel will display examples in cURL, Python, etc. Copy the cURL and Python examples.
For the examples, I selected my cluster for the Linked Data Source, sample_mflix for the Database and movies for the Collection.
Testing with the cURL example
Since I use Windows for my development workstation, I must modify the cURL example.
Original example:
1 2 3 4 5 6 7 8 9 10 |
curl --location --request POST 'https://data.mongodb-api.com/app/data-redacted/endpoint/data/v1/action/findOne' \ --header 'Content-Type: application/json' \ --header 'Access-Control-Request-Headers: *' \ --header 'api-key: redacted' \ --data-raw '{ "collection":"movies", "database":"sample_mflix", "dataSource":"jhanleytest", "projection": {"_id": 1} }' |
On Windows, it is much easier to move cURL data to a file. I first replaced the --data-raw
argument with -d @test.json:
1 2 3 4 5 6 |
{ "collection":"movies", "database":"sample_mflix", "dataSource":"jhanleytest", "projection": {"_id": 1} } |
The modified example is:
1 2 3 4 5 6 7 8 9 10 |
set APIKEY=REDACTED set BASE_URL=https://data.mongodb-api.com/app/data-REDACTED/endpoint/data/v1 set URL=%BASE_URL%/action/findOne curl --location --request POST %URL% ^ --header "Content-Type: application/json" ^ --header "Access-Control-Request-Headers: *" ^ --header "api-key: %APIKEY%" ^ -d @test1.json |
Executing that command results in:
1 |
{"document":{"_id":"62c8a0426f4d01bc002cabac"}} |
Excellent, the API works from my desktop using non-browser tools.
MongoDB Data API and CORS
My big question now is does the MongoDB API support CORS so that browsers can make requests?
I wrote a simple PyScript Python program. Update with the correct URL and API Key.
main.py:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
try: from error_handler import errorHandler import asyncio import json from pyodide.http import pyfetch except Exception as e: errorHandler(e) async def test_mongodb(): apikey = REDACTED base_url = 'https://data.mongodb-api.com/app/data-REDACTED/endpoint/data/v1' url = base_url + '/action/findOne' method = "POST" # headers = {"Content-type": "application/json"} headers = { "Content-type": "application/json", 'Access-Control-Request-Headers': '*', 'api-key': apikey } body = json.dumps({ "collection": "movies", "database": "sample_mflix", "dataSource": "jhanleytest" }) try: response = await pyfetch(url, method=method, headers=headers, body=body) except Exception as e: errorHandler(e) return console.log("results", await response.json()) console.log("status", response.status) try: await test_mongodb() except Exception as e: errorHandler(e) |
Sadly to say, MongoDB did not think of web browsers when designing the MongoDB Data API. My code receives the following error:
1 |
Access to fetch at 'https://data.mongodb-api.com/app/data-redacted/endpoint/data/v1/action/findOne' from origin 'http://localhost:9000' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled. |
What is the solution?
There are two solutions:
- MongoDB can improve the Data API to support specifying CORS header in the Data API configuration.
- Use a proxy application that runs alongside the browser to add CORS headers.
Since I have no control over the Data API, I decided to write a CORS proxy for PyScript. I will write another article once I am ready to publish.
MongoDB Data API and CORS
MongoDB has a page regarding the DATA API and CORS. Please click this link and vote so that they know how important this is:
Please Support CORS from the Data API
What should MongoDB provide as a solution?
The MongoDB Data API should:
- Provide a method of specifying allowed origins and HTTP methods.
- Respond to the HTTP OPTIONS method with an HTTP Status Code 200 and the following headers as a minimum:
- access-control-allow-headers
- access-control-allow-methods
- access-control-allow-origin
- access-control-allow-credentials
I wrote a Python program to send an OPTIONS request to the DATA API. MongoDB does return CORS headers. If I send the CORS header
headers["Access-Control-Request-Headers"] = "api-key,content-type"
then the response does not have CORS headers. The item that makes a difference is api-key
.
For PyScript, I discovered that if I remove the HTTP header api-key
the request passes the CORS preflight test and the response is HTTP Status Code 400:
1 2 3 4 5 |
{ "error":"no authentication methods were specified", "error_code":"InvalidParameter", "link":"https://realm.mongodb.com/groups/REDACTED/apps/REDACTED/logs?co_id=REDACTED" } |
I think this means MongoDB is close to enabling CORS support.
More Information
- Other articles that I have written on Pyscript
- Other articles that I have written on MongoDB
- An Introduction to the MongoDB Atlas Data API
- Data API Endpoints
- Load Sample Data
Photography Credit
I write free articles about technology. Recently, I learned about Pexels.com which provides free images. The image in this article is courtesy of Pixabay at Pexels.
I design software for enterprise-class systems and data centers. My background is 30+ years in storage (SCSI, FC, iSCSI, disk arrays, imaging) virtualization. 20+ years in identity, security, and forensics.
For the past 14+ years, I have been working in the cloud (AWS, Azure, Google, Alibaba, IBM, Oracle) designing hybrid and multi-cloud software solutions. I am an MVP/GDE with several.
August 12, 2023 at 7:33 PM
https://feedback.mongodb.com/forums/945334-atlas-app-services/suggestions/44666878-please-support-cors-from-the-data-api
Your requested feature was released.