[System] HttpListenerRequest: ignore bad cookies and keep request alive (#5657)
[mono.git] / mcs / class / System / Test / System.Net / HttpListenerRequestTest.cs
1 //
2 // HttpListenerRequestTest.cs - Unit tests for System.Net.HttpListenerRequest
3 //
4 // Authors:
5 //      Gert Driesen (drieseng@users.sourceforge.net)
6 //      David Straw
7 //
8 // Copyright (C) 2007 Gert Driesen
9 //
10 // Permission is hereby granted, free of charge, to any person obtaining
11 // a copy of this software and associated documentation files (the
12 // "Software"), to deal in the Software without restriction, including
13 // without limitation the rights to use, copy, modify, merge, publish,
14 // distribute, sublicense, and/or sell copies of the Software, and to
15 // permit persons to whom the Software is furnished to do so, subject to
16 // the following conditions:
17 // 
18 // The above copyright notice and this permission notice shall be
19 // included in all copies or substantial portions of the Software.
20 // 
21 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
25 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
26 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
27 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28 //
29
30 using System;
31 using System.IO;
32 using System.Net;
33 using System.Net.NetworkInformation;
34 using System.Net.Sockets;
35 using System.Text;
36 using System.Collections.Generic;
37 using System.Threading.Tasks;
38
39 using NUnit.Framework;
40
41 using MonoTests.Helpers;
42
43 namespace MonoTests.System.Net
44 {
45         [TestFixture]
46         public class HttpListenerRequestTest
47         {
48                 [Test]
49                 [Category ("NotWorking")] // Bug #5742 
50                 public void HasEntityBody ()
51                 {
52                         HttpListenerContext ctx;
53                         HttpListenerRequest request;
54                         NetworkStream ns;
55                         var port = NetworkHelpers.FindFreePort ();
56                         HttpListener listener = HttpListener2Test.CreateAndStartListener (
57                                 "http://127.0.0.1:" + port + "/HasEntityBody/");
58
59                         // POST with non-zero Content-Lenth
60                         ns = HttpListener2Test.CreateNS (port);
61                         HttpListener2Test.Send (ns, "POST /HasEntityBody/ HTTP/1.1\r\nHost: 127.0.0.1\r\nContent-Length: 3\r\n\r\n123");
62                         ctx = listener.GetContext ();
63                         request = ctx.Request;
64                         Assert.IsTrue (request.HasEntityBody, "#A");
65                         HttpListener2Test.Send (ctx.Response.OutputStream, "%%%OK%%%");
66
67                         // POST with zero Content-Lenth
68                         ns = HttpListener2Test.CreateNS (port);
69                         HttpListener2Test.Send (ns, "POST /HasEntityBody/ HTTP/1.1\r\nHost: 127.0.0.1\r\nContent-Length: 0\r\n\r\n123");
70                         ctx = listener.GetContext ();
71                         request = ctx.Request;
72                         Assert.IsFalse (request.HasEntityBody, "#B");
73                         HttpListener2Test.Send (ctx.Response.OutputStream, "%%%OK%%%");
74
75                         // POST with chunked encoding
76                         ns = HttpListener2Test.CreateNS (port);
77                         HttpListener2Test.Send (ns, "POST /HasEntityBody HTTP/1.1\r\nHost: 127.0.0.1\r\nTransfer-Encoding: chunked\r\n\r\n0\r\n");
78                         ctx = listener.GetContext ();
79                         request = ctx.Request;
80                         Assert.IsTrue (request.HasEntityBody, "#C");
81                         HttpListener2Test.Send (ctx.Response.OutputStream, "%%%OK%%%");
82
83                         // GET with no Content-Length
84                         ns = HttpListener2Test.CreateNS (port);
85                         HttpListener2Test.Send (ns, "GET /HasEntityBody HTTP/1.1\r\nHost: 127.0.0.1\r\n\r\n");
86                         ctx = listener.GetContext ();
87                         request = ctx.Request;
88                         Assert.IsFalse (request.HasEntityBody, "#D");
89                         HttpListener2Test.Send (ctx.Response.OutputStream, "%%%OK%%%");
90
91                         // GET with non-zero Content-Length
92                         ns = HttpListener2Test.CreateNS (port);
93                         HttpListener2Test.Send (ns, "GET /HasEntityBody HTTP/1.1\r\nHost: 127.0.0.1\r\nContent-Length: 3\r\n\r\n");
94                         ctx = listener.GetContext ();
95                         request = ctx.Request;
96                         Assert.IsTrue (request.HasEntityBody, "#E");
97                         HttpListener2Test.Send (ctx.Response.OutputStream, "%%%OK%%%");
98
99                         // GET with zero Content-Length
100                         ns = HttpListener2Test.CreateNS (port);
101                         HttpListener2Test.Send (ns, "GET /HasEntityBody HTTP/1.1\r\nHost: 127.0.0.1\r\nContent-Length: 0\r\n\r\n");
102                         ctx = listener.GetContext ();
103                         request = ctx.Request;
104                         Assert.IsFalse (request.HasEntityBody, "#F");
105                         HttpListener2Test.Send (ctx.Response.OutputStream, "%%%OK%%%");
106
107                         // GET with chunked encoding
108                         ns = HttpListener2Test.CreateNS (port);
109                         HttpListener2Test.Send (ns, "GET /HasEntityBody HTTP/1.1\r\nHost: 127.0.0.1\r\nTransfer-Encoding: chunked\r\n\r\n0\r\n");
110                         ctx = listener.GetContext ();
111                         request = ctx.Request;
112                         Assert.IsTrue (request.HasEntityBody, "#G");
113                         HttpListener2Test.Send (ctx.Response.OutputStream, "%%%OK%%%");
114
115                         // PUT with non-zero Content-Lenth
116                         ns = HttpListener2Test.CreateNS (port);
117                         HttpListener2Test.Send (ns, "PUT /HasEntityBody/ HTTP/1.1\r\nHost: 127.0.0.1\r\nContent-Length: 3\r\n\r\n123");
118                         ctx = listener.GetContext ();
119                         request = ctx.Request;
120                         Assert.IsTrue (request.HasEntityBody, "#H");
121
122                         // PUT with zero Content-Lenth
123                         ns = HttpListener2Test.CreateNS (port);
124                         HttpListener2Test.Send (ns, "PUT /HasEntityBody/ HTTP/1.1\r\nHost: 127.0.0.1\r\nContent-Length: 0\r\n\r\n123");
125                         ctx = listener.GetContext ();
126                         request = ctx.Request;
127                         Assert.IsFalse (request.HasEntityBody, "#I");
128
129                         // INVALID with non-zero Content-Lenth
130                         ns = HttpListener2Test.CreateNS (port);
131                         HttpListener2Test.Send (ns, "INVALID /HasEntityBody/ HTTP/1.1\r\nHost: 127.0.0.1\r\nContent-Length: 3\r\n\r\n123");
132                         ctx = listener.GetContext ();
133                         request = ctx.Request;
134                         Assert.IsTrue (request.HasEntityBody, "#J");
135
136                         // INVALID with zero Content-Lenth
137                         ns = HttpListener2Test.CreateNS (port);
138                         HttpListener2Test.Send (ns, "INVALID /HasEntityBody/ HTTP/1.1\r\nHost: 127.0.0.1\r\nContent-Length: 0\r\n\r\n123");
139                         ctx = listener.GetContext ();
140                         request = ctx.Request;
141                         Assert.IsFalse (request.HasEntityBody, "#K");
142
143                         // INVALID with chunked encoding
144                         ns = HttpListener2Test.CreateNS (port);
145                         HttpListener2Test.Send (ns, "INVALID /HasEntityBody/ HTTP/1.1\r\nHost: 127.0.0.1\r\nTransfer-Encoding: chunked\r\n\r\n0\r\n");
146                         ctx = listener.GetContext ();
147                         request = ctx.Request;
148                         Assert.IsTrue (request.HasEntityBody, "#L");
149
150                         listener.Close ();
151                 }
152
153                 [Test]
154 #if FEATURE_NO_BSD_SOCKETS
155                 [ExpectedException (typeof (PlatformNotSupportedException))]
156 #endif
157                 public void HttpMethod ()
158                 {
159                         var port = NetworkHelpers.FindFreePort ();
160                         HttpListener listener = HttpListener2Test.CreateAndStartListener (
161                                 "http://127.0.0.1:" + port + "/HttpMethod/");
162                         NetworkStream ns = HttpListener2Test.CreateNS (port);
163                         HttpListener2Test.Send (ns, "pOsT /HttpMethod/ HTTP/1.1\r\nHost: 127.0.0.1\r\nContent-Length: 3\r\n\r\n123");
164                         HttpListenerContext ctx = listener.GetContext ();
165                         HttpListenerRequest request = ctx.Request;
166                         Assert.AreEqual ("pOsT", request.HttpMethod);
167                         listener.Close ();
168                 }
169
170                 [Test]
171 #if FEATURE_NO_BSD_SOCKETS
172                 [ExpectedException (typeof (PlatformNotSupportedException))]
173 #endif
174                 public void HttpBasicAuthScheme ()
175                 {
176                         var port = NetworkHelpers.FindFreePort ();                      
177                         HttpListener listener = HttpListener2Test.CreateAndStartListener ("http://*:" + port + "/authTest/", AuthenticationSchemes.Basic);
178                         //dummy-wait for context
179                         listener.BeginGetContext (null, listener);
180                         NetworkStream ns = HttpListener2Test.CreateNS (port);
181                         HttpListener2Test.Send (ns, "GET /authTest/ HTTP/1.0\r\n\r\n");
182                         String response = HttpListener2Test.Receive (ns, 512);
183                         Assert.IsTrue (response.Contains ("WWW-Authenticate: Basic realm"), "#A");
184                         ns.Close ();
185                         listener.Close ();
186                 }
187
188                 [Test]
189 #if FEATURE_NO_BSD_SOCKETS
190                 [ExpectedException (typeof (PlatformNotSupportedException))]
191 #endif
192                 public void HttpRequestUriIsNotDecoded ()
193                 {
194                         var port = NetworkHelpers.FindFreePort ();
195                         HttpListener listener = HttpListener2Test.CreateAndStartListener (
196                                 "http://127.0.0.1:" + port + "/RequestUriDecodeTest/");
197                         NetworkStream ns = HttpListener2Test.CreateNS (port);
198                         HttpListener2Test.Send (ns, "GET /RequestUriDecodeTest/?a=b&c=d%26e HTTP/1.1\r\nHost: 127.0.0.1\r\n\r\n");
199                         HttpListenerContext ctx = listener.GetContext ();
200                         HttpListenerRequest request = ctx.Request;
201                         Assert.AreEqual ("/RequestUriDecodeTest/?a=b&c=d%26e", request.Url.PathAndQuery);
202                         listener.Close ();
203                 }
204
205                 [Test]
206 #if FEATURE_NO_BSD_SOCKETS
207                 [ExpectedException (typeof (PlatformNotSupportedException))]
208 #endif
209                 public void HttpRequestIsLocal ()
210                 {
211                         var port = NetworkHelpers.FindFreePort ();
212                         var ips = new List<IPAddress> ();
213                         ips.Add (IPAddress.Loopback);
214                         foreach (var adapter in NetworkInterface.GetAllNetworkInterfaces ()) {
215                                 if (adapter.OperationalStatus != OperationalStatus.Up)
216                                         continue;
217                                 foreach (var ip in adapter.GetIPProperties ().UnicastAddresses) {
218                                         ips.Add (ip.Address);
219                                 }
220                         }
221
222                         foreach (var ip in ips) {
223                                 if (ip.AddressFamily != AddressFamily.InterNetwork)
224                                         continue;
225
226                                 HttpListener listener = HttpListener2Test.CreateAndStartListener (
227                                         "http://" + ip + ":" + port + "/HttpRequestIsLocal/");
228                                 NetworkStream ns = HttpListener2Test.CreateNS (ip, port);
229                                 HttpListener2Test.Send (ns, "GET /HttpRequestIsLocal/ HTTP/1.0\r\n\r\n");
230                                 HttpListenerContext ctx = listener.GetContext ();
231                                 HttpListenerRequest request = ctx.Request;
232                                 Assert.AreEqual (true, request.IsLocal, "IP " + ip + " is not local");
233                                 listener.Close ();
234                         }
235                 }
236
237                 [Test] // #29927
238 #if FEATURE_NO_BSD_SOCKETS
239                 [ExpectedException (typeof (PlatformNotSupportedException))]
240 #endif
241                 public void HttpRequestUriUnescape ()
242                 {
243                         var prefix = "http://localhost:" + NetworkHelpers.FindFreePort () + "/";
244                         var key = "Product/1";
245
246                         var expectedUrl = prefix + key + "/";
247                         var rawUrl = prefix + Uri.EscapeDataString (key) + "/";
248
249                         HttpListener listener = new HttpListener ();
250                         listener.Prefixes.Add (prefix);
251                         listener.Start ();
252
253                         var contextTask = listener.GetContextAsync ();
254
255                         var request = (HttpWebRequest) WebRequest.Create (rawUrl);
256                         request.GetResponseAsync ();
257
258                         Assert.IsTrue (contextTask.Wait (1000));
259
260                         Assert.AreEqual (expectedUrl, contextTask.Result.Request.Url.AbsoluteUri);
261
262                         listener.Close ();
263                 }
264
265                 [Test]
266 #if FEATURE_NO_BSD_SOCKETS
267                 [ExpectedException (typeof (PlatformNotSupportedException))]
268 #endif
269                 public void EmptyWrite ()
270                 {
271                         var prefix = "http://localhost:" + NetworkHelpers.FindFreePort () + "/";
272
273                         HttpListener listener = new HttpListener ();
274                         listener.Prefixes.Add (prefix);
275                         listener.Start ();
276
277                         Task.Run (() => {
278                                 var context = listener.GetContext ();
279
280                                 var s = context.Response.OutputStream;
281                                 s.Write (new byte[10], 0, 0);
282                                 return;
283                         });
284
285                         var request = (HttpWebRequest)WebRequest.Create (prefix);
286                         var rsp = request.GetResponseAsync ();
287                         Assert.IsFalse (rsp.Wait (1000), "Don't send on empty write");
288                 }
289
290                 [Test]
291                 public void HttpRequestIgnoreBadCookies ()
292                 {
293                         var port = NetworkHelpers.FindFreePort ();
294                         HttpListener listener = HttpListener2Test.CreateAndStartListener (
295                                 "http://127.0.0.1:" + port + "/HttpRequestIgnoreBadCookiesTest/");
296                         NetworkStream ns = HttpListener2Test.CreateNS (port);
297                         HttpListener2Test.Send (ns, "GET /HttpRequestIgnoreBadCookiesTest/?a=b HTTP/1.1\r\nHost: 127.0.0.1\r\nCookie: ELOQUA=GUID=5ca2346347357f4-f877-4eff-96aa-70fe0b677650; ELQSTATUS=OK; WRUID=609099666.123259461695; CommunityServer-UserCookie2101=lv=Thu, 26 Jul 2012 15:25:11 GMT&mra=Mon, 01 Oct 2012 17:40:05 GMT; PHPSESSID=1234dg3opfjb4qafp0oo645; __utma=9761706.1153317537.1357240270.1357240270.1357317902.2; __utmb=9761706.6.10.1357317902; __utmc=9761706; __utmz=9761706.1357240270.1.1.utmcsr=test.testdomain.com|utmccn=(referral)|utmcmd=referral|utmcct=/test/1234\r\n\r\n");
298                         HttpListenerContext ctx = listener.GetContext ();
299                         HttpListenerRequest request = ctx.Request;
300                         Assert.AreEqual ("/HttpRequestIgnoreBadCookiesTest/?a=b", request.Url.PathAndQuery);
301                         listener.Close ();
302                 }
303         }
304 }