CherryPy-クイックガイド

CherryPyはPythonのWebフレームワークであり、Python開発者にHTTPプロトコルへの使いやすいインターフェースを提供します。Webアプリケーションライブラリとも呼ばれます。

CherryPyは、動的言語としてPythonの長所を使用して、HTTPプロトコルをモデル化してAPIにバインドします。これはPython用の最も古いWebフレームワークの1つであり、クリーンなインターフェースと信頼性の高いプラットフォームを提供します。

CherryPyの歴史

Remi Delonは、2002年6月下旬にCherryPyの最初のバージョンをリリースしました。これは、成功したPythonWebライブラリの出発点でした。Remiは、Webアプリケーション開発の最も優れた代替手段の1つとしてPythonを信頼しているフランスのハッカーです。

レミによって開発されたプロジェクトは、アプローチに興味を持った多くの開発者を魅了しました。このアプローチには、次の機能が含まれていました-

  • CherryPyは、model-view-controllerパターンに近かった。

  • CherryPyクラスは、CherryPyエンジンによって処理およびコンパイルされ、完全なアプリケーションと独自の組み込みWebサーバーを組み込んだ自己完結型のPythonモジュールを生成する必要があります。

  • CherryPyは、URLとそのクエリ文字列をPythonメソッド呼び出しにマップできます。

http://somehost.net/echo?message=hello would map to echo(message='hello')

CherryPyプロジェクトでの2年間の開発中に、コミュニティによってサポートされ、Remiはいくつかの改善されたバージョンをリリースしました。

2004年6月、プロジェクトの将来と、同じアーキテクチャで継続する必要があるかどうかについての議論が始まりました。その後、数人のプロジェクト常連によるブレーンストーミングとディスカッションにより、オブジェクト公開エンジンとフィルターの概念が生まれ、すぐにCherryPy2のコア部分になりました。その後、2004年10月に、CherryPy 2alphaの最初のバージョンが概念実証としてリリースされました。これらのコアアイデア。CherryPy2.0は大成功でした。ただし、その設計はまだ改善可能であり、リファクタリングが必要であることが認識されました。

フィードバックに基づいて話し合った後、CherryPyのAPIをさらに変更してエレガンスを向上させ、2005年10月にCherryPy 2.1.0をリリースしました。さまざまな変更を加えた後、チームは2006年4月にCherryPy2.2.0をリリースしました。

CherryPyの強み

CherryPyの以下の特徴がその強みと考えられています-

シンプルさ

CherryPyでプロジェクトを開発することは、Pythonの規則とインデントに従って開発された数行のコードを使用する単純なタスクです。

CherryPyも非常にモジュール化されています。主要コンポーネントは正しいロジックコンセプトで適切に管理されており、親クラスは子クラスに拡張できます。

CherryPyはPythonのすべての機能を活用しています。また、ワールドクラスのアプリケーションを開発するために必要な強力な拡張ポイントであるツールとプラグインも提供します。

オープンソース

CherryPyはオープンソースのPythonWebフレームワーク(オープンソースのBSDライセンスの下でライセンス供与)です。つまり、このフレームワークはゼロコストで商業的に使用できます。

コミュニティヘルプ

さまざまな種類の質問と回答を完全にサポートする献身的なコミュニティがあります。コミュニティは、初心者レベルから上級レベルまで、開発者に完全な支援を提供しようとします。

展開

アプリケーションをデプロイするための費用効果の高い方法があります。CherryPyには、アプリケーションをホストするための独自の本番用HTTPサーバーが含まれています。CherryPyは、WSGI準拠のゲートウェイにもデプロイできます。

CherryPyは、ほとんどのオープンソースプロジェクトと同様のパッケージで提供され、次のようにさまざまな方法でダウンロードおよびインストールできます。

  • Tarballの使用
  • easy_installを使用する
  • Subversionの使用

要件

CherryPyフレームワークをインストールするための基本的な要件は次のとおりです。

  • バージョン2.4以降のPython
  • CherryPy 3.0

Pythonモジュールのインストールは簡単なプロセスと見なされます。インストールには、次のコマンドの使用が含まれます。

python setup.py build
python setup.py install

Pythonのパッケージは、次のデフォルトディレクトリに保存されています-

  • UNIXまたはLinuxの場合、
/usr/local/lib/python2.4/site-packages
or
/usr/lib/python2.4/site-packages
  • Microsoft Windowsでは、
C:\Python or C:\Python2x
  • Mac OSでは、
Python:Lib:site-package

Tarballを使用したインストール

Tarballは、ファイルまたはディレクトリの圧縮アーカイブです。CherryPyフレームワークは、リリース(アルファ、ベータ、および安定版)ごとにTarballを提供します。

ライブラリの完全なソースコードが含まれています。この名前は、UNIXやその他のオペレーティングシステムで使用されているユーティリティに由来しています。

tarボールを使用してCherryPyをインストールするために従うべき手順は次のとおりです-

Step 1 −ユーザーの要件に従ってバージョンをダウンロードします。 http://download.cherrypy.org/

Step 2− Tarballがダウンロードされたディレクトリを検索し、解凍します。Linuxオペレーティングシステムの場合、次のコマンドを入力します-

tar zxvf cherrypy-x.y.z.tgz

Microsoft Windowsの場合、ユーザーは7-ZipやWinzipなどのユーティリティを使用して、グラフィカルインターフェイスを介してアーカイブを解凍できます。

Step 3 −新しく作成したディレクトリに移動し、次のコマンドを使用してCherryPyをビルドします−

python setup.py build

グローバルインストールの場合、次のコマンドを使用する必要があります-

python setup.py install

easy_installを使用したインストール

Python Enterprise Application Kit(PEAK)は、EasyInstallという名前のPythonモジュールを提供します。これにより、Pythonパッケージのデプロイが容易になります。このモジュールは、Pythonアプリケーションと製品のダウンロード、ビルド、およびデプロイの手順を簡素化します。

CherryPyをインストールする前に、EasyInstallをシステムにインストールする必要があります。

Step 1 −ez_setup.pyモジュールをからダウンロードします。 http://peak.telecommunity.com コンピューターの管理者権限を使用して実行します:pythonez_setup.py。

Step 2 − Easy Installをインストールするには、次のコマンドを使用します。

