Hi everyone I'm new with python bottle and I'm developing an API to be consumed by Angularjs. When I try to use the endpoints it shows me the next error in the browser console:
XMLHttpRequest cannot load build.my.domain.com:8001/api/ldap/authenticate. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin build.my.domain.com:8000' is therefore not allowed access.
I currently enabled the bottle CORS:
the decorator
def enable_cors(fn):
def _enable_cors(*args, **kwargs):
response.headers['Access-Control-Allow-Origin'] = '*'
response.headers['Access-Control-Allow-Methods'] = 'GET, POST, PUT, OPTIONS'
response.headers['Access-Control-Allow-Headers'] = 'Origin, Accept, Content-Type, X-Requested-With, X-CSRF-Token'
if request.method != 'OPTIONS':
# actual request; reply with the actual response
return fn(*args, **kwargs)
return _enable_cors
Even after make the call the back shows me the next log:
http://build.my.domain.com:8000
10.30.16.70 - - [05/Mar/2016 12:58:07] "OPTIONS /api/ldap/authenticate HTTP/1.1" 200 0
http://build.my.domaincom:8000
10.30.16.70 - - [05/Mar/2016 12:58:07] "OPTIONS /api/ldap/authenticate HTTP/1.1" 200 0
but I stills the errors appears
XMLHttpRequest cannot load build.my.domain.com:8001/api/ldap/authenticate. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin build.my.domain.com:8000' is therefore not allowed access.
Related
I am managing an app built by third parts in python.
I have this url dispatcher
urls += [(r'/path/objectAlpha/(.*)', objectAlphaHandler)] # this was made by third parts, it is expected to work
and this class
class objectAlphaHandler(BaseHandler):
def __init__(self, application, request, **kwargs):
super(objectAlphaHandler, self).__init__(application, request, **kwargs) # do the init of the basehandler
#gen.coroutine
def post(self, action=''):
response = {}
...
response = yield self.my_method(json_data)
...
self.write(json.dumps(response))
def my_method(self, json_data)
...
I want to check that the app correctly receives the request and returns some response.
So I try to access that url with Postman
request type:
POST
URL:
http://<machine_ip>:<machine_port>/path/objectAlpha/
I get this error from Postman response box
Parse Error: The server returned a malformed response
and when I click on "view in console" I see
POST http://machine_ip>:<machine_port>/path/objectAlpha/
Error: Parse Error: Expected HTTP/
Request Headers
Content-Type: application/json
User-Agent: PostmanRuntime/7.28.4
Accept: */*
Postman-Token: d644d7dd-699b-4d77-b32f-46a575ae31fc
Host: xx.xxx.x.xx:22
Accept-Encoding: gzip, deflate, br
Connection: keep-alive
Request Body
What does Error: Parse Error: Expected HTTP/ mean?
I checked my app logs but it seems it is not handling any request, even if Postman indicates that the server is returning a (malformed) response.
I also tryed to chenge the target url to:
https...
but it returns
Error: write EPROTO 28427890592840:error:100000f7:SSL routines:OPENSSL_internal:WRONG_VERSION_NUMBER:../../third_party/boringssl/src/ssl/tls_record.cc:242:
which I found out it indicates I should stick with HTTP
Then I tried also:
http://<machine_ip>/path/objectAlpha/
and
<machine_ip>/path/objectAlpha/
which generically return:
Error: connect ECONNREFUSED <machine_ip>:80
I also tryed to substitute line
urls += [(r'/path/objectAlpha/(.*)', objectAlphaHandler)]
with
urls += [(r'/path/objectAlpha/', objectAlphaHandler)]
and
urls += [(r'/path/objectAlpha', objectAlphaHandler)]
but none of these worked.
What is wrong? How can I fix it?
UPDATE
Apparently, according to this thread on Postman Github, the problem happens only on Postman Desktop and not on Postman on browser.
So I tryed to send the request form Postman on my browser but I get
Cloud Agent Error: Can not send requests to reserved address. Make sure address is publicly accessible or select a different agent.
because, according to this other thread,
Postman Website cannot send a request to your computer's localhost. It first needs to connect to your PC with the Postman desktop client
and even if I follow the indications in that answer
Run it [ndr. Postman desktop], then go to the Postman workspace in your browser -> send the request and it will work.
I still get the same
Error: Parse Error: Expected HTTP/
on both Postman Desktop and Postman on browser.
UPDATE
Going on debugging, I tryed to cast a curl on that URL from my terminal:
myuser#mymachine-VirtualBox:~$ curl --verbose "http://<target_machine_ip>:<target_machine_port>/path/objectAlpha"
and I got:
* Trying <target_machine_ip>:<target_machine_port>...
* Connected to <target_machine_ip> (<target_machine_ip>) port <target_machine_port> (#0)
> GET /orkpos5/receipt HTTP/1.1
> Host: <target_machine_ip>:<target_machine_port>
> User-Agent: curl/7.74.0
> Accept: */*
>
* Received HTTP/0.9 when not allowed
* Closing connection 0
curl: (1) Received HTTP/0.9 when not allowed
SOLVED
Since the exposed API has been built by third parts for internal use, it is not exposed to the public.
I did not know that, so in the request URL I had put the well-known port number for HTTP requests, the number 22 (see the list of well-known port numbers.).
To solve the problem, in the request URL, I changed the <target_machine_port> to the port on which the API is actually exposed.
I'am using default cherrypy logger.
I have log every access request to my server. For GET request i have full info, like
127.0.0.1 - - [06/Jul/2021:16:10:28] "GET /test/?contract_id=228322 HTTP/1.0" 200 33
But for POST request i can't log query params or body.
127.0.0.1 - - [06/Jul/2021:13:21:03] "POST /test HTTP/1.0" 201 169
So how can i log POST query's body?
You can create tool like
def response_logging():
cherrypy.log.access_log.info(
'[{time}] {ip} "{user_agent}" {request_line} "{query_params}" "{body}" "{status}" {response}'.format(
time=datetime.now().strftime("%d/%m/%Y:%H:%M:%S"),
ip=cherrypy.request.remote.ip,
user_agent=cherrypy.request.headers["User-Agent"],
request_line=cherrypy.request.request_line,
query_params=cherrypy.request.body.request_params or "",
body=cherrypy.request.json if hasattr(cherrypy.request, "json") else "",
status=cherrypy.response.status,
response=cherrypy.response.body
)
)
cherrypy.tools.response_logging = cherrypy.Tool('on_end_request', response_logging)
print(cherrypy.request.params) # Prints params on querystring
print(cherrypy.request.headers) # Prints received headers on request
print(cherrypy.request.body) # Prints Body received
I'm writing a simple Flask application in which I want to send some data from the front-end to the Flask app, have it perform some operations, and return new data to the front-end for display. I have made similar applications before, and by returning the POST response object, instead of render_template(), I'm able to simply return the data and do what I want with it on the front-end. However, this time I'm having problems.
I make a POST request from the Jquery in the front-end. Everything seems to work fine, I can see the data being returned in the browser console, except the page reloads before I can display the new data. It reloads to http://xxx.x.x.x:5000/?.
I can see the get request for /? in the Flask console. I'd like to know why it is doing this, and how I can get it to stop.
(I've found this difficult to research because most search engines will silently ignore any question marks in a query.)
Flask app:
import json
from flask import Flask, Response, render_template, request
from src.simple_lookup import analogy_lookup
app = Flask(__name__)
app.config['DEBUG'] = True
#app.route('/')
def hello_world():
return render_template('index.html', results=['a', 'b'])
#app.route('/get_words_simple', methods=['POST'])
def get_words_simple():
print('request.form:', request.form.keys)
data = analogy_lookup(request.form['keyword'], request.form['base'], request.form['goal'])
resp = Response(json.dumps(data), status=200, mimetype='application/json')
print('data:', data)
print('resp:', resp)
return resp
if __name__ == "__main__":
app.run()
Jquery:
$.post('get_words_simple?', data, function(json, status) {
console.log('response:', json);
if (json.hasOwnProperty('error')) {
$('.results').append('<p>' + json.error);
return;
}
var words = json.words;
$.each(words, function(i, text) {
var p = $("<p>");
p.append(text);
$('.results').append(p);
});
});
Flask console:
127.0.0.1 - - [27/Dec/2018 11:12:21] "GET / HTTP/1.1" 200 -
127.0.0.1 - - [27/Dec/2018 11:12:21] "GET /static/js/main.js HTTP/1.1" 200 -
request.form: <bound method MultiDict.keys of ImmutableMultiDict([('keyword', ''), ('base', ''), ('goal', '')])>
127.0.0.1 - - [27/Dec/2018 11:12:23] "GET /? HTTP/1.1" 200 -
127.0.0.1 - - [27/Dec/2018 11:12:23] "GET /static/js/main.js HTTP/1.1" 200 -
data: ['obtuvo', 'takata', 'stadshypotek', 'kriwet', 'shafiee', 'martorell', 'collum', '29,400', 'muteesa', 'patzek']
resp: <Response 111 bytes [200 OK]>
127.0.0.1 - - [27/Dec/2018 11:12:23] "POST /get_words_simple? HTTP/1.1" 200 -
Problem was that Bootstrap overrides type="submit" button functionality if it's in a form group. So my Jquery was doing everything right, but something about the html of the button was screwing everything up and trying to make a post request in a different way
I am running an FLASK app where I check the JWT in the index endpoint. The problem was I get 2 response when I execute this end point .
127.0.0.1 - - [06/Dec/2018 17:38:21] "GET / HTTP/1.1" 302 -
127.0.0.1 - - [06/Dec/2018 17:38:21] "GET /home HTTP/1.0" 200 -
My code is
#app.route('/')
def index():
try:
encoded_jwt=request.headers.get('jwt')
print(encoded_jwt)
secret = "-----BEGIN PUBLIC KEY----- ........"
claims = jwt.decode(encoded_jwt, secret)
print(type(claims))
import json
json_parse = json.loads(json.dumps(claims))
email = json_parse['http://wso2.org/claims/emailaddress']
print(email)
roles = json_parse['http://wso2.org/claims/role']
print(roles)
session['email'] = email
if ROLETAGOFADMIN in roles:
role="admin"
elif "" in roles:
role = "employee"
else:
role=None
session['role'] = role
if 'email' in session and (session['role'] == "admin" or session['role'] == "employee" )and request.method == "GET":
if 'lastpage' in session:
lastpage=session['lastpage']
print(lastpage)
session.pop('lastpage')
return redirect(lastpage)
else:
return redirect(url_for('home'))
else:
return "Sorry. Unfortunately You have no access."
except Exception as e:
return redirect(url_for('error'))
My Identity server is redirecting because of the first response. I couldn't find the way to fix that. I am not aware of that the error is occurred because of the try catch . Please help me.
You are using Flask's redirect to issue a redirect which is going to send a 302 response to the client with a Location header instructing the client to go to /home instead. Then the client has to issue the request to this new URL where the client finally gets the 200 response code. That is why you are seeing two requests and the 302 and 200 response codes in the server logs.
This particular line is causing the redirect:
return redirect(url_for('home'))
It seems like you expected redirect to simply render the content of /home and return that as the response with the original request to / (e.g. a single 200 response). If that's what you actually want, you could instead use render_template (or whatever you use in /home to render your content) to directly render that page. However, I would recommend keeping the redirect behavior as you have it.
I have a Flask-Restful API configured with some CORS options:
api = Api()
api.decorators=[cors.crossdomain(origin='*', headers=['accept', 'Content-Type'])]
...
api.init_app(app)
My API accepts POST requests which may fail if the data in the request is invalid:
class myAPI(Resource):
def post(self):
args = request.get_json()
if args.get('something'):
return {'message': 'Request worked, data received!',
'something': args['something']}
else:
abort(500, "Error: Data must contain a 'something' field!")
When I make a successful POST request to my API I can see that the CORS options are properly set:
...
* upload completely sent off: 81 out of 81 bytes
* HTTP 1.0, assume close after body
< HTTP/1.0 200 OK
< Content-Type: application/json
< Content-Length: 205
< Access-Control-Allow-Origin: *
< Access-Control-Allow-Methods: HEAD, GET, POST, OPTIONS
< Access-Control-Max-Age: 21600
< Access-Control-Allow-Headers: ACCEPT, CONTENT-TYPE
< Server: Werkzeug/0.9.4 Python/2.7.6
If, however, the post call in my class exits through the abort method (by purposely sending bad data to the request) then the Access-Control-* fields are all missing from the response:
* upload completely sent off: 75 out of 75 bytes
* HTTP 1.0, assume close after body
< HTTP/1.0 500 INTERNAL SERVER ERROR
< Content-Type: application/json
< Content-Length: 51
< Server: Werkzeug/0.9.4 Python/2.7.6
Is it possible to make the abort method play nice with my CORS rules, or should I create my own full-fledged response and avoid using the abort function?
When you trigger an abort, the error handler registered to the HTTP error code is automatically invoked, and the response is not actually served by your view function.
If you use the CORS middleware which is provided by Flask-Cors, instead of the decorator form, in the case of handled exceptions and aborts, the CORS headers will be injected as expected.
If an unhandled exception occurs, (E.G. there is an error in your code, and a 500 internal server error), Flask bypasses middleware, and after_request handlers are not run.
Full disclosure, I wrote Flask-Cors.