• 検索結果がありません。

Google 應用服務引擎 最新協作平台活動 衛道中學程式設計

N/A
N/A
Protected

Academic year: 2018

シェア "Google 應用服務引擎 最新協作平台活動 衛道中學程式設計"

Copied!
23
0
0

読み込み中.... (全文を見る)

全文

(1)

03

建立

Google

應用服務引擎

應用程式

(2)

04

03

02

01

05

07

06

G

o

o

g

le

在瞭解

Google

應用服務引擎(

Google App Engine

)的運作機制,也準備好開發

環境之後,就可以開始瞭解如何撰寫應用程式了。本章將介紹如何在

Google

用服務引擎環境中設定一個應用程式,接著處理用戶端的請求(

request

)及回應

response

)來完成網站應用程式的運作。最後再介紹

Google

應用服務引擎提供

webapp

開發框架(

framework

),並且使用它來開發網站應用程式。

3-1 基本的

Google

應用服務引擎應用程式

本節將會介紹如何從無到有建立一個

Google

應用服務引擎應用程式專案,這是在

Google

應用服務引擎上開發應用程式的根本,熟悉它的運作模式後,便能夠以此

為基礎繼續開發更複雜的網站。

3-1-1

∣應用程式的設定檔

一個

Google

應用服務引擎應用程式,至少要有一個

app.yaml

檔案,用來作為整

個應用程式的設定檔,開發用的伺服器及

Google

應用服務引擎線上環境都依據

app.yaml

來調整應用程式,除了在這個檔案設定應用程式環境之外,也要設定程

式要如何處理用戶端(

client

)的請求。

在上一章測試安裝環境時

app.yaml

檔案的內容為:

application: hello version: 1

runtime: python api_version: 1

handlers: - url: /

script: main.py

(3)

04

03-1

02

01

05

07

06

G

o

o

g

le

以這個設定檔的內容為例,它描述了一個基本應用程式的設定,包括:

application

屬性

:此為應用程式

ID

Application Identifier

),就上述範例將應

用程式

ID

設定為

hello

,上傳部署應用程式時,就是根據這個設定值來決定要

上傳到哪一個應用程式的空間。也就是說,在

Google

應用服務引擎上建立的

應用程式是使用何種應用程式

ID

,這個屬性就要填寫相同的

ID

version

屬性

:此表示應用程式的版本,

Google

應用服務引擎在部署應用程式

時,不同的上傳內容可以用版本作區隔,並且隨時切換上線應用程式的版本,

而且只要沒有刪除某個版本的內容,都可以透過特定的

URL

連接到特定版本

的程式。若在上傳部署時使用相同的版本,則會將同一版本中較舊的內容覆

蓋。在這個例子中,設定為

1

。值得注意的是,版本不一定要是數字,也可以

alpha

beta

這樣的字串。

runtime

屬性

:這是設定應用程式該使用何種程式語言在

Google

應用服務引擎

上運行,由於本書主要是介紹

Python

,所以,這個屬性都會設定為

python

api_version

屬性

:是用來指定使用

Google

應用服務引擎函式庫的版本,目前

最新的版本是

1.2.2

,如果將這個屬性設定為

1

,則會使用

1.*.*

版本之中最新

的版本(基本上目前都會設定為

1

,直接使用最新的版本)。

handlers

屬性

:就是用來設定應用程式要怎麼處理不同的

URL

請求。其底下

每一組設定以連字號(

-

)開頭符號區隔,接著就是設定某種形式的

URL

要對

應到哪一個

Python

檔案。以上述範例來說,當

URL

是「

/

」(根目錄)時,

就對應到

main.py

檔案去處理它。

URL

的設定也可以用正規表示式(

Regular

Expression

)的方式來設定,若將此例中的

URL

設定成「

/.*

」,則表示不論何

URL

都是交由

main.py

來處理。

在此只介紹

app.yaml