easy_install product_name

Step 3− easy_installは、Python Package Index(PyPI)を検索して、指定された製品を見つけます。PyPIは、すべてのPython製品の情報の一元化されたリポジトリです。

次のコマンドを使用して、利用可能な最新バージョンのCherryPyをデプロイします-

easy_install cherrypy

Step 4 − easy_installは、CherryPyをダウンロードし、ビルドして、Python環境にグローバルにインストールします。

Subversionを使用したインストール

次の状況では、Subversionを使用したCherryPyのインストールをお勧めします-

  • 機能が存在するか、バグが修正されており、開発中のコードでのみ使用できます。

  • 開発者がCherryPy自体に取り組んでいるとき。

  • ユーザーがバージョン管理リポジトリのメインブランチからのブランチを必要とする場合。

  • 以前のリリースのバグ修正用。

Subversioningの基本原則は、リポジトリを登録し、一連の変更を含む各バージョンを追跡することです。

Subversionを使用したCherryPyのインストールを理解するには、次の手順に従ってください-

Step 1 −プロジェクトの最新バージョンを使用するには、Subversionリポジトリにあるトランクフォルダをチェックアウトする必要があります。

Step 2 −シェルから次のコマンドを入力します−

svn co http://svn.cherrypy.org/trunk cherrypy

Step 3 −ここで、CherryPyディレクトリを作成し、完全なソースコードをそのディレクトリにダウンロードします。

インストールのテスト

Javaなどのアプリケーションと同じように、アプリケーションがシステムに正しくインストールされているかどうかを確認する必要があります。

前の章で説明した3つの方法のいずれかを選択して、CherryPyを環境にインストールしてデプロイできます。CherryPyは、次のようにPythonシェルからインポートできる必要があります-

import cherrypy

cherrypy.__version__
'3.0.0'

CherryPyがローカルシステムのPython環境にグローバルにインストールされていない場合は、PYTHONPATH環境変数を設定する必要があります。そうしないと、次のようにエラーが表示されます。

import cherrypy

Traceback (most recent call last):
File "<stdin>", line 1, in ?
ImportError: No module named cherrypy

CherryPyの動作を理解するために定義する必要のある重要なキーワードがいくつかあります。キーワードと定義は次のとおりです-

S.No キーワードと定義
1.1。

Web Server

HTTPプロトコルを扱うインターフェースです。その目標は、HTTP要求をアプリケーションサーバーに変換して、応答を取得することです。

2.2。

Application

情報を収集するソフトウェアです。

3.3。

Application server

これは、1つ以上のアプリケーションを保持するコンポーネントです。

4.4。

Web application server

これは、Webサーバーとアプリケーションサーバーの組み合わせです。

次の例は、CherryPy −のサンプルコードを示しています。

import cherrypy

class demoExample:
   def index(self):
   return "Hello World!!!"
   index.exposed = True
cherrypy.quickstart(demoExample())

コードがどのように機能するかを理解しましょう-

  • 名前の付いたパッケージ CherryPy 適切に機能するように、常に指定されたクラスにインポートされます。

  • 上記の例では、 index パラメータ「HelloWorld !!!」を返します。

  • 最後の行はWebサーバーを起動し、指定されたクラス(ここでは、demoExample)を呼び出し、デフォルトの関数インデックスに記載されている値を返します。

サンプルコードは次の出力を返します-

CherryPyには、独自のWeb(HTTP)サーバーが付属しています。そのため、CherryPyは自己完結型であり、ユーザーはライブラリを取得してから数分以内にCherryPyアプリケーションを実行できます。

ザ・ web server アプリケーションへのゲートウェイとして機能し、すべての要求と応答を追跡します。

Webサーバーを起動するには、ユーザーは次の呼び出しを行う必要があります-

cherryPy.server.quickstart()

ザ・ internal engine of CherryPy 以下の活動に責任があります-

  • 要求オブジェクトと応答オブジェクトの作成と管理。
  • CherryPyプロセスの制御と管理。

CherryPy –構成

フレームワークには、HTTPサーバーをパラメーター化できる独自の構成システムが付属しています。構成の設定は、INI形式に近い構文のテキストファイルまたは完全なPython辞書として保存できます。

CherryPyサーバーインスタンスを構成するには、開発者は設定のグローバルセクションを使用する必要があります。

global_conf = {
   'global': {
      'server.socket_host': 'localhost',
      'server.socket_port': 8080,
   },
}

application_conf = {
   '/style.css': {
      'tools.staticfile.on': True,
      'tools.staticfile.filename': os.path.join(_curdir, 'style.css'),
   }
}

This could be represented in a file like this:
[global]
server.socket_host = "localhost"
server.socket_port = 8080
[/style.css]
tools.staticfile.on = True
tools.staticfile.filename = "/full/path/to.style.css"

HTTPコンプライアンス

CherryPyはゆっくりと進化してきましたが、HTTP / 1.0をサポートするHTTP仕様のコンパイルが含まれており、後でHTTP /1.1をサポートして転送されます。

CherryPyは、仕様のすべての必須レベルと必須レベルを実装しているが、すべての必須レベルを実装しているわけではないため、HTTP /1.1に条件付きで準拠していると言われています。したがって、CherryPyはHTTP /1.1の次の機能をサポートします-

  • クライアントがHTTP / 1.1をサポートすると主張する場合、指定されたプロトコルバージョンで行われたすべての要求でヘッダーフィールドを送信する必要があります。実行されない場合、CherryPyはリクエストの処理をただちに停止します。

  • CherryPyは、すべての構成で使用されるDateヘッダーフィールドを生成します。

  • CherryPyは、クライアントのサポートにより、応答ステータスコード(100)を処理できます。

  • CherryPyの組み込みHTTPサーバーは、Connection:Keep-Aliveヘッダーを使用することにより、HTTP /1.1のデフォルトである持続的接続をサポートします。

  • CherryPyは、正しくチャンク化されたリクエストとレスポンスを処理します。

  • CherryPyは、If-Modified-SinceヘッダーとIf-Unmodified-Sinceヘッダーの2つの異なる方法でリクエストをサポートし、それに応じてリクエストに従って応答を送信します。

  • CherryPyは任意のHTTPメソッドを許可します。

  • CherryPyは、クライアントとサーバーに設定された設定の間のHTTPバージョンの組み合わせを処理します。

