001package com.facebook.swift.service; 002 003import static org.jboss.netty.handler.codec.http.HttpResponseStatus.OK; 004 005import java.util.Iterator; 006import java.util.ServiceLoader; 007 008import org.jboss.netty.buffer.ChannelBuffer; 009import org.jboss.netty.buffer.ChannelBuffers; 010import org.jboss.netty.channel.ChannelFutureListener; 011import org.jboss.netty.channel.ChannelHandlerContext; 012import org.jboss.netty.channel.MessageEvent; 013import org.jboss.netty.channel.SimpleChannelUpstreamHandler; 014import org.jboss.netty.channel.UpstreamMessageEvent; 015import org.jboss.netty.handler.codec.http.DefaultHttpResponse; 016import org.jboss.netty.handler.codec.http.HttpMethod; 017import org.jboss.netty.handler.codec.http.HttpRequest; 018import org.jboss.netty.handler.codec.http.HttpResponse; 019 020import com.facebook.nifty.core.ThriftMessage; 021import com.facebook.nifty.core.ThriftTransportType; 022import com.google.common.base.Supplier; 023import com.google.common.base.Throwables; 024import com.google.common.io.Resources; 025 026/** 027 * XHR(XML Http Request)è§£ç 器<br> 028 * å°†{@link HttpRequest}请求的内容数æ®(content)转为{@link ThriftMessage}, 029 * æä¾›ç»™{@link com.facebook.nifty.core.NiftyDispatcher} 030 * @author guyadong 031 * 032 */ 033public class ThriftXHRDecoder extends SimpleChannelUpstreamHandler implements Supplier<HttpRequest> { 034 035 private HttpRequest request; 036 public ThriftXHRDecoder() { 037 } 038 private static volatile byte[] homepage; 039 /** 040 * SPI(Service Provider Interface)æœºåˆ¶åŠ è½½ {@link XHRHomepageProvider}实例获å–页颿•°æ®,æ²¡æœ‰æ‰¾åˆ°è¿”å›žé»˜è®¤é¡µé¢æ•°æ® 041 * @return homepage页颿•°æ® 042 * @throws Exception 043 */ 044 private static byte[] loadHomepageByXHRHomepageProvider() throws Exception { 045 ServiceLoader<XHRHomepageProvider> providers = ServiceLoader.load(XHRHomepageProvider.class); 046 Iterator<XHRHomepageProvider> itor = providers.iterator(); 047 if(itor.hasNext()){ 048 XHRHomepageProvider provider = itor.next(); 049 try{ 050 byte [] homepage = provider.homepage(); 051 if(homepage != null){ 052 return homepage; 053 } 054 } catch (Exception e) { 055 // 读å–å¼‚å¸¸æ—¶ä½¿ç”¨é»˜è®¤é¡µé¢æ•°æ® 056 } 057 } 058 // 返回默认HOMEPAGEæ•°æ® 059 return Resources.toByteArray(ThriftXHRDecoder.class.getResource("/xhr_homepage.html")); 060 061 } 062 private static byte[] loadHomepage(){ 063 if(null == homepage){ 064 synchronized (ThriftXHRDecoder.class) { 065 if(null == homepage){ 066 try { 067 homepage = loadHomepageByXHRHomepageProvider(); 068 } catch (Exception e) { 069 Throwables.throwIfUnchecked(e); 070 throw new RuntimeException(e); 071 } 072 } 073 } 074 } 075 return homepage; 076 } 077 @Override 078 public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception { 079 if(e.getMessage() instanceof HttpRequest){ 080 request = (HttpRequest)e.getMessage(); 081 if(request.getContent().readable()){ 082 if(HttpMethod.POST.equals(request.getMethod())){ 083 ThriftMessage thriftMessage = new ThriftMessage(request.getContent(),ThriftTransportType.UNFRAMED); 084 ctx.sendUpstream(new UpstreamMessageEvent(ctx.getChannel(), thriftMessage, e.getRemoteAddress())); 085 return; 086 } 087 }else{ 088 // 空请求(没有内容)时输出首页 089 HttpResponse response = new DefaultHttpResponse(request.getProtocolVersion(), OK); 090 ChannelBuffer content = ChannelBuffers.wrappedBuffer(loadHomepage()); 091 response.setContent(content); 092 ctx.getChannel().write(response).addListener(ChannelFutureListener.CLOSE); 093 return ; 094 } 095 } 096 super.messageReceived(ctx, e); 097 } 098 @Override 099 public HttpRequest get() { 100 return request; 101 } 102}