Issues with Cross-Origin using flask and ajax - javascript

I'm having some issues with the "Cross-Origin Request Blocked". I tried to allow first from the server, than from all ("*"). Got every time the same error message on the chrome developer toolkit.
Here is my flask python code:
application = Flask(__name__)
application.config.from_object(__name__)
cors = CORS(application, resorces={r'/*': {"origins": '*'}})
#application.route("/get-live-data",methods=['GET'])
#cross_origin()
def live_data():
con = connect_db()
cur = con.cursor()
cur.execute("SELECT * from envoiContinuT")
sqlite_result = cur.fetchall()
cle = json.load(open(JSON_STATUS))
parametres = json.load(open(JSON_PARAMETRES))
descT = []
for key in cle["status"]:
attr = parametres[key]
if attr["envoiC"] == 1:
descT.append(attr["description"])
response = any_response(flask.jsonify(data=descT))
return response
Here is my Ajax code:
var baseURL = "http://localhost:8000";
function getLiveData(data){
//Get the parameters descriptions
$.ajax({
method: 'GET',
url:baseURL + '/get-live-data',
headers: {
"Accept" : "application/json",
"Content-type": "application/json"
},
success:function(data){
console.log(data);
//populateAccordion(data);
},
error: function(XMLHttpRequest, textStatus, errorThrown) {
console.log("Status: " + textStatus);
console.log("Error: " + errorThrown);
}
});
}
Thank you for your answer!

You have a typo here:
cors = CORS(application, resorces={r'/*': {"origins": '*'}})
^^^^^^^^
Should be:
cors = CORS(application, resources={r'/*': {"origins": '*'}})
Also, there’s no point in sending a Content-type request header for GET request. There’s no request body for GET requests, so no need to specify a content type. So instead just do this:
headers: {
"Accept" : "application/json",
},
Otherwise, if you send a Content-Type request header with the value application/json, that triggers your browser to do a CORS preflight OPTIONS request, and your config must allow it:
#application.route("/get-live-data",methods=['GET', 'POST'])
#cross_origin(headers=['Content-Type']) # Send Access-Control-Allow-Headers
But if you allow the Content-Type request header, you might as well allow POST requests too (as above)—since as mentioned earlier here, there’s no point in allowing it just for GET requests.

Related

Ajax POST not reaching server, returning 400 only in Firefox

