flask keep blocking post request sent with "fetch" in js [closed] - flask

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 4 days ago.
Improve this question
i'am trying to make a chrome extension to send back DOM content to the flask server written below. but i am facing this error POST http://localhost:5000/api/json net::ERR_BLOCKED_BY_CLIENT content.js:10 and then afterwards : Uncaught (in promise) TypeError: Failed to fetch.
here is the code:
server.py:
from flask import Flask, request
from flask_cors import CORS
app = Flask(__name__)
cors = CORS(app, resources={r"/api/*": {"origins": "*"}})
app.config['WTF_CSRF_CHECK_DEFAULT'] = False
#app.route('/api/json', methods=['POST'])
def json():
request_data = request.get_json()
language = None
framework = None
python_version = None
example = None
boolean_test = None
if request_data:
if 'language' in request_data:
language = request_data['language']
if 'framework' in request_data:
framework = request_data['framework']
if 'version_info' in request_data:
if 'python' in request_data['version_info']:
python_version = request_data['version_info']['python']
if 'examples' in request_data:
if (type(request_data['examples']) == list) and (len(request_data['examples']) > 0):
example = request_data['examples'][0]
if 'boolean_test' in request_data:
boolean_test = request_data['boolean_test']
return '''
The language value is: {}
The framework value is: {}
The Python version is: {}
The item at index 0 in the example list is: {}
The boolean value is: {}'''.format(language, framework, python_version, example, boolean_test)
if __name__ == '__main__':
app.run(host="0.0.0.0",port=5000,debug=True)
content.js:
fetch('http://localhost:5000/api/json', {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({
"language" : "Python",
"framework" : "Flask",
"website" : "Scotch",
"version_info" : {
"python" : "3.9.0",
"flask" : "1.1.2"
},
"examples" : ["query", "form", "json"],
"boolean_test" : true
})
})
.then(response => response.json())
.then(response => console.log(JSON.stringify(response)))
and finally manifest.json:
{
"manifest_version": 3,
"name": "test extension",
"version": "1.0",
"content_scripts": [{
"matches":["*://*.google.com/*"],
"js": ["content.js"]
}],
"action": {
"default_title": "Click",
"default_popup": "popup.html"
},
"background":{
"service_worker":"background.js"
},
"permissions":["activeTab"]
}
i tried disabling CORS and CSRF protection, but none of them worked. i couldnt send a post request with postman neither.with these attirbutes set:
changed type to "POST" ,On the body tab, change to raw and selected JSON from the drop-down.
body:
{
"language" : "Python",
"framework" : "Flask",
"website" : "Scotch",
"version_info" : {
"python" : "3.9.0",
"flask" : "1.1.2"
},
"examples" : ["query", "form", "json"],
"boolean_test" : true
}

You are trying to parse a response in JSON format within your fetch call. But the server doesn't send any JSON. Use jsonify inside your endpoint. You can find documentation here.
from flask import jsonify
#app.post('/api/json')
def json():
request_data = request.get_json()
language = None
framework = None
python_version = None
example = None
boolean_test = None
if request_data:
if 'language' in request_data:
language = request_data['language']
if 'framework' in request_data:
framework = request_data['framework']
if 'version_info' in request_data \
and 'python' in request_data['version_info']:
python_version = request_data['version_info']['python']
if 'examples' in request_data \
and (type(request_data['examples']) == list) \
and (len(request_data['examples']) > 0):
example = request_data['examples'][0]
if 'boolean_test' in request_data:
boolean_test = request_data['boolean_test']
return jsonify(
language=language,
framework=framework,
python_version=python_version,
boolean_test=boolean_test
)

Related

How to bind a path variable to the request body parameter?

