Main Page | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Class Members | File Members | Related Pages

HttpHeaders.d

Go to the documentation of this file.
00001 /*******************************************************************************
00002 
00003         @file HttpHeaders.d
00004         
00005         Copyright (c) 2004 Kris Bell
00006         
00007         This software is provided 'as-is', without any express or implied
00008         warranty. In no event will the authors be held liable for damages
00009         of any kind arising from the use of this software.
00010         
00011         Permission is hereby granted to anyone to use this software for any 
00012         purpose, including commercial applications, and to alter it and/or 
00013         redistribute it freely, subject to the following restrictions:
00014         
00015         1. The origin of this software must not be misrepresented; you must 
00016            not claim that you wrote the original software. If you use this 
00017            software in a product, an acknowledgment within documentation of 
00018            said product would be appreciated but is not required.
00019 
00020         2. Altered source versions must be plainly marked as such, and must 
00021            not be misrepresented as being the original software.
00022 
00023         3. This notice may not be removed or altered from any distribution
00024            of the source.
00025 
00026         4. Derivative works are permitted, but they must carry this notice
00027            in full and credit the original source.
00028 
00029 
00030                         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
00031 
00032         
00033         @version        Initial version, April 2004      
00034         @author         Kris
00035 
00036 
00037 *******************************************************************************/
00038 
00039 module mango.http.server.HttpHeaders;
00040 
00041 private import  mango.io.Token,
00042                 mango.io.Tokenizer;
00043 
00044 private import  mango.io.model.IBuffer,
00045                 mango.io.model.IWriter;
00046 
00047 private import  mango.http.utils.TokenStack;
00048 
00049 private import  mango.http.server.HttpTokens;
00050 
00051 /*******************************************************************************
00052 
00053         Headers are distinct types in their own right. This is because they
00054         are somewhat optimized via a trailing ':' character.
00055 
00056 *******************************************************************************/
00057 
00058 struct HttpHeaderName
00059 {
00060         char[]     value;  
00061 }
00062 
00063 /*******************************************************************************
00064 
00065         Define the traditional set of HTTP header names
00066         
00067 *******************************************************************************/
00068 
00069 struct HttpHeader
00070 {   
00071         // size of both the request & response buffer (per thread)
00072         static const int IOBufferSize                 = 16 * 1024;
00073 
00074         // maximum length for POST parameters (to avoid DOS ...)
00075         static const int MaxPostParamSize             = 4 * 1024;
00076 
00077         static const HttpHeaderName Version           = {"HTTP/1.0"};
00078         static const HttpHeaderName TextHtml          = {"text/html"};
00079 
00080         static const HttpHeaderName Accept            = {"Accept:"};
00081         static const HttpHeaderName AcceptCharset     = {"Accept-Charset:"};
00082         static const HttpHeaderName AcceptEncoding    = {"Accept-Encoding:"};
00083         static const HttpHeaderName AcceptLanguage    = {"Accept-Language:"};
00084         static const HttpHeaderName AcceptRanges      = {"Accept-Ranges:"};
00085         static const HttpHeaderName Age               = {"Age:"};
00086         static const HttpHeaderName Allow             = {"Allow:"};
00087         static const HttpHeaderName Authorization     = {"Authorization:"};
00088         static const HttpHeaderName CacheControl      = {"Cache-Control:"};
00089         static const HttpHeaderName Connection        = {"Connection:"};
00090         static const HttpHeaderName ContentEncoding   = {"Content-Encoding:"};
00091         static const HttpHeaderName ContentLanguage   = {"Content-Language:"};
00092         static const HttpHeaderName ContentLength     = {"Content-Length:"};
00093         static const HttpHeaderName ContentLocation   = {"Content-Location:"};
00094         static const HttpHeaderName ContentRange      = {"Content-Range:"};
00095         static const HttpHeaderName ContentType       = {"Content-Type:"};
00096         static const HttpHeaderName Cookie            = {"Cookie:"};
00097         static const HttpHeaderName Date              = {"Date:"};
00098         static const HttpHeaderName ETag              = {"ETag:"};
00099         static const HttpHeaderName Expect            = {"Expect:"};
00100         static const HttpHeaderName Expires           = {"Expires:"};
00101         static const HttpHeaderName From              = {"From:"};
00102         static const HttpHeaderName Host              = {"Host:"};
00103         static const HttpHeaderName Identity          = {"identity:"};
00104         static const HttpHeaderName IfMatch           = {"If-Match:"};
00105         static const HttpHeaderName IfModifiedSince   = {"If-Modified-Since:"};
00106         static const HttpHeaderName IfNoneMatch       = {"If-None-Match:"};
00107         static const HttpHeaderName IfRange           = {"If-Range:"};
00108         static const HttpHeaderName IfUnmodifiedSince = {"If-Unmodified-Since:"};
00109         static const HttpHeaderName LastModified      = {"Last-Modified:"};
00110         static const HttpHeaderName Location          = {"Location:"};
00111         static const HttpHeaderName MaxForwards       = {"Max-Forwards:"};
00112         static const HttpHeaderName MimeVersion       = {"MIME-Version:"};
00113         static const HttpHeaderName Pragma            = {"Pragma:"};
00114         static const HttpHeaderName ProxyAuthenticate = {"Proxy-Authenticate:"};
00115         static const HttpHeaderName ProxyConnection   = {"Proxy-Connection:"};
00116         static const HttpHeaderName Range             = {"Range:"};
00117         static const HttpHeaderName Referrer          = {"Referer:"};
00118         static const HttpHeaderName RetryAfter        = {"Retry-After:"};
00119         static const HttpHeaderName Server            = {"Server:"};
00120         static const HttpHeaderName ServletEngine     = {"Servlet-Engine:"};
00121         static const HttpHeaderName SetCookie         = {"Set-Cookie:"};
00122         static const HttpHeaderName SetCookie2        = {"Set-Cookie2:"};
00123         static const HttpHeaderName TE                = {"TE:"};
00124         static const HttpHeaderName Trailer           = {"Trailer:"};
00125         static const HttpHeaderName TransferEncoding  = {"Transfer-Encoding:"};
00126         static const HttpHeaderName Upgrade           = {"Upgrade:"};
00127         static const HttpHeaderName UserAgent         = {"User-Agent:"};
00128         static const HttpHeaderName Vary              = {"Vary:"};
00129         static const HttpHeaderName Warning           = {"Warning:"};
00130         static const HttpHeaderName WwwAuthenticate   = {"WWW-Authenticate:"};
00131 }
00132 
00133 
00134 /******************************************************************************
00135 
00136         Exposes freachable HttpHeader instances 
00137 
00138 ******************************************************************************/
00139 
00140 struct HeaderElement
00141 {
00142         HttpHeaderName  name;
00143         char[]          value;
00144 }
00145 
00146 /******************************************************************************
00147 
00148         Maintains a set of input headers. These are placed into an input
00149         buffer and indexed via a TokenStack. 
00150 
00151 ******************************************************************************/
00152 
00153 class HttpHeaders : HttpTokens
00154 {
00155         private static BoundToken line;
00156 
00157         // tell compiler to used super.parse() also
00158         alias HttpTokens.parse parse;
00159 
00160         /**********************************************************************
00161                 
00162                 Setup a line tokenizer for later use
00163           
00164         **********************************************************************/
00165 
00166         static this ()
00167         {
00168                 // have to make our own LineTokenizer since we can't 
00169                 // depend upon the static Tokenizer.line to be 'live'
00170                 // before we're invoked here.
00171                 line = new BoundToken (new LineTokenizer());
00172         }
00173 
00174         /**********************************************************************
00175                 
00176                 Construct this set of headers, using a TokenStack based
00177                 upon a ':' delimeter   
00178               
00179         **********************************************************************/
00180 
00181         this ()
00182         {
00183                 // separator is a ':', and specify we want it included as
00184                 // part of the name whilst iterating
00185                 super (':', true);
00186         }
00187 
00188         /**********************************************************************
00189                 
00190                 Clone a source set of HttpHeaders
00191 
00192         **********************************************************************/
00193 
00194         this (HttpHeaders source)
00195         {
00196                 super (source);
00197         }
00198 
00199         /**********************************************************************
00200                 
00201                 Clone this set of HttpHeaders
00202 
00203         **********************************************************************/
00204 
00205         HttpHeaders clone ()
00206         {
00207                 return new HttpHeaders (this);
00208         }
00209 
00210         /**********************************************************************
00211                 
00212                 Read all header lines. Everything is mapped rather 
00213                 than being allocated & copied
00214 
00215         **********************************************************************/
00216 
00217         void parse (IBuffer input)
00218         {
00219                 setParsed (true);
00220                 while (line.next(input) && line.getLength())
00221                        stack.push(line);
00222         }
00223 
00224         /**********************************************************************
00225                 
00226                 Return the value of the provided header, or null if the
00227                 header does not exist
00228 
00229         **********************************************************************/
00230 
00231         char[] get (HttpHeaderName name)
00232         {
00233                 return super.get (name.value);
00234         }
00235 
00236         /**********************************************************************
00237                 
00238                 Return the integer value of the provided header, or -1 
00239                 if the header does not exist
00240 
00241         **********************************************************************/
00242 
00243         int getInt (HttpHeaderName name)
00244         {
00245                 return super.getInt (name.value);
00246         }
00247 
00248         /**********************************************************************
00249                 
00250                 Return the date value of the provided header, or -1 
00251                 if the header does not exist
00252 
00253         **********************************************************************/
00254 
00255         long getDate (HttpHeaderName name)
00256         {
00257                 return super.getDate (name.value);
00258         }
00259 
00260         /**********************************************************************
00261 
00262                 Iterate over the set of headers. This is a shell around
00263                 the superclass, where we can convert the HttpToken into 
00264                 a HeaderElement instead.
00265 
00266         **********************************************************************/
00267 
00268         int opApply (int delegate(inout HeaderElement) dg)
00269         {
00270                 HeaderElement   element;
00271                 int             result = 0;
00272 
00273                 foreach (HttpToken token; super)
00274                         {
00275                         element.name.value = token.name;
00276                         element.value = token.value;
00277                         result = dg (element);
00278                         if (result)
00279                             break;
00280                         }
00281                 return result;
00282         }
00283 
00284         /**********************************************************************
00285 
00286                 Create a filter for iterating of a set of named headers.
00287                 We have to create a filter since we can't pass additional
00288                 arguments directly to an opApply() method.
00289 
00290         **********************************************************************/
00291 
00292         FilteredHeaders createFilter (HttpHeaderName header)
00293         {
00294                 return new FilteredHeaders (this, header);
00295         }
00296 
00297         /**********************************************************************
00298 
00299                 Filter class for isolating a set of named headers.
00300 
00301         **********************************************************************/
00302 
00303         private static class FilteredHeaders : FilteredTokens
00304         {       
00305                 /**************************************************************
00306 
00307                         Construct a filter upon the specified headers, for
00308                         the given header name.
00309 
00310                 **************************************************************/
00311 
00312                 this (HttpHeaders headers, HttpHeaderName header)
00313                 {
00314                         super (headers, header.value);
00315                 }
00316 
00317                 /**************************************************************
00318 
00319                         Iterate over all headers matching the given name. 
00320                         This wraps the HttpToken iterator to convert the 
00321                         output into a HeaderElement instead.
00322 
00323                 **************************************************************/
00324 
00325                 int opApply (int delegate(inout HeaderElement) dg)
00326                 {
00327                         HeaderElement   element;
00328                         int             result = 0;
00329                         
00330                         foreach (HttpToken token; super)
00331                                 {
00332                                 element.name.value = token.name;
00333                                 element.value = token.value;
00334                                 result = dg (element);
00335                                 if (result)
00336                                     break;
00337                                 }
00338                         return result;
00339                 }
00340 
00341         }
00342 }
00343 
00344 
00345 /******************************************************************************
00346 
00347         Maintains a set of output headers. These are held in an output
00348         buffer, and indexed via a TokenStack. Deleting a header could be 
00349         supported by setting the TokenStack entry to null, and ignoring
00350         such values when it's time to write the headers.
00351 
00352 ******************************************************************************/
00353 
00354 class HttpMutableHeaders : HttpHeaders
00355 {
00356         /**********************************************************************
00357                 
00358                 Construct output headers, using the provided buffer as
00359                 a place to stash the header content.
00360 
00361         **********************************************************************/
00362 
00363         this (IBuffer output)
00364         {
00365                 super ();
00366                 super.setOutputBuffer (output);
00367         }
00368 
00369         /**********************************************************************
00370                 
00371                 Clone a source set of HttpMutableHeaders
00372 
00373         **********************************************************************/
00374 
00375         this (HttpMutableHeaders source)
00376         {
00377                 super (source);
00378         }
00379 
00380         /**********************************************************************
00381                 
00382                 Clone this set of HttpMutableHeaders
00383 
00384         **********************************************************************/
00385 
00386         HttpMutableHeaders clone ()
00387         {
00388                 return new HttpMutableHeaders (this);
00389         }
00390 
00391         /**********************************************************************
00392                 
00393                 Add the specified header, and use a callback to provide
00394                 the content.
00395 
00396         **********************************************************************/
00397 
00398         void add (HttpHeaderName name, void delegate (IBuffer) dg)
00399         {
00400                 super.add (name.value, dg);
00401         }
00402 
00403         /**********************************************************************
00404                 
00405                 Add the specified header and text 
00406 
00407         **********************************************************************/
00408 
00409         void add (HttpHeaderName name, char[] value)
00410         {
00411                 super.add (name.value, value);
00412         }
00413 
00414         /**********************************************************************
00415                 
00416                 Add the specified header and integer value
00417 
00418         **********************************************************************/
00419 
00420         void addInt (HttpHeaderName name, int value)
00421         {
00422                 super.addInt (name.value, value);
00423         }
00424 
00425         /**********************************************************************
00426                 
00427                 Add the specified header and long/date value
00428 
00429         **********************************************************************/
00430 
00431         void addDate (HttpHeaderName name, long value)
00432         {
00433                 super.addDate (name.value, value);
00434         }
00435 
00436         /**********************************************************************
00437                 
00438                 Return the output buffer provided during construction.
00439 
00440         **********************************************************************/
00441 
00442         IBuffer getOutputBuffer ()
00443         {
00444                 return super.getOutputBuffer ();
00445         }
00446 }

Generated on Mon Nov 14 10:59:38 2005 for Mango by  doxygen 1.4.0