VFPCGI Day7
出自VFP Wiki
VFPCGI的第七天
上次還沒實做關於 POST 的部份,所以這次延續上次的例子,並且做了一些擴充,這樣可以讓你很清楚怎麼取 GET 與 POST 來的資料。
這裡我添加了一個 form,這是用來放表單資料的,再按下 submit 之後,你會在表單的下方看到讀到的結果。這邊也利用了 text...endtext 來作為一個 template 產生器,你可以看到 text...endtext 可以很方便的同時寫 html,並且在裡面嵌入變數(用<<與>>把變數括起來)。
*
* cgi05
*
SET PROCEDURE TO cgilib
DECLARE INTEGER GetStdHandle in Win32API integer nHandleType
declare integer ReadFile in Win32API integer hFile, string @ cBuffer,;
integer nBytes, integer @ nBytes2, integer @ nBytes3
LOCAL oResponse
oResponse = CREATEOBJECT( "RESPONSE" )
LOCAL cRequestMethod, cInput
cRequestMethod = UPPER( GETENV( "REQUEST_METHOD" ) )
cInput = "<p>REQUEST_METHOD=" + cRequestMethod + "</p>"
DO CASE
CASE cRequestMethod == "GET"
cInput = cInput + GETENV( "QUERY_STRING" )
CASE cRequestMethod == "POST"
&&lenght of input string in STDIN is in this environment variable
LOCAL lcContentLength, lnContentLength
LOCAL lnHandle
LOCAL lcInput
LOCAL lnOverlappedIO
lcContentLength = GETENV("CONTENT_LENGTH")
IF LEN( lcContentLength ) > 0 THEN
lnContentLength=VAL( lcContentLength )
ELSE
lnContentLength = 0
ENDIF
IF lnContentLength > 0 THEN
&&get the input from STDIN
lnInHandle=GetStdHandle(-10)
lcInPut=REPLICATE(' ', lnContentLength )
lnOverlappedIO=0
ReadFile(lnInHandle, @lcInPut, lnContentLength, @lnContentLength, @lnOverlappedIO)
ELSE
lcInput=''
ENDIF
cInput = cInput + lcInput
OTHERWISE
cInput = ""
ENDCASE
lcHtml = ""
TEXT TO lcHtml NOSHOW ADDITIVE TEXTMERGE
<script language="javascript">
function method_change( form )
{
switch ( form.cboMethod.value ) {
case "GET": form.method = "GET"; break;
case "POST": form.method = "POST"; break;
}
}
</script>
<form method="get" action="vfpcgi.exe">
RequestMethod: <select name="cboMethod" onChange="return method_change(this.form);">
<option value="GET" <<IIF(cRequestMethod=="GET", "selected", "")>> >GET</option>
<option value="POST" <<IIF(cRequestMethod=="POST", "selected", "")>> >POST</option>
</select><br/>
<input type="text" name="txt" value=""/>
<select name="cbo">
<option value="0" selected>0</option>
<option value="1">1</option>
<option value="2">2</option>
</select><br/>
<input type="submit" value="Submit"/>
<input type="reset" value="Reset"/>
</form>
<pre>
<<cInput>>
</pre>
ENDTEXT
oResponse.Write( lcHtml )
同時,也對上次的 Response 類別作一點修正,在上次 Response 類別裡面,用來作為 cache 的 cursor,其資料欄位是 varchar(254),換言之,每次 Write 時,只能塞入 254 個字元,如果超過的話,就完蛋了。這次我把她修正為 M,也就是 Memo 型態。
DEFINE CLASS RESPONSE as Custom bDirty = .F. bHeaderOut = .F. ADD OBJECT Headers AS collection PROCEDURE Init CREATE CURSOR outputCache ( outLine M ) ENDPROC PROCEDURE destroy IF this.bDirty == .T. this.flush() ENDIF USE IN outputCache ENDPROC PROCEDURE Write LPARAMETERS theHtml LOCAL lcOutput INSERT INTO outputCache values( theHtml ) this.bDirty = .t. RETURN ENDPROC HIDDEN PROCEDURE InternalWrite LPARAMETER lcOutput DECLARE INTEGER GetStdHandle in Win32API integer nHandleType declare integer WriteFile in Win32API integer hFile, string @ cBuffer,; integer nBytes, integer @ nBytes2, integer @ nBytes3 LOCAL lnOutHandle LOCAL lnBytesWritten LOCAL lnOverLappedIO lnOutHandle=GetStdHandle(-11) lnBytesWritten=0 lnOverLappedIO=0 WriteFile(lnOutHandle, @lcOutput, len(lcOutput), @lnBytesWritten, @lnOverLappedIO) ENDPROC PROCEDURE flushHeader LOCAL lcDefaultOutput LOCAL lcOutput LOCAL lcKey local i lcDefaultOutput="" lcOutput = "" FOR i = 1 TO this.Headers.Count lcKey = this.Headers.GetKey( i ) IF !EMPTY( lcKey ) THEN lcOutput = lcOutput + lcKey + ": " + this.Headers.Item(i) + CHR(13) + CHR(10) ENDIF NEXT IF this.Headers.getKey( "Content-type" ) == 0 THEN lcOutput = lcOutput + "Content-type: text/html"+chr(13)+chr(10) ENDIF lcOutput = lcOutput + chr(13)+chr(10) this.InternalWrite( lcDefaultOutput + lcOutput ) this.bHeaderOut = .T. ENDPROC PROCEDURE flush IF this.bDirty == .f. then RETURN ENDIF LOCAL lcAlias LOCAL lcOutput IF this.bHeaderOut == .F. THEN this.flushHeader() ENDIF lcAlias = ALIAS() SELECT outputCache GO top SCAN lcOutput = outputCache.outLine this.InternalWrite( lcOutput ) ENDSCAN SELECT( lcAlias ) ENDPROC ENDDEFINE
同樣的,新增 cgi05 以後,將她設置為主程式,重新編譯之後,再丟到對應路徑即可。