無精で短気で傲慢なプログラマ

UNIX や web やプログラムの技術的なことを中心に。

スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

PageTop

SSL/TLS 必須ページの .htaccess 設定

http://example.jp/ は http だが、http://example.jp/security/ は SSL/TLS 必須と
する場合の .htaccess 設定。

方法1. バーチャルホスト (VirtualHost ディレクティブ) を別に切る
 これが一番スマートかも。それができない場合は方法2 や方法3 で対応。

方法2. SSLRequireSSL を使う。
 .htaccess に
  SSLRequireSSL
 と書くだけで、そのディレクトリ以下は SSL 必須となる (SSL 以外のアクセスは deny する)。
 httpd.conf に記述するなら
  <Directory "/foo/bar">
   SSLRequireSSL
  </Directory>
 とする。
  マニュアル: http://httpd.apache.org/docs/2.0/ja/mod/mod_ssl.html#SSLRequireSSL

方法3. RewiteCond で判別し、http(80) の場合は他に飛ばす。
 RewriteEngine on
 RewriteCond %{SERVER_PORT} ^80$
 RewriteRule ([^/]*)$ http://%{HTTP_HOST}/$0
  マニュアル: http://httpd.apache.org/docs/2.0/ja/mod/mod_rewrite.html

ちなみに
 SetenvIf SERVER_PORT 80 NO_SSL=1
 Deny from env=NO_SSL
という判定方法は SetenvIf から SERVER_PORT を参照できないため無理っぽい。

さらに余談。Apache-SSL には SSLRequireSSL と逆の働きをする (SSL なら拒否)、
SSLDenySSL というディレクティブが存在する。しかし mod_ssl には SSLDenySSL は
存在しないし、mod_ssl を取り込んだ形の Apache2 にも存在しない (Apache-SSL と
mod_ssl は別物
)。
PageTop

SELECT 要素の value プロパティ

SELECT 要素の値を参照・代入する場合は
 参照: myform.myselect.options[myform.myselect.selectedIndex].value
 代入: myform.myselect.selectedIndex = "..";
とするしかないとずっと思っていたのだが、
 参照: myform.myselect.value
 代入: myform.myselect.value = '..';
と書けるということを先日知った。

例:





ソース:
  <select name="pref">
    <option value="0">選択してください</option>
    <option value="1">1:北海道</option>
    <option value="2">2:東京都</option>
    <option value="3">3:沖縄県</option>
  </select>
  <input type="button" value="SELECT要素の valueを表示"
          onClick="alert(this.form.pref.value)">
  <input type="button" value="東京都にセット"
          onClick="this.form.pref.value = 2">


DOM level-1 の 付録 E: ECMAスクリプト言語バインディング にも
HTMLSelectElement オブジェクトは以下のプロパティをもつ。
  value このプロパティは String 型である。
とあるので、多分問題なさそう。少なくとも IE6 と Firefox1.5.0.6 では動作した。


Javascript の初歩ですかそうですか。
PageTop

「GCCプログラミング工房」の西田亙氏が「GNU開発ツール」を自費出版

西田亙氏が「GNU開発ツール」を自費出版 より。

UNIX USERでGCCプログラミング工房を連載されていた西田亙氏が、Computer Architecture Series 「GNU開発ツール」を自費出版します。価格は 4,500円。

久々に読みたい本が出てきた。早速予約。
PageTop

続・これ、読みやすいの?

perl - There's more than one best practice
> この点ははっきり言おう。こういう形でreturnできるのはperlの美点だと。

途中で return できるのは別に perl 独自の機能ではないですよね。「perl
なら許される」ということであれば、ちょっと理解できない。どんな言語で
あろうと、基本は出口はひとつがベストと考えます。ただし実際にプログラム
を組むと、例外処理・エラー処理が必要になるので、なかなかそうもいかない。
ではどういう return なら容認するかというと、わたしの場合は
   sub func {
      return if $debug;
      ...
   }

という関数先頭付近で値のチェックをして return するタイプ。あるいは
関数の途中であっても、
   sub func {
      ...
      $ret = subfunc1();
      return if ( ! $ret );

      $ret = subfunc2();
      return if ( ! $ret );

      $ret = subfunc3();
      return if ( ! $ret );
      ...
   }
といったように、後から読んだ人に
  「この関数内ではこういう戻り方をする」
  「だから新たなチェックをする場合は、この書き方を真似しろよ。
   if とか使うなよ」
とアピールしているなら OK。小飼さんのソースからは、書き手の意思やメッセージが
見えない (しいて言うなら「俺は return にはこだわらない」かな?)。書き手の意思を
こめられない場合は、if 文を使うべきだと思います。

