1
2
3
4
5
6
7
8
9
10
11
12
13
14 package ch.mimo.netty.handler.codec.icap;
15
16 import java.util.List;
17
18 import org.jboss.netty.buffer.ChannelBuffer;
19
20
21
22
23
24
25
26
27
28 public class ReadIcapHeaderState extends State<Object> {
29
30 private static final String SYNTHETIC_ENCAPSULATED_HEADER_VALUE = "null-body=0";
31
32 public ReadIcapHeaderState(String name) {
33 super(name);
34 }
35
36 @Override
37 public void onEntry(ChannelBuffer buffer, IcapMessageDecoder icapMessageDecoder) throws DecodingException {
38 if(icapMessageDecoder.message == null) {
39 throw new IllegalArgumentException("This state requires a valid IcapMessage instance");
40 }
41 }
42
43 @Override
44 public StateReturnValue execute(ChannelBuffer buffer, IcapMessageDecoder icapMessageDecoder) throws DecodingException {
45 List<String[]> headerList = IcapDecoderUtil.readHeaders(buffer,icapMessageDecoder.maxIcapHeaderSize);
46 icapMessageDecoder.message.clearHeaders();
47 for(String[] header : headerList) {
48 icapMessageDecoder.message.addHeader(header[0],header[1]);
49 }
50 boolean isRequest = icapMessageDecoder.message instanceof IcapRequest;
51 boolean isOptionsRequest = isRequest && ((IcapRequest)icapMessageDecoder.message).getMethod().equals(IcapMethod.OPTIONS);
52
53 handleEncapsulationHeaderVolatility(icapMessageDecoder.message);
54 validateMandatoryMessageHeaders(icapMessageDecoder.message);
55
56 Encapsulated encapsulated = null;
57 String headerValue = icapMessageDecoder.message.getHeader(IcapHeaders.Names.ENCAPSULATED);
58 if(headerValue != null) {
59 encapsulated = new Encapsulated(icapMessageDecoder.message.getHeader(IcapHeaders.Names.ENCAPSULATED));
60 icapMessageDecoder.message.setEncapsulatedHeader(encapsulated);
61 }
62 if(isOptionsRequest) {
63 return StateReturnValue.createRelevantResult(icapMessageDecoder.message);
64 } else if(encapsulated != null && !encapsulated.containsEntry(IcapMessageElementEnum.REQHDR) & !encapsulated.containsEntry(IcapMessageElementEnum.RESHDR)) {
65 return StateReturnValue.createRelevantResult(icapMessageDecoder.message);
66 }
67 return StateReturnValue.createIrrelevantResult();
68 }
69
70 @Override
71 public StateEnum onExit(ChannelBuffer buffer, IcapMessageDecoder icapMessageDecoder, Object decisionInformation) throws DecodingException {
72 IcapMessage message = icapMessageDecoder.message;
73 Encapsulated encapsulated = message.getEncapsulatedHeader();
74 if(message instanceof IcapRequest && ((IcapRequest)message).getMethod().equals(IcapMethod.OPTIONS)) {
75 if(encapsulated != null && encapsulated.containsEntry(IcapMessageElementEnum.OPTBODY)) {
76 return StateEnum.READ_CHUNK_SIZE_STATE;
77 } else {
78 return null;
79 }
80 } else {
81 IcapMessageElementEnum entry = encapsulated.getNextEntry();
82 if(entry != null) {
83 if(entry.equals(IcapMessageElementEnum.REQHDR)) {
84 return StateEnum.READ_HTTP_REQUEST_INITIAL_AND_HEADERS;
85 } else if(entry.equals(IcapMessageElementEnum.RESHDR)) {
86 return StateEnum.READ_HTTP_RESPONSE_INITIAL_AND_HEADERS;
87 } else if(entry.equals(IcapMessageElementEnum.REQBODY)) {
88 return StateEnum.READ_CHUNK_SIZE_STATE;
89 } else if(entry.equals(IcapMessageElementEnum.RESBODY)) {
90 return StateEnum.READ_CHUNK_SIZE_STATE;
91 }
92 }
93 }
94 return null;
95 }
96
97 private void validateMandatoryMessageHeaders(IcapMessage message) {
98 if(!(message instanceof IcapResponse)) {
99 if(!message.containsHeader(IcapHeaders.Names.HOST)) {
100 throw new IcapDecodingError("Mandatory ICAP message header [Host] is missing");
101 }
102 }
103 if(!message.containsHeader(IcapHeaders.Names.ENCAPSULATED)) {
104 throw new IcapDecodingError("Mandatory ICAP message header [Encapsulated] is missing");
105 }
106 }
107
108
109
110
111
112
113
114
115
116
117 private void handleEncapsulationHeaderVolatility(IcapMessage message) {
118
119
120
121
122 boolean requiresSynthecticEncapsulationHeader = false;
123 if(!message.containsHeader(IcapHeaders.Names.ENCAPSULATED)) {
124 if(message instanceof IcapRequest && ((IcapRequest)message).getMethod().equals(IcapMethod.OPTIONS)) {
125 requiresSynthecticEncapsulationHeader = true;
126 } else if(message instanceof IcapResponse) {
127 IcapResponse response = (IcapResponse)message;
128 IcapResponseStatus status = response.getStatus();
129 if(status.equals(IcapResponseStatus.CONTINUE) | status.equals(IcapResponseStatus.NO_CONTENT)) {
130 requiresSynthecticEncapsulationHeader = true;
131 }
132 }
133 }
134
135 if(requiresSynthecticEncapsulationHeader) {
136 message.addHeader(IcapHeaders.Names.ENCAPSULATED,SYNTHETIC_ENCAPSULATED_HEADER_VALUE);
137 }
138 }
139 }