A few days ago, I was experimenting with using Google Cloud Funtions to interact with the ICON blockchain. The function was set up to respond to an HTTP trigger, and it worked fine when accessed directly from a web browser. However, when I tried to access the function URL with Vue, the browser console reported a number of CORS-related errors. After some digging around and testing, I was able to resolve the issue. In this post, I’ll show you how I enabled CORS for a Google Cloud Function using the Python 3.7 runtime.
These are the CORS-related errors I was experiencing when calling my Google Cloud Function from a Vue application running on a localhost web server.
- XMLHttpRequest cannot load https://xyz.cloudfunctions.net/function.
- No ‘Access-Control-Allow-Origin’ header is present on the requested resource.
- Origin ‘https://localhost:3000’ is therefore not allowed access.
Here’s the Python code I was using for my Google Cloud Function.
import json
from iconsdk.icon_service import IconService
from iconsdk.providers.http_provider import HTTPProvider
def get_latest_block(request):
icon_service = IconService(HTTPProvider("https://ctz.solidwallet.io", 3))
block = icon_service.get_block("latest")
return json.dumps(block, indent=2)
As you can see, it is quite basic. All it does is make a request to an ICON node, and returns the details for the latest block. While this function works fine when requested through a web browser or curl, accessing it from an application without proper CORS configuration doesn’t work.
To make the above function accessible from my Vue project, I had to make a few changes to the Python code in Google Cloud Functions. CORS consists of two requests, a pre-flight request followed by the main request. While I am not a CORS expert, I think the issue with accessing the Google Cloud Funtion from Vue was related to the proper CORS headers not being set in my Vue application.
To resolve this issue, Google’s documentation recommends setting the proper headers in the Cloud Funtion itself.
The updated version of the Google Cloud Function can be found below. As you can see, there is an additional if
block that sets the correct headers for a pre-flight request with the OPTIONS
method. After the correct headers have been set, the main request is made with the output of the function, a 200 response code, and the CORS headers – return (json.dumps(block), 200, headers)
.
import json
from iconsdk.icon_service import IconService
from iconsdk.providers.http_provider import HTTPProvider
def get_latest_block(request):
## Set ICON service.
icon_service = IconService(HTTPProvider("https://ctz.solidwallet.io", 3))
## Get latest block.
block = icon_service.get_block("latest")
## Set CORS headers for the preflight request
if request.method == 'OPTIONS':
## Allows GET requests from any origin with the Content-Type
headers = {
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Methods': 'GET',
'Access-Control-Allow-Headers': 'Content-Type',
'Access-Control-Max-Age': '3600'
}
return ('', 204, headers)
## Set CORS headers for the main request
headers = {
'Access-Control-Allow-Origin': '*'
}
return (json.dumps(block), 200, headers)
After rewriting the Google Cloud Function in this way, I was able to call the function successfully in my Vue application.