2012-05-23 85 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