1

I'd like to send some (JSON, for now) data to a Python script and access the result. After trying and failing to do this own my own, I came across two examples here on SO. I have been able to make neither work.

pythonAjaxTest.html:

...
        <script>

            $(function(){
                $('#ajaxButton').click(function(){

                    alert("Ajaxing...");

                    $.ajax({
                        url: "ajaxTest.py", //equivalently, replace with "saveList.py"
                        type: "POST",
                        dataType: "json",
                        data: JSON.stringify({
                            "param" : { "hello" : "world" }
                        }),
                        success: function(response) {
                            alert(response.responseText);
                        }, error: function(response) {
                            alert(response.responseText);
                        }
                    }); 
                });
            });

        </script>
...

ajaxTest.py:

#!/usr/bin/env python

import sys
import json
import cgi

fs = cgi.FieldStorage()

sys.stdout.write("Content-Type: application/json")

sys.stdout.write("\n")
sys.stdout.write("\n")

result = {}
result['success'] = True
result['message'] = "The command Completed Successfully"
result['keys'] = ",".join(fs.keys())

d = {}
for k in fs.keys():
    d[k] = fs.getvalue(k)

result['data'] = d

sys.stdout.write(json.dumps(result,indent=1))
sys.stdout.write("\n")

sys.stdout.close()  

saveList.py:

#!/usr/bin/python

import sys, json

result = {'success':'true','message':'The Command Completed Successfully'};

myjson = json.load(sys.stdin)
# Do something with 'myjson' object

print 'Content-Type: application/json\n\n'
print json.dumps(result)    # or "json.dump(result, sys.stdout)"

With both of these, I get a 400 error in the console and following responseText:

<?xml version=‘1.0’ encoding ‘UTF-8’?><Error><Code>InvalidArgument</Code><Message>Invalid argument.</Message><Details>POST object expects Content-Type multipart/form-data</Details></Error>

Given that I'm using basically the exact same code as in each of the accepted answers to these two questions, I'm not sure what I'm doing wrong. Is this simply a Google Cloud issue? All my source files are together in a bucket. (1, 2.)


I'm running these scripts with a n1-standard-1 (1 vCPU, 3.75 GB memory) VM.

The desired behavior: I want to make a successful Ajax request to these Python files and have the result—some result—returned. I'm looking for exactly the behavior described by the answerers of the two questions I linked to.

Specific problem or error: The Ajax fails. The error is a 400 and the text is above.

Shortest code necessary: The code I have included is perhaps somewhat long, but I've included because I want to include exactly what was in other accepted answers. (Problem statement:) How I can make an Ajax request to Python files that work in other circumstances work on Google Cloud?


Currently working through Martijn's answer...

Randoms
  • 2,110
  • 2
  • 20
  • 31
  • Google App Engine is *not a CGI environment*. Why not pick up on the [quickstart for Python on App Engine](https://cloud.google.com/appengine/docs/standard/python/quickstart). – Martijn Pieters Jul 29 '17 at 11:28
  • You've also not included *how you are running* these scripts. I assumed that you were trying to use the App Engine, but perhaps you are using a VM or a container engine. You mentioned a bucket, but that's a *storage* solution, files in a bucket are not seen as executable code. – Martijn Pieters Jul 29 '17 at 11:42
  • @MartijnPieters I'm assuming the quickstart won't be helpful if I'm working on a VM? – Randoms Jul 29 '17 at 22:23

2 Answers2

0

It looks like your javascript code is alright, but I think you can fix up the Python code a little bit - you're using stdin/out which I haven't seen to have very good results. I'd suggest you use a library like Tornado or even the python-included simpleHttpServer.

There's an example here for Tornado on their home page: http://www.tornadoweb.org/en/stable/

And even simpler is the simpleHttpServer, here is a working sample: Reading JSON from SimpleHTTPServer Post data

Furthermore I would suggest you try running these examples locally on your home computer before the Google Cloud. It is most likely an issue with the code rather than GCP.

Good luck!

jimf
  • 4,527
  • 1
  • 16
  • 21
0

The Google App Engine does not connect your Python code via CGI. CGI examples are not going to work, no.

Instead, a different, more modern standard, the Web Server Gateway Interface is used; see the [Python Runtime Environment documentation]https://cloud.google.com/appengine/docs/standard/python/runtime):

A Python web app interacts with the App Engine web server using the WSGI protocol, so apps can use any WSGI-compatible web application framework. App Engine includes a simple web application framework, called webapp2, to make it easy to get started. For larger applications, mature third-party frameworks, such as Django, work well with App Engine.

Rather than pick up random Python scripts from around the web, start with the Quickstart examples and move from there.

Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
  • I'm running this from a VM. I'm sorry I didn't include this information initially. Are the pages you linked here still applicable? – Randoms Jul 29 '17 at 22:41
  • @Randoms: no, then this is not applicable. Do you have a web server installed on the VM? How did you configure it? This should all have been *in your question*. – Martijn Pieters Jul 30 '17 at 09:51