で、この場合は return 云々以前に、そもそも関数の切り出し方がイマイチなのでは
ないでしょうか。search_result 関数は

 - Yahoo! にリクエストを投げてレスポンスを取得
 - レスポンスを解析
 - 取り出したデータに OL・LI 要素を付加して返す

という順序凝縮になっており、「この関数は何をしてるの?」という問いに対して、
「~です」とスパッと答えることができない。だから結果的に return に無理が出てくる。

最初に見たときは「OL 要素というオブジェクトを返す関数」かなと思ったのですが、
よく見ると

 ('x hits', '<ol>', '<li>...</li>', '<li>...</li>', '</ol>')

と先頭にヒット数がついた配列を返しているので、ちょっと違う。

> そして、今回は関数化はもう一つの重要な利点を帯びている。
> それは、関数search_result()が、このサンプルコードの「ホット
> スポット」だからだ。読者が注意して読むべきなのは、そこだけ
> なのだ。あとは定数の設定、モジュールの宣言、結果の出力(print)
> といった「日常茶飯事」であり、読み飛ばしてかまわないところなのだ。

なるほど、そういう視点はありませんでした。しかし、ホットスポットと
いいつつも query が指定されていなければ return したり、HTML 生成を
行っていたり、いまいちホットスポットにしきれていない。トータルで
読みやすくなっているのか? というと、ちょっと疑問です。

結局のところ、仮にホットスポット化によってわかりやすくなるとしても、
return がいまいち、関数の切り出し方がいまいち、という結果になるなら、
関数化しないという選択肢も決して間違いではないでしょう。

なお、仕事でやるなら
   $response = get_response()
   ($hit, @data) = parse_response($response)
と機能凝縮で分けます。しかし今回のソース短さでは引数・戻り値の受け渡しが
煩雑になるだけで、関数に切り出すメリットがありません。


で、わたしが一番気になるのは、雑誌の読者がこのソースを理解できるの?
ということです。まぁ、はてなユーザが相手なら問題ないのかもしれませんが、
たとえばラクダ本の存在すら知らなくて、CGI&Perlポケットリファレンス
で全部済ませてしまう人も多いわけです。

そういう人たちに map・URI.pm・CGI.pm をふんだんに盛り込んだソース
を与えても、意味がわからんと投げ出す人・ぱっと見て読もうともしない人が
少なからずいるような気がします。そうなると、Yahoo! API の使い方を伝える
という本来の目的が達成できない。

特に
   return
      $xml->{'totalResultsAvailable'}, "hits",
      ol(map {
         encode_utf8 li(a({href=>$_->{'ClickUrl'}}, $_->{'Title'}))
         } @{ $xml->{'Result'} } );

を読んで、foreach ( @{ $xml->{'Result'} } ) でまわす書き方に書き
換えられない人は結構多いんじゃないでしょうか。

「そういう読者はターゲットにしていない」というのもひとつの考え方ですが、
あまりにもったいないなぁと。

最初のソースで解説しておいて、より美しいソースはコレだぜ! という展開
なら納得できますが、最初からリファクタリング後のソースを出すのはどう
なんでしょう。小飼さんのソースで編集からの OK が出ますか? (わたしは
雑誌執筆経験がないので、純粋な疑問です)

> それにしても惜しい。「無精で短気で傲慢なプログラマ」さんは、こうした
> 議論を進めるにあたって、サンプルコードを用意すべきであった。私のそれは
> きちんと動作検証までしてある(もちろんAPPIDは私のに変えてある)。少々
> 傲慢さが足りないのではないだろうか。

blog のタイトルで「俺って優秀だぜ」と自慢するのもおこがましいので当初は、
 「無精で短気で傲慢なプログラマを目指して」
としようかと思ったのですが、長かったので削ったのです。なので無精な
わけではないのです :-)

で、わたしの場合は、元のソースの方がわかりやすいと思いました。ただし
わたしなりの色を出すとすれば以下のようにします。おもしろみのないソースで
すみません。

[狙いと言い訳]
 - 目的は「Yahoo! API の使い方の解説」を読者に伝えること。
 - 読者を選ばないため、できる限りモジュールを使わない。
 - import せず LWP::Simple::get() と書くことで、モジュールを知らない読者が
  混乱しないよう配慮。
 - デリファレンス結果を一度配列 @results に格納し、リファレンスをわかって
  いない読者に配慮。
 - Model と View の分離をちょっとだけ主張してみる。
 - Model から View のデータ受け渡しの @click_urls と @titles は非常にかっこ
  悪いが、Class::Struct を使ったり、クラスをうほどでもないので、ここは妥協。
  (多分なにかしら適当なモジュールがあると思いますが、知らないので)
 - LWP::Simple::get に失敗した場合は致命的エラーなので die。
  fatalsToBrowser で画面に表示。改造時の利便性を考慮。
 - parse_args は、インタフェース仕様書を兼ねている。プログラム内で必要な
  入力はここで全部用意しろよ、途中で直接環境変数を参照したりするなよ、
  サニタイズするならここでやれよ、という意図を込めたつもり。
 - 一度も動かしてません。構文チェックもしてません。申し訳ない。

