Hatena::ブログ(Diary)

脳みそスワップアウト(旧) このページをアンテナに追加 RSSフィード

2016-03-30

2012-04-26

[][] HTTPステータスコード 1xx系 メタ

今更ながら,今後増えてゆくであろうweb api開発時のためにまとめておく。

Restfulでありリソース指向であるものが美しい設計と考える。


100 (Continue)

そのリクエストが受けられるということを示す。

クライアントはExpectヘッダ他を送る必要がある。


受けられない場合は417を返す。


101 (Switching Protocols)

使わない。

クライアントがHTTP以外のプロトコルを使うことの宣言である Upgrade ヘッダを送り,

それを許可した場合にこれを返すことになっているようだ。


web apiは普通HTTP(S)サーバ上で動いており,HTTP(S)以外のプロトコルは喋れないので出番がない。

[][] HTTPステータスコード 2xx系 正常系

200 (OK)

あらゆるメソッドの正常終了


201 (Created)

putでリソースを新規作成した場合。

Locationヘッダはリソースへのパスをポイントしなければならない。


202 (Accepted)

クライアントからの要求をリアルタイムに処理はしないが受け付けたことを示す。

もちろん途中で失敗するかもしれない。

バッチなど非同期処理に使う。


リソース指向な設計では,ジョブ用のリソースを新規作成して,

LocationヘッダにそのURIをポイントする。


203 (Non-Authoritative Information)

使わない。

レスポンスヘッダの一部が自分以外の何かから得たものであり,

正確でない可能性があることを知らせたい?


正直よくわからない。


204 (No Content)

ステータスメッセージもしくはリソースの返却をサーバが拒否したことを示す。

PUT, POST, DELETEに対して返す。


GETに対して返す場合は,リソースは存在してもそれが空であることを示す。

bodyはない。


205 (Reset Content)

あまり使わない。

204と同じだが,クライアントがデータソースをリセットすべきであることを示す。

bodyはない。


206 (Partial Content)

200と同じだが,部分GET用のレスポンス。

クライアントはContent-Rangeを送信する。


レスポンスヘッダにDateが必要。

ETagとContent-Locationはリソース全体を返す場合のものと同じ。

bodyは部分リソース。


207 (Multi-Status)

HTTPのWebDAV拡張。

複数のステータスコードをbodyに付けられるため,

バッチリクエストのレスポンスに使える。

bodyはWebDAVボキャブラリ。RFC2518参照。

[][] HTTPステータスコード 3xx系 redirect

300 (Multiple Choices)

あまり使わない。

要求されたリソースの表現方法が複数あり,どれを返せばよいかわからないことを示す。

クライアントがAccept-*の指定をしてなかったか,存在しない表現を要求したかのどちらか。


デフォルトを決めておいて,200とともにそれを返してもよい。

だからあまり使われない。


400を返してエラー扱いにしてしまってもよいか?それは厳しすぎか?


Locationで優先度の高いURIをつけることができる。

bodyは表現のURIリスト。HTMLがいいようだ。


301 (Moved Permanently)

リソースが移動した。恒久的に。

Locationヘッダはリソースへのパスをポイントしなければならない。

bodyには,新しいURIへリンクするHTMLがつけられるが必須ではない。


302 (Found)

使わない方がいいが,

しかしクライアント開発の場合にはこのステータスは知っておかなければならない。

HTTP/1.0では,Moved TemporaryだったがHTTP/1.1で名前が変わった。


本来は,307(Temporary Redirect)と同じように処理されるべきだったのだが,

しかしそのようなクライアントは少なく,PUT,POST,DELETEのときに

303(See Other)と同じように処理するクライアントがほとんどだった。

この問題があったため,HTTP/1.1では307(Temporary Redirect)が新設されたという経緯がある。


つまりこのステータスは曖昧なもののため,新規開発で採用すべきではない。

303か307を使うべき。

もちろん303と307を理解しないHTTP/1.0クライアントとやり取りをする場合は別である。


Locationヘッダにはredirect先のURIをポイントする必要がある。

bodyには新しいURIをリンクするHTMLを付けられるが必須ではない。


303 (See Other)

処理は完了しているが,リソースを返す代わりにリソースのURIを返す。


「本当」のURIは1つしか存在しないはずで,そのエイリアスだった場合などに使う。