I have a Flask server running in Apache that returns an HTML page with a button to submit an AJAX POST request to a relative URL. In Firefox, the AJAX call fails immediately with a 400, logging POST response ERROR code: 400. Logging the xhr object or the data parameter to the console results in <unavailable>, with its responseText attribute as undefined. The response is exactly the same, regardless of what URL is passed to AJAX. The absolute URL (http://thehostname.com/path/send-email) also gives the same result.
Apache's access.log shows no request coming in at the time of the AJAX requests. The request does not come up at all in Firefox's "Network" tab of the dev tools. The request works fine in Chrome with all other conditions the same, as well is with cURL.
The code is below. Please help!
HTML:
<img width="20px" src="mail.png" alt="" onerror="this.style.display='none'" onclick="sendEmail('val1', 'val2', 'val3')">
JS:
function sendEmail(val1, val2, val3) {
val1 = prompt('Prompt2 for ' + val2 + ':', val1);
console.log('Val1: '+ val1);
if(val1) {
let xhr = $.ajax({
method: 'POST',
url: 'send-email',
// Tried with and without stringify
data: JSON.stringify({param1: val1, param2: val2, param3: val3}),
contentType: "application/json; charset=utf-8",
dataType: 'text',
cache: false,
traditional: true
}).done(function(){
alert("Sent!");
}).fail(function(data){
console.log("Info:");
console.log(xhr.responseText);
alert('Failed to send');
});
}
console.log("Ret false");
return false;
};
Python endpoint:
#app.route('/autorack_testing_report/send-email', methods=['POST'])
#app.route('/send-email', methods=['POST'])
def send_email():
print("Send email") # Not getting printed
info = request.form or request.json
if not (info and info.get('param1') and info.get('param2')):
abort(400, 'Must supply recipient and ticket')
send_to_list = re.split(',|;', info['param1'])
send_to = []
for s in send_to_list:
if s.strip():
send_to.append(s.strip() + '#domain.com')
send_to = ','.join(send_to)
ticket = info['ticket']
smtp = smtplib.SMTP('mysmtphost', 25)
msg = MIMEMultipart('alternative')
msg['Subject'] = 'subject'
msg['From'] = msg['To'] = send_to
msg.attach(MIMEText('somecontent', 'plain'))
smtp.sendmail(send_to, send_to, msg.as_string())
smtp.quit()
resp = make_response('Success', 200)
resp.headers['Content-Type'] = 'text/plain'
return resp
Firefox console output:
Val1: myinput
Ret false
POST response ERROR code: 400
POST response ERROR code: 400
Info:
undefined
No Python output, since Apache isn't receiving the request.
The 400 Bad Request response status code indicates that the server cannot or will not process the request due to something that is perceived to be a client error (e.g., malformed request syntax, invalid request message framing, or deceptive request routing). where does 'send-email' point to?

Cross origin POST request not working for Outlook API

I'm using this part of the Outlook API. It says that you should be able to do a post request, however when I try I get the following error:
Failed to load https://login.microsoftonline.com/common/oauth2/v2.0/token: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:3003' is therefore not allowed access. The response had HTTP status code 400.
How do I fix this though? I obviously don't have access to Outlook's servers, but surely they would let me do a post request considering that's what it says to do in the documentation!.
Here is my code by the way if that helps:
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script>
let url = new URL(window.location);
let code = url.searchParams.get('code');
let redirect = 'http%3A%2F%2Flocalhost%3A3003%2Fauth-process-token.html';
let clientId = '<MY ID>';
let clientSecret = '<MY KEY>';
var req_string = 'grant_type=authorization_code&code=' + code + '&redirect_uri=' + redirect + '&client_id=' + clientId + '&client_secret=' + clientSecret;
$.ajax({
type: 'POST',
url: 'https://login.microsoftonline.com/common/oauth2/v2.0/token',
crossDomain: true,
data: req_string,
dataType: 'application/x-www-form-urlencoded',
success: function (responseData, textStatus, jqXHR) {
var value = responseData.someKey;
},
error: function (responseData, textStatus, errorThrown) {
console.log('POST failed.', errorThrown);
}
});
</script>
EDIT: I fixed the "bad request" error, but it still gives me the other one.
One workaround for this is by using cors.io
http://cors.io/?http://your_link
so it would be
http://cors.io/?https://login.microsoftonline.com/common/oauth2/v2.0/token

Javascript Fetch API: header params not working

This is my sample request:
var header = new Headers({
'Platform-Version': 1,
'App-Version': 1,
'Platform': 'FrontEnd'
});
var myInit = {
method : 'GET',
headers: header,
mode : 'no-cors',
cache : 'default'
}
fetch('http://localhost:3000/api/front_end/v1/login', myInit)
.then(res => {
console.log(res.text())
})
When I debug, I see that this request is sent successfully to server, but server hasn't received header params (in this case is Platform-Version, App-Version and Platform). Please tell me which part do I config wrong.
thanks
You are using it correctly, but you have to tell your backend service to allow custom headers (X-). For example, in PHP:
header("Access-Control-Allow-Headers: X-Requested-With");
Also, your custom headers should be prefixed with X-. So you should have:
'X-Platform-Version': '1'
And one last thing, your mode needs to be cors.
You can see that standard headers are being sent with the following code. take a look at the network tab to see the standard request headers.
var header = new Headers();
// Your server does not currently allow this one
header.append('X-Platform-Version', 1);
// You will see this one in the log in the network tab
header.append("Content-Type", "text/plain");
var myInit = {
method: 'GET',
headers: header,
mode: 'cors',
cache: 'default'
}
fetch('http://localhost:3000/api/front_end/v1/login', myInit)
.then(res => {
console.log(res.text())
});

How to disable 'withCredentials' in api call using node.js only (https package)

I'm using a node.js script that load in-built https package. When using it I get error:
XMLHttpRequest cannot load [constructed-api-url]. A wildcard '*' cannot be used in the 'Access-Control-Allow-Origin' header when the credentials flag is true. Origin 'http://localhost:3000' is therefore not allowed access. The credentials mode of an XMLHttpRequest is controlled by the withCredentials attribute.
I'm using node.js 4.4.3, and its https api docs does not really mention anything about withCredentials.
The script being used is this one.
Is there anyway to set the xhr call's withCredentials to false using node.js https?
I am looking to something analogous to this jquery ajax call (just focusing on the xhr field):
$.ajax({
type: 'POST', async:true,
url: 'https://someapp.constructed.url/token',
dataType: "json",
contentType: 'application/x-www-form-urlencoded; charset=utf-8',
xhrFields: {
withCredentials: true
},
headers: {
'Authorization': 'Basic ' + appInfo
},
success: function (result) {
var token = result.access_token;
//…
},
error: function (req, status, error) {
if (typeof(req) != 'undefined') {
var msg = status || req.responseJSON.error;
//…
}
}
});
There is another very similar example, but this is related to the request package, which I don't want to include in dependencies. Beside, my used script is already using https.
So the answer was there all the time, after all:
After a bit of research, found that node's https package uses practically same options as http, including the withCredentials option (not documented in node's http/https, but part of xhr documentation). It was a matter of including the url option within the options object along the withCredentials option, and then pass the options object as parameter for https.get.
And the constructed code would be more or less as follows (focus on the options variable):
var options = {
url: 'https://my.domain.com/api/endpoint',
withCredentials: false
}
var querystring = '?key=' + [_my_api_key];
var param1 = '&' + [paramKey] + '=' + [paramValue];
var datos;
options.url += querystring;
options.url += param1;
https.get(options, function (res) {
res.on('data', function (data) {
datos += data;
});
res.on('end', function () {
try {
var data = JSON.parse(datos);
} catch (e) {
console.error('Unable to parse response as JSON', e);
}
});
}).on('error', function (e) {
console.error('An error occurred with the request:', e.message);
callback(e.message);
});