マルチスレッドアプリケーションサーバー

CherryPyは、マルチスレッドの概念に基づいて設計されています。開発者がCherryPy名前空間に値を取得または設定するたびに、マルチスレッド環境で実行されます。

Cherrypy.requestとcherrypy.responseはどちらもスレッドデータコンテナです。これは、実行時にどのリクエストがプロキシされるかを知ることで、アプリケーションがそれらを個別に呼び出すことを意味します。

スレッドパターンを使用するアプリケーションサーバーは、スレッドの使用が同期要件による問題の可能性を高めると見なされているため、高く評価されていません。

他の選択肢は次のとおりです。

マルチプロセスパターン

各リクエストは、独自のPythonプロセスによって処理されます。ここでは、サーバーのパフォーマンスと安定性が優れていると見なすことができます。

非同期パターン

ここでは、新しい接続を受け入れてデータをクライアントに送り返すことは、要求プロセスとは非同期に行われます。この手法は、その効率で知られています。

URLディスパッチ

CherryPyコミュニティは、より柔軟になりたいと考えており、ディスパッチャ向けの他のソリューションをいただければ幸いです。CherryPy 3は、他​​の組み込みディスパッチャーを提供し、独自のディスパッチャーを作成して使用する簡単な方法を提供します。

  • HTTPメソッドの開発に使用されるアプリケーション。(GET、POST、PUTなど)
  • URLでルートを定義するもの– Routes Dispatcher

HTTPメソッドディスパッチャ

一部のアプリケーションでは、URIは、リソース上でサーバーによって実行されるアクションから独立しています。

例えば、http://xyz.com/album/delete/10

URIには、クライアントが実行したい操作が含まれています。

デフォルトでは、CherryPyディスパッチャーは次のようにマップします-

album.delete(12)

上記のディスパッチャは正しく記述されていますが、次の方法で独立させることができます-

http://xyz.com/album/10

ユーザーは、サーバーが正確なページをどのようにディスパッチするのか疑問に思うかもしれません。この情報は、HTTPリクエスト自体によって運ばれます。クライアントからサーバーへのリクエストがある場合、CherryPyは最適なハンドラーに見えます。ハンドラーは、URIの対象となるリソースの表現です。

DELETE /album/12 HTTP/1.1

ルートディスパッチャ

ディスパッチに必要なメソッドのパラメータのリストは次のとおりです-

  • nameパラメータは、接続するルートの一意の名前です。

  • ルートはURIに一致するパターンです。

  • コントローラは、ページハンドラを含むインスタンスです。

  • Routesディスパッチャーを使用すると、URIに一致するパターンが接続され、特定のページハンドラーが関連付けられます。

それがどのように機能するかを理解するために例を見てみましょう-

import random
import string
import cherrypy

class StringMaker(object):
   @cherrypy.expose
   def index(self):
      return "Hello! How are you?"
   
   @cherrypy.expose
   def generate(self, length=9):
      return ''.join(random.sample(string.hexdigits, int(length)))
		
if __name__ == '__main__':
   cherrypy.quickstart(StringMaker ())

上記のコードの出力を取得するには、以下の手順に従ってください-

Step 1 −上記のファイルを次のように保存します tutRoutes.py

Step 2 −次のURLにアクセスしてください−

http://localhost:8080/generate?length=10

Step 3 −次の出力が表示されます−

CherryPy内では、組み込みツールがCherryPyライブラリを呼び出すための単一のインターフェースを提供します。CherryPyで定義されたツールは、次の方法で実装できます。

  • 構成設定から
  • Pythonデコレータとして、またはページハンドラの特別な_cp_config属性を介して
  • 任意の関数内から適用できるPython呼び出し可能オブジェクトとして

基本認証ツール

このツールの目的は、アプリケーションで設計されたアプリケーションに基本認証を提供することです。

引数

このツールは次の引数を使用します-

名前 デフォルト 説明
レルム 該当なし レルム値を定義する文字列。
ユーザー 該当なし 次の形式の辞書-username:passwordまたはそのような辞書を返すPython呼び出し可能関数。
暗号化 なし クライアントから返されたパスワードを暗号化し、ユーザー辞書で提供されている暗号化されたパスワードと比較するために使用されるPythoncallable。

それがどのように機能するかを理解するために例を見てみましょう-

import sha
import cherrypy

class Root:
@cherrypy.expose
def index(self):

return """
<html>
   <head></head>
   <body>
      <a href = "admin">Admin </a>
   </body>
</html>
""" 

class Admin:

@cherrypy.expose
def index(self):
return "This is a private area"

if __name__ == '__main__':
def get_users():
# 'test': 'test'
return {'test': 'b110ba61c4c0873d3101e10871082fbbfd3'}
def encrypt_pwd(token):

return sha.new(token).hexdigest()
   conf = {'/admin': {'tools.basic_auth.on': True,
      tools.basic_auth.realm': 'Website name',
      'tools.basic_auth.users': get_users,
      'tools.basic_auth.encrypt': encrypt_pwd}}
   root = Root()
root.admin = Admin()
cherrypy.quickstart(root, '/', config=conf)

ザ・ get_users関数はハードコードされた辞書を返しますが、データベースまたはその他の場所から値をフェッチします。クラスadminには、CherryPyの認証組み込みツールを利用するこの関数が含まれています。認証により、パスワードとユーザーIDが暗号化されます。

パスワードは侵入者によってエンコードおよびデコードされる可能性があるため、基本認証ツールは実際には安全ではありません。

キャッシングツール

このツールの目的は、CherryPyで生成されたコンテンツのメモリキャッシュを提供することです。

引数

このツールは次の引数を使用します-

名前 デフォルト 説明
invalid_methods ( "POST"、 "PUT"、 "DELETE") キャッシュされないHTTPメソッドの文字列のタプル。これらのメソッドは、リソースのキャッシュされたコピーも無効(削除)します。
cache_Class MemoryCache キャッシュに使用されるクラスオブジェクト

デコードツール

このツールの目的は、着信要求パラメーターをデコードすることです。

引数

このツールは次の引数を使用します-