たとえば /hoge/fuga/current.tar.gz が /hoge/fuga/1.2.3.tar.gz のエイリアスだった,など。


Locationヘッダは新しいURIをポイントする。

bodyは301同様。


304 (Not Modified)

クライアントが既にそのデータを持っていることを示す。

条件付きHTTPリクエストと併用される。


Dateヘッダは必須。

ETagとContent-Locationは200の時と同じものを設定すべき。

Expires,Cache-Control,Varyは,以前に送信したものから変更されている場合には必要となる。

bodyはない。


305 (Use Proxy)

あまり使わない。

クライアントが特定のproxyを利用する必要があることを示す。

そういうケースがあまりないからあまり使わない。


LocationヘッダはproxyのURIをポイントする。


306 未使用


307 (Temporary Redirect)

リソースが別のURIにあり,再送する必要があることを示す。


GETの場合は303と同義。ミラーサイトへ誘導したい場合など。

POST,PUT,DELETEの場合はサーバが何かしらのアクションを起こすことになるので303とは意味が違う。


303なら正常終了したがbodyがないことを示す。

処理後のリソースが欲しければクライアントは新しいURIにGETを送る必要がある。


307は,サーバが処理を実行しようとすらしていないことを示す。

クライアントは新しいURIにリクエスト全体を再送する必要がある。

Locationヘッダは再送すべきURIをポイントする。

bodyは301同様。

[][] HTTPステータスコード 4xx系 クライアントサイドのエラー

400 (Bad Request)

不正な形式,無意味なデータをクライアントが送信してきた場合。

クライアント側の汎用エラーなので,他の4xx系が使えなければこれ。


必要あればbodyにエラーメッセージを付ける。


401 (Unauthrized)

認証情報がない・正しくない。

WWW-Authenticateヘッダにクライアントへの指示を設定,ヒントを与えるべき。

bodyにはエラードキュメント。ヒントのHTMLでもいい。


402 (Payment Required)

予約。規定されていない。


403 (Forbidden)

アクセス拒否

但し,これはリソースが存在することを暗黙のうちに公表している。404も検討すべき。


単に認証情報が不足している場合は401なので,。

特定IPや時間帯による制限に使う方がいいのだろう。


bodyには拒否された理由のドキュメント。必須ではない。


404 (Not Found)

リソースがない場合。

とくに,クライアントがどのリソースを要求しているのかをサーバ側がわからない場合。


同時に,このURIが空いていることも示しているのだが,

403(Forbidden)や401(Authentication Required)を隠すための嘘である可能性もあることに注意。


405 (Method Not Allowed)

このリソースがサポートしていないHTTPメソッドを使った場合。


Allowヘッダにはサポートするメソッドのリストを付ける


406 (Not Acceptable)

Accept-*の内容に制限が多すぎて,表現を返せない場合。


無視して優先度の高い表現を200とともに返すことが多いためあまり使われない。

bodyは有効な表現のリンクのリスト。


407 (Proxy Authentication Required)

proxyサーバの場合のみ。

認証をクリアしなければproxyが使えないことを示す。

Proxy-Authorizationヘッダのついたリクエストと併用される。


Proxy-Authenticateヘッダに,期待する認証の情報をつける。

407をクリアしたあと,401に引っかかる可能性があるがこの挙動に問題はない。


408 (Request Timeout)

あまり使わない。

コネクション確立後,全然リクエストが送られてこないのであれば,

これを返して接続閉じる必要がある。

アプリのレイヤではあまり使わなさそう。


409 (Conflict)

すでにリソースが存在する場合。

何らかの競合・矛盾が起きてしまう場合にこれを返す。


Locationに競合の原因であるURIをポイントする。

bodyにはドキュメントを。必須ではないがあったほうがいいと思う。


410 (Gone)

リソースがない場合。

以前にはそこにリソースがあったが,現在はもう存在しないことをわかっており,

かつ新しいURIを知らない場合。もし知っているのなら301である。


301同様,永続的な扱いである。


411 (Length Required)

Content-Lengthヘッダのないリクエストを許可しない場合。


412 (Precondition Failed)

リクエストヘッダで事前条件を指定されたものの,その条件が満たされなかった場合。


主にIf-Unmodified-SinceをつけたPUTで使う。


If-Match, If-None-Match, If-Unmodified-Sinceのいずれかのヘッダを持つリクエストと併用する。

但し,If-None-MatchのGETとHEADが満たされなかった場合だけは304である。