Using Emotion API for Video (Javascript or Ruby)

So I'm working on posting a video to the Emotion API for video and I haven't been able to get a response.
I've been able to get it to work on the Microsoft online console, but when I try to implement it in my Rails app using (1) JavaScript Ajax, or (2) Ruby server-side code, I consistently get various errors.
Here's my code. At first I tried to Ajax way, but I had a suspicion that the API doesn't have CORS enabled. So then I tried Ruby, to no success.
Ruby attempt:
def index
uri = URI('https://api.projectoxford.ai/emotion/v1.0/recognizeinvideo')
uri.query = URI.encode_www_form({
})
data = File.read("./public/mark_zuck.mov")
request = Net::HTTP::Post.new(uri.request_uri)
# Request headers
request['Ocp-Apim-Subscription-Key'] = 'e0ae8aad4c7f4e33b51d776730cff5a9'
# Request body
request.body = data
request.content_type = "video/mov"
response = Net::HTTP.start(uri.host, uri.port, :use_ssl => uri.scheme == 'https') do |http|
http.request(request)
end
puts response.body
end
Here's my Ajax attempt:
function CallAPI(apiUrl, apiKey){
console.log("API called");
$(".loading").css("display", "inline-block");
$.ajax({
url: apiUrl,
beforeSend: function (xhrObj) {
xhrObj.setRequestHeader("Content-Type", "application/octet-stream");
xhrObj.setRequestHeader("Ocp-Apim-Subscription-Key", apiKey);
},
type: "POST",
data: '{"url": "http://localhost:5000/mark_zuck.mov"}',
processData: false,
success: function(response){
console.log("API success");
ProcessResult(response);
$(".loading").css("display", "none");
console.log(response);
},
error: function(error){
console.log("API failed");
$("#response").text(error.getAllResponseHeaders());
$(".loading").css("display", "none");
console.log(error);
}
})
Yes, I've regenerated my key. This is just to illustrate my point.
So you have to set Content-Type to application/octet-stream if it's a binary file you're sending, like I was.
If you use a url you should set Content-Type to application/json and the url must be publicly available.

Categories

Resources