Merge pull request #3269 from alexanderkyte/silence_zero_len
[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
38 using NUnit.Framework;
39
40 using MonoTests.Helpers;
41
42 namespace MonoTests.System.Net
43 {
44         [TestFixture]
45         [Category ("RequiresBSDSockets")]
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                 public void HttpMethod ()
155                 {
156                         var port = NetworkHelpers.FindFreePort ();
157                         HttpListener listener = HttpListener2Test.CreateAndStartListener (
158                                 "http://127.0.0.1:" + port + "/HttpMethod/");
159                         NetworkStream ns = HttpListener2Test.CreateNS (port);
160                         HttpListener2Test.Send (ns, "pOsT /HttpMethod/ HTTP/1.1\r\nHost: 127.0.0.1\r\nContent-Length: 3\r\n\r\n123");
161                         HttpListenerContext ctx = listener.GetContext ();
162                         HttpListenerRequest request = ctx.Request;
163                         Assert.AreEqual ("pOsT", request.HttpMethod);
164                         listener.Close ();
165                 }
166
167                 [Test]
168                 public void HttpBasicAuthScheme ()
169                 {
170                         var port = NetworkHelpers.FindFreePort ();                      
171                         HttpListener listener = HttpListener2Test.CreateAndStartListener ("http://*:" + port + "/authTest/", AuthenticationSchemes.Basic);
172                         //dummy-wait for context
173                         listener.BeginGetContext (null, listener);
174                         NetworkStream ns = HttpListener2Test.CreateNS (port);
175                         HttpListener2Test.Send (ns, "GET /authTest/ HTTP/1.0\r\n\r\n");
176                         String response = HttpListener2Test.Receive (ns, 512);
177                         Assert.IsTrue (response.Contains ("WWW-Authenticate: Basic realm"), "#A");
178                         ns.Close ();
179                         listener.Close ();
180                 }
181
182                 [Test]
183                 public void HttpRequestUriIsNotDecoded ()
184                 {
185                         var port = NetworkHelpers.FindFreePort ();
186                         HttpListener listener = HttpListener2Test.CreateAndStartListener (
187                                 "http://127.0.0.1:" + port + "/RequestUriDecodeTest/");
188                         NetworkStream ns = HttpListener2Test.CreateNS (port);
189                         HttpListener2Test.Send (ns, "GET /RequestUriDecodeTest/?a=b&c=d%26e HTTP/1.1\r\nHost: 127.0.0.1\r\n\r\n");
190                         HttpListenerContext ctx = listener.GetContext ();
191                         HttpListenerRequest request = ctx.Request;
192                         Assert.AreEqual ("/RequestUriDecodeTest/?a=b&c=d%26e", request.Url.PathAndQuery);
193                         listener.Close ();
194                 }
195
196                 [Test]
197                 public void HttpRequestIsLocal ()
198                 {
199                         var port = NetworkHelpers.FindFreePort ();
200                         var ips = new List<IPAddress> ();
201                         ips.Add (IPAddress.Loopback);
202                         foreach (var adapter in NetworkInterface.GetAllNetworkInterfaces ()) {
203                                 foreach (var ip in adapter.GetIPProperties ().UnicastAddresses) {
204                                         ips.Add (ip.Address);
205                                 }
206                         }
207
208                         foreach (var ip in ips) {
209                                 if (ip.AddressFamily != AddressFamily.InterNetwork)
210                                         continue;
211
212                                 HttpListener listener = HttpListener2Test.CreateAndStartListener (
213                                         "http://" + ip + ":" + port + "/HttpRequestIsLocal/");
214                                 NetworkStream ns = HttpListener2Test.CreateNS (ip, port);
215                                 HttpListener2Test.Send (ns, "GET /HttpRequestIsLocal/ HTTP/1.0\r\n\r\n");
216                                 HttpListenerContext ctx = listener.GetContext ();
217                                 HttpListenerRequest request = ctx.Request;
218                                 Assert.AreEqual (true, request.IsLocal, "IP " + ip + " is not local");
219                                 listener.Close ();
220                         }
221                 }
222
223                 [Test] // #29927
224                 public void HttpRequestUriUnescape ()
225                 {
226                         var prefix = "http://localhost:" + NetworkHelpers.FindFreePort () + "/";
227                         var key = "Product/1";
228
229                         var expectedUrl = prefix + key + "/";
230                         var rawUrl = prefix + Uri.EscapeDataString (key) + "/";
231
232                         HttpListener listener = new HttpListener ();
233                         listener.Prefixes.Add (prefix);
234                         listener.Start ();
235
236                         var contextTask = listener.GetContextAsync ();
237
238                         var request = (HttpWebRequest) WebRequest.Create (rawUrl);
239                         request.GetResponseAsync ();
240
241                         if(!contextTask.Wait (1000))
242                                 Assert.Fail ("Timeout");
243
244                         Assert.AreEqual (expectedUrl, contextTask.Result.Request.Url.AbsoluteUri);
245
246                         listener.Close ();
247                 }
248         }
249 }