名前 デフォルト 説明
エンコーディング なし content-typeヘッダーを探します
Default_encoding 「UTF-8」 何も提供または見つからない場合に使用されるデフォルトのエンコーディング。

それがどのように機能するかを理解するために例を見てみましょう-

import cherrypy
from cherrypy import tools

class Root:
@cherrypy.expose
def index(self):

return """ 
<html>
   <head></head>
   <body>
      <form action = "hello.html" method = "post">
         <input type = "text" name = "name" value = "" />
         <input type = ”submit” name = "submit"/>
      </form>
   </body>
</html>
"""

@cherrypy.expose
@tools.decode(encoding='ISO-88510-1')
def hello(self, name):
return "Hello %s" % (name, )
if __name__ == '__main__':
cherrypy.quickstart(Root(), '/')

上記のコードはユーザーから文字列を取得し、ユーザーを「hello.html」ページにリダイレクトします。このページでは、指定された名前で「Hello」と表示されます。

上記のコードの出力は次のとおりです-

hello.html

フルスタックアプリケーションは、コマンドまたはファイルの実行を介して新しいアプリケーションを作成する機能を提供します。

web2pyフレームワークのようなPythonアプリケーションを考えてみましょう。プロジェクト/アプリケーション全体がMVCフレームワークの観点から作成されます。同様に、CherryPyを使用すると、ユーザーは要件に応じてコードのレイアウトを設定および構成できます。

この章では、CherryPyアプリケーションを作成して実行する方法について詳しく学習します。

ファイルシステム

アプリケーションのファイルシステムを次のスクリーンショットに示します-

これがファイルシステムにあるさまざまなファイルの簡単な説明です-

  • config.py−すべてのアプリケーションには、構成ファイルとそれをロードする方法が必要です。この機能はconfig.pyで定義できます。

  • controllers.py− MVCは、ユーザーに人気のあるデザインパターンです。controllers.pyは、cherrypy.treeにマウントされるすべてのオブジェクトが実装される場所です。

  • models.py −このファイルは、一部のサービスまたは永続データの保存のためにデータベースと直接対話します。

  • server.py −このファイルは、負荷分散プロキシで適切に機能する本番環境に対応したWebサーバーと対話します。

  • Static −すべてのCSSファイルと画像ファイルが含まれます。

  • Views −特定のアプリケーションのすべてのテンプレートファイルが含まれます。

CherryPyアプリケーションを作成する手順を詳しく学びましょう。

Step 1 −アプリケーションを含む必要のあるアプリケーションを作成します。

Step 2−ディレクトリ内に、プロジェクトに対応するpythonパッケージを作成します。geditディレクトリを作成し、その中に_init_.pyファイルを含めます。

Step 3 −パッケージ内に、次の内容のcontrollers.pyファイルを含めます−

#!/usr/bin/env python

import cherrypy

class Root(object):

   def __init__(self, data):
      self.data = data

   @cherrypy.expose
   def index(self):
      return 'Hi! Welcome to your application'

def main(filename):
   data = {} # will be replaced with proper functionality later

   # configuration file
   cherrypy.config.update({
      'tools.encode.on': True, 'tools.encode.encoding': 'utf-8',
      'tools.decode.on': True,
      'tools.trailing_slash.on': True,
      'tools.staticdir.root': os.path.abspath(os.path.dirname(__file__)),
   })

   cherrypy.quickstart(Root(data), '/', {
      '/media': {
         'tools.staticdir.on': True,
         'tools.staticdir.dir': 'static'
      }
   })
	
if __name__ == '__main__':
main(sys.argv[1])

Step 4−ユーザーがフォームを介して値を入力するアプリケーションについて考えてみます。アプリケーションにindex.htmlとsubmit.htmlの2つのフォームを含めましょう。

Step 5 − In the above code for controllers, we have index(), which is a default function and loads first if a particular controller is called.

Step 6 − The implementation of the index() method can be changed in the following way −

@cherrypy.expose
   def index(self):
      tmpl = loader.load('index.html')
	 
      return tmpl.generate(title='Sample').render('html', doctype='html')

Step 7 − This will load index.html on starting the given application and direct it to the given output stream. The index.html file is as follows −

index.html

<!DOCTYPE html >
<html>
   <head>
      <title>Sample</title>
   </head>
	
   <body class = "index">
      <div id = "header">
         <h1>Sample Application</h1>
      </div>
		
      <p>Welcome!</p>
		
      <div id = "footer">
         <hr>
      </div>
		
   </body>
	
</html>

Step 8 − It is important to add a method to the Root class in controller.py if you want to create a form which accepts values such as names and titles.

@cherrypy.expose
   def submit(self, cancel = False, **value):
	
      if cherrypy.request.method == 'POST':
         if cancel:
            raise cherrypy.HTTPRedirect('/') # to cancel the action
         link = Link(**value)
         self.data[link.id] = link
         raise cherrypy.HTTPRedirect('/')
      tmp = loader.load('submit.html')
      streamValue = tmp.generate()
		
      return streamValue.render('html', doctype='html')

Step 9 − The code to be included in submit.html is as follows −

<!DOCTYPE html>
   <head>
      <title>Input the new link</title>
   </head>
	
   <body class = "submit">
      <div id = " header">
         <h1>Submit new link</h1>
      </div>
		
      <form action = "" method = "post">
         <table summary = "">
            <tr>
               <th><label for = " username">Your name:</label></th>
               <td><input type = " text" id = " username" name = " username" /></td>
            </tr>
				
            <tr>
               <th><label for = " url">Link URL:</label></th>
               <td><input type = " text" id=" url" name= " url" /></td>
            </tr>
				
            <tr>
               <th><label for = " title">Title:</label></th>
               <td><input type = " text" name = " title" /></td>
            </tr>
				
            <tr>
               <td></td>
               <td>
                  <input type = " submit" value = " Submit" />
                  <input type = " submit" name = " cancel" value = "Cancel" />
               </td>
            </tr>
				
         </table>
			
      </form>
      <div id = "footer">
      </div>
		
   </body>
	
</html>

Step 10 − You will receive the following output −

Here, the method name is defined as “POST”. It is always important to cross verify the method specified in the file. If the method includes “POST” method, the values should be rechecked in the database in appropriate fields.

