PKF8org/PKF8 org/jruby/PKF8org/jruby/rack/PKF8org/jruby/webapp/PKF88+UMH-org/jruby/rack/DefaultRackApplication$1.classH1N , - ./ 01 23 45 67 89:;<val$envLjavax/servlet/ServletRequest;this$0'Lorg/jruby/rack/DefaultRackApplication;H(Lorg/jruby/rack/DefaultRackApplication;Ljavax/servlet/ServletRequest;)VCodeLineNumberTableLocalVariableTablethis InnerClasses)Lorg/jruby/rack/DefaultRackApplication$1;execute(Lorg/jruby/runtime/builtin/IRubyObject;[Lorg/jruby/runtime/builtin/IRubyObject;Lorg/jruby/runtime/Block;)Lorg/jruby/runtime/builtin/IRubyObject;exLjava/io/IOException;recv'Lorg/jruby/runtime/builtin/IRubyObject;args([Lorg/jruby/runtime/builtin/IRubyObject;blockLorg/jruby/runtime/Block;getArity()Lorg/jruby/runtime/Arity; SourceFileDefaultRackApplication.javaEnclosingMethod= >?   @org/jruby/RubyIOA BCD EF Gjava/io/IOExceptionH IJK LM'org/jruby/rack/DefaultRackApplication$1java/lang/Object#org/jruby/runtime/callback/Callback%org/jruby/rack/DefaultRackApplicationcall=(Ljavax/servlet/ServletRequest;)Lorg/jruby/rack/RackResponse;()V%org/jruby/runtime/builtin/IRubyObject getRuntime()Lorg/jruby/Ruby;javax/servlet/ServletRequestgetInputStream$()Ljavax/servlet/ServletInputStream;((Lorg/jruby/Ruby;Ljava/io/InputStream;)V#org/jruby/exceptions/RaiseExceptioncreateNativeRaiseExceptionL(Lorg/jruby/Ruby;Ljava/lang/Throwable;)Lorg/jruby/exceptions/RaiseException;org/jruby/runtime/Arity NO_ARGUMENTSLorg/jruby/runtime/Arity;  9*+*,*& %Y+*:+ !"#4 %% %!"%#$%&. ' '()*+  PKF8\./*+org/jruby/rack/DefaultRackApplication.class*1U , - . /0 123 6 78 9:; <= />?@A application'Lorg/jruby/runtime/builtin/IRubyObject;()VCodeLineNumberTableLocalVariableTablethis'Lorg/jruby/rack/DefaultRackApplication;call=(Ljavax/servlet/ServletRequest;)Lorg/jruby/rack/RackResponse;envLjavax/servlet/ServletRequest;runtimeLorg/jruby/Ruby; servlet_envresponseinit ExceptionsBdestroysetApplication*(Lorg/jruby/runtime/builtin/IRubyObject;)V SourceFileDefaultRackApplication.java   CDE FG HIto_io'org/jruby/rack/DefaultRackApplication$1 InnerClasses JK LMN OP%org/jruby/runtime/builtin/IRubyObject QRorg/jruby/rack/RackResponse ST%org/jruby/rack/DefaultRackApplicationjava/lang/Objectorg/jruby/rack/RackApplication*org/jruby/rack/RackInitializationException getRuntime()Lorg/jruby/Ruby;$org/jruby/javasupport/JavaEmbedUtils javaToRubyK(Lorg/jruby/Ruby;Ljava/lang/Object;)Lorg/jruby/runtime/builtin/IRubyObject; getMetaClass()Lorg/jruby/RubyClass;H(Lorg/jruby/rack/DefaultRackApplication;Ljavax/servlet/ServletRequest;)Vorg/jruby/RubyClass defineMethod:(Ljava/lang/String;Lorg/jruby/runtime/callback/Callback;)Vorg/jruby/RubygetCurrentContext#()Lorg/jruby/runtime/ThreadContext; callMethod(Lorg/jruby/runtime/ThreadContext;Ljava/lang/String;[Lorg/jruby/runtime/builtin/IRubyObject;)Lorg/jruby/runtime/builtin/IRubyObject; rubyToJava\(Lorg/jruby/Ruby;Lorg/jruby/runtime/builtin/IRubyObject;Ljava/lang/Class;)Ljava/lang/Object;!/* J*M,+N-Y*+ *,   Y-S :, $*=,4JJ @ !:"= #$+0 %&'+3 ()>*+ 67*+5 PKF84org/jruby/rack/DefaultRackApplicationFactory$1.class41'    this$0.Lorg/jruby/rack/DefaultRackApplicationFactory;1(Lorg/jruby/rack/DefaultRackApplicationFactory;)VCodeLineNumberTableLocalVariableTablethis InnerClasses0Lorg/jruby/rack/DefaultRackApplicationFactory$1;create9(Lorg/jruby/Ruby;)Lorg/jruby/runtime/builtin/IRubyObject;runtimeLorg/jruby/Ruby; SourceFile"DefaultRackApplicationFactory.javaEnclosingMethod" #$  % &.org/jruby/rack/DefaultRackApplicationFactory$1java/lang/ObjectEorg/jruby/rack/DefaultRackApplicationFactory$ApplicationObjectFactoryApplicationObjectFactory,org/jruby/rack/DefaultRackApplicationFactorynewApplication"()Lorg/jruby/rack/RackApplication;()VcreateApplicationObject   4 *+* -   = *+ .   ! PKF84org/jruby/rack/DefaultRackApplicationFactory$2.class*1'    this$0.Lorg/jruby/rack/DefaultRackApplicationFactory;1(Lorg/jruby/rack/DefaultRackApplicationFactory;)VCodeLineNumberTableLocalVariableTablethis InnerClasses0Lorg/jruby/rack/DefaultRackApplicationFactory$2;create9(Lorg/jruby/Ruby;)Lorg/jruby/runtime/builtin/IRubyObject;runtimeLorg/jruby/Ruby; SourceFile"DefaultRackApplicationFactory.javaEnclosingMethod" #$  % &.org/jruby/rack/DefaultRackApplicationFactory$2java/lang/ObjectEorg/jruby/rack/DefaultRackApplicationFactory$ApplicationObjectFactoryApplicationObjectFactory,org/jruby/rack/DefaultRackApplicationFactorynewErrorApplication"()Lorg/jruby/rack/RackApplication;()VcreateErrorApplicationObject   4 *+* e   = *+ f   ! PKF8;L#6org/jruby/rack/DefaultRackApplicationFactory$3$1.class`1O - . /01 .2 3 4 56 7 89:;<=this$1> InnerClasses0Lorg/jruby/rack/DefaultRackApplicationFactory$3;3(Lorg/jruby/rack/DefaultRackApplicationFactory$3;)VCodeLineNumberTableLocalVariableTablethis2Lorg/jruby/rack/DefaultRackApplicationFactory$3$1; getStatus()I getHeaders()Ljava/util/Map;getBody()Ljava/lang/String;respond+(Ljavax/servlet/http/HttpServletResponse;)VexLjava/io/IOException;response(Ljavax/servlet/http/HttpServletResponse; SourceFile"DefaultRackApplicationFactory.javaEnclosingMethod ?@  AB CDjava/lang/StringBuilder#Application initialization failed: EF GHI J" K"L MNjava/io/IOException0org/jruby/rack/DefaultRackApplicationFactory$3$1java/lang/Objectorg/jruby/rack/RackResponse.org/jruby/rack/DefaultRackApplicationFactory$3call=(Ljavax/servlet/ServletRequest;)Lorg/jruby/rack/RackResponse;()Vjava/util/Collections EMPTY_MAPLjava/util/Map;append-(Ljava/lang/String;)Ljava/lang/StringBuilder;val$eLjava/lang/Exception;java/lang/Exception getMessagetoString&javax/servlet/http/HttpServletResponse sendError(ILjava/lang/String;)V 4 *+*u  .r  .s !"-t #$x*+Y*  M%( w%z){ )%&**'()*+,PKF8 '4org/jruby/rack/DefaultRackApplicationFactory$3.class11 $ % &' ()*+val$eLjava/lang/Exception;this$0.Lorg/jruby/rack/DefaultRackApplicationFactory;F(Lorg/jruby/rack/DefaultRackApplicationFactory;Ljava/lang/Exception;)VCodeLineNumberTableLocalVariableTablethis InnerClasses0Lorg/jruby/rack/DefaultRackApplicationFactory$3;init()V Exceptions,call=(Ljavax/servlet/ServletRequest;)Lorg/jruby/rack/RackResponse;envLjavax/servlet/ServletRequest;destroy SourceFile"DefaultRackApplicationFactory.javaEnclosingMethod- ./ 0org/jruby/rack/DefaultRackApplicationFactory$3$1 0.org/jruby/rack/DefaultRackApplicationFactory$3java/lang/Objectorg/jruby/rack/RackApplication*org/jruby/rack/RackInitializationException,org/jruby/rack/DefaultRackApplicationFactorynewErrorApplication"()Lorg/jruby/rack/RackApplication;3(Lorg/jruby/rack/DefaultRackApplicationFactory$3;)V    9*+*,*~ +o = Y*q  +~  !"#PKF8Y -4org/jruby/rack/DefaultRackApplicationFactory$4.class1B ) * + , - ./0 1 2345 val$appfact6ApplicationObjectFactory InnerClassesGLorg/jruby/rack/DefaultRackApplicationFactory$ApplicationObjectFactory; val$runtimeLorg/jruby/Ruby;this$0.Lorg/jruby/rack/DefaultRackApplicationFactory;(Lorg/jruby/rack/DefaultRackApplicationFactory;Lorg/jruby/rack/DefaultRackApplicationFactory$ApplicationObjectFactory;Lorg/jruby/Ruby;)VCodeLineNumberTableLocalVariableTablethis0Lorg/jruby/rack/DefaultRackApplicationFactory$4; Exceptionsinit()Vre%Lorg/jruby/exceptions/RaiseException;destroy SourceFile"DefaultRackApplicationFactory.javaEnclosingMethod7 89     :; <=#org/jruby/exceptions/RaiseException*org/jruby/rack/RackInitializationException >? @A.org/jruby/rack/DefaultRackApplicationFactory$4%org/jruby/rack/DefaultRackApplicationEorg/jruby/rack/DefaultRackApplicationFactory$ApplicationObjectFactory,org/jruby/rack/DefaultRackApplicationFactorycreateApplicationi(Lorg/jruby/rack/DefaultRackApplicationFactory$ApplicationObjectFactory;)Lorg/jruby/rack/RackApplication;create9(Lorg/jruby/Ruby;)Lorg/jruby/runtime/builtin/IRubyObject;setApplication*(Lorg/jruby/runtime/builtin/IRubyObject;)V((Lorg/jruby/exceptions/RaiseException;)V$org/jruby/javasupport/JavaEmbedUtils terminate(Lorg/jruby/Ruby;)V  >*+*,*-*  k*** LY+  !"# 6*   $%&'(' PKF8~qlKorg/jruby/rack/DefaultRackApplicationFactory$ApplicationObjectFactory.classl1  create9(Lorg/jruby/Ruby;)Lorg/jruby/runtime/builtin/IRubyObject; SourceFile"DefaultRackApplicationFactory.java Eorg/jruby/rack/DefaultRackApplicationFactory$ApplicationObjectFactoryApplicationObjectFactory InnerClassesjava/lang/Object,org/jruby/rack/DefaultRackApplicationFactory   PKF8c^2org/jruby/rack/DefaultRackApplicationFactory.class^1 <y ;zl {| ;} ~ ~ ; ; ; ; ;  y   y    & ; * { . 0y 0 0 ; 7 < ApplicationObjectFactory InnerClasses rackupScriptLjava/lang/String;servletContextLjavax/servlet/ServletContext; classCacheLorg/jruby/util/ClassCache;errorApplication Lorg/jruby/rack/RackApplication;()VCodeLineNumberTableLocalVariableTablethis.Lorg/jruby/rack/DefaultRackApplicationFactory;init!(Ljavax/servlet/ServletContext;)VnewApplication"()Lorg/jruby/rack/RackApplication; ExceptionsgetApplicationappfinishedWithApplication#(Lorg/jruby/rack/RackApplication;)VgetErrorApplicationdestroy newRuntime()Lorg/jruby/Ruby;binjrubyeLjava/lang/Exception;configLorg/jruby/RubyInstanceConfig;runtimeLorg/jruby/Ruby;re%Lorg/jruby/exceptions/RaiseException;createApplicationObject9(Lorg/jruby/Ruby;)Lorg/jruby/runtime/builtin/IRubyObject;createErrorApplicationObjectnewErrorApplicationcreateRackServletWrapperK(Lorg/jruby/Ruby;Ljava/lang/String;)Lorg/jruby/runtime/builtin/IRubyObject;rackupcreateApplicationi(Lorg/jruby/rack/DefaultRackApplicationFactory$ApplicationObjectFactory;)Lorg/jruby/rack/RackApplication;rie,Lorg/jruby/rack/RackInitializationException;appfactGLorg/jruby/rack/DefaultRackApplicationFactory$ApplicationObjectFactory;verify6(Lorg/jruby/Ruby;Ljava/lang/String;)Ljava/lang/String;scriptsetErrorApplication SourceFile"DefaultRackApplicationFactory.java IJ CD AB  EF GH iS.org/jruby/rack/DefaultRackApplicationFactory$1 I mn RS PJ ZJorg/jruby/RubyInstanceConfig /META-INF/jruby.home/bin/jruby   java/lang/Exceptionjava/util/ArrayList  $servlet_context  require 'rack/handler/servlet' #org/jruby/exceptions/RaiseException*org/jruby/rack/RackInitializationException I jkrun JRuby::Rack::ErrorsApp.new.org/jruby/rack/DefaultRackApplicationFactory$23Warning: error application could not be initialized .org/jruby/rack/DefaultRackApplicationFactory$3 Ijava/lang/StringBuilder0Rack::Handler::Servlet.new(Rack::Builder.new {(  )}.to_app) [\.org/jruby/rack/DefaultRackApplicationFactory$4 I ,org/jruby/rack/DefaultRackApplicationFactoryjava/lang/Object%org/jruby/rack/RackApplicationFactoryEorg/jruby/rack/DefaultRackApplicationFactory$ApplicationObjectFactoryjavax/servlet/ServletContextgetInitParameter&(Ljava/lang/String;)Ljava/lang/String;java/lang/Thread currentThread()Ljava/lang/Thread;getContextClassLoader()Ljava/lang/ClassLoader;$org/jruby/javasupport/JavaEmbedUtilscreateClassCache4(Ljava/lang/ClassLoader;)Lorg/jruby/util/ClassCache;1(Lorg/jruby/rack/DefaultRackApplicationFactory;)Vorg/jruby/rack/RackApplication setClassCache(Lorg/jruby/util/ClassCache;)Vjava/lang/Class getResource"(Ljava/lang/String;)Ljava/net/URL; java/net/URLgetFile()Ljava/lang/String;java/lang/Stringlength()I substring(II)Ljava/lang/String; setJRubyHome(Ljava/lang/String;)V initialize@(Ljava/util/List;Lorg/jruby/RubyInstanceConfig;)Lorg/jruby/Ruby;org/jruby/RubygetGlobalVariables.()Lorg/jruby/internal/runtime/GlobalVariables; javaToRubyK(Lorg/jruby/Ruby;Ljava/lang/Object;)Lorg/jruby/runtime/builtin/IRubyObject;*org/jruby/internal/runtime/GlobalVariablessetb(Ljava/lang/String;Lorg/jruby/runtime/builtin/IRubyObject;)Lorg/jruby/runtime/builtin/IRubyObject; evalScriptlet;(Ljava/lang/String;)Lorg/jruby/runtime/builtin/IRubyObject;((Lorg/jruby/exceptions/RaiseException;)Vlog*(Ljava/lang/String;Ljava/lang/Throwable;)VF(Lorg/jruby/rack/DefaultRackApplicationFactory;Ljava/lang/Exception;)Vappend-(Ljava/lang/String;)Ljava/lang/StringBuilder;toString(Lorg/jruby/rack/DefaultRackApplicationFactory;Lorg/jruby/rack/DefaultRackApplicationFactory$ApplicationObjectFactory;Lorg/jruby/Ruby;)V getMessage!;<=ABCDEFGHIJK3*L M NOPQKv.*+*+* * ** L"#$&%'-)M.NO.CDRSK7 * Y* L,M  NOT&USKI *L++L45 6M NOVHT&WXK?+L :;MNOVHYSK/* L>M NOZJKA* * LB CDM NO[\KaYL+* M+,, dMY+M, ,*!"W,#$W,L&Y+',/VW%L. HIKM,N0O<PNRUSWTXUM>]B0^_O`a<bcX deaNOT&fgK> *+*(LZM NO bchgK<*+)(L^MNObciSK,**Y*+L++L*,+-.Y*+/Lc ijkl"nM  VH^_,NOjkK[+0Y123,3435$LM NObclBmnK*6M7Y*+,8M,M&Y,'&%LM4 bcop deNOqrT&stKg+,$9N-: L M* ^_NObcuBvXK>*+ L MNOVHwx@*>;? *.7PKF86l *org/jruby/rack/DefaultRackDispatcher.class 1t : ; < = >? @A BC DE FGH IJK FL IM NO PQRS ITUVWservletContextLjavax/servlet/ServletContext;!(Ljavax/servlet/ServletContext;)VCodeLineNumberTableLocalVariableTablethis&Lorg/jruby/rack/DefaultRackDispatcher;processR(Ljavax/servlet/http/HttpServletRequest;Ljavax/servlet/http/HttpServletResponse;)VreLjava/lang/Exception;request'Ljavax/servlet/http/HttpServletRequest;response(Ljavax/servlet/http/HttpServletResponse; rackFactory'Lorg/jruby/rack/RackApplicationFactory;app Lorg/jruby/rack/RackApplication; ExceptionsXYgetRackFactory)()Lorg/jruby/rack/RackApplicationFactory;handleException(Ljava/lang/Exception;Lorg/jruby/rack/RackApplicationFactory;Ljavax/servlet/http/HttpServletRequest;Ljavax/servlet/http/HttpServletResponse;)VerrorAppe SourceFileDefaultRackDispatcher.java Z  23 [\] ^_` ab cdjava/lang/Exception 45 rack.factorye fg%org/jruby/rack/RackApplicationFactoryh ij0Error: Couldn't handle error: response committed kl mZ n\rack.exceptiono pqException caughtError: Couldn't handle error rs$org/jruby/rack/DefaultRackDispatcherjava/lang/Objectorg/jruby/rack/RackDispatcherjavax/servlet/ServletExceptionjava/io/IOException()VgetApplication"()Lorg/jruby/rack/RackApplication;org/jruby/rack/RackApplicationcall=(Ljavax/servlet/ServletRequest;)Lorg/jruby/rack/RackResponse;org/jruby/rack/RackResponserespond+(Ljavax/servlet/http/HttpServletResponse;)VfinishedWithApplication#(Lorg/jruby/rack/RackApplication;)Vjavax/servlet/ServletContext getAttribute&(Ljava/lang/String;)Ljava/lang/Object;&javax/servlet/http/HttpServletResponse isCommitted()Zlog*(Ljava/lang/String;Ljava/lang/Throwable;)VresetgetErrorApplication%javax/servlet/http/HttpServletRequest setAttribute'(Ljava/lang/String;Ljava/lang/Object;)V sendError(I)V!F **+   !" #$\*N:-:+,;-0:*-+,  -: -.I.9IIKI6  $#%.!0"9$>%I$P%[( >0 %&\!"\'(\)*W+,T-./01239*  + !"45g *+,:-+*+-:*JM6 2 3469&:/;;<J@M=O>\?fA H&$6.O7&g!"g%&g+,g'(g)*/0189PKF8org/jruby/rack/merb/PKF8X5#4org/jruby/rack/PoolingRackApplicationFactory$1.class1g 2 3 4 56 578 9 0: 5; 0<= 4> ? 5@ A B CD EFG CHIJKval$appsLjava/util/Queue;this$0.Lorg/jruby/rack/PoolingRackApplicationFactory;B(Lorg/jruby/rack/PoolingRackApplicationFactory;Ljava/util/Queue;)VCodeLineNumberTableLocalVariableTablethis InnerClasses0Lorg/jruby/rack/PoolingRackApplicationFactory$1;run()Vapp Lorg/jruby/rack/RackApplication;ex,Lorg/jruby/rack/RackInitializationException; SourceFile"PoolingRackApplicationFactory.javaEnclosingMethodL MN   (O PQ RSorg/jruby/rack/RackApplication T( UV WX YZjava/lang/StringBuilder.Info: add application to the pool. size now = [\ ]^ [_ `ab cd e(*org/jruby/rack/RackInitializationException'Error: unable to initialize application cf.org/jruby/rack/PoolingRackApplicationFactory$1java/lang/Objectjava/lang/Runnable,org/jruby/rack/PoolingRackApplicationFactorylaunchInitializerThreads(Ljava/util/Queue;)Vjava/util/QueueisEmpty()Zremove()Ljava/lang/Object;init access$000A(Lorg/jruby/rack/PoolingRackApplicationFactory;)Ljava/util/Queue;add(Ljava/lang/Object;)Z access$100N(Lorg/jruby/rack/PoolingRackApplicationFactory;)Ljavax/servlet/ServletContext;append-(Ljava/lang/String;)Ljava/lang/StringBuilder;size()I(I)Ljava/lang/StringBuilder;toString()Ljava/lang/String;javax/servlet/ServletContextlog(Ljava/lang/String;)V notifyAll*(Ljava/lang/String;Ljava/lang/Throwable;)V  9*+*,*!" #&'( TL*YM*,ç{*L,çN,-+*YM*+ W* Y  **,ç :,qL* + ,),,/,A!F '17AOy" )*+,#&-./01% PKF8Grw2org/jruby/rack/PoolingRackApplicationFactory.classt17 X X Y  X X Z X U     X X X X U  X X X  #  Z  Z ( X Xu0 X U ;  : : Z B Yg X  U UDEFAULT_TIMEOUTI ConstantValueservletContextLjavax/servlet/ServletContext; realFactory'Lorg/jruby/rack/RackApplicationFactory;applicationPoolLjava/util/Queue; Signature3Ljava/util/Queue;initialLjava/lang/Integer;maximumtimeoutJpermits Ljava/util/concurrent/Semaphore;*(Lorg/jruby/rack/RackApplicationFactory;)VCodeLineNumberTableLocalVariableTablethis.Lorg/jruby/rack/PoolingRackApplicationFactory;factoryinit!(Ljavax/servlet/ServletContext;)VspecifiedTimeout ExceptionsnewApplication"()Lorg/jruby/rack/RackApplication;getApplicationex Ljava/lang/InterruptedException;finishedWithApplication#(Lorg/jruby/rack/RackApplication;)Vapp Lorg/jruby/rack/RackApplication;getErrorApplicationdestroy()Vi$Ljava/util/Iterator;getApplicationPool()Ljava/util/Collection;:()Ljava/util/Collection;fillInitialPoolappsLocalVariableTypeTablelaunchInitializerThreads(Ljava/util/Queue;)Vi numThreads6(Ljava/util/Queue;)VcreateApplications()Ljava/util/Queue;,Lorg/jruby/rack/RackInitializationException;5()Ljava/util/Queue;waitForNextAvailable(J)V getInitial()Ljava/lang/Integer; getMaximum getRangeValue9(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/Integer;endLjava/lang/String;gsValuevgetPositiveInteger'(Ljava/lang/String;)Ljava/lang/Integer;eLjava/lang/Exception;string access$000A(Lorg/jruby/rack/PoolingRackApplicationFactory;)Ljava/util/Queue;x0 access$100N(Lorg/jruby/rack/PoolingRackApplicationFactory;)Ljavax/servlet/ServletContext; SourceFile"PoolingRackApplicationFactory.java _` cd njava/util/LinkedList jk ab vwjruby.runtime.timeout.sec java/lang/StringBuilder$Info: using runtime pool timeout of    seconds     gh ih java/util/concurrent/Semaphore n lm |{  java/lang/InterruptedException*org/jruby/rack/RackInitializationExceptiontimeout: all listeners busy n  org/jruby/rack/RackApplication   ! { "#$ % & ' () !jruby.runtime.initializer.threads *+java/lang/Thread.org/jruby/rack/PoolingRackApplicationFactory$1 InnerClasses n,JRuby-Rack-App-Init- - n. / z{javax/servlet/ServletException,Error: unable to create application for pool 0minIdle max maxActivejruby. .runtimes jruby.pool. Warning: no  runtimes specified.Info: received  runtimes = 1 23 45java/lang/Integer n6java/lang/Exception,org/jruby/rack/PoolingRackApplicationFactoryjava/lang/Object%org/jruby/rack/RackApplicationFactory longValue()Jappend-(Ljava/lang/String;)Ljava/lang/StringBuilder;(J)Ljava/lang/StringBuilder;toString()Ljava/lang/String;javax/servlet/ServletContextlog(Ljava/lang/String;)VintValue()I(IZ)Vjava/util/concurrent/TimeUnitSECONDSLjava/util/concurrent/TimeUnit; tryAcquire#(JLjava/util/concurrent/TimeUnit;)Z*(Ljava/lang/String;Ljava/lang/Throwable;)Vjava/util/QueueisEmpty()Zremove()Ljava/lang/Object;sizeadd(Ljava/lang/Object;)Zreleaseiterator()Ljava/util/Iterator;java/util/IteratorhasNextnextjava/util/CollectionsunmodifiableCollection.(Ljava/util/Collection;)Ljava/util/Collection;valueOf(I)Ljava/lang/Integer;B(Lorg/jruby/rack/PoolingRackApplicationFactory;Ljava/util/Queue;)V(I)Ljava/lang/StringBuilder;)(Ljava/lang/Runnable;Ljava/lang/String;)Vstartwait-(Ljava/lang/Object;)Ljava/lang/StringBuilder;getInitParameter&(Ljava/lang/String;)Ljava/lang/String;parseInt(Ljava/lang/String;)I(I)V!XYZ[\]^_`abcdefghihjklmnop`**Y**+ q/*,01rstubvwp*+* + * M, *, +Y******6*** ***Y***q>45789";C=K>S?Z@rAzCEFHr st_`xhyBz{p/*qKr sty#|{p[*!** !WL#Y$+%*YL*&*'(+ð+çM+,* )",FLGILLOLq* OQTRS%V,W8XGZQ\r }~[sty#pH*YM****,ñ*++W* *,,çN,-#B$?BBEBq"`a!b$d/e6f=hGirHstH{p4 * -qlr  stp:*YL*.M,/,0(N-1+ç :+/2262qpq$r-t9ur $:stp2*2qyr step/*3L*+4*YM*& *57,çN,-&)),)q $.r/st*d *fyBpG*8 M,9M>,/:Y;Y*+<Y=>?@ϱq @Fr*4\GstGd@h Gfep<YL=*(+* A+WNBYC-D+%(#q"%()4:r*) } 0\<st4d 4fyBep *YN*E-ç :-N"qr }~ st jkp3 *FGHqr  stp3 *IJHqr  stp*YK+L N-*YM, N-'*YN+O(*YP+Q-R-q!9=ar*stkhp!*+ST= UYVMWqr* \!st!p/*q%r tp/*q%r t ;PKF8k@;$org/jruby/rack/RackApplication.class;1  init()V Exceptionscall=(Ljavax/servlet/ServletRequest;)Lorg/jruby/rack/RackResponse;destroy SourceFileRackApplication.javaorg/jruby/rack/RackApplicationjava/lang/Object*org/jruby/rack/RackInitializationException   PKF8"+org/jruby/rack/RackApplicationFactory.class1init!(Ljavax/servlet/ServletContext;)V ExceptionsnewApplication"()Lorg/jruby/rack/RackApplication;getApplicationfinishedWithApplication#(Lorg/jruby/rack/RackApplication;)VgetErrorApplicationdestroy()V SourceFileRackApplicationFactory.java%org/jruby/rack/RackApplicationFactoryjava/lang/Objectjavax/servlet/ServletException*org/jruby/rack/RackInitializationException     PKF8V^#org/jruby/rack/RackDispatcher.class-1 EXCEPTIONLjava/lang/String; ConstantValueDYNAMIC_REQS_ONLYprocessR(Ljavax/servlet/http/HttpServletRequest;Ljavax/servlet/http/HttpServletResponse;)V Exceptions SourceFileRackDispatcher.javaorg/jruby/rack/RackDispatcherjava/lang/Objectrack.exceptionrack.dynamic.requests.onlyjavax/servlet/ServletExceptionjava/io/IOException   PKF8uGr!org/jruby/rack/RackFilter$1.class 11  ! " # $% &'(this$0Lorg/jruby/rack/RackFilter;E(Lorg/jruby/rack/RackFilter;Ljavax/servlet/http/HttpServletRequest;)VCodeLineNumberTableLocalVariableTablethis InnerClassesLorg/jruby/rack/RackFilter$1;x0'Ljavax/servlet/http/HttpServletRequest; getPathInfo()Ljava/lang/String; SourceFileRackFilter.javaEnclosingMethod) *+ ,java/lang/StringBuilder -  ./.html 0org/jruby/rack/RackFilter$1,javax/servlet/http/HttpServletRequestWrapperorg/jruby/rack/RackFiltermaybeAppendHtmlToPathG(Ljavax/servlet/ServletRequest;)Ljavax/servlet/http/HttpServletRequest;*(Ljavax/servlet/http/HttpServletRequest;)V()Vappend-(Ljava/lang/String;)Ljava/lang/StringBuilder;toString   ? *+*,t  AY*u   PKF8̏!org/jruby/rack/RackFilter$2.class11  ! " # $% &'(this$0Lorg/jruby/rack/RackFilter;E(Lorg/jruby/rack/RackFilter;Ljavax/servlet/http/HttpServletRequest;)VCodeLineNumberTableLocalVariableTablethis InnerClassesLorg/jruby/rack/RackFilter$2;x0'Ljavax/servlet/http/HttpServletRequest;getServletPath()Ljava/lang/String; SourceFileRackFilter.javaEnclosingMethod) *+ ,java/lang/StringBuilder -  ./.html 0org/jruby/rack/RackFilter$2,javax/servlet/http/HttpServletRequestWrapperorg/jruby/rack/RackFiltermaybeAppendHtmlToPathG(Ljavax/servlet/ServletRequest;)Ljavax/servlet/http/HttpServletRequest;*(Ljavax/servlet/http/HttpServletRequest;)V()Vappend-(Ljava/lang/String;)Ljava/lang/StringBuilder;toString   ? *+*,{  AY*|   PKF8R`_Z5org/jruby/rack/RackFilter$ResponseStatusCapture.classZ17 + , - . / 0 134statusI+(Ljavax/servlet/http/HttpServletResponse;)VCodeLineNumberTableLocalVariableTablethisResponseStatusCapture InnerClasses1Lorg/jruby/rack/RackFilter$ResponseStatusCapture;response(Ljavax/servlet/http/HttpServletResponse; sendError(ILjava/lang/String;)VmessageLjava/lang/String; Exceptions5(I)V sendRedirect(Ljava/lang/String;)Vpath setStatus flushBuffer()VisError()Z access$0004(Lorg/jruby/rack/RackFilter$ResponseStatusCapture;)Zx0 SourceFileRackFilter.java $%  ! ! "#6/org/jruby/rack/RackFilter$ResponseStatusCapture-javax/servlet/http/HttpServletResponseWrapperjava/io/IOExceptionorg/jruby/rack/RackFilter    I *+*ȵ>; ?  H* BC  >* FG I *.*+JK L  !R***OP QS !]** *,VW XZ  "#> **]^ `  $%:*c &'/*: ()* 2 PKF8@l org/jruby/rack/RackFilter.class 71 K LM NO P QRS T UV W XY Z[ \]^ _` a bc K d e fgh jk jlmnResponseStatusCapture InnerClasses dispatcherLorg/jruby/rack/RackDispatcher;()VCodeLineNumberTableLocalVariableTablethisLorg/jruby/rack/RackFilter;"(Lorg/jruby/rack/RackDispatcher;)Vdispinit(Ljavax/servlet/FilterConfig;)VconfigLjavax/servlet/FilterConfig; ExceptionsodoFilter[(Ljavax/servlet/ServletRequest;Ljavax/servlet/ServletResponse;Ljavax/servlet/FilterChain;)VrequestLjavax/servlet/ServletRequest;responseLjavax/servlet/ServletResponse;chainLjavax/servlet/FilterChain; httpRequest'Ljavax/servlet/http/HttpServletRequest; httpResponse(Ljavax/servlet/http/HttpServletResponse;capture1Lorg/jruby/rack/RackFilter$ResponseStatusCapture;pdestroymaybeAppendHtmlToPathG(Ljavax/servlet/ServletRequest;)Ljavax/servlet/http/HttpServletRequest; servletPathLjava/lang/String;pathInfouri SourceFileRackFilter.java $% "#$org/jruby/rack/DefaultRackDispatcherq rs $t CD&javax/servlet/http/HttpServletResponse/org/jruby/rack/RackFilter$ResponseStatusCapture $uv 3w xy z%rack.dynamic.requests.only{ |}~ %javax/servlet/http/HttpServletRequest java/lang/StringBuilder  org/jruby/rack/RackFilter$1 $org/jruby/rack/RackFilter$2org/jruby/rack/RackFilterjava/lang/Objectjavax/servlet/Filterjavax/servlet/ServletExceptionjava/io/IOExceptionjavax/servlet/FilterConfiggetServletContext ()Ljavax/servlet/ServletContext;!(Ljavax/servlet/ServletContext;)V+(Ljavax/servlet/http/HttpServletResponse;)Vjavax/servlet/FilterChain@(Ljavax/servlet/ServletRequest;Ljavax/servlet/ServletResponse;)V access$0004(Lorg/jruby/rack/RackFilter$ResponseStatusCapture;)Zresetjava/lang/BooleanTRUELjava/lang/Boolean;javax/servlet/ServletRequest setAttribute'(Ljava/lang/String;Ljava/lang/Object;)Vorg/jruby/rack/RackDispatcherprocessR(Ljavax/servlet/http/HttpServletRequest;Ljavax/servlet/http/HttpServletResponse;)VgetServletPath()Ljava/lang/String; getPathInfoappend-(Ljava/lang/String;)Ljava/lang/StringBuilder;toStringjava/lang/String lastIndexOf(I)IE(Lorg/jruby/rack/RackFilter;Ljavax/servlet/http/HttpServletRequest;)V!"#$%&3*' ( )*$+&F **+'!" #( )* ,#-.&J*Y+' '(()*/01234&L*+:,:Y :-  $ + *+'& ,- ./"0*112<3K5(HL)*L56L78L9:E;< ?=>4?@1A2B%&+'8( )*CD&a+M,N,:-:Y:./Y*,M Y*,M,'. hi jkmn2pCqHrUy_(>a)*a56\;< UEFMGFJHFIJ! PKF8~E0org/jruby/rack/RackInitializationException.classx1D ( )* + ,- ./ 012 +3 4 .5 / /67((Lorg/jruby/exceptions/RaiseException;)VCodeLineNumberTableLocalVariableTablethis,Lorg/jruby/rack/RackInitializationException;re%Lorg/jruby/exceptions/RaiseException;exceptionMessage9(Lorg/jruby/exceptions/RaiseException;)Ljava/lang/String;stLjava/lang/StringBuilder;bLjava/io/ByteArrayOutputStream;*(Ljava/lang/String;Ljava/lang/Throwable;)VmsgLjava/lang/String;exLjava/lang/Throwable; SourceFile RackInitializationException.java  !java/lang/StringBuilder 89 :;< => ?@ java/io/ByteArrayOutputStreamjava/io/PrintStream A BC*org/jruby/rack/RackInitializationExceptionjava/lang/Exception()V#org/jruby/exceptions/RaiseException getException()Lorg/jruby/RubyException;org/jruby/RubyExceptiontoString()Ljava/lang/String;append-(Ljava/lang/String;)Ljava/lang/StringBuilder;(Ljava/io/OutputStream;)VprintBacktrace(Ljava/io/PrintStream;)V!B *++     D*AYL+*W Y M* Y, +,W+" %4=B  6% D!I*+,  ! "#$%&'PKF8u9w)$!org/jruby/rack/RackResponse.class$1  getStatus()I getHeaders()Ljava/util/Map;getBody()Ljava/lang/String;respond+(Ljavax/servlet/http/HttpServletResponse;)V SourceFileRackResponse.javaorg/jruby/rack/RackResponsejava/lang/Object   PKF819 org/jruby/rack/RackServlet.classn19 $ %& '( )*+ ,-./ dispatcherLorg/jruby/rack/RackDispatcher;()VCodeLineNumberTableLocalVariableTablethisLorg/jruby/rack/RackServlet;"(Lorg/jruby/rack/RackDispatcher;)Vinit (Ljavax/servlet/ServletConfig;)VconfigLjavax/servlet/ServletConfig;service@(Ljavax/servlet/ServletRequest;Ljavax/servlet/ServletResponse;)VrequestLjavax/servlet/ServletRequest;responseLjavax/servlet/ServletResponse; Exceptions01 SourceFileRackServlet.java  $org/jruby/rack/DefaultRackDispatcher2 34 5%javax/servlet/http/HttpServletRequest&javax/servlet/http/HttpServletResponse6 78org/jruby/rack/RackServletjavax/servlet/http/HttpServletjavax/servlet/ServletExceptionjava/io/IOExceptionjavax/servlet/ServletConfiggetServletContext ()Ljavax/servlet/ServletContext;!(Ljavax/servlet/ServletContext;)Vorg/jruby/rack/RackDispatcherprocessR(Ljavax/servlet/http/HttpServletRequest;Ljavax/servlet/http/HttpServletResponse;)V!   3*   F **+   J*Y+ $%T*+, *+  !"#PKF8/org/jruby/rack/RackServletContextListener.class1W 2 3 45 67 89 :;< 8= 8>? @ 8ABC 2 DEFG FACTORY_KEYLjava/lang/String; ConstantValuefactory'Lorg/jruby/rack/RackApplicationFactory;()VCodeLineNumberTableLocalVariableTablethis+Lorg/jruby/rack/RackServletContextListener;*(Lorg/jruby/rack/RackApplicationFactory;)VfactoryForTestcontextInitialized&(Ljavax/servlet/ServletContextEvent;)VexLjava/lang/Exception;ctxEvent#Ljavax/servlet/ServletContextEvent;ctxLjavax/servlet/ServletContext;faccontextDestroyednewApplicationFactory)()Lorg/jruby/rack/RackApplicationFactory; SourceFileRackServletContextListener.java  H IJ ./ rack.factoryK LM NOjava/lang/Exception(Error: application initialization failed PQ RS%org/jruby/rack/RackApplicationFactory T UV+org/jruby/rack/SharedRackApplicationFactory,org/jruby/rack/DefaultRackApplicationFactory ")org/jruby/rack/RackServletContextListenerjava/lang/Object$javax/servlet/ServletContextListener!javax/servlet/ServletContextEventgetServletContext ()Ljavax/servlet/ServletContext;javax/servlet/ServletContext setAttribute'(Ljava/lang/String;Ljava/lang/Object;)Vinit!(Ljavax/servlet/ServletContext;)Vlog*(Ljava/lang/String;Ljava/lang/Throwable;)V getAttribute&(Ljava/lang/String;)Ljava/lang/Object;destroyremoveAttribute(Ljava/lang/String;)V!< **   !"F **+  ! #$%*+M*N,--,:,  ""# $&)'()*4 &'* !*()%*+ ,-%$+M,  N-- ,-.012#4*$ !$()*+,./M**YY78 ;  !01PKF8M4/org/jruby/rack/RackTag$1.class/1= & '() * $+ ,- $. /01this$0Lorg/jruby/rack/RackTag;B(Lorg/jruby/rack/RackTag;Ljavax/servlet/http/HttpServletRequest;)VCodeLineNumberTableLocalVariableTablethis InnerClassesLorg/jruby/rack/RackTag$1;x0'Ljavax/servlet/http/HttpServletRequest; getMethod()Ljava/lang/String; getRequestURI getPathInfogetQueryStringgetServletPath SourceFile RackTag.javaEnclosingMethod2 34  5GETjava/lang/StringBuilder 6 78 9:? ;8 <org/jruby/rack/RackTag$1,javax/servlet/http/HttpServletRequestWrapperorg/jruby/rack/RackTagdoEndTag()I*(Ljavax/servlet/http/HttpServletRequest;)V()V access$000,(Lorg/jruby/rack/RackTag;)Ljava/lang/String;append-(Ljava/lang/String;)Ljava/lang/StringBuilder; access$100toString ? *+*,!  - N$Y**   $2* 2*    - ! !"#$%  PKF8ձ|c ^ org/jruby/rack/RackTag.class^ 1p 8 9 : ; <=> ?@A BC <FG H IJ <K LM NO PQR STUpathLjava/lang/String;params()VCodeLineNumberTableLocalVariableTablethisLorg/jruby/rack/RackTag;setPath(Ljava/lang/String;)V setParamsdoEndTag()Irequest'Ljavax/servlet/http/HttpServletRequest;resultLorg/jruby/rack/RackResponse;factory'Lorg/jruby/rack/RackApplicationFactory;app Lorg/jruby/rack/RackApplication;eLjava/lang/Exception; Exceptions access$000,(Lorg/jruby/rack/RackTag;)Ljava/lang/String;x0 access$100 SourceFile RackTag.java    VWX YZ rack.factory[ \]%org/jruby/rack/RackApplicationFactory ^_org/jruby/rack/RackTag$1 InnerClasses `a%javax/servlet/http/HttpServletRequest bc de fgh ijk l# mnjava/lang/Exceptionjavax/servlet/jsp/JspException oorg/jruby/rack/RackTag#javax/servlet/jsp/tagext/TagSupport pageContextLjavax/servlet/jsp/PageContext;javax/servlet/jsp/PageContextgetServletContext ()Ljavax/servlet/ServletContext;javax/servlet/ServletContext getAttribute&(Ljava/lang/String;)Ljava/lang/Object;getApplication"()Lorg/jruby/rack/RackApplication; getRequest ()Ljavax/servlet/ServletRequest;B(Lorg/jruby/rack/RackTag;Ljavax/servlet/http/HttpServletRequest;)Vorg/jruby/rack/RackApplicationcall=(Ljavax/servlet/ServletRequest;)Lorg/jruby/rack/RackResponse;getOut()Ljavax/servlet/jsp/JspWriter;org/jruby/rack/RackResponsegetBody()Ljava/lang/String;javax/servlet/jsp/JspWriterwritefinishedWithApplication#(Lorg/jruby/rack/RackApplication;)V(Ljava/lang/Throwable;)V!/*  !"#>*+   !$#>*+  !%& l*L+ M Y** N,-:*+,:+, LY+FPPRP\_2 ,#5$F&M'P&\*_(`)i+>,'(5)*J+,C-.` /0l !123/* 4!53/* 4!67E  PKF8org/jruby/rack/rails/PKF8<1org/jruby/rack/SharedRackApplicationFactory.class1E / 0 1 2 345 678 9 2 : ;<=>? realFactory'Lorg/jruby/rack/RackApplicationFactory; application Lorg/jruby/rack/RackApplication;*(Lorg/jruby/rack/RackApplicationFactory;)VCodeLineNumberTableLocalVariableTablethis-Lorg/jruby/rack/SharedRackApplicationFactory;factoryinit!(Ljavax/servlet/ServletContext;)Vex,Lorg/jruby/rack/RackInitializationException;servletContextLjavax/servlet/ServletContext; ExceptionsnewApplication"()Lorg/jruby/rack/RackApplication;getApplicationfinishedWithApplication#(Lorg/jruby/rack/RackApplication;)VappgetErrorApplicationdestroy()V SourceFile!SharedRackApplicationFactory.java ,   &% *org/jruby/rack/RackInitializationException,unable to create shared application instance@ ABjavax/servlet/ServletException C *%D +,+org/jruby/rack/SharedRackApplicationFactoryjava/lang/Object%org/jruby/rack/RackApplicationFactoryjavax/servlet/ServletContextlog*(Ljava/lang/String;Ljava/lang/Throwable;)V(Ljava/lang/Throwable;)Vorg/jruby/rack/RackApplication!F **+   .*+**M+, Y,  $-   ..!"# $%/* # #&%/*' #'(5+)*%4 * .  +,8 *  2 3  -.PKF8бd_4org/jruby/rack/merb/MerbRackApplicationFactory.class_1"   ()VCodeLineNumberTableLocalVariableTablethis0Lorg/jruby/rack/merb/MerbRackApplicationFactory;createApplicationObject9(Lorg/jruby/Ruby;)Lorg/jruby/runtime/builtin/IRubyObject;runtimeLorg/jruby/Ruby; SourceFileMerbRackApplicationFactory.java  require 'jruby/rack/merb'  run JRuby::Rack::MerbFactory.new !.org/jruby/rack/merb/MerbRackApplicationFactory,org/jruby/rack/DefaultRackApplicationFactoryorg/jruby/Ruby evalScriptlet;(Ljava/lang/String;)Lorg/jruby/runtime/builtin/IRubyObject;createRackServletWrapperK(Lorg/jruby/Ruby;Ljava/lang/String;)Lorg/jruby/runtime/builtin/IRubyObject;!  /*    G+W*+   PKF8ڔơ4org/jruby/rack/merb/MerbServletContextListener.classc1   ()VCodeLineNumberTableLocalVariableTablethis0Lorg/jruby/rack/merb/MerbServletContextListener;newApplicationFactory)()Lorg/jruby/rack/RackApplicationFactory; SourceFileMerbServletContextListener.java  +org/jruby/rack/SharedRackApplicationFactory.org/jruby/rack/merb/MerbRackApplicationFactory .org/jruby/rack/merb/MerbServletContextListener)org/jruby/rack/RackServletContextListener*(Lorg/jruby/rack/RackApplicationFactory;)V!  /*    9YY   PKF83mh6org/jruby/rack/rails/RailsRackApplicationFactory.classh1"   ()VCodeLineNumberTableLocalVariableTablethis2Lorg/jruby/rack/rails/RailsRackApplicationFactory;createApplicationObject9(Lorg/jruby/Ruby;)Lorg/jruby/runtime/builtin/IRubyObject;runtimeLorg/jruby/Ruby; SourceFile RailsRackApplicationFactory.java  require 'rack/adapter/rails' !run JRuby::Rack::RailsFactory.new !0org/jruby/rack/rails/RailsRackApplicationFactory,org/jruby/rack/DefaultRackApplicationFactoryorg/jruby/Ruby evalScriptlet;(Ljava/lang/String;)Lorg/jruby/runtime/builtin/IRubyObject;createRackServletWrapperK(Lorg/jruby/Ruby;Ljava/lang/String;)Lorg/jruby/runtime/builtin/IRubyObject;!  /*    G+W*+   PKF8ގ6org/jruby/rack/rails/RailsServletContextListener.class[1   ()VCodeLineNumberTableLocalVariableTablethis2Lorg/jruby/rack/rails/RailsServletContextListener;newApplicationFactory)()Lorg/jruby/rack/RackApplicationFactory; SourceFile RailsServletContextListener.java  ,org/jruby/rack/PoolingRackApplicationFactory0org/jruby/rack/rails/RailsRackApplicationFactory 0org/jruby/rack/rails/RailsServletContextListener)org/jruby/rack/RackServletContextListener*(Lorg/jruby/rack/RackApplicationFactory;)V!  /*    9YY   PKF8_3."org/jruby/webapp/FileServlet.class.1  ()VCodeLineNumberTableLocalVariableTablethisLorg/jruby/webapp/FileServlet; SourceFileFileServlet.java org/jruby/webapp/FileServletorg/jruby/rack/RackServlet!/*     PKF8d_+org/jruby/webapp/RailsContextListener.class_1  ()VCodeLineNumberTableLocalVariableTablethis'Lorg/jruby/webapp/RailsContextListener; SourceFileRailsContextListener.java %org/jruby/webapp/RailsContextListener0org/jruby/rack/rails/RailsServletContextListener!/*     PKF861#org/jruby/webapp/RailsServlet.class11  ()VCodeLineNumberTableLocalVariableTablethisLorg/jruby/webapp/RailsServlet; SourceFileRailsServlet.java org/jruby/webapp/RailsServletorg/jruby/rack/RackServlet!/*     PKF8cgi/PKF8jruby/PKF8rack/PKF8qo( # rack.rb# # Copyright (C) 2007, 2008 Christian Neukirchen # # Rack is freely distributable under the terms of an MIT-style license. # See COPYING or http://www.opensource.org/licenses/mit-license.php. $: << File.expand_path(File.dirname(__FILE__)) # The Rack main module, serving as a namespace for all core Rack # modules and classes. # # All modules meant for use in your application are autoloaded here, # so it should be enough just to require rack.rb in your code. module Rack # The Rack protocol version number implemented. VERSION = [0,1] # Return the Rack protocol version as a dotted string. def self.version VERSION.join(".") end autoload :Builder, "rack/builder" autoload :Cascade, "rack/cascade" autoload :CommonLogger, "rack/commonlogger" autoload :File, "rack/file" autoload :ForwardRequest, "rack/recursive" autoload :Lint, "rack/lint" autoload :Recursive, "rack/recursive" autoload :Reloader, "rack/reloader" autoload :ShowExceptions, "rack/showexceptions" autoload :ShowStatus, "rack/showstatus" autoload :Static, "rack/static" autoload :URLMap, "rack/urlmap" autoload :Utils, "rack/utils" autoload :MockRequest, "rack/mock" autoload :MockResponse, "rack/mock" autoload :Request, "rack/request" autoload :Response, "rack/response" module Auth autoload :Basic, "rack/auth/basic" autoload :AbstractRequest, "rack/auth/abstract/request" autoload :AbstractHandler, "rack/auth/abstract/handler" autoload :OpenID, "rack/auth/openid" module Digest autoload :MD5, "rack/auth/digest/md5" autoload :Nonce, "rack/auth/digest/nonce" autoload :Params, "rack/auth/digest/params" autoload :Request, "rack/auth/digest/request" end end module Session autoload :Cookie, "rack/session/cookie" autoload :Pool, "rack/session/pool" autoload :Memcache, "rack/session/memcache" end # *Adapters* connect Rack with third party web frameworks. # # Rack includes an adapter for Camping, see README for other # frameworks supporting Rack in their code bases. # # Refer to the submodules for framework-specific calling details. module Adapter autoload :Camping, "rack/adapter/camping" end # *Handlers* connect web servers with Rack. # # Rack includes Handlers for Mongrel, WEBrick, FastCGI, CGI, SCGI # and LiteSpeed. # # Handlers usually are activated by calling MyHandler.run(myapp). # A second optional hash can be passed to include server-specific # configuration. module Handler autoload :CGI, "rack/handler/cgi" autoload :FastCGI, "rack/handler/fastcgi" autoload :Mongrel, "rack/handler/mongrel" autoload :WEBrick, "rack/handler/webrick" autoload :LSWS, "rack/handler/lsws" autoload :SCGI, "rack/handler/scgi" end end PKF8 cgi/session/PKF85n !cgi/session/java_servlet_store.rb class CGI #:nodoc:all class Session class JavaServletStore RAILS_SESSION_KEY = "__current_rails_session" def initialize(session, option=nil) @java_request = option["java_servlet_request"] if option unless @java_request raise 'JavaServletStore requires that HttpServletRequest is made available to the session' end @digest = option['digest'] || 'SHA1' @session_data = {} end # Restore session state from the Java session def restore @session_data = {} java_session = @java_request.getSession(false) if java_session java_session.getAttributeNames.each do |k| if k == RAILS_SESSION_KEY marshalled_bytes = java_session.getAttribute(RAILS_SESSION_KEY) if marshalled_bytes data = Marshal.load(String.from_java_bytes(marshalled_bytes)) @session_data.update data if Hash === data end else @session_data[k] = java_session.getAttribute(k) end end end @session_data end # Save session state to the Java session def update java_session = @java_request.getSession(true) hash = @session_data.dup hash.delete_if do |k,v| if String === k case v when String, Numeric, true, false, nil java_session.setAttribute k, v true else if v.respond_to?(:java_object) java_session.setAttribute k, v true else false end end end end unless hash.empty? marshalled_string = Marshal.dump(hash) marshalled_bytes = marshalled_string.to_java_bytes java_session.setAttribute(RAILS_SESSION_KEY, marshalled_bytes) end end # Update and close the Java session entry def close update end # Delete the Java session entry def delete java_session = @java_request.getSession(false) java_session.invalidate if java_session end def generate_digest(data) java_session = @java_request.getSession(true) @secret ||= java_session.getAttribute("__rails_secret") unless @secret @secret = java_session.getId + java_session.getLastAccessedTime.to_s java_session.setAttribute("__rails_secret", @secret) end OpenSSL::HMAC.hexdigest(OpenSSL::Digest::Digest.new(@digest), @secret, data) end # The session state def data @session_data end def []=(k, v) @session_data[k] = v end def [](k) @session_data[k] end def each(&b) @session_data.each(&b) end private # Attempts to redirect any messages to the data object. def method_missing(name, *args, &block) @session_data.send(name, *args, &block) end end end end PKF8 jruby/rack/PKF8B750 jruby/rack.rb0#-- # Copyright 2007-2008 Sun Microsystems, Inc. # This source code is available under the MIT license. # See the file LICENSE.txt for details. #++ require 'rack' require 'time' # some of rack uses Time#rfc822 but doesn't pull this in require 'jruby/rack/servlet_helper' require 'jruby/rack/servlet_ext'PKF8 jruby/rack/merb.rb Srequire 'jruby/rack' require 'cgi/session/java_servlet_store' module JRuby module Rack class MerbServletHelper < ::JRuby::Rack::ServletHelper attr_reader :merb_environment, :merb_root def initialize(servlet_context = nil) super @merb_root = @servlet_context.getInitParameter('merb.root') @merb_root ||= '/WEB-INF' @merb_root = @servlet_context.getRealPath(@merb_root) @merb_environment = @servlet_context.getInitParameter('merb.environment') @merb_environment ||= 'production' end def load_environment load_merb setup_adapter setup_sessions start_merb end def load_merb framework = File.expand_path(File.join(@merb_root, 'framework')) if File.directory?(framework) logger.debug("Trying to load Merb from #{framework}") core = File.join(framework, 'merb-core') if File.directory?(core) $LOAD_PATH.push File.join(core, 'lib') end more = File.join(framework, 'merb-more') if File.directory?(more) Dir.new(more).select {|d| d =~ /merb-/}.each do |d| $LOAD_PATH.push File.join(more, d, 'lib') end end plugins = File.join(framework, 'merb-plugins') if File.directory?(plugins) Dir.new(plugins).select {|d| d =~ /merb_/}.each do |d| $LOAD_PATH.push File.join(plugins, d, 'lib') end end else logger.debug("Didn't find a framework/ directory, falling back to Rubygems") require 'rubygems' end require 'merb-core' require 'merb-core/rack' Merb.frozen! end def setup_adapter logger.debug('Registering Merb servlet adapter') Merb::Rack::Adapter.register %w{servlet}, :Servlet end def setup_sessions logger.debug('Registering Merb servlet sessions') Merb.register_session_type 'servlet', 'jruby/rack/merb', 'Using Java servlet sessions' end def start_merb logger.debug('Starting Merb') Merb.start :merb_root => merb_root, :environment => merb_environment, :adapter => 'servlet' end end class MerbFactory def self.new MerbServletHelper.new.load_environment ::Rack::Builder.new { run ::Merb::Config[:app] }.to_app end end end end # Merb likes to hardcode things into the Merb:: namespace. module Merb module Rack class Servlet def self.start(opts={}) Merb.logger.info("Using Java servlet adapter") if self == Merb::Rack::Servlet Merb.logger.flush end end end module SessionMixin def setup_session Merb.logger.info("Setting Up Java servlet session") opts = {'java_servlet_request' => request.env['java.servlet_request']} request.session = CGI::Session::JavaServletStore.new(nil, opts) request.session.restore end def finalize_session Merb.logger.info("Finalizing Java servlet session") request.session.update end def session_store_type "servlet" end end end PKF8J|jruby/rack/rails.rb#-- # Copyright 2007-2008 Sun Microsystems, Inc. # This source code is available under the MIT license. # See the file LICENSE.txt for details. #++ require 'jruby/rack' module JRuby module Rack class RailsServletHelper < ServletHelper attr_accessor :rails_env, :rails_root def initialize(servlet_context = nil) super @rails_root = @servlet_context.getInitParameter 'rails.root' @rails_root ||= '/WEB-INF' @rails_root = @servlet_context.getRealPath @rails_root @rails_env = @servlet_context.getInitParameter 'rails.env' @rails_env ||= 'production' ENV['RAILS_ROOT'] = @rails_root ENV['RAILS_ENV'] = @rails_env silence_warnings { Object.const_set("PUBLIC_ROOT", public_root) } end def load_environment require 'cgi/session/java_servlet_store' require 'jruby/rack/rails_boot' load File.join(rails_root, 'config', 'environment.rb') require 'dispatcher' require 'jruby/rack/rails_ext' setup_sessions setup_logger end # This hook method is called back from within the mechanism installed # by rails_boot above. We're setting appropriate defaults for the # servlet environment here that can still be overridden (if desired) in # the application's environment files. def boot_for_servlet_environment require 'action_controller' ActionController::Base.page_cache_directory = PUBLIC_ROOT ActionController::Base.session_store = :java_servlet_store ActionView::Base.cache_template_loading = true silence_warnings do ActionView::Helpers::AssetTagHelper.const_set("ASSETS_DIR", PUBLIC_ROOT) ActionView::Helpers::AssetTagHelper.const_set("JAVASCRIPTS_DIR", "#{PUBLIC_ROOT}/javascripts") ActionView::Helpers::AssetTagHelper.const_set("STYLESHEETS_DIR", "#{PUBLIC_ROOT}/stylesheets") end end def setup_sessions if default_sessions? session_options[:database_manager] = java_servlet_store end # Turn off default cookies when using Java sessions if java_sessions? session_options[:no_cookies] = true end end def setup_logger if defined?(::RAILS_DEFAULT_LOGGER) class << ::RAILS_DEFAULT_LOGGER # Make these accessible to wire in the log device public :instance_variable_get, :instance_variable_set end if defined?(ActiveSupport::BufferedLogger) # Rails 2.x old_device = ::RAILS_DEFAULT_LOGGER.instance_variable_get "@log" old_device.close rescue nil ::RAILS_DEFAULT_LOGGER.instance_variable_set "@log", logdev else # Rails 1.x old_device = ::RAILS_DEFAULT_LOGGER.instance_variable_get "@logdev" old_device.close rescue nil ::RAILS_DEFAULT_LOGGER.instance_variable_set "@logdev", Logger::LogDevice.new(logdev) end end end def session_options @session_options ||= SESSION_OPTIONS end def session_options_for_request(env) options = session_options.dup options[:java_servlet_request] = env['java.servlet_request'] options end def java_sessions? session_options[:database_manager] == java_servlet_store end def default_sessions? session_options[:database_manager] == default_store end def default_store defined?(::CGI::Session::PStore) && CGI::Session::PStore end def java_servlet_store CGI::Session::JavaServletStore end def options {:public => public_root, :root => rails_root, :environment => rails_env} end def silence_warnings oldv, $VERBOSE = $VERBOSE, nil begin yield ensure $VERBOSE = oldv end end end class RailsSetup def initialize(app, servlet_helper) @app = app @servlet_helper = servlet_helper end def call(env) env['rails.session_options'] = @servlet_helper.session_options_for_request(env) env["RAILS_RELATIVE_URL_ROOT"] = env['java.servlet_request'].getContextPath @app.call(env) end end class RailsFactory def self.new helper = RailsServletHelper.instance helper.load_environment ::Rack::Builder.new { use RailsSetup, helper run ::Rack::Adapter::Rails.new(helper.options) }.to_app end end end endPKF8cljruby/rack/rails_boot.rb%#-- # Copyright 2007-2008 Sun Microsystems, Inc. # This source code is available under the MIT license. # See the file LICENSE.txt for details. #++ module Rails # This hook code exists to allow us to hook into the Rails boot sequence so # that we can set some additional defaults that are more friendly to the servlet # environment, but still can be overridden by the application in the Rails # initializer. # # Only for Rails 2.0, unfortunately. This code is mildly evil, but we're hoping # the Rails booter code won't change too much. class BootHook def initialize(real_boot) @real_boot = real_boot end def run result = @real_boot.run JRuby::Rack::RailsServletHelper.instance.boot_for_servlet_environment result end def custom_boot end end class Boot # Hook into methods added for Rails::Boot, and redefine Rails.pick_boot. # Only needs to be done once, so remove the method_added hook when done. def self.method_added(meth) class << ::Rails alias_method :original_pick_boot, :pick_boot def pick_boot BootHook.new(original_pick_boot) end end class << self; remove_method :method_added; end end end endPKF86(#jruby/rack/rails_ext.rb##-- # Copyright 2007-2008 Sun Microsystems, Inc. # This source code is available under the MIT license. # See the file LICENSE.txt for details. #++ require 'action_controller' module ActionController class CgiRequest #:nodoc: # Replace session_options writer to merge session options # With ones passed into request (so we can preserve the # java servlet request) def session_options=(opts) if opts == false @session_options = false elsif @session_options @session_options.update(opts) else @session_options = opts end end end class Base def servlet_request request.env['java.servlet_request'] end def forward_to(url) @performed_render = true req = servlet_request response.headers['Forward'] = proc do |resp| req.getRequestDispatcher(url).forward(req, resp) end end end module Rescue # Rails 2.0 static rescue files def render_optional_error_file(status_code) #:nodoc: status = interpret_status(status_code) path = "#{PUBLIC_ROOT}/#{status[0,3]}.html" if File.exists?(path) render :file => path, :status => status else head status end end def rescue_action_in_public(exception) #:nodoc: if respond_to?(:render_optional_error_file) # Rails 2 render_optional_error_file response_code_for_rescue(exception) else # Rails 1 case exception when RoutingError, UnknownAction render_text(IO.read(File.join(PUBLIC_ROOT, '404.html')), "404 Not Found") else render_text(IO.read(File.join(PUBLIC_ROOT, '500.html')), "500 Internal Error") end end end end end module JRuby::Rack SESSION_OPTIONS = ActionController::CgiRequest::DEFAULT_SESSION_OPTIONS end PKF8~ŭjruby/rack/servlet_ext.rbz#-- # Copyright 2007-2008 Sun Microsystems, Inc. # This source code is available under the MIT license. # See the file LICENSE.txt for details. #++ # Ruby-friendly extensions to the servlet API. module Java::JavaxServletHttp::HttpServletRequest # Fetch an attribute from the servlet request. def [](key) getAttribute(key.to_s) end # Set an attribute in the servlet request. def []=(key, val) setAttribute(key.to_s, val) end # Retrieve all the attribute names (keys) from the servlet request. def keys getAttributeNames.to_a end end module Java::JavaxServletHttp::HttpSession # Fetch an attribute from the session. def [](key) getAttribute(key.to_s) end # Set an attribute in the session. def []=(key, val) setAttribute(key.to_s, val) end # Retrieve all the attribute names (keys) from the session. def keys getAttributeNames.to_a end end PKF8Ynijruby/rack/servlet_helper.rbi#-- # Copyright 2007-2008 Sun Microsystems, Inc. # This source code is available under the MIT license. # See the file LICENSE.txt for details. #++ module JRuby module Rack class Response include Java::org.jruby.rack.RackResponse def initialize(arr) @status, @headers, @body = *arr end def getStatus @status end def getHeaders @headers end def getBody b = "" @body.each {|part| b << part } b end def respond(response) if fwd = @headers["Forward"] fwd.call(response) else write_status(response) write_headers(response) write_body(response) end end def write_status(response) response.setStatus(@status.to_i) end def write_headers(response) @headers.each do |k,v| case k when /^Content-Type$/i response.setContentType(v.to_s) when /^Content-Length$/i response.setContentLength(v.to_i) else v.each {|val| response.addHeader(k.to_s, val) } end end end def write_body(response) stream = response.getOutputStream @body.each do |el| stream.write(el.to_java_bytes) end end end class ServletLog def initialize(context = $servlet_context) @context = context end def puts(msg) write msg.to_s end def write(msg) @context.log(msg) end def flush; end def close; end end class ServletHelper attr_reader :public_root, :gem_path def initialize(servlet_context = nil) @servlet_context = servlet_context || $servlet_context @public_root = @servlet_context.getInitParameter 'public.root' @public_root ||= @servlet_context.getInitParameter 'files.prefix' # Goldspike @public_root ||= '/WEB-INF/public' @public_root = "/#{@public_root}" unless @public_root =~ %r{^/} @public_root = @servlet_context.getRealPath @public_root @public_root = @public_root.chomp("/") @gem_path = @servlet_context.getInitParameter 'gem.path' @gem_path ||= '/WEB-INF/gems' @gem_path = @servlet_context.getRealPath @gem_path setup_gems end def logdev @logdev ||= ServletLog.new @servlet_context end def logger @logger ||= begin; require 'logger'; Logger.new(logdev); end end def setup_gems $LOAD_PATH << 'META-INF/jruby.home/lib/ruby/site_ruby/1.8' ENV['GEM_PATH'] = @gem_path end def self.instance @instance ||= self.new end end class Errors EXCEPTION = org.jruby.rack.RackDispatcher::EXCEPTION def initialize(file_server) @file_server = file_server end def call(env) [code = response_code(env), *response_content(env, code)] end def response_code(env) exc = env[EXCEPTION] if exc env['rack.showstatus.detail'] = exc.getMessage if exc.getCause.kind_of?(Java::JavaLang::InterruptedException) 503 else 500 end else 500 end end def response_content(env, code) @responses ||= Hash.new do |h,k| env["PATH_INFO"] = "/#{code}.html" response = @file_server.call(env) body = response[2] unless Array === body newbody = "" body.each do |chunk| newbody << chunk end response[2] = [newbody] end h[k] = response end response = @responses[code] if response[0] != 404 env["rack.showstatus.detail"] = nil response[1..2] else [{}, []] end end end class ErrorsApp def self.new ::Rack::Builder.new { use ::Rack::ShowStatus run Errors.new(::Rack::File.new(ServletHelper.instance.public_root)) }.to_app end end end endPKF8 rack/adapter/PKF8 rack/auth/PKF8p^rack/builder.rbmodule Rack # Rack::Builder implements a small DSL to iteratively construct Rack # applications. # # Example: # # app = Rack::Builder.new { # use Rack::CommonLogger # use Rack::ShowExceptions # map "/lobster" do # use Rack::Lint # run Rack::Lobster.new # end # } # # +use+ adds a middleware to the stack, +run+ dispatches to an application. # You can use +map+ to construct a Rack::URLMap in a convenient way. class Builder def initialize(&block) @ins = [] instance_eval(&block) end def use(middleware, *args, &block) @ins << if block_given? lambda { |app| middleware.new(app, *args, &block) } else lambda { |app| middleware.new(app, *args) } end end def run(app) @ins << app #lambda { |nothing| app } end def map(path, &block) if @ins.last.kind_of? Hash @ins.last[path] = Rack::Builder.new(&block).to_app else @ins << {} map(path, &block) end end def to_app @ins[-1] = Rack::URLMap.new(@ins.last) if Hash === @ins.last inner_app = @ins.last @ins[0...-1].reverse.inject(inner_app) { |a, e| e.call(a) } end def call(env) to_app.call(env) end end end PKF8;Ak8kfrack/cascade.rbfmodule Rack # Rack::Cascade tries an request on several apps, and returns the # first response that is not 404 (or in a list of configurable # status codes). class Cascade attr_reader :apps def initialize(apps, catch=404) @apps = apps @catch = [*catch] end def call(env) status = headers = body = nil raise ArgumentError, "empty cascade" if @apps.empty? @apps.each { |app| begin status, headers, body = app.call(env) break unless @catch.include?(status.to_i) end } [status, headers, body] end end end PKF8;ķrack/commonlogger.rb]module Rack # Rack::CommonLogger forwards every request to an +app+ given, and # logs a line in the Apache common log format to the +logger+, or # rack.errors by default. class CommonLogger def initialize(app, logger=nil) @app = app @logger = logger end def call(env) dup._call(env) end def _call(env) @env = env @logger ||= self @time = Time.now @status, @header, @body = @app.call(env) [@status, @header, self] end # By default, log to rack.errors. def <<(str) @env["rack.errors"].write(str) @env["rack.errors"].flush end def each length = 0 @body.each { |part| length += part.size yield part } @now = Time.now # Common Log Format: http://httpd.apache.org/docs/1.3/logs.html#common # lilith.local - - [07/Aug/2006 23:58:02] "GET / HTTP/1.1" 500 - # %{%s - %s [%s] "%s %s%s %s" %d %s\n} % @logger << %{%s - %s [%s] "%s %s%s %s" %d %s %0.4f\n} % [@env["REMOTE_ADDR"] || "-", @env["REMOTE_USER"] || "-", @now.strftime("%d/%b/%Y %H:%M:%S"), @env["REQUEST_METHOD"], @env["PATH_INFO"], @env["QUERY_STRING"].empty? ? "" : "?"+@env["QUERY_STRING"], @env["HTTP_VERSION"], @status.to_s[0..3], (length.zero? ? "-" : length.to_s), @now - @time ] end end end PKF8GO rack/file.rb Dmodule Rack # Rack::File serves files below the +root+ given, according to the # path info of the Rack request. # # Handlers can detect if bodies are a Rack::File, and use mechanisms # like sendfile on the +path+. class File attr_accessor :root attr_accessor :path def initialize(root) @root = root end def call(env) dup._call(env) end F = ::File def _call(env) if env["PATH_INFO"].include? ".." return [403, {"Content-Type" => "text/plain"}, ["Forbidden\n"]] end @path = F.join(@root, Utils.unescape(env["PATH_INFO"])) ext = F.extname(@path)[1..-1] if F.file?(@path) && F.readable?(@path) [200, { "Last-Modified" => F.mtime(@path).rfc822, "Content-Type" => MIME_TYPES[ext] || "text/plain", "Content-Length" => F.size(@path).to_s }, self] else return [404, {"Content-Type" => "text/plain"}, ["File not found: #{env["PATH_INFO"]}\n"]] end end def each F.open(@path, "rb") { |file| while part = file.read(8192) yield part end } end # :stopdoc: # From WEBrick. MIME_TYPES = { "ai" => "application/postscript", "asc" => "text/plain", "avi" => "video/x-msvideo", "bin" => "application/octet-stream", "bmp" => "image/bmp", "class" => "application/octet-stream", "cer" => "application/pkix-cert", "crl" => "application/pkix-crl", "crt" => "application/x-x509-ca-cert", #"crl" => "application/x-pkcs7-crl", "css" => "text/css", "dms" => "application/octet-stream", "doc" => "application/msword", "dvi" => "application/x-dvi", "eps" => "application/postscript", "etx" => "text/x-setext", "exe" => "application/octet-stream", "gif" => "image/gif", "htm" => "text/html", "html" => "text/html", "jpe" => "image/jpeg", "jpeg" => "image/jpeg", "jpg" => "image/jpeg", "js" => "text/javascript", "lha" => "application/octet-stream", "lzh" => "application/octet-stream", "mov" => "video/quicktime", "mpe" => "video/mpeg", "mpeg" => "video/mpeg", "mpg" => "video/mpeg", "pbm" => "image/x-portable-bitmap", "pdf" => "application/pdf", "pgm" => "image/x-portable-graymap", "png" => "image/png", "pnm" => "image/x-portable-anymap", "ppm" => "image/x-portable-pixmap", "ppt" => "application/vnd.ms-powerpoint", "ps" => "application/postscript", "qt" => "video/quicktime", "ras" => "image/x-cmu-raster", "rb" => "text/plain", "rd" => "text/plain", "rtf" => "application/rtf", "sgm" => "text/sgml", "sgml" => "text/sgml", "tif" => "image/tiff", "tiff" => "image/tiff", "txt" => "text/plain", "xbm" => "image/x-xbitmap", "xls" => "application/vnd.ms-excel", "xml" => "text/xml", "xpm" => "image/x-xpixmap", "xwd" => "image/x-xwindowdump", "zip" => "application/zip", } # :startdoc: end end PKF8 rack/handler/PKF8X:S: rack/lint.rbS:module Rack # Rack::Lint validates your application and the requests and # responses according to the Rack spec. class Lint def initialize(app) @app = app end # :stopdoc: class LintError < RuntimeError; end module Assertion def assert(message, &block) unless block.call raise LintError, message end end end include Assertion ## This specification aims to formalize the Rack protocol. You ## can (and should) use Rack::Lint to enforce it. ## ## When you develop middleware, be sure to add a Lint before and ## after to catch all mistakes. ## = Rack applications ## A Rack application is an Ruby object (not a class) that ## responds to +call+. def call(env=nil) ## It takes exactly one argument, the *environment* assert("No env given") { env } check_env env env['rack.input'] = InputWrapper.new(env['rack.input']) env['rack.errors'] = ErrorWrapper.new(env['rack.errors']) ## and returns an Array of exactly three values: status, headers, @body = @app.call(env) ## The *status*, check_status status ## the *headers*, check_headers headers ## and the *body*. check_content_type status, headers [status, headers, self] end ## == The Environment def check_env(env) ## The environment must be an true instance of Hash (no ## subclassing allowed) that includes CGI-like headers. ## The application is free to modify the environment. assert("env #{env.inspect} is not a Hash, but #{env.class}") { env.instance_of? Hash } ## ## The environment is required to include these variables ## (adopted from PEP333), except when they'd be empty, but see ## below. ## REQUEST_METHOD:: The HTTP request method, such as ## "GET" or "POST". This cannot ever ## be an empty string, and so is ## always required. ## SCRIPT_NAME:: The initial portion of the request ## URL's "path" that corresponds to the ## application object, so that the ## application knows its virtual ## "location". This may be an empty ## string, if the application corresponds ## to the "root" of the server. ## PATH_INFO:: The remainder of the request URL's ## "path", designating the virtual ## "location" of the request's target ## within the application. This may be an ## empty string, if the request URL targets ## the application root and does not have a ## trailing slash. ## QUERY_STRING:: The portion of the request URL that ## follows the ?, if any. May be ## empty, but is always required! ## SERVER_NAME, SERVER_PORT:: When combined with SCRIPT_NAME and PATH_INFO, these variables can be used to complete the URL. Note, however, that HTTP_HOST, if present, should be used in preference to SERVER_NAME for reconstructing the request URL. SERVER_NAME and SERVER_PORT can never be empty strings, and so are always required. ## HTTP_ Variables:: Variables corresponding to the ## client-supplied HTTP request ## headers (i.e., variables whose ## names begin with HTTP_). The ## presence or absence of these ## variables should correspond with ## the presence or absence of the ## appropriate HTTP header in the ## request. ## In addition to this, the Rack environment must include these ## Rack-specific variables: ## rack.version:: The Array [0,1], representing this version of Rack. ## rack.url_scheme:: +http+ or +https+, depending on the request URL. ## rack.input:: See below, the input stream. ## rack.errors:: See below, the error stream. ## rack.multithread:: true if the application object may be simultaneously invoked by another thread in the same process, false otherwise. ## rack.multiprocess:: true if an equivalent application object may be simultaneously invoked by another process, false otherwise. ## rack.run_once:: true if the server expects (but does not guarantee!) that the application will only be invoked this one time during the life of its containing process. Normally, this will only be true for a server based on CGI (or something similar). ## The server or the application can store their own data in the ## environment, too. The keys must contain at least one dot, ## and should be prefixed uniquely. The prefix rack. ## is reserved for use with the Rack core distribution and must ## not be used otherwise. ## %w[REQUEST_METHOD SERVER_NAME SERVER_PORT QUERY_STRING rack.version rack.input rack.errors rack.multithread rack.multiprocess rack.run_once].each { |header| assert("env missing required key #{header}") { env.include? header } } ## The environment must not contain the keys ## HTTP_CONTENT_TYPE or HTTP_CONTENT_LENGTH ## (use the versions without HTTP_). %w[HTTP_CONTENT_TYPE HTTP_CONTENT_LENGTH].each { |header| assert("env contains #{header}, must use #{header[5,-1]}") { not env.include? header } } ## The CGI keys (named without a period) must have String values. env.each { |key, value| next if key.include? "." # Skip extensions assert("env variable #{key} has non-string value #{value.inspect}") { value.instance_of? String } } ## ## There are the following restrictions: ## * rack.version must be an array of Integers. assert("rack.version must be an Array, was #{env["rack.version"].class}") { env["rack.version"].instance_of? Array } ## * rack.url_scheme must either be +http+ or +https+. assert("rack.url_scheme unknown: #{env["rack.url_scheme"].inspect}") { %w[http https].include? env["rack.url_scheme"] } ## * There must be a valid input stream in rack.input. check_input env["rack.input"] ## * There must be a valid error stream in rack.errors. check_error env["rack.errors"] ## * The REQUEST_METHOD must be one of +GET+, +POST+, +PUT+, ## +DELETE+, +HEAD+, +OPTIONS+, +TRACE+. assert("REQUEST_METHOD unknown: #{env["REQUEST_METHOD"]}") { %w[GET POST PUT DELETE HEAD OPTIONS TRACE].include?(env["REQUEST_METHOD"]) } ## * The SCRIPT_NAME, if non-empty, must start with / assert("SCRIPT_NAME must start with /") { !env.include?("SCRIPT_NAME") || env["SCRIPT_NAME"] == "" || env["SCRIPT_NAME"] =~ /\A\// } ## * The PATH_INFO, if non-empty, must start with / assert("PATH_INFO must start with /") { !env.include?("PATH_INFO") || env["PATH_INFO"] == "" || env["PATH_INFO"] =~ /\A\// } ## * The CONTENT_LENGTH, if given, must consist of digits only. assert("Invalid CONTENT_LENGTH: #{env["CONTENT_LENGTH"]}") { !env.include?("CONTENT_LENGTH") || env["CONTENT_LENGTH"] =~ /\A\d+\z/ } ## * One of SCRIPT_NAME or PATH_INFO must be ## set. PATH_INFO should be / if ## SCRIPT_NAME is empty. assert("One of SCRIPT_NAME or PATH_INFO must be set (make PATH_INFO '/' if SCRIPT_NAME is empty)") { env["SCRIPT_NAME"] || env["PATH_INFO"] } ## SCRIPT_NAME never should be /, but instead be empty. assert("SCRIPT_NAME cannot be '/', make it '' and PATH_INFO '/'") { env["SCRIPT_NAME"] != "/" } end ## === The Input Stream def check_input(input) ## The input stream must respond to +gets+, +each+ and +read+. [:gets, :each, :read].each { |method| assert("rack.input #{input} does not respond to ##{method}") { input.respond_to? method } } end class InputWrapper include Assertion def initialize(input) @input = input end ## * +gets+ must be called without arguments and return a string, ## or +nil+ on EOF. def gets(*args) assert("rack.input#gets called with arguments") { args.size == 0 } v = @input.gets assert("rack.input#gets didn't return a String") { v.nil? or v.instance_of? String } v end ## * +read+ must be called without or with one integer argument ## and return a string, or +nil+ on EOF. def read(*args) assert("rack.input#read called with too many arguments") { args.size <= 1 } if args.size == 1 assert("rack.input#read called with non-integer argument") { args.first.kind_of? Integer } end v = @input.read(*args) assert("rack.input#read didn't return a String") { v.nil? or v.instance_of? String } v end ## * +each+ must be called without arguments and only yield Strings. def each(*args) assert("rack.input#each called with arguments") { args.size == 0 } @input.each { |line| assert("rack.input#each didn't yield a String") { line.instance_of? String } yield line } end ## * +close+ must never be called on the input stream. def close(*args) assert("rack.input#close must not be called") { false } end end ## === The Error Stream def check_error(error) ## The error stream must respond to +puts+, +write+ and +flush+. [:puts, :write, :flush].each { |method| assert("rack.error #{error} does not respond to ##{method}") { error.respond_to? method } } end class ErrorWrapper include Assertion def initialize(error) @error = error end ## * +puts+ must be called with a single argument that responds to +to_s+. def puts(str) @error.puts str end ## * +write+ must be called with a single argument that is a String. def write(str) assert("rack.errors#write not called with a String") { str.instance_of? String } @error.write str end ## * +flush+ must be called without arguments and must be called ## in order to make the error appear for sure. def flush @error.flush end ## * +close+ must never be called on the error stream. def close(*args) assert("rack.errors#close must not be called") { false } end end ## == The Response ## === The Status def check_status(status) ## The status, if parsed as integer (+to_i+), must be bigger than 100. assert("Status must be >100 seen as integer") { status.to_i > 100 } end ## === The Headers def check_headers(header) ## The header must respond to each, and yield values of key and value. assert("header should respond to #each") { header.respond_to? :each } header.each { |key, value| ## The header keys must be Strings. assert("header key must be a string, was #{key.class}") { key.instance_of? String } ## The header must not contain a +Status+ key, assert("header must not contain Status") { key.downcase != "status" } ## contain keys with : or newlines in their name, assert("header names must not contain : or \\n") { key !~ /[:\n]/ } ## contain keys names that end in - or _, assert("header names must not end in - or _") { key !~ /[-_]\z/ } ## but only contain keys that consist of ## letters, digits, _ or - and start with a letter. assert("invalid header name: #{key}") { key =~ /\A[a-zA-Z][a-zA-Z0-9_-]*\z/ } ## ## The values of the header must respond to #each. assert("header values must respond to #each") { value.respond_to? :each } value.each { |item| ## The values passed on #each must be Strings assert("header values must consist of Strings") { item.instance_of?(String) } ## and not contain characters below 037. assert("invalid header value #{key}: #{item.inspect}") { item !~ /[\000-\037]/ } } } end ## === The Content-Type def check_content_type(status, headers) headers.each { |key, value| ## There must be a Content-Type, except when the ## +Status+ is 204 or 304, in which case there must be none ## given. if key.downcase == "content-type" assert("Content-Type header found in #{status} response, not allowed"){ not [204, 304].include? status.to_i } return end } assert("No Content-Type header found") { [201, 204, 304].include? status.to_i } end ## === The Body def each @closed = false ## The Body must respond to #each @body.each { |part| ## and must only yield String values. assert("Body yielded non-string value #{part.inspect}") { part.instance_of? String } yield part } ## ## If the Body responds to #close, it will be called after iteration. # XXX howto: assert("Body has not been closed") { @closed } ## ## The Body commonly is an Array of Strings, the application ## instance itself, or a File-like object. end def close @closed = true @body.close if @body.respond_to?(:close) end # :startdoc: end end ## == Thanks ## Some parts of this specification are adopted from PEP333: Python ## Web Server Gateway Interface ## v1.0 (http://www.python.org/dev/peps/pep-0333/). I'd like to thank ## everyone involved in that effort. PKF8brack/lobster.rbrequire 'zlib' require 'rack/request' require 'rack/response' module Rack # Paste has a Pony, Rack has a Lobster! class Lobster LobsterString = Zlib::Inflate.inflate("eJx9kEEOwyAMBO99xd7MAcytUhPlJyj2 P6jy9i4k9EQyGAnBarEXeCBqSkntNXsi/ZCvC48zGQoZKikGrFMZvgS5ZHd+aGWVuWwhVF0 t1drVmiR42HcWNz5w3QanT+2gIvTVCiE1lm1Y0eU4JGmIIbaKwextKn8rvW+p5PIwFl8ZWJ I8jyiTlhTcYXkekJAzTyYN6E08A+dk8voBkAVTJQ==".delete("\n ").unpack("m*")[0]) LambdaLobster = lambda { |env| if env["QUERY_STRING"].include?("flip") lobster = LobsterString.split("\n"). map { |line| line.ljust(42).reverse }. join("\n") href = "?" else lobster = LobsterString href = "?flip" end [200, {"Content-Type" => "text/html"}, ["Lobstericious!", "
", lobster, "
", "flip!"] ] } def call(env) req = Request.new(env) if req.GET["flip"] == "left" lobster = LobsterString.split("\n"). map { |line| line.ljust(42).reverse }. join("\n") href = "?flip=right" elsif req.GET["flip"] == "crash" raise "Lobster crashed" else lobster = LobsterString href = "?flip=left" end Response.new.finish do |res| res.write "Lobstericious!" res.write "
"
        res.write lobster
        res.write "
" res.write "

flip!

" res.write "

crash!

" end end end end if $0 == __FILE__ require 'rack' require 'rack/showexceptions' Rack::Handler::WEBrick.run \ Rack::ShowExceptions.new(Rack::Lint.new(Rack::Lobster.new)), :Port => 9292 end PKF83Ixs rack/mock.rbsrequire 'uri' require 'stringio' require 'rack/lint' require 'rack/utils' require 'rack/response' module Rack # Rack::MockRequest helps testing your Rack application without # actually using HTTP. # # After performing a request on a URL with get/post/put/delete, it # returns a MockResponse with useful helper methods for effective # testing. # # You can pass a hash with additional configuration to the # get/post/put/delete. # :input:: A String or IO-like to be used as rack.input. # :fatal:: Raise a FatalWarning if the app writes to rack.errors. # :lint:: If true, wrap the application in a Rack::Lint. class MockRequest class FatalWarning < RuntimeError end class FatalWarner def puts(warning) raise FatalWarning, warning end def write(warning) raise FatalWarning, warning end def flush end def string "" end end DEFAULT_ENV = { "rack.version" => [0,1], "rack.input" => StringIO.new, "rack.errors" => StringIO.new, "rack.multithread" => true, "rack.multiprocess" => true, "rack.run_once" => false, } def initialize(app) @app = app end def get(uri, opts={}) request("GET", uri, opts) end def post(uri, opts={}) request("POST", uri, opts) end def put(uri, opts={}) request("PUT", uri, opts) end def delete(uri, opts={}) request("DELETE", uri, opts) end def request(method="GET", uri="", opts={}) env = self.class.env_for(uri, opts.merge(:method => method)) if opts[:lint] app = Rack::Lint.new(@app) else app = @app end errors = env["rack.errors"] MockResponse.new(*(app.call(env) + [errors])) end # Return the Rack environment used for a request to +uri+. def self.env_for(uri="", opts={}) uri = URI(uri) env = DEFAULT_ENV.dup env["REQUEST_METHOD"] = opts[:method] || "GET" env["SERVER_NAME"] = uri.host || "example.org" env["SERVER_PORT"] = uri.port ? uri.port.to_s : "80" env["QUERY_STRING"] = uri.query.to_s env["PATH_INFO"] = (!uri.path || uri.path.empty?) ? "/" : uri.path env["rack.url_scheme"] = uri.scheme || "http" env["SCRIPT_NAME"] = opts[:script_name] || "" if opts[:fatal] env["rack.errors"] = FatalWarner.new else env["rack.errors"] = StringIO.new end opts[:input] ||= "" if String === opts[:input] env["rack.input"] = StringIO.new(opts[:input]) else env["rack.input"] = opts[:input] end opts.each { |field, value| env[field] = value if String === field } env end end # Rack::MockResponse provides useful helpers for testing your apps. # Usually, you don't create the MockResponse on your own, but use # MockRequest. class MockResponse def initialize(status, headers, body, errors=StringIO.new("")) @status = status.to_i @original_headers = headers @headers = Rack::Utils::HeaderHash.new headers.each { |field, values| values.each { |value| @headers[field] = value } } @body = "" body.each { |part| @body << part } @errors = errors.string end # Status attr_reader :status # Headers attr_reader :headers, :original_headers def [](field) headers[field] end # Body attr_reader :body def =~(other) @body =~ other end def match(other) @body.match other end # Errors attr_accessor :errors include Response::Helpers end end PKF8yN<rack/recursive.rbOrequire 'uri' module Rack # Rack::ForwardRequest gets caught by Rack::Recursive and redirects # the current request to the app at +url+. # # raise ForwardRequest.new("/not-found") # class ForwardRequest < Exception attr_reader :url, :env def initialize(url, env={}) @url = URI(url) @env = env @env["PATH_INFO"] = @url.path @env["QUERY_STRING"] = @url.query if @url.query @env["HTTP_HOST"] = @url.host if @url.host @env["HTTP_PORT"] = @url.port if @url.port @env["rack.url_scheme"] = @url.scheme if @url.scheme super "forwarding to #{url}" end end # Rack::Recursive allows applications called down the chain to # include data from other applications (by using # rack['rack.recursive.include'][...] or raise a # ForwardRequest to redirect internally. class Recursive def initialize(app) @app = app end def call(env) @script_name = env["SCRIPT_NAME"] @app.call(env.merge('rack.recursive.include' => method(:include))) rescue ForwardRequest => req call(env.merge(req.env)) end def include(env, path) unless path.index(@script_name) == 0 && (path[@script_name.size] == ?/ || path[@script_name.size].nil?) raise ArgumentError, "can only include below #{@script_name}, not #{path}" end env = env.merge("PATH_INFO" => path, "SCRIPT_NAME" => @script_name, "REQUEST_METHOD" => "GET", "CONTENT_LENGTH" => "0", "CONTENT_TYPE" => "", "rack.input" => StringIO.new("")) @app.call(env) end end end PKF8.rack/reloader.rb require 'thread' module Rack # Rack::Reloader checks on every request, but at most every +secs+ # seconds, if a file loaded changed, and reloads it, logging to # rack.errors. # # It is recommended you use ShowExceptions to catch SyntaxErrors etc. class Reloader def initialize(app, secs=10) @app = app @secs = secs # reload every @secs seconds max @last = Time.now end def call(env) if Time.now > @last + @secs Thread.exclusive { reload!(env['rack.errors']) @last = Time.now } end @app.call(env) end def reload!(stderr=STDERR) need_reload = $LOADED_FEATURES.find_all { |loaded| begin if loaded =~ /\A[.\/]/ # absolute filename or 1.9 abs = loaded else abs = $LOAD_PATH.map { |path| ::File.join(path, loaded) }. find { |file| ::File.exist? file } end if abs ::File.mtime(abs) > @last - @secs rescue false else false end end } need_reload.each { |l| $LOADED_FEATURES.delete l } need_reload.each { |to_load| begin if require to_load stderr.puts "#{self.class}: reloaded `#{to_load}'" end rescue LoadError, SyntaxError => e raise e # Possibly ShowExceptions end } stderr.flush need_reload end end end PKF8Ewrack/request.rbFrequire 'rack/utils' module Rack # Rack::Request provides a convenient interface to a Rack # environment. It is stateless, the environment +env+ passed to the # constructor will be directly modified. # # req = Rack::Request.new(env) # req.post? # req.params["data"] class Request # The environment of the request. attr_reader :env def initialize(env) @env = env end def body; @env["rack.input"] end def scheme; @env["rack.url_scheme"] end def script_name; @env["SCRIPT_NAME"].to_s end def path_info; @env["PATH_INFO"].to_s end def port; @env["SERVER_PORT"].to_i end def request_method; @env["REQUEST_METHOD"] end def query_string; @env["QUERY_STRING"].to_s end def host # Remove port number. (@env["HTTP_HOST"] || @env["SERVER_NAME"]).gsub(/:\d+\z/, '') end def script_name=(s); @env["SCRIPT_NAME"] = s.to_s end def path_info=(s); @env["PATH_INFO"] = s.to_s end def get?; request_method == "GET" end def post?; request_method == "POST" end def put?; request_method == "PUT" end def delete?; request_method == "DELETE" end # Returns the data recieved in the query string. def GET if @env["rack.request.query_string"] == query_string @env["rack.request.query_hash"] else @env["rack.request.query_string"] = query_string @env["rack.request.query_hash"] = Utils.parse_query(query_string) end end # Returns the data recieved in the request body. # # This method support both application/x-www-form-urlencoded and # multipart/form-data. def POST if @env["rack.request.form_input"] == @env["rack.input"] @env["rack.request.form_hash"] else @env["rack.request.form_input"] = @env["rack.input"] unless @env["rack.request.form_hash"] = Utils::Multipart.parse_multipart(env) @env["rack.request.form_vars"] = @env["rack.input"].read @env["rack.request.form_hash"] = Utils.parse_query(@env["rack.request.form_vars"]) end @env["rack.request.form_hash"] end end # The union of GET and POST data. def params self.GET.update(self.POST) end # shortcut for request.params[key] def [](key) params[key.to_s] end # shortcut for request.params[key] = value def []=(key, value) params[key.to_s] = value end # like Hash#values_at def values_at(*keys) keys.map{|key| params[key] } end # the referer of the client or '/' def referer @env['HTTP_REFERER'] || '/' end alias referrer referer def cookies return {} unless @env["HTTP_COOKIE"] if @env["rack.request.cookie_string"] == @env["HTTP_COOKIE"] @env["rack.request.cookie_hash"] else @env["rack.request.cookie_string"] = @env["HTTP_COOKIE"] # According to RFC 2109: # If multiple cookies satisfy the criteria above, they are ordered in # the Cookie header such that those with more specific Path attributes # precede those with less specific. Ordering with respect to other # attributes (e.g., Domain) is unspecified. @env["rack.request.cookie_hash"] = Utils.parse_query(@env["rack.request.cookie_string"], ';,').inject({}) {|h,(k,v)| h[k] = Array === v ? v.first : v h } end end def xhr? @env["HTTP_X_REQUESTED_WITH"] == "XMLHttpRequest" end # Tries to return a remake of the original request URL as a string. def url url = scheme + "://" url << host if scheme == "https" && port != 443 || scheme == "http" && port != 80 url << ":#{port}" end url << fullpath url end def fullpath path = script_name + path_info path << "?" << query_string unless query_string.empty? path end end end PKF8@h?:rack/response.rb:require 'rack/request' require 'rack/utils' module Rack # Rack::Response provides a convenient interface to create a Rack # response. # # It allows setting of headers and cookies, and provides useful # defaults (a OK response containing HTML). # # You can use Response#write to iteratively generate your response, # but note that this is buffered by Rack::Response until you call # +finish+. +finish+ however can take a block inside which calls to # +write+ are syncronous with the Rack response. # # Your application's +call+ should end returning Response#finish. class Response def initialize(body=[], status=200, header={}, &block) @status = status @header = Utils::HeaderHash.new({"Content-Type" => "text/html"}. merge(header)) @writer = lambda { |x| @body << x } @block = nil @body = [] if body.respond_to? :to_str write body.to_str elsif body.respond_to?(:each) body.each { |part| write part.to_s } else raise TypeError, "stringable or iterable required" end yield self if block_given? end attr_reader :header attr_accessor :status, :body def [](key) header[key] end def []=(key, value) header[key] = value end def set_cookie(key, value) case value when Hash domain = "; domain=" + value[:domain] if value[:domain] path = "; path=" + value[:path] if value[:path] # According to RFC 2109, we need dashes here. # N.B.: cgi.rb uses spaces... expires = "; expires=" + value[:expires].clone.gmtime. strftime("%a, %d-%b-%Y %H:%M:%S GMT") if value[:expires] value = value[:value] end value = [value] unless Array === value cookie = Utils.escape(key) + "=" + value.map { |v| Utils.escape v }.join("&") + "#{domain}#{path}#{expires}" case self["Set-Cookie"] when Array self["Set-Cookie"] << cookie when String self["Set-Cookie"] = [self["Set-Cookie"], cookie] when nil self["Set-Cookie"] = cookie end end def delete_cookie(key, value={}) unless Array === self["Set-Cookie"] self["Set-Cookie"] = [self["Set-Cookie"]].compact end self["Set-Cookie"].reject! { |cookie| cookie =~ /\A#{Utils.escape(key)}=/ } set_cookie(key, {:value => '', :path => nil, :domain => nil, :expires => Time.at(0) }.merge(value)) end def finish(&block) @block = block if [204, 304].include?(status.to_i) header.delete "Content-Type" [status.to_i, header.to_hash, []] else [status.to_i, header.to_hash, self] end end alias to_a finish # For *response def each(&callback) @body.each(&callback) @writer = callback @block.call(self) if @block end def write(str) @writer.call str.to_s str end def close body.close if body.respond_to?(:close) end def empty? @block == nil && @body.empty? end alias headers header module Helpers def invalid?; @status < 100 || @status >= 600; end def informational?; @status >= 100 && @status < 200; end def successful?; @status >= 200 && @status < 300; end def redirection?; @status >= 300 && @status < 400; end def client_error?; @status >= 400 && @status < 500; end def server_error?; @status >= 500 && @status < 600; end def ok?; @status == 200; end def forbidden?; @status == 403; end def not_found?; @status == 404; end def redirect?; [301, 302, 303, 307].include? @status; end def empty?; [201, 204, 304].include? @status; end # Headers attr_reader :headers, :original_headers def include?(header) !!headers[header] end def content_type headers["Content-Type"] end def content_length cl = headers["Content-Length"] cl ? cl.to_i : cl end def location headers["Location"] end end include Helpers end end PKF8 rack/session/PKF8+**rack/showexceptions.rb*Qrequire 'ostruct' require 'erb' require 'rack/request' module Rack # Rack::ShowExceptions catches all exceptions raised from the app it # wraps. It shows a useful backtrace with the sourcefile and # clickable context, the whole Rack environment and the request # data. # # Be careful when you use this on public-facing sites as it could # reveal information helpful to attackers. class ShowExceptions CONTEXT = 7 def initialize(app) @app = app @template = ERB.new(TEMPLATE) end def call(env) @app.call(env) rescue StandardError, LoadError, SyntaxError => e [500, {"Content-Type" => "text/html"}, pretty(env, e)] end def pretty(env, exception) req = Rack::Request.new(env) path = (req.script_name + req.path_info).squeeze("/") frames = exception.backtrace.map { |line| frame = OpenStruct.new if line =~ /(.*?):(\d+)(:in `(.*)')?/ frame.filename = $1 frame.lineno = $2.to_i frame.function = $4 begin lineno = frame.lineno-1 lines = ::File.readlines(frame.filename) frame.pre_context_lineno = [lineno-CONTEXT, 0].max frame.pre_context = lines[frame.pre_context_lineno...lineno] frame.context_line = lines[lineno].chomp frame.post_context_lineno = [lineno+CONTEXT, lines.size].min frame.post_context = lines[lineno+1..frame.post_context_lineno] rescue end frame else nil end }.compact env["rack.errors"].puts "#{exception.class}: #{exception.message}" env["rack.errors"].puts exception.backtrace.map { |l| "\t" + l } env["rack.errors"].flush [@template.result(binding)] end def h(obj) # :nodoc: case obj when String Utils.escape_html(obj) else Utils.escape_html(obj.inspect) end end # :stopdoc: # adapted from Django # Copyright (c) 2005, the Lawrence Journal-World # Used under the modified BSD license: # http://www.xfree86.org/3.3.6/COPYRIGHT2.html#5 TEMPLATE = <<'HTML' <%=h exception.class %> at <%=h path %>

<%=h exception.class %> at <%=h path %>

<%=h exception.message %>

Ruby <%=h frames.first.filename %>: in <%=h frames.first.function %>, line <%=h frames.first.lineno %>
Web <%=h req.request_method %> <%=h(req.host + path)%>

Jump to:

Traceback (innermost first)

    <% frames.each { |frame| %>
  • <%=h frame.filename %>: in <%=h frame.function %> <% if frame.context_line %>
    <% if frame.pre_context %>
      <% frame.pre_context.each { |line| %>
    1. <%=h line %>
    2. <% } %>
    <% end %>
    1. <%=h frame.context_line %>...
    <% if frame.post_context %>
      <% frame.post_context.each { |line| %>
    1. <%=h line %>
    2. <% } %>
    <% end %>
    <% end %>
  • <% } %>

Request information

GET

<% unless req.GET.empty? %> <% req.GET.sort_by { |k, v| k.to_s }.each { |key, val| %> <% } %>
Variable Value
<%=h key %>
<%=h val.inspect %>
<% else %>

No GET data.

<% end %>

POST

<% unless req.POST.empty? %> <% req.POST.sort_by { |k, v| k.to_s }.each { |key, val| %> <% } %>
Variable Value
<%=h key %>
<%=h val.inspect %>
<% else %>

No POST data.

<% end %> <% unless req.cookies.empty? %> <% req.cookies.each { |key, val| %> <% } %>
Variable Value
<%=h key %>
<%=h val.inspect %>
<% else %>

No cookie data.

<% end %>

Rack ENV

<% env.sort_by { |k, v| k.to_s }.each { |key, val| %> <% } %>
Variable Value
<%=h key %>
<%=h val %>

You're seeing this error because you use Rack::ShowException.

HTML # :startdoc: end end PKF8( rack/showstatus.rb require 'erb' require 'rack/request' require 'rack/utils' module Rack # Rack::ShowStatus catches all empty responses the app it wraps and # replaces them with a site explaining the error. # # Additional details can be put into rack.showstatus.detail # and will be shown as HTML. If such details exist, the error page # is always rendered, even if the reply was not empty. class ShowStatus def initialize(app) @app = app @template = ERB.new(TEMPLATE) end def call(env) status, headers, body = @app.call(env) # client or server error, or explicit message if status.to_i >= 400 && (body.empty? rescue false) || env["rack.showstatus.detail"] req = Rack::Request.new(env) message = Rack::Utils::HTTP_STATUS_CODES[status.to_i] || status.to_s detail = env["rack.showstatus.detail"] || message [status, headers.merge("Content-Type" => "text/html"), [@template.result(binding)]] else [status, headers, body] end end def h(obj) # :nodoc: case obj when String Utils.escape_html(obj) else Utils.escape_html(obj.inspect) end end # :stopdoc: # adapted from Django # Copyright (c) 2005, the Lawrence Journal-World # Used under the modified BSD license: # http://www.xfree86.org/3.3.6/COPYRIGHT2.html#5 TEMPLATE = <<'HTML' <%=h message %> at <%=h req.script_name + req.path_info %>

<%=h message %> (<%= status.to_i %>)

Request Method: <%=h req.request_method %>
Request URL: <%=h req.url %>

<%= detail %>

You're seeing this error because you use Rack::ShowStatus.

HTML # :startdoc: end end PKF8cbrack/static.rbtmodule Rack # The Rack::Static middleware intercepts requests for static files # (javascript files, images, stylesheets, etc) based on the url prefixes # passed in the options, and serves them using a Rack::File object. This # allows a Rack stack to serve both static and dynamic content. # # Examples: # use Rack::Static, :urls => ["/media"] # will serve all requests beginning with /media from the "media" folder # located in the current directory (ie media/*). # # use Rack::Static, :urls => ["/css", "/images"], :root => "public" # will serve all requests beginning with /css or /images from the folder # "public" in the current directory (ie public/css/* and public/images/*) class Static def initialize(app, options={}) @app = app @urls = options[:urls] || ["/favicon.ico"] root = options[:root] || Dir.pwd @file_server = Rack::File.new(root) end def call(env) path = env["PATH_INFO"] can_serve = @urls.any? { |url| path.index(url) == 0 } if can_serve @file_server.call(env) else @app.call(env) end end end end PKF8Ve prack/urlmap.rbKmodule Rack # Rack::URLMap takes a hash mapping urls or paths to apps, and # dispatches accordingly. Support for HTTP/1.1 host names exists if # the URLs start with http:// or https://. # # URLMap modifies the SCRIPT_NAME and PATH_INFO such that the part # relevant for dispatch is in the SCRIPT_NAME, and the rest in the # PATH_INFO. This should be taken care of when you need to # reconstruct the URL in order to create links. # # URLMap dispatches in such a way that the longest paths are tried # first, since they are most specific. class URLMap def initialize(map) @mapping = map.map { |location, app| if location =~ %r{\Ahttps?://(.*?)(/.*)} host, location = $1, $2 else host = nil end location = "" if location == "/" [host, location, app] }.sort_by { |(h, l, a)| -l.size } # Longest path first end def call(env) path = env["PATH_INFO"].to_s.squeeze("/") hHost, sName, sPort = env.values_at('HTTP_HOST','SERVER_NAME','SERVER_PORT') @mapping.each { |host, location, app| if (hHost == host || sName == host \ || (host.nil? && (hHost == sName || hHost == sName+':'+sPort))) \ and location == path[0, location.size] \ and (path[location.size] == nil || path[location.size] == ?/) env["SCRIPT_NAME"] += location.dup env["PATH_INFO"] = path[location.size..-1] env["PATH_INFO"].gsub!(/\/\z/, '') env["PATH_INFO"] = "/" if env["PATH_INFO"].empty? return app.call(env) end } [404, {"Content-Type" => "text/plain"}, ["Not Found: #{path}"]] end end end PKF8< rack/utils.rbrequire 'tempfile' module Rack # Rack::Utils contains a grab-bag of useful methods for writing web # applications adopted from all kinds of Ruby libraries. module Utils # Performs URI escaping so that you can construct proper # query strings faster. Use this rather than the cgi.rb # version since it's faster. (Stolen from Camping). def escape(s) s.to_s.gsub(/([^ a-zA-Z0-9_.-]+)/n) { '%'+$1.unpack('H2'*$1.size).join('%').upcase }.tr(' ', '+') end module_function :escape # Unescapes a URI escaped string. (Stolen from Camping). def unescape(s) s.tr('+', ' ').gsub(/((?:%[0-9a-fA-F]{2})+)/n){ [$1.delete('%')].pack('H*') } end module_function :unescape # Stolen from Mongrel: # Parses a query string by breaking it up at the '&' # and ';' characters. You can also use this to parse # cookies by changing the characters used in the second # parameter (which defaults to '&;'). def parse_query(qs, d = '&;') params = {} (qs||'').split(/[#{d}] */n).inject(params) { |h,p| k, v=unescape(p).split('=',2) if cur = params[k] if cur.class == Array params[k] << v else params[k] = [cur, v] end else params[k] = v end } return params end module_function :parse_query # Escape ampersands, brackets and quotes to their HTML/XML entities. def escape_html(string) string.to_s.gsub("&", "&"). gsub("<", "<"). gsub(">", ">"). gsub("'", "'"). gsub('"', """) end module_function :escape_html class Context < Proc def initialize app_f=nil, app_r=nil @for, @app = app_f, app_r end alias_method :old_inspect, :inspect def inspect "#{old_inspect} ==> #{@for.inspect} ==> #{@app.inspect}" end def pretty_print pp pp.text old_inspect pp.nest 1 do pp.breakable pp.text '=for> ' pp.pp @for pp.breakable pp.text '=app> ' pp.pp @app end end end # A case-normalizing Hash, adjusting on [] and []=. class HeaderHash < Hash def initialize(hash={}) hash.each { |k, v| self[k] = v } end def to_hash {}.replace(self) end def [](k) super capitalize(k) end def []=(k, v) super capitalize(k), v end def capitalize(k) k.to_s.downcase.gsub(/^.|[-_\s]./) { |x| x.upcase } end end # Every standard HTTP code mapped to the appropriate message. # Stolen from Mongrel. HTTP_STATUS_CODES = { 100 => 'Continue', 101 => 'Switching Protocols', 200 => 'OK', 201 => 'Created', 202 => 'Accepted', 203 => 'Non-Authoritative Information', 204 => 'No Content', 205 => 'Reset Content', 206 => 'Partial Content', 300 => 'Multiple Choices', 301 => 'Moved Permanently', 302 => 'Moved Temporarily', 303 => 'See Other', 304 => 'Not Modified', 305 => 'Use Proxy', 400 => 'Bad Request', 401 => 'Unauthorized', 402 => 'Payment Required', 403 => 'Forbidden', 404 => 'Not Found', 405 => 'Method Not Allowed', 406 => 'Not Acceptable', 407 => 'Proxy Authentication Required', 408 => 'Request Time-out', 409 => 'Conflict', 410 => 'Gone', 411 => 'Length Required', 412 => 'Precondition Failed', 413 => 'Request Entity Too Large', 414 => 'Request-URI Too Large', 415 => 'Unsupported Media Type', 500 => 'Internal Server Error', 501 => 'Not Implemented', 502 => 'Bad Gateway', 503 => 'Service Unavailable', 504 => 'Gateway Time-out', 505 => 'HTTP Version not supported' } # A multipart form data parser, adapted from IOWA. # # Usually, Rack::Request#POST takes care of calling this. module Multipart EOL = "\r\n" def self.parse_multipart(env) unless env['CONTENT_TYPE'] =~ %r|\Amultipart/form-data.*boundary=\"?([^\";,]+)\"?|n nil else boundary = "--#{$1}" params = {} buf = "" content_length = env['CONTENT_LENGTH'].to_i input = env['rack.input'] boundary_size = boundary.size + EOL.size bufsize = 16384 content_length -= boundary_size status = input.read(boundary_size) raise EOFError, "bad content body" unless status == boundary + EOL rx = /(?:#{EOL})?#{Regexp.quote boundary}(#{EOL}|--)/ loop { head = nil body = '' filename = content_type = name = nil until head && buf =~ rx if !head && i = buf.index("\r\n\r\n") head = buf.slice!(0, i+2) # First \r\n buf.slice!(0, 2) # Second \r\n filename = head[/Content-Disposition:.* filename="?([^\";]*)"?/ni, 1] content_type = head[/Content-Type: (.*)\r\n/ni, 1] name = head[/Content-Disposition:.* name="?([^\";]*)"?/ni, 1] body = Tempfile.new("RackMultipart") if filename next end # Save the read body part. if head && (boundary_size+4 < buf.size) body << buf.slice!(0, buf.size - (boundary_size+4)) end c = input.read(bufsize < content_length ? bufsize : content_length) raise EOFError, "bad content body" if c.nil? || c.empty? buf << c content_length -= c.size end # Save the rest. if i = buf.index(rx) body << buf.slice!(0, i) buf.slice!(0, boundary_size+2) content_length = -1 if $1 == "--" end if filename body.rewind data = {:filename => filename, :type => content_type, :name => name, :tempfile => body, :head => head} else data = body end if name if name =~ /\[\]\z/ params[name] ||= [] params[name] << data else params[name] = data end end break if buf.empty? || content_length == -1 } params end end end end end PKF8{J6rack/adapter/camping.rb#module Rack module Adapter class Camping def initialize(app) @app = app end def call(env) env["PATH_INFO"] ||= "" env["SCRIPT_NAME"] ||= "" controller = @app.run(env['rack.input'], env) h = controller.headers h.each_pair do |k,v| if v.kind_of? URI h[k] = v.to_s end end [controller.status, controller.headers, controller.body] end end end end PKF8'urack/adapter/rails.rbwrequire 'cgi' require 'jruby/rack/rails' # Based on http://github.com/macournoyer/thin/tree/master/lib/rack/adapter/rails.rb # Adapter to run a Rails app with any supported Rack handler. # By default it will try to load the Rails application in the # current directory in the development environment. # Options: # root: Root directory of the Rails app # env: Rails environment to run in (development, production or test) # Based on http://fuzed.rubyforge.org/ Rails adapter module Rack module Adapter class Rails def initialize(options={}) @root = options[:root] || Dir.pwd @env = options[:environment] || 'production' @public = options[:public] || ::File.join(@root, "public") @file_server = Rack::File.new(@public) end # TODO refactor this in File#can_serve?(path) ?? def file_exist?(path) full_path = ::File.join(@file_server.root, Utils.unescape(path)) ::File.file?(full_path) && ::File.readable?(full_path) end def serve_file(env) @file_server.call(env) end def serve_rails(env) request = Request.new(env) response = Response.new cgi = CGIWrapper.new(request, response) Dispatcher.dispatch(cgi, session_options(env), response) response.finish end def call(env) if env['rack.dynamic.requests.only'] serve_rails(env) else path = env['PATH_INFO'].chomp('/') cached_path = (path.empty? ? 'index' : path) + ActionController::Base.page_cache_extension if file_exist?(path) # Serve the file if it's there serve_file(env) elsif file_exist?(cached_path) # Serve the page cache if it's there env['PATH_INFO'] = cached_path serve_file(env) else # No static file, let Rails handle it serve_rails(env) end end end def session_options(env) env['rails.session_options'] || ActionController::CgiRequest::DEFAULT_SESSION_OPTIONS end protected class CGIWrapper < ::CGI def initialize(request, response, *args) @request = request @response = response @args = *args @input = request.body super(*args) end def header(options = "text/html") if options.is_a?(String) @response['Content-Type'] = options unless @response['Content-Type'] else @response['Content-Length'] = options.delete('Content-Length').to_s if options['Content-Length'] @response['Content-Type'] = options.delete('type') || "text/html" @response['Content-Type'] += "; charset=" + options.delete('charset') if options['charset'] @response['Content-Language'] = options.delete('language') if options['language'] @response['Expires'] = options.delete('expires') if options['expires'] @response.status = options.delete('Status') if options['Status'] # Convert 'cookie' header to 'Set-Cookie' headers. # Because Set-Cookie header can appear more the once in the response body, # we store it in a line break seperated string that will be translated to # multiple Set-Cookie header by the handler. if cookie = options.delete('cookie') cookies = [] case cookie when Array then cookie.each { |c| cookies << c.to_s } when Hash then cookie.each { |_, c| cookies << c.to_s } else cookies << cookie.to_s end @output_cookies.each { |c| cookies << c.to_s } if @output_cookies @response['Set-Cookie'] = cookies unless cookies.empty? end options.each { |k,v| @response[k] = v } end "" end def params @params ||= @request.params end def cookies @request.cookies end def query_string @request.query_string end # Used to wrap the normal args variable used inside CGI. def args @args end # Used to wrap the normal env_table variable used inside CGI. def env_table @request.env end # Used to wrap the normal stdinput variable used inside CGI. def stdinput @input end def stdoutput STDERR.puts "stdoutput should not be used." @response.body end end end end end PKF8rack/auth/abstract/PKF8Wrack/auth/basic.rb[require 'rack/auth/abstract/handler' require 'rack/auth/abstract/request' module Rack module Auth # Rack::Auth::Basic implements HTTP Basic Authentication, as per RFC 2617. # # Initialize with the Rack application that you want protecting, # and a block that checks if a username and password pair are valid. # # See also: example/protectedlobster.rb class Basic < AbstractHandler def call(env) auth = Basic::Request.new(env) return unauthorized unless auth.provided? return bad_request unless auth.basic? if valid?(auth) env['REMOTE_USER'] = auth.username return @app.call(env) end unauthorized end private def challenge 'Basic realm="%s"' % realm end def valid?(auth) @authenticator.call(*auth.credentials) end class Request < Auth::AbstractRequest def basic? :basic == scheme end def credentials @credentials ||= params.unpack("m*").first.split(/:/, 2) end def username credentials.first end end end end end PKF8rack/auth/digest/PKF8Fd50rack/auth/openid.rb0# AUTHOR: blink ; blink#ruby-lang@irc.freenode.net require 'rack/auth/abstract/handler' require 'openid' module Rack module Auth # Rack::Auth::OpenID provides a simple method for permitting openid # based logins. It requires the ruby-openid lib from janrain to operate, # as well as some method of session management of a Hash type. # # After a transaction, the response status object is stored in the # environment at rack.auth.openid.status, which can be used in the # followup block or in a wrapping application to accomplish # additional data maniipulation. # # NOTE: Due to the amount of data that ruby-openid stores in the session, # Rack::Session::Cookie may fault. # # A hash of data is stored in the session hash at the key of :openid. # The fully canonicalized identity url is stored within at 'identity'. # Extension data from 'openid.sreg.nickname' would be stored as # { 'nickname' => value }. # # NOTE: To my knowledge there is no collision at this point from storage # of this manner, if there is please let me know so I may adjust this app # to cope. class OpenID < AbstractHandler # Required for ruby-openid OIDStore = ::OpenID::MemoryStore.new # A Hash of options is taken as it's single initializing # argument. String keys are taken to be openid protocol # extension namespaces. # # For example: 'sreg' => { 'required' => # 'nickname' } # # Other keys are taken as options for Rack::Auth::OpenID, normally Symbols. # Only :return is required. :trust is highly recommended to be set. # # * :return defines the url to return to after the client authenticates # with the openid service provider. Should point to where this app is # mounted. (ex: 'http://mysite.com/openid') # * :trust defines the url identifying the site they are actually logging # into. (ex: 'http://mysite.com/') # * :session_key defines the key to the session hash in the env. # (by default it uses 'rack.session') def initialize(options={}) raise ArgumentError, 'No return url provided.' unless options[:return] warn 'No trust url provided.' unless options[:trust] options[:trust] ||= options[:return] @options = { :session_key => 'rack.session' }.merge(options) end def call(env) request = Rack::Request.new env return no_session unless session = request.env[@options[:session_key]] resp = if request.GET['openid.mode'] finish session, request.GET, env elsif request.GET['openid_url'] check session, request.GET['openid_url'], env else bad_request end end def check(session, oid_url, env) consumer = ::OpenID::Consumer.new session, OIDStore oid = consumer.begin oid_url return auth_fail unless oid.status == ::OpenID::SUCCESS @options.each do |ns,s| next unless ns.is_a? String s.each {|k,v| oid.add_extension_arg(ns, k, v) } end r_url = @options.fetch :return do |k| request.url end t_url = @options.fetch :trust env['rack.auth.openid.status'] = oid return 303, {'Location'=>oid.redirect_url( t_url, r_url )}, [] end def finish(session, params, env) consumer = ::OpenID::Consumer.new session, OIDStore oid = consumer.complete params return bad_login unless oid.status == ::OpenID::SUCCESS session[:openid] = {'identity' => oid.identity_url} @options.each do |ns,s| next unless ns.is_a? String oid.extension_response(ns).each{|k,v| session[k]=v } end env['rack.auth.openid.status'] = oid return 303, {'Location'=>@options[:trust]}, [] end def no_session @options. fetch :no_session, [500,{'Content-Type'=>'text/plain'},'No session available.'] end def auth_fail @options. fetch :auth_fail, [500, {'Content-Type'=>'text/plain'},'Foreign server failure.'] end def bad_login @options. fetch :bad_login, [401, {'Content-Type'=>'text/plain'},'Identification has failed.'] end end end end PKF8+&rack/auth/abstract/handler.rb&module Rack module Auth # Rack::Auth::AbstractHandler implements common authentication functionality. # # +realm+ should be set for all handlers. class AbstractHandler attr_accessor :realm def initialize(app, &authenticator) @app, @authenticator = app, authenticator end private def unauthorized(www_authenticate = challenge) return [ 401, { 'WWW-Authenticate' => www_authenticate.to_s }, [] ] end def bad_request [ 400, {}, [] ] end end end end PKF8brack/auth/abstract/request.rbumodule Rack module Auth class AbstractRequest def initialize(env) @env = env end def provided? !authorization_key.nil? end def parts @parts ||= @env[authorization_key].split(' ', 2) end def scheme @scheme ||= parts.first.downcase.to_sym end def params @params ||= parts.last end private AUTHORIZATION_KEYS = ['HTTP_AUTHORIZATION', 'X-HTTP_AUTHORIZATION', 'X_HTTP_AUTHORIZATION'] def authorization_key @authorization_key ||= AUTHORIZATION_KEYS.detect { |key| @env.has_key?(key) } end end end end PKF81r0 + rack/auth/digest/md5.rb+ require 'rack/auth/abstract/handler' require 'rack/auth/digest/request' require 'rack/auth/digest/params' require 'rack/auth/digest/nonce' require 'digest/md5' module Rack module Auth module Digest # Rack::Auth::Digest::MD5 implements the MD5 algorithm version of # HTTP Digest Authentication, as per RFC 2617. # # Initialize with the [Rack] application that you want protecting, # and a block that looks up a plaintext password for a given username. # # +opaque+ needs to be set to a constant base64/hexadecimal string. # class MD5 < AbstractHandler attr_accessor :opaque attr_writer :passwords_hashed def initialize(app) super @passwords_hashed = nil end def passwords_hashed? !!@passwords_hashed end def call(env) auth = Request.new(env) unless auth.provided? return unauthorized end if !auth.digest? || !auth.correct_uri? || !valid_qop?(auth) return bad_request end if valid?(auth) if auth.nonce.stale? return unauthorized(challenge(:stale => true)) else env['REMOTE_USER'] = auth.username return @app.call(env) end end unauthorized end private QOP = 'auth'.freeze def params(hash = {}) Params.new do |params| params['realm'] = realm params['nonce'] = Nonce.new.to_s params['opaque'] = H(opaque) params['qop'] = QOP hash.each { |k, v| params[k] = v } end end def challenge(hash = {}) "Digest #{params(hash)}" end def valid?(auth) valid_opaque?(auth) && valid_nonce?(auth) && valid_digest?(auth) end def valid_qop?(auth) QOP == auth.qop end def valid_opaque?(auth) H(opaque) == auth.opaque end def valid_nonce?(auth) auth.nonce.valid? end def valid_digest?(auth) digest(auth, @authenticator.call(auth.username)) == auth.response end def md5(data) ::Digest::MD5.hexdigest(data) end alias :H :md5 def KD(secret, data) H([secret, data] * ':') end def A1(auth, password) [ auth.username, auth.realm, password ] * ':' end def A2(auth) [ auth.method, auth.uri ] * ':' end def digest(auth, password) password_hash = passwords_hashed? ? password : H(A1(auth, password)) KD(password_hash, [ auth.nonce, auth.nc, auth.cnonce, QOP, H(A2(auth)) ] * ':') end end end end end PKF8rack/auth/digest/nonce.rb8require 'digest/md5' module Rack module Auth module Digest # Rack::Auth::Digest::Nonce is the default nonce generator for the # Rack::Auth::Digest::MD5 authentication handler. # # +private_key+ needs to set to a constant string. # # +time_limit+ can be optionally set to an integer (number of seconds), # to limit the validity of the generated nonces. class Nonce class << self attr_accessor :private_key, :time_limit end def self.parse(string) new(*string.unpack("m*").first.split(' ', 2)) end def initialize(timestamp = Time.now, given_digest = nil) @timestamp, @given_digest = timestamp.to_i, given_digest end def to_s [([ @timestamp, digest ] * ' ')].pack("m*").strip end def digest ::Digest::MD5.hexdigest([ @timestamp, self.class.private_key ] * ':') end def valid? digest == @given_digest end def stale? !self.class.time_limit.nil? && (@timestamp - Time.now.to_i) < self.class.time_limit end def fresh? !stale? end end end end end PKF8hUrack/auth/digest/params.rbKmodule Rack module Auth module Digest class Params < Hash def self.parse(str) split_header_value(str).inject(new) do |header, param| k, v = param.split('=', 2) header[k] = dequote(v) header end end def self.dequote(str) # From WEBrick::HTTPUtils ret = (/\A"(.*)"\Z/ =~ str) ? $1 : str.dup ret.gsub!(/\\(.)/, "\\1") ret end def self.split_header_value(str) # From WEBrick::HTTPUtils str.scan(/((?:"(?:\\.|[^"])+?"|[^",]+)+)(?:,\s*|\Z)/n).collect{ |v| v[0] } end def initialize super yield self if block_given? end def [](k) super k.to_s end def []=(k, v) super k.to_s, v.to_s end UNQUOTED = ['qop', 'nc', 'stale'] def to_s inject([]) do |parts, (k, v)| parts << "#{k}=" + (UNQUOTED.include?(k) ? v.to_s : quote(v)) parts end.join(', ') end def quote(str) # From WEBrick::HTTPUtils '"' << str.gsub(/[\\\"]/o, "\\\1") << '"' end end end end end PKF8 9rack/auth/digest/request.rb$require 'rack/auth/abstract/request' require 'rack/auth/digest/params' require 'rack/auth/digest/nonce' module Rack module Auth module Digest class Request < Auth::AbstractRequest def method @env['REQUEST_METHOD'] end def digest? :digest == scheme end def correct_uri? @env['PATH_INFO'] == uri end def nonce @nonce ||= Nonce.parse(params['nonce']) end def params @params ||= Params.parse(parts.last) end def method_missing(sym) if params.has_key? key = sym.to_s return params[key] end super end end end end end PKF8nrack/handler/cgi.rbjmodule Rack module Handler class CGI def self.run(app, options=nil) serve app end def self.serve(app) env = ENV.to_hash env.delete "HTTP_CONTENT_LENGTH" env["SCRIPT_NAME"] = "" if env["SCRIPT_NAME"] == "/" env.update({"rack.version" => [0,1], "rack.input" => STDIN, "rack.errors" => STDERR, "rack.multithread" => false, "rack.multiprocess" => true, "rack.run_once" => true, "rack.url_scheme" => ["yes", "on", "1"].include?(ENV["HTTPS"]) ? "https" : "http" }) env["QUERY_STRING"] ||= "" env["HTTP_VERSION"] ||= env["SERVER_PROTOCOL"] env["REQUEST_PATH"] ||= "/" status, headers, body = app.call(env) begin send_headers status, headers send_body body ensure body.close if body.respond_to? :close end end def self.send_headers(status, headers) STDOUT.print "Status: #{status}\r\n" headers.each { |k, vs| vs.each { |v| STDOUT.print "#{k}: #{v}\r\n" } } STDOUT.print "\r\n" STDOUT.flush end def self.send_body(body) body.each { |part| STDOUT.print part STDOUT.flush } end end end end PKF85ipkrack/handler/fastcgi.rbkrequire 'fcgi' module Rack module Handler class FastCGI def self.run(app, options={}) file = options[:File] and STDIN.reopen(UNIXServer.new(file)) port = options[:Port] and STDIN.reopen(TCPServer.new(port)) FCGI.each { |request| serve request, app } end module ProperStream # :nodoc: def each # This is missing by default. while line = gets yield line end end def read(*args) if args.empty? super || "" # Empty string on EOF. else super end end end def self.serve(request, app) env = request.env env.delete "HTTP_CONTENT_LENGTH" request.in.extend ProperStream env["SCRIPT_NAME"] = "" if env["SCRIPT_NAME"] == "/" env.update({"rack.version" => [0,1], "rack.input" => request.in, "rack.errors" => request.err, "rack.multithread" => false, "rack.multiprocess" => true, "rack.run_once" => false, "rack.url_scheme" => ["yes", "on", "1"].include?(env["HTTPS"]) ? "https" : "http" }) env["QUERY_STRING"] ||= "" env["HTTP_VERSION"] ||= env["SERVER_PROTOCOL"] env["REQUEST_PATH"] ||= "/" env.delete "PATH_INFO" if env["PATH_INFO"] == "" status, headers, body = app.call(env) begin send_headers request.out, status, headers send_body request.out, body ensure body.close if body.respond_to? :close request.finish end end def self.send_headers(out, status, headers) out.print "Status: #{status}\r\n" headers.each { |k, vs| vs.each { |v| out.print "#{k}: #{v}\r\n" } } out.print "\r\n" out.flush end def self.send_body(out, body) body.each { |part| out.print part out.flush } end end end end PKF8@rack/handler/lsws.rb@require 'lsapi' #require 'cgi' module Rack module Handler class LSWS def self.run(app, options=nil) while LSAPI.accept != nil serve app end end def self.serve(app) env = ENV.to_hash env.delete "HTTP_CONTENT_LENGTH" env["SCRIPT_NAME"] = "" if env["SCRIPT_NAME"] == "/" env.update({"rack.version" => [0,1], "rack.input" => STDIN, "rack.errors" => STDERR, "rack.multithread" => false, "rack.multiprocess" => true, "rack.run_once" => false, "rack.url_scheme" => ["yes", "on", "1"].include?(ENV["HTTPS"]) ? "https" : "http" }) env["QUERY_STRING"] ||= "" env["HTTP_VERSION"] ||= env["SERVER_PROTOCOL"] env["REQUEST_PATH"] ||= "/" status, headers, body = app.call(env) begin send_headers status, headers send_body body ensure body.close if body.respond_to? :close end end def self.send_headers(status, headers) print "Status: #{status}\r\n" headers.each { |k, vs| vs.each { |v| print "#{k}: #{v}\r\n" } } print "\r\n" STDOUT.flush end def self.send_body(body) body.each { |part| print part STDOUT.flush } end end end end PKF8͝QLrack/handler/mongrel.rbLrequire 'mongrel' require 'stringio' module Rack module Handler class Mongrel < ::Mongrel::HttpHandler def self.run(app, options={}) server = ::Mongrel::HttpServer.new(options[:Host] || '0.0.0.0', options[:Port] || 8080) server.register('/', Rack::Handler::Mongrel.new(app)) yield server if block_given? server.run.join end def initialize(app) @app = app end def process(request, response) env = {}.replace(request.params) env.delete "HTTP_CONTENT_TYPE" env.delete "HTTP_CONTENT_LENGTH" env["SCRIPT_NAME"] = "" if env["SCRIPT_NAME"] == "/" env.update({"rack.version" => [0,1], "rack.input" => request.body || StringIO.new(""), "rack.errors" => STDERR, "rack.multithread" => true, "rack.multiprocess" => false, # ??? "rack.run_once" => false, "rack.url_scheme" => "http", }) env["QUERY_STRING"] ||= "" env.delete "PATH_INFO" if env["PATH_INFO"] == "" status, headers, body = @app.call(env) begin response.status = status.to_i headers.each { |k, vs| vs.each { |v| response.header[k] = v } } body.each { |part| response.body << part } response.finished ensure body.close if body.respond_to? :close end end end end end PKF8Q$rack/handler/scgi.rbrequire 'scgi' require 'stringio' module Rack module Handler class SCGI < ::SCGI::Processor attr_accessor :app def self.run(app, options=nil) new(options.merge(:app=>app, :host=>options[:Host], :port=>options[:Port], :socket=>options[:Socket])).listen end def initialize(settings = {}) @app = settings[:app] @log = Object.new def @log.info(*args); end def @log.error(*args); end super(settings) end def process_request(request, input_body, socket) env = {}.replace(request) env.delete "HTTP_CONTENT_TYPE" env.delete "HTTP_CONTENT_LENGTH" env["REQUEST_PATH"], env["QUERY_STRING"] = env["REQUEST_URI"].split('?', 2) env["HTTP_VERSION"] ||= env["SERVER_PROTOCOL"] env["PATH_INFO"] = env["REQUEST_PATH"] env["QUERY_STRING"] ||= "" env["SCRIPT_NAME"] = "" env.update({"rack.version" => [0,1], "rack.input" => StringIO.new(input_body), "rack.errors" => STDERR, "rack.multithread" => true, "rack.multiprocess" => true, "rack.run_once" => false, "rack.url_scheme" => ["yes", "on", "1"].include?(env["HTTPS"]) ? "https" : "http" }) status, headers, body = app.call(env) begin socket.write("Status: #{status}\r\n") headers.each do |k, vs| vs.each {|v| socket.write("#{k}: #{v}\r\n")} end socket.write("\r\n") body.each {|s| socket.write(s)} ensure body.close if body.respond_to? :close end end end end end PKF8KD ? rack/handler/servlet.rb? #-- # Copyright 2007-2008 Sun Microsystems, Inc. # This source code is available under the MIT license. # See the file LICENSE.txt for details. #++ require 'jruby/rack' module Rack module Handler class Servlet def initialize(rack_app) @rack_app = rack_app end def call(servlet_env) env = env_hash add_input_errors_scheme(servlet_env, env) add_servlet_request_attributes(servlet_env, env) add_variables(servlet_env, env) add_headers(servlet_env, env) JRuby::Rack::Response.new(@rack_app.call(env)) end def env_hash { "rack.version" => Rack::VERSION, "rack.multithread" => true, "rack.multiprocess" => false, "rack.run_once" => false } end def add_input_errors_scheme(servlet_env, env) env['rack.input'] = servlet_env.to_io env['rack.errors'] = JRuby::Rack::ServletLog.new env['rack.url_scheme'] = servlet_env.getScheme env['java.servlet_request'] = servlet_env env['java.servlet_context'] = $servlet_context end def add_servlet_request_attributes(servlet_env, env) servlet_env.getAttributeNames.each do |k| env[k] = servlet_env.getAttribute(k) end end def add_variables(servlet_env, env) context_path = servlet_env.getContextPath || "" env["REQUEST_METHOD"] ||= servlet_env.getMethod || "GET" env["SCRIPT_NAME"] ||= "#{context_path}#{servlet_env.getServletPath}" env["REQUEST_URI"] ||= servlet_env.getRequestURI || "" path_info = servlet_env.getServletPath || "" path_info += servlet_env.getPathInfo if servlet_env.getPathInfo env["PATH_INFO"] ||= path_info env["QUERY_STRING"] ||= servlet_env.getQueryString || "" env["SERVER_NAME"] ||= servlet_env.getServerName || "" env["REMOTE_HOST"] ||= servlet_env.getRemoteHost || "" env["REMOTE_ADDR"] ||= servlet_env.getRemoteAddr || "" env["REMOTE_USER"] ||= servlet_env.getRemoteUser || "" env["SERVER_PORT"] ||= servlet_env.getServerPort env["SERVER_PORT"] = env["SERVER_PORT"].to_s unless String === env["SERVER_PORT"] end def add_headers(servlet_env, env) env["CONTENT_TYPE"] ||= servlet_env.getContentType env.delete("CONTENT_TYPE") unless env["CONTENT_TYPE"] env["CONTENT_LENGTH"] ||= servlet_env.getContentLength env["CONTENT_LENGTH"] = env["CONTENT_LENGTH"].to_s unless String === env["CONTENT_LENGTH"] env.delete("CONTENT_LENGTH") unless env["CONTENT_LENGTH"] && env["CONTENT_LENGTH"].to_i >= 0 servlet_env.getHeaderNames.each do |h| next if h =~ /^Content-(Type|Length)$/i env["HTTP_#{h.upcase.gsub(/-/, '_')}"] ||= servlet_env.getHeader(h) end end end end end PKF8orack/handler/webrick.rbrequire 'webrick' require 'stringio' module Rack module Handler class WEBrick < WEBrick::HTTPServlet::AbstractServlet def self.run(app, options={}) server = ::WEBrick::HTTPServer.new(options) server.mount "/", Rack::Handler::WEBrick, app trap(:INT) { server.shutdown } yield server if block_given? server.start end def initialize(server, app) super server @app = app end def service(req, res) env = req.meta_vars env.delete_if { |k, v| v.nil? } env.update({"rack.version" => [0,1], "rack.input" => StringIO.new(req.body.to_s), "rack.errors" => STDERR, "rack.multithread" => true, "rack.multiprocess" => false, "rack.run_once" => false, "rack.url_scheme" => ["yes", "on", "1"].include?(ENV["HTTPS"]) ? "https" : "http" }) env["HTTP_VERSION"] ||= env["SERVER_PROTOCOL"] env["QUERY_STRING"] ||= "" env["REQUEST_PATH"] ||= "/" env.delete "PATH_INFO" if env["PATH_INFO"] == "" status, headers, body = @app.call(env) begin res.status = status.to_i headers.each { |k, vs| vs.each { |v| res[k] = v } } body.each { |part| res.body << part } ensure body.close if body.respond_to? :close end end end end end PKF8޴]Xrack/session/cookie.rbXmodule Rack module Session # Rack::Session::Cookie provides simple cookie based session management. # The session is a Ruby Hash stored as base64 encoded marshalled data # set to :key (default: rack.session). # # Example: # # use Rack::Session::Cookie, :key => 'rack.session', # :domain => 'foo.com', # :path => '/', # :expire_after => 2592000 # # All parameters are optional. class Cookie def initialize(app, options={}) @app = app @key = options[:key] || "rack.session" @default_options = {:domain => nil, :path => "/", :expire_after => nil}.merge(options) end def call(env) load_session(env) status, headers, body = @app.call(env) commit_session(env, status, headers, body) end private def load_session(env) request = Rack::Request.new(env) session_data = request.cookies[@key] begin session_data = session_data.unpack("m*").first session_data = Marshal.load(session_data) env["rack.session"] = session_data rescue env["rack.session"] = Hash.new end env["rack.session.options"] = @default_options.dup end def commit_session(env, status, headers, body) session_data = Marshal.dump(env["rack.session"]) session_data = [session_data].pack("m*") if session_data.size > (4096 - @key.size) env["rack.errors"].puts("Warning! Rack::Session::Cookie data size exceeds 4K. Content dropped.") [status, headers, body] else options = env["rack.session.options"] cookie = Hash.new cookie[:value] = session_data cookie[:expires] = Time.now + options[:expire_after] unless options[:expire_after].nil? response = Rack::Response.new(body, status, headers) response.set_cookie(@key, cookie.merge(options)) response.to_a end end end end end PKF8g/ rack/session/pool.rb # AUTHOR: blink ; blink#ruby-lang@irc.freenode.net module Rack module Session # Rack::Session::Pool provides simple cookie based session management. # Session data is stored in a hash held by @pool. The corresponding # session key sent to the client. # The pool is unmonitored and unregulated, which means that over # prolonged use the session pool will be very large. # # Example: # # use Rack::Session::Pool, :key => 'rack.session', # :domain => 'foo.com', # :path => '/', # :expire_after => 2592000 # # All parameters are optional. class Pool attr_reader :pool, :key def initialize(app, options={}) @app = app @key = options[:key] || "rack.session" @default_options = {:domain => nil, :path => "/", :expire_after => nil}.merge(options) @pool = Hash.new @default_context = context app, &nil end def call(env) @default_context.call(env) end def context(app, &block) Rack::Utils::Context.new self, app do |env| load_session env block[env] if block response = app.call(env) commit_session env, response response end end private def load_session(env) sess_id = env.fetch('HTTP_COOKIE','')[/#{@key}=([^,;]+)/,1] begin sess_id = Array.new(8){rand(16).to_s(16)}*'' end while @pool.key? sess_id if sess_id.nil? or !@pool.key? sess_id session = @pool.fetch sess_id, {} session.instance_variable_set '@dat', [sess_id, Time.now] @pool.store sess_id, env['rack.session'] = session env["rack.session.options"] = @default_options.dup end def commit_session(env, response) session = env['rack.session'] options = env['rack.session.options'] sdat = session.instance_variable_get '@dat' cookie = Utils.escape(@key)+'='+Utils.escape(sdat[0]) cookie<< "; domain=#{options[:domain]}" if options[:domain] cookie<< "; path=#{options[:path]}" if options[:path] cookie<< "; expires=#{sdat[1]+options[:expires_after]}" if options[:expires_after] case a = (h = response[1])['Set-Cookie'] when Array then a << cookie when String then h['Set-Cookie'] = [a, cookie] when nil then h['Set-Cookie'] = cookie end end end end end PKF8 META-INF/PKF8HM˨META-INF/jruby-rack.tld\ 1.0 jruby-rack urn:org.jruby.rack rails org.jruby.rack.RackTag empty Makes requests to the rails application and renders the results to the page path true true java.lang.String params false true java.lang.String rack org.jruby.rack.RackTag empty Makes requests to the rack application and renders the results to the page path true true java.lang.String params false true java.lang.String PKF8|META-INF/MANIFEST.MFjManifest-Version: 1.0 Created-By: Buildr Build-By: nicksieger Build-Jdk: 1.5.0_13 Implementation-Title: JRuby Rack adapter Implementation-Version: PK4F8 AMETA-INF/PK4F8|META-INF/MANIFEST.MFPK4F8HM˨طMETA-INF/jruby-rack.tldPK4F8A.cgi/PK4F8 Acgi/session/PK4F85n !"cgi/session/java_servlet_store.rbPK4F8AUjruby/PK4F8B750 jruby/rack.rbPK4F8 Afjruby/rack/PK4F8 jruby/rack/merb.rbPK4F8J|jruby/rack/rails.rbPK4F8cljruby/rack/rails_boot.rbPK4F86(# jruby/rack/rails_ext.rbPK4F8~ŭjjruby/rack/servlet_ext.rbPK4F8Yni+jruby/rack/servlet_helper.rbPK4F8Aorg/PK4F8 A'org/jruby/PK4F8ATorg/jruby/rack/PK4F88+UMH-org/jruby/rack/DefaultRackApplication$1.classPK4F8\./*+Rorg/jruby/rack/DefaultRackApplication.classPK4F84org/jruby/rack/DefaultRackApplicationFactory$1.classPK4F84org/jruby/rack/DefaultRackApplicationFactory$2.classPK4F8;L#6org/jruby/rack/DefaultRackApplicationFactory$3$1.classPK4F8 '4 org/jruby/rack/DefaultRackApplicationFactory$3.classPK4F8Y -4i%org/jruby/rack/DefaultRackApplicationFactory$4.classPK4F8~qlK,org/jruby/rack/DefaultRackApplicationFactory$ApplicationObjectFactory.classPK4F8c^2.org/jruby/rack/DefaultRackApplicationFactory.classPK4F86l *9Forg/jruby/rack/DefaultRackDispatcher.classPK4F8X5#4Qorg/jruby/rack/PoolingRackApplicationFactory$1.classPK4F8Grw2Zorg/jruby/rack/PoolingRackApplicationFactory.classPK4F8k@;$uorg/jruby/rack/RackApplication.classPK4F8"+tworg/jruby/rack/RackApplicationFactory.classPK4F8V^#yorg/jruby/rack/RackDispatcher.classPK4F8uGr!{org/jruby/rack/RackFilter$1.classPK4F8̏!'org/jruby/rack/RackFilter$2.classPK4F8R`_Z5dorg/jruby/rack/RackFilter$ResponseStatusCapture.classPK4F8@l org/jruby/rack/RackFilter.classPK4F8~E0 org/jruby/rack/RackInitializationException.classPK4F8u9w)$!org/jruby/rack/RackResponse.classPK4F819 borg/jruby/rack/RackServlet.classPK4F8/6org/jruby/rack/RackServletContextListener.classPK4F8M4/org/jruby/rack/RackTag$1.classPK4F8ձ|c ^  org/jruby/rack/RackTag.classPK4F8<1޼org/jruby/rack/SharedRackApplicationFactory.classPK4F8AfQorg/jruby/rack/merb/PK4F8бd_40org/jruby/rack/merb/MerbRackApplicationFactory.classPK4F8ڔơ4org/jruby/rack/merb/MerbServletContextListener.classPK4F8Aorg/jruby/rack/rails/PK4F83mh6org/jruby/rack/rails/RailsRackApplicationFactory.classPK4F8ގ6org/jruby/rack/rails/RailsServletContextListener.classPK4F8Aorg/jruby/webapp/PK4F8_3."org/jruby/webapp/FileServlet.classPK4F8d_+ org/jruby/webapp/RailsContextListener.classPK4F861#org/jruby/webapp/RailsServlet.classPK4F8qo( # rack.rbPK4F8A~rack/PK4F8 A/rack/adapter/PK4F8{J6'rack/adapter/camping.rbPK4F8'u)rack/adapter/rails.rbPK4F8 A0rack/auth/PK4F8A<rack/auth/abstract/PK4F8+&/Srack/auth/abstract/handler.rbPK4F8bUrack/auth/abstract/request.rbPK4F8W<rack/auth/basic.rbPK4F8AArack/auth/digest/PK4F81r0 + _Xrack/auth/digest/md5.rbPK4F8crack/auth/digest/nonce.rbPK4F8hUhrack/auth/digest/params.rbPK4F8 9mrack/auth/digest/request.rbPK4F8Fd50Arack/auth/openid.rbPK4F8p^00rack/builder.rbPK4F8;Ak8kfd5rack/cascade.rbPK4F8;ķ7rack/commonlogger.rbPK4F8GO =rack/file.rbPK4F8 AJrack/handler/PK4F8nprack/handler/cgi.rbPK4F85ipkvrack/handler/fastcgi.rbPK4F8@Arack/handler/lsws.rbPK4F8͝QL7rack/handler/mongrel.rbPK4F8Q$rack/handler/scgi.rbPK4F8KD ? rack/handler/servlet.rbPK4F8orack/handler/webrick.rbPK4F8X:S: Jrack/lint.rbPK4F8bqrack/lobster.rbPK4F83Ixs rack/mock.rbPK4F8yN<<rack/recursive.rbPK4F8. rack/reloader.rbPK4F8EwErack/request.rbPK4F8@h?:0rack/response.rbPK4F8 Arack/session/PK4F8޴]X٤rack/session/cookie.rbPK4F8g/ jrack/session/pool.rbPK4F8+**rack/showexceptions.rbPK4F8( rack/showstatus.rbPK4F8cbrack/static.rbPK4F8Ve prack/urlmap.rbPK4F8<  rack/utils.rbPKaa