├── src └── CodeScales.Http │ ├── CodeScales.Http.Tests │ ├── resources │ │ ├── small-text.txt │ │ ├── logo.png │ │ ├── ResourceManager.cs │ │ └── big-text.txt │ ├── NameValueColl.cs │ ├── Properties │ │ └── AssemblyInfo.cs │ ├── Constants.cs │ ├── CodeScales.Http.Tests.csproj │ ├── MessageData.cs │ ├── HttpRedirectTests.cs │ ├── HttpGetTests.cs │ └── HttpPostTests.cs │ ├── CodeScales.Http.Tests.Server │ ├── HttpGet200.aspx │ ├── HttpGet302.aspx │ ├── HttpPost200.aspx │ ├── HttpRedirectTarget1.aspx │ ├── HttpMultipartPost200.aspx │ ├── HttpGet200WithSetCookies.aspx │ ├── SendPostRequest.htm │ ├── SendMultipartPostRequest.htm │ ├── AspNetUpload.aspx │ ├── HttpGet200.aspx.designer.cs │ ├── HttpGet302.aspx.designer.cs │ ├── HttpPost200.aspx.designer.cs │ ├── HttpMultipartPost200.aspx.designer.cs │ ├── HttpRedirectTarget1.aspx.designer.cs │ ├── HttpGet200WithSetCookies.aspx.designer.cs │ ├── AspNetUpload.aspx.cs │ ├── HttpGet302.aspx.cs │ ├── Web.config │ ├── Properties │ │ └── AssemblyInfo.cs │ ├── AspNetUpload.aspx.designer.cs │ ├── HttpRedirectTarget1.aspx.cs │ ├── HttpPost200.aspx.cs │ ├── HttpGet200WithSetCookies.aspx.cs │ ├── HttpGet200.aspx.cs │ ├── HttpMultipartPost200.aspx.cs │ └── CodeScales.Http.Tests.Server.csproj │ ├── CodeScales.Http.Examples │ ├── Program.cs │ ├── HttpPostExamples.cs │ ├── Properties │ │ └── AssemblyInfo.cs │ ├── CodeScales.Http.Examples.csproj │ └── HttpGetExample.cs │ ├── CodeScales.Http │ ├── Entity │ │ ├── BasicHttpEntity.cs │ │ ├── HttpEntityEnclosingRequest.cs │ │ ├── HttpEntity.cs │ │ ├── Mime │ │ │ ├── Body.cs │ │ │ ├── InputStreamBody.cs │ │ │ ├── StringBody.cs │ │ │ └── FileBody.cs │ │ ├── AbstractHttpEntity.cs │ │ ├── EntityUtils.cs │ │ ├── UrlEncodedFormEntity.cs │ │ └── MultipartEntity.cs │ ├── Network │ │ ├── HttpNetworkException.cs │ │ ├── HttpConnectionFactory.cs │ │ ├── HttpProtocol.cs │ │ └── HttpConnection.cs │ ├── Methods │ │ ├── HttpRequest.cs │ │ ├── HttpMessageBase.cs │ │ ├── HttpResponse.cs │ │ ├── HttpGet.cs │ │ └── HttpPost.cs │ ├── Common │ │ └── NameValuePair.cs │ ├── Properties │ │ └── AssemblyInfo.cs │ ├── Cookies │ │ ├── HttpCookie.cs │ │ ├── HttpCookieCollection.cs │ │ └── HttpCookieStore.cs │ ├── Protocol │ │ └── HTTP.cs │ ├── CodeScales.Http.csproj │ ├── HttpBehavior.cs │ └── HttpClient.cs │ └── CodeScales.Http.sln └── README.md /src/CodeScales.Http/CodeScales.Http.Tests/resources/small-text.txt: -------------------------------------------------------------------------------- 1 | this is a test -------------------------------------------------------------------------------- /src/CodeScales.Http/CodeScales.Http.Tests/resources/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yaroncon/c-sharp-http-client/HEAD/src/CodeScales.Http/CodeScales.Http.Tests/resources/logo.png -------------------------------------------------------------------------------- /src/CodeScales.Http/CodeScales.Http.Tests.Server/HttpGet200.aspx: -------------------------------------------------------------------------------- 1 | <%@ Page Language="C#" AutoEventWireup="true" CodeBehind="HttpGet200.aspx.cs" Inherits="CodeScales.Http.Tests.Server.HttpGet200" %> 2 | 3 | -------------------------------------------------------------------------------- /src/CodeScales.Http/CodeScales.Http.Tests.Server/HttpGet302.aspx: -------------------------------------------------------------------------------- 1 | <%@ Page Language="C#" AutoEventWireup="true" CodeBehind="HttpGet302.aspx.cs" Inherits="CodeScales.Http.Tests.Server.HttpGet302" %> 2 | 3 | -------------------------------------------------------------------------------- /src/CodeScales.Http/CodeScales.Http.Tests.Server/HttpPost200.aspx: -------------------------------------------------------------------------------- 1 | <%@ Page Language="C#" AutoEventWireup="true" CodeBehind="HttpPost200.aspx.cs" Inherits="CodeScales.Http.Tests.Server.HttpPost200" %> 2 | 3 | -------------------------------------------------------------------------------- /src/CodeScales.Http/CodeScales.Http.Tests.Server/HttpRedirectTarget1.aspx: -------------------------------------------------------------------------------- 1 | <%@ Page Language="C#" AutoEventWireup="true" CodeBehind="HttpRedirectTarget1.aspx.cs" Inherits="CodeScales.Http.Tests.Server.HttpRedirectTarget1" %> 2 | 3 | -------------------------------------------------------------------------------- /src/CodeScales.Http/CodeScales.Http.Tests.Server/HttpMultipartPost200.aspx: -------------------------------------------------------------------------------- 1 | <%@ Page Language="C#" AutoEventWireup="true" CodeBehind="HttpMultipartPost200.aspx.cs" Inherits="CodeScales.Http.Tests.Server.HttpMultipartPost200" %> 2 | 3 | -------------------------------------------------------------------------------- /src/CodeScales.Http/CodeScales.Http.Tests.Server/HttpGet200WithSetCookies.aspx: -------------------------------------------------------------------------------- 1 | <%@ Page Language="C#" AutoEventWireup="true" CodeBehind="HttpGet200WithSetCookies.aspx.cs" Inherits="CodeScales.Http.Tests.Server.HttpGet200WithSetCookies" %> 2 | 3 | -------------------------------------------------------------------------------- /src/CodeScales.Http/CodeScales.Http.Examples/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace CodeScales.Http.Examples 6 | { 7 | class Program 8 | { 9 | static void Main(string[] args) 10 | { 11 | HttpPostExamples.DoPost(); 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/CodeScales.Http/CodeScales.Http.Tests.Server/SendPostRequest.htm: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Untitled Page 5 | 6 | 7 |
8 | 9 | 10 | 11 |
12 | 13 | 14 | -------------------------------------------------------------------------------- /src/CodeScales.Http/CodeScales.Http.Tests.Server/SendMultipartPostRequest.htm: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Untitled Page 5 | 6 | 7 |
8 |
9 |
10 |
11 | 12 |
13 | 14 | 15 | -------------------------------------------------------------------------------- /src/CodeScales.Http/CodeScales.Http.Tests.Server/AspNetUpload.aspx: -------------------------------------------------------------------------------- 1 | <%@ Page Language="C#" AutoEventWireup="true" CodeBehind="AspNetUpload.aspx.cs" Inherits="CodeScales.Http.Tests.Server.AspNetUpload" %> 2 | 3 | 4 | 5 | 6 | 7 | Untitled Page 8 | 9 | 10 |
11 |
12 |
13 | 15 |
16 |
17 | 18 | 19 | -------------------------------------------------------------------------------- /src/CodeScales.Http/CodeScales.Http.Tests.Server/HttpGet200.aspx.designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:2.0.50727.1873 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace CodeScales.Http.Tests.Server { 12 | 13 | 14 | /// 15 | /// HttpGet200 class. 16 | /// 17 | /// 18 | /// Auto-generated class. 19 | /// 20 | public partial class HttpGet200 { 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/CodeScales.Http/CodeScales.Http.Tests.Server/HttpGet302.aspx.designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:2.0.50727.1873 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace CodeScales.Http.Tests.Server { 12 | 13 | 14 | /// 15 | /// HttpGet302 class. 16 | /// 17 | /// 18 | /// Auto-generated class. 19 | /// 20 | public partial class HttpGet302 { 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/CodeScales.Http/CodeScales.Http.Tests.Server/HttpPost200.aspx.designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:2.0.50727.3603 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace CodeScales.Http.Tests.Server { 12 | 13 | 14 | /// 15 | /// HttpPost200 class. 16 | /// 17 | /// 18 | /// Auto-generated class. 19 | /// 20 | public partial class HttpPost200 { 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/CodeScales.Http/CodeScales.Http.Tests.Server/HttpMultipartPost200.aspx.designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:2.0.50727.4927 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace CodeScales.Http.Tests.Server { 12 | 13 | 14 | /// 15 | /// HttpMultipartPost200 class. 16 | /// 17 | /// 18 | /// Auto-generated class. 19 | /// 20 | public partial class HttpMultipartPost200 { 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/CodeScales.Http/CodeScales.Http.Tests.Server/HttpRedirectTarget1.aspx.designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:2.0.50727.1873 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace CodeScales.Http.Tests.Server { 12 | 13 | 14 | /// 15 | /// HttpRedirectTarget1 class. 16 | /// 17 | /// 18 | /// Auto-generated class. 19 | /// 20 | public partial class HttpRedirectTarget1 { 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/CodeScales.Http/CodeScales.Http.Tests.Server/HttpGet200WithSetCookies.aspx.designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:2.0.50727.3603 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace CodeScales.Http.Tests.Server { 12 | 13 | 14 | /// 15 | /// HttpGet200WithSetCookies class. 16 | /// 17 | /// 18 | /// Auto-generated class. 19 | /// 20 | public partial class HttpGet200WithSetCookies { 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/CodeScales.Http/CodeScales.Http/Entity/BasicHttpEntity.cs: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2010 CodeScales.com 2 | * 3 | * Licensed under the Apache License, Version 2.0 (the "License"); 4 | * you may not use this file except in compliance with the License. 5 | * You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | * See the License for the specific language governing permissions and 13 | * limitations under the License. 14 | */ 15 | 16 | using System; 17 | using System.Collections.Generic; 18 | using System.Text; 19 | 20 | namespace CodeScales.Http.Entity 21 | { 22 | public class BasicHttpEntity : AbstractHttpEntity 23 | { 24 | 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/CodeScales.Http/CodeScales.Http.Tests/NameValueColl.cs: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2010 CodeScales.com 2 | * 3 | * Licensed under the Apache License, Version 2.0 (the "License"); 4 | * you may not use this file except in compliance with the License. 5 | * You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | * See the License for the specific language governing permissions and 13 | * limitations under the License. 14 | */ 15 | 16 | using System; 17 | using System.Collections.Generic; 18 | using System.Text; 19 | 20 | using CodeScales.Http.Common; 21 | 22 | namespace CodeScales.Http.Tests 23 | { 24 | [Serializable] 25 | public class NameValueColl : List 26 | { 27 | 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/CodeScales.Http/CodeScales.Http/Entity/HttpEntityEnclosingRequest.cs: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2010 CodeScales.com 2 | * 3 | * Licensed under the Apache License, Version 2.0 (the "License"); 4 | * you may not use this file except in compliance with the License. 5 | * You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | * See the License for the specific language governing permissions and 13 | * limitations under the License. 14 | */ 15 | 16 | using System; 17 | using System.Collections.Generic; 18 | using System.Text; 19 | 20 | namespace CodeScales.Http.Entity 21 | { 22 | public interface HttpEntityEnclosingRequest 23 | { 24 | HttpEntity Entity { get; set;} 25 | bool ExpectContinue { get; } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/CodeScales.Http/CodeScales.Http/Entity/HttpEntity.cs: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2010 CodeScales.com 2 | * 3 | * Licensed under the Apache License, Version 2.0 (the "License"); 4 | * you may not use this file except in compliance with the License. 5 | * You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | * See the License for the specific language governing permissions and 13 | * limitations under the License. 14 | */ 15 | 16 | using System; 17 | 18 | namespace CodeScales.Http.Entity 19 | { 20 | public interface HttpEntity 21 | { 22 | byte[] Content { get; set; } 23 | string ContentEncoding { get; set; } 24 | long ContentLength { get; set; } 25 | string ContentType { get; set; } 26 | bool IsChunked { get; set; } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/CodeScales.Http/CodeScales.Http.Examples/HttpPostExamples.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | using CodeScales.Http; 6 | using CodeScales.Http.Methods; 7 | using CodeScales.Http.Entity; 8 | using CodeScales.Http.Common; 9 | 10 | namespace CodeScales.Http.Examples 11 | { 12 | public class HttpPostExamples 13 | { 14 | public static void DoPost() 15 | { 16 | HttpClient client = new HttpClient(); 17 | HttpPost postMethod = new HttpPost(new Uri("http://www.w3schools.com/asp/demo_simpleform.asp")); 18 | 19 | List nameValuePairList = new List(); 20 | nameValuePairList.Add(new NameValuePair("fname", "brian")); 21 | 22 | UrlEncodedFormEntity formEntity = new UrlEncodedFormEntity(nameValuePairList, Encoding.UTF8); 23 | postMethod.Entity = formEntity; 24 | 25 | HttpResponse response = client.Execute(postMethod); 26 | 27 | Console.WriteLine("Response Code: " + response.ResponseCode); 28 | Console.WriteLine("Response Content: " + EntityUtils.ToString(response.Entity)); 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/CodeScales.Http/CodeScales.Http/Network/HttpNetworkException.cs: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2010 CodeScales.com 2 | * 3 | * Licensed under the Apache License, Version 2.0 (the "License"); 4 | * you may not use this file except in compliance with the License. 5 | * You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | * See the License for the specific language governing permissions and 13 | * limitations under the License. 14 | */ 15 | 16 | using System; 17 | using System.Collections.Generic; 18 | using System.Text; 19 | 20 | namespace CodeScales.Http.Network 21 | { 22 | public class HttpNetworkException : Exception 23 | { 24 | 25 | public HttpNetworkException(string message) 26 | : base(message) 27 | { 28 | 29 | } 30 | 31 | public HttpNetworkException(string message, Exception innerException) : base(message, innerException) 32 | { 33 | 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/CodeScales.Http/CodeScales.Http/Entity/Mime/Body.cs: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2010 CodeScales.com 2 | * 3 | * Licensed under the Apache License, Version 2.0 (the "License"); 4 | * you may not use this file except in compliance with the License. 5 | * You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | * See the License for the specific language governing permissions and 13 | * limitations under the License. 14 | */ 15 | 16 | /* 17 | * ==================================================================== 18 | * 19 | * This class is inspired by org.apache.http.entity.mime.content.AbstractContentBody 20 | * 21 | * ==================================================================== 22 | * 23 | */ 24 | 25 | using System; 26 | using System.Collections.Generic; 27 | using System.Text; 28 | 29 | namespace CodeScales.Http.Entity.Mime 30 | { 31 | public interface Body 32 | { 33 | byte[] GetContent(string boundry); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/CodeScales.Http/CodeScales.Http/Methods/HttpRequest.cs: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2010 CodeScales.com 2 | * 3 | * Licensed under the Apache License, Version 2.0 (the "License"); 4 | * you may not use this file except in compliance with the License. 5 | * You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | * See the License for the specific language governing permissions and 13 | * limitations under the License. 14 | */ 15 | 16 | using System; 17 | using System.Collections.Generic; 18 | using System.Text; 19 | using System.Net; 20 | 21 | namespace CodeScales.Http.Methods 22 | { 23 | public abstract class HttpRequest : HttpMessageBase 24 | { 25 | private Uri m_uri = null; 26 | 27 | public abstract string Method { get; } 28 | public abstract string GetRequestLine(bool useProxy); 29 | 30 | public Uri Uri 31 | { 32 | get { return m_uri; } 33 | set { m_uri = value; } 34 | } 35 | 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/CodeScales.Http/CodeScales.Http.Tests.Server/AspNetUpload.aspx.cs: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2010 CodeScales.com 2 | * 3 | * Licensed under the Apache License, Version 2.0 (the "License"); 4 | * you may not use this file except in compliance with the License. 5 | * You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | * See the License for the specific language governing permissions and 13 | * limitations under the License. 14 | */ 15 | 16 | using System; 17 | using System.Data; 18 | using System.Configuration; 19 | using System.Collections; 20 | using System.Web; 21 | using System.Web.Security; 22 | using System.Web.UI; 23 | using System.Web.UI.WebControls; 24 | using System.Web.UI.WebControls.WebParts; 25 | using System.Web.UI.HtmlControls; 26 | 27 | namespace CodeScales.Http.Tests.Server 28 | { 29 | public partial class AspNetUpload : System.Web.UI.Page 30 | { 31 | protected void Page_Load(object sender, EventArgs e) 32 | { 33 | 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/CodeScales.Http/CodeScales.Http/Entity/Mime/InputStreamBody.cs: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2010 CodeScales.com 2 | * 3 | * Licensed under the Apache License, Version 2.0 (the "License"); 4 | * you may not use this file except in compliance with the License. 5 | * You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | * See the License for the specific language governing permissions and 13 | * limitations under the License. 14 | */ 15 | 16 | /* 17 | * ==================================================================== 18 | * 19 | * This class is inspired by org.apache.http.entity.mime.content.InputStreamBody 20 | * 21 | * ==================================================================== 22 | * 23 | */ 24 | 25 | using System; 26 | using System.Collections.Generic; 27 | using System.Text; 28 | 29 | namespace CodeScales.Http.Entity.Mime 30 | { 31 | public class InputStreamBody : Body 32 | { 33 | public byte[] GetContent(string boundry) 34 | { 35 | return null; 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/CodeScales.Http/CodeScales.Http.Tests.Server/HttpGet302.aspx.cs: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2010 CodeScales.com 2 | * 3 | * Licensed under the Apache License, Version 2.0 (the "License"); 4 | * you may not use this file except in compliance with the License. 5 | * You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | * See the License for the specific language governing permissions and 13 | * limitations under the License. 14 | */ 15 | 16 | using System; 17 | using System.Data; 18 | using System.Configuration; 19 | using System.Collections; 20 | using System.Collections.Specialized; 21 | using System.Web; 22 | using System.Web.Security; 23 | using System.Web.UI; 24 | using System.Web.UI.WebControls; 25 | using System.Web.UI.WebControls.WebParts; 26 | using System.Web.UI.HtmlControls; 27 | 28 | namespace CodeScales.Http.Tests.Server 29 | { 30 | public partial class HttpGet302 : System.Web.UI.Page 31 | { 32 | protected void Page_Load(object sender, EventArgs e) 33 | { 34 | Response.Redirect("HttpRedirectTarget1.aspx"); 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/CodeScales.Http/CodeScales.Http.Examples/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("CodeScales.Http.Examples")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("Microsoft")] 12 | [assembly: AssemblyProduct("CodeScales.Http.Examples")] 13 | [assembly: AssemblyCopyright("Copyright © Microsoft 2010")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("78e8ebd8-eefb-4d09-9875-fadd73c59f55")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | [assembly: AssemblyVersion("1.0.0.0")] 33 | [assembly: AssemblyFileVersion("1.0.0.0")] 34 | -------------------------------------------------------------------------------- /src/CodeScales.Http/CodeScales.Http.Tests.Server/Web.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 15 | 16 | 21 | 22 | 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /src/CodeScales.Http/CodeScales.Http/Common/NameValuePair.cs: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2010 CodeScales.com 2 | * 3 | * Licensed under the Apache License, Version 2.0 (the "License"); 4 | * you may not use this file except in compliance with the License. 5 | * You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | * See the License for the specific language governing permissions and 13 | * limitations under the License. 14 | */ 15 | 16 | using System; 17 | using System.Collections.Generic; 18 | using System.Text; 19 | 20 | namespace CodeScales.Http.Common 21 | { 22 | [Serializable] 23 | public class NameValuePair 24 | { 25 | private string m_name; 26 | private string m_value; 27 | 28 | public NameValuePair() 29 | { 30 | } 31 | 32 | public NameValuePair(string name, string value) 33 | { 34 | this.m_name = name; 35 | this.m_value = value; 36 | } 37 | 38 | public string Name 39 | { 40 | get { return m_name; } 41 | set { m_name = value; } 42 | } 43 | 44 | public string Value 45 | { 46 | get { return this.m_value; } 47 | set { this.m_value = value; } 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/CodeScales.Http/CodeScales.Http/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("CodeScales.Http")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("CodeScales.com")] 12 | [assembly: AssemblyProduct("CodeScales.Http")] 13 | [assembly: AssemblyCopyright("Copyright © CodeScales.com 2010")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("7a0a7b45-63ff-4937-9ccf-ba4bdf340054")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Revision and Build Numbers 33 | // by using the '*' as shown below: 34 | [assembly: AssemblyVersion("1.0.0.0")] 35 | [assembly: AssemblyFileVersion("1.0.0.0")] 36 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # c-sharp-http-client 2 | Automatically exported from code.google.com/p/c-sharp-http-client 3 | 4 | CSharp HttpClient by CodeScales.com 5 | 6 | An HTTP client library with a very simple API, written in CSharp (.Net 2.0) for sending HTTP requests and receiving HTTP responses. 7 | This library is much simpler to use than the HttpWebRequest provided with the .Net library. 8 | This library was inspired by the JAVA HttpClient library, and has a very similar API. 9 | See codescales.com for more details 10 | You are encouraged to visit the project's web site at http://www.codescales.com for code examples and documentation. 11 | 12 | What can you do with it? 13 | 14 | Send GET requests. 15 | Send POST requests with parameters, using Url-Encoded Entity. 16 | upload Files to an HTTP server, using a Multipart Entity. 17 | Send Post request with parameters, using Multipart Entity (which is actually the same as #3). 18 | Control the redirect behavior of the client, using HttpBehavior. 19 | Use as many parallel connections (sockets) as you need, using the default HttpConnectionFactory. 20 | Use a proxy server that does not need a password. 21 | Current Status 22 | 23 | This is a preliminary version. Some basic functionality is missing. See the limitations section for details. It is still work in progress, and you are welcome to write me if you want to help at yaron@codescales.com. 24 | 25 | Limitations 26 | 27 | This is a list of things that are NOT supported yet: 28 | 29 | Transfer-Encoding: gzip 30 | Requests with keep-alive header. 31 | Expiration of cookies. 32 | Using proxies that need password. 33 | HTTPS and SSL. 34 | -------------------------------------------------------------------------------- /src/CodeScales.Http/CodeScales.Http.Tests/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("CodeScales.Http.Tests")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("CodeScales.com")] 12 | [assembly: AssemblyProduct("CodeScales.Http.Tests")] 13 | [assembly: AssemblyCopyright("Copyright © CodeScales.com 2010")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("5c6afe3c-2ca9-4dac-bd8d-09c51bd78883")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Revision and Build Numbers 33 | // by using the '*' as shown below: 34 | [assembly: AssemblyVersion("1.0.0.0")] 35 | [assembly: AssemblyFileVersion("1.0.0.0")] 36 | -------------------------------------------------------------------------------- /src/CodeScales.Http/CodeScales.Http.Tests.Server/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("CodeScales.Http.Tests.Server")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("CodeScales.com")] 12 | [assembly: AssemblyProduct("CodeScales.Http.Tests.Server")] 13 | [assembly: AssemblyCopyright("Copyright © CodeScales.com 2010")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("3d5900ae-111a-45be-96b3-d9e4606ca793")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Revision and Build Numbers 33 | // by using the '*' as shown below: 34 | [assembly: AssemblyVersion("1.0.0.0")] 35 | [assembly: AssemblyFileVersion("1.0.0.0")] 36 | -------------------------------------------------------------------------------- /src/CodeScales.Http/CodeScales.Http/Methods/HttpMessageBase.cs: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2010 CodeScales.com 2 | * 3 | * Licensed under the Apache License, Version 2.0 (the "License"); 4 | * you may not use this file except in compliance with the License. 5 | * You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | * See the License for the specific language governing permissions and 13 | * limitations under the License. 14 | */ 15 | 16 | using System; 17 | using System.Collections.Generic; 18 | using System.Text; 19 | using System.Net; 20 | 21 | namespace CodeScales.Http.Methods 22 | { 23 | public abstract class HttpMessageBase 24 | { 25 | private WebHeaderCollection m_headers = new WebHeaderCollection(); 26 | private Dictionary m_parameters = new Dictionary(); 27 | 28 | public virtual WebHeaderCollection Headers 29 | { 30 | get 31 | { 32 | return m_headers; 33 | } 34 | set 35 | { 36 | this.m_headers = value; 37 | } 38 | } 39 | 40 | public Dictionary Parameters 41 | { 42 | get 43 | { 44 | return m_parameters; 45 | } 46 | set 47 | { 48 | this.m_parameters = value; 49 | } 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/CodeScales.Http/CodeScales.Http.Tests/Constants.cs: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2010 CodeScales.com 2 | * 3 | * Licensed under the Apache License, Version 2.0 (the "License"); 4 | * you may not use this file except in compliance with the License. 5 | * You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | * See the License for the specific language governing permissions and 13 | * limitations under the License. 14 | */ 15 | 16 | using System; 17 | using System.Collections.Generic; 18 | using System.Text; 19 | 20 | namespace CodeScales.Http.Tests 21 | { 22 | public class Constants 23 | { 24 | public const string HTTP_GET_200 = "http://localhost/CodeScales/HttpGet200.aspx"; 25 | public const string HTTP_GET_200_CODESCALES_COM = "http://www.codescales.com/"; 26 | public const string HTTP_GET_200_WITH_SET_COOKIES = "http://localhost/CodeScales/HttpGet200WithSetCookies.aspx"; 27 | public const string HTTP_GET_302 = "http://localhost/CodeScales/HttpGet302.aspx"; 28 | public const string HTTP_POST_200 = "http://localhost/CodeScales/HttpPost200.aspx"; 29 | public const string HTTP_POST_W3SCHOOLS = "http://www.w3schools.com/asp/demo_simpleform.asp"; 30 | public const string HTTP_MULTIPART_POST_200 = "http://localhost/CodeScales/HttpMultipartPost200.aspx"; 31 | public const string HTTP_REDIRECT_TARGET_1 = "http://localhost/CodeScales/HttpRedirectTarget1.aspx"; 32 | public const string FIDDLER_DEFAULT_ADDRESS = "http://localhost:8888/"; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/CodeScales.Http/CodeScales.Http/Entity/Mime/StringBody.cs: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2010 CodeScales.com 2 | * 3 | * Licensed under the Apache License, Version 2.0 (the "License"); 4 | * you may not use this file except in compliance with the License. 5 | * You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | * See the License for the specific language governing permissions and 13 | * limitations under the License. 14 | */ 15 | 16 | /* 17 | * ==================================================================== 18 | * 19 | * This class is inspired by org.apache.http.entity.mime.content.StringBody 20 | * 21 | * ==================================================================== 22 | * 23 | */ 24 | 25 | using System; 26 | using System.Collections.Generic; 27 | using System.Text; 28 | 29 | using CodeScales.Http.Network; 30 | 31 | namespace CodeScales.Http.Entity.Mime 32 | { 33 | public class StringBody : Body 34 | { 35 | private Encoding m_encoding; 36 | private string m_name; 37 | private string m_value; 38 | 39 | public StringBody(Encoding encoding, string name, string value) 40 | { 41 | this.m_encoding = encoding; 42 | this.m_name = name; 43 | this.m_value = value; 44 | } 45 | 46 | public byte[] GetContent(string boundry) 47 | { 48 | return this.m_encoding.GetBytes(HTTPProtocol.GetPostParameter(this.m_name, this.m_value, boundry)); 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/CodeScales.Http/CodeScales.Http/Cookies/HttpCookie.cs: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2010 CodeScales.com 2 | * 3 | * Licensed under the Apache License, Version 2.0 (the "License"); 4 | * you may not use this file except in compliance with the License. 5 | * You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | * See the License for the specific language governing permissions and 13 | * limitations under the License. 14 | */ 15 | 16 | using System; 17 | using System.Collections.Generic; 18 | using System.Text; 19 | 20 | namespace CodeScales.Http.Cookies 21 | { 22 | public class HttpCookie 23 | { 24 | private string m_name; 25 | private string m_value; 26 | private string m_path; 27 | private DateTime m_expiration; 28 | 29 | public HttpCookie(string name, string value) 30 | { 31 | this.m_name = name; 32 | this.m_value = value; 33 | } 34 | 35 | public string Name 36 | { 37 | get { return m_name; } 38 | set { m_name = value; } 39 | } 40 | 41 | public string Value 42 | { 43 | get { return m_value; } 44 | set { m_value = value; } 45 | } 46 | 47 | public string Path 48 | { 49 | get { return m_path; } 50 | set { m_path = value; } 51 | } 52 | 53 | public DateTime Expiration 54 | { 55 | get { return m_expiration; } 56 | set { m_expiration = value; } 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/CodeScales.Http/CodeScales.Http.Tests.Server/AspNetUpload.aspx.designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:2.0.50727.4927 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace CodeScales.Http.Tests.Server { 12 | 13 | 14 | /// 15 | /// AspNetUpload class. 16 | /// 17 | /// 18 | /// Auto-generated class. 19 | /// 20 | public partial class AspNetUpload { 21 | 22 | /// 23 | /// form1 control. 24 | /// 25 | /// 26 | /// Auto-generated field. 27 | /// To modify move field declaration from designer file to code-behind file. 28 | /// 29 | protected global::System.Web.UI.HtmlControls.HtmlForm form1; 30 | 31 | /// 32 | /// FileUpload1 control. 33 | /// 34 | /// 35 | /// Auto-generated field. 36 | /// To modify move field declaration from designer file to code-behind file. 37 | /// 38 | protected global::System.Web.UI.WebControls.FileUpload FileUpload1; 39 | 40 | /// 41 | /// Submit1 control. 42 | /// 43 | /// 44 | /// Auto-generated field. 45 | /// To modify move field declaration from designer file to code-behind file. 46 | /// 47 | protected global::System.Web.UI.WebControls.Button Submit1; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/CodeScales.Http/CodeScales.Http.Tests/resources/ResourceManager.cs: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2010 CodeScales.com 2 | * 3 | * Licensed under the Apache License, Version 2.0 (the "License"); 4 | * you may not use this file except in compliance with the License. 5 | * You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | * See the License for the specific language governing permissions and 13 | * limitations under the License. 14 | */ 15 | 16 | using System; 17 | using System.Collections.Generic; 18 | using System.Text; 19 | using System.IO; 20 | using System.Reflection; 21 | 22 | namespace CodeScales.Http.Tests.resources 23 | { 24 | public class ResourceManager 25 | { 26 | private const string RESOURCE_FOLDER = "resources"; 27 | 28 | public static FileInfo GetResourceFileInfo(string fileName) 29 | { 30 | string filePath = Assembly.GetAssembly(typeof(ResourceManager)).Location; 31 | filePath = filePath.Substring(0, filePath.LastIndexOf('\\')) + "\\"; 32 | byte[] fileBytes = GetResourceBinary(fileName); 33 | File.WriteAllBytes(filePath + fileName, fileBytes); 34 | return new FileInfo(filePath + fileName); 35 | } 36 | 37 | public static byte[] GetResourceBinary(string fileName) 38 | { 39 | Stream stream = Assembly.GetAssembly(typeof(ResourceManager)).GetManifestResourceStream("CodeScales.Http.Tests.resources." + fileName); 40 | BinaryReader reader = new BinaryReader(stream); 41 | return reader.ReadBytes((int)reader.BaseStream.Length); 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/CodeScales.Http/CodeScales.Http/Network/HttpConnectionFactory.cs: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2010 CodeScales.com 2 | * 3 | * Licensed under the Apache License, Version 2.0 (the "License"); 4 | * you may not use this file except in compliance with the License. 5 | * You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | * See the License for the specific language governing permissions and 13 | * limitations under the License. 14 | */ 15 | 16 | using System; 17 | using System.Collections.Generic; 18 | using System.Text; 19 | 20 | namespace CodeScales.Http.Network 21 | { 22 | internal class HttpConnectionFactory 23 | { 24 | public HttpConnection GetConnnection(Uri uri, Uri proxy) 25 | { 26 | return GetConnectionPrivate(uri, proxy); 27 | } 28 | 29 | // make sure the connection is still open and from the same host 30 | public HttpConnection GetConnnection(Uri uri, Uri proxy, HttpConnection liveConnection) 31 | { 32 | if (liveConnection != null 33 | && liveConnection.IsConnected() 34 | && liveConnection.Uri.Host.ToLower() == uri.Host.ToLower()) 35 | { 36 | return liveConnection; 37 | } 38 | else 39 | { 40 | liveConnection.Close(); 41 | return GetConnectionPrivate(uri, proxy); 42 | } 43 | } 44 | 45 | private HttpConnection GetConnectionPrivate(Uri uri, Uri proxy) 46 | { 47 | HttpConnection conn = new HttpConnection(this, uri, proxy); 48 | conn.SetBusy(true); 49 | conn.Connect(); 50 | return conn; 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/CodeScales.Http/CodeScales.Http/Cookies/HttpCookieCollection.cs: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2010 CodeScales.com 2 | * 3 | * Licensed under the Apache License, Version 2.0 (the "License"); 4 | * you may not use this file except in compliance with the License. 5 | * You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | * See the License for the specific language governing permissions and 13 | * limitations under the License. 14 | */ 15 | 16 | using System; 17 | using System.Collections.Generic; 18 | using System.Text; 19 | 20 | namespace CodeScales.Http.Cookies 21 | { 22 | public class HttpCookieCollection 23 | { 24 | 25 | private Dictionary m_cookies = new Dictionary(); 26 | 27 | public Dictionary.KeyCollection Keys 28 | { 29 | get 30 | { 31 | return this.m_cookies.Keys; 32 | } 33 | } 34 | 35 | public int Count 36 | { 37 | get 38 | { 39 | return this.m_cookies.Count; 40 | } 41 | } 42 | 43 | public HttpCookie GetCookie(string key) 44 | { 45 | return this.m_cookies[key]; 46 | } 47 | 48 | public void Add(string key, HttpCookie cookie) 49 | { 50 | if (cookie.Value != null && cookie.Value != string.Empty) 51 | { 52 | if (this.m_cookies.ContainsKey(key)) 53 | { 54 | this.m_cookies[key].Value = cookie.Value; 55 | } 56 | else 57 | this.m_cookies.Add(key, cookie); 58 | 59 | 60 | } 61 | } 62 | 63 | 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/CodeScales.Http/CodeScales.Http/Protocol/HTTP.cs: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2010 CodeScales.com 2 | * 3 | * Licensed under the Apache License, Version 2.0 (the "License"); 4 | * you may not use this file except in compliance with the License. 5 | * You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | * See the License for the specific language governing permissions and 13 | * limitations under the License. 14 | */ 15 | 16 | using System; 17 | using System.Collections.Generic; 18 | using System.Text; 19 | 20 | namespace CodeScales.Http.Protocol 21 | { 22 | public class HTTP 23 | { 24 | /** HTTP header definitions */ 25 | public const string TRANSFER_ENCODING = "Transfer-Encoding"; 26 | public const string CONTENT_LEN = "Content-Length"; 27 | public const string CONTENT_TYPE = "Content-Type"; 28 | public const string CONTENT_ENCODING = "Content-Encoding"; 29 | public const string EXPECT_DIRECTIVE = "Expect"; 30 | public const string CONN_DIRECTIVE = "Connection"; 31 | public const string PROXY_CONN_DIRECTIVE = "Proxy-Connection"; 32 | public const string TARGET_HOST = "Host"; 33 | public const string USER_AGENT = "User-Agent"; 34 | public const string DATE_HEADER = "Date"; 35 | public const string SERVER_HEADER = "Server"; 36 | 37 | /** HTTP expectations */ 38 | public const string EXPECT_CONTINUE = "100-Continue"; 39 | 40 | /** HTTP connection control */ 41 | public const string CONN_CLOSE = "Close"; 42 | public const string CONN_KEEP_ALIVE = "Keep-Alive"; 43 | 44 | /** Transfer encoding definitions */ 45 | public const string CHUNK_CODING = "chunked"; 46 | public const string IDENTITY_CODING = "identity"; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/CodeScales.Http/CodeScales.Http.Tests.Server/HttpRedirectTarget1.aspx.cs: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2010 CodeScales.com 2 | * 3 | * Licensed under the Apache License, Version 2.0 (the "License"); 4 | * you may not use this file except in compliance with the License. 5 | * You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | * See the License for the specific language governing permissions and 13 | * limitations under the License. 14 | */ 15 | 16 | using System; 17 | using System.Data; 18 | using System.Configuration; 19 | using System.Collections; 20 | using System.Web; 21 | using System.Web.Security; 22 | using System.Web.UI; 23 | using System.Web.UI.WebControls; 24 | using System.Web.UI.WebControls.WebParts; 25 | using System.Web.UI.HtmlControls; 26 | 27 | using CodeScales.Http.Common; 28 | 29 | namespace CodeScales.Http.Tests.Server 30 | { 31 | public partial class HttpRedirectTarget1 : System.Web.UI.Page 32 | { 33 | protected void Page_Load(object sender, EventArgs e) 34 | { 35 | MessageData msgData = new MessageData(); 36 | if (Request.QueryString != null 37 | && Request.QueryString.Count > 0) 38 | { 39 | foreach (string s in Request.QueryString.AllKeys) 40 | { 41 | msgData.QueryParameters.Add(new NameValuePair(s, Request.QueryString[s])); 42 | } 43 | } 44 | 45 | if (Request.Cookies != null 46 | && Request.Cookies.Count > 0) 47 | { 48 | foreach (string s in Request.Cookies.AllKeys) 49 | { 50 | msgData.Cookies.Add(new NameValuePair(s, Request.Cookies[s].Value)); 51 | } 52 | } 53 | Response.Write(msgData.ToString()); 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/CodeScales.Http/CodeScales.Http.Tests.Server/HttpPost200.aspx.cs: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2010 CodeScales.com 2 | * 3 | * Licensed under the Apache License, Version 2.0 (the "License"); 4 | * you may not use this file except in compliance with the License. 5 | * You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | * See the License for the specific language governing permissions and 13 | * limitations under the License. 14 | */ 15 | 16 | using System; 17 | using System.Data; 18 | using System.Configuration; 19 | using System.Collections; 20 | using System.Collections.Specialized; 21 | using System.Web; 22 | using System.Web.Security; 23 | using System.Web.UI; 24 | using System.Web.UI.WebControls; 25 | using System.Web.UI.WebControls.WebParts; 26 | using System.Web.UI.HtmlControls; 27 | 28 | using CodeScales.Http.Common; 29 | 30 | namespace CodeScales.Http.Tests.Server 31 | { 32 | public partial class HttpPost200 : System.Web.UI.Page 33 | { 34 | protected void Page_Load(object sender, EventArgs e) 35 | { 36 | MessageData msgData = new MessageData(); 37 | if (Request.Form != null 38 | && Request.Form.Count > 0) 39 | { 40 | foreach (string s in Request.Form.AllKeys) 41 | { 42 | msgData.PostParameters.Add(new NameValuePair(s, Request.Form[s])); 43 | } 44 | } 45 | 46 | if (Request.Cookies != null 47 | && Request.Cookies.Count > 0) 48 | { 49 | foreach (string s in Request.Cookies.AllKeys) 50 | { 51 | msgData.Cookies.Add(new NameValuePair(s, Request.Cookies[s].Value)); 52 | } 53 | } 54 | Response.Write(msgData.ToString()); 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/CodeScales.Http/CodeScales.Http.Tests.Server/HttpGet200WithSetCookies.aspx.cs: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2010 CodeScales.com 2 | * 3 | * Licensed under the Apache License, Version 2.0 (the "License"); 4 | * you may not use this file except in compliance with the License. 5 | * You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | * See the License for the specific language governing permissions and 13 | * limitations under the License. 14 | */ 15 | 16 | using System; 17 | using System.Data; 18 | using System.Configuration; 19 | using System.Collections; 20 | using System.Collections.Specialized; 21 | using System.Web; 22 | using System.Web.Security; 23 | using System.Web.UI; 24 | using System.Web.UI.WebControls; 25 | using System.Web.UI.WebControls.WebParts; 26 | using System.Web.UI.HtmlControls; 27 | 28 | using CodeScales.Http.Common; 29 | 30 | namespace CodeScales.Http.Tests.Server 31 | { 32 | public partial class HttpGet200WithSetCookies : System.Web.UI.Page 33 | { 34 | protected void Page_Load(object sender, EventArgs e) 35 | { 36 | MessageData msgData = new MessageData(); 37 | if (Request.QueryString != null 38 | && Request.QueryString.Count > 0) 39 | { 40 | foreach (string s in Request.QueryString.AllKeys) 41 | { 42 | msgData.QueryParameters.Add(new NameValuePair(s, Request.QueryString[s])); 43 | } 44 | } 45 | if (Request.QueryString != null 46 | && Request.QueryString.Count > 0) 47 | { 48 | foreach (string s in Request.QueryString.AllKeys) 49 | { 50 | Response.Cookies.Add(new HttpCookie(s, Request.QueryString[s])); 51 | } 52 | } 53 | Response.Write(msgData.ToString()); 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/CodeScales.Http/CodeScales.Http.Tests.Server/HttpGet200.aspx.cs: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2010 CodeScales.com 2 | * 3 | * Licensed under the Apache License, Version 2.0 (the "License"); 4 | * you may not use this file except in compliance with the License. 5 | * You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | * See the License for the specific language governing permissions and 13 | * limitations under the License. 14 | */ 15 | 16 | using System; 17 | using System.Data; 18 | using System.Configuration; 19 | using System.Collections; 20 | using System.Collections.Specialized; 21 | using System.Web; 22 | using System.Web.Security; 23 | using System.Web.UI; 24 | using System.Web.UI.WebControls; 25 | using System.Web.UI.WebControls.WebParts; 26 | using System.Web.UI.HtmlControls; 27 | 28 | 29 | using CodeScales.Http.Common; 30 | 31 | namespace CodeScales.Http.Tests.Server 32 | { 33 | public partial class HttpGet200 : System.Web.UI.Page 34 | { 35 | protected void Page_Load(object sender, EventArgs e) 36 | { 37 | MessageData msgData = new MessageData(); 38 | if (Request.QueryString != null 39 | && Request.QueryString.Count > 0) 40 | { 41 | foreach (string s in Request.QueryString.AllKeys) 42 | { 43 | msgData.QueryParameters.Add(new NameValuePair(s, Request.QueryString[s])); 44 | } 45 | } 46 | 47 | if (Request.Cookies != null 48 | && Request.Cookies.Count > 0) 49 | { 50 | foreach (string s in Request.Cookies.AllKeys) 51 | { 52 | msgData.Cookies.Add(new NameValuePair(s, Request.Cookies[s].Value)); 53 | } 54 | } 55 | Response.Write(msgData.ToString()); 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/CodeScales.Http/CodeScales.Http/Methods/HttpResponse.cs: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2010 CodeScales.com 2 | * 3 | * Licensed under the Apache License, Version 2.0 (the "License"); 4 | * you may not use this file except in compliance with the License. 5 | * You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | * See the License for the specific language governing permissions and 13 | * limitations under the License. 14 | */ 15 | 16 | using System; 17 | using System.Collections.Generic; 18 | using System.Text; 19 | using System.Net; 20 | 21 | using CodeScales.Http.Network; 22 | using CodeScales.Http.Entity; 23 | 24 | namespace CodeScales.Http.Methods 25 | { 26 | public class HttpResponse : HttpMessageBase 27 | { 28 | private int m_responseCode = 0; 29 | private Uri m_requestUri = null; 30 | private HttpEntity m_entity = null; 31 | 32 | public HttpResponse() 33 | { 34 | 35 | } 36 | 37 | public int ResponseCode 38 | { 39 | get { return m_responseCode; } 40 | set { m_responseCode = value; } 41 | } 42 | 43 | public Uri RequestUri 44 | { 45 | get { return m_requestUri; } 46 | set { m_requestUri = value; } 47 | } 48 | 49 | public HttpEntity Entity 50 | { 51 | get { return m_entity; } 52 | set { m_entity = value; } 53 | } 54 | 55 | public string Location 56 | { 57 | get 58 | { 59 | if (this.Headers != null && 60 | this.Headers["Location"] != null) 61 | { 62 | try { return new Uri(this.Headers["Location"]).AbsoluteUri; } 63 | catch { return new Uri(this.m_requestUri, this.Headers["Location"]).AbsoluteUri; } 64 | } 65 | else 66 | return string.Empty; 67 | } 68 | } 69 | 70 | 71 | 72 | 73 | } 74 | } -------------------------------------------------------------------------------- /src/CodeScales.Http/CodeScales.Http.Examples/CodeScales.Http.Examples.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | Debug 4 | AnyCPU 5 | 8.0.50727 6 | 2.0 7 | {7479716F-061C-4751-8895-B405E8B6B4EE} 8 | Exe 9 | Properties 10 | CodeScales.Http.Examples 11 | CodeScales.Http.Examples 12 | 13 | 14 | true 15 | full 16 | false 17 | bin\Debug\ 18 | DEBUG;TRACE 19 | prompt 20 | 4 21 | 22 | 23 | pdbonly 24 | true 25 | bin\Release\ 26 | TRACE 27 | prompt 28 | 4 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | {FC262E96-6275-4798-8181-D9001FB50541} 44 | CodeScales.Http 45 | 46 | 47 | 48 | 55 | -------------------------------------------------------------------------------- /src/CodeScales.Http/CodeScales.Http.Tests.Server/HttpMultipartPost200.aspx.cs: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2010 CodeScales.com 2 | * 3 | * Licensed under the Apache License, Version 2.0 (the "License"); 4 | * you may not use this file except in compliance with the License. 5 | * You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | * See the License for the specific language governing permissions and 13 | * limitations under the License. 14 | */ 15 | 16 | using System; 17 | using System.Data; 18 | using System.Configuration; 19 | using System.Collections; 20 | using System.Collections.Specialized; 21 | using System.Web; 22 | using System.Web.Security; 23 | using System.Web.UI; 24 | using System.Web.UI.WebControls; 25 | using System.Web.UI.WebControls.WebParts; 26 | using System.Web.UI.HtmlControls; 27 | 28 | using CodeScales.Http.Common; 29 | 30 | namespace CodeScales.Http.Tests.Server 31 | { 32 | public partial class HttpMultipartPost200 : System.Web.UI.Page 33 | { 34 | protected void Page_Load(object sender, EventArgs e) 35 | { 36 | MessageData msgData = new MessageData(); 37 | if (Request.Form != null 38 | && Request.Form.Count > 0) 39 | { 40 | foreach (string s in Request.Form.AllKeys) 41 | { 42 | msgData.PostParameters.Add(new NameValuePair(s, Request.Form[s])); 43 | } 44 | } 45 | 46 | if (Request.Cookies != null 47 | && Request.Cookies.Count > 0) 48 | { 49 | foreach (string s in Request.Cookies.AllKeys) 50 | { 51 | msgData.Cookies.Add(new NameValuePair(s, Request.Cookies[s].Value)); 52 | } 53 | } 54 | 55 | if (Request.Files != null 56 | && Request.Files.Count > 0) 57 | { 58 | foreach (string key in Request.Files.AllKeys) 59 | { 60 | msgData.Files.Add(new NameValuePair(Request.Files[key].FileName, Request.Files[key].ContentLength.ToString())); 61 | } 62 | } 63 | Response.Write(msgData.ToString()); 64 | } 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /src/CodeScales.Http/CodeScales.Http/Entity/AbstractHttpEntity.cs: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2010 CodeScales.com 2 | * 3 | * Licensed under the Apache License, Version 2.0 (the "License"); 4 | * you may not use this file except in compliance with the License. 5 | * You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | * See the License for the specific language governing permissions and 13 | * limitations under the License. 14 | */ 15 | 16 | /* 17 | * ==================================================================== 18 | * 19 | * This class is inspired by org.apache.http.entity.AbstractHttpEntity 20 | * 21 | * ==================================================================== 22 | * 23 | */ 24 | 25 | using System; 26 | using System.Collections.Generic; 27 | using System.Text; 28 | 29 | namespace CodeScales.Http.Entity 30 | { 31 | public abstract class AbstractHttpEntity : HttpEntity 32 | { 33 | // void WriteTo(OutputStream); 34 | private byte[] m_content; 35 | private string m_contentEncoding; 36 | private long m_contentLength = -1; 37 | private string m_contentType; 38 | private bool m_isChunked; 39 | 40 | // Replaces the getContent and writeTo methods in java 41 | public byte[] Content 42 | { 43 | get { return m_content; } 44 | set { m_content = value; } 45 | } 46 | 47 | // this is not the .net Encoding relevant header 48 | public string ContentEncoding 49 | { 50 | get { return m_contentEncoding; } 51 | set { m_contentEncoding = value; } 52 | } 53 | 54 | public long ContentLength 55 | { 56 | get { return m_contentLength; } 57 | set { m_contentLength = value; } 58 | } 59 | 60 | // this is the .net Encoding relevant header 61 | public string ContentType 62 | { 63 | get { return m_contentType; } 64 | set { m_contentType = value; } 65 | } 66 | 67 | // for future reference. this method is not used. 68 | public bool IsChunked 69 | { 70 | get { return m_isChunked; } 71 | set { m_isChunked = value; } 72 | } 73 | 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /src/CodeScales.Http/CodeScales.Http/Entity/EntityUtils.cs: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2010 CodeScales.com 2 | * 3 | * Licensed under the Apache License, Version 2.0 (the "License"); 4 | * you may not use this file except in compliance with the License. 5 | * You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | * See the License for the specific language governing permissions and 13 | * limitations under the License. 14 | */ 15 | 16 | using System; 17 | using System.Collections.Generic; 18 | using System.Text; 19 | using System.Net; 20 | 21 | using CodeScales.Http.Network; 22 | using CodeScales.Http.Protocol; 23 | 24 | namespace CodeScales.Http.Entity 25 | { 26 | public class EntityUtils 27 | { 28 | public static string ToString(HttpEntity entity) 29 | { 30 | if (entity != null 31 | && entity.Content != null) 32 | { 33 | return HTTPProtocol.GetEncoding(entity.ContentType).GetString(entity.Content); 34 | } 35 | else 36 | return string.Empty; 37 | } 38 | 39 | public static string GetContentType(WebHeaderCollection headers) 40 | { 41 | 42 | if (headers != null && 43 | headers[HTTP.CONTENT_TYPE] != null) 44 | return headers[HTTP.CONTENT_TYPE]; 45 | else 46 | return null; 47 | 48 | } 49 | 50 | public static int GetContentLength(WebHeaderCollection headers) 51 | { 52 | if (headers != null && 53 | headers[HTTP.CONTENT_LEN] != null) 54 | { 55 | return int.Parse(headers[HTTP.CONTENT_LEN]); 56 | } 57 | return 0; 58 | } 59 | 60 | public static string GetTransferEncoding(WebHeaderCollection headers) 61 | { 62 | if (headers != null && 63 | headers[HTTP.TRANSFER_ENCODING] != null) 64 | return headers[HTTP.TRANSFER_ENCODING]; 65 | else 66 | return null; 67 | } 68 | 69 | public static int ConvertHexToInt(string hexValue) 70 | { 71 | try 72 | { 73 | return int.Parse(hexValue, System.Globalization.NumberStyles.HexNumber); 74 | } 75 | catch 76 | { 77 | return 0; 78 | } 79 | } 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /src/CodeScales.Http/CodeScales.Http/Cookies/HttpCookieStore.cs: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2010 CodeScales.com 2 | * 3 | * Licensed under the Apache License, Version 2.0 (the "License"); 4 | * you may not use this file except in compliance with the License. 5 | * You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | * See the License for the specific language governing permissions and 13 | * limitations under the License. 14 | */ 15 | 16 | using System; 17 | using System.Collections.Generic; 18 | using System.Text; 19 | 20 | using CodeScales.Http.Methods; 21 | using CodeScales.Http.Cookies; 22 | using CodeScales.Http.Network; 23 | 24 | namespace CodeScales.Http.Cookies 25 | { 26 | public class HttpCookieStore 27 | { 28 | private Dictionary m_cookieStore = new Dictionary(); 29 | 30 | internal void WriteCookiesToRequest(HttpRequest request) 31 | { 32 | string host = request.Uri.Host; 33 | if (this.m_cookieStore.ContainsKey(host)) 34 | { 35 | HttpCookieCollection cookieColl = this.m_cookieStore[request.Uri.Host]; 36 | if (cookieColl != null) 37 | { 38 | request.Headers.Add("Cookie", HTTPProtocol.GetCookiesHeader(cookieColl)); 39 | } 40 | } 41 | } 42 | 43 | internal void ReadCookiesFromResponse(HttpResponse response) 44 | { 45 | lock (this) 46 | { 47 | Uri responseUri = response.RequestUri; 48 | HttpCookieCollection cookieColl = null; 49 | if (this.m_cookieStore.ContainsKey(responseUri.Host)) 50 | { 51 | cookieColl = this.m_cookieStore[responseUri.Host]; 52 | } 53 | else 54 | { 55 | cookieColl = new HttpCookieCollection(); 56 | this.m_cookieStore.Add(responseUri.Host, cookieColl); 57 | } 58 | 59 | string [] cookieHeaders = response.Headers.GetValues("Set-Cookie"); 60 | if (cookieHeaders != null) 61 | { 62 | 63 | foreach (string header in cookieHeaders) 64 | { 65 | HTTPProtocol.AddHttpCookie(header, cookieColl); 66 | } 67 | } 68 | } 69 | } 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /src/CodeScales.Http/CodeScales.Http.Examples/HttpGetExample.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | using CodeScales.Http; 6 | using CodeScales.Http.Entity; 7 | using CodeScales.Http.Methods; 8 | 9 | namespace CodeScales.Http.Examples 10 | { 11 | public class HttpGetExample 12 | { 13 | public static void DoGet() 14 | { 15 | HttpClient httpClient = new HttpClient(); 16 | HttpGet httpGet = new HttpGet(new Uri("http://www.codescales.com")); 17 | HttpResponse httpResponse = httpClient.Execute(httpGet); 18 | 19 | Console.WriteLine("Response Code: " + httpResponse.ResponseCode); 20 | Console.WriteLine("Response Content: " + EntityUtils.ToString(httpResponse.Entity)); 21 | } 22 | 23 | public static void DoGetWithRedirects() 24 | { 25 | HttpClient httpClient = new HttpClient(); 26 | httpClient.MaxRedirects = 0; 27 | HttpGet httpGet = new HttpGet(new Uri("http://www.codescales.com/home")); 28 | HttpResponse httpResponse = httpClient.Execute(httpGet); 29 | 30 | Console.WriteLine("Response Code: " + httpResponse.ResponseCode); 31 | Console.WriteLine("Response Code: " + httpResponse.Location); 32 | Console.WriteLine("Response Content: " + EntityUtils.ToString(httpResponse.Entity)); 33 | } 34 | 35 | public static void DoGetWithRedirects2() 36 | { 37 | HttpClient httpClient = new HttpClient(); 38 | HttpGet httpGet = new HttpGet(new Uri("http://www.codescales.com/home")); 39 | 40 | HttpBehavior httpBehavior = new HttpBehavior(); 41 | httpBehavior.AddStep(301, "http://www.codescales.com"); 42 | httpBehavior.AddStep(200); 43 | 44 | HttpResponse httpResponse = httpClient.Execute(httpGet, httpBehavior); 45 | 46 | Console.WriteLine("Response Code: " + httpResponse.ResponseCode); 47 | Console.WriteLine("Response Code: " + httpResponse.Location); 48 | Console.WriteLine("Response Content: " + EntityUtils.ToString(httpResponse.Entity)); 49 | } 50 | 51 | public static void DoGetWithProxy() 52 | { 53 | HttpClient httpClient = new HttpClient(); 54 | httpClient.Proxy = new Uri("http://localhost:8888/"); // default address of fiddler 55 | HttpGet httpGet = new HttpGet(new Uri("http://www.codescales.com")); 56 | HttpResponse httpResponse = httpClient.Execute(httpGet); 57 | 58 | Console.WriteLine("Response Code: " + httpResponse.ResponseCode); 59 | Console.WriteLine("Response Content: " + EntityUtils.ToString(httpResponse.Entity)); 60 | } 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/CodeScales.Http/CodeScales.Http/Entity/UrlEncodedFormEntity.cs: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2010 CodeScales.com 2 | * 3 | * Licensed under the Apache License, Version 2.0 (the "License"); 4 | * you may not use this file except in compliance with the License. 5 | * You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | * See the License for the specific language governing permissions and 13 | * limitations under the License. 14 | */ 15 | 16 | /* 17 | * ==================================================================== 18 | * 19 | * This class is inspired by org.apache.http.client.entity.UrlEncodedFormEntity 20 | * 21 | * ==================================================================== 22 | * 23 | */ 24 | 25 | using System; 26 | using System.Collections.Generic; 27 | using System.Text; 28 | using System.Web; 29 | 30 | using CodeScales.Http.Common; 31 | using CodeScales.Http.Network; 32 | 33 | namespace CodeScales.Http.Entity 34 | { 35 | public class UrlEncodedFormEntity : HttpEntity 36 | { 37 | private Encoding m_encoding; 38 | private List m_parameters; 39 | private byte[] m_content; 40 | 41 | public UrlEncodedFormEntity(List parameters, Encoding encoding) 42 | { 43 | this.m_parameters = parameters; 44 | this.m_encoding = encoding; 45 | 46 | StringBuilder stringBuilder = new StringBuilder(); 47 | HTTPProtocol.AddPostParameters(this.m_parameters, stringBuilder); 48 | m_content = this.m_encoding.GetBytes(stringBuilder.ToString()); 49 | } 50 | 51 | public string ContentEncoding 52 | { 53 | get { return null; } 54 | set {} 55 | } 56 | 57 | public string ContentType 58 | { 59 | get { return "application/x-www-form-urlencoded"; } 60 | set {} 61 | } 62 | 63 | public byte[] Content 64 | { 65 | get 66 | { 67 | return this.m_content; 68 | } 69 | set {} 70 | } 71 | 72 | public long ContentLength 73 | { 74 | get 75 | { 76 | if (this.m_content != null) 77 | { 78 | return this.m_content.GetLongLength(0); 79 | } 80 | else 81 | return 0; 82 | } 83 | set {} 84 | } 85 | 86 | public bool IsChunked 87 | { 88 | get 89 | { 90 | return false; 91 | } 92 | set {} 93 | } 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /src/CodeScales.Http/CodeScales.Http/Entity/Mime/FileBody.cs: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2010 CodeScales.com 2 | * 3 | * Licensed under the Apache License, Version 2.0 (the "License"); 4 | * you may not use this file except in compliance with the License. 5 | * You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | * See the License for the specific language governing permissions and 13 | * limitations under the License. 14 | */ 15 | 16 | /* 17 | * ==================================================================== 18 | * 19 | * This class is inspired by org.apache.http.entity.mime.content.FileBody 20 | * 21 | * ==================================================================== 22 | * 23 | */ 24 | 25 | using System; 26 | using System.Collections.Generic; 27 | using System.Text; 28 | using System.IO; 29 | 30 | using CodeScales.Http.Network; 31 | 32 | namespace CodeScales.Http.Entity.Mime 33 | { 34 | public class FileBody : Body 35 | { 36 | private string m_name; 37 | private string m_fileName; 38 | private byte[] m_content; 39 | private string m_mimeType; 40 | 41 | public FileBody(string name, string fileName, FileInfo fileInfo, string mimeType) 42 | : this(name, fileName, fileInfo) 43 | { 44 | this.m_mimeType = mimeType; 45 | } 46 | 47 | public FileBody(string name, string fileName, FileInfo fileInfo) 48 | { 49 | this.m_name = name; 50 | this.m_fileName = fileName; 51 | this.m_content = null; 52 | 53 | if (fileInfo == null) 54 | { 55 | this.m_content = new byte[0]; 56 | } 57 | else 58 | { 59 | using (BinaryReader reader = new BinaryReader(fileInfo.OpenRead())) 60 | { 61 | this.m_content = reader.ReadBytes((int)reader.BaseStream.Length); 62 | } 63 | } 64 | } 65 | 66 | public byte[] GetContent(string boundry) 67 | { 68 | List bytes = new List(); 69 | if (this.m_content.Length == 0 || this.m_mimeType == null || this.m_mimeType.Equals(string.Empty)) 70 | { 71 | bytes.AddRange(Encoding.ASCII.GetBytes(HTTPProtocol.AddPostParametersFile(this.m_name, this.m_fileName, boundry, "application/octet-stream"))); 72 | } 73 | else 74 | { 75 | bytes.AddRange(Encoding.ASCII.GetBytes(HTTPProtocol.AddPostParametersFile(this.m_name, this.m_fileName, boundry, this.m_mimeType))); 76 | } 77 | bytes.AddRange(this.m_content); 78 | bytes.AddRange(Encoding.ASCII.GetBytes("\r\n")); 79 | return bytes.ToArray(); 80 | } 81 | 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /src/CodeScales.Http/CodeScales.Http.Tests/CodeScales.Http.Tests.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | Debug 4 | AnyCPU 5 | 8.0.50727 6 | 2.0 7 | {AADEA75C-2370-4C6E-A704-FEA3E11A8EAB} 8 | Library 9 | Properties 10 | CodeScales.Http.Tests 11 | CodeScales.Http.Tests 12 | 13 | 14 | true 15 | full 16 | false 17 | bin\Debug\ 18 | DEBUG;TRACE 19 | prompt 20 | 4 21 | 22 | 23 | pdbonly 24 | true 25 | bin\Release\ 26 | TRACE 27 | prompt 28 | 4 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | {FC262E96-6275-4798-8181-D9001FB50541} 50 | CodeScales.Http 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 66 | -------------------------------------------------------------------------------- /src/CodeScales.Http/CodeScales.Http/Methods/HttpGet.cs: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2010 CodeScales.com 2 | * 3 | * Licensed under the Apache License, Version 2.0 (the "License"); 4 | * you may not use this file except in compliance with the License. 5 | * You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | * See the License for the specific language governing permissions and 13 | * limitations under the License. 14 | */ 15 | 16 | using System; 17 | using System.Collections.Generic; 18 | using System.Text; 19 | using System.Net; 20 | using System.Web; 21 | 22 | namespace CodeScales.Http.Methods 23 | { 24 | public class HttpGet : HttpRequest 25 | { 26 | private static string METHOD = "GET"; 27 | 28 | public HttpGet() 29 | { 30 | this.Headers.Add("UserAgent", @"Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322; .NET CLR 2.0.50727)"); 31 | } 32 | 33 | public HttpGet(Uri uri) : this() 34 | { 35 | this.Uri = uri; 36 | } 37 | 38 | public override string Method 39 | { 40 | get 41 | { 42 | return METHOD; 43 | } 44 | } 45 | 46 | public override string GetRequestLine(bool useProxy) 47 | { 48 | Uri url = AddParametersToPath(this.Uri); 49 | 50 | string requestUri = null; 51 | if (useProxy) 52 | { 53 | requestUri = url.AbsoluteUri; 54 | } 55 | else 56 | { 57 | requestUri = url.PathAndQuery; 58 | } 59 | 60 | return Method + " " + requestUri + " HTTP/1.1"; 61 | } 62 | 63 | private Uri AddParametersToPath(Uri url) 64 | { 65 | if (this.Parameters.Count > 0) 66 | { 67 | string absoluteUri = url.AbsoluteUri; 68 | StringBuilder newQuery = new StringBuilder(); 69 | newQuery.Append(absoluteUri); 70 | if (absoluteUri.IndexOf('?') < 0) 71 | { 72 | newQuery.Append('?'); 73 | } 74 | else 75 | { 76 | newQuery.Append('&'); 77 | } 78 | int counter = 1; 79 | foreach (string key in this.Parameters.Keys) 80 | { 81 | newQuery.Append(key + '=' + HttpUtility.UrlEncode(this.Parameters[key])); 82 | if (counter < this.Parameters.Count) 83 | { 84 | newQuery.Append('&'); 85 | } 86 | counter++; 87 | } 88 | return new Uri(newQuery.ToString()); 89 | } 90 | else 91 | return url; 92 | } 93 | 94 | 95 | 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /src/CodeScales.Http/CodeScales.Http.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 9.00 3 | # Visual Studio 2005 4 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CodeScales.Http.Tests.Server", "CodeScales.Http.Tests.Server\CodeScales.Http.Tests.Server.csproj", "{064A9560-7590-42A9-9E33-1FC1689760B3}" 5 | ProjectSection(WebsiteProperties) = preProject 6 | Debug.AspNetCompiler.Debug = "True" 7 | Release.AspNetCompiler.Debug = "False" 8 | EndProjectSection 9 | EndProject 10 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CodeScales.Http", "CodeScales.Http\CodeScales.Http.csproj", "{FC262E96-6275-4798-8181-D9001FB50541}" 11 | ProjectSection(WebsiteProperties) = preProject 12 | Debug.AspNetCompiler.Debug = "True" 13 | Release.AspNetCompiler.Debug = "False" 14 | EndProjectSection 15 | EndProject 16 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CodeScales.Http.Tests", "CodeScales.Http.Tests\CodeScales.Http.Tests.csproj", "{AADEA75C-2370-4C6E-A704-FEA3E11A8EAB}" 17 | ProjectSection(WebsiteProperties) = preProject 18 | Debug.AspNetCompiler.Debug = "True" 19 | Release.AspNetCompiler.Debug = "False" 20 | EndProjectSection 21 | EndProject 22 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CodeScales.Http.Examples", "CodeScales.Http.Examples\CodeScales.Http.Examples.csproj", "{7479716F-061C-4751-8895-B405E8B6B4EE}" 23 | ProjectSection(WebsiteProperties) = preProject 24 | Debug.AspNetCompiler.Debug = "True" 25 | Release.AspNetCompiler.Debug = "False" 26 | EndProjectSection 27 | EndProject 28 | Global 29 | GlobalSection(SubversionScc) = preSolution 30 | Svn-Managed = True 31 | Manager = AnkhSVN - Subversion Support for Visual Studio 32 | EndGlobalSection 33 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 34 | Debug|Any CPU = Debug|Any CPU 35 | Release|Any CPU = Release|Any CPU 36 | EndGlobalSection 37 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 38 | {064A9560-7590-42A9-9E33-1FC1689760B3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 39 | {064A9560-7590-42A9-9E33-1FC1689760B3}.Debug|Any CPU.Build.0 = Debug|Any CPU 40 | {064A9560-7590-42A9-9E33-1FC1689760B3}.Release|Any CPU.ActiveCfg = Release|Any CPU 41 | {064A9560-7590-42A9-9E33-1FC1689760B3}.Release|Any CPU.Build.0 = Release|Any CPU 42 | {FC262E96-6275-4798-8181-D9001FB50541}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 43 | {FC262E96-6275-4798-8181-D9001FB50541}.Debug|Any CPU.Build.0 = Debug|Any CPU 44 | {FC262E96-6275-4798-8181-D9001FB50541}.Release|Any CPU.ActiveCfg = Release|Any CPU 45 | {FC262E96-6275-4798-8181-D9001FB50541}.Release|Any CPU.Build.0 = Release|Any CPU 46 | {AADEA75C-2370-4C6E-A704-FEA3E11A8EAB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 47 | {AADEA75C-2370-4C6E-A704-FEA3E11A8EAB}.Debug|Any CPU.Build.0 = Debug|Any CPU 48 | {AADEA75C-2370-4C6E-A704-FEA3E11A8EAB}.Release|Any CPU.ActiveCfg = Release|Any CPU 49 | {AADEA75C-2370-4C6E-A704-FEA3E11A8EAB}.Release|Any CPU.Build.0 = Release|Any CPU 50 | {7479716F-061C-4751-8895-B405E8B6B4EE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 51 | {7479716F-061C-4751-8895-B405E8B6B4EE}.Debug|Any CPU.Build.0 = Debug|Any CPU 52 | {7479716F-061C-4751-8895-B405E8B6B4EE}.Release|Any CPU.ActiveCfg = Release|Any CPU 53 | {7479716F-061C-4751-8895-B405E8B6B4EE}.Release|Any CPU.Build.0 = Release|Any CPU 54 | EndGlobalSection 55 | GlobalSection(SolutionProperties) = preSolution 56 | HideSolutionNode = FALSE 57 | EndGlobalSection 58 | EndGlobal 59 | -------------------------------------------------------------------------------- /src/CodeScales.Http/CodeScales.Http/CodeScales.Http.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | Debug 4 | AnyCPU 5 | 8.0.50727 6 | 2.0 7 | {FC262E96-6275-4798-8181-D9001FB50541} 8 | Library 9 | Properties 10 | CodeScales.Http 11 | CodeScales.Http 12 | 13 | 14 | true 15 | full 16 | false 17 | bin\Debug\ 18 | DEBUG;TRACE 19 | prompt 20 | 4 21 | 22 | 23 | pdbonly 24 | true 25 | bin\Release\ 26 | TRACE 27 | prompt 28 | 4 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 74 | -------------------------------------------------------------------------------- /src/CodeScales.Http/CodeScales.Http.Tests/MessageData.cs: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2010 CodeScales.com 2 | * 3 | * Licensed under the Apache License, Version 2.0 (the "License"); 4 | * you may not use this file except in compliance with the License. 5 | * You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | * See the License for the specific language governing permissions and 13 | * limitations under the License. 14 | */ 15 | 16 | using System; 17 | using System.Collections.Generic; 18 | using System.Text; 19 | using System.Xml.Serialization; 20 | using System.IO; 21 | 22 | namespace CodeScales.Http.Tests 23 | { 24 | [Serializable] 25 | public class MessageData 26 | { 27 | private NameValueColl m_queryParameters; 28 | private NameValueColl m_postParameters; 29 | private NameValueColl m_cookies; 30 | private NameValueColl m_files; 31 | 32 | public static MessageData Empty 33 | { 34 | get 35 | { 36 | return new MessageData(); 37 | } 38 | } 39 | 40 | public NameValueColl QueryParameters 41 | { 42 | get 43 | { 44 | if (m_queryParameters == null) 45 | { 46 | m_queryParameters = new NameValueColl(); 47 | } 48 | return m_queryParameters; 49 | } 50 | set { m_queryParameters = value; } 51 | } 52 | 53 | public NameValueColl PostParameters 54 | { 55 | get 56 | { 57 | if (m_postParameters == null) 58 | { 59 | m_postParameters = new NameValueColl(); 60 | } 61 | return m_postParameters; 62 | } 63 | set { m_postParameters = value; } 64 | } 65 | 66 | public NameValueColl Cookies 67 | { 68 | get 69 | { 70 | if (m_cookies == null) 71 | { 72 | m_cookies = new NameValueColl(); 73 | } 74 | return m_cookies; 75 | } 76 | set { m_cookies = value; } 77 | } 78 | 79 | public NameValueColl Files 80 | { 81 | get 82 | { 83 | if (m_files == null) 84 | { 85 | m_files = new NameValueColl(); 86 | } 87 | return m_files; 88 | } 89 | set { m_files = value; } 90 | } 91 | 92 | public override string ToString() 93 | { 94 | XmlSerializer xs = new XmlSerializer(typeof(MessageData)); 95 | TextWriter writer = new StringWriter(); 96 | xs.Serialize(writer, this); 97 | return writer.ToString(); 98 | } 99 | 100 | public MessageData FromString(string xmlString) 101 | { 102 | XmlSerializer xs = new XmlSerializer(typeof(MessageData)); 103 | TextReader reader = new StringReader(xmlString); 104 | return (MessageData)xs.Deserialize(reader); 105 | } 106 | 107 | 108 | 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /src/CodeScales.Http/CodeScales.Http/Entity/MultipartEntity.cs: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2010 CodeScales.com 2 | * 3 | * Licensed under the Apache License, Version 2.0 (the "License"); 4 | * you may not use this file except in compliance with the License. 5 | * You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | * See the License for the specific language governing permissions and 13 | * limitations under the License. 14 | */ 15 | 16 | /* 17 | * ==================================================================== 18 | * 19 | * This class is inspired by org.apache.http.entity.mime.MultipartEntity 20 | * 21 | * ==================================================================== 22 | * 23 | */ 24 | 25 | using System; 26 | using System.Collections.Generic; 27 | using System.Text; 28 | 29 | using CodeScales.Http.Entity.Mime; 30 | using CodeScales.Http.Network; 31 | 32 | namespace CodeScales.Http.Entity 33 | { 34 | public class MultipartEntity : HttpEntity 35 | { 36 | private List m_bodyList = new List(); 37 | private string m_boundry; 38 | 39 | public MultipartEntity() 40 | { 41 | GenerateBoundry(); 42 | } 43 | 44 | public void AddBody(Body body) 45 | { 46 | this.m_bodyList.Add(body); 47 | } 48 | 49 | public string ContentEncoding 50 | { 51 | get { return null; } 52 | set {} 53 | } 54 | 55 | public string ContentType 56 | { 57 | get { return "multipart/form-data; boundary=" + m_boundry; } 58 | set {} 59 | } 60 | 61 | public byte[] Content 62 | { 63 | get 64 | { 65 | List byteList = new List(); 66 | foreach (Body body in this.m_bodyList) 67 | { 68 | byteList.AddRange(body.GetContent(this.m_boundry)); 69 | } 70 | if (this.m_bodyList.Count > 0) 71 | { 72 | byteList.AddRange(Encoding.ASCII.GetBytes(HTTPProtocol.AddPostParametersEnd(this.m_boundry))); 73 | } 74 | return byteList.ToArray(); 75 | } 76 | set {} 77 | } 78 | 79 | public long ContentLength 80 | { 81 | get 82 | { 83 | return this.Content.Length; 84 | } 85 | set {} 86 | } 87 | 88 | public bool IsChunked 89 | { 90 | get 91 | { 92 | return false; 93 | } 94 | set {} 95 | } 96 | 97 | private static string allowedCharacters = "abcdefghijklmnopqrstuvwxyz1234567890"; 98 | private void GenerateBoundry() 99 | { 100 | Random random = new Random(DateTime.Now.Millisecond); 101 | StringBuilder sb = new StringBuilder(); 102 | sb.Append("---------------------------"); 103 | for (int i = 0; i < 14; i++) 104 | { 105 | sb.Append(allowedCharacters[random.Next(allowedCharacters.Length-1)]); 106 | } 107 | this.m_boundry = sb.ToString(); 108 | } 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /src/CodeScales.Http/CodeScales.Http/Methods/HttpPost.cs: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2010 CodeScales.com 2 | * 3 | * Licensed under the Apache License, Version 2.0 (the "License"); 4 | * you may not use this file except in compliance with the License. 5 | * You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | * See the License for the specific language governing permissions and 13 | * limitations under the License. 14 | */ 15 | 16 | using System; 17 | using System.Collections.Generic; 18 | using System.Text; 19 | using System.Net; 20 | 21 | using CodeScales.Http.Entity; 22 | using CodeScales.Http.Protocol; 23 | 24 | namespace CodeScales.Http.Methods 25 | { 26 | public class HttpPost : HttpRequest, HttpEntityEnclosingRequest 27 | { 28 | private static string METHOD = "POST"; 29 | private HttpEntity m_entity = null; 30 | 31 | public HttpPost() 32 | { 33 | } 34 | 35 | public HttpPost(Uri uri) : this() 36 | { 37 | this.Uri = uri; 38 | } 39 | 40 | public override string Method 41 | { 42 | get 43 | { 44 | return METHOD; 45 | } 46 | } 47 | 48 | public override string GetRequestLine(bool useProxy) 49 | { 50 | string requestUri = null; 51 | if (useProxy) 52 | { 53 | requestUri = this.Uri.AbsoluteUri; 54 | } 55 | else 56 | { 57 | requestUri = this.Uri.PathAndQuery; 58 | } 59 | 60 | return Method + " " + requestUri + " HTTP/1.1"; 61 | } 62 | 63 | public HttpEntity Entity 64 | { 65 | get { return m_entity; } 66 | set { m_entity = value; } 67 | } 68 | 69 | public override WebHeaderCollection Headers 70 | { 71 | get 72 | { 73 | if (base.Headers != null && this.m_entity != null) 74 | { 75 | if (base.Headers[HTTP.CONTENT_LEN] == null 76 | || base.Headers[HTTP.CONTENT_LEN] == string.Empty) 77 | { 78 | base.Headers[HTTP.CONTENT_LEN] = this.m_entity.ContentLength.ToString(); 79 | } 80 | 81 | if (base.Headers[HTTP.CONTENT_TYPE] == null 82 | || base.Headers[HTTP.CONTENT_TYPE] == string.Empty) 83 | { 84 | base.Headers[HTTP.CONTENT_TYPE] = this.m_entity.ContentType; 85 | } 86 | base.Headers.Add(HTTP.USER_AGENT, @"Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322; .NET CLR 2.0.50727)"); 87 | } 88 | 89 | return base.Headers; 90 | } 91 | set 92 | { 93 | base.Headers = value; 94 | } 95 | } 96 | 97 | public bool ExpectContinue 98 | { 99 | get 100 | { 101 | if (base.Headers != null) 102 | { 103 | return (base.Headers[HTTP.EXPECT_DIRECTIVE] != null 104 | && base.Headers[HTTP.EXPECT_DIRECTIVE].Equals(HTTP.EXPECT_CONTINUE)); 105 | } 106 | else return false; 107 | } 108 | } 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /src/CodeScales.Http/CodeScales.Http/HttpBehavior.cs: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2010 CodeScales.com 2 | * 3 | * Licensed under the Apache License, Version 2.0 (the "License"); 4 | * you may not use this file except in compliance with the License. 5 | * You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | * See the License for the specific language governing permissions and 13 | * limitations under the License. 14 | */ 15 | 16 | using System; 17 | using System.Collections.Generic; 18 | using System.Text; 19 | 20 | namespace CodeScales.Http 21 | { 22 | public class HttpBehavior 23 | { 24 | private Queue m_steps = new Queue(); 25 | 26 | public void AddStep(int responseCode) 27 | { 28 | AddStep(responseCode, null); 29 | } 30 | 31 | public void AddStep(int responseCode, string url) 32 | { 33 | RedirectStep rs = new RedirectStep(); 34 | rs.ResponseCode = responseCode; 35 | rs.Url = url; 36 | m_steps.Enqueue(rs); 37 | } 38 | 39 | public bool IsEmpty() 40 | { 41 | return m_steps.Count == 0; 42 | } 43 | 44 | public RedirectStep GetNextStep() 45 | { 46 | if (m_steps.Count > 0) 47 | { 48 | return m_steps.Dequeue(); 49 | } 50 | else 51 | { 52 | // if there is no next step 53 | throw new HttpBehaviorException(); 54 | } 55 | } 56 | 57 | public class RedirectStep 58 | { 59 | private int m_responseCode = 0; 60 | private string m_url = null; 61 | 62 | public int ResponseCode 63 | { 64 | get { return m_responseCode; } 65 | set { m_responseCode = value; } 66 | } 67 | 68 | public string Url 69 | { 70 | get { return m_url; } 71 | set { m_url = value; } 72 | } 73 | 74 | internal void Compare(int responseStatus, string redirectUri) 75 | { 76 | if (m_responseCode != responseStatus) 77 | { 78 | throw new HttpBehaviorException(responseStatus, redirectUri); 79 | } 80 | 81 | if (m_responseCode == 301 || m_responseCode == 302) 82 | { 83 | if (IsEmpty(redirectUri) && !IsEmpty(m_url)) 84 | throw new HttpBehaviorException(); 85 | 86 | if (!IsEmpty(redirectUri) && IsEmpty(m_url)) 87 | throw new HttpBehaviorException(); 88 | 89 | if (redirectUri.StartsWith(m_url)) 90 | { 91 | return; //OK 92 | } 93 | else 94 | { 95 | throw new HttpBehaviorException(); 96 | } 97 | } 98 | } 99 | 100 | private bool IsEmpty(string uri) 101 | { 102 | if (uri == null || uri.Equals(string.Empty)) 103 | return true; 104 | else 105 | return false; 106 | } 107 | 108 | internal bool IsRedirect() 109 | { 110 | return (m_responseCode == 301 || m_responseCode == 302); 111 | } 112 | } 113 | } 114 | 115 | public class HttpBehaviorException : Exception 116 | { 117 | private int m_responseCode = 0; 118 | private string m_locatioon = null; 119 | 120 | public HttpBehaviorException() 121 | { 122 | } 123 | 124 | public HttpBehaviorException(int responseCode, string location) 125 | { 126 | this.m_responseCode = responseCode; 127 | this.m_locatioon = location; 128 | } 129 | } 130 | 131 | } 132 | 133 | -------------------------------------------------------------------------------- /src/CodeScales.Http/CodeScales.Http.Tests/HttpRedirectTests.cs: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2010 CodeScales.com 2 | * 3 | * Licensed under the Apache License, Version 2.0 (the "License"); 4 | * you may not use this file except in compliance with the License. 5 | * You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | * See the License for the specific language governing permissions and 13 | * limitations under the License. 14 | */ 15 | 16 | using System; 17 | using System.Collections.Generic; 18 | using System.Text; 19 | 20 | using CodeScales.Http; 21 | using CodeScales.Http.Methods; 22 | using CodeScales.Http.Entity; 23 | using NUnit.Framework; 24 | 25 | namespace CodeScales.Http.Tests 26 | { 27 | [TestFixture] 28 | public class HttpRedirectTests 29 | { 30 | [Test] 31 | public void HttpGetWithRedirect() 32 | { 33 | // with SetMaxRedirects 34 | // make sure we are not redirected 35 | HttpClient client = new HttpClient(); 36 | client.MaxRedirects = 0; 37 | HttpGet getMethod = new HttpGet(new Uri(Constants.HTTP_GET_302)); 38 | HttpResponse response = client.Execute(getMethod); 39 | 40 | Assert.AreEqual(302, response.ResponseCode); 41 | Console.Write(EntityUtils.ToString(response.Entity)); 42 | 43 | getMethod = new HttpGet(new Uri(response.Location)); 44 | response = client.Execute(getMethod); 45 | 46 | Assert.AreEqual(200, response.ResponseCode); 47 | Assert.AreEqual(Constants.HTTP_REDIRECT_TARGET_1, response.RequestUri.AbsoluteUri); 48 | string responseString = EntityUtils.ToString(response.Entity); 49 | Console.Write(responseString); 50 | 51 | } 52 | 53 | [Test] 54 | public void HttpGetWithRedirect2() 55 | { 56 | // with SetMaxRedirects 57 | // make sure we were redirected 58 | HttpClient client = new HttpClient(); 59 | client.MaxRedirects = 1; 60 | HttpGet getMethod = new HttpGet(new Uri(Constants.HTTP_GET_302)); 61 | HttpResponse response = client.Execute(getMethod); 62 | 63 | Assert.AreEqual(200, response.ResponseCode); 64 | Assert.AreEqual(Constants.HTTP_REDIRECT_TARGET_1, response.RequestUri.AbsoluteUri); 65 | string responseString = EntityUtils.ToString(response.Entity); 66 | Console.Write(responseString); 67 | 68 | } 69 | 70 | [Test] 71 | public void HttpGetWithRedirect3() 72 | { 73 | // this time with HTTPBehavior 74 | // make sure we were redirected and no exception is thrown 75 | HttpClient client = new HttpClient(); 76 | HttpBehavior httpBehavior = new HttpBehavior(); 77 | httpBehavior.AddStep(302, Constants.HTTP_REDIRECT_TARGET_1); 78 | httpBehavior.AddStep(200); 79 | HttpGet getMethod = new HttpGet(new Uri(Constants.HTTP_GET_302)); 80 | HttpResponse response = client.Execute(getMethod, httpBehavior); 81 | 82 | Assert.AreEqual(200, response.ResponseCode); 83 | Assert.AreEqual(Constants.HTTP_REDIRECT_TARGET_1, response.RequestUri.AbsoluteUri); 84 | string responseString = EntityUtils.ToString(response.Entity); 85 | Console.Write(responseString); 86 | } 87 | 88 | [Test] 89 | [ExpectedException(typeof(HttpBehaviorException))] 90 | public void HttpGetWithRedirect4() 91 | { 92 | // this time with HTTPBehavior 93 | // here both response code and location are wrong 94 | // make sure an exception is thrown 95 | 96 | HttpClient client = new HttpClient(); 97 | HttpBehavior httpBehavior = new HttpBehavior(); 98 | httpBehavior.AddStep(200); 99 | HttpGet getMethod = new HttpGet(new Uri(Constants.HTTP_GET_302)); 100 | HttpResponse response = client.Execute(getMethod, httpBehavior); 101 | } 102 | 103 | [Test] 104 | [ExpectedException(typeof(HttpBehaviorException))] 105 | public void HttpGetWithRedirect5() 106 | { 107 | // this time with HTTPBehavior 108 | // here the response code is wrong 109 | // make sure an exception is thrown 110 | 111 | HttpClient client = new HttpClient(); 112 | HttpBehavior httpBehavior = new HttpBehavior(); 113 | httpBehavior.AddStep(200, Constants.HTTP_GET_302); 114 | HttpGet getMethod = new HttpGet(new Uri(Constants.HTTP_GET_302)); 115 | HttpResponse response = client.Execute(getMethod, httpBehavior); 116 | } 117 | 118 | [Test] 119 | [ExpectedException(typeof(HttpBehaviorException))] 120 | public void HttpGetWithRedirect6() 121 | { 122 | // this time with HTTPBehavior 123 | // here the response location is wrong 124 | // make sure an exception is thrown 125 | 126 | HttpClient client = new HttpClient(); 127 | HttpBehavior httpBehavior = new HttpBehavior(); 128 | httpBehavior.AddStep(302, Constants.HTTP_GET_200); 129 | HttpGet getMethod = new HttpGet(new Uri(Constants.HTTP_GET_302)); 130 | HttpResponse response = client.Execute(getMethod, httpBehavior); 131 | } 132 | 133 | [Test] 134 | public void HttpGetWithRedirect7() 135 | { 136 | // this time with HTTPBehavior 137 | // make sure we get only the first response 138 | // and do not make the second call 139 | HttpClient client = new HttpClient(); 140 | HttpBehavior httpBehavior = new HttpBehavior(); 141 | httpBehavior.AddStep(302, Constants.HTTP_REDIRECT_TARGET_1); 142 | HttpGet getMethod = new HttpGet(new Uri(Constants.HTTP_GET_302)); 143 | HttpResponse response = client.Execute(getMethod, httpBehavior); 144 | 145 | Assert.AreEqual(302, response.ResponseCode); 146 | Assert.AreEqual(Constants.HTTP_REDIRECT_TARGET_1, response.Location); 147 | } 148 | 149 | } 150 | } 151 | -------------------------------------------------------------------------------- /src/CodeScales.Http/CodeScales.Http.Tests.Server/CodeScales.Http.Tests.Server.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | Debug 4 | AnyCPU 5 | 8.0.50727 6 | 2.0 7 | {064A9560-7590-42A9-9E33-1FC1689760B3} 8 | {349c5851-65df-11da-9384-00065b846f21};{fae04ec0-301f-11d3-bf4b-00c04f79efbc} 9 | Library 10 | Properties 11 | CodeScales.Http.Tests.Server 12 | CodeScales.Http.Tests.Server 13 | 14 | 15 | true 16 | full 17 | false 18 | bin\ 19 | DEBUG;TRACE 20 | prompt 21 | 4 22 | 23 | 24 | pdbonly 25 | true 26 | bin\ 27 | TRACE 28 | prompt 29 | 4 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | ASPXCodeBehind 57 | AspNetUpload.aspx 58 | 59 | 60 | AspNetUpload.aspx 61 | 62 | 63 | HttpMultipartPost200.aspx 64 | ASPXCodeBehind 65 | 66 | 67 | HttpMultipartPost200.aspx 68 | 69 | 70 | HttpPost200.aspx 71 | ASPXCodeBehind 72 | 73 | 74 | HttpPost200.aspx 75 | 76 | 77 | HttpGet200WithSetCookies.aspx 78 | ASPXCodeBehind 79 | 80 | 81 | HttpGet200WithSetCookies.aspx 82 | 83 | 84 | HttpGet302.aspx 85 | ASPXCodeBehind 86 | 87 | 88 | HttpGet302.aspx 89 | 90 | 91 | ASPXCodeBehind 92 | HttpGet200.aspx 93 | 94 | 95 | HttpGet200.aspx 96 | 97 | 98 | ASPXCodeBehind 99 | HttpRedirectTarget1.aspx 100 | 101 | 102 | HttpRedirectTarget1.aspx 103 | 104 | 105 | 106 | 107 | 108 | {AADEA75C-2370-4C6E-A704-FEA3E11A8EAB} 109 | CodeScales.Http.Tests 110 | 111 | 112 | {FC262E96-6275-4798-8181-D9001FB50541} 113 | CodeScales.Http 114 | 115 | 116 | 117 | 118 | 125 | 126 | 127 | 128 | 129 | False 130 | True 131 | 1508 132 | / 133 | 134 | 135 | False 136 | 137 | 138 | 139 | 140 | -------------------------------------------------------------------------------- /src/CodeScales.Http/CodeScales.Http.Tests/HttpGetTests.cs: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2010 CodeScales.com 2 | * 3 | * Licensed under the Apache License, Version 2.0 (the "License"); 4 | * you may not use this file except in compliance with the License. 5 | * You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | * See the License for the specific language governing permissions and 13 | * limitations under the License. 14 | */ 15 | 16 | using System; 17 | using System.Collections.Generic; 18 | using System.Text; 19 | 20 | using CodeScales.Http; 21 | using CodeScales.Http.Common; 22 | using CodeScales.Http.Methods; 23 | using CodeScales.Http.Entity; 24 | using NUnit.Framework; 25 | 26 | namespace CodeScales.Http.Tests 27 | { 28 | [TestFixture] 29 | public class HttpGetTests 30 | { 31 | [Test] 32 | public void HttpGet() 33 | { 34 | HttpClient client = new HttpClient(); 35 | HttpGet getMethod = new HttpGet(new Uri(Constants.HTTP_GET_200)); 36 | HttpResponse response = client.Execute(getMethod); 37 | 38 | Assert.AreEqual(200, response.ResponseCode); 39 | string responseString = EntityUtils.ToString(response.Entity); 40 | Assert.AreEqual(MessageData.Empty.ToString(), responseString); 41 | Assert.AreEqual(Constants.HTTP_GET_200, response.RequestUri.AbsoluteUri); 42 | Console.Write(responseString); 43 | 44 | } 45 | 46 | [Test] 47 | public void HttpGetWithParameters() 48 | { 49 | HttpClient client = new HttpClient(); 50 | HttpGet getMethod = new HttpGet(new Uri(Constants.HTTP_GET_200)); 51 | getMethod.Parameters.Add("test", "1 and text"); 52 | getMethod.Parameters.Add("test2", "2 and text <> &&"); 53 | HttpResponse response = client.Execute(getMethod); 54 | 55 | Assert.AreEqual(200, response.ResponseCode); 56 | Assert.AreEqual(Constants.HTTP_GET_200, response.RequestUri.AbsoluteUri); 57 | // assert the parameters 58 | MessageData md = new MessageData(); 59 | md.QueryParameters.Add(new NameValuePair("test", "1 and text")); 60 | md.QueryParameters.Add(new NameValuePair("test2", "2 and text <> &&")); 61 | string responseString = EntityUtils.ToString(response.Entity); 62 | Assert.AreEqual(md.ToString(), responseString); 63 | Console.Write(responseString); 64 | } 65 | 66 | [Test] 67 | public void HttpGetWithProxy() 68 | { 69 | HttpClient client = new HttpClient(); 70 | client.Proxy = new Uri(Constants.FIDDLER_DEFAULT_ADDRESS); 71 | HttpGet getMethod = new HttpGet(new Uri(Constants.HTTP_GET_200)); 72 | HttpResponse response = client.Execute(getMethod); 73 | 74 | Assert.AreEqual(200, response.ResponseCode); 75 | string responseString = EntityUtils.ToString(response.Entity); 76 | Assert.AreEqual(MessageData.Empty.ToString(), responseString); 77 | Assert.AreEqual(Constants.HTTP_GET_200, response.RequestUri.AbsoluteUri); 78 | Console.Write(responseString); 79 | } 80 | 81 | [Test] 82 | public void HttpGetWithCookies() 83 | { 84 | // with SetMaxRedirects 85 | // make sure we are not redirected 86 | HttpClient client = new HttpClient(); 87 | client.MaxRedirects = 0; 88 | HttpGet getMethod = new HttpGet(new Uri(Constants.HTTP_GET_200_WITH_SET_COOKIES)); 89 | getMethod.Parameters.Add("cookie1", "value1"); 90 | getMethod.Parameters.Add("cookie2", "value2"); 91 | HttpResponse response = client.Execute(getMethod); 92 | 93 | Assert.AreEqual(200, response.ResponseCode); 94 | Assert.AreEqual(Constants.HTTP_GET_200_WITH_SET_COOKIES, response.RequestUri.AbsoluteUri); 95 | 96 | getMethod = new HttpGet(new Uri(Constants.HTTP_GET_200)); 97 | response = client.Execute(getMethod); 98 | 99 | Assert.AreEqual(200, response.ResponseCode); 100 | Assert.AreEqual(Constants.HTTP_GET_200, response.RequestUri.AbsoluteUri); 101 | 102 | // assert the cookies 103 | MessageData md = new MessageData(); 104 | md.Cookies.Add(new NameValuePair("cookie1", "value1")); 105 | md.Cookies.Add(new NameValuePair("cookie2", "value2")); 106 | string responseString = EntityUtils.ToString(response.Entity); 107 | Assert.AreEqual(md.ToString(), responseString); 108 | Console.Write(responseString); 109 | } 110 | 111 | [Test] 112 | public void HttpGetWithChunkedResponse() 113 | { 114 | // we use codescales.com that is hosted by google 115 | // the google server always uses chunked transfer-encoding 116 | 117 | HttpClient client = new HttpClient(); 118 | HttpGet getMethod = new HttpGet(new Uri(Constants.HTTP_GET_200_CODESCALES_COM)); 119 | HttpResponse response = client.Execute(getMethod); 120 | 121 | Assert.AreEqual(200, response.ResponseCode); 122 | string responseString = EntityUtils.ToString(response.Entity); 123 | Assert.AreEqual(Constants.HTTP_GET_200_CODESCALES_COM, response.RequestUri.AbsoluteUri); 124 | Console.Write(responseString); 125 | } 126 | 127 | [Test] 128 | public void HttpGetWithChunkedResponse2() 129 | { 130 | // we use codescales.com that is hosted by google 131 | // the google server always uses chunked transfer-encoding 132 | 133 | HttpClient client = new HttpClient(); 134 | HttpGet getMethod = new HttpGet(new Uri("http://forums.photographyreview.com/showthread.php?t=68825")); 135 | HttpResponse response = client.Execute(getMethod); 136 | 137 | Assert.AreEqual(200, response.ResponseCode); 138 | string responseString = EntityUtils.ToString(response.Entity); 139 | Assert.AreEqual("http://forums.photographyreview.com/showthread.php?t=68825", response.RequestUri.AbsoluteUri); 140 | Console.Write(responseString); 141 | } 142 | 143 | } 144 | } 145 | -------------------------------------------------------------------------------- /src/CodeScales.Http/CodeScales.Http/HttpClient.cs: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2010 CodeScales.com 2 | * 3 | * Licensed under the Apache License, Version 2.0 (the "License"); 4 | * you may not use this file except in compliance with the License. 5 | * You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | * See the License for the specific language governing permissions and 13 | * limitations under the License. 14 | */ 15 | 16 | using System; 17 | using System.Collections.Generic; 18 | using System.Text; 19 | using System.Net; 20 | using System.IO; 21 | 22 | using CodeScales.Http.Cookies; 23 | using CodeScales.Http.Methods; 24 | using CodeScales.Http.Network; 25 | using CodeScales.Http.Entity; 26 | 27 | namespace CodeScales.Http 28 | { 29 | public class HttpClient 30 | { 31 | private HttpCookieStore m_cookieStore = new HttpCookieStore(); 32 | private Uri m_proxy = null; 33 | private int m_maxRedirects = 1; 34 | 35 | public Uri Proxy 36 | { 37 | set 38 | { 39 | this.m_proxy = value; 40 | } 41 | } 42 | 43 | public int MaxRedirects 44 | { 45 | set 46 | { 47 | this.m_maxRedirects = value; 48 | } 49 | get 50 | { 51 | return this.MaxRedirects; 52 | } 53 | } 54 | 55 | public HttpResponse Execute(HttpRequest request) 56 | { 57 | return Navigate(request, null); 58 | } 59 | 60 | public HttpResponse Execute(HttpRequest request, HttpBehavior httpBehavior) 61 | { 62 | return Navigate(request, httpBehavior); 63 | } 64 | 65 | private HttpResponse Navigate(HttpRequest request, HttpBehavior httpBehavior) 66 | { 67 | bool ContinueRedirect = true; 68 | HttpResponse response = null; 69 | 70 | HttpConnectionFactory connFactory = new HttpConnectionFactory(); 71 | HttpConnection connection = connFactory.GetConnnection(request.Uri, this.m_proxy); 72 | 73 | HttpBehavior.RedirectStep rs = null; 74 | string redirectUri = null; 75 | int responseCode = 0; 76 | int redirectCounter = 0; 77 | 78 | try 79 | { 80 | while (ContinueRedirect) 81 | { 82 | try 83 | { 84 | response = SendRequestAndGetResponse(connection, request); 85 | redirectUri = response.Location; 86 | responseCode = response.ResponseCode; 87 | 88 | // response code 100 means that we need to wait for another response 89 | // and receive the response from the socket again on the same connection 90 | if (responseCode == 100) 91 | { 92 | response = GetResponse(connection); 93 | redirectUri = response.Location; 94 | responseCode = response.ResponseCode; 95 | } 96 | 97 | if (httpBehavior != null) 98 | { 99 | rs = httpBehavior.GetNextStep(); 100 | rs.Compare(responseCode, redirectUri); 101 | ContinueRedirect = !httpBehavior.IsEmpty(); 102 | } 103 | else 104 | { 105 | ContinueRedirect = (redirectCounter < this.m_maxRedirects && (responseCode == 301 || responseCode == 302)); 106 | redirectCounter++; 107 | } 108 | 109 | if (ContinueRedirect) 110 | { 111 | request = new HttpGet(new Uri(redirectUri)); 112 | // make sure the connection is still open and redirect url is from the same host 113 | connection = connFactory.GetConnnection(request.Uri, this.m_proxy, connection); 114 | } 115 | 116 | } 117 | catch (Exception ex) 118 | { 119 | int i = 0; 120 | throw ex; 121 | } 122 | 123 | } 124 | } 125 | finally 126 | { 127 | connection.Close(); 128 | } 129 | return response; 130 | 131 | } 132 | 133 | private HttpResponse SendRequestAndGetResponse(HttpConnection connection, HttpRequest request) 134 | { 135 | m_cookieStore.WriteCookiesToRequest(request); 136 | 137 | // if we need to send a body (not only headers) 138 | if (request.GetType().GetInterface("HttpEntityEnclosingRequest") != null) 139 | { 140 | HttpEntityEnclosingRequest heer = (HttpEntityEnclosingRequest)request; 141 | connection.SendRequestHeaderAndEntity(request, heer.Entity, heer.ExpectContinue); 142 | } 143 | else 144 | { 145 | connection.SendRequestHeader(request); 146 | } 147 | 148 | return GetResponse(connection); 149 | 150 | } 151 | 152 | private HttpResponse GetResponse(HttpConnection connection) 153 | { 154 | HttpResponse response = connection.ReceiveResponseHeaders(); 155 | m_cookieStore.ReadCookiesFromResponse(response); 156 | connection.ReceiveResponseEntity(response); 157 | 158 | // for response code 100 we expect another http message to arrive later 159 | if (response.ResponseCode != 100) 160 | { 161 | connection.CheckKeepAlive(response); 162 | } 163 | return response; 164 | } 165 | 166 | private string GetRedirectUri(Uri uri) 167 | { 168 | if (uri != null) 169 | return uri.AbsoluteUri; 170 | else 171 | return ""; 172 | } 173 | 174 | 175 | } 176 | } 177 | -------------------------------------------------------------------------------- /src/CodeScales.Http/CodeScales.Http/Network/HttpProtocol.cs: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2010 CodeScales.com 2 | * 3 | * Licensed under the Apache License, Version 2.0 (the "License"); 4 | * you may not use this file except in compliance with the License. 5 | * You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | * See the License for the specific language governing permissions and 13 | * limitations under the License. 14 | */ 15 | 16 | using System; 17 | using System.Collections.Generic; 18 | using System.Text; 19 | using System.Web; 20 | 21 | using CodeScales.Http.Cookies; 22 | using CodeScales.Http.Common; 23 | 24 | namespace CodeScales.Http.Network 25 | { 26 | internal class HTTPProtocol 27 | { 28 | private const string VIEWSTATEStart = " ExtractUrlParameters(string url) 31 | { 32 | if (url.IndexOf('?') < 0) 33 | return null; 34 | string query = url.Substring(url.IndexOf('?') + 1); 35 | if (query == null) 36 | return null; 37 | string[] parameters = query.Split('&'); 38 | if (parameters.Length <= 0) 39 | return null; 40 | Dictionary dic = new Dictionary(StringComparer.InvariantCultureIgnoreCase); 41 | foreach (string param in parameters) 42 | { 43 | string[] namevalue = param.Split('='); 44 | if (namevalue != null && namevalue.Length == 2) 45 | { 46 | dic.Add(namevalue[0], namevalue[1]); 47 | } 48 | } 49 | return dic; 50 | } 51 | 52 | public static string GetViewState(string html) 53 | { 54 | string viewState = ""; 55 | if (html.IndexOf("__VIEWSTATE") > 0) 56 | { 57 | int start = html.IndexOf(VIEWSTATEStart) + VIEWSTATEStart.Length; 58 | int end = html.IndexOf("\"", start); 59 | viewState = html.Substring(start, end - start); 60 | } 61 | return viewState; 62 | } 63 | 64 | internal static void AddPostParameters(List parameters, StringBuilder builder) 65 | { 66 | int counter = 0; 67 | foreach (NameValuePair pair in parameters) 68 | { 69 | builder.Append(pair.Name + "=" + HttpUtility.UrlEncode(pair.Value)); 70 | if (counter < parameters.Count - 1) 71 | { 72 | builder.Append("&"); 73 | } 74 | counter++; 75 | } 76 | } 77 | 78 | internal static string GetPostParameter(string name, string value, string boundry) 79 | { 80 | StringBuilder builder = new StringBuilder(); 81 | string paramBoundry = "--" + boundry + "\r\n"; 82 | string stringParam = "Content-Disposition: form-data; name=\""; 83 | string paramEnd = "\"\r\n\r\n"; 84 | builder.Append(paramBoundry); 85 | builder.Append(stringParam + name + paramEnd + value + "\r\n"); 86 | return builder.ToString(); 87 | } 88 | 89 | internal static string AddPostParametersFile(string name, string fileName, string boundry, string contentType) 90 | { 91 | if (name == null) 92 | { 93 | name = string.Empty; 94 | } 95 | if (fileName == null) 96 | { 97 | fileName = string.Empty; 98 | } 99 | 100 | StringBuilder builder = new StringBuilder(); 101 | string paramBoundry = "--" + boundry + "\r\n"; 102 | string stringParam = "Content-Disposition: form-data; name=\""; 103 | string paramEnd = "\"; filename=\"" + fileName + "\"\r\nContent-Type: " + contentType + "\r\n\r\n"; 104 | builder.Append(paramBoundry); 105 | builder.Append(stringParam + name + paramEnd); 106 | return builder.ToString(); 107 | } 108 | 109 | internal static string AddPostParametersEnd(string boundry) 110 | { 111 | return "--" + boundry + "--\r\n\r\n"; 112 | } 113 | 114 | public static Encoding GetEncoding(string contentType) 115 | { 116 | Encoding encoding = null; 117 | string enStr = GetCharacterSet(contentType); 118 | if (enStr != null && enStr != string.Empty) 119 | { 120 | try 121 | { 122 | encoding = Encoding.GetEncoding(enStr); 123 | } 124 | catch 125 | { 126 | encoding = Encoding.UTF8; //default 127 | } 128 | } 129 | else 130 | { 131 | encoding = Encoding.UTF8; //default 132 | } 133 | return encoding; 134 | } 135 | 136 | private static string GetCharacterSet(string s) 137 | { 138 | s = s.ToUpper(); 139 | int start = s.LastIndexOf("CHARSET"); 140 | if (start == -1) 141 | return ""; 142 | 143 | 144 | start = s.IndexOf("=", start); 145 | if (start == -1) 146 | return ""; 147 | 148 | 149 | start++; 150 | s = s.Substring(start).Trim(); 151 | int end = s.Length; 152 | 153 | 154 | int i = s.IndexOf(";"); 155 | if (i != -1) 156 | end = i; 157 | i = s.IndexOf("\""); 158 | if (i != -1 && i < end) 159 | end = i; 160 | i = s.IndexOf("'"); 161 | if (i != -1 && i < end) 162 | end = i; 163 | i = s.IndexOf("/"); 164 | if (i != -1 && i < end) 165 | end = i; 166 | 167 | 168 | return s.Substring(0, end).Trim(); 169 | } 170 | 171 | public static string GetCookiesHeader(CodeScales.Http.Cookies.HttpCookieCollection cookies) 172 | { 173 | if (cookies != null && cookies.Count > 0) 174 | { 175 | int cookieCounter = 0; 176 | StringBuilder sb = new StringBuilder(); 177 | // sb.Append("Cookie: "); 178 | foreach (string key in cookies.Keys) 179 | { 180 | sb.Append(key + "=" + cookies.GetCookie(key).Value); 181 | if (cookieCounter < cookies.Count - 1) 182 | { 183 | sb.Append(';'); 184 | } 185 | cookieCounter++; 186 | } 187 | return sb.ToString(); // +"\r\n"; 188 | } 189 | return null; 190 | } 191 | 192 | public static void AddHttpCookie(string headerPart, CodeScales.Http.Cookies.HttpCookieCollection cookies) 193 | { 194 | if (headerPart == null || headerPart == "" || cookies == null) 195 | return; 196 | 197 | string[] cookie_components = headerPart.Split(';'); 198 | 199 | if (cookie_components != null && cookie_components.Length > 0) 200 | { 201 | string kv = cookie_components[0]; 202 | int pos = kv.IndexOf('='); 203 | if (pos == -1) 204 | { 205 | /* XXX ugh */ 206 | 207 | } 208 | else 209 | { 210 | string key = kv.Substring(0, pos).Trim(); 211 | string val = kv.Substring(pos + 1).Trim(); 212 | 213 | cookies.Add(key, new CodeScales.Http.Cookies.HttpCookie(key, val)); 214 | } 215 | } 216 | } 217 | } 218 | } 219 | 220 | -------------------------------------------------------------------------------- /src/CodeScales.Http/CodeScales.Http.Tests/HttpPostTests.cs: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2010 CodeScales.com 2 | * 3 | * Licensed under the Apache License, Version 2.0 (the "License"); 4 | * you may not use this file except in compliance with the License. 5 | * You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | * See the License for the specific language governing permissions and 13 | * limitations under the License. 14 | */ 15 | 16 | using System; 17 | using System.Collections.Generic; 18 | using System.Text; 19 | using System.IO; 20 | 21 | using CodeScales.Http; 22 | using CodeScales.Http.Common; 23 | using CodeScales.Http.Methods; 24 | using CodeScales.Http.Entity; 25 | using CodeScales.Http.Entity.Mime; 26 | using NUnit.Framework; 27 | 28 | using CodeScales.Http.Tests.resources; 29 | 30 | namespace CodeScales.Http.Tests 31 | { 32 | [TestFixture] 33 | public class HttpPostTests 34 | { 35 | [Test] 36 | public void HttpPost() 37 | { 38 | HttpClient client = new HttpClient(); 39 | HttpPost postMethod = new HttpPost(new Uri(Constants.HTTP_POST_200)); 40 | List nameValuePairList = new List(); 41 | nameValuePairList.Add(new NameValuePair("param1","value1")); 42 | nameValuePairList.Add(new NameValuePair("param2","!#$^&*((<>")); 43 | UrlEncodedFormEntity formEntity = new UrlEncodedFormEntity(nameValuePairList, Encoding.UTF8); 44 | postMethod.Entity = formEntity; 45 | HttpResponse response = client.Execute(postMethod); 46 | 47 | Assert.AreEqual(200, response.ResponseCode); 48 | string responseString = EntityUtils.ToString(response.Entity); 49 | MessageData md = new MessageData(); 50 | md.PostParameters.Add(new NameValuePair("param1", "value1")); 51 | md.PostParameters.Add(new NameValuePair("param2", "!#$^&*((<>")); 52 | Assert.AreEqual(md.ToString(), responseString); 53 | Assert.AreEqual(Constants.HTTP_POST_200, response.RequestUri.AbsoluteUri); 54 | Console.Write(responseString); 55 | 56 | } 57 | 58 | [Test] 59 | public void HttpPostWithParameters2() 60 | { 61 | HttpClient client = new HttpClient(); 62 | 63 | // first request - to get cookies 64 | HttpGet getMethod = new HttpGet(new Uri(Constants.HTTP_POST_W3SCHOOLS)); 65 | HttpResponse response = client.Execute(getMethod); 66 | Assert.AreEqual(200, response.ResponseCode); 67 | 68 | // second request - to send form data 69 | HttpPost postMethod = new HttpPost(new Uri(Constants.HTTP_POST_W3SCHOOLS)); 70 | List nameValuePairList = new List(); 71 | nameValuePairList.Add(new NameValuePair("fname", "user 1")); 72 | UrlEncodedFormEntity formEntity = new UrlEncodedFormEntity(nameValuePairList, Encoding.UTF8); 73 | postMethod.Entity = formEntity; 74 | response = client.Execute(postMethod); 75 | 76 | Assert.AreEqual(200, response.ResponseCode); 77 | string responseString = EntityUtils.ToString(response.Entity); 78 | Assert.IsTrue(responseString.Contains("Hello user 1!")); 79 | 80 | } 81 | 82 | [Test] 83 | public void HttpPostWithFilesAndParameters() 84 | { 85 | // this method sends an empty file (or no file :) 86 | HttpClient client = new HttpClient(); 87 | HttpPost postMethod = new HttpPost(new Uri(Constants.HTTP_MULTIPART_POST_200)); 88 | 89 | MultipartEntity multipartEntity = new MultipartEntity(); 90 | StringBody stringBody1 = new StringBody(Encoding.ASCII, "param1", "value1"); 91 | multipartEntity.AddBody(stringBody1); 92 | StringBody stringBody2 = new StringBody(Encoding.ASCII, "param2", "!#$^&*((<>"); 93 | multipartEntity.AddBody(stringBody2); 94 | FileBody fileBody1 = new FileBody("photo", "me.file", null); 95 | multipartEntity.AddBody(fileBody1); 96 | postMethod.Entity = multipartEntity; 97 | HttpResponse response = client.Execute(postMethod); 98 | 99 | Assert.AreEqual(200, response.ResponseCode); 100 | string responseString = EntityUtils.ToString(response.Entity); 101 | MessageData md = new MessageData(); 102 | md.PostParameters.Add(new NameValuePair("param1", "value1")); 103 | md.PostParameters.Add(new NameValuePair("param2", "!#$^&*((<>")); 104 | md.Files.Add(new NameValuePair("me.file", "0")); 105 | Assert.AreEqual(md.ToString(), responseString); 106 | Assert.AreEqual(Constants.HTTP_MULTIPART_POST_200, response.RequestUri.AbsoluteUri); 107 | Console.Write(responseString); 108 | } 109 | 110 | [Test] 111 | public void HttpPostWithFilesAndParameters2() 112 | { 113 | // this method sends a file and checks for the number of bytes recieved 114 | HttpClient client = new HttpClient(); 115 | HttpPost postMethod = new HttpPost(new Uri(Constants.HTTP_MULTIPART_POST_200)); 116 | 117 | MultipartEntity multipartEntity = new MultipartEntity(); 118 | 119 | string fileName = "big-text.txt"; 120 | 121 | FileInfo fi = ResourceManager.GetResourceFileInfo(fileName); 122 | FileBody fileBody1 = new FileBody("file", fileName, fi, "text/plain"); 123 | 124 | multipartEntity.AddBody(fileBody1); 125 | postMethod.Entity = multipartEntity; 126 | 127 | StringBody stringBody1 = new StringBody(Encoding.ASCII, "param1", "value1"); 128 | multipartEntity.AddBody(stringBody1); 129 | StringBody stringBody2 = new StringBody(Encoding.ASCII, "param2", "!#$^&*((<>"); 130 | multipartEntity.AddBody(stringBody2); 131 | 132 | HttpResponse response = client.Execute(postMethod); 133 | 134 | Assert.AreEqual(200, response.ResponseCode); 135 | string responseString = EntityUtils.ToString(response.Entity); 136 | MessageData md = new MessageData(); 137 | md.PostParameters.Add(new NameValuePair("param1", "value1")); 138 | md.PostParameters.Add(new NameValuePair("param2", "!#$^&*((<>")); 139 | md.Files.Add(new NameValuePair(fileName, fi.Length.ToString())); 140 | Assert.AreEqual(md.ToString(), responseString); 141 | Assert.AreEqual(Constants.HTTP_MULTIPART_POST_200, response.RequestUri.AbsoluteUri); 142 | Console.Write(responseString); 143 | } 144 | 145 | [Test] 146 | public void HttpPostWithFilesAndParameters3() 147 | { 148 | // this method sends a file and checks for the number of bytes recieved 149 | HttpClient client = new HttpClient(); 150 | string url = "http://www.fiddler2.com/sandbox/FileForm.asp"; 151 | HttpPost postMethod = new HttpPost(new Uri(url)); 152 | 153 | MultipartEntity multipartEntity = new MultipartEntity(); 154 | postMethod.Entity = multipartEntity; 155 | 156 | string fileName = "small-text.txt"; 157 | 158 | StringBody stringBody1 = new StringBody(Encoding.ASCII, "1", "1_"); 159 | multipartEntity.AddBody(stringBody1); 160 | 161 | FileInfo fi = ResourceManager.GetResourceFileInfo(fileName); 162 | FileBody fileBody1 = new FileBody("fileentry", fileName, fi, "text/plain"); 163 | multipartEntity.AddBody(fileBody1); 164 | 165 | StringBody stringBody2 = new StringBody(Encoding.ASCII, "_charset_", "windows-1252"); 166 | multipartEntity.AddBody(stringBody2); 167 | 168 | HttpResponse response = client.Execute(postMethod); 169 | 170 | Assert.AreEqual(200, response.ResponseCode); 171 | string responseString = EntityUtils.ToString(response.Entity); 172 | Assert.AreEqual(url, response.RequestUri.AbsoluteUri); 173 | Console.Write(responseString); 174 | } 175 | } 176 | } 177 | -------------------------------------------------------------------------------- /src/CodeScales.Http/CodeScales.Http.Tests/resources/big-text.txt: -------------------------------------------------------------------------------- 1 | this is a test this is a test this is a test 2 | this is a test this is a test this is a test 3 | this is a test this is a test this is a test 4 | this is a test this is a test this is a test 5 | this is a test this is a test this is a test 6 | this is a test this is a test this is a test 7 | this is a test this is a test this is a test 8 | this is a test this is a test this is a test 9 | this is a test this is a test this is a test 10 | this is a test this is a test this is a test 11 | this is a test this is a test this is a test 12 | this is a test this is a test this is a test 13 | this is a test this is a test this is a test 14 | this is a test this is a test this is a test 15 | this is a test this is a test this is a test 16 | this is a test this is a test this is a test 17 | this is a test this is a test this is a test 18 | this is a test this is a test this is a test 19 | this is a test this is a test this is a test 20 | this is a test this is a test this is a test 21 | this is a test this is a test this is a test 22 | this is a test this is a test this is a test 23 | this is a test this is a test this is a test 24 | this is a test this is a test this is a test 25 | this is a test this is a test this is a test 26 | this is a test this is a test this is a test 27 | this is a test this is a test this is a test 28 | this is a test this is a test this is a test 29 | this is a test this is a test this is a test 30 | this is a test this is a test this is a test 31 | this is a test this is a test this is a test 32 | this is a test this is a test this is a test 33 | this is a test this is a test this is a test 34 | this is a test this is a test this is a test 35 | this is a test this is a test this is a test 36 | this is a test this is a test this is a test 37 | this is a test this is a test this is a test 38 | this is a test this is a test this is a test 39 | this is a test this is a test this is a test 40 | this is a test this is a test this is a test 41 | this is a test this is a test this is a test 42 | this is a test this is a test this is a test 43 | this is a test this is a test this is a test 44 | this is a test this is a test this is a test 45 | this is a test this is a test this is a test 46 | this is a test this is a test this is a test 47 | this is a test this is a test this is a test 48 | this is a test this is a test this is a test 49 | this is a test this is a test this is a test 50 | this is a test this is a test this is a test 51 | this is a test this is a test this is a test 52 | this is a test this is a test this is a test 53 | this is a test this is a test this is a test 54 | this is a test this is a test this is a test 55 | this is a test this is a test this is a test 56 | this is a test this is a test this is a test 57 | this is a test this is a test this is a test 58 | this is a test this is a test this is a test 59 | this is a test this is a test this is a test 60 | this is a test this is a test this is a test 61 | this is a test this is a test this is a test 62 | this is a test this is a test this is a test 63 | this is a test this is a test this is a test 64 | this is a test this is a test this is a test 65 | this is a test this is a test this is a test 66 | this is a test this is a test this is a test 67 | this is a test this is a test this is a test 68 | this is a test this is a test this is a test 69 | this is a test this is a test this is a test 70 | this is a test this is a test this is a test 71 | this is a test this is a test this is a test 72 | this is a test this is a test this is a test 73 | this is a test this is a test this is a test 74 | this is a test this is a test this is a test 75 | this is a test this is a test this is a test 76 | this is a test this is a test this is a test 77 | this is a test this is a test this is a test 78 | this is a test this is a test this is a test 79 | this is a test this is a test this is a test 80 | this is a test this is a test this is a test 81 | this is a test this is a test this is a test 82 | this is a test this is a test this is a test 83 | this is a test this is a test this is a test 84 | this is a test this is a test this is a test 85 | this is a test this is a test this is a test 86 | this is a test this is a test this is a test 87 | this is a test this is a test this is a test 88 | this is a test this is a test this is a test 89 | this is a test this is a test this is a test 90 | this is a test this is a test this is a test 91 | this is a test this is a test this is a test 92 | this is a test this is a test this is a test 93 | this is a test this is a test this is a test 94 | this is a test this is a test this is a test 95 | this is a test this is a test this is a test 96 | this is a test this is a test this is a test 97 | this is a test this is a test this is a test 98 | this is a test this is a test this is a test 99 | this is a test this is a test this is a test 100 | this is a test this is a test this is a test 101 | this is a test this is a test this is a test 102 | this is a test this is a test this is a test 103 | this is a test this is a test this is a test 104 | this is a test this is a test this is a test 105 | this is a test this is a test this is a test 106 | this is a test this is a test this is a test 107 | this is a test this is a test this is a test 108 | this is a test this is a test this is a test 109 | this is a test this is a test this is a test 110 | this is a test this is a test this is a test 111 | this is a test this is a test this is a test 112 | this is a test this is a test this is a test 113 | this is a test this is a test this is a test 114 | this is a test this is a test this is a test 115 | this is a test this is a test this is a test 116 | this is a test this is a test this is a test 117 | this is a test this is a test this is a test 118 | this is a test this is a test this is a test 119 | this is a test this is a test this is a test 120 | this is a test this is a test this is a test 121 | this is a test this is a test this is a test 122 | this is a test this is a test this is a test 123 | this is a test this is a test this is a test 124 | this is a test this is a test this is a test 125 | this is a test this is a test this is a test 126 | this is a test this is a test this is a test 127 | this is a test this is a test this is a test 128 | this is a test this is a test this is a test 129 | this is a test this is a test this is a test 130 | this is a test this is a test this is a test 131 | this is a test this is a test this is a test 132 | this is a test this is a test this is a test 133 | this is a test this is a test this is a test 134 | this is a test this is a test this is a test 135 | this is a test this is a test this is a test 136 | this is a test this is a test this is a test 137 | this is a test this is a test this is a test 138 | this is a test this is a test this is a test 139 | this is a test this is a test this is a test 140 | this is a test this is a test this is a test 141 | this is a test this is a test this is a test 142 | this is a test this is a test this is a test 143 | this is a test this is a test this is a test 144 | this is a test this is a test this is a test 145 | this is a test this is a test this is a test 146 | this is a test this is a test this is a test 147 | this is a test this is a test this is a test 148 | this is a test this is a test this is a test 149 | this is a test this is a test this is a test 150 | this is a test this is a test this is a test 151 | this is a test this is a test this is a test 152 | this is a test this is a test this is a test 153 | this is a test this is a test this is a test 154 | this is a test this is a test this is a test 155 | this is a test this is a test this is a test 156 | this is a test this is a test this is a test 157 | this is a test this is a test this is a test 158 | this is a test this is a test this is a test 159 | this is a test this is a test this is a test 160 | this is a test this is a test this is a test 161 | this is a test this is a test this is a test 162 | this is a test this is a test this is a test 163 | this is a test this is a test this is a test 164 | this is a test this is a test this is a test 165 | this is a test this is a test this is a test 166 | this is a test this is a test this is a test 167 | this is a test this is a test this is a test 168 | this is a test this is a test this is a test 169 | this is a test this is a test this is a test 170 | this is a test this is a test this is a test 171 | this is a test this is a test this is a test 172 | this is a test this is a test this is a test 173 | this is a test this is a test this is a test 174 | this is a test this is a test this is a test 175 | this is a test this is a test this is a test 176 | this is a test this is a test this is a test 177 | this is a test this is a test this is a test 178 | this is a test this is a test this is a test 179 | this is a test this is a test this is a test 180 | this is a test this is a test this is a test 181 | this is a test this is a test this is a test 182 | this is a test this is a test this is a test 183 | this is a test this is a test this is a test 184 | this is a test this is a test this is a test 185 | this is a test this is a test this is a test 186 | this is a test this is a test this is a test 187 | this is a test this is a test this is a test 188 | this is a test this is a test this is a test 189 | this is a test this is a test this is a test 190 | this is a test this is a test this is a test 191 | this is a test this is a test this is a test 192 | this is a test this is a test this is a test 193 | this is a test this is a test this is a test 194 | this is a test this is a test this is a test 195 | this is a test this is a test this is a test 196 | this is a test this is a test this is a test 197 | this is a test this is a test this is a test 198 | this is a test this is a test this is a test 199 | this is a test this is a test this is a test 200 | this is a test this is a test this is a test 201 | this is a test this is a test this is a test 202 | this is a test this is a test this is a test 203 | this is a test this is a test this is a test 204 | this is a test this is a test this is a test 205 | this is a test this is a test this is a test 206 | this is a test this is a test this is a test 207 | this is a test this is a test this is a test 208 | this is a test this is a test this is a test 209 | this is a test this is a test this is a test 210 | this is a test this is a test this is a test 211 | this is a test this is a test this is a test 212 | this is a test this is a test this is a test 213 | this is a test this is a test this is a test 214 | this is a test this is a test this is a test 215 | this is a test this is a test this is a test 216 | this is a test this is a test this is a test 217 | this is a test this is a test this is a test 218 | this is a test this is a test this is a test 219 | this is a test this is a test this is a test 220 | this is a test this is a test this is a test 221 | this is a test this is a test this is a test 222 | this is a test this is a test this is a test 223 | this is a test this is a test this is a test 224 | this is a test this is a test this is a test 225 | this is a test this is a test this is a test 226 | this is a test this is a test this is a test 227 | this is a test this is a test this is a test 228 | this is a test this is a test this is a test 229 | this is a test this is a test this is a test 230 | this is a test this is a test this is a test 231 | this is a test this is a test this is a test 232 | this is a test this is a test this is a test 233 | this is a test this is a test this is a test 234 | this is a test this is a test this is a test 235 | this is a test this is a test this is a test 236 | this is a test this is a test this is a test 237 | this is a test this is a test this is a test 238 | this is a test this is a test this is a test 239 | this is a test this is a test this is a test 240 | this is a test this is a test this is a test 241 | this is a test this is a test this is a test 242 | this is a test this is a test this is a test 243 | this is a test this is a test this is a test 244 | this is a test this is a test this is a test 245 | this is a test this is a test this is a test 246 | this is a test this is a test this is a test 247 | this is a test this is a test this is a test 248 | this is a test this is a test this is a test 249 | this is a test this is a test this is a test 250 | this is a test this is a test this is a test 251 | this is a test this is a test this is a test 252 | this is a test this is a test this is a test 253 | this is a test this is a test this is a test 254 | this is a test this is a test this is a test 255 | this is a test this is a test this is a test 256 | this is a test this is a test this is a test 257 | this is a test this is a test this is a test 258 | this is a test this is a test this is a test 259 | this is a test this is a test this is a test 260 | this is a test this is a test this is a test 261 | this is a test this is a test this is a test 262 | this is a test this is a test this is a test 263 | this is a test this is a test this is a test 264 | this is a test this is a test this is a test 265 | this is a test this is a test this is a test 266 | this is a test this is a test this is a test 267 | this is a test this is a test this is a test 268 | -------------------------------------------------------------------------------- /src/CodeScales.Http/CodeScales.Http/Network/HttpConnection.cs: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2010 CodeScales.com 2 | * 3 | * Licensed under the Apache License, Version 2.0 (the "License"); 4 | * you may not use this file except in compliance with the License. 5 | * You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | * See the License for the specific language governing permissions and 13 | * limitations under the License. 14 | */ 15 | 16 | using System; 17 | using System.Collections.Generic; 18 | using System.Text; 19 | using System.Text.RegularExpressions; 20 | using System.Net; 21 | using System.Net.Sockets; 22 | using System.Threading; 23 | 24 | using CodeScales.Http.Methods; 25 | using CodeScales.Http.Entity; 26 | using CodeScales.Http.Protocol; 27 | 28 | namespace CodeScales.Http.Network 29 | { 30 | internal class HttpConnection 31 | { 32 | 33 | private HttpConnectionFactory m_factory = null; 34 | private bool m_isBusy = false; 35 | private Socket m_socket = null; 36 | private Uri m_proxy = null; 37 | private Uri m_uri = null; 38 | private int m_timeout = 60 * 1000; 39 | 40 | internal HttpConnection(HttpConnectionFactory factory, Uri uri, Uri proxy) 41 | { 42 | this.m_factory = factory; 43 | this.m_uri = uri; 44 | this.m_proxy = proxy; 45 | } 46 | 47 | internal Uri Uri 48 | { 49 | get 50 | { 51 | return this.m_uri; 52 | } 53 | } 54 | 55 | internal Uri EndPointUri 56 | { 57 | get 58 | { 59 | if (this.m_proxy != null) 60 | { 61 | return this.m_proxy; 62 | } 63 | else 64 | { 65 | return this.m_uri; 66 | } 67 | } 68 | } 69 | 70 | internal bool IsConnected() 71 | { 72 | return (m_socket != null 73 | && m_socket.Connected); 74 | } 75 | 76 | internal void Connect() 77 | { 78 | m_socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); 79 | IPEndPoint remoteEP = new IPEndPoint(Dns.Resolve(this.EndPointUri.Host).AddressList[0], EndPointUri.Port); 80 | m_socket.Connect(remoteEP); 81 | 82 | m_socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.SendTimeout, 60 * 1000); 83 | m_socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReceiveTimeout, 60 * 1000); 84 | } 85 | 86 | public void Close() 87 | { 88 | if (m_socket != null) 89 | { 90 | m_socket.Close(); 91 | } 92 | } 93 | 94 | public bool IsBusy() 95 | { 96 | return this.m_isBusy; 97 | } 98 | 99 | public void SetBusy(bool busyState) 100 | { 101 | this.m_isBusy = busyState; 102 | } 103 | 104 | public void CheckKeepAlive(HttpResponse response) 105 | { 106 | WebHeaderCollection headers = response.Headers; 107 | 108 | if ((headers[HTTP.CONN_DIRECTIVE] != null && headers[HTTP.CONN_DIRECTIVE].ToLower() == HTTP.CONN_KEEP_ALIVE) || 109 | (headers[HTTP.PROXY_CONN_DIRECTIVE] != null && headers[HTTP.PROXY_CONN_DIRECTIVE].ToLower() == HTTP.CONN_KEEP_ALIVE)) 110 | { 111 | return; 112 | } 113 | else 114 | { 115 | this.Close(); 116 | } 117 | } 118 | 119 | public void SendRequestHeader(HttpRequest request) 120 | { 121 | if (!this.IsConnected()) 122 | { 123 | throw new HttpNetworkException("Socket is closed or not ready"); 124 | } 125 | this.m_socket.Send(Encoding.ASCII.GetBytes(GetRequestHeader(request).ToString())); 126 | 127 | int counter = 0; 128 | // wait another timeout period for the response to arrive. 129 | while (!(this.m_socket.Available > 0) && counter < (this.m_timeout / 100)) 130 | { 131 | counter++; 132 | Thread.Sleep(100); 133 | } 134 | } 135 | 136 | public void SendRequestHeaderAndEntity(HttpRequest request, HttpEntity httpEntity, bool expectContinue) 137 | { 138 | if (!this.IsConnected()) 139 | { 140 | throw new HttpNetworkException("Socket is closed or not ready"); 141 | } 142 | byte[] header = Encoding.ASCII.GetBytes(GetRequestHeader(request).ToString()); 143 | byte[] body = httpEntity.Content; 144 | 145 | // first send the headers 146 | Send(header, 0, header.Length, this.m_timeout); 147 | 148 | // then look for 100-continue response for no more than 2 seconds 149 | if (expectContinue) 150 | { 151 | // 2 seconds timeout for 100-continue 152 | WaitForDataToArriveAtSocket(2 * 1000); 153 | if (this.m_socket.Available > 0) 154 | { 155 | // now read the 100-continue response 156 | HttpResponse response = ReceiveResponseHeaders(); 157 | if (response.ResponseCode != 100) 158 | { 159 | throw new HttpNetworkException("reponse returned before entity was sent, but it is not 100-continue"); 160 | } 161 | } 162 | } 163 | 164 | byte[] message = body; 165 | 166 | int sendBufferSize = this.m_socket.SendBufferSize; 167 | int size = (message.Length > sendBufferSize) ? sendBufferSize : message.Length; 168 | for (int i = 0; i < message.Length; i = i + size) 169 | { 170 | int remaining = (size < (message.Length - i)) ? size : (message.Length - i); 171 | Send(message, i, remaining, this.m_timeout); 172 | } 173 | 174 | } 175 | 176 | private void WaitForDataToArriveAtSocket(int timeout) 177 | { 178 | int counter = 0; 179 | // wait another timeout period for the response to arrive. 180 | while (!(this.m_socket.Available > 0) && counter < (timeout / 100)) 181 | { 182 | counter++; 183 | Thread.Sleep(100); 184 | } 185 | } 186 | 187 | private void Send(byte[] buffer, int offset, int size, int timeout) 188 | { 189 | int startTickCount = Environment.TickCount; 190 | int sent = 0; // how many bytes is already sent 191 | do 192 | { 193 | if (Environment.TickCount > startTickCount + timeout) 194 | throw new Exception("Timeout."); 195 | try 196 | { 197 | sent += this.m_socket.Send(buffer, offset + sent, size - sent, SocketFlags.None); 198 | } 199 | catch (SocketException ex) 200 | { 201 | if (ex.SocketErrorCode == SocketError.WouldBlock || 202 | ex.SocketErrorCode == SocketError.IOPending || 203 | ex.SocketErrorCode == SocketError.NoBufferSpaceAvailable) 204 | { 205 | // socket buffer is probably full, wait and try again 206 | Thread.Sleep(30); 207 | } 208 | else 209 | throw ex; // any serious error occurr 210 | } 211 | } while (sent < size); 212 | } 213 | 214 | private StringBuilder GetRequestHeader(HttpRequest request) 215 | { 216 | StringBuilder sb = new StringBuilder(); 217 | sb.AppendLine(request.GetRequestLine(this.m_proxy != null)); 218 | sb.AppendLine("Host: " + this.m_uri.Host); 219 | sb.Append(request.Headers); 220 | return sb; 221 | } 222 | 223 | public HttpResponse ReceiveResponseHeaders() 224 | { 225 | if (!this.IsConnected()) 226 | { 227 | throw new HttpNetworkException("Socket is closed or not ready"); 228 | } 229 | 230 | WaitForDataToArriveAtSocket(this.m_timeout); 231 | 232 | HttpResponse httpResponse = new HttpResponse(); 233 | httpResponse.RequestUri = this.Uri; 234 | string Header = ""; 235 | WebHeaderCollection Headers = new WebHeaderCollection(); 236 | 237 | byte[] bytes = new byte[10]; 238 | while (this.m_socket.Receive(bytes, 0, 1, SocketFlags.None) > 0) 239 | { 240 | Header += Encoding.ASCII.GetString(bytes, 0, 1); 241 | if (bytes[0] == '\n' && Header.EndsWith("\r\n\r\n")) 242 | break; 243 | } 244 | MatchCollection matches = new Regex("[^\r\n]+").Matches(Header.TrimEnd('\r', '\n')); 245 | for (int n = 1; n < matches.Count; n++) 246 | { 247 | string[] strItem = matches[n].Value.Split(new char[] { ':' }, 2); 248 | if (strItem.Length > 1) 249 | { 250 | if (!strItem[0].Trim().ToLower().Equals("set-cookie")) 251 | { 252 | Headers.Add(strItem[0].Trim(), strItem[1].Trim()); 253 | } 254 | else 255 | { 256 | Headers.Add(strItem[0].Trim(), strItem[1].Trim()); 257 | // HTTPProtocol.AddHttpCookie(strItem[1].Trim(), cookieCollection); 258 | } 259 | } 260 | } 261 | 262 | httpResponse.Headers = Headers; 263 | 264 | // set the response code 265 | if (matches.Count > 0) 266 | { 267 | try 268 | { 269 | string firstLine = matches[0].Value; 270 | int index1 = firstLine.IndexOf(" "); 271 | int index2 = firstLine.IndexOf(" ", index1 + 1); 272 | httpResponse.ResponseCode = Int32.Parse(firstLine.Substring(index1 + 1, index2 - index1 - 1)); 273 | } 274 | catch (Exception ex) 275 | { 276 | throw new HttpNetworkException("Response Code is missing from the response"); 277 | } 278 | } 279 | 280 | return httpResponse; 281 | 282 | } 283 | 284 | public void ReceiveResponseEntity(HttpResponse response) 285 | { 286 | if (!this.IsConnected()) 287 | { 288 | throw new HttpNetworkException("Socket is closed or not ready"); 289 | } 290 | 291 | string chunkedHeader = EntityUtils.GetTransferEncoding(response.Headers); 292 | if (chunkedHeader != null 293 | && chunkedHeader.ToLower().Equals(HTTP.CHUNK_CODING)) 294 | { 295 | List byteBuffer = new List(); 296 | BasicHttpEntity httpEntity = new BasicHttpEntity(); 297 | httpEntity.ContentLength = 0; 298 | httpEntity.ContentType = EntityUtils.GetContentType(response.Headers); 299 | response.Entity = httpEntity; 300 | 301 | int chunkSize = EntityUtils.ConvertHexToInt(ReceiveLine()); 302 | while (chunkSize > 0) 303 | { 304 | // for each chunk... 305 | byteBuffer.AddRange(ReceiveBytes(chunkSize)); 306 | httpEntity.ContentLength += chunkSize; 307 | string test = ReceiveLine(); 308 | chunkSize = EntityUtils.ConvertHexToInt(ReceiveLine()); 309 | } 310 | 311 | httpEntity.Content = byteBuffer.ToArray(); 312 | } 313 | else 314 | { 315 | // TODO: support "Transfer-Encoding: chunked" 316 | int length = EntityUtils.GetContentLength(response.Headers); 317 | if (length > 0) 318 | { 319 | BasicHttpEntity httpEntity = new BasicHttpEntity(); 320 | httpEntity.ContentLength = length; 321 | httpEntity.Content = ReceiveBytes(length).ToArray(); 322 | httpEntity.ContentType = EntityUtils.GetContentType(response.Headers); 323 | response.Entity = httpEntity; 324 | } 325 | } 326 | 327 | return; 328 | } 329 | 330 | private string ReceiveLine() 331 | { 332 | WaitForDataToArriveAtSocket(this.m_timeout); 333 | 334 | string line = string.Empty; 335 | byte[] bytes = new byte[10]; 336 | while (this.m_socket.Receive(bytes, 0, 1, SocketFlags.None) > 0) 337 | { 338 | line += Encoding.ASCII.GetString(bytes, 0, 1); 339 | if (bytes[0] == '\n' && line.EndsWith("\r\n")) 340 | break; 341 | } 342 | return line.Replace("\r\n",""); 343 | } 344 | 345 | private List ReceiveBytes(long size) 346 | { 347 | WaitForDataToArriveAtSocket(this.m_timeout); 348 | 349 | List byteBuffer = new List(); 350 | int minSize = 10240; 351 | if (size < 10240) 352 | { 353 | minSize = (int)size; 354 | } 355 | byte[] RecvBuffer = new byte[minSize]; 356 | long nBytes, nTotalBytes = 0; 357 | int RecvSize = minSize; 358 | 359 | // loop to receive response buffer 360 | while ((nBytes = this.m_socket.Receive(RecvBuffer, 0, RecvSize, SocketFlags.None)) > 0) 361 | { 362 | // increment total received bytes 363 | nTotalBytes += nBytes; 364 | 365 | // add received buffer to response string 366 | if (nBytes < minSize) 367 | { 368 | byte[] smallByteArray = new byte[nBytes]; 369 | for (int i = 0; i < nBytes; i++) 370 | { 371 | smallByteArray[i] = RecvBuffer[i]; 372 | } 373 | byteBuffer.AddRange(smallByteArray); 374 | } 375 | else 376 | { 377 | byteBuffer.AddRange(RecvBuffer); 378 | } 379 | 380 | if (nTotalBytes >= size && size > 0) 381 | break; 382 | else 383 | { 384 | long nBytesLeft = size - nTotalBytes; 385 | if (nBytesLeft < RecvSize) 386 | { 387 | RecvSize = (int)nBytesLeft; 388 | } 389 | } 390 | } 391 | return byteBuffer; 392 | } 393 | 394 | } 395 | } 396 | --------------------------------------------------------------------------------