If the method includes “GET” method, the values to be saved will be visible in the URL.

A web service is a set of web-based components that helps in the exchange of data between the application or systems which also includes open protocols and standards. It can be published, used and found on the web.

Web services are of various types like RWS (RESTfUL Web Service), WSDL, SOAP and many more.

REST — Representational State Transfer

A type of remote access protocol, which, transfers state from client to server which can be used to manipulate state instead of calling remote procedures.

  • Does not define any specific encoding or structure and ways of returning useful error messages.

  • Uses HTTP "verbs" to perform state transfer operations.

  • The resources are uniquely identified using URL.

  • It is not an API but instead an API transport layer.

REST maintains the nomenclature of resources on a network and provides unified mechanism to perform operations on these resources. Each resource is identified by at least one identifier. If the REST infrastructure is implemented with the base of HTTP, then these identifiers are termed as Uniform Resource Identifiers (URIs).

The following are the two common subsets of the URI set −

Subset Full form Example
URL Uniform Resource Locator http://www.gmail.com/
URN Uniform Resource Name urn:isbn:0-201-71088-9 urn:uuid:13e8cf26-2a25-11db-8693-000ae4ea7d46

Before understanding the implementation of CherryPy architecture, let’s focus on the architecture of CherryPy.

CherryPy includes the following three components −

  • cherrypy.engine − It controls process startup/teardown and event handling.

  • cherrypy.server − It configures and controls the WSGI or HTTP server.

  • cherrypy.tools − A toolbox of utilities that are orthogonal to processing an HTTP request.

REST Interface through CherryPy

RESTful web service implements each section of CherryPy architecture with the help of the following −

  • Authentication
  • Authorization
  • Structure
  • Encapsulation
  • Error Handling

Authentication

Authentication helps in validating the users with whom we are interacting. CherryPy includes tools to handle each authentication method.

def authenticate():
   if not hasattr(cherrypy.request, 'user') or cherrypy.request.user is None:
      # < Do stuff to look up your users >
		
      cherrypy.request.authorized = False # This only authenticates. 
         Authz must be handled separately.
		
      cherrypy.request.unauthorized_reasons = []
      cherrypy.request.authorization_queries = []
		
cherrypy.tools.authenticate = \
   cherrypy.Tool('before_handler', authenticate, priority=10)

The above function authenticate() will help to validate the existence of the clients or users. The built-in tools help to complete the process in a systematic way.

Authorization

Authorization helps in maintaining the sanity of the process via URI. The process also helps in morphing objects by user token leads.

def authorize_all():
   cherrypy.request.authorized = 'authorize_all'
	
cherrypy.tools.authorize_all = cherrypy.Tool('before_handler', authorize_all, priority=11)

def is_authorized():
   if not cherrypy.request.authorized:
      raise cherrypy.HTTPError("403 Forbidden",
         ','.join(cherrypy.request.unauthorized_reasons))
			
cherrypy.tools.is_authorized = cherrypy.Tool('before_handler', is_authorized, 
priority = 49)

cherrypy.config.update({
   'tools.is_authorized.on': True,
   'tools.authorize_all.on': True
})

The built-in tools of authorization help in handling the routines in a systematic way, as mentioned in the previous example.

Structure

Maintaining a structure of API helps in reducing the work load of mapping the URI of application. It is always necessary to keep API discoverable and clean. The basic structure of API for CherryPy framework should have the following −

  • Accounts and User
  • Autoresponder
  • Contact
  • File
  • Folder
  • List and field
  • Message and Batch

Encapsulation

Encapsulation helps in creating API which is lightweight, human readable and accessible to various clients. The list of items along with Creation, Retrieval, Update and Deletion requires encapsulation of API.

Error Handling

This process manages errors, if any, if API fails to execute at the particular instinct. For example, 400 is for Bad Request and 403 is for unauthorized request.

Example

Consider the following as an example for database, validation, or application errors.

import cherrypy
import json

def error_page_default(status, message, traceback, version):
   ret = {
      'status': status,
      'version': version,
      'message': [message],
      'traceback': traceback
   }
	
   return json.dumps(ret)
	
class Root:
   _cp_config = {'error_page.default': error_page_default}
	
@cherrypy.expose
   def index(self):
      raise cherrypy.HTTPError(500, "Internal Sever Error")
cherrypy.quickstart(Root())

The above code will produce the following output −

Management of API (Application Programming Interface) is easy through CherryPy because of the built-in access tools.

HTTP Methods

The list of HTTP methods which operate on the resources are as follows −

S.No HTTP Method & Operation
1.

HEAD

Retrieves the resource metadata.

2.

GET

Retrieves the resource metadata and content.

3.

POST

Requests the server to create a new resource using the data enclosed in the request body.

4.

PUT

Requests the server to replace an existing resource with the one enclosed in the request body.

5.

DELETE

Requests the server to remove the resource identified by that URI.

6.

OPTIONS

Requests the server to return details about capabilities either globally or specifically towards a resource.

Atom Publishing Protocol (APP)

APP has arisen from the Atom community as an application-level protocol on top of HTTP to allow the publishing and editing of web resources. The unit of messages between an APP server and a client is based on the Atom XML-document format.

The Atom Publishing Protocol defines a set of operations between an APP service and a user-agent using HTTP and its mechanisms and the Atom XML-document format as the unit of messages.

APP first defines a service document, which provides the user agent with the URI of the different collections served by the APP service.

Example

Let us take an example to demonstrate how APP works −

<?xml version = "1.0" encoding = "UTF-8"?>
<service xmlns = "http://purl.org/atom/app#" xmlns:atom = "http://www.w3.org/2005/Atom">
   
   <workspace>
      <collection href = "http://host/service/atompub/album/">
         <atom:title> Albums</atom:title>
         <categories fixed = "yes">
            <atom:category term = "friends" />
         </categories>
      </collection>
      
      <collection href = "http://host/service/atompub/film/">
         <atom:title>Films</atom:title>
         <accept>image/png,image/jpeg</accept>
      </collection>
   </workspace>
	
</service>

APP specifies how to perform the basic CRUD operations against a member of a collection or the collection itself by using HTTP methods as described in the following table −

