]> granicus.if.org Git - apache/blob - include/http_protocol.h
Add the first draft of the http_filter. In time this filter will split
[apache] / include / http_protocol.h
1 /* ====================================================================
2  * The Apache Software License, Version 1.1
3  *
4  * Copyright (c) 2000 The Apache Software Foundation.  All rights
5  * reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  *
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  *
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in
16  *    the documentation and/or other materials provided with the
17  *    distribution.
18  *
19  * 3. The end-user documentation included with the redistribution,
20  *    if any, must include the following acknowledgment:
21  *       "This product includes software developed by the
22  *        Apache Software Foundation (http://www.apache.org/)."
23  *    Alternately, this acknowledgment may appear in the software itself,
24  *    if and wherever such third-party acknowledgments normally appear.
25  *
26  * 4. The names "Apache" and "Apache Software Foundation" must
27  *    not be used to endorse or promote products derived from this
28  *    software without prior written permission. For written
29  *    permission, please contact apache@apache.org.
30  *
31  * 5. Products derived from this software may not be called "Apache",
32  *    nor may "Apache" appear in their name, without prior written
33  *    permission of the Apache Software Foundation.
34  *
35  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
36  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
37  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
38  * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
39  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
40  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
41  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
42  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
43  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
44  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
45  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
46  * SUCH DAMAGE.
47  * ====================================================================
48  *
49  * This software consists of voluntary contributions made by many
50  * individuals on behalf of the Apache Software Foundation.  For more
51  * information on the Apache Software Foundation, please see
52  * <http://www.apache.org/>.
53  *
54  * Portions of this software are based upon public domain software
55  * originally written at the National Center for Supercomputing Applications,
56  * University of Illinois, Urbana-Champaign.
57  */
58
59 #ifndef APACHE_HTTP_PROTOCOL_H
60 #define APACHE_HTTP_PROTOCOL_H
61
62 #include "ap_hooks.h"
63 #include "apr_portable.h"
64 #include "apr_mmap.h"
65 #include "util_filter.h"
66 #include "ap_buckets.h"
67
68 #ifdef __cplusplus
69 extern "C" {
70 #endif
71
72 /**
73  * @package HTTP protocol handling
74  */
75
76 /*
77  * Prototypes for routines which either talk directly back to the user,
78  * or control the ones that eventually do.
79  */
80
81 /**
82  * Read a request and fill in the fields.
83  * @param c The current connection
84  * @return The new request_rec
85  */ 
86 request_rec *ap_read_request(conn_rec *c);
87
88 /**
89  * Send a single HTTP header field
90  * @param r The current request
91  * @param fieldname The Header field to send
92  * @param fieldval The value of the header
93  * @deffunc int ap_send_header_field(request_rec *r, const char *fieldname, const char *fieldval)
94  */
95 API_EXPORT_NONSTD(int) ap_send_header_field(request_rec *r, const char *fieldname,
96                       const char *fieldval);
97
98 /**
99  * Send the minimal part of an HTTP response header.
100  * @param r The current request
101  * @warning Modules should be very careful about using this, and should 
102  *          prefer ap_send_http_header().  Much of the HTTP/1.1 implementation 
103  *          correctness depends on code in ap_send_http_header().
104  * @deffunc void ap_basic_http_header(request_rec *r)
105  */
106 API_EXPORT(void) ap_basic_http_header(request_rec *r);
107
108 /**
109  * Send the Status-Line and header fields for HTTP response
110  * @param l The current request
111  * @deffunc void ap_send_http_header(request_rec *l)
112  */
113 API_EXPORT(void) ap_send_http_header(request_rec *l);
114
115 /* Send the response to special method requests */
116
117 API_EXPORT(int) ap_send_http_trace(request_rec *r);
118 int ap_send_http_options(request_rec *r);
119
120 /* Finish up stuff after a request */
121
122 /**
123  * Called at completion of sending the response.  It sends the terminating
124  * protocol information.
125  * @param r The current request
126  * @deffunc void ap_finalize_request_protocol(request_rec *r)
127  */
128 API_EXPORT(void) ap_finalize_request_protocol(request_rec *r);
129
130 /**
131  * Send error back to client.
132  * @param r The current request
133  * @param recursive_error last arg indicates error status in case we get 
134  *      an error in the process of trying to deal with an ErrorDocument 
135  *      to handle some other error.  In that case, we print the default 
136  *      report for the first thing that went wrong, and more briefly report 
137  *      on the problem with the ErrorDocument.
138  * @deffunc void ap_send_error_response(request_rec *r, int recursive_error)
139  */
140 API_EXPORT(void) ap_send_error_response(request_rec *r, int recursive_error);
141
142 /* Set last modified header line from the lastmod date of the associated file.
143  * Also, set content length.
144  *
145  * May return an error status, typically HTTP_NOT_MODIFIED (that when the
146  * permit_cache argument is set to one).
147  */
148
149 /**
150  * Set the content length for this request
151  * @param r The current request
152  * @param length The new content length
153  * @return Always 0, can be safely ignored
154  * @deffunc int ap_set_content_length(request_rec *r, long length)
155  */
156 API_EXPORT(int) ap_set_content_length(request_rec *r, long length);
157 /**
158  * Set the keepalive status for this request
159  * @param r The current request
160  * @return 1 if keepalive can be set, 0 otherwise
161  * @deffunc int ap_set_keepalive(request_rec *r)
162  */
163 API_EXPORT(int) ap_set_keepalive(request_rec *r);
164 /**
165  * Return the latest rational time from a request/mtime pair.  Mtime is 
166  * returned unless it's in the future, in which case we return the current time.
167  * @param r The current request
168  * @param mtime The last modified time
169  * @return the latest rational time.
170  * @deffunc apr_time_t ap_rationalize_mtime(request_rec *r, apr_time_t mtime)
171  */
172 API_EXPORT(apr_time_t) ap_rationalize_mtime(request_rec *r, apr_time_t mtime);
173 /**
174  * Construct an entity tag from the resource information.  If it's a real
175  * file, build in some of the file characteristics.
176  * @param r The current request
177  * @param force_weak Force the entity tag to be weak - it could be modified
178  *                   again in as short an interval.
179  * @return The entity tag
180  * @deffunc char *ap_make_etag(request_rec *r, int force_weak)
181  */ 
182 API_EXPORT(char *) ap_make_etag(request_rec *r, int force_weak);
183 /**
184  * Set the E-tag outgoing header
185  * @param The current request
186  * @deffunc void ap_set_etag(request_rec *r)
187  */
188 API_EXPORT(void) ap_set_etag(request_rec *r);
189 /**
190  * Set the last modified time for the file being sent
191  * @param r The current request
192  * @deffunc void ap_set_last_modified(request_rec *r)
193  */
194 API_EXPORT(void) ap_set_last_modified(request_rec *r);
195 /**
196  * Implements condition GET rules for HTTP/1.1 specification.  This function
197  * inspects the client headers and determines if the response fulfills 
198  * the requirements specified.
199  * @param r The current request
200  * @return 1 if the response fulfills the condition GET rules, 0 otherwise
201  * @deffunc int ap_meets_conditions(request_rec *r)
202  */
203 API_EXPORT(int) ap_meets_conditions(request_rec *r);
204
205 /* Other ways to send stuff at the client.  All of these keep track
206  * of bytes_sent automatically.  This indirection is intended to make
207  * it a little more painless to slide things like HTTP-NG packetization
208  * underneath the main body of the code later.  In the meantime, it lets
209  * us centralize a bit of accounting (bytes_sent).
210  *
211  * These also return the number of bytes written by the call.
212  * They should only be called with a timeout registered, for obvious reaasons.
213  * (Ditto the send_header stuff).
214  */
215
216 /**
217  * Send an entire file to the client, using sendfile if supported by the 
218  * current platform
219  * @param fd The file to send.
220  * @param r The current request
221  * @param offset Offset into the file to start sending.
222  * @param length Amount of data to send
223  * @param nbytes Amount of data actually sent
224  * @deffunc apr_status_t ap_send_fd(apr_file_t *fd, request_rec *r, apr_off_t offset, apr_size_t length, apr_size_t *nbytes);
225  */
226 API_EXPORT(apr_status_t) ap_send_fd(apr_file_t *fd, request_rec *r, apr_off_t offset, 
227                                    apr_size_t length, apr_size_t *nbytes);
228 /**
229  * Send the body of a response to the client
230  * @param f The BUFF structure associated with a client
231  * @param r The current request
232  * @return The number of bytes sent
233  * @deffunc long ap_send_fb(BUFF *f, request_rec *r)
234  */
235 API_EXPORT(long) ap_send_fb(BUFF *f, request_rec *r);
236 /**
237  * Send a specified number of bytes from the body of the response to the client
238  * @param f the BUFF structure associated with a client
239  * @param r The current request
240  * @param length The number of bytes to send
241  * @return The number of bytes sent
242  * @deffunc long ap_send_fb_length(BUFF *f, request_rec *r, long length)
243  */
244 API_EXPORT(long) ap_send_fb_length(BUFF *f, request_rec *r, long length);
245 /**
246  * Send an MMAP'ed file to the client
247  * @param mm The MMAP'ed file to send
248  * @param r The current request
249  * @param offset The offset into the MMAP to start sending
250  * @param length The amount of data to send
251  * @return The number of bytes sent
252  * @deffunc size_t ap_send_mmap(apr_mmap_t *mm, request_rec *r, size_t offset, size_t length)
253  */
254 API_EXPORT(size_t) ap_send_mmap(apr_mmap_t *mm, request_rec *r, size_t offset,
255                              size_t length);
256
257 /**
258  * Create a new method list with the specified number of preallocated
259  * slots for extension methods.
260  *
261  * @param   p       Pointer to a pool in which the structure should be
262  *                  allocated.
263  * @param   nelts   Number of preallocated extension slots
264  * @return  Pointer to the newly created structure.
265  * @deffunc ap_method_list_t ap_make_method_list(apr_pool_t *p, int nelts)
266  */
267 API_EXPORT(ap_method_list_t *) ap_make_method_list(apr_pool_t *p, int nelts);
268 API_EXPORT(void) ap_copy_method_list(ap_method_list_t *dest,
269                                      ap_method_list_t *src);
270 API_EXPORT_NONSTD(void) ap_method_list_do(int (*comp) (void *urec, const char *mname,
271                                                        int mnum),
272                                           void *rec,
273                                           const ap_method_list_t *ml, ...);
274 API_EXPORT(void) ap_method_list_vdo(int (*comp) (void *urec, const char *mname,
275                                                  int mnum),
276                                     void *rec, const ap_method_list_t *ml,
277                                     va_list vp);
278 /**
279  * Search for an HTTP method name in an ap_method_list_t structure, and
280  * return true if found.
281  *
282  * @param   method  String containing the name of the method to check.
283  * @param   l       Pointer to a method list, such as cmd->methods_limited.
284  * @return  1 if method is in the list, otherwise 0
285  * @deffunc int ap_method_in_list(const char *method, ap_method_list_t *l)
286  */
287 API_EXPORT(int) ap_method_in_list(ap_method_list_t *l, const char *method);
288
289 /**
290  * Add an HTTP method name to an ap_method_list_t structure if it isn't
291  * already listed.
292  *
293  * @param   method  String containing the name of the method to check.
294  * @param   l       Pointer to a method list, such as cmd->methods_limited.
295  * @return  None.
296  * @deffunc void ap_method_in_list(ap_method_list_t *l, const char *method)
297  */
298 API_EXPORT(void) ap_method_list_add(ap_method_list_t *l, const char *method);
299     
300 /**
301  * Remove an HTTP method name from an ap_method_list_t structure.
302  *
303  * @param   l       Pointer to a method list, such as cmd->methods_limited.
304  * @param   method  String containing the name of the method to remove.
305  * @return  None.
306  * @deffunc void ap_method_list_remove(ap_method_list_t *l, const char *method)
307  */
308 API_EXPORT(void) ap_method_list_remove(ap_method_list_t *l,
309                                        const char *method);
310
311 /**
312  * Reset a method list to be completely empty.
313  *
314  * @param   l       Pointer to a method list, such as cmd->methods_limited.
315  * @return  None.
316  * @deffunc void ap_clear_method_list(ap_method_list_t *l)
317  */
318 API_EXPORT(void) ap_clear_method_list(ap_method_list_t *l);
319     
320 /* Hmmm... could macrofy these for now, and maybe forever, though the
321  * definitions of the macros would get a whole lot hairier.
322  */
323
324 /**
325  * Output one character for this request
326  * @param c the character to output
327  * @param r the current request
328  * @return The number of bytes sent
329  * @deffunc int ap_rputc(int c, request_rec *r)
330  */
331 API_EXPORT(int) ap_rputc(int c, request_rec *r);
332 /**
333  * Output a string for the current request
334  * @param str The string to output
335  * @param r The current request
336  * @return The number of bytes sent
337  * @deffunc int ap_rputs(const char *str, request_rec *r)
338  */
339 API_EXPORT(int) ap_rputs(const char *str, request_rec *r);
340 /**
341  * Write a buffer for the current request
342  * @param buf The buffer to write
343  * @param nbyte The number of bytes to send from the buffer
344  * @param r The current request
345  * @return The number of bytes sent
346  * @deffunc int ap_rwrite(const void *buf, int nbyte, request_rec *r)
347  */
348 API_EXPORT(int) ap_rwrite(const void *buf, int nbyte, request_rec *r);
349 /**
350  * Write an unspecified number of strings to the request
351  * @param r The current request
352  * @param ... The strings to write
353  * @return The number of bytes sent
354  * @deffunc int ap_rvputs(request_rec *r, ...)
355  */
356 API_EXPORT_NONSTD(int) ap_rvputs(request_rec *r,...);
357 /**
358  * Output data to the client in a printf format
359  * @param r The current request
360  * @param fmt The format string
361  * @param vlist The arguments to use to fill out the format string
362  * @return The number of bytes sent
363  * @deffunc int ap_vrprintf(request_rec *r, const char *fmt, va_list vlist)
364  */
365 API_EXPORT(int) ap_vrprintf(request_rec *r, const char *fmt, va_list vlist);
366 /**
367  * Output data to the client in a printf format
368  * @param r The current request
369  * @param fmt The format string
370  * @param ... The arguments to use to fill out the format string
371  * @return The number of bytes sent
372  * @deffunc int ap_rprintf(request_rec *r, const char *fmt, ...)
373  */
374 API_EXPORT_NONSTD(int) ap_rprintf(request_rec *r, const char *fmt,...)
375                                 __attribute__((format(printf,2,3)));
376 /**
377  * Flush all of the data for the current request to the client
378  * @param r The current request
379  * @return The number of bytes sent
380  * @deffunc int ap_rflush(request_rec *r)
381  */
382 API_EXPORT(int) ap_rflush(request_rec *r);
383
384 /**
385  * Index used in custom_responses array for a specific error code
386  * (only use outside protocol.c is in getting them configured).
387  * @param status HTTP status code
388  * @return The index of the response
389  * @deffunc int ap_index_of_response(int status)
390  */
391 API_EXPORT(int) ap_index_of_response(int status);
392
393 /** 
394  * Return the Status-Line for a given status code (excluding the
395  * HTTP-Version field). If an invalid or unknown status code is
396  * passed, "500 Internal Server Error" will be returned. 
397  * @param status The HTTP status code
398  * @return The Status-Line
399  * @deffunc const char *ap_get_status_line(int status)
400  */
401 API_EXPORT(const char *) ap_get_status_line(int status);
402
403 /* Reading a block of data from the client connection (e.g., POST arg) */
404
405 /**
406  * Setup the client to allow Apache to read the request body.
407  * @param r The current request
408  * @param read_policy How the server should interpret a chunked 
409  *                    transfer-encoding.  One of: <PRE>
410  *    REQUEST_NO_BODY          Send 413 error if message has any body
411  *    REQUEST_CHUNKED_ERROR    Send 411 error if body without Content-Length
412  *    REQUEST_CHUNKED_DECHUNK  If chunked, remove the chunks for me.
413  *    REQUEST_CHUNKED_PASS     Pass the chunks to me without removal.
414  * </PRE>
415  * @return either OK or an error code
416  * @deffunc int ap_setup_cleint_block(request_rec *r, int read_policy)
417  */
418 API_EXPORT(int) ap_setup_client_block(request_rec *r, int read_policy);
419 /**
420  * Determine if the client has sent any data.  This also sends a 
421  * 100 Continue resposne to HTTP/1.1 clients, so modules should not be called
422  * until the module is ready to read content.
423  * @warning Never call this function more than once.
424  * @param r The current request
425  * @return 0 if there is no message to read, 1 otherwise
426  * @deffunc int ap_should_client_block(request_rec *r)
427  */
428 API_EXPORT(int) ap_should_client_block(request_rec *r);
429 /**
430  * Call this in a loop.  It will put data into a buffer and return the length
431  * of the input block
432  * @param r The current request
433  * @param buffer The buffer in which to store the data
434  * @param bufsiz The size of the buffer
435  * @return Number of bytes inserted into the buffer.  When done reading, 0
436  *         if EOF, or -1 if there was an error
437  * @deffunc long ap_get_client_block(request_rec *r, char *buffer, int bufsiz)
438  */
439 API_EXPORT(long) ap_get_client_block(request_rec *r, char *buffer, int bufsiz);
440 /**
441  * In HTTP/1.1, any method can have a body.  However, most GET handlers
442  * wouldn't know what to do with a request body if they received one.
443  * This helper routine tests for and reads any message body in the request,
444  * simply discarding whatever it receives.  We need to do this because
445  * failing to read the request body would cause it to be interpreted
446  * as the next request on a persistent connection.
447  * @param r The current request
448  * @return error status if request is malformed, OK otherwise 
449  * @deffunc int ap_discard_request_body(request_rec *r)
450  */
451 API_EXPORT(int) ap_discard_request_body(request_rec *r);
452
453 /* Sending a byterange */
454
455 /**
456  * Setup the request to send Byte Range requests
457  * @param r the current request
458  * @return 1 if request was setup for byte range requests, 0 otherwise
459  * @deffunc int ap_set_byterange(request_rec *r)
460  */
461 API_EXPORT(int) ap_set_byterange(request_rec *r);
462 /**
463  * Send one byte range chunk for a byte range request
464  * @param r The current request
465  * @param offset Set to the position it should be after the chunk is sent
466  * @param length Set to the length in should be after the chunk is sent
467  * @deffunc int ap_each_byterange(request_rec *r, apr_off_t *offset, apr_size_t *length)
468  */
469 API_EXPORT(int) ap_each_byterange(request_rec *r, apr_off_t *offset,
470                                   apr_size_t *length);
471 /**
472  * Setup the output headers so that the client knows how to authenticate
473  * itself the next time, if an authentication request failed.  This function
474  * works for both basic and digest authentication
475  * @param r The current request
476  * @deffunc void ap_note_auth_failure(request_rec *r)
477  */ 
478 API_EXPORT(void) ap_note_auth_failure(request_rec *r);
479 /**
480  * Setup the output headers so that the client knows how to authenticate
481  * itself the next time, if an authentication request failed.  This function
482  * works only for basic authentication
483  * @param r The current request
484  * @deffunc void ap_note_basic_auth_failure(request_rec *r)
485  */ 
486 API_EXPORT(void) ap_note_basic_auth_failure(request_rec *r);
487 /**
488  * Setup the output headers so that the client knows how to authenticate
489  * itself the next time, if an authentication request failed.  This function
490  * works only for digest authentication
491  * @param r The current request
492  * @deffunc void ap_note_digest_auth_failure(request_rec *r)
493  */ 
494 API_EXPORT(void) ap_note_digest_auth_failure(request_rec *r);
495 /**
496  * Get the password from the request headers
497  * @param r The current request
498  * @param pw The password as set in the headers
499  * @return 0 (OK) if it set the 'pw' argument (and assured
500  *         a correct value in r->connection->user); otherwise it returns 
501  *         an error code, either HTTP_INTERNAL_SERVER_ERROR if things are 
502  *         really confused, HTTP_UNAUTHORIZED if no authentication at all 
503  *         seemed to be in use, or DECLINED if there was authentication but 
504  *         it wasn't Basic (in which case, the caller should presumably 
505  *         decline as well).
506  * @deffunc int ap_get_basic_auth_pw(request_rec *r, const char **pw)
507  */
508 API_EXPORT(int) ap_get_basic_auth_pw(request_rec *r, const char **pw);
509
510 /*
511  * Setting up the protocol fields for subsidiary requests...
512  * Also, a wrapup function to keep the internal accounting straight.
513  */
514
515 void ap_set_sub_req_protocol(request_rec *rnew, const request_rec *r);
516 void ap_finalize_sub_req_protocol(request_rec *sub_r);
517
518 /**
519  * parse_uri: break apart the uri
520  * @warning Side Effects: <PRE>
521  *    - sets r->args to rest after '?' (or NULL if no '?')
522  *    - sets r->uri to request uri (without r->args part)
523  *    - sets r->hostname (if not set already) from request (scheme://host:port)
524  * </PRE>
525  * @param r The current request
526  * @param uri The uri to break apart
527  * @deffunc void ap_parse_uri(request_rec *r, const char *uri)
528  */
529 CORE_EXPORT(void) ap_parse_uri(request_rec *r, const char *uri);
530
531 /**
532  * Get the method number associated with the given string, assumed to
533  * contain an HTTP method.  Returns M_INVALID if not recognized.
534  * @param method A string containing a valid HTTP method
535  * @return The method number
536  * @deffunc int ap_method_number_of(const char *method)
537  */
538 API_EXPORT(int) ap_method_number_of(const char *method);
539
540 /**
541  * Get the method name associated with the given internal method
542  * number.  Returns NULL if not recognized.
543  * @param methnum An integer value corresponding to an internal method number
544  * @return The name corresponding to the method number
545  * @deffunc const char *ap_method_name_of(int methnum)
546  */
547 API_EXPORT(const char *) ap_method_name_of(int methnum);
548
549 int http_filter(ap_filter_t *f, ap_bucket_brigade *b);
550
551   /* Hooks */
552   /*
553    * post_read_request --- run right after read_request or internal_redirect,
554    *                  and not run during any subrequests.
555    */
556 /**
557  * This hook allows modules to affect the request immediately after the request
558  * has been read, and before any other phases have been processes.  This allows
559  * modules to make decisions based upon the input header fields
560  * @param r The current request
561  * @return OK or DECLINED
562  * @deffunc ap_run_post_read_request(request_rec *r)
563  */
564 AP_DECLARE_HOOK(int,post_read_request,(request_rec *))
565 /**
566  * This hook allows modules to perform any module-specific logging activities
567  * over and above the normal server things.
568  * @param r The current request
569  * @return OK, DECLINED, or HTTP_...
570  * @deffunc int ap_run_log_transaction(request_rec *r)
571  */
572 AP_DECLARE_HOOK(int,log_transaction,(request_rec *))
573 /**
574  * This hook allows modules to retrieve the http method from a request.  This
575  * allows Apache modules to easily extend the methods that Apache understands
576  * @param r The current request
577  * @return The http method from the request
578  * @deffunc const char *ap_run_http_method(const request_rec *r)
579  */
580 AP_DECLARE_HOOK(const char *,http_method,(const request_rec *))
581 /**
582  * Return the default port from the current request
583  * @param r The current request
584  * @return The current port
585  * @deffunc unsigned short ap_run_default_port(const request_rec *r)
586  */
587 AP_DECLARE_HOOK(unsigned short,default_port,(const request_rec *))
588
589 #ifdef __cplusplus
590 }
591 #endif
592
593 #endif  /* !APACHE_HTTP_PROTOCOL_H */