2012-05-23 87 views
8

我已经安装了Apache2并且可以运行Python。将JSON发布到Python CGI

虽然我有问题。我有两页。

一个Python的页面和其它的HTML页面用jQuery

是否有人可以告诉我怎样才能让我的AJAX后才能正常工作。

<html> 
<head> 

</head> 
<body> 
<script> 
    $(function() 
    { 
     alert('Im going to start processing'); 

     $.ajax({ 
      url: "saveList.py", 
      type: "post", 
      data: {'param':{"hello":"world"}}, 
      dataType: "application/json", 
      success : function(response) 
      { 
       alert(response); 
      } 
     }); 
    }); 
</script> 
</body> 
</html> 

而Python代码

import sys 
import json 

def index(req): 
    result = {'success':'true','message':'The Command Completed Successfully'}; 

    data = sys.stdin.read(); 

    myjson = json.loads(data); 

    return str(myjson); 
+0

据推测,没有任何反应?请告诉我们你看到的问题。 –

+0

您是否发布了百分比编码的JSON或JSON字符串? – SuperSaiyan

+0

我只是想要它,所以它显示我发布的内容,所以我有一个想法,它实际上工作。目前回复“空” – TheMonkeyMan

回答

9

OK,让我们继续前进,以更新的问题。

首先,您应该传递字符串表示形式的Ajax数据属性。然后,因为你混合dataTypecontentType属性,更改dataType价值"json"

$.ajax({ 
    url: "saveList.py", 
    type: "post", 
    data: JSON.stringify({'param':{"hello":"world"}}), 
    dataType: "json", 
    success: function(response) { 
     alert(response); 
    } 
}); 

最后,修改代码位使用JSON要求的工作方式如下:

#!/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)" 

其结果是,在Ajax请求的处理程序success您将收到successmessage属性的对象。

+1

他发布了一个'application/json'而不是'application/x-www-form-urlencoded'。他从stdin中读取的方式是正确的(IMO)。我想问题在别处。 – SuperSaiyan

+0

@Thrustmaster你在说什么? * standard * Ajax请求的默认contentType是exaclty'application/x-www-form-urlencoded'。为什么你需要使用别的东西? – VisioN

+1

OP是(从他的代码中)在HTTP主体中使用JSON字符串进行HTTP/POST。内容类型将是'application/json',需要使用'$ .ajax({contentType:“application/json”},...)'来设置。你在那里提出的建议是对JSON字符串进行网址编码,其中,IMO不是OP正在做的事情(因为他正确地从服务器端的标准输入读取了这个信息) – SuperSaiyan

0

你应该阅读JSON数据是这样的:

#!/usr/bin/env python3 

import os 
import sys 
import json 

content_len = int(os.environ["CONTENT_LENGTH"]) 

req_body = sys.stdin.read(content_len) 
my_dict = json.loads(req_body) 

用下面的代码,你可以遇到问题:

myjson = json.load(sys.stdin) 

或者少写简洁:

requ_body = sys.stdin.read() 
my_dict = json.load(requ_body) 

确实为我工作,当我的cgi脚本在apache服务器上时,但你不能指望一般的工作 - 就像我发现cgi脚本在另一台服务器上时一样。按照CGI规范:

RFC 3875     CGI Version 1.1     October 2004 


4.2. Request Message-Body 

    Request data is accessed by the script in a system-defined method; 
    unless defined otherwise, this will be by reading the 'standard 
    input' file descriptor or file handle. 

     Request-Data = [ request-body ] [ extension-data ] 
     request-body = <CONTENT_LENGTH>OCTET 
     extension-data = *OCTET 

    A request-body is supplied with the request if the CONTENT_LENGTH is 
    not NULL. The server MUST make at least that many bytes available 
    for the script to read. The server MAY signal an end-of-file 
    condition after CONTENT_LENGTH bytes have been read or it MAY supply 
    extension data. Therefore, the script MUST NOT attempt to read more 
    than CONTENT_LENGTH bytes, even if more data is available. However, 
    it is not obliged to read any of the data. 

重点线是:

脚本不能试图了解更多 比CONTENT_LENGTH字节,即使更多的数据是可用的。

显然,apache请求正文发送到CGI脚本,这会导致sys.stdin.read()返回之后立即发送一个EOF信号给CGI脚本。但根据cgi规范,服务器不需要在请求正文后发送eof信号,并且我发现我的cgi脚本挂在sys.stdin.read()上 - 当我的脚本位于另一个服务器上时,最终导致超时错误。

因此,为了在JSON数据在一般情况下阅读,你应该这样做:

content_len = int(os.environ["CONTENT_LENGTH"]) 

req_body = sys.stdin.read(content_len) 
my_dict = json.loads(req_body) 

服务器设置了CGI脚本,其中包含头信息,一堆的环境变量,其中一个是CONTENT_LENGTH。

这是一个失败的卷曲请求是什么样子,当我用myjson = json.load(sys.stdin)

-v  verbose output 
-H  specify one header 
--data implicitly specifies a POST request 

Note that curl automatically calculates a Content-Length header 
for you. 

~$ curl -v \ 
> -H 'Content-Type: application/json' \ 
> --data '{"a": 1, "b": 2}' \ 
> http://localhost:65451/cgi-bin/1.py 

* Trying ::1... 
* TCP_NODELAY set 
* Connection failed 
* connect to ::1 port 65451 failed: Connection refused 
* Trying 127.0.0.1... 
* TCP_NODELAY set 
* Connected to localhost (127.0.0.1) port 65451 (#0) 
> POST /cgi-bin/1.py HTTP/1.1 
> Host: localhost:65451 
> User-Agent: curl/7.58.0 
> Accept: */* 
> Content-Type: application/json 
> Content-Length: 16 
> 
* upload completely sent off: 16 out of 16 bytes 

=== hung here for about 5 seconds ==== 

< HTTP/1.1 504 Gateway Time-out 
< Date: Thu, 08 Mar 2018 17:53:30 GMT 
< Content-Type: text/html 
< Server: inets/6.4.5 
* no chunk, no close, no size. Assume close to signal end 
< 
* Closing connection 0