Operation HTTP Method Status Code Content
Retrieve GET 200 An Atom entry representing the resource
Create POST 201 The URI of the newly created resource via the Location and Content-Location headers
Update PUT 200 An Atom entry representing the resource
Delete DELETE 200 None

The Presentation Layer ensures that the communication passing through it targets the intended recipients. CherryPy maintains the working of presentation layer by various template engines.

A template engine takes the input of the page with the help of business logic and then processes it to the final page which targets only the intended audience.

Kid — The Template Engine

Kid is a simple template engine which includes the name of the template to be processed (which is mandatory) and input of the data to be passed when the template is rendered.

On creation of the template for the first time, Kid creates a Python module which can be served as a cached version of the template.

The kid.Template function returns an instance of the template class which can be used to render the output content.

The template class provides the following set of commands −

S.No Command & Description
1.

serialize

It returns the output content as a string.

2.

generate

It returns the output content as an iterator.

3.

write

It dumps the output content into a file object.

The parameters used by these commands are as follows −

S.No Command & Description
1.

encoding

It informs how to encode the output content

2.

fragment

It is a Boolean value which tells to XML prolog or Doctype

3.

output

This type of serialization is used to render the content

Example

Let us take an example to understand how kid works −

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html xmlns:py = "http://purl.org/kid/ns#">
   <head>
      <title>${title}</title> <link rel = "stylesheet" href = "style.css" /> </head> <body> <p>${message}</p>
   </body>
</html>

The next step after saving the file is to process the template via the Kid engine.

import kid

params = {'title': 'Hello world!!', 'message': 'CherryPy.'}
t = kid.Template('helloworld.kid', **params)
print t.serialize(output='html')

Kid's Attributes

The following are the attributes of Kid −

XML-Based Templating Language

It is an XML-based language. A Kid template must be a well-formed XML document with proper naming conventions.

Kid implements attributes within the XML elements to update the underlying engine on the action to be followed for reaching the element. To avoid overlapping with other existing attributes within the XML document, Kid has introduced its own namespace.

<p py:if = "...">...</p>

Variable Substitution

Kid comes with a variable substitution scheme and a simple approach — ${variable-name}.

The variables can either be used in attributes of elements or as the text content of an element. Kid will evaluate the variable each and every time the execution takes place.

If the user needs the output of a literal string as ${something}, it can be escaped using the variable substitution by doubling the dollar sign.

Conditional Statement

For toggling different cases in the template, the following syntax is used −

<tag py:if = "expression">...</tag>

Here, tag is the name of the element, for instance DIV or SPAN.

The expression is a Python expression. If as a Boolean it evaluates to True, the element will be included in the output content or else it will not be a part of the output content.

Looping Mechanism

For looping an element in Kid, the following syntax is used −

<tag py:for = "expression">...</tag>

Here, tag is the name of the element. The expression is a Python expression, for example for value in [...].

Example

The following code shows how the looping mechanism works −

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
   <head>
      <title>${title}</title> <link rel = "stylesheet" href = "style.css" /> </head> <body> <table> <caption>A few songs</caption> <tr> <th>Artist</th> <th>Album</th> <th>Title</th> </tr> <tr py:for = "info in infos"> <td>${info['artist']}</td>
            <td>${info['album']}</td> <td>${info['song']}</td>
         </tr>
      </table>
   </body>
</html>

import kid

params = discography.retrieve_songs()
t = kid.Template('songs.kid', **params)
print t.serialize(output='html')

The output for the above code with the looping mechanism is as follows −

Till the year 2005, the pattern followed in all web applications was to manage one HTTP request per page. The navigation of one page to another page required loading the complete page. This would reduce the performance at a greater level.

Thus, there was a rise in rich client applications which used to embed AJAX, XML, and JSON with them.

AJAX

Asynchronous JavaScript and XML (AJAX) is a technique to create fast and dynamic web pages. AJAX allows web pages to be updated asynchronously by exchanging small amounts of data behind the scenes with the server. This means that it is possible to update parts of a web page, without reloading the whole page.

Google Maps, Gmail, YouTube, and Facebook are a few examples of AJAX applications.

Ajax is based on the idea of sending HTTP requests using JavaScript; more specifically AJAX relies on the XMLHttpRequest object and its API to perform those operations.

JSON

JSON is a way to carry serialized JavaScript objects in such a way that JavaScript application can evaluate them and transform them into JavaScript objects which can be manipulated later.

For instance, when the user requests the server for an album object formatted with the JSON format, the server would return the output as following −

{'description': 'This is a simple demo album for you to test', 'author': ‘xyz’}

Now the data is a JavaScript associative array and the description field can be accessed via −

data ['description'];

Applying AJAX to the Application

Consider the application which includes a folder named “media” with index.html and Jquery plugin, and a file with AJAX implementation. Let us consider the name of the file as “ajax_app.py”

ajax_app.py

import cherrypy
import webbrowser
import os
import simplejson
import sys

MEDIA_DIR = os.path.join(os.path.abspath("."), u"media")

class AjaxApp(object):
   @cherrypy.expose
   def index(self):
      return open(os.path.join(MEDIA_DIR, u'index.html'))

   @cherrypy.expose
   def submit(self, name):
      cherrypy.response.headers['Content-Type'] = 'application/json'
      return simplejson.dumps(dict(title="Hello, %s" % name))
		
config = {'/media':
   {'tools.staticdir.on': True,
   'tools.staticdir.dir': MEDIA_DIR,}
}
			
def open_page():
webbrowser.open("http://127.0.0.1:8080/")
cherrypy.engine.subscribe('start', open_page)
cherrypy.tree.mount(AjaxApp(), '/', config=config)
cherrypy.engine.start()

The class “AjaxApp” redirects to the web page of “index.html”, which is included in the media folder.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" 
   " http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
	
<html xmlns = "http://www.w3.org/1999/xhtml" lang = "en" xml:lang = "en">
   <head>
      <title>AJAX with jQuery and cherrypy</title>
      <meta http-equiv = " Content-Type" content = " text/html; charset=utf-8" />
      <script type = " text/javascript" src = " /media/jquery-1.4.2.min.js"></script>
		
      <script type = " text/javascript">
         $(function() { // When the testform is submitted... $("#formtest").submit(function() {
         
               // post the form values via AJAX...
               $.post('/submit', {name: $("#name").val()}, function(data) {
         
                  // and set the title with the result
                  $("#title").html(data['title']) ;
               });
               return false ;
            });
         });
      </script>
		
   </head>
	
   <body>
      <h1 id = "title">What's your name?</h1>
      <form id = " formtest" action = " #" method = " post">
         <p>
            <label for = " name">Name:</label>
            <input type = " text" id = "name" /> <br />
            <input type = " submit" value = " Set" />
         </p>
      </form>
   </body>
	