413 (Request Entity Too Large)

データが大きすぎてサーバが処理できないことを示す。


クライアント側がこのエラーを気にする場合は,先にExpect付きで送って

100が得られるかどうかを確認するという方法がある。


Retry-Afterヘッダに日時や秒数を指定することができる。

一時的な問題だった場合などにはこれを付ける。


414 (Request-URI Too Long)

あまり使わない。

HTTPの仕様ではURIの長さに制限はないが,webサーバで制限がある場合がほとんど。

サービスもそれに倣うなら使うのだろう。


415 (Unsupported Media Type)

理解できないメディアタイプで送られてきた場合。

より汎用的な400を使ってしまってもいい。


416 (Requested Range Not Satisfiable)

あまり使わない。

範囲がリソース自体よりも大きいなど,部分GETで範囲が適用できない場合。


Range付きのリクエストと併用される。

If-Rangeが付いていた場合は送信されない。


Content-Rangeにリソースの実際のサイズをつける。


417 (Expectation Failed)

100の逆。

[][] HTTPステータスコード 5xx系 サーバサイドのエラー

500 (Internal Server Error)

サーバ側で詳細不明の問題が起きている。

必要であればbodyにエラーメッセージを付けるが,

クライアントで解決できる問題ではないので無意味かも。


501 (Not Implemented)

サーバがサポートしてないHTTPの機能を使おうとした。

WebDAVのHTTP拡張機能を使おうとした場合などに返すことが多い。


405との違いは,サーバがメソッド自体を認識するか否か。


502 (Bad Gateway)

proxyからのみ返される。

proxy - アップストリームサーバ間の問題。

503 (Service Unavailable)

サーバ側で詳細不明の問題が起きている


高負荷でサーバリソース不足の場合が多い。

サーバ側はこれを返す代わりにリクエスト自体を拒否するという手もある。


Retry-Afterを付けられるが,大抵予想できない。


504 (Gateway Timeout)

proxyからのみ返される。

proxyがアップストリームサーバに接続できなかったことを示す。


505 (HTTP Version Not Supported)

使わないが,サービスとしてはありなのかも?


bodyにはサポートするプロトコルについてのドキュメント。

2011-02-07

[][]CentOS-5.5 64bit + PHP-5.3.5 のメモ

CentOS-5.5の64bit環境で,

PHP-5.3.5をソースからビルド,MySQL5.0もソースからビルド

phpバンドルされているgdと,libjpeg等の画像ライブラリをパッケージで導入しなければならない。


変えられないルールはこのとおり。

これらを利用するようPHPビルドする必要がある。

  • MySQLのprefixは /usr/local/mysql (諸々の事情)
  • libjpegのprefixは /usr/lib64 (通常のパッケージ)
    • /usr/lib64/libjpeg.so

これが大変面倒ではまっている。

PHPのconfigureスクリプトが気が利かないのである。


たとえば,このようにconfigureしたとする。

./configure \
--prefix=/usr/local/php-5.3.5 \
--without-pear \
--with-mysql=shared,"/usr/local/mysql-5.0.91" \
--with-pdo-mysql=shared,"/usr/local/mysql-5.0.91" \
--with-gd=shared \
--with-jpeg-dir=/usr

すると libjpeg が見つからないといわれる。

configure: error: libjpeg.(a|so) not found.

libjpegの検索順序はこのとおり。(configure 36644行目)

赤文字部分が --with-jpeg-dir の値である。

/usr/lib/libjpeg.so

/usr/local/lib/libjpeg.so

/usr/lib/libjpeg.so


64bit環境なので,lib64を探しに行かなければならない。

青文字の部分は $PHP_LIBDIR であり,--with-libdir で指定できる。

すると検索順序はこうなって見つけることができる。

/usr/lib64/libjpeg.so (これ)

/usr/local/lib64/libjpeg.so

/usr/lib64/libjpeg.so


が,今度はlibmysqlclientが見つからなくなる。

configure: error: Cannot find libmysqlclient under /usr/local/mysql-5.0.91.
Note that the MySQL client library is not bundled anymore!

検索順序を見てみると(59786行目)

/usr/local/mysql/lib/libmysqlclient.so

/usr/local/mysql/lib/mysql/libmysqlclient.so (これ)

これならいいのだが,先ほど指定した $PHP_LIBDIR の影響で

