Monday, 8 October 2007

Provide JSON Service in CGI Mode by Python

上一篇中说到,Abyss Web Server提供了对Python的CGI模式的支持。具体的配置比较简单,只需指定Python解析器的位置,绑定py文件即可。详见这里

作为第一个Python Web应用,毫无疑问地,从简单的hello.py开始。

#! /usr/bin/env python

import cgi

if (__name__=='__main__'):

print "Content-Type: text/html" # HTML is following
print # blank line, end of headers

print "<TITLE>Python CGI Script</TITLE>"

print "<H1>Python CGI Script</H1>"
print "Hello, world!"

呵呵,真够简单的。接下来,该玩点流行的玩意了,于是就试了一下通过Ajax,发送和接受JSON数据。

客户端实际的页面,和Python没啥关系。采用了mootools提供的Ajax和JSON函数。源码如下:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<title>JSON Ajax Demo</title>
<script src='mootools.remote.js' type="text/javascript"></script>
<script language="JavaScript" type="text/javascript">
<!--
var jStatusServiceUrl = './jsonService.py';

function getLength() {
var keystring = $('keystring').value;

var uidString = Json.toString({requeststring: keystring});

new Ajax(jStatusServiceUrl, {
postBody: uidString,

onComplete: function(jsonResult) {
var jsonObj = Json.evaluate(jsonResult);

if( jsonObj.status == 'OKAY' ) {
$('answer').setHTML( jsonObj.length );
}
else {
$('answer').setHTML( "connection error." );
}

}
}).request();
}
//-->
</script>
</head>

<body>
<form method=post action="">
Type a string: 
<input type="text" name="keystring" id="keystring"><br><br>
<div>
How long is the string
<input type="button" value="?" onclick="getLength()">
</div>
<div>Answer: <span id="answer"></span></div>
</form>
</body>
</html>

这个页面的意思是,用户输入一个字符串,发送给jsonService.py,然后将返回的字符串长度,显示出来。数据传送格式,JSON;数据传送方式,Ajax POST。

在最初的试验中,是采用GET方式向jsonService.py发数据。Python的CGI module能够很好地完成任务。当尝试使用POST方式传数据的时候,发现CGI module抓不到POST数据。正常的通过FORM发送的POST数据,却是正常的。没办法,只好拿起剪刀和浆糊,自己DIY了。顺便简单地封装一下,就有了jsonCgiAdapter.py,一个Python JSON CGI适配器。其源码如下:

#!/usr/bin/env python

import sys, os
import cjson

def getJsonData():
fin = sys.stdin
env = os.environ

try:
contentLen = int( env['CONTENT_LENGTH'] )
data = fin.read( contentLen )
return cjson.decode( data )
except Exception, e:
return ""

def sendJsonData( dataObject ):
fout = sys.stdout

resultData = cjson.encode( dataObject )

response = "Content-Type: text/plain\n"
response += "Content-Length: %d\n\n" % len(resultData)
response += resultData

if sys.platform == "win32":
try:
import msvcrt
msvcrt.setmode(fout.fileno(), os.O_BINARY)
except:
pass

# put out the response
fout.write(response)
fout.flush()

jsonCgiAdapter.py使用了cjson模块,进行JSON数据解析,提供了两个函数,用于CGI模式下,完成接受、发送JSON数据。这样,jsonService.py就写成了这样:

#!/usr/bin/env python

from jsonCgiAdapter import getJsonData, sendJsonData

def getStringLength( jData ):
jStatus = { "status" : "ERROR" }

if isinstance(jData, dict) and jData.has_key( "requeststring" ) :
jStatus[ "length" ] = len( jData["requeststring"] )
jStatus[ "status" ] = "OKAY"

return jStatus

if (__name__=='__main__'):

jData = getJsonData()

currentStatus = getStringLength( jData )

sendJsonData( currentStatus )

输入abc123,返回6。Down,一个简单的Python版JSON Service程序完成。如果再添点料,加点酱油和香醋,...。

0 Comments:

Post a Comment

<< Home