From a5fbd0a7d47ffdae5b41f09016d0658de1d1204c Mon Sep 17 00:00:00 2001
From: Mladen Turk Apache HTTP Server Version 2.1 Available Languages: en This module requires the service of Thus, in order to get the ability of handling Do not enable proxying until you have secured your server. Open proxy
+ servers are dangerous both to your network and to the Internet at
+ large. This module provides no
+ directives. The Once a connection is assigned to a particular request, it will not be
+ used for any others until the request-handling cycle has terminated. In
+ other words, requests are not multiplexed over connections. This makes
+ for much simpler code at either end of the connection, although it does
+ cause more connections to be open at once. Once the web server has opened a connection to the servlet container,
+ the connection can be in one of the following states: Once a connection is assigned to handle a particular request, the basic
+ request informaton (e.g. HTTP headers, etc) is sent over the connection in
+ a highly condensed form (e.g. common strings are encoded as integers).
+ Details of that format are below in Request Packet Structure. If there is a
+ body to the request At this point, the servlet container is presumably ready to start
+ processing the request. As it does so, it can send the
+ following messages back to the web server:
+ Each message is accompanied by a differently formatted packet of data.
+ See Response Packet Structures below for details. There is a bit of an XDR heritage to this protocol, but it differs
+ in lots of ways (no 4 byte alignment, for example). Byte order: I am not clear about the endian-ness of the individual
+ bytes. I'm guessing the bytes are little-endian, because that's what
+ XDR specifies, and I'm guessing that sys/socket library is magically
+ making that so (on the C side). If anyone with a better knowledge of
+ socket calls can step in, that would be great. There are four data types in the protocol: bytes, booleans,
+ integers and strings.
+ According to much of the code, the max packet size is Packets sent from the server to the container begin with
+ For most packets, the first byte of the payload encodes the type of
+ message. The exception is for request body packets sent from the server to
+ the container -- they are sent with a standard packet header ( The web server can send the following messages to the servlet container:
+ To ensure some basic security, the container will only actually do the
+ The first The servlet container can send the following types of messages to the
+ webserver:
+ Each of the above messages has a different internal structure, detailed
+ below. For messages from the server to the container of type
+ Forward Request: The The Not that the all-important header is For all requests, this will be 2. See above for details on other Prefix
+ codes. The HTTP method, encoded as a single byte: Later version of ajp13, will transport
+ additional methods, even if they are not in this list. These are all fairly self-explanatory. Each of these is required, and
+ will be sent for every request. The structure of The Java code that reads this grabs the first two-byte integer and if
+ it sees an This works on the assumption that no header names will have length
+ greater than The attributes prefixed with a The The The The Beyond this list of basic attributes, any number of other attributes
+ can be sent via the Finally, after all the attributes have been sent, the attribute
+ terminator, for messages which the container can send back to the server. The chunk is basically binary data, and is sent directly back to the
+ browser. The status code and message are the usual HTTP things
+ (e.g. After the code or the string header name, the header value is
+ immediately encoded. Signals the end of this request-handling cycle. If the
+ The container asks for more data from the request (If the body was
+ too large to fit in the first packet sent over or when the request is
+ chuncked). The server will send a body packet back with an amount of data
+ which is the minimum of the Available Languages: en This module requires the service of Thus, in order to get the ability of handling Do not enable proxying until you have secured your server. Open proxy
+ servers are dangerous both to your network and to the Internet at
+ large. The Once a connection is assigned to a particular request, it will not be
+ used for any others until the request-handling cycle has terminated. In
+ other words, requests are not multiplexed over connections. This makes
+ for much simpler code at either end of the connection, although it does
+ cause more connections to be open at once. Once the web server has opened a connection to the servlet container,
+ the connection can be in one of the following states:Apache Module mod_proxy_ajp
+
+
+Description: AJP support module for
+ mod_proxy
+Status: Extension
+Module Identifier: proxy_ajp_module Source File: proxy_ajp.c Summary
+
+ mod_proxy
. It provides support for the
+ Apache JServ Protocol version 1.3
(hereafter
+ AJP13).AJP13
+ protocol, mod_proxy
and
+ mod_proxy_ajp
have to be present in the server.Warning
+ Directives
+Topics
+
+
Overview of the protocol
Basic Packet Structure
Request Packet Structure
Response Packet Structure
See also
+
+
mod_proxy
Overview of the protocol
+ AJP13
protocol is packet-oriented. A binary format
+ was presumably chosen over the more readable plain text for reasons of
+ performance. The web server communicates with the servlet container over
+ TCP connections. To cut down on the expensive process of socket creation,
+ the web server will attempt to maintain persistent TCP connections to the
+ servlet container, and to reuse a connection for multiple request/response
+ cycles.
+
+
No request is being handled over this connection.
The connecton is handling a specific request.(content-length > 0)
, that is sent in a
+ separate packet immediately after.
+
+
Send a set of headers back to the browser.
Send a chunk of body data back to the browser.
+
Get further data from the request if it hasn't all
+ been transferred yet. This is necessary because the packets have a fixed
+ maximum size and arbitrary amounts of data can be included the body of a
+ request (for uploaded files, for example). (Note: this is unrelated to
+ HTTP chunked tranfer).
Finish the request-handling cycle.Basic Packet Structure
+
+
+
+ 1 = true
, 0 = false
.
+ Using other non-zero values as true (i.e. C-style) may work in some places,
+ but it won't in others.0 to 2^16 (32768)
. Stored in
+ 2 bytes with the high-order byte first.strlen
. This is a touch confusing on the Java side, which
+ is littered with odd autoincrement statements to skip over these
+ terminators. I believe the reason this was done was to allow the C
+ code to be extra efficient when reading strings which the servlet
+ container is sending back -- with the terminating \0 character, the
+ C code can pass around references into a single buffer, without copying.
+ if the \0 was missing, the C code would have to copy things out in order
+ to get its notion of a string.Packet Size
+
+ 8 * 1024 bytes (8K)
. The actual length of the packet is encoded in
+ the header.Packet Headers
+ 0x1234
. Packets sent from the container to the server
+ begin with AB
(that's the ASCII code for A followed by the
+ ASCII code for B). After those first two bytes, there is an integer
+ (encoded as above) with the length of the payload. Although this might
+ suggest that the maximum payload could be as large as 2^16, in fact, the
+ code sets the maximum to be 8K.
+
+
+
+
+ Packet Format (Server->Container)
+
+
+ Byte
+ 0
+ 1
+ 2
+ 3
+ 4...(n+3)
+
+
+ Contents
+ 0x12
+ 0x34
+ Data Length (n)
+ Data
+
+
+
+
+ Packet Format (Container->Server)
+
+
+ Byte
+ 0
+ 1
+ 2
+ 3
+ 4...(n+3)
+
+
+ Contents
+ A
+ B
+ Data Length (n)
+ Data
+
+ 0x1234
and then length of the packet), but without any prefix code
+ after that.
+
+
+
+ Code
+ Type of Packet
+ Meaning
+
+
+ 2
+ Forward Request
+ Begin the request-processing cycle with the following data
+
+
+ 7
+ Shutdown
+ The web server asks the container to shut itself down.
+
+
+ 8
+ Ping
+ The web server asks the container to take control
+ (secure login phase).
+
+
+ 10
+ CPing
+ The web server asks the container to respond quickly with a CPong.
+
+
+
+ none
+ Data
+ Size (2 bytes) and corresponding body data.
+ Shutdown
if the request comes from the same machine on which
+ it's hosted.Data
packet is send immediatly after the
+ Forward Request
by the web server.
+
+
+
+ Code
+ Type of Packet
+ Meaning
+
+
+ 3
+ Send Body Chunk
+ Send a chunk of the body from the servlet container to the web
+ server (and presumably, onto the browser).
+
+
+ 4
+ Send Headers
+ Send the response headers from the servlet container to the web
+ server (and presumably, onto the browser).
+
+
+ 5
+ End Response
+ Marks the end of the response (and thus the request-handling cycle).
+
+
+
+ 6
+ Get Body Chunk
+ Get further data from the request if it hasn't all been
+ transferred yet.
+
+
+ 9
+ CPong Reply
+ The reply to a CPing request
+ Request Packet Structure
+
+AJP13_FORWARD_REQUEST :=
+ prefix_code (byte) 0x02 = JK_AJP13_FORWARD_REQUEST
+ method (byte)
+ protocol (string)
+ req_uri (string)
+ remote_addr (string)
+ remote_host (string)
+ server_name (string)
+ server_port (integer)
+ is_ssl (boolean)
+ num_headers (integer)
+ request_headers *(req_header_name req_header_value)
+ attributes *(attribut_name attribute_value)
+ request_terminator (byte) OxFF
+
request_headers
have the following structure:
+
+req_header_name :=
+ sc_req_header_name | (string) [see below for how this is parsed]
+
+sc_req_header_name := 0xA0xx (integer)
+
+req_header_value := (string)
+
attributes
are optional and have the following
+ structure:
+attribute_name := sc_a_name | (sc_a_req_attribute string)
+
+attribute_value := (string)
+
+
content-length
,
+ because it determines whether or not the container looks for another
+ packet immediately.Detailed description of the elements of Forward Request
+
+ Request prefix
+ Method
+
+
+
+ Command Name Code
+ OPTIONS 1
+ GET 2
+ HEAD 3
+ POST 4
+ PUT 5
+ DELETE 6
+ TRACE 7
+ PROPFIND 8
+ PROPPATCH 9
+ MKCOL 10
+ COPY 11
+ MOVE 12
+ LOCK 13
+ UNLOCK 14
+ ACL 15
+ REPORT 16
+ VERSION-CONTROL 17
+ CHECKIN 18
+ CHECKOUT 19
+ UNCHECKOUT 20
+ SEARCH 21
+ MKWORKSPACE 22
+ UPDATE 23
+ LABEL 24
+ MERGE 25
+ BASELINE_CONTROL 26
+ MKACTIVITY 27 protocol, req_uri, remote_addr, remote_host, server_name,
+ server_port, is_ssl
+ Headers
+ request_headers
is the following:
+ First, the number of headers num_headers
is encoded.
+ Then, a series of header name req_header_name
/ value
+ req_header_value
pairs follows.
+ Common header names are encoded as integers,
+ to save space. If the header name is not in the list of basic headers,
+ it is encoded normally (as a string, with prefixed length). The list of
+ common headers sc_req_header_name
and their codes
+ is as follows (all are case-sensitive):
+
+
+ Name Code value Code name
+ accept 0xA001 SC_REQ_ACCEPT
+ accept-charset 0xA002 SC_REQ_ACCEPT_CHARSET
+
+ accept-encoding 0xA003 SC_REQ_ACCEPT_ENCODING
+
+ accept-language 0xA004 SC_REQ_ACCEPT_LANGUAGE
+
+ authorization 0xA005 SC_REQ_AUTHORIZATION
+
+ connection 0xA006 SC_REQ_CONNECTION
+ content-type 0xA007 SC_REQ_CONTENT_TYPE
+
+ content-length 0xA008 SC_REQ_CONTENT_LENGTH
+
+ cookie 0xA009 SC_REQ_COOKIE
+ cookie2 0xA00A SC_REQ_COOKIE2
+ host 0xA00B SC_REQ_HOST
+ pragma 0xA00C SC_REQ_PRAGMA
+ referer 0xA00D SC_REQ_REFERER
+ user-agent 0xA00E SC_REQ_USER_AGENT '0xA0'
in the most significant
+ byte, it uses the integer in the second byte as an index into an array of
+ header names. If the first byte is not 0xA0
, it assumes that
+ the two-byte integer is the length of a string, which is then read in.0x9999 (==0xA000 - 1)
, which is perfectly
+ reasonable, though somewhat arbitrary.Note:
+ The content-length
header is extremely
+ important. If it is present and non-zero, the container assumes that
+ the request has a body (a POST request, for example), and immediately
+ reads a separate packet off the input stream to get that body.
+ Attributes
+ ?
+ (e.g. ?context
) are all optional. For each, there is a
+ single byte code to indicate the type of attribute, and then a string to
+ give its value. They can be sent in any order (thogh the C code always
+ sends them in the order listed below). A special terminating code is
+ sent to signal the end of the list of optional attributes. The list of
+ byte codes is:
+
+
+ Information Code Value Note
+ ?context 0x01 Not currently implemented
+
+ ?servlet_path 0x02 Not currently implemented
+
+ ?remote_user 0x03
+ ?auth_type 0x04
+ ?query_string 0x05
+ ?jvm_route 0x06
+ ?ssl_cert 0x07
+ ?ssl_cipher 0x08
+ ?ssl_session 0x09
+ ?req_attribute 0x0A Name (the name of the
+ attribute follows)
+ ?ssl_key_size 0x0B
+ are_done 0xFF request_terminator context
and servlet_path
are not
+ currently set by the C code, and most of the Java code completely ignores
+ whatever is sent over for those fields (and some of it will actually break
+ if a string is sent along after one of those codes). I don't know if this
+ is a bug or an unimplemented feature or just vestigial code, but it's
+ missing from both sides of the connection.remote_user
and auth_type
presumably
+ refer to HTTP-level authentication, and communicate the remote user's
+ username and the type of authentication used to establish their identity
+ (e.g. Basic, Digest).query_string
, ssl_cert
,
+ ssl_cipher
, and ssl_session
refer to the
+ corresponding pieces of HTTP and HTTPS.jvm_route
, is used to support sticky
+ sessions -- associating a user's sesson with a particular Tomcat instance
+ in the presence of multiple, load-balancing servers.req_attribute
code 0x0A
.
+ A pair of strings to represent the attribute name and value are sent
+ immediately after each instance of that code. Environment values are passed
+ in via this method.0xFF
, is sent. This signals both the end of the
+ list of attributes and also then end of the Request Packet.Response Packet Structure
+
+AJP13_SEND_BODY_CHUNK :=
+ prefix_code 3
+ chunk_length (integer)
+ chunk *(byte)
+
+
+AJP13_SEND_HEADERS :=
+ prefix_code 4
+ http_status_code (integer)
+ http_status_msg (string)
+ num_headers (integer)
+ response_headers *(res_header_name header_value)
+
+res_header_name :=
+ sc_res_header_name | (string) [see below for how this is parsed]
+
+sc_res_header_name := 0xA0 (byte)
+
+header_value := (string)
+
+AJP13_END_RESPONSE :=
+ prefix_code 5
+ reuse (boolean)
+
+
+AJP13_GET_BODY_CHUNK :=
+ prefix_code 6
+ requested_length (integer)
+
Details:
+ Send Body Chunk
+ Send Headers
+ 200
and OK
). The response header names are
+ encoded the same way the request header names are. See header_encoding above
+ for details about how the the codes are distinguished from the strings.
+ The codes for common headers are:
+
+
+ Name Code value
+ Content-Type 0xA001
+ Content-Language 0xA002
+ Content-Length 0xA003
+ Date 0xA004
+ Last-Modified 0xA005
+ Location 0xA006
+ Set-Cookie 0xA007
+ Set-Cookie2 0xA008
+ Servlet-Engine 0xA009
+ Status 0xA00A
+ WWW-Authenticate 0xA00B End Response
+ reuse
flag is true (==1)
, this TCP connection can
+ now be used to handle new incoming requests. If reuse
is false
+ (anything other than 1 in the actual C code), the connection should
+ be closed.Get Body Chunk
+ request_length
, the maximum send
+ body size (8186 (8 Kbytes - 6))
, and the number of bytes
+ actually left to send from the request body.
+ If there is no more data in the body (i.e. the servlet container is
+ trying to read past the end of the body), the server will send back an
+ empty packet, which is a body packet with a payload length of 0.
+ (0x12,0x34,0x00,0x00)
Apache JServ Protocol version 1.3
(hereafter
+ AJP13).AJP13
+ protocol, AJP13
protocol is packet-oriented. A binary format
+ was presumably chosen over the more readable plain text for reasons of
+ performance. The web server communicates with the servlet container over
+ TCP connections. To cut down on the expensive process of socket creation,
+ the web server will attempt to maintain persistent TCP connections to the
+ servlet container, and to reuse a connection for multiple request/response
+ cycles.
+
No request is being handled over this connection.
The connecton is handling a specific request.
Once a connection is assigned to handle a particular request, the basic
+ request informaton (e.g. HTTP headers, etc) is sent over the connection in
+ a highly condensed form (e.g. common strings are encoded as integers).
+ Details of that format are below in Request Packet Structure. If there is a
+ body to the request (content-length > 0)
, that is sent in a
+ separate packet immediately after.
At this point, the servlet container is presumably ready to start + processing the request. As it does so, it can send the + following messages back to the web server: +
Each message is accompanied by a differently formatted packet of data. + See Response Packet Structures below for details.
+ + +There is a bit of an XDR heritage to this protocol, but it differs + in lots of ways (no 4 byte alignment, for example).
+Byte order: I am not clear about the endian-ness of the individual + bytes. I'm guessing the bytes are little-endian, because that's what + XDR specifies, and I'm guessing that sys/socket library is magically + making that so (on the C side). If anyone with a better knowledge of + socket calls can step in, that would be great.
+There are four data types in the protocol: bytes, booleans, + integers and strings. +
1 = true
, 0 = false
.
+ Using other non-zero values as true (i.e. C-style) may work in some places,
+ but it won't in others.0 to 2^16 (32768)
. Stored in
+ 2 bytes with the high-order byte first.strlen
. This is a touch confusing on the Java side, which
+ is littered with odd autoincrement statements to skip over these
+ terminators. I believe the reason this was done was to allow the C
+ code to be extra efficient when reading strings which the servlet
+ container is sending back -- with the terminating \0 character, the
+ C code can pass around references into a single buffer, without copying.
+ if the \0 was missing, the C code would have to copy things out in order
+ to get its notion of a string.According to much of the code, the max packet size is
+ 8 * 1024 bytes (8K)
. The actual length of the packet is encoded in
+ the header.
Packets sent from the server to the container begin with
+ 0x1234
. Packets sent from the container to the server
+ begin with AB
(that's the ASCII code for A followed by the
+ ASCII code for B). After those first two bytes, there is an integer
+ (encoded as above) with the length of the payload. Although this might
+ suggest that the maximum payload could be as large as 2^16, in fact, the
+ code sets the maximum to be 8K.
+
Packet Format (Server->Container) | +|||||
Byte | +0 | +1 | +2 | +3 | +4...(n+3) | +
Contents | +0x12 | +0x34 | +Data Length (n) | +Data | +
Packet Format (Container->Server) | +|||||
Byte | +0 | +1 | +2 | +3 | +4...(n+3) | +
Contents | +A | +B | +Data Length (n) | +Data | +
For most packets, the first byte of the payload encodes the type of
+ message. The exception is for request body packets sent from the server to
+ the container -- they are sent with a standard packet header (
+ 0x1234
and then length of the packet), but without any prefix code
+ after that.
The web server can send the following messages to the servlet container: +
Code | +Type of Packet | +Meaning | +
2 | +Forward Request | +Begin the request-processing cycle with the following data | +
7 | +Shutdown | +The web server asks the container to shut itself down. | +
8 | +Ping | +The web server asks the container to take control + (secure login phase). | +
10 | +CPing | +The web server asks the container to respond quickly with a CPong. + | +
none | +Data | +Size (2 bytes) and corresponding body data. | +
To ensure some basic security, the container will only actually do the
+ Shutdown
if the request comes from the same machine on which
+ it's hosted.
The first Data
packet is send immediatly after the
+ Forward Request
by the web server.
The servlet container can send the following types of messages to the + webserver: +
Code | +Type of Packet | +Meaning | +
3 | +Send Body Chunk | +Send a chunk of the body from the servlet container to the web + server (and presumably, onto the browser). | +
4 | +Send Headers | +Send the response headers from the servlet container to the web + server (and presumably, onto the browser). | +
5 | +End Response | +Marks the end of the response (and thus the request-handling cycle). + | +
6 | +Get Body Chunk | +Get further data from the request if it hasn't all been + transferred yet. | +
9 | +CPong Reply | +The reply to a CPing request | +
Each of the above messages has a different internal structure, detailed + below.
+For messages from the server to the container of type + Forward Request:
++AJP13_FORWARD_REQUEST := + prefix_code (byte) 0x02 = JK_AJP13_FORWARD_REQUEST + method (byte) + protocol (string) + req_uri (string) + remote_addr (string) + remote_host (string) + server_name (string) + server_port (integer) + is_ssl (boolean) + num_headers (integer) + request_headers *(req_header_name req_header_value) + attributes *(attribut_name attribute_value) + request_terminator (byte) OxFF +
The request_headers
have the following structure:
+
+req_header_name := + sc_req_header_name | (string) [see below for how this is parsed] + +sc_req_header_name := 0xA0xx (integer) + +req_header_value := (string) +
The attributes
are optional and have the following
+ structure:
+attribute_name := sc_a_name | (sc_a_req_attribute string) + +attribute_value := (string) + +
Not that the all-important header is content-length
,
+ because it determines whether or not the container looks for another
+ packet immediately.
For all requests, this will be 2. See above for details on other Prefix + codes.
+The HTTP method, encoded as a single byte:
+Command Name | Code |
OPTIONS | 1 |
GET | 2 |
HEAD | 3 |
POST | 4 |
PUT | 5 |
DELETE | 6 |
TRACE | 7 |
PROPFIND | 8 |
PROPPATCH | 9 |
MKCOL | 10 |
COPY | 11 |
MOVE | 12 |
LOCK | 13 |
UNLOCK | 14 |
ACL | 15 |
REPORT | 16 |
VERSION-CONTROL | 17 |
CHECKIN | 18 |
CHECKOUT | 19 |
UNCHECKOUT | 20 |
SEARCH | 21 |
MKWORKSPACE | 22 |
UPDATE | 23 |
LABEL | 24 |
MERGE | 25 |
BASELINE_CONTROL | 26 |
MKACTIVITY | 27 |
Later version of ajp13, will transport + additional methods, even if they are not in this list.
+These are all fairly self-explanatory. Each of these is required, and + will be sent for every request.
+The structure of request_headers
is the following:
+ First, the number of headers num_headers
is encoded.
+ Then, a series of header name req_header_name
/ value
+ req_header_value
pairs follows.
+ Common header names are encoded as integers,
+ to save space. If the header name is not in the list of basic headers,
+ it is encoded normally (as a string, with prefixed length). The list of
+ common headers sc_req_header_name
and their codes
+ is as follows (all are case-sensitive):
Name | Code value | Code name |
accept | 0xA001 | SC_REQ_ACCEPT |
accept-charset | 0xA002 | SC_REQ_ACCEPT_CHARSET + |
accept-encoding | 0xA003 | SC_REQ_ACCEPT_ENCODING + |
accept-language | 0xA004 | SC_REQ_ACCEPT_LANGUAGE + |
authorization | 0xA005 | SC_REQ_AUTHORIZATION | +
connection | 0xA006 | SC_REQ_CONNECTION |
content-type | 0xA007 | SC_REQ_CONTENT_TYPE | +
content-length | 0xA008 | SC_REQ_CONTENT_LENGTH | +
cookie | 0xA009 | SC_REQ_COOKIE |
cookie2 | 0xA00A | SC_REQ_COOKIE2 |
host | 0xA00B | SC_REQ_HOST |
pragma | 0xA00C | SC_REQ_PRAGMA |
referer | 0xA00D | SC_REQ_REFERER |
user-agent | 0xA00E | SC_REQ_USER_AGENT |
The Java code that reads this grabs the first two-byte integer and if
+ it sees an '0xA0'
in the most significant
+ byte, it uses the integer in the second byte as an index into an array of
+ header names. If the first byte is not 0xA0
, it assumes that
+ the two-byte integer is the length of a string, which is then read in.
This works on the assumption that no header names will have length
+ greater than 0x9999 (==0xA000 - 1)
, which is perfectly
+ reasonable, though somewhat arbitrary.
content-length
header is extremely
+ important. If it is present and non-zero, the container assumes that
+ the request has a body (a POST request, for example), and immediately
+ reads a separate packet off the input stream to get that body.
+ The attributes prefixed with a ?
+ (e.g. ?context
) are all optional. For each, there is a
+ single byte code to indicate the type of attribute, and then a string to
+ give its value. They can be sent in any order (thogh the C code always
+ sends them in the order listed below). A special terminating code is
+ sent to signal the end of the list of optional attributes. The list of
+ byte codes is:
Information | Code Value | Note |
?context | 0x01 | Not currently implemented + |
?servlet_path | 0x02 | Not currently implemented + |
?remote_user | 0x03 | |
?auth_type | 0x04 | |
?query_string | 0x05 | |
?jvm_route | 0x06 | |
?ssl_cert | 0x07 | |
?ssl_cipher | 0x08 | |
?ssl_session | 0x09 | |
?req_attribute | 0x0A | Name (the name of the + attribute follows) |
?ssl_key_size | 0x0B | |
are_done | 0xFF | request_terminator |
The context
and servlet_path
are not
+ currently set by the C code, and most of the Java code completely ignores
+ whatever is sent over for those fields (and some of it will actually break
+ if a string is sent along after one of those codes). I don't know if this
+ is a bug or an unimplemented feature or just vestigial code, but it's
+ missing from both sides of the connection.
The remote_user
and auth_type
presumably
+ refer to HTTP-level authentication, and communicate the remote user's
+ username and the type of authentication used to establish their identity
+ (e.g. Basic, Digest).
The query_string
, ssl_cert
,
+ ssl_cipher
, and ssl_session
refer to the
+ corresponding pieces of HTTP and HTTPS.
The jvm_route
, is used to support sticky
+ sessions -- associating a user's sesson with a particular Tomcat instance
+ in the presence of multiple, load-balancing servers.
Beyond this list of basic attributes, any number of other attributes
+ can be sent via the req_attribute
code 0x0A
.
+ A pair of strings to represent the attribute name and value are sent
+ immediately after each instance of that code. Environment values are passed
+ in via this method.
Finally, after all the attributes have been sent, the attribute
+ terminator, 0xFF
, is sent. This signals both the end of the
+ list of attributes and also then end of the Request Packet.
for messages which the container can send back to the server.
++AJP13_SEND_BODY_CHUNK := + prefix_code 3 + chunk_length (integer) + chunk *(byte) + + +AJP13_SEND_HEADERS := + prefix_code 4 + http_status_code (integer) + http_status_msg (string) + num_headers (integer) + response_headers *(res_header_name header_value) + +res_header_name := + sc_res_header_name | (string) [see below for how this is parsed] + +sc_res_header_name := 0xA0 (byte) + +header_value := (string) + +AJP13_END_RESPONSE := + prefix_code 5 + reuse (boolean) + + +AJP13_GET_BODY_CHUNK := + prefix_code 6 + requested_length (integer) +
The chunk is basically binary data, and is sent directly back to the + browser.
+The status code and message are the usual HTTP things
+ (e.g. 200
and OK
). The response header names are
+ encoded the same way the request header names are. See header_encoding above
+ for details about how the the codes are distinguished from the strings.
+ The codes for common headers are:
Name | Code value |
Content-Type | 0xA001 |
Content-Language | 0xA002 |
Content-Length | 0xA003 |
Date | 0xA004 |
Last-Modified | 0xA005 |
Location | 0xA006 |
Set-Cookie | 0xA007 |
Set-Cookie2 | 0xA008 |
Servlet-Engine | 0xA009 |
Status | 0xA00A |
WWW-Authenticate | 0xA00B |
After the code or the string header name, the header value is + immediately encoded.
+Signals the end of this request-handling cycle. If the
+ reuse
flag is true (==1)
, this TCP connection can
+ now be used to handle new incoming requests. If reuse
is false
+ (anything other than 1 in the actual C code), the connection should
+ be closed.
The container asks for more data from the request (If the body was
+ too large to fit in the first packet sent over or when the request is
+ chuncked). The server will send a body packet back with an amount of data
+ which is the minimum of the request_length
, the maximum send
+ body size (8186 (8 Kbytes - 6))
, and the number of bytes
+ actually left to send from the request body.
+ If there is no more data in the body (i.e. the servlet container is
+ trying to read past the end of the body), the server will send back an
+ empty packet, which is a body packet with a payload length of 0.
+ (0x12,0x34,0x00,0x00)