#!/usr/local/bin/perl
use strict;
use warnings;
use LWP::Simple;
use XML::Simple;
use Encode;
use CGI::Carp qw(fatalsToBrowser);

my $webapi_baseurl = 'http://api.search.yahoo.co.jp/WebSearchService/V1/webSearch';
my $myydn_appid = '..';
my $max_results = 10;

my $query = parse_args($ENV{'QUERY_STRING'});

my $hit_num;
my @click_urls;
my @titles;

if ( defined $query ){
    # リクエストURIの生成
    my $req_url = "$webapi_baseurl?appid=$myydn_appid&query=$key&results=$max_results";

    # APIへリクエストを送信
    my $yahoo_response = LWP::Simple::get($req_url) or die "$!";

    # 取得したXMLをパースする
    my $xmlsimple = XML::Simple->new();
    my $yahoo_xml = $xmlsimple->XMLin($yahoo_response, ForceArray=>['Result']);

    # 件数取得
    $hit_num = $yahoo_xml->{'totalResultsAvailable'};

    # URL とタイトルを取得
    my @results = @{$yahoo_xml->{'Result'}};
    foreach my $result (@results){
       push(@click_urls, $result->{'ClickUrl'});
       push(@titles, $result->{'Title'});
    }
}

print "Content-type: text/html; charset=utf8\n";
print "\n";
print "<html><body>\n";
print "<form><input type='text' name='query'><input type='submit' value='search'></form>\n";

if ( defined $query ){
   print "$hit_num hits\n";
    
   print "<ol>\n";
   for ( my $i=0 ; $i<@click_urls ; $i++ ){
      printf("<li><a href='%s'></a></li>\n",
             $click_urls[$i],
             Encode::encode_utf8($titles[$i]));
   }
   print "</ol>\n";
}
print "</body>\n";
print "</html>\n";

exit 0;

#--------
sub parse_args {
    my ($query_string) = @_;
    my $l_query = undef;
    foreach ( split('&', $query_string) ){
        my ($key, $value) = split('=', $_);
        $value =~ tr/+/ /;
        $value =~ s/(\W)/"%" . unpack("H2", $1)/ge;
        if ( $key eq 'query' ){
           $l_query = $value;
        }
    }
    return $l_query;   
}

PageTop

これ、読みやすいの?

perl - 勝手に添削 - WEB+DB Press Vol.32 pp.94

について。

わたしなんかよりよっぽど perl を知っている人なのだろうから機能的な
点についてはコメントしないが、はたしてこの添削後のコードはきれいなのか?

気になるのは、
   sub search_result{
      return unless param("query");
      ...
      my $response = get($uri) or return;
      ...
と途中で節操なく return しているところ。

上記関数の引数がなく、$q がグローバル変数化しているところ。

最後の
   return
      $xml->{'totalResultsAvailable'}, "hits",
      ol(map {
            encode_utf8 li(a({href=>$_->{'ClickUrl'}}, $_->{'Title'}))
         } @{ $xml->{'Result'} } );
のごちゃごちゃ感はどうなんだろう? 元ソースの
   (my $key = $q->param("query")) =~ s/(\W)/"%" . unpack("H2", $1)/ge;
がダメで、こっちはいいのか?

わたしが CGI.pm 嫌いなので、こういうソースを見慣れていないだけ?

そしてちょっとショックだったのは、はてブ でわたしと同じ感想を持った人が
いないこと。世の中の流れってそうなの? わたしがズレてるわけ?


あと、元ネタの記事は読んでないけど、解説が目的の場合は読者の脳内
スタックをなるべく消費しない、つまり過度に関数化しない方がよいと思う。
まぁこれは人それぞれだろうけど。


2006/4/23 2:29 追記。

わかってない奴だなぁと言われて傷つくのが嫌だったので (軟弱者)、こっそり
リンクしていたのだが、即座にバレてしまったので後付けでトラックバックを打ちました。

2006/4/24 1:19 追記。

引用コードのインデントが違うとの ご指摘 が。修正しました。fc2 の使い方が
よくわからず、手で &nbsp; に置き換えたときのミスです。申し訳ない。
PageTop
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。