2

I have the following Bottle routing set up:

import tornado
from bottle import route, run, hook, response
import cudpred as cp

_allow_origin = '*'
_allow_methods = 'PUT, GET, POST, DELETE, OPTIONS'
_allow_headers = 'Authorization, Origin, Accept, Content-Type, X-Requested-With, X-CSRF-Token'

@hook('after_request') 
def enable_cors():
    '''Add headers to enable CORS'''

    response.headers['Access-Control-Allow-Origin'] = _allow_origin
    response.headers['Access-Control-Allow-Methods'] = _allow_methods
    response.headers['Access-Control-Allow-Headers'] = _allow_headers

@route('/', method = 'OPTIONS')
@route('/<path:path>', method = 'OPTIONS')
def options_handler(path = None):
    return

@route('/mapjson/<weekdaytopredict:int>/<hourtopredict:int>')
def mapjson(weekdaytopredict=0, hourtopredict=0):
    return cp.writeGeoJSON(weekdaytopredict, hourtopredict)


@route('/preddt/<weekdaytopredict:int>/<hourtopredict:int>/<predictionmethod:int>/<normalization:int>')
def preddt(weekdaytopredict=0, hourtopredict=0, predictionmethod =0, normalization=0):
    return cp.predicitonCalculator(weekdaytopredict, hourtopredict, predictionmethod, normalization)

run(server='tornado', host='0.0.0.0', port=2526, debug=False, reloader=True)

I'm making an API call through an HTML <form> which is connected to a JavaScript function which then calls the API:

<form onSubmit=" return updateMap(event, document.getElementById('weekday').value, document.getElementById('hour').value, document.getElementById('method').value, document.getElementById('normalization').value)">  
...</* Form />...
</form>

And the JavaScript function is:

function updateMap(e, weekday, hour, model, normalization){
    e.preventDefault();
    if (typeof(weekday) == 'undefined' || typeof(hour) == 'undefined' || weekday == '' || hour == '') {
        mapurl = 'mymap.url';
    } else if(model == 0) {
        mapurl = 'http://remote_machine:port/mapjson/' + weekday + '/' + hour
    } else {
        mapurl = 'http://remote_machine:port/preddt/' + weekday + '/' + hour + '/' + model + '/' + normalization
    }
    ...ETC...
}

My issue is, that this works for the mapjson call, but doesn't work for the preddt call. Whenever I run any request for mapjson, it returns the requested output without a problem, however, if I try to access http://remote_machine:port/preddt with parameters, I get:

XMLHttpRequest cannot load http://remote_machine:port/preddt/4/21/1/0. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://my.hosted.website.com' is therefore not allowed access. The response had HTTP status code 500.

What am I missing, how to fix this?

lte__
  • 7,175
  • 25
  • 74
  • 131

1 Answers1

0

The clue is this, at the end of the error message you posted: The response had HTTP status code 500

Your /preddt route is returning HTTP 500. Your call to cp.predicitonCalculator is likely to be the culprit.

I'm surprised that you didn't see error in your bottle console; maybe Tornado is putting them in some log file? I'd look for one.

Other easy things to try:

  • Try running it without Tornado, to see if the cause of the server error becomes more apparent, e.g. printed on the console.

  • Set bottle's debug=True. (You have it set to False right now, not sure why.)

  • Hit your server with curl, so you can examine the HTTP response, and the headers, more directly than with a browser.

  • To demonstrate that it's indeed cp.predicitonCalculator, modify your preddt function to simply return a string. You will no longer get the HTTP 500 error (and your CORS headers will work).

(Also, longer term, an after_request hook may not be the most robust way to set the CORS headers.)

Good luck.

Community
  • 1
  • 1
ron rothman
  • 17,348
  • 7
  • 41
  • 43