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

Generated on Sun Nov 7 19:06:51 2004 for Mango by doxygen 1.3.6