Drizzle¶
Name¶
drizzle-nginx-module - MySQLとDrizzleと直接対話するためのupstreamモジュール
注意
このモジュールはNGIXのソースと一緒に配布されません。 インストレーションの説明を見てください。
概要¶
http { ... upstream cluster { # simple round-robin drizzle_server 127.0.0.1:3306 dbname=test password=some_pass user=monty protocol=mysql; drizzle_server 127.0.0.1:1234 dbname=test2 password=pass user=bob protocol=drizzle; } upstream backend { drizzle_server 127.0.0.1:3306 dbname=test password=some_pass user=monty protocol=mysql; } server { location /mysql { set $my_sql 'select * from cats'; drizzle_query $my_sql; drizzle_pass backend; drizzle_connect_timeout 500ms; # default 60s drizzle_send_query_timeout 2s; # default 60s drizzle_recv_cols_timeout 1s; # default 60s drizzle_recv_rows_timeout 1s; # default 60s } ... # for connection pool monitoring location /mysql-pool-status { allow 127.0.0.1; deny all; drizzle_status; } } }
説明¶
これは libdrizzle をブロッキング無しおよびストリーミングの方法でNGINXに統合するNGINX upstreamモジュールです。
基本的にNGINXのためにMySQL、Drizzle およびDrizzleあるいはMySQLのプロトコルをサポートをする他のRDBMSへの内部的なアクセスの効率的かつ柔軟な方法を提供します。またそれらのRDBMSバックエンドへの直接的なRESTインタフェースを提供することもできます。
このモジュールは人間が読むことができる出力を生成しませんが、私たちが設計したResty-DBD-Stream (RDS) と呼ばれるバイナリ形式を生成します。通常、このモジュールと動作するには、HttpRdsJsonModule, HttpRdsCsvModuleあるいは HttpLuaRdsParserのようなほかのコンポーネントを必要とするでしょう。詳細は出力フォーマット を見てください。
Keepalive 接続プール¶
このモジュールはMySQLあるいはDrizzle TCP接続のための組み込みのワーカーあたりの接続プールの仕組みを提供します。
以下は例の設定です:
upstream backend { drizzle_server 127.0.0.1:3306 dbname=test password=some_pass user=monty protocol=mysql; drizzle_keepalive max=100 mode=single overflow=reject; }
現在のところ、接続プールはプール内の動作していない接続を割り当てるために単純なFIFOアルゴリズムを使用します。つまり、最も最近に(成功した)使用された接続が次に最初に使われるでしょう。そして、新しい動作をしていない接続は、プールが既に一杯出会ってもプール内の最も古い動作していない接続を常に置き換えるでしょう。
詳細は drizzle_keepalive_ directive を見てください。
Last Insert ID¶
LAST_INSERT_ID を取得したい場合は、SQL挿入クエリを実行した場合に自動的にngx_drizzleが返しています。以下のサンプルの nginx.conf
断片を考えてみてください:
location /test { echo_location /mysql "drop table if exists foo"; echo; echo_location /mysql "create table foo (id serial not null, primary key (id), val real);"; echo; echo_location /mysql "insert into foo (val) values (3.1415926);"; echo; echo_location /mysql "select * from foo;"; echo; } location /mysql { drizzle_pass backend; drizzle_module_header off; drizzle_query $query_string; rds_json on; }
GET /test
は以下の出力を与えます:
{"errcode":0} {"errcode":0} {"errcode":0,"insert_id":1,"affected_rows":1} [{"id":1,"val":3.1415926}]
(3つ目のJSO応答の中のaffected_rows
と) insert_id
が見えるでしょう。
ディレクティブ¶
drizzle_server¶
構文 drizzle_server <host> user=<user> password=<pass> dbname=<database>
構文 drizzle_server <host>:<port> user=<user> password=<pass> dbname=<database> protocol=<protocol> charset=<charset>
デフォルト none
コンテキスト upstream
サーバの名前とパラメータを直接あり当てます。名前に関しては、任意のポート(デフォルト: 3306)と一緒にドメイン名、アドレスを使うことができます。ドメイン名が幾つかのアドレスに解決される場合は、全てが使われます。
以下のオプションがサポートされます:
user=<user>
MySQL/Drizzle user name<user>
for login.password=<pass>
Specify mysql password<pass>
for login.#
あるいのような特別な文字あるいはスペースをパスワードテキストにある場合は、シングルクォートあるいはダブルクォートのどちらかでキー-値ペア全体をクォートする必要があるでしょう。drizzle_server 127.0.0.1:3306 user=monty "password=a b#1" dbname=test protocol=mysql;
dbname=<database>
Specify default MySQL database<database>
for the connection. MySQLはSQLクエリ内のデータベース名をもつテーブル名を条件付けることで異なるデータベースに所属するテーブルを参照することができることに注意してください。protocol=<protocol>
どのプロトコル、drizzle
あるいはmysql
を使うかを指定します。デフォルトはdrizzle
です。charset=<charset>
明示的にMySQL接続のために文字セットを指定します。 このオプションを空では無い値に設定すると、mysql接続が確立したすぐ後にこのモジュールはset names '<charset>'
クエリを送信するでしょう。MySQL接続のデフォルトの文字エンコーディングが既に期待しているものであれば、このオプションを設定すると特別な実行時のコストがあるためこのオプションを設定する必要はありません。以下は小さな例です:drizzle_server foo.bar.com:3306 user=monty password=some_pass dbname=test protocol=mysql charset=utf8;
注意
mysqlサーバの場合、
utf8
は有効なエンコーディング名ですが、"utf-8"はそうではありません。
drizzle_keepalive¶
構文 drizzle_keepalive max=<size> mode=<mode>
デフォルト max=0 mode=single
コンテキスト upstream
MySQL/Drizzle 接続のためにkeep-alive接続を設定します。
以下のオプションがサポートされます:
max=<num>
現在のupstreamブロックのための接続プールの容量を指定します。<num>の値は非ゼロでなければなりません。0
に設定すると、事実上接続プールを無効にします。このオプションはデフォルトは0
です。mode=<mode>
これは2つの値、single
とmulti
をサポートします。single
モードはプールが現在のupstreamブロックの様々なdrizzleサーバを区別しないが、multi
モードはプールが個々のサーバホスト名とポートを持つ接続を再利用しないかも知れないことを意味します。たとえmulti
でも、dbname
あるいはuser
パラメータの違いは静かに無視されることに注意してください。デフォルトはsingle
です。overflow=<action>
このオプションは新しいデータベース接続が要求された時に接続プールがすでに一杯の時に何をするかを指定します。reject
あるいはignore
のどちらかを指定することができます。reject
の場合は、現在のリクエストを拒否し、503 Service Unavailable
エラーページを返します。ignore
の場合、このモジュールは新しいデータベース接続を生成するでしょう。
drizzle_query¶
構文 drizzle_query <sql>
デフォルト none
コンテキスト http, server, location, location if
Drizzle/MySQL バックエンドに送信されるSQLクエリを指定します。
NGINX 変数の補完がサポートされていますが、SQLインジェクションアタックに注意しなければなりません。例えば、SQL補完の値をクォートするために set_quote_sql_str
ディレクティブを使うことができます:
location /cat { set_unescape_uri $name $arg_name; set_quote_sql_str $quoted_name $name; drizzle_query "select * from cats where name = $quoted_name"; drizzle_pass my_backend; }
drizzle_pass¶
構文 drizzle_pass <remote>
デフォルト none
コンテキスト location, location if
Phasecontent
このディレクティブは現在のlocationでクエリされるためのDrizzleあるいはMySQL upstream名を指定します。<remote>
引数は drizzle_server_directiveで定義されたどのようなupstream名で指定することができます。
動的バックエンドルーティングするように、NGINXの変数は<remote>
引数に挿入されます。例えば:
upstream moon { drizzle_server ...; } server { location /cat { set $backend 'moon'; drizzle_query ...; drizzle_pass $backend; } }
drizzle_connect_timeout¶
構文 drizzle_connect_time <time>
デフォルト 60s
コンテキスト http, server, location, location if
遠隔のDrizzleあるいはMySQLサーバへの接続のための(総)タイムアウトを指定します。
<time>
引数は、s
(秒), ms
(ミリ秒), m
(分)のような任意の時間単位を持つ数字がありえます。デフォルトの時間単位は s
, つまり"秒"です。デフォルトの設定は 60s
です。
drizzle_send_query_timeout¶
構文 drizzle_send_query_timeout <time>
デフォルト 60s
コンテキスト http, server, location, location if
SQLクエリをリモートのDrizzleあるいはMySQLサーバに送信するための(総)タイムアウトを指定します。
<time>
引数は、s
(秒), ms
(ミリ秒), m
(分)のような任意の時間単位を持つ数字がありえます。デフォルトの時間単位は s
、つまり"秒"です。デフォルトの設定は 60s
です。
drizzle_recv_cols_timeout¶
構文 drizzle_recv_cols_timeout <time>
デフォルト 60s
コンテキスト http, server, location, location if
リモートDrizzleあるいはMySQLサーバへの結果セットのカラムのメタデータを受信するための(総)タイムアウトを指定します。
<time>
引数は、s
(秒), ms
(ミリ秒), m
(分)のような任意の時間単位を持つ数字がありえます。デフォルトの時間単位は s
、つまり"秒"です。デフォルトの設定は 60s
です。
drizzle_recv_rows_timeout¶
構文 drizzle_recv_rows_timeout <time>
デフォルト 60s
コンテキスト http, server, location, location if
(もしある場合は)リモートDrizzleあるいはMySQLサーバへの結果セットのカラムの行データを受信するための(総)タイムアウトを指定します。
<time>
引数は、s
(秒), ms
(ミリ秒), m
(分)のような任意の時間単位を持つ数字がありえます。デフォルトの時間単位は s
、つまり"秒"です。デフォルトの設定は 60s
です。
drizzle_buffer_size¶
構文 drizzle_buffer_size <size>
デフォルト 4k/8k
コンテキスト http, server, location, location if
drizzle出力のためのバッファサイズを指定します。ページサイズのデフォルト(4k/8k)。バッファが大きくなればなるほど、出力プロセスはストリームではなくなるでしょう。
drizzle_module_header¶
構文 drizzle_module_header [on|off]
デフォルト on
コンテキスト http, server, location, location if
応答内のdrizzleヘッダを出力するかどうかを制御する。デフォルト on。
drizzleモジュールヘッダは以下のように見えます:
X-Resty-DBD-Module: ngx_drizzle 0.1.0
drizzle_status¶
構文 drizzle_status
デフォルト none
コンテキスト location, location if
Phasecontent
指定された場合、現在のNGINX locationは現在のNGINXワーカープロセスの仮想サーバ内の全てのdrizzle upstreamサーバのための状況レポートを出力するでしょう。
出力は以下のように見えます:
worker process: 15231 upstream backend active connections: 0 connection pool capacity: 10 overflow: reject cached connection queue: 0 free'd connection queue: 10 cached connection successfully used count: free'd connection successfully used count: 3 0 0 0 0 0 0 0 0 0 servers: 1 peers: 1 upstream backend2 active connections: 0 connection pool capacity: 0 servers: 1 peers: 1
注意
nginx.conf
内に設定した複数のNGINXワーカープロセスが無い場合は、これはグローバルな統計ではありません。
変数¶
このモジュールは以下のNGINXの変数を生成します:
$drizzle_thread_id¶
現在のSQLクエリがタイムアウトした場合には、この変数は後ろで動作しているMySQLあるいはDrizzleクエリのスレッドIDの原文の数を割り当てられるでしょう。さらにこのスレッドIDはタイムアウトクエリを中止するためにSQL kill コマンドをの中で使うことができます。
例は次のようになります:
drizzle_connect_timeout 1s; drizzle_send_query_timeout 2s; drizzle_recv_cols_timeout 1s; drizzle_recv_rows_timeout 1s; location /query { drizzle_query 'select sleep(10)'; drizzle_pass my_backend; rds_json on; more_set_headers -s 504 'X-Mysql-Tid: $drizzle_thread_id'; } location /kill { drizzle_query "kill query $arg_tid"; drizzle_pass my_backend; rds_json on; } location /main { content_by_lua ' local res = ngx.location.capture("/query") if res.status ~= ngx.HTTP_OK then local tid = res.header["X-Mysql-Tid"] if tid and tid ~= "" then ngx.location.capture("/kill", { args = {tid = tid} }) end return ngx.HTTP_INTERNAL_SERVER_ERROR; end ngx.print(res.body) ' }
ここで、headers_more, lua および HttpRdsJsonModule も使用します。SQLクエリがタイムアウトした場合は、すぐにそれを明示的にキャンセルするでしょう。一つの落とし穴としてNGINXをビルドする時にこの順番でこれらのモジュールを追加する必要があります:
そのようにして、それらの出力フィルタは逆順に動作するでしょう。つまり、まずRDSをJSONに変換し、X-Mysql-Tid
カスタムヘッダを追加し、最後にLuaモジュールを使って全体(サブリクエスト)の応答をキャプチャします。OpenResty bundle を使うことが推奨されますが、それはモジュールの構築順を自動的に保証します。
出力フォーマット¶
このモジュールは ngx_postgresのような様々なNGINXデータベースドライバモジュールで共有される形式のバイナリのクエリ結果を生成します。このデータフォーマットはResty DBD Stream
(RDS)という名前です。
webアプリの開発者であれば、もっと興味があるかも知れません。
- JSON出力を取得するにはHttpRdsJsonModule を使います。
- カンマ区切り(CSV)の出力を取得するには HttpRdsCsvModule を使います。
- RDSデータをLuaデータ構造にパースするには HttpLuaRdsParser を使います。
HTTP応答ヘッダの部分については、200 OK
ステータスコードが常に返されなければなりません。Content-Type
ヘッダは application/x-resty-dbd-stream
に設定されなければなりません。この応答を生成するドライバは X-Resty-DBD
ヘッダも設定します。例えば、このモジュールは以下の出旅行ヘッダを追加します:
X-Resty-DBD-Module: drizzle 0.1.0
0.1.0
の部分はこのモジュール自身のバージョン番号です。ですが、この X-Resty-DBD-Module
ヘッダは任意です。
以下はHTTP応答ボディフォーマットです(バージョン 0.0.3):
RDS ヘッダ部分¶
RDS ヘッダ部分は以下のフィールドからなります:
uint8_t
エンディアンタイプ (1 はビッグエンディアン、そうでなければリトルエンディアンを意味します)uint32_t
フォーマットバージョン (v1.2.3は数値で1002003を表します)uint8_t
結果タイプ (0は通常のSQL結果タイプを意味します。現在のところ固定です)uint16_t
標準エラーコードuint16_t
ドライバ固有のエラーコードuint16_t
ドライバ固有のエラー文字列長u_char
ドライバ固有のエラー文字列データuint64_t
影響を受けたデータベースの行uint64_t
insert id (if none, 0)uint16_t
行数
RDS ボディ部分¶
RDS内の column count
フィールドがゼロの場合、RDSボディ部分の全体が省略されます。
RDS ボディ部分は2つの部分、Columns_ と Rows_ からできています。
Columns¶
カラム部分は0個以上のカラムデータからできています。カラムの数は RDSヘッダ部分のcolumn count
によって決定されます。
各カラムは以下のフィールドからできています。
uint16_t
標準のカラムタイプコードとカラムリスト終端には非ゼロ値を、そうでなければゼロ。uint16_t
ドライバ固有のカラムタイプコードuint16_t
カラム名の長さu_char
カラム名のデータ
Rows¶
行部分は0個以上の行データからできていて、8ビットのゼロで終わります。
各行データは行フラグ および任意のフィールド のデータからできています。
行フラグ¶
uint8_t
有効行(1は有効を意味し、0は行リストの終端を意味します)
フィールドデータ¶
フィールドデータは0個以上のデータのフィールドからできています。フィールドの数はRDSヘッダPart_で指定されるcolumn number
によって事前に決定されます。
uint32_t
フィールド長 ((uint32_t) -1 は NULL を表します)u_char
field data in textual representation), is empty (0) if field length == (uint32_t) -1
RDS バッファの制限¶
NGINXの出力リンクレベルでは、以下のコンポーネントが1つの ngx_buf_t
struct に配置されるべきです:
- ヘッダ
- 各カラムとカラムリストの終端
- 各行の有効フラグバイトと行リストの終端
- each field in each row (if any) but the field data can span multiple bufs.
ステータスコード¶
MySQLのクエリの結果のMySQLエラーコードがOKでは無い場合、テーブルが存在しない場合の 410 Gone
エラーページの場合を除いて、500エラーページがこのモジュールによって返されます。
警告¶
- 単一のupstreamブロックの中で
upstream_hash
および keepalive のような他のupstreamモジュールをこのモジュールと一緒に使われるべきではありません。 - server <|HttpUpstreamModule|#server> のようなディレクティブがdrizzle_server_ と混成されるべきではありません。
- サーバエントリを定義するためにdrizzle_server_ を使用しないupstramバックエンドは drizzle_pass_ ディレクティブの中で使われるべきではありません。
トラブルシューティグ¶
以下のエラーメッセージを
error.log
の中で見つけた場合:failed to connect: 15: drizzle_state_handshake_result_read: old insecure authentication mechanism not supported in upstream, ...
then you may checkout if your MySQL is too old (at least 5.x is required) or your mysql config file explicitly forces the use of old authentication method (you should remove the
old-passwords
line from yourmy.cnf
and add the linesecure_auth 1
).以下のエラーメッセージを
error.log
の中で見つけた場合:failed to connect: 23: Access denied for user 'root'@'ubuntu' (using password: YES) while connecting to drizzle upstream, ...
MySQLサーバサイドでMySQLアカウントがTCPログインアクセスを受け付けているかを調べる必要があります。素早く調べる方法はMySQLの公式クライアントでサーバに接続することです:
mysql --protocol=tcp -u user --password=password -h foo.bar.com dbname
注意
--protocol=tcp
オプションがここでは必要です。そうでなければ、MySQLクライアントはUnixドメインソケットをMySQLサーバに接続するために使うかも知れません。
知られている問題¶
- 後ろで動いているlibdrizzleライブラリが
CLIENT_MULTI_RESULTS
フラグをまだサポートしていない :(しかし必ず動くようにするでしょう) ため、mysql procedureの呼び出しは現在のところサポートされていません - 後ろで動いているlibdrizzleライブラリが
CLIENT_MULTI_STATEMENTS
をサポートしていないため、一つのSQL内の複数のSQLステートメントをサポートされていません。 - このモジュールは(まだ)
RTSIG
イベントモデルで動作しません。
インストール
このモジュールをngx_openrestyバンドルを使って HttpRdsJsonModuleと一緒にインストールすることがお勧めされます:
http://openresty.org
インストレーションのステップは通常 ./configure --with-http_drizzle_module && make && make install
するぐらいシンプルです( しかし、手動でlibdrizzleライブラリをインストールする必要があります。詳細な指示はhttp://openresty.org/#DrizzleNginxModule を見てください。)
別のやり方として、NGINXコアソースを手動でこのモジュールをコンパイルすることができます:
- 今はdrizzleプロジェクトで配布されhttps://launchpad.net/drizzleからダウンロード可能なlibdrizzle 1.0をまずインストールする必要があります。最新のdrizzle7リリースはlibdrizzle 1.0の個別ビルドをサポートしません。そしてインストールが面倒なBoostおよびProtobufのような多くの外部依存を必要とします。libdrizzle 1.0の個別ビルドをサポートする最後のバージョンは
2011.07.21
です。http://openresty.org/download/drizzle7-2011.07.21.tar.gz からダウンロードすることができます。drizzle7のこのバージョンのlibdrizzle1.0のインストールは通常以下のように簡単です
tar xzvf drizzle7-2011.07.21.tar.gz cd drizzle7-2011.07.21/ ./configure --without-server make libdrizzle-1.0 make install-libdrizzle-1.0
python
コマンドがpython2
インタプリタを指すようにしてください。最近は以下のことが知られています: Arch Linux distribution,python
はデフォルトでpython3
にリンクされており、make libdrizzle-1.0
はエラーをもたらすでしょう。File "config/pandora-plugin", line 185 print "Dependency loop detected with %s" % plugin['name'] ^ SyntaxError: invalid syntax make: *\** [.plugin.scan] Error 1
python
をpython2
に向けることでこれを修正することができます。
- drizzle-nginx-moduleのfile listからこのモジュールのリリースtarballの最新のバージョンをダウンロードします。
- 例えば、バージョン1.7.7 (NGINX互換性を見てください)のNGINXのソースコードをnginx.orgからダウンロードし、このモジュールを使ってソースをビルドします:
wget 'http://nginx.org/download/nginx-1.7.7.tar.gz' tar -xzvf nginx-1.7.7.tar.gz cd nginx-1.7.7/ # if you have installed libdrizzle to the prefix /opt/drizzle, then # specify the following environments: # export LIBDRIZZLE_INC=/opt/drizzle/include/libdrizzle-1.0 # export LIBDRIZZLE_LIB=/opt/drizzle/lib # Here we assume you would install you nginx under /opt/nginx/. ./configure --prefix=/opt/nginx \ --add-module=/path/to/drizzle-nginx-module make -j2 make install
通常はこのupstreamモジュールによって生成されたバイナリのRDS出力からのJSON出力を取得するためにHttpRdsJsonModuleも必要です。
互換性¶
MySQLを使っている場合は、MySQL 5.0 ~ 5.5
が必要です。MySQL 5.6+
が動作するかは分かりません; 報告を歓迎します!
このモジュールはLinuxおよびMac OS Xでテストされました。POSIX準拠のシステムの報告はとても感謝されるでしょう。
NGINXの以下のバージョンがこのモジュールで動作するはずです:
- 1.7.x (最後のテスト: 1.7.7)
- 1.6.x
- 1.5.x (最後のテスト: 1.5.8)
- 1.4.x (最後のテスト: 1.4.4)
- 1.3.x (最後のテスト: 1.3.7)
- 1.2.x (最後のテスト: 1.2.9)
- 1.1.x (最後のテスト: 1.1.5)
- 1.0.x (最後のテスト: 1.0.8)
- 0.8.x (最後のテスト: 0.8.55)
- 0.7.x >= 0.7.44 (最後にテストされたバージョンは 0.7.67です)
0.6.x
および 0.5.x
のようなNGINXの以前のバージョンは動作しないでしょう。
0.7.44
以上のNGINXの特定のバージョンでこのモジュールが動作しないことを見つけたら、バグの報告を考えてみてください。
コミュニティ¶
英語のメーリングリスト¶
openresty-en メーリングリストは英語を話す人のためのものです。
バグのレポート¶
バグレポート、欲しいもののリスト、あるいはパッチを下記でサブミットしてください
- GitHubで提供される問題追跡インタフェース 上でチケットを作成
- あるいは、OpenResty communityにメールを送信。
ソースリポジトリ¶
github上のopenresty/drizzle-nginx-moduleで利用可能
テストスィート¶
このモジュールはPerl駆動テストスィートが付いています。テストケースも 宣言的 です。Perl世界のTest::Nginx <http://search.cpan.org/perldoc?Test::Nginx> モジュールに感謝します。
アナタの側でそれを実行するには:
$ PATH=/path/to/your/nginx-with-echo-module:$PATH prove -r t
単一のNGINX サーバ (デフォルトでは localhost:1984
) は全てのテストスクリプト(.t
ファイル)に渡って使用されるため、prove
ユーティリティを起動する時に-jN
を指定することで並行してテストスィートを実行することは意味がありません。
TODO¶
- MySQLのトランザクションサポートの追加。
- 複数ステートメントのMYSQLクエリサポートの追加。
- drizzle_max_output_size ディレクティブの実装。RDS データが大きくサイズが指定されている場合は、モジュールはできるだけ速く出力を終了しようとしますが、結果の応答ボディがまだ有効なRDSフォーマットの中にあることを確実にし続けるでしょう。
- フェイルオーバーのサポートのための drizzle_upstream_next 機構の実装。
- 一つのlocation内での複数の drizzle_query_ directives のサポートの追加。
- upstreamサーバクラスタのための weighted ラウンドロビン アルゴリズムの実装。
- 指定したタイムアウトで動いていない接続をコネクションプールが自動的にリリースするように、
max_idle_time
オプションのdrizzle_server_directiveへの追加。 - 接続プールが自動的に接続数を生成し、それらをプール内に置くように、
min
オプションの drizzle_server_ directive への追加。 - drizzle_server_ directive の中でのUnixドメインソケットのサポートの追加。
- drizzle_process ディレクティブによって処理されなかった変数をdrizzle_query_directiveが拒否するようにする。これはMySQLインジェクションから私たちを守るでしょう。そのようなチェックを無効にするための ("strict=no")オプションもあるでしょう。
著者¶
- chaoslawful (王晓哲) <chaoslawful at gmail dot com>
- Yichun “agentzh” Zhang (章亦春) <agentzh at gmail dot com>, CloudFlare Inc.
- Piotr Sikora <piotr.sikora at frickle dot com>, CloudFlare Inc.
Copyright & License¶
このモジュールはBSDライセンスのもとにライセンスされます。
Copyright (C) 2009-2014, by Xiaozhe Wang (chaoslawful) <chaoslawful@gmail.com>.
Copyright (C) 2009-2014, by Yichun “agentzh” Zhang (章亦春) <agentzh@gmail.com>, CloudFlare Inc.
Copyright (C) 2010-2014, by FRiCKLE Piotr Sikora <info@frickle.com>, CloudFlare Inc.
無断転載禁ず
修正の如何に関係なくソースおよびバイナリ形式での再配布および使用は以下の条件に合う限り許可されます:
- Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.