blog mail me! feed

X-Accel-Redirect的一点教训.

栋力博客使用的是wpmu, 不过版本比较低了, 因此wp-content/blogs.php中还没有用X-Sendfile或者X-Accel-Redirect头来处理静态文件的代码.
于是乎, 很久以前做了一个基于nginx和X-Accel-Redirect的hack,  不过今天bluef提醒我说静态文件的Content-Type有问题,
回头去看了下NginxXSendfile模块的文档, 才发现里面提到:

You should also know that the following headers aren’t modified by nginx:

Content-Type
Content-Disposition
Accept-Ranges
Set-Cookie
Cache-Control
Expires

于是把wpmu原来的处理mimetype的函数加了回去.

当然, wpmu 2.9.1.1的这个blogs.php已经很完善了, 可以直接通过配置, 支持X-Sendfile, X-Accel-Redirect头的同时, 也有了较好的缓存控制.
改天有空可以考虑把栋力博客迁移到新版本上去, 最担心的还是栋力博客启用的大量自定义插件的兼容性问题.

公交路线–>KML

如图, TG的漂移立功了...

如图, TG的漂移立功了...

下午坐82路回家, 看到一站”新南门”, 但是实在难以揣测这个站点是在府南河的哪一头, 为了避免少走弯路, 提前在滨江路下车了.
车还在浆洗街的时候, 摸出手机, 打开Google Maps看了看, 最后发现无法显示具体的公交线路图, 作罢.
回家后有点无聊, 就动手自己写了一个.

这个API的一个示例: http://tremblefrog.org/bus.php?lane=56

56是公交线路编号, 嗯, 这个URL里面没有城市.
设计得比较山寨, 只能支持成都的公交查询.
打算明天扩充一下功能, 顺便加一个URL Rewrite.

关于这个API怎么用:
你可以直接在(手机)浏览器中访问这个地址, 即会得到一个生成好的KML文件.
与KML关联的程序(Google Maps, Google Earth)可以直接打开.
你也可以在手机版的Google Maps中使用”搜索”功能, 搜索这个URL, 不一会儿就会看到结果显示了.

已知的bug: 地图漂移. TG的这个政策太恶心了.
你要知道, 我做这个web service的初衷是因为不知道公交站具体位置在哪里,
现在漂移了一条街, 这个破玩意儿还有毛用.

*UPDATE*
感谢来自dongmeng110的研究, 现在已经加入了偏移补偿, 可以正常显示了 :)
(maps.google.com的卫星图显示因为本身没有偏移, 补偿后反而会有偏移 -.-)

Read the rest of this entry »

豆瓣-图书馆馆藏信息Mashup.

今天回家, 突然想起某逆飞JR给我提过的在豆瓣对应页面显示图书馆馆藏信息的事情了.
正好图书馆系统(不得不说, 新系统和川大那个图书馆系统比起来, 还是垃圾)上线了, 就折腾了漫长的一段时候后, 弄出来了.

可以在这里访问到这个脚本: http://tremblefrog.org/libdb/
目前我还没有把它改成一个GreaseMonkey脚本, 不过本身是很简单的事情.
在豆瓣任意一本书的界面, 运行脚本就可以看到一个小窗口显示的豆瓣藏书信息了.

Screenshot

"Screenshot"

我校图书馆特立独行, 有的书储存的ISBN10, 有的书储存的ISBN13, 这逼得我必须去调用豆瓣的API,
在此要愤慨的凸一下图书馆信息的混乱.

不过新图书馆系统总的来说, 速度上总算有了点指数级的提升, 使得这个脚本不会像蜗牛一样慢.
当然现在功能还很简单了, 比如信息是按照ISBN对应查找的, 所以可能不同版次的图书, 还有不同出版社的图书, 尽管同名, 但是会显示没有.
我也正在考虑在搜索页面也加上这个脚本, 然后用Python多线程去并行的抓取图书馆的数据.

因为Javascript的安全性的问题, 搞得本来想在Javascript实现的很多东西, 基本都扔到PHP里实现去了.
之所以用PHP没用Python是因为偷懒, 服务器上的nginx的mod_wsgi模块没有装 -.-#
谢谢汪峰童鞋的歌陪伴了俺敲代码和调试的2个小时.

改天把API的计数器加上, 再把搜索页面的查询完成了,
就把源代码也一并扔出来.
有人想改进它再好不过了, 反正我未来一年也基本不会怎么借图书馆的书了.
>.<

最后很无奈的说一句: 用了这个系统才知道学校图书馆的图书资源多么的稀少
尤其是人文类的, 唉, 工科学校嘛, 认了, 其实反正我也不看人文社科书, 哈哈.

