2012/10/31

Recent entries from same category

  1. RapidJSON や simdjson よりも速いC言語から使えるJSONライブラリ「yyjson」
  2. コメントも扱える高機能な C++ 向け JSON パーサ「jsoncpp」
  3. C++ で flask ライクなウェブサーバ「clask」書いた。
  4. C++ 用 SQLite3 ORM 「sqlite_orm」が便利。
  5. zsh で PATH に相対パスを含んだ場合にコマンドが補完できないのは意図的かどうか。

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