Help

Re: Fetch generated "TypeError : ... not permitted"

Solved
Jump to Solution
2866 1
cancel
Showing results for 
Search instead for 
Did you mean: 
s_kmb
5 - Automation Enthusiast
5 - Automation Enthusiast

Hello !

I am encountering a problem when creating an automation script for one of my tables. 

I set up a trigger to occur when the user creates a record. I then wrote a script to be run as an action of the trigger. This script contains a 'fetch' call to a local Flask server where we will do all the process ensuing this trigger activation.

Unfortunately, whenever I test my script, it always indicates : 

 

TypeError: Requests to '10.110.90.204' are not permitted
    at main on line 1

 

Here is the script I am using :

 

let response = await fetch('https://10.110.90.204:8050/process');

 

Can you help me with this, please ?

1 Solution

Accepted Solutions
ag314
6 - Interface Innovator
6 - Interface Innovator

Right, but that's because 192.168... is on your local network. When you run code from Airtable, you are using their servers. You cannot access a 192.168.. (ie local address) from an Airtable script. You will need Flask running on a public server that you can access. The original code you showed had a public IP address - that's what you need to be using. Which was why I was saying to be VERY, VERY careful when it comes to security and SSL policies. You NEVER want to expose any production servers - especially ones containing important (non-dummy) data - without having a very clear business case.

If you need to access Flask via your local IP address, then one option would be to write a little javascript app on your network that gets the Airtable info you need via Airtable's API and then forwards it along to Flash - and vice-versa. But this is not a clean solution, nor does it let you tie into automation hooks.

If the issues are CORS related, then you may not be able to use automation's fetch method. In which case, you'll want to consider Airtable scripting (outside of an automation) where you can use remoteFetchAsync. 

If you want to elaborate a bit more on your specific use-case, I might be able to suggest some other options.

See Solution in Thread

14 Replies 14
ag314
6 - Interface Innovator
6 - Interface Innovator

Very often a fetch API request requires two components: the url, as you included, and an options object with headers describing the type of request, access credentials, and those sorts of things.

Here’s an example:

let url = YOUR_URL

const options = {
  method: 'GET',
  headers: {
    "Content-Type": "application/json",
    "Authorization": "Bearer " + YOUR_ACCESS_TOKEN
  },
}

let res = await fetch(url, options)

let response = await res.json() // or res.text()
console.log(response)

I’m not too familiar with Flash, but I suspect you may need an "Access-Control-Allow-Origin" header field in the request.

s_kmb
5 - Automation Enthusiast
5 - Automation Enthusiast

Hello ag314, thank you for your reply.

Unfortunately, I still have the same problem. I tried doing the same via the Scripting Extension. When using "fetch()", I have the following error :

ERROR
TypeError: Failed to fetch
    at main on line 10
This error might be related to Cross-Origin Resource Sharing (CORS), a security mechanism that prevents websites from making malicious requests to other sites.

Unfortunately, it also stops some legitimate use-cases (such as calling an external API from the scripting app). You should be able to find some more information about this error from your browser's network developer tools, usually accessed by right-clicking on the page, choosing inspect element, and selecting the console tab in the panel that opens.

If you see notices or errors that refer to CORS or Access-Control-Allow-Origin, it's likely you've encountered a CORS error. The scripting app can't reliably detect CORS errors in all browsers, so you should double-check your code to make sure there aren't other errors (e.g. a mistyped domain name) that could be causing this instead.

You can try using the remoteFetchAsync API or a Scripting Action which both don't run in the browser and therefore don't have CORS limitations. You could also try contacting the API provider to ask about enabling CORS, or post on the community forum to see if there's a workaround for your specific API.

When using remoteFetchAsync(), I have this : 

ERROR
j: Error: Requests to '10.110.89.105' are not permitted
    at main on line 10

 The Flask server I use for testing has the following code :

app = Flask(__name__)
cors = CORS(app)

@app.route("/process", methods=['GET', 'POST']) # used for airtable webhooks -> programming notifications
def process():
    print(request)
    json_string = "webhook received"
    resp = Response(json_string)
    resp.headers['Access-Control-Allow-Origin'] = 'https://airtable.com'
    return resp

if __name__ == '__main__':
    app.run(host='10.110.89.105', port=8050, ssl_context='adhoc', debug=True)

 I do not know what to do from here... I think I am missing something but the question is ... what ?

