001package ca.uhn.hl7v2.hoh.encoder; 002 003import static org.junit.Assert.*; 004 005import java.io.ByteArrayInputStream; 006import java.io.ByteArrayOutputStream; 007import java.nio.charset.Charset; 008 009import org.junit.BeforeClass; 010import org.junit.Test; 011 012import ca.uhn.hl7v2.hoh.encoder.AbstractHl7OverHttpDecoder; 013import ca.uhn.hl7v2.hoh.encoder.Hl7OverHttpRequestDecoder; 014import ca.uhn.hl7v2.hoh.util.GZipUtils; 015import ca.uhn.hl7v2.hoh.util.SplitInputStream; 016 017public class Hl7OverHttpDecoderTest { 018 019 private static String ourSampleMessage; 020 private static String ourSampleMessageWithMultibyte; 021 022 @BeforeClass 023 public static void beforeClass() { 024 ourSampleMessage = "MSH|^~\\&|||||200803051508||ADT^A31|2|P|2.5\r" + 025 "EVN||200803051509\r" + 026 "PID|||ZZZZZZ83M64Z148R^^^SSN^SSN^^20070103\r"; 027 028 ourSampleMessageWithMultibyte = ourSampleMessage.replace("SSN", "Iā„HAPI"); 029 } 030 031 // TODO: add test to make sure that a request with chunked encoding can be decoded 032 033 @Test 034 public void testDecodeFromStream() throws Exception { 035 036 ByteArrayOutputStream bos = new ByteArrayOutputStream(); 037 String msg = "POST /AppName HTTP/1.1\r\n" + "Content-Type: application/hl7-v2; charset=ISO-8859-2\r\n" + "Content-Length: " + ourSampleMessage.getBytes("ISO-8859-1").length + "\r\n" + "Authorization: Basic aGVsbG86d29ybGQ=\r\n" + "\r\n"; 038 bos.write(msg.getBytes("ISO-8859-1")); 039 bos.write(ourSampleMessage.getBytes("ISO-8859-2")); 040 AbstractHl7OverHttpDecoder d = new Hl7OverHttpRequestDecoder(); 041 ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bos.toByteArray()); 042 d.readHeadersAndContentsFromInputStreamAndDecode(byteArrayInputStream); 043 044 assertEquals(0, byteArrayInputStream.available()); 045 assertTrue(d.getConformanceProblems().toString(), d.getConformanceProblems().isEmpty()); 046 assertEquals(Charset.forName("ISO-8859-2"), d.getCharset()); 047 assertTrue(d.isCharsetExplicitlySet()); 048 assertEquals("application/hl7-v2", d.getContentType()); 049 assertEquals(ourSampleMessage, d.getMessage()); 050 assertEquals("hello", d.getUsername()); 051 assertEquals("world", d.getPassword()); 052 assertEquals("/AppName", d.getPath()); 053 054 } 055 056 /** 057 * Allow malformed client to be processed correctly, per 058 * http://www.w3.org/Protocols/rfc2616/rfc2616-sec19.html#sec19.3 059 */ 060 @Test 061 public void testDecodeFromStreamWithHeaderLineEndingLF() throws Exception { 062 063 ByteArrayOutputStream bos = new ByteArrayOutputStream(); 064 String msg = "POST /AppName HTTP/1.1\n" + // - 065 "Content-Type: application/hl7-v2; charset=ISO-8859-2\n" + // - 066 "Content-Length: " + ourSampleMessage.getBytes("ISO-8859-1").length + "\n" + // - 067 "Authorization: Basic aGVsbG86d29ybGQ=\n" + // - 068 "\n"; 069 bos.write(msg.getBytes("ISO-8859-1")); 070 bos.write(ourSampleMessage.getBytes("ISO-8859-2")); 071 AbstractHl7OverHttpDecoder d = new Hl7OverHttpRequestDecoder(); 072 ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bos.toByteArray()); 073 d.readHeadersAndContentsFromInputStreamAndDecode(byteArrayInputStream); 074 075 assertEquals(0, byteArrayInputStream.available()); 076 assertTrue(d.getConformanceProblems().toString(), d.getConformanceProblems().isEmpty()); 077 assertEquals(Charset.forName("ISO-8859-2"), d.getCharset()); 078 assertTrue(d.isCharsetExplicitlySet()); 079 assertEquals("application/hl7-v2", d.getContentType()); 080 assertEquals(ourSampleMessage, d.getMessage()); 081 assertEquals("hello", d.getUsername()); 082 assertEquals("world", d.getPassword()); 083 assertEquals("/AppName", d.getPath()); 084 085 } 086 087 /** 088 * Allow malformed client to be processed correctly, per 089 * http://www.w3.org/Protocols/rfc2616/rfc2616-sec19.html#sec19.3 090 */ 091 @Test 092 public void testDecodeFromStreamWithWeirdHeaderLineSpaces() throws Exception { 093 094 ByteArrayOutputStream bos = new ByteArrayOutputStream(); 095 String msg = "POST \t\t /AppName \tHTTP/1.1\n" + // - 096 "Content-Type:\t\t application/hl7-v2; charset=ISO-8859-2\n" + // - 097 "Content-Length: " + ourSampleMessage.getBytes("ISO-8859-1").length + "\n" + // - 098 "Authorization:\t\t\t\t Basic aGVsbG86d29ybGQ=\n" + // - 099 "\n"; 100 bos.write(msg.getBytes("ISO-8859-1")); 101 bos.write(ourSampleMessage.getBytes("ISO-8859-2")); 102 AbstractHl7OverHttpDecoder d = new Hl7OverHttpRequestDecoder(); 103 ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bos.toByteArray()); 104 d.readHeadersAndContentsFromInputStreamAndDecode(byteArrayInputStream); 105 106 assertEquals(0, byteArrayInputStream.available()); 107 assertTrue(d.getConformanceProblems().toString(), d.getConformanceProblems().isEmpty()); 108 assertEquals(Charset.forName("ISO-8859-2"), d.getCharset()); 109 assertTrue(d.isCharsetExplicitlySet()); 110 assertEquals("application/hl7-v2", d.getContentType()); 111 assertEquals(ourSampleMessage, d.getMessage()); 112 assertEquals("hello", d.getUsername()); 113 assertEquals("world", d.getPassword()); 114 assertEquals("/AppName", d.getPath()); 115 116 } 117 118 @Test 119 public void testDecodeFromStreamWithTwoMessages() throws Exception { 120 121 ByteArrayOutputStream bos = new ByteArrayOutputStream(); 122 String msg = "POST /AppName HTTP/1.1\r\n" + "Content-Type: application/hl7-v2; charset=ISO-8859-2\r\n" + "Content-Length: " + ourSampleMessage.getBytes("ISO-8859-1").length + "\r\n" + "Authorization: Basic aGVsbG86d29ybGQ=\r\n" + "\r\n"; 123 bos.write(msg.getBytes("ISO-8859-1")); 124 bos.write(ourSampleMessage.getBytes("ISO-8859-2")); 125 126 // Double the message 127 bos.write(bos.toByteArray()); 128 129 AbstractHl7OverHttpDecoder d = new Hl7OverHttpRequestDecoder(); 130 ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bos.toByteArray()); 131 d.readHeadersAndContentsFromInputStreamAndDecode(byteArrayInputStream); 132 133 assertTrue(d.getConformanceProblems().toString(), d.getConformanceProblems().isEmpty()); 134 assertEquals(Charset.forName("ISO-8859-2"), d.getCharset()); 135 assertTrue(d.isCharsetExplicitlySet()); 136 assertEquals("application/hl7-v2", d.getContentType()); 137 assertEquals(ourSampleMessage, d.getMessage()); 138 assertEquals("hello", d.getUsername()); 139 assertEquals("world", d.getPassword()); 140 assertEquals("/AppName", d.getPath()); 141 142 // Read a second 143 144 d = new Hl7OverHttpRequestDecoder(); 145 d.readHeadersAndContentsFromInputStreamAndDecode(byteArrayInputStream); 146 147 assertEquals(0, byteArrayInputStream.available()); 148 assertTrue(d.getConformanceProblems().toString(), d.getConformanceProblems().isEmpty()); 149 assertEquals(Charset.forName("ISO-8859-2"), d.getCharset()); 150 assertTrue(d.isCharsetExplicitlySet()); 151 assertEquals("application/hl7-v2", d.getContentType()); 152 assertEquals(ourSampleMessage, d.getMessage()); 153 assertEquals("hello", d.getUsername()); 154 assertEquals("world", d.getPassword()); 155 assertEquals("/AppName", d.getPath()); 156 157 } 158 159 @Test 160 public void testDecodeFromStreamWithMultibyteSequences() throws Exception { 161 ByteArrayOutputStream bos = new ByteArrayOutputStream(); 162 String msg = "POST /AppName HTTP/1.1\r\n" + "Content-Type: application/hl7-v2; charset=UTF-8\r\n" + "Content-Length: " + ourSampleMessageWithMultibyte.getBytes("UTF-8").length + "\r\n" + "Authorization: Basic aGVsbG86d29ybGQ=\r\n" + "\r\n"; 163 bos.write(msg.getBytes("ISO-8859-1")); 164 bos.write(ourSampleMessageWithMultibyte.getBytes("UTF-8")); 165 AbstractHl7OverHttpDecoder d = new Hl7OverHttpRequestDecoder(); 166 ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bos.toByteArray()); 167 d.readHeadersAndContentsFromInputStreamAndDecode(byteArrayInputStream); 168 169 assertEquals(0, byteArrayInputStream.available()); 170 assertTrue(d.getConformanceProblems().toString(), d.getConformanceProblems().isEmpty()); 171 assertEquals(Charset.forName("UTF-8"), d.getCharset()); 172 assertTrue(d.isCharsetExplicitlySet()); 173 assertEquals("application/hl7-v2", d.getContentType()); 174 assertEquals(ourSampleMessageWithMultibyte, d.getMessage()); 175 assertEquals("hello", d.getUsername()); 176 assertEquals("world", d.getPassword()); 177 assertEquals("/AppName", d.getPath()); 178 179 } 180 181 @Test 182 public void testDecodeFromStreamWithCompression() throws Exception { 183 byte[] sampleMessage = GZipUtils.compress(ourSampleMessageWithMultibyte.getBytes("UTF-8")); 184 185 ByteArrayOutputStream bos = new ByteArrayOutputStream(); 186 String msg = "POST /AppName HTTP/1.1\r\n" + 187 "Content-Type: application/hl7-v2; charset=UTF-8\r\n" + 188 "Content-Length: " + sampleMessage.length + "\r\n" + 189 "Content-Encoding: gzip\r\n" + 190 "Authorization: Basic aGVsbG86d29ybGQ=\r\n" + "\r\n"; 191 192 bos.write(msg.getBytes("ISO-8859-1")); 193 bos.write(sampleMessage); 194 AbstractHl7OverHttpDecoder d = new Hl7OverHttpRequestDecoder(); 195 ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bos.toByteArray()); 196 d.readHeadersAndContentsFromInputStreamAndDecode(byteArrayInputStream); 197 198 assertEquals(0, byteArrayInputStream.available()); 199 assertTrue(d.getConformanceProblems().toString(), d.getConformanceProblems().isEmpty()); 200 assertEquals(Charset.forName("UTF-8"), d.getCharset()); 201 assertTrue(d.isCharsetExplicitlySet()); 202 assertEquals("application/hl7-v2", d.getContentType()); 203 assertEquals(ourSampleMessageWithMultibyte, d.getMessage()); 204 assertEquals("hello", d.getUsername()); 205 assertEquals("world", d.getPassword()); 206 assertEquals("/AppName", d.getPath()); 207 208 } 209 210 @Test 211 public void testDecodeFromStreamWithMultipleMessages() throws Exception { 212 213 ByteArrayOutputStream bos = new ByteArrayOutputStream(); 214 String msg = "POST /AppName HTTP/1.1\r\n" + "Content-Type: application/hl7-v2; charset=ISO-8859-2\r\n" + "Content-Length: " + ourSampleMessage.getBytes("ISO-8859-1").length + "\r\n" + "Authorization: Basic aGVsbG86d29ybGQ=\r\n" + "\r\n"; 215 216 bos.write(msg.getBytes("ISO-8859-1")); 217 bos.write(ourSampleMessage.getBytes("ISO-8859-2")); 218 bos.write(msg.getBytes("ISO-8859-1")); 219 bos.write(ourSampleMessage.getBytes("ISO-8859-2")); 220 221 ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bos.toByteArray()); 222 223 AbstractHl7OverHttpDecoder d = new Hl7OverHttpRequestDecoder(); 224 d.readHeadersAndContentsFromInputStreamAndDecode(byteArrayInputStream); 225 226 assertTrue(d.getConformanceProblems().toString(), d.getConformanceProblems().isEmpty()); 227 assertEquals(Charset.forName("ISO-8859-2"), d.getCharset()); 228 assertTrue(d.isCharsetExplicitlySet()); 229 assertEquals("application/hl7-v2", d.getContentType()); 230 assertEquals(ourSampleMessage, d.getMessage()); 231 assertEquals("hello", d.getUsername()); 232 assertEquals("world", d.getPassword()); 233 assertEquals("/AppName", d.getPath()); 234 235 d = new Hl7OverHttpRequestDecoder(); 236 d.readHeadersAndContentsFromInputStreamAndDecode(byteArrayInputStream); 237 238 assertEquals(0, byteArrayInputStream.available()); 239 assertTrue(d.getConformanceProblems().toString(), d.getConformanceProblems().isEmpty()); 240 assertEquals(Charset.forName("ISO-8859-2"), d.getCharset()); 241 assertTrue(d.isCharsetExplicitlySet()); 242 assertEquals("application/hl7-v2", d.getContentType()); 243 assertEquals(ourSampleMessage, d.getMessage()); 244 assertEquals("hello", d.getUsername()); 245 assertEquals("world", d.getPassword()); 246 assertEquals("/AppName", d.getPath()); 247 248 } 249 250 /** 251 * Simulate a network blip causing a delay mid-message 252 */ 253 @Test 254 public void testDecodeFromStreamWithPauseInTheMiddleOfMessage() throws Exception { 255 256 ByteArrayOutputStream bos = new ByteArrayOutputStream(); 257 String msg = "POST /AppName HTTP/1.1\r\n" + "Content-Type: application/hl7-v2; charset=ISO-8859-2\r\n" + "Content-Length: " + ourSampleMessage.getBytes("ISO-8859-1").length + "\r\n" + "Authorization: Basic aGVsbG86d29ybGQ=\r\n" + "\r\n"; 258 bos.write(msg.getBytes("ISO-8859-1")); 259 bos.write(ourSampleMessage.getBytes("ISO-8859-2")); 260 AbstractHl7OverHttpDecoder d = new Hl7OverHttpRequestDecoder(); 261 262 ByteArrayInputStream bais = new ByteArrayInputStream(bos.toByteArray()); 263 SplitInputStream is = new SplitInputStream(bais, msg.length() + 10); 264 265 d.readHeadersAndContentsFromInputStreamAndDecode(is); 266 267 assertEquals(0, bais.available()); 268 assertTrue(d.getConformanceProblems().toString(), d.getConformanceProblems().isEmpty()); 269 assertEquals(Charset.forName("ISO-8859-2"), d.getCharset()); 270 assertTrue(d.isCharsetExplicitlySet()); 271 assertEquals("application/hl7-v2", d.getContentType()); 272 assertEquals(ourSampleMessage, d.getMessage()); 273 assertEquals("hello", d.getUsername()); 274 assertEquals("world", d.getPassword()); 275 assertEquals("/AppName", d.getPath()); 276 277 } 278 279 /** 280 * Simulate a network blip causing a delay mid-message 281 */ 282 @Test 283 public void testDecodeFromStreamWithPauseInStatusLine() throws Exception { 284 285 ByteArrayOutputStream bos = new ByteArrayOutputStream(); 286 String msg = "POST /AppName HTTP/1.1\r\n" + "Content-Type: application/hl7-v2; charset=ISO-8859-2\r\n" + "Content-Length: " + ourSampleMessage.getBytes("ISO-8859-1").length + "\r\n" + "Authorization: Basic aGVsbG86d29ybGQ=\r\n" + "\r\n"; 287 bos.write(msg.getBytes("ISO-8859-1")); 288 bos.write(ourSampleMessage.getBytes("ISO-8859-2")); 289 AbstractHl7OverHttpDecoder d = new Hl7OverHttpRequestDecoder(); 290 291 ByteArrayInputStream bais = new ByteArrayInputStream(bos.toByteArray()); 292 SplitInputStream is = new SplitInputStream(bais, 5); 293 294 d.readHeadersAndContentsFromInputStreamAndDecode(is); 295 296 assertEquals(0, bais.available()); 297 assertTrue(d.getConformanceProblems().toString(), d.getConformanceProblems().isEmpty()); 298 assertEquals(Charset.forName("ISO-8859-2"), d.getCharset()); 299 assertTrue(d.isCharsetExplicitlySet()); 300 assertEquals("application/hl7-v2", d.getContentType()); 301 assertEquals(ourSampleMessage, d.getMessage()); 302 assertEquals("hello", d.getUsername()); 303 assertEquals("world", d.getPassword()); 304 assertEquals("/AppName", d.getPath()); 305 306 } 307 308 /** 309 * Simulate a network blip causing a delay mid-message 310 */ 311 @Test 312 public void testDecodeFromStreamWithPauseInMiddleOfHeaders() throws Exception { 313 314 ByteArrayOutputStream bos = new ByteArrayOutputStream(); 315 String msg = "POST /AppName HTTP/1.1\r\n" + "Content-Type: application/hl7-v2; charset=ISO-8859-2\r\n" + "Content-Length: " + ourSampleMessage.getBytes("ISO-8859-1").length + "\r\n" + "Authorization: Basic aGVsbG86d29ybGQ=\r\n" + "\r\n"; 316 bos.write(msg.getBytes("ISO-8859-1")); 317 bos.write(ourSampleMessage.getBytes("ISO-8859-2")); 318 AbstractHl7OverHttpDecoder d = new Hl7OverHttpRequestDecoder(); 319 320 ByteArrayInputStream bais = new ByteArrayInputStream(bos.toByteArray()); 321 SplitInputStream is = new SplitInputStream(bais, 30); 322 323 d.readHeadersAndContentsFromInputStreamAndDecode(is); 324 325 assertEquals(0, bais.available()); 326 assertTrue(d.getConformanceProblems().toString(), d.getConformanceProblems().isEmpty()); 327 assertEquals(Charset.forName("ISO-8859-2"), d.getCharset()); 328 assertTrue(d.isCharsetExplicitlySet()); 329 assertEquals("application/hl7-v2", d.getContentType()); 330 assertEquals(ourSampleMessage, d.getMessage()); 331 assertEquals("hello", d.getUsername()); 332 assertEquals("world", d.getPassword()); 333 assertEquals("/AppName", d.getPath()); 334 335 } 336}