檔案裡最基本、必須要設定的部分,還沒有將所有設定的選

項全部列出,在本書後面章節中,有需要增加、調整

app.yaml

設定的部分,就會

(4)

04

03

02

01

05

07

06

G

o

o

g

le

3-1-2

∣處理

URL

script

檔案

app.yaml

裡設定了不同

URL

所對應的(

Python

script

檔案來處理請求,以一

個網站應用程式而言,「處理請求」就是根據

URL

以及用戶端送來的參數做一些

程式運算,最後再輸出結果(某些狀況可能輸出結果為空字串)給用戶端,在《第

2-3-4

節:驗證

SDK

安裝》的範例做了回應用戶端最簡單的示範:

print 'Content-Type: text/plain' print ''

print 'Hello, world'

程式碼3-2:main.py檔案內容

根據

HTTP

通訊協定的規範,輸出回應的標頭(

response headers

)是用來提示回

應內容的格式、類別或屬性等。在上述範例中輸出了一個「

Content-Type

」的回

應標頭,告訴客戶端以下的輸出內容是

text/plain

(純文字)型態。在回應標

頭後,空一行(

print ''

)之後開始輸出回應內容。這個範例輸出了一行文字

'Hello, world'

」。

回應標頭可以視情況來設定,如果沒有回應標頭,有的瀏覽器會將回應的內容看

作是

text/plain

,有的則是會以

text/html

型態來處理,所以,最好在輸出前加上

Content-Type

」回應標頭,讓所有瀏覽器處理方式一致。

如果將

main.py

的內容修改為:

print 'Content-Type: text/plain' print ''

print '<h1>Hello, world</h1>'

(5)

04

03-1

02

01

05

07

06

G

o

o

g

le

則執行此程式後,在瀏覽器執行的效果如圖

3-1

所示:

圖3-1:當Content-Type為text/plain型態時,瀏覽器處理的結果

從執行結果可以看出,瀏覽器會根據

Content-Type

的類型來處理伺服器回應的結

果。若是將

Content-Type

標頭修改為

text/html

,則會變成:

圖3-2:Content-Type為text/html時,瀏覽器處理的結果

此時,瀏覽器就會以

text/html

的型態來處理回應的內容,便會處理

<h1>

這個

(6)

04

03

02

01

05

07

06

G

o

o

g

le

其實,

Google

應用服務引擎上的應用程式,結構就是這麼簡單。只要有一個設定

檔案,其他的

Python

程式碼或是靜態檔案(請見《第

3-1-4

節:加入靜態檔案》)

就可以構成一個應用程式。接下來,將要介紹如何在專案中加入其他的

Python

script

檔案。

3-1-3

∣加入一個新的

script

現在來為

hello

這個應用程式做擴充。首先,在

hello

的資料夾裡加入一個

now.

py

的檔案,預計當

URL

/now

時,便能呼叫

now.py

這個

Python script

,以回應

現在的時間。

首先,修改

app.yaml

檔案內容,在

handlers

區段中加入一個

URL

對應規則:

handlers: - url: /

script: main.py - url: /now script: now.py

程式碼3-4:在app.yaml檔案中加入一個URL對應規則

現在這個應用程式已經設定

URL

/now

會對應到

now.py

來處理,所以,下一個步

驟就是要修改

now.py

的內容:

from datetime import datetime

now = datetime.now()

print """Content-Type: text/html

It is <b>%s</b> now.""" % now

程式碼3-5:now.py的檔案內容

這段程式碼使用到

Python

標準函式庫中的

datetime

模組,是透過

datetime.

now()

方法來取得現在的時間。在輸出結果中,用到了

Python

的多行字串(是用

(7)

04

03-1

02

01

05

07

06

G

o

o

g

le

Tip

Python在字串輸出時,可以使用%s表示字串型態變數(或是該變數可以轉換成字串型 態),如果要輸出多個變數,我們可以這樣做:

name = 'eric'

email = '[email protected]'

print 'Your name is %s, and email is %s' % (name, email)

便會依照變數提供的順序擺在適當的位置。

在啟動

hello

這個專案之後,開啟瀏覽器讀取

http://localhost:8080/now

此網址,

就可以看到

now.py

的執行結果:

圖3-3:/now的執行結果

Tip

如果要在Python中輸入中文字,除了檔案的編碼要是UTF-8之外,也要在Python檔案 (*.py)的第一行加上:

# coding: utf-8

(8)

04

03

02

01

05

07

06

G

o

o

g

le

3-1-4

∣加入靜態檔案

如果輸出的回應是一個

HTML

的頁面,很多時候會需要加入一些,如

CSS

JavaScript

或圖片影像等靜態檔案,不過,光是把靜態檔案放在同一個目錄(資料

夾)下,

Google

應用服務引擎的伺服器是找不到這些檔案。因為一個

HTML

面在敘述靜態檔案位置時,對於瀏覽器來說,這只是另一個

URL

,瀏覽器依然需

要對伺服器做

HTTP GET

請求,所以,必須要透過調整

app.yaml

裡的設定才能

存取靜態檔案。

就上述例子來說,若是打算在

/now

的輸出頁面上放一個時鐘的圖案,假設圖檔

time.png

,那麼,在

app.yaml

裡的

handlers

必須加入一組

URL

規則:

handlers: - url: /

script: main.py - url: /now script: now.py

- url: /time.png

static_files: time.png upload: time.png

程式碼3-6:在app.yaml檔案中,加入靜態檔案的設定

仍必須指定圖片的

URL

以及檔案的位置,這樣才能在

/now

的輸入裡透過

<img>

這個

HTML

標籤選到「

time.png

」這張圖片。

from datetime import datetime

print """Content-Type: text/html

It is <img src="/time.png"><b>%s</b> now.""" % datetime.now()

程式碼3-7:在now.py檔案中加入 <img> 標籤用來輸出圖片

(9)

04

03-1

02

01

05

07

06

G

o

o

g

le

圖3-4:在應用程式中使用靜態檔案

雖然這樣的設定可以存取到靜態檔案,但是,如果靜態檔案一多,而每個檔案都

必須逐一設定,就顯得十分麻煩。幸好,在

app.yaml

設定檔案中,是可以設定

「靜態檔案目錄」,如此一來,只需要將靜態檔案放在同一個設定的目錄下就可

以存取。

只要在

hello

這個專案目錄下建立一個

static

目錄,然後把靜態檔案(如:

time.png

)放在

static

目錄裡。再修改

app.yaml

檔案的設定如下:

handlers: - url: /

script: main.py - url: /now script: now.py

- url: /s

static_dir: static

程式碼3-8:在app.yaml檔案中加入靜態目錄的設定

透過以上的設定,

URL

/s

就會指到

static

資料夾,

now.py

的內容就可以修改

(10)

04

03

02

01

05

07

06

G

o

o

g

le

from datetime import datetime

print """Content-Type: text/html

It is <img src="/s/time.png"><b>%s</b> now.""" % datetime.now()

程式碼3-9:使用靜態目錄後,修改的now.py檔案內容

重新讀取

http://localhost:8080/now

後,也會有一樣的效果。即使在

static

目錄下

放置其他的檔案,也只需要在輸出的結果中修改

URL

,不必再去修改

app.yaml

檔案的設定。

在本節介紹了如何在

app.yaml

檔案中加入

URL

對應規則,以及該如何輸出純文

字或是

HTML

頁面給瀏覽器。在下一節中,將會介紹一個網站應用程式該如何處

理一般的

HTTP GET/POST

請求。

3-2 處理

HTTP

請求及回應

HTTP

通訊協定就是一連串的請求及回應,本節將要介紹如何利用

Python

標準函

式庫中的

cgi

模組來處理

HTTP

的請求及回應。

3-2-1

∣處理參數資料

雖然在上一章已經可以建立一個應用程式,而且也能夠把結果輸出到用戶端,但

是處理

HTTP

請求參數的部分,還需要借助

cgi

模組來處理。

首先,將

main.py

的內容修改為:

import cgi

query = cgi.FieldStorage()

name = query.getvalue('who', 'anonymous')

print """Content-Type: text/html

(11)

04

03-2

02

01

05

07

06

H

T

T

P

在此,利用了

cgi

模組中的

FieldStorage

物件,然後取得客戶端作

HTTP

請求

時的

who

參數,若

who

參數不存在,就以預設值

anonymous

取代,再把值儲存在

name

變數供後面的字串輸出。如果讀取網址

http://localhost:8080/

而不帶任何的參

數,看到的畫面會是:

圖3-5:未帶參數時,name變數使用預設值anonymous

因為找不到

who

參數的值,

name

變數的值就會是

anonymous

,倘若存取網址時帶

who

參數,如同

http://localhost:8080/?who=eric

,那麼看到的畫面就會是:

(12)

04

03

02

01

05

07

06

G

o

o

g

le

能夠處理

HTTP GET

請求所帶參數之後,依照同樣的原理,也可以用來處理表

單資料(通常是

HTTP POST

請求)。在

hello

專案資料夾中新增一個

register.

html

檔案,這個

HTML

檔案是用來呈現在一個表單,然後處理表單資料的

URL

先設定為

/reg

,所以,先將

app.yaml

的設定修改為:

handlers: - url: /

script: main.py

- url: /reg script: reg.py - url: /register.html

static_files: register.html upload: register.html

程式碼3-11:在app.yaml檔案中加入 /reg及 /register.html兩個URL規則

以下是

register.html

檔案的內容:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/ strict.dtd">

<html> <head>

<meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <title>註冊表單</title>

</head> <body>

<form method="post" action="/reg"> <fieldset>

<legend>註冊表單</legend> <p>

<label for="name">您的大名: </label> <input type="text" id="name" name="name"> </p>

<p>

<label for="email">您的 E-Mail: </label> <input type="text" id="email" name="email"> </p>

<p>

<input type="submit" value="送出資料"> </p>

</fieldset> </form> </body>

(13)

04

03-2

02

01

05

07

06

H

T

T

P

表單會將資料送至

/reg

,接下來就是要寫處理表單的

reg.py

檔案內容:

# coding: utf-8 -*-import cgi

form = cgi.FieldStorage() name = form.getvalue('name', '') email = form.getvalue('email', '')

print """Content-Type: text/html; charset=utf-8

<h1>您註冊的資料如下:</h1> <ul>

<li>您的大名: %s</li> <li>您的Email: %s</li> </ul>

""" % (name, email)

程式碼3-13:處理表單的reg.py檔案內容

因 為

reg.py

檔 案 會 輸 出 中 文 字, 為 了 避 免 瀏 覽 器 處 理 編 碼 錯 誤, 在 此 於

Content-Type

回 應 標 頭 後 加 上

charset=utf-8

, 提 示 瀏 覽 器 字 元 編 碼 要 使 用

UTF-8

從這個範例可以看出,透過

cgi

模組來處理

HTTP GET/POST

的參數資料是很容

易的,只要再加上操作資料庫系統的部分,很快就可以做出一個簡單的報名系

統。

3-2-2

∣利用

template

引擎輸出網頁

從上一節的範例可以看到,輸出網頁的部分是用靜態檔案的方式處理;或是在處

理回應時,產生一大串

HTML

字串之後再輸出。如果要回應的網頁很複雜,用

Python

字串的方式來處理就會變得不好維護。

Google

應用服務引擎提供了一套

template

系統,讓開發者可以把複雜的網頁寫成

檔案,然後,在需要變動數值的地方,再以特殊的語法將變數的值放入。例如,

(14)

04

03

02

01

05

07

06

G

o

o

g

le

首先,在

hello

資料夾下建立一個

result.html

檔案,作為表單處理後的輸出結

果:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/ strict.dtd">

<html> <head>

<meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <title>註冊結果</title>

</head> <body>

<h1>註冊資料如下:</h1> <ul>

<li>您的大名:{{name}}</li> <li>您的Email:{{email}}</li> </ul>

</body> </html>

程式碼3-14:result.html檔案的內容

在這個檔案中,其不同的地方就是名稱及

email

的變數,在此使用了這套

template

系統的語法「

{{}}

來輸出變數內容。為了讓處理的表單用這個檔案作為輸出,

所以

reg.py

的檔案內容必須要做一些修改:

import cgi import os

from google.appengine.ext.webapp import template

form = cgi.FieldStorage() name = form.getvalue('name', '') email = form.getvalue('email', '')

template_path = os.path.join(os.path.dirname(__file__), 'result.html')

print 'Content-Type: text/html;charset=utf-8' print ''

print template.render(template_path, {'name': name, 'email': email})

(15)

04

03-2

02

01

05

07

06

H

T

T

P

改寫後,在表單送出後所出現的執行結果:

圖3-7:用template改寫的註冊系統

使用

template

系統來輸出網頁,就可以把頁面呈現與程式運算的部分抽離,即使

頁面的版型要重新設計,也不必辛苦地修改

Python

檔案。關於

template

的用法,

將會在《第

6

章:

Template

引擎》逐一介紹。

Tip

Google應用服務引擎提供的template系統是django (http://www.djangoproject.com/)開 發框架的template系統,目前仍是django 0.96版的template系統。

3-2-3

HTTP

請求與回應標頭

除了

GET/POST

的參數資料之外,在處理一個請求時,往往還需要更多用戶端或

是請求的資料。例如,用戶端在作

HTTP

請求時,也會根據

HTTP

通訊協定送出

(16)

04

03

02

01

05

07

06

G

o

o

g

le

舉例來說,大部分的瀏覽器會送出一個

User-Agent

的標頭,告訴伺服器自己是個

什麼樣的用戶端。而這樣的標題會放在程式的

HTTP_USER_AGENT

環境變數裡。所

以,我們可以寫出一個如同下列的程式碼:

import os

def main():

ua = os.environ.get('HTTP_USER_AGENT') print """Content-Type: text/html

Your browser's User-Agent is [ <b>%s</b> ]""" % ua

if __name__ == '__main__': main()

程式碼3-16:取得User-Agent請求標頭

Tip

os.environ是 以Python的dict資 料 結 構 來 儲 存 環 境 變 數, 理 論 上, 也 可 以 使 用 os.environ['HTTP_USER_AGENT'] 來取得資料,但是,這樣的寫法可能會有問題。如果 os.environ中沒有HTTP_USER_AGENT這個key,則會產生程式錯誤。所以,通常在做這樣 的操作時,都會使用has_key作檢查:

if os.environ.has_key('HTTP_USER_AGENT'): ua = os.environ['HTTP_USER_AGENT']

或是直接使用get方法來取值,如果key不存在,只會傳回None而不會產生錯誤,而且 利用get方法還可以指定預設值,因此,一般都會建議使用get方法來取dict資料結構的 值。

ua = os.environ.get('HTTP_USER_AGENT')

或是可用:

(17)

04

03-2

02

01

05

07

06

H

T

T

P

如果以

Mac OS X

上的

Mozilla Firefox

瀏覽器來開啟,就會得到以下的畫面:

圖3-8:取得用戶端的User-Agent請求標頭

3-1

列出常見的

HTTP

請求標頭名稱、對應的環境變數名稱,以及使用的時機

與意義(完整的

HTTP

請求標頭可參考

HTTP

通訊協定的文件

http://www.w3.org/

Protocols/rfc2616/rfc2616.html

)。

請求標頭名稱 環境變數名稱 使用時間及意義

Accept HTTP_ACCEPT 用 戶 端 接 受 的 回 應 格 式,

如 t e x t / h t m l , a p p l i c a t i o n / x h t m l + x m l , a p p l i c a t i o n / xml;q=0.9,*/*;q=0.8。伺服器可以

根據這個標題來決定是否要有不同 的回應型態。

Accept-Charset HTTP_ACCEPT_CHARSET 用戶端所接受的字元編碼列表。如 Big5,utf-8;q=0.7,*;q=0.7。

Accept-Languange HTTP_ACCEPT_LANGUAGE 用 戶 端 使 用 的 語 系 列 表。 如 zh-tw,en-us;q=0.7,en;q=0.3。

(18)

04

03

02

01

05

07

06

G

o

o

g

le

請求標頭名稱 環境變數名稱 使用時間及意義

Connection HTTP_CONNECTION 用戶端使用的連接方式。如 keep-alive。

Content-Length CONTENT_LENGTH 用戶端請求時資料的長度。通常是

HTTP POST請求,時才會傳送此 標頭。

Content-Type CONTENT_TYPE 用戶端請求時,請求資料的型態。

通常是在HTTP POST請求時,才 會傳送此標頭。

Cookie HTTP_COOKIE 如果用戶端有cookie資料,則會以 此標頭將cookie資料傳送到伺服器 端。

Host HTTP_HOST 用戶端進行HTTP請求的伺服器名 稱。 例 如,http://example.com/foo/

bar的Host就是example.com。

Keep-Alive HTTP_KEEP_ALIVE 用戶端若使用keep-alive的連接方

式時的逾時秒數。如300。

Referer HTTP_REFERER 用戶端進行HTTP請求時,URI的

參考來源(是從何處取得該URI來

作為請求)。

User-Agent HTTP_USER_AGENT 用戶端的描述,通常包括瀏覽器的

名稱以及系統平台。如果要針對不 同瀏覽器而提供不同內容時,可以 參考此標頭來作決定。

表3-1:常用的HTTP請求標頭(續)

除了

HTTP

請求標頭之外,也有一些環境變數與開發網站應用程式有關:

環境變數名稱 使用時機與意義

PATH_INFO 用戶端請求的URI。如:/ 或 /now。

QUERY_STRING 用戶端作HTTP GET請求時,所帶的參數字串。

(19)

04

03-2

02

01

05

07

06

H

T

T

P

環境變數名稱 使用時機與意義

REMOTE_ADDR 用戶端作HTTP請求時的IP位址。如果用戶端透過Proxy

伺服器操作,則為Proxy伺服器的IP位址。

SERVER_NAME 伺服器的名稱。

SERVER_PORT 伺服器開放服務的連接埠號碼。

表3-2:與網站應用程式開發相關的環境變數(續)

用戶端在對伺服器作

HTTP

請求時,會根據情況送出一連串的請求標頭(

request

header

);而伺服器在回應用戶端時,也可以送出回應標頭(

response header

)來

說明回應內容,或是提示瀏覽器下一步應該做什麼事。在之前的程式碼中已經介

紹過回應標頭中

Content-Type

的用法及效果,表

3-3

列出一些常用的回應標頭。

環境變數名稱 使用時機與意義

Cache-Control 用來通知用戶端,針對這個請求的回應內容要快取的時間, 讓瀏覽器決定是否快取。

使用範例:

Cache-Control: max-age=3600

Content-Length 提示用戶端回應內容的長度,單位是byte。

使用範例:

Content-Length: 4096

Content-Type 提示用戶端回應內容的型態。

使用範例:

Content-Type: application/x-javascript

Expires 用來通知用戶端,針對這個請求的回應,會在什麼時間過

期,讓瀏覽器決定是否快取。

使用範例:

Expires: Wed, 05 Oct 2016 19:16:20 GMT

(20)

04

03

02

01

05

07

06

G

o

o

g

le

環境變數名稱 使用時機與意義

Last-Modified 用來提示用戶端,針對這個請求的回應內容,最後一次修改

的時間,讓瀏覽器決定是否快取。

使用範例:

Last-Modified: Wed, 25 Mar 2009 02:00:00 GMT

Location 告訴瀏覽器要導向哪一個網址,送出這個標頭之後,就不能

再送出其他的回應內容。

使用範例:

Location: http://www.google.com/

Set-Cookie 如果要存放一些資料在用戶端的cookie,就可以使用這個標 頭來作設定。參數以「;」隔開。

使用範例:

Set-Cookie: name=eric; gender=m

表3-3:常用的回應標頭(續)

3-2-4

∣使用

Cookie

記錄資料

HTTP

通訊協定中,伺服器端如果有資料要儲存在用戶端,可以利用

cookie

制來儲存,伺服器只要加上

Set-Cookie

回應標頭,遵守

HTTP

通訊協定的用戶端

就會將

cookie

值儲存,在下一次對伺服器作請求時,就會加上

Cookie

這個請求

標題傳送到伺服器端。

Tip

很多網站的身分確認機制都會利用cookie來儲存身分識別的資料,如果有安全性的顧慮, 可以對cookie加上過期時間以及限制使用網域。詳情可以參考維基百科的介紹:

http://en.wikipedia.org/wiki/HTTP_cookie

不過,知名的XSS(Cross-Site Scripting)攻擊手法就是利用cookie來危害網站安全, 因此,在使用cookie時,還是要十分小心。

(21)

04

03-2

02

01

05

07

06

H

T

T

P

在用戶端的

cookie

中加入一個

counter

參數,用來計算同一個用戶端做了多少次

請求。

# coding: utf-8 -*-import os

def main():

cookie = os.environ.get('HTTP_COOKIE') counter = 0

if cookie: # 如果有 cookie,看看裡面是不是已經有 counter 值 pos = cookie.find('counter')

if pos != -1:

counter_param = cookie[pos:].split(';')[0] counter = int(counter_param.split('=')[1])

counter = counter + 1

# 送出新的 counter 值到用戶端的 cookie print """Set-Cookie: counter=%d Content-Type: text/html; charset=utf-8

您已經瀏覽了 <b>%d</b> 次""" % (counter, counter)

if __name__ == '__main__': main()

程式碼3-17:利用cookie做成簡單的訪客計數器

此程式從環境變數中取得

HTTP_COOKIE

的值,觀看用戶端是否有帶

cookie

資料

到伺服器端。如果訪客是第一次瀏覽這一個

URI

,那麼

cookie

變數的值就會是

None

,而

counter

就會從

0

開始計算。

如果

cookie

值不為

None

,程式就會開始從

cookie

尋找是否有出現「

counter

」,

由 於

cookie

值 可 能 不 只 一 個 參 數,

cookie

資 料 內 容 可 能 會 是

a=b; x=123;

foo=bar

的 字 串。 如 果 找 到「

counter

」( 也 就 是

pos

不 為

-1

), 就 會 先 把 原 本

cookie

資料裡「

counter

」之前的內容刪除,再拿「以『;』作區隔」的第一筆資

料,應該會是「

counter=xxx

」,這時只要取出「

=

」右側的值,就是

counter

目前

的數字了。

(22)

04

03

02

01

05

07

06

G

o

o

g

le

(字串第

6

個字元),那麼

cookie[5:]

就會是

'x=123; foo=bar

'

的字串,此

時, 再 將 這 個 字 串 用「

cookie[5:].split(';')

分 開, 就 會 產 生

['x=123',

'foo=bar']

Python list

資料結構,

list

中的第一個元素正是要取得的字串,所

cookie[5:].split(';')[0]

就 會 是

'x=123'

。 最 後, 再 使 用

split

方 法 把

x

」及「

123

」用「

=

」隔開,就能取到

123

不過,要注意的是,因為本例的

counter

是數字型態的變數,用

split

方法拿到

的結果則是字串型態,所以,在上面的程式碼中使用

int()

來將字串型態強制轉

換為數字型態。

取得

counter

的資料後,剩下的工作就是把它加一,然後再利用回應標頭中的

Set-Cookie

counter

的資料送給用戶端儲存,下一次當用戶端對這個

URI

作請

求時,就會把

cookie

中的

counter

參數一起傳送到伺服器了。

Tip

在本例中,輸出變數時用了「%d」作為「數字型態」變數的輸出。

(23)

04

03-3

02

01

05

07

06

使

w

e

b

a

p

p

3-3 使用

webapp

開發框架

除了使用

cgi

模組來處理

HTTP

通訊協定之外,

Google

應用服務引擎提供了一個

簡單的開發框架(

framework

)-

webapp

,可供開發者使用。利用

webapp

開發框

架來撰寫

Google

應用服務引擎上的網站應用程式,許多複雜的

HTTP

通訊協定的

處理都已經有可以直接使用的函式庫或是物件。而且,只用

cgi

模組開發網站應

用程式還有許多限制(例如,

CGI

程式無法修改

HTTP

狀態代碼),使用開發框

架,對於開發者來說,是可以省下許多力氣處理繁瑣的

HTTP

通訊協定(或者說

有更高的處理彈性),專注於應用程式本身的開發。

3-3-1

∣建立應用程式

webapp

開發框架中裡有一套處理

URI

規則對應的方式,在此,我們可以建立一

webapp_hello

專案,而其中的

app.yaml

可以改為:

application: webapp_hello version: 1

runtime: python api_version: 1

handlers:

- url: /.*

script: main.py

程式碼3-18:改寫後的app.yaml部分檔案內容

因為

URL

對應的部分將交由

webapp

開發框架來處理,在此就先把

app.yaml

URL

全部對應到

main.py

,如果有靜態檔案或目錄要保留時,請注意要將這些

URL

的對應放在

/.*

之前,如下列程式碼:

handlers: - url: /s

static_dir: static - url: /robot.txt

static_files: robot.txt upload: robot.txt

- url: /.*

圖 3-3:/now 的執行結果
圖 3-5:未帶參數時,name 變數使用預設值 anonymous
圖 3-8:取得用戶端的 User-Agent 請求標頭 表 3-1 列出常見的 HTTP 請求標頭名稱、對應的環境變數名稱,以及使用的時機 與意義(完整的 HTTP 請求標頭可參考 HTTP 通訊協定的文件 http://www.w3.org/ Protocols/rfc2616/rfc2616.html) 。 請求標頭名稱 環境變數名稱 使用時間及意義 Accept HTTP_ACCEPT 用 戶 端 接 受 的 回 應 格 式, 如 text/html,application/ x h t m l +
圖 3-9:簡單的計數器程式

参照

関連したドキュメント

ZoomのHP https://zoom.us にアクセスし、画面右上の「サインアップは無料です」をクリッ

●お使いのパソコンに「Windows XP Service Pack 2」をインストールされているお客様へ‥‥. 「Windows XP Service

[r]

飼料用米・WCS 用稲・SGS

運転時の異常な過渡変化及び設計基準事故時に必要な操作は,中央制御室にて実施可

これらの実証試験等の結果を踏まえて改良を重ね、安全性評価の結果も考慮し、図 4.13 に示すプロ トタイプ タイプ B

印刷物をみた。右側を開けるのか,左側を開け

如果负脉冲在这个区域内,驱动 器将正常工作 If the negative pulse is inside this area, the driver will work properly... 如果负脉冲在这个区域内,驱动