/usr/local/mysql/lib64/libmysqlclient.so

/usr/local/mysql/lib64/mysql/libmysqlclient.so

こうなってしまう。



ふんぎー!



これってつまり,今回のような構成ではPHPビルドと同時に

mysql拡張とgd拡張の両方をビルドすることはできないということなのでは。


phpでソースからのビルドrpmでの導入を混在させると,

64bit環境ではさらに面倒が増えるような感触。


そういうわけで,PHPmysql拡張を同時にビルドして,

gd拡張は後から追加することにした。

これなら $PHP_LIBDIR のスコープが狭いのであんしん。

$ cd /usr/local/src/php-5.3.5/ext/gd
$ /usr/local/php-5.3.5/bin/phpize
$ ./configure \
 --with-libdir=lib64 \
 --with-php-config=/usr/local/php-5.3.5/bin/php-config \
 --enable-gd=shared \
 --with-jpeg-dir=/usr \
 --with-png-dir=/usr \
 --with-freetype-dir=/usr \
 --enable-gd-native-ttf \
 2>&1 | tee _config.log

/usr/local/mysql/lib へのリンクを /usr/local/mysql/lib64 に作るというのも手かにゃ。

そうすれば $PHP_LIBDIR を lib64 にしたままいっぺんにできるけども,

あまりエレガンスではない気がするる。

2011-01-24

[][] OracleXE + oci8拡張メモ

無料,商用利用でまで無料な OracleXE を使って,PHPのoci8拡張を構築するメモ。

PHP-5.3.5(source), oracle-xe-client-10.2.0.1-1.0, CentOS-5.5。


OracleXEは,RPMパッケージとDEBパッケージが用意されているので,

インストールにXも必要なく簡単に導入できる。


ダウンロードはここから。ユーザ登録が必要。

http://www.oracle.com/technetwork/database/express-edition/downloads/index.html


さっくりRPMインストール

$ sudo rpm -ivh oracle-xe-client-10.2.0.1-1.0.i386.rpm
# PHPのソースツリーに移動して
$ cd /usr/local/src/php-5.3.5/ext/oci8
# phpize
$ /usr/local/php-5.3.5/bin/phpize

$ ./configure \
--with-php-config=/usr/local/php-5.3.5/bin/php-config \
--with-oci8=/usr/lib/oracle/xe/app/oracle/product/10.2.0/client

$ make

$ sudo make install

現時点では64bit OSに対応していないのが残念。

2010-08-26

[][]commons-digesterメモ

Javaはコードは読めるけどあまり使う機会がないので、

ポピュラーなライブラリであっても使うのに四苦八苦!


今回はcommons-digesterにハマったのでメモしておく。


一口でいうと、XML⇒Object変換ツール。

DOMとかでゴリゴリやるのに比べて比較的簡単に変換することができる。

Struts発祥なんだとか。


で、こんなXMLから<user>部分をUserオブジェクトに、かつ<options>はMapで保持、とかするには

<root>
  <id>1</id>
  <user>
    <firstName>アラレ</firstName>
    <lastName>則巻</lastName>
    <options>
      <option name="gender">female</option>
      <option name="hoge">fuga</option>
    </options>
  </user>
</root>

こんな感じみたい

Digester d = new Digester();

// root/user見つけたらUserインスタンス作って
d.addObjectCreate("root/user", User.class);
// root/user/firstName見つけたらfirstNameを設定・lastNameも同様
d.addBeanPropertySetter("root/user/firstName");
d.addBeanPropertySetter("root/user/lastName");
// optionsが現れたらHashMap作成
d.addObjectCreate("root/user/options", HashMap.class);
// optionが現れたら、put()メソッド呼ぶ。引数は2個。
d.addCallMethod("root/user/options/option", "put", 2);
// name属性と
d.addCallParam("root/user/options/option", 0, "name");
// 値部分
d.addCallParam("root/user/options/option", 1);
// ひとつ上のstackのsetOptions() でMapを登録
d.addSetNext("root/user/options", "setOptions");

URL xmlFile = DigesterSimpleListSample.class.getResource("in_test.xml");
User user = (User) d.parse(xmlFile);

System.out.println(ToStringBuilder.reflectionToString(user));

パース部分はXMLの設定ファイルで書くこともできて、

そうするとソースに手を加えずに…ということができるみたい。

でもこれをXMLで表現することは私には難しかった。