</html>

AJAXの関数は、<script>タグに含まれています。

出力

上記のコードは次の出力を生成します-

ユーザーが値を送信すると、AJAX機能が実装され、画面は次のようにフォームにリダイレクトされます-

この章では、CherryPyフレームワークでアプリケーションを作成する方法に焦点を当てます。

検討する PhotoblogCherryPyのデモアプリケーション用のアプリケーション。Photoblogアプリケーションは通常のブログですが、主要なテキストはテキストではなく写真になります。Photoblogアプリケーションの主な特徴は、開発者が設計と実装により集中できることです。

基本構造–エンティティの設計

エンティティは、アプリケーションの基本構造を設計します。以下は、Photoblogアプリケーションのエンティティです-

  • Film
  • Photo
  • Album

以下は、実体関連の基本的なクラス図です。

設計構造

前の章で説明したように、プロジェクトの設計構造は次のスクリーンショットのようになります-

Photoblogアプリケーションのサブディレクトリがある特定のアプリケーションについて考えてみます。サブディレクトリはPhoto、Album、Filmで、controllers.py、models.py、server.pyが含まれます。

機能的には、Photoblogアプリケーションは、従来のCRUDインターフェイス(作成、取得、更新、削除)を介してこれらのエンティティを操作するためのAPIを提供します。

データベースへの接続

ストレージモジュールには、一連の操作が含まれています。操作の1つであるデータベースとの接続。

これは完全なアプリケーションであるため、データベースとの接続はAPIに必須であり、作成、取得、更新、および削除の機能を維持するために必須です。

import dejavu

arena = dejavu.Arena()
from model import Album, Film, Photo
def connect():

conf = {'Connect': "host=localhost dbname=Photoblog user=test password=test"}
arena.add_store("main", "postgres", conf)
arena.register_all(globals())

上記のコードの領域は、基盤となるストレージマネージャーとビジネスロジックレイヤーの間のインターフェイスになります。

接続機能は、PostgreSQLRDBMSのアリーナオブジェクトにストレージマネージャーを追加します。

接続が取得されると、ビジネス要件に従ってフォームを作成し、アプリケーションの作業を完了することができます。

アプリケーションを作成する前に最も重要なことは entity mapping アプリケーションの構造を設計します。

テストは、アプリケーションがさまざまな観点から実行されるプロセスです。

  • 問題のリストを見つける
  • 期待される結果と実際の結果、出力、状態などの違いを見つけます。
  • 実装フェーズを理解します。
  • 現実的な目的に役立つアプリケーションを見つけてください。

テストの目的は、開発者に責任を負わせることではなく、ツールを提供し、特定の時点でのアプリケーションの状態を推定するための品質を向上させることです。

テストは事前に計画する必要があります。これには、テストの目的を定義し、テストケースの範囲を理解し、ビジネス要件のリストを作成し、プロジェクトのさまざまなフェーズに伴うリスクを認識する必要があります。

テストは、システムまたはアプリケーションで検証されるさまざまな側面として定義されます。以下はのリストですcommon test approaches

  • Unit testing−これは通常、開発者自身によって実行されます。これは、コードの単位が期待どおりに機能するかどうかを確認することを目的としています。

  • Usability testing−開発者は通常、システムの知識がないエンドユーザー向けのアプリケーションを作成していることを忘れることがあります。ユーザビリティテストは、製品の長所と短所を検証します。

  • Functional/Acceptance testing −ユーザビリティテストはアプリケーションまたはシステムが使用可能かどうかをチェックしますが、機能テストは指定されたすべての機能が実装されていることを確認します。

  • Load and performance testing−これは、システムが実行する負荷およびパフォーマンステストに適応できるかどうかを理解するために実行されます。これは、ハードウェアの変更、SQLクエリの最適化などにつながる可能性があります。

  • Regression testing −製品の連続リリースによって、以前の機能が損なわれないことを確認します。

  • Reliability and resilience testing −信頼性テストは、1つまたは複数のコンポーネントの内訳でシステムアプリケーションを検証するのに役立ちます。

ユニットテスト

フォトブログアプリケーションは、常にユニットテストを使用して以下をチェックします-

  • 新しい機能は正しく、期待どおりに機能します。
  • 既存の機能は、新しいコードリリースによって壊れることはありません。
  • 欠陥は修正され、修正されたままです。

Pythonには、ユニットテストへの異なるアプローチを提供する標準のユニットテストモジュールが付属しています。

単体テスト

unittestは、KentBeckとErichGammaによって開発されたJavaユニットテストパッケージであるJUnitに基づいています。ユニットテストは、定義されたデータを返すだけです。モックオブジェクトを定義できます。これらのオブジェクトを使用すると、アプリケーション全体に依存することなく、設計のインターフェイスに対してテストできます。また、他のテストを含めて、分離モードでテストを実行する方法も提供します。

次のようにダミークラスを定義しましょう-

import unittest

class DummyTest(unittest.TestCase):
def test_01_forward(self):
dummy = Dummy(right_boundary=3)
   self.assertEqual(dummy.forward(), 1)
   self.assertEqual(dummy.forward(), 2)
   self.assertEqual(dummy.forward(), 3)
   self.assertRaises(ValueError, dummy.forward)

def test_02_backward(self):
dummy = Dummy(left_boundary=-3, allow_negative=True)
   self.assertEqual(dummy.backward(), -1)
   self.assertEqual(dummy.backward(), -2)
   self.assertEqual(dummy.backward(), -3)
   self.assertRaises(ValueError, dummy.backward)

def test_03_boundaries(self):
dummy = Dummy(right_boundary=3, left_boundary=-3,allow_negative=True)
   self.assertEqual(dummy.backward(), -1)
   self.assertEqual(dummy.backward(), -2)
   self.assertEqual(dummy.forward(), -1)
   self.assertEqual(dummy.backward(), -2)
   self.assertEqual(dummy.backward(), -3)