在写tuna前的一点架构思考.

  1. 需要断点续传吗?
    断点续传需要HTTP服务器的支持, 之前是est大神实现的s1完成的对PUT协议的支持.
    client可以通过Google Gears, 不过服务器端还有很多可以考虑的地方.

    首先, 如何识别一个需要resume的upload request呢?
    我想用cookie应该是比较好的方法, 每次用户提出一个上传请求, 就建立一个cookie, 上传完成后删除此cookie.
    这样避免了在最初的demo中, 使用随机的nonce带来的关闭浏览器就无法继续的bug.

  2. 如何实现?
    我想把判断abortive的上传的部分交给前台和cookie去做, 而不是在nginx内部实现.
    否则不仅仅会使得开发效率降低, 而且还得额外引入SQLite的代码, 有些古怪.

    nginx的module应该是只负责处理PUT请求就可以了, 如果发现一个不存在的续传请求,
    简单的抛出 400 Bad Request就ok.

  3. 目标?
    tuna的目标是实现一个类似rapidshare这种下载站, 每个文件有一个默认的expiration,
    下载可以推迟这个deadline.

    下载被理解为一个dormforce id所发起的一个成功的GET行为.
    一个dormforce id在不同IP产生的多次request均计算为一次.

  4. 架构?
    准备采用nginx + php-fpm + php + mysql 实现, 因为是服务器上已经有的生产环境.

    从209的那块新的SCSI硬盘上再单独划出一个逻辑卷做repository,
    这样管理起来灵活方便些.

    nginx 挂上 upload module 和 accesskey module, 用作大文件上传的hash, 和防盗链的控制.
    下载的时候用php通过X-SendFile提供访问控制和请求转发.
    因为upload module把文件的文件名都命名为了数字格式, 没有extension,
    所以需要php提供Content-Type和Content-Disposition头.

    防盗链这块, 用referer做第一级的过滤.
    第二级用accesskey, 使用在GET参数里的nonce值, 请求文件, IP做一个MD5的accesskey保证这个地址在一个时间戳上, 对应一个文件和一个IP是唯一的.
    第三级在php这里, 判断这个做nonce值的timestamp是否已经过期(比如300s), 如果okay则放行.

整体上应该大体就是这样.
唯一需要更改的地方就是让nginx的upload module支持PUT协议和续传.
中间需要改的地方还需要仔细看下.

一个wpmu的hack, 用nginx代替php处理静态文件.

wpmu使用php处理静态文件的模式一直让我很不舒服,
结果今天研究了N久如何绕开php来做静态文件的处理.

先选取了自己以为最简单的实现方法, 用squid做反向代理.
装上了squid 3.1, 发现网上的config教程都是2.6的, 完全不适用,
研究了manual后, 配好了反向代理,
接着, 尴尬的事情就发生了, 因为是本地做反向代理,
无疑通过nginx来进行proxy_pass的结果就是死循环…

nginx –[proxy_pass]–> squid –[http request]–> nginx –[proxy_pass]–> squid…

太糟糕了, 要解决这个问题只有通过实现两个virtual server, 并且重写host来实现反向代理.
庞大的工程. 遂放弃.

后来转向nginx的X-SendFile功能,
原理是捕捉到特定的X-Accel-Redirect头后,
通过实现一个内部的location, 来完成一个重定向.

不过事情没有这么简单, 现有栋力博客的重写规则是:
rewrite ^.*/files/(.*) /wp-content/blogs.php?file=$1;

而静态路径里也含有 /files/ , 所以会被同时重写, 最后返回一个500 Internal Error,
并且这个error是没法通过FireBug或者日志来trace的.
研究了下nginx的判断逻辑, 加了一条URL判断后终于搞定.

详细的步骤如下:
Read the rest of this entry »

杂念.

这周都无一例外的早上8点爬起来了, 逛一圈网站,
然后开始背单词. 早起看到的城市还是很漂亮的.

被php的引用类型折腾得够呛,
从某种意义上来说, 引用很像C语言的指针, 但是很可怕的是,
如果你把一个引用对象当作指针来用, 只会是灾难.

首先来说, php把array也用实例而不是引用传递,
且用foreach枚举元素时, 每个元素也会被重新实例化.
因此如果要对一个数组中的元素建立引用, 只能通过 array[index],
来建立对于对应元素的引用访问, 否则引用只会指向被你实例化后的元素. 

把引用的对象push到了一个数组里, 用unique_id作的associated_id,
结果这个数组的元素也只能通过下标访问, 一旦通过 var _element = ptr_list[index]; 
声明了另外一个_element对象, 引用关系也就莫名其妙的消失了.

我承认也许是我看manual太草率, 以至于在这里还是搞不明白引用对象使用中各个细节和处理的关系,
不过大概就先记在这里, 以后要用到就明白了.

—————— 

发现libsvm是可以直接嵌入到程序中使用的, 而svm-train/predict/scale.c 就是相当好的examples,
不过呢其实把libsvm直接编译到自己的程序里的唯一好处是省去了数据输出和再读入的时间,
对于大量的参数判别还是很有用的(比如某BT的双密码子64*64参数).

发现libsvm在进行迭代的时候, 迭代次数越小也就说明数据是越具有特征性的,
或者说更容易建立用于discrimination的hyperplane.
通过数据的svm-scale后, iterations由4k+下降到了~400, 准确率由78%上升到99.7%可以看出,
迭代数可以一定程度反映所选参数的优劣.

当然我担心64*64参数下, 有的参数分量会不会过小而导致数据直接为0,
由此scale的时候产生巨大的误差.
试试就知道了.