ag314
6 - Interface Innovator
6 - Interface Innovator

Please paste in the fetch code you are using, including the headers. But be sure to X-out your Bearer token or whatever authorization key is required by Flask.

s_kmb
5 - Automation Enthusiast
5 - Automation Enthusiast

Sure ! Here is the fetch code : 

let url = 'https://10.110.89.105:8050/process';
const options = {
    method : "GET",
    headers: {
        "Content-Type": "application/json",
        "Access-Control-Allow-Origin" : "https://airtable.com"
    },
};
let res = await fetch(url, options);
let response = await res.json();
console.log(response);
ag314
6 - Interface Innovator
6 - Interface Innovator

What error are you getting with the code above? Add a console.log(res) right after the res line please. 

s_kmb
5 - Automation Enthusiast
5 - Automation Enthusiast

I added the console.log(res) thing but it says the same thing : "Requests are not permitted".

I think the execution cannot reach the console.log() because of the fetching blocking it with the await.

So I tested without "await" to see what happens, with the following code :

let url = 'https://192.168.1.12:8050/process';
const options = {
    method : "GET",
    headers: {
        "Content-Type": "application/json",
        "Access-Control-Allow-Origin" : "https://airtable.com"
    },
    
};
let res = fetch(url, options);
console.log(res);

 And it returned this : 

CONSOLE.LOG
{}

And also the same message as before : 

ERROR
TypeError: Requests to '192.168.1.12' are not permitted
    at main on line 10

 

ag314
6 - Interface Innovator
6 - Interface Innovator

You need the await as fetch is an asynchronous method. So displaying the console.log(res) without it will simply show you an empty res since it hasn't yet had a chance to fetch anything.

Has this ever worked from Airtable to Flask? I'm wondering if there's something on the server side (Flask). Perhaps the self-signed SSL certificate (ssl_context=adhoc) is not being trusted. One thing you could try as a TEST ONLY experiment would be to remove the ssl_context=adhoc argument from the app.run on the server. Again, this would be for TESTING PURPOSES ONLY - you never want to run this way in a live environment.

Also, please be sure the url you are using matches what you enabled in the app.run on the server.

s_kmb
5 - Automation Enthusiast
5 - Automation Enthusiast

I tried again and it's still the same problem.

Flask server :

from flask import Flask, request, Response
from flask_cors import CORS, cross_origin

app = Flask(__name__)

cors = CORS(app)

@app.route("/process", methods=['GET', 'POST']) # used for airtable webhooks -> programming notifications
def process():
    print(request)
    json_string = "webhook received"
    resp = Response(json_string)
    resp.headers['Access-Control-Allow-Origin'] = '*'
    return resp

if __name__ == '__main__':
    app.run(host='192.168.1.12', port=8050, debug=True)

Airtable script : 

let url = 'https://192.168.1.12:8050/process';
const options = {
    method : "GET",
    headers: {
        "Content-Type": "application/json",
        "Access-Control-Allow-Origin" : "https://airtable.com"
    },
    
};
let res = await fetch(url, options);
console.log(res);

And no it has never worked from Airtable to Flask. However, using 'https://192.168.1.12:8050/processin a browser works perfectly. The response is returned and displayed onto the web page.

ag314
6 - Interface Innovator
6 - Interface Innovator

Right, but that's because 192.168... is on your local network. When you run code from Airtable, you are using their servers. You cannot access a 192.168.. (ie local address) from an Airtable script. You will need Flask running on a public server that you can access. The original code you showed had a public IP address - that's what you need to be using. Which was why I was saying to be VERY, VERY careful when it comes to security and SSL policies. You NEVER want to expose any production servers - especially ones containing important (non-dummy) data - without having a very clear business case.

If you need to access Flask via your local IP address, then one option would be to write a little javascript app on your network that gets the Airtable info you need via Airtable's API and then forwards it along to Flash - and vice-versa. But this is not a clean solution, nor does it let you tie into automation hooks.

If the issues are CORS related, then you may not be able to use automation's fetch method. In which case, you'll want to consider Airtable scripting (outside of an automation) where you can use remoteFetchAsync. 

If you want to elaborate a bit more on your specific use-case, I might be able to suggest some other options.