コードの説明は次のとおりです-

  • unittestモジュールをインポートして、特定のクラスの単体テスト機能を提供する必要があります。

  • クラスは、unittestをサブクラス化して作成する必要があります。

  • 上記のコードのすべてのメソッドは、単語テストで始まります。これらのメソッドはすべて、unittestハンドラーによって呼び出されます。

  • assert / failメソッドは、例外を管理するためにテストケースによって呼び出されます。

これをテストケースを実行するための例として考えてください-

if __name__ == '__main__':
unittest.main()

テストケースを実行した結果(出力)は次のようになります。

----------------------------------------------------------------------
Ran 3 tests in 0.000s
OK

機能テスト

アプリケーションの機能が要件に従って形になり始めると、一連の機能テストにより、仕様に関するアプリケーションの正確性を検証できます。ただし、Seleniumなどのサードパーティ製品を使用する必要があるパフォーマンスを向上させるには、テストを自動化する必要があります。

CherryPyは、機能テストの作成を容易にする組み込み関数のようなヘルパークラスを提供します。

負荷テスト

作成しているアプリケーションとボリュームに関する期待によっては、アプリケーションが特定のレベルのパフォーマンスに到達するのを妨げている潜在的なボトルネックを検出するために、負荷テストとパフォーマンステストを実行する必要がある場合があります。

このセクションでは、FunkLoadパッケージに含まれていないため、パフォーマンステストまたは負荷テストの実行方法については詳しく説明しません。

FunkLoadの非常に基本的な例は次のとおりです-

from funkload.FunkLoadTestCase 
import FunkLoadTestCase

class LoadHomePage(FunkLoadTestCase):
def test_homepage(self):

server_url = self.conf_get('main', 'url')
nb_time = self.conf_getInt('test_homepage', 'nb_time')
home_page = "%s/" % server_url

for i in range(nb_time):
self.logd('Try %i' % i)
self.get(home_page, description='Get gome page')
if __name__ in ('main', '__main__'):

import unittest

unittest.main()

上記のコードの詳細な説明は次のとおりです-

  • FunkLoadがテスト中に発生したことを追跡する内部ジョブを実行できるように、テストケースはFunkLoadTestCaseクラスから継承する必要があります。

  • FunkLoadはクラス名に基づいてファイルを検索するため、クラス名は重要です。

  • 設計されたテストケースは、構成ファイルに直接アクセスできます。Get()メソッドとpost()メソッドは、応答を取得するためにサーバーに対して呼び出されるだけです。

この章では、組み込みのCherryPyHTTPサーバーを介して有効化されるCherryPyベースのアプリケーションSSLに焦点を当てます。

構成

Webアプリケーションに必要な構成設定にはさまざまなレベルがあります-

  • Web server −HTTPサーバーにリンクされた設定

  • Engine −エンジンのホスティングに関連する設定

  • Application −ユーザーが使用するアプリケーション

展開

CherryPyアプリケーションのデプロイは、必要なすべてのパッケージがPythonシステムパスから利用できる非常に簡単な方法であると考えられています。共有Webホスト環境では、Webサーバーはフロントエンドに常駐し、ホストプロバイダーがフィルタリングアクションを実行できるようにします。フロントエンドサーバーはApacheまたはlighttpd

このセクションでは、ApacheおよびlighttpdWebサーバーの背後でCherryPyアプリケーションを実行するためのいくつかのソリューションを紹介します。

cherrypy
def setup_app():

class Root:
@cherrypy.expose
def index(self):
   # Return the hostname used by CherryPy and the remote
   # caller IP address
	
return "Hello there %s from IP: %s " %
(cherrypy.request.base, cherrypy.request.remote.ip)
cherrypy.config.update({'server.socket_port': 9091,
   'environment': 'production',
   'log.screen': False,
   'show_tracebacks': False})
	
cherrypy.tree.mount(Root())
if __name__ == '__main__':

setup_app()
cherrypy.server.quickstart()
cherrypy.engine.start()

SSL

SSL (Secure Sockets Layer)CherryPyベースのアプリケーションでサポートできます。SSLサポートを有効にするには、次の要件を満たす必要があります-

  • PyOpenSSLパッケージをユーザーの環境にインストールします
  • サーバー上にSSL証明書と秘密鍵を持っている

証明書と秘密鍵の作成

証明書と秘密鍵の要件に対処しましょう-

  • まず、ユーザーは秘密鍵を必要とします-
openssl genrsa -out server.key 2048
  • このキーはパスワードで保護されていないため、保護が弱くなります。
  • 次のコマンドが発行されます-
openssl genrsa -des3 -out server.key 2048
  • プログラムにはパスフレーズが必要です。ご使用のバージョンのOpenSSLで空の文字列を指定できる場合は、そうしてください。それ以外の場合は、デフォルトのパスフレーズを入力してから、次のように生成されたキーから削除します。

openssl rsa -in server.key -out server.key
  • 証明書の作成は次のとおりです-
openssl req -new -key server.key -out server.csr
  • このプロセスでは、いくつかの詳細を入力するように求められます。これを行うには、次のコマンドを発行する必要があります-

openssl x509 -req -days 60 -in server.csr -signkey
server.key -out server.crt
  • 新しく署名された証明書は60日間有効です。

次のコードはその実装を示しています-

import cherrypy
import os, os.path

localDir = os.path.abspath(os.path.dirname(__file__))
CA = os.path.join(localDir, 'server.crt')
KEY = os.path.join(localDir, 'server.key')
def setup_server():

class Root:
@cherrypy.expose
def index(self):
   return "Hello there!"
	
cherrypy.tree.mount(Root())
if __name__ == '__main__':

setup_server()
cherrypy.config.update({'server.socket_port': 8443,
   'environment': 'production',
   'log.screen': True,
   'server.ssl_certificate': CA,
   'server.ssl_private_key': KEY})
	
cherrypy.server.quickstart()
cherrypy.engine.start()

次のステップはサーバーを起動することです。成功すると、画面に次のメッセージが表示されます-

HTTP Serving HTTPS on https://localhost:8443/