I want to post a HTTP request like this:
http://localhost/context/{{name}}/{{age}}
And I want to bind these path variables to request body, if my request body is :
{
"name": "Frank",
"age": 18
}
the final request I want to send is:
http://localhost/context/Frank/18
so how to achieve this function in POSTMAN?
postman request
Provisioning your request in Postman (non-parametric url):
Parametric url
I don't think you need to pass variables in your route, since you're already passing them in the request-body. However, here's a brief.
If you're working with NodeJS (using Express) and any JS library, you can send the request as thus, (using axios):
const body = {
"name": "Frank",
"age": 18
}
const requestHandler = async() => {
const serverResponse = await axios.post(`http://localhost/context/${body.name}/${body.age}`, {data: body}, {
headers: {
"Content-Type": "application/json",
"Authorization": `Bearer ${backend-token}`
}
};
Then, on your server-side, with a proper definition for your routes (for parametric and non-paramatric choice of url), you'd create a route to handle the request as:
Using Express
import {Router} from "express";
const yourServerRouter = Router();
yourServerRouter.post(`yourPrimaryDomain/:name/:age`, function-to-handle-request)
If you're working with a python framework (Flask or Django), you can do thus:
Flask (using flask_restful):
urls = [f"your_base_url/name/age"]
from flask_restful import Resource, request
import json
class BioData(Resource):
def post(self):
url = request.url
if "context" in url:
request_body = json.loads(request.data)
response = self.context_handler(request_data)
def context_handler(self, request_data):
name, age = request_data
....
....
flask_app = Flask(__name__)
flask_app.add_resource(BioData, *urls)
Django (Using DRF - viewsets)
from rest_framework import viewsets, routers
class BioDataViewsets(viewsets.ModelViewSets):
#action(methods=["POST"], detail=False, url_name="context", url_path="context")
def context(self, *args, **kwargs):
clients_request = json.loads(self.request.body)
**define your path as above (for flask)**
context_router = routers.DefaultRouter()
context_router.register("name/age/", company_viewsets.CompanyViewSets)
url_patterns = [path(f"your_base_url/context", include(context_router.urls())]
Eventually I got some clues from this page. The request body can be parsed through Pre-request-Script, and the attributes of interest can be set as variables and referenced in URL.
var r = JSON.parse(request.data);
pm.variables.set("name", r.name);
pm.variables.set("age", r.age);
And use below form to apply variables set in the Pre-request-Script:
http://localhost/context/{{name}}/{{age}}
the request body is :
{
"name": "Frank",
"age": 18
}
postman request

Not able to connect to the translation API

url: https://translatorappeagle.cognitiveservices.azure.com/
I'm also using my key from my resources page. I get a an error 404: not found. I copied the code from the getting started section for the translation API.
Please let me know what to do.
import os, requests, uuid, json
key_var_name = 'TRANSLATOR_TEXT_SUBSCRIPTION_KEY'
if not key_var_name in os.environ:
raise Exception('Please set/export the environment variable: {}'.format(key_var_name))
subscription_key = os.environ[key_var_name]
endpoint_var_name = 'TRANSLATOR_TEXT_ENDPOINT'
if not endpoint_var_name in os.environ:
raise Exception('Please set/export the environment variable: {}'.format(endpoint_var_name))
endpoint = os.environ[endpoint_var_name]
# If you encounter any issues with the base_url or path, make sure
# that you are using the latest endpoint: https://learn.microsoft.com/azure/cognitive-services/translator/reference/v3-0-translate
path = '/translate?api-version=3.0'
params = '&to=de&to=it'
constructed_url = endpoint + path + params
headers = {
'Ocp-Apim-Subscription-Key': subscription_key,
'Content-type': 'application/json',
'X-ClientTraceId': str(uuid.uuid4())
}
# You can pass more than one object in body.
body = [{
'text' : 'Hello World!'
}]
request = requests.post(constructed_url, headers=headers, json=body)
response = request.json()
print(json.dumps(response, sort_keys=True, indent=4, separators=(',', ': ')))

Django, CORS, CSRF - am I doing it right?

My setup (local) is the following:
Vue.js running on localhost:8080 (npm run serve)
REST API built with Django running on localhost:8000 (./manage-py runserver)
In order to enable this to work I've made the following additions:
ALLOWED_HOSTS = [
...
'localhost',
'localhost:8000',
'localhost:8080',
]
INSTALLED_APPS = [
...
'rest_framework',
'corsheaders',
]
MIDDLEWARE = [
...
'django.contrib.sessions.middleware.SessionMiddleware',
'corsheaders.middleware.CorsMiddleware',
'django.middleware.common.CommonMiddleware',
...
]
CORS_ORIGIN_WHITELIST = (
'localhost:8080',
'localhost:8000',
)
CORS_ALLOW_CREDENTIALS = True
from corsheaders.defaults import default_headers
CORS_ALLOW_HEADERS = default_headers + (
'credentials',
)
One of my API functions:
#ensure_csrf_cookie
def try_login(request):
# this is just to get the initial CSRF token:
if request.method == "GET" or request.method == "OPTIONS":
return JsonResponse({'status': 'ok'})
# else, an actual login request:
else:
data = JSONParser().parse(request)
user = authenticate(request, username=data['user'] , password=data['pass'])
if user is not None:
login(request, user)
return JsonResponse({'login_succ': 'ok'});
else:
return JsonResponse({'login_succ': 'fail'});
Finally, in Vue:
api: function(endpoint, method, data) {
var headers = new Headers();
headers.append('content-type', 'application/json');
if (... this is not the first request ever ...)
{
csrftoken = document.cookie.replace(/(?:(?:^|.*;\s*)csrftoken\s*\=\s*([^;]*).*$)|^.*$/, "$1");
headers.append('X-CSRFToken', csrftoken);
}
method = method || 'GET';
var config = {
method: method,
body: data !== undefined ? JSON.stringify(data) : null,
headers: headers,
};
config['credentials'] = 'include';
return fetch(endpoint, config)
.then(response => response.json())
.catch((error) => { console.log(...); });
},
trylogin: function() {
// initial request: just to get the CSRF token
this.api(".../login/", "GET").then(
response => {
this.api(".../login/", "POST", {'username': ..., 'password': ...} ).then(
response => {
if ("login_succ" in response && res["login_succ"] == "ok")
{} // user is logged in
}
);
}
);
}
What happens now, afaiu, is that my initial API request (which does not have to be pointed to the endpoint equal to the subsequent POST request, right?) gets the CSRF token as a cookie. Every subsequent request reads this cookie and sets the X-CSRFToken header. The cookie itself is also being sent in the subsequent requests. I do not understand why is the token needed in both places.
Is this approach correct? Is everything I've done necessary? (Are there redundant parts?) I'm especially interested in the way that I should acquire the token in the first place, and in general with the token's lifecycle.
Thank you.

Haystack-Whoosh Django search engine works locally but not on production

Using Whosh 2.7.4 and Django-Haystack version 2.5.dev1.
We have a similar setup as described here:
https://www.youtube.com/watch?v=jKSNciGr8kY&index=16&list=PLxxA5z-8B2xk4szCgFmgonNcCboyNneMD
https://www.youtube.com/watch?v=B-n6_m66TmA&index=22&list=PLxxA5z-8B2xk4szCgFmgonNcCboyNneMD
settings.py
WHOOSH_INDEX = os.path.join(PROJECT_ROOT, 'whoosh_index/')
HAYSTACK_CONNECTIONS = {
'default': {
'ENGINE': 'haystack.backends.whoosh_backend.WhooshEngine',
'PATH': WHOOSH_INDEX,
'INCLUDE_SPELLING': True,
},
}
ajax.js
$(function(){
$('#search').keyup(function() {
$.ajax({
type: "POST",
url: "/search/",
data: {
'search_text' : $('#search').val(),
'csrfmiddlewaretoken' : $("input[name=csrfmiddlewaretoken]").val()
},
success: searchSuccess,
dataType: 'html'
});
});
});
function searchSuccess(data, textStatus, jqXHR)
{
$('#search-results').html(data);
}
views.py
def search_titles(request):
txt = request.POST.get('search_text', '')
if txt:
articles = SearchQuerySet().autocomplete(content_auto=txt)
# if the post request is empty, return nothing
# this prevents internal server error with jquery
else:
articles = []
return render_to_response('ajax_search.html', {'articles': articles})
def articles(request):
language = 'en-gb'
session_language = 'en-gb'
if 'lang' in request.COOKIES:
language = request.COOKIES['lang']
if 'lang' in request.session:
session_language = request.session['lang']
args = {}
args.update(csrf(request))
args['articles'] = Article.objects.all()
args['language'] = language
args['session_language'] = session_language
return render_to_response('index.html', args)
We have tried rebuilding and updating index via manage.py, doesn't give any result. We've also made sure that the production and local version of the Django-Haystack and whoosh modules are the same.
Any ideas? Any kind of assistance would be appreciated ! :)

Not able to post to solr server using python and requests

This is the code I am trying to implement:-
import requests
import tornado.ioloop
import tornado.web
import tornado.autoreload
import json
class MainHandler(tornado.web.RequestHandler):
def get(self):
payload = [{"id" : "978-0641723445", "cat" : ["book","hardcover"], "name" : "The Lightning Thief", "author" : "Rick Riordan","series_t" : "Percy Jackson Olympians", "sequence_i" : 1, "genre_s" : "fantasy", "inStock" : True, "price" : 12.50, "pages_i" : 384}]
url = 'http://localhost:8983/solr/update/json'
headers = {'content-type' : 'application/json'}
# files = {'file': ('books.json', open('books.json', 'rb'))}
timeline = requests.post(url, data = json.dumps(payload), headers = headers)
self.write(timeline.text)
class QueryHandler(tornado.web.RequestHandler):
def get(self):
# timeline = requests.get('http://localhost:8983/solr/collection1/select?q=a&wt=json&indent=true')
payload = {'q' : 'a', 'wt' : 'json', 'indent' : True}
timeline = requests.get('http://localhost:8983/solr/collection1/select', params = payload)
self.write(timeline.json())
application = tornado.web.Application([
(r"/", MainHandler),
(r"/query", QueryHandler)
])
if __name__ == "__main__":
application.listen(8888)
io_loop = tornado.ioloop.IOLoop.instance()
tornado.autoreload.start(io_loop)
io_loop.start()
I am able to query the solr server on localhost:8888/query
but on localhost:8888 where I am trying to post the data, I get this response from solr:-
{
responseHeader: {
status: 0,
QTime: 46
}
}
Data is not getting posted to the solr server.
Any suggestions ??
The code doesn't contain commitWithin info in the header. The parameter is in milliseconds. Its only after a commit the data is available for search from Solr. The following may serve as an example to POST data to solr. Add the JSON header along with the commitWithin time and the data as a JSON string to the data param
requests.post("http://localhost:8983/solr/collection1/update?wt=json", headers={"Content-Type":"application/json"}, data='{"add":{ "doc":{"id" : 14, "log_type" : "debug", "log_text" : "A transaction of debug from Kimy"},"boost":1.0,"overwrite":true, "commitWithin": 1000}}')
Response :
{"responseHeader":{"status":0,"QTime":128}}