VFPCGI Day7
出自VFP Wiki
(修訂版本間差異)
小 |
小 |
||
(1個中途的修訂版本沒有顯示) | |||
第1行: | 第1行: | ||
[[Category:VFPCGI]] | [[Category:VFPCGI]] | ||
=====VFPCGI的第七天===== | =====VFPCGI的第七天===== | ||
- | + | 上次還沒實做關於 POST 的部份,所以這次延續上次的例子,並且做了一些擴充,這樣可以讓你很清楚怎麼取 GET 與 POST 來的資料。 | |
- | + | ||
- | + | 這裡我添加了一個 form,這是用來放表單資料的,再按下 submit 之後,你會在表單的下方看到讀到的結果。這邊也利用了 text...endtext 來作為一個 template 產生器,你可以看到 text...endtext 可以很方便的同時寫 html,並且在裡面嵌入變數(用<<與>>把變數括起來)。 | |
- | + | ||
- | + | ||
- | + | ||
- | |||
- | |||
- | |||
- | |||
- | |||
- | |||
<pre> | <pre> | ||
* | * | ||
- | * | + | * cgi05 |
* | * | ||
+ | |||
SET PROCEDURE TO cgilib | 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 | LOCAL oResponse | ||
oResponse = CREATEOBJECT( "RESPONSE" ) | oResponse = CREATEOBJECT( "RESPONSE" ) | ||
- | LOCAL cRequestMethod | + | LOCAL cRequestMethod, cInput |
- | cRequestMethod = GETENV( "REQUEST_METHOD" ) | + | cRequestMethod = UPPER( GETENV( "REQUEST_METHOD" ) ) |
- | + | cInput = "<p>REQUEST_METHOD=" + cRequestMethod + "</p>" | |
DO CASE | DO CASE | ||
CASE cRequestMethod == "GET" | CASE cRequestMethod == "GET" | ||
- | + | cInput = cInput + GETENV( "QUERY_STRING" ) | |
CASE cRequestMethod == "POST" | 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 | 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 ) | ||
</pre> | </pre> | ||
- | + | 同時,也對上次的 Response 類別作一點修正,在上次 Response 類別裡面,用來作為 cache 的 cursor,其資料欄位是 varchar(254),換言之,每次 Write 時,只能塞入 254 個字元,如果超過的話,就完蛋了。這次我把她修正為 M,也就是 Memo 型態。 | |
+ | |||
<pre> | <pre> | ||
- | + | 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 | ||
</pre> | </pre> | ||
- | + | 同樣的,新增 cgi05 以後,將她設置為主程式,重新編譯之後,再丟到對應路徑即可。 | |
- | + |
在2006年11月22日 (三) 14:59的最新修訂版本
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 以後,將她設置為主程式,重新編譯之後,再丟到對應路徑即可。