2012/10/31


サブドメインに任意の文字列が入るウェブアプリのローカル開発 - 冬通りに消え行く制服ガールは?夢物語にリアルを求めない。 - subtech

サブドメインに任意の文字列が入るようなサービスをローカルで開発しようとすると、いろんなホストを /etc/hosts に書かないといけなくてすごく不便なので、なんとかしようと思っていたところ、id:hakobe932 先生に「それアレでできますよ」との御言葉を頂き、簡単なスクリプトを書きました。

http://subtech.g.hatena.ne.jp/cho45/20110804/1312389877
僕ならこうやるかも

libcho45.c
#define _GNU_SOURCE
#include <dlfcn.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <netdb.h>

static const char* host_mask;
static struct hostent *(*__gethostbyname)
    (const char*);
static int (*__gethostbyname_r)
    (const char*, struct hostent*, char*, size_tstruct hostent**, int *);
static int (*__getaddrinfo)
    (const char*, const char*, const struct addrinfo*, struct addrinfo**);

__attribute__((constructor))
void
wrap_gethostbyname() {
  __gethostbyname = dlsym(RTLD_NEXT, "gethostbyname");
  __gethostbyname_r = dlsym(RTLD_NEXT, "gethostbyname_r");
  __getaddrinfo = dlsym(RTLD_NEXT, "getaddrinfo");
  host_mask = getenv("HOST_MASK");
  if (!host_mask) host_mask = "";
}

struct hostent*
gethostbyname(const char* name) {
  if(strstr(name, host_mask)){
    return (*__gethostbyname)("localhost");
  }
  return (*__gethostbyname)(name);
}

int
gethostbyname_r(const char* name, struct hostent* result, char* buffer, size_t buflen, struct hostent** presult, int* h_errnop) {
  if(strstr(name, host_mask)){
    return (*__gethostbyname_r)("localhost", result, buffer, buflen, presult, h_errnop);
  }
  return (*__gethostbyname_r)(name, result, buffer, buflen, presult, h_errnop);
}

int
getaddrinfo(const char* name, const char* service, const struct addrinfo* hints, struct addrinfo** res) {
  if(strstr(name, host_mask)){
    return (*__getaddrinfo)("localhost", service, hints, res);
  }
  return (*__getaddrinfo)(name, service, hints, res);
}
このソースを # gcc -o libcho45.so -fPIC -shared libcho45.c -ldl -lnsl
でビルドして、例えばこんなperlスクリプトであれば

cho45.pl
use strict;
use warnings;

use LWP::UserAgent;

my $ua = LWP::UserAgent->new;
my $res = $ua->get("http://cho45.local.example.com/");
warn $res->decoded_content;
以下の様に起動する
# HOST_MASK=.local.example.com LD_PRELOAD=./libcho45.so perl cho45.pl
まぁ、やってる事は単純ですね!もちろんちゃんとした後方一致にするべきですが、まぁいいですよね。
昔のオジサン達はこんな事やってました。

この辺り、オジサンじゃないけどkazuhoさん辺りが詳しそう。
Posted at by



2012/10/30


plack を使ってて「サーバのサブフォルダを間借りして動かしたい」って事がたまにあるんだけど、そんな場合 nginx の設定でリバースプロキシに渡すって事をやります。 location /foo {
    try_files $uri $uri.html $uri/index.html @proxy-foo;
}

location @proxy-foo {
    proxy_pass http://localhost:5000;
    proxy_set_header Host $http_host;
}
この場合、通常の Plack アプリケーションだと / がアプリケーションルートになっているので404になってしまう。よって app.psgi とは別に !perl

use strict;
use warnings;
use Plack::Builder;
use Plack::Util;

builder {
    mount '/foo/' => Plack::Util::load_psgi('app.psgi');
}
の様な wrapper スクリプトを書く必要がありました。
しかし先日、plackup に --path 引数が追加され $ plackup --path /foo と書くことで、自動的にマウントしてくれる機能が付きました。
これでいちいち wrapper スクリプトを書かずに済むようになりました。

僕的に便利
Posted at by



2012/10/29


Github Notification API が出ました。
Notifications API - GitHub

Recent posts in this category Notifications API technoweenie on October 26, 2012 Latest commit per d...

https://github.com/blog/1306-notifications-api
github の通知を取得する場合、これまでは miyagawa さんが github growler でやっていた様に、ダッシュボードのRSSを使って自分のイベントを抽出しなければなりませんでしたが、Notification API を使う事で Github 上と同じ通知メッセージが取れる様になりました。
今日は Perl で Github のメッセージを通知するアプリケーションを作ってみました。
#!perl

use strict;
use warnings;
use LWP::UserAgent;
use HTTP::Request;
use Encode;
use JSON;
use Term::ReadKey;
use Data::Deduper;
use Growl::Any;

my ($username$password);

print "Username: ";
chomp($username = <STDIN>);
print "Password: ";
ReadMode(2);
chomp($password = ReadLine(0));
ReadMode(0);
print "\n";

my $ua = LWP::UserAgent->new;
$ua->ssl_opts(verify_hostname => 0);

my $req = HTTP::Request->new('POST''https://api.github.com/authorizations');
$req->content(to_json {
    scopes => ['notifications'],
    note => 'github-notification.pl',
    note_url => 'https://github.com/mattn/github-notification',
});
$req->authorization_basic($username$password);
my $res = from_json $ua->request($req)->decoded_content;
my $token = $res->{token};

my $dd = Data::Deduper->new(
    expr => sub {
        my ($a$b) = @_;
        $a->{id} eq $b->{id}
    },
);

my $growl = Growl::Any->new(
    appname => 'Github Notification',
    events => ['notification''error'],
);

while (1) {
    $res = $ua->get("https://api.github.com/notifications?access_token=$token");
    my $items = from_json decode_utf8 $res->decoded_content;
    for ($dd->dedup($items)) {
        $growl->notify(
            'notification',
            $_->{subject}->{title},
            $_->{description},
            $_->{repository}->{owner}->{avatar_url})
    }
    sleep($res->header('X-Poll-Interval') || 60);
}
前半部分はトークンを取る処理で、パスワードは token を得る為だけに使っています。
簡単ですね。これでどんなネタ振りも取りこぼす事無く反応出来ますね!
github notification
Posted at by