From d2ce2e6e79ae45979362cc5583258285274b10dc Mon Sep 17 00:00:00 2001 From: Deniz Piri Date: Fri, 29 May 2015 20:47:05 +0200 Subject: [PATCH 01/20] ResponseCallbackDispatcher should be marked with DonDestroyOnLoad() This patch allows ResponseCallbackDispatcher to survive when a new level is loaded in. --- src/ResponseCallbackDispatcher.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/ResponseCallbackDispatcher.cs b/src/ResponseCallbackDispatcher.cs index f87c31c..2f857aa 100644 --- a/src/ResponseCallbackDispatcher.cs +++ b/src/ResponseCallbackDispatcher.cs @@ -33,6 +33,7 @@ public static void Init() } singletonGameObject = new GameObject(); + GameObject.DontDestroyOnLoad(singletonGameObject); singleton = singletonGameObject.AddComponent< ResponseCallbackDispatcher >(); singletonGameObject.name = "HTTPResponseCallbackDispatcher"; } From cd76bd5d75fe8551254664cd4367ef8faeb8cf4a Mon Sep 17 00:00:00 2001 From: Yakov Borevich Date: Mon, 8 Jun 2015 15:15:41 +0300 Subject: [PATCH 02/20] StreamedWWWForm for UnityHTTP --- src/FormDataStream.cs | 158 +++++++++++++++++++++++++++++++++++++++++ src/Request.cs | 35 ++++++--- src/StreamedWWWForm.cs | 62 ++++++++++++++++ 3 files changed, 246 insertions(+), 9 deletions(-) create mode 100644 src/FormDataStream.cs create mode 100644 src/StreamedWWWForm.cs diff --git a/src/FormDataStream.cs b/src/FormDataStream.cs new file mode 100644 index 0000000..71da5ed --- /dev/null +++ b/src/FormDataStream.cs @@ -0,0 +1,158 @@ +using System; +using System.IO; +using System.Text; +using System.Collections.Generic; +namespace HTTP { + + public class FormPart { + string fieldName; + string mimeType; + byte[] header; + Stream contents; + int position = 0; + + public FormPart(string fieldName, string mimeType, string boundary, Stream contents, string fileName=null){ + string filenameheader = ""; + if (fileName != null){ + filenameheader = "; filename=\"" + fileName +"\""; + } + header = Encoding.ASCII.GetBytes( + "\r\n--" + boundary + "\r\n" + + "Content-Type: " + mimeType + "\r\n" + + "Content-disposition: form-data; name=\"" + fieldName + "\"" + filenameheader + "\r\n\r\n" + ); + this.contents = contents; + } + public long Length { + get { + return header.Length + contents.Length; + } + } + public int Read(byte[] buffer, int offset, int size){ + int writed = 0; + int bytesToWrite; + if (position < header.Length){ + bytesToWrite = (int)(header.Length - position) > size ? size : (int)(header.Length - position); + Array.Copy ( + header, // from header + position, // started from position + buffer, // to buffer + offset, // started with offset + bytesToWrite + ); + writed += bytesToWrite; + position += bytesToWrite; + } + if (writed >= size){ + return writed; + } + bytesToWrite = contents.Read(buffer, writed + offset, size - writed); + writed += bytesToWrite; + position += bytesToWrite; + return writed; + } + } + + public class FormDataStream: Stream { + long position = 0; + List parts = new List(); + bool dirty = false; + byte[] footer; + string boundary; + + public FormDataStream(string boundary){ + this.boundary = boundary; + footer = Encoding.ASCII.GetBytes("\r\n--" + boundary + "--\r\n"); + } + + public override bool CanRead { get { return true; } } + public override bool CanSeek { get { return false; } } + public override bool CanTimeout { get { return false; } } + public override bool CanWrite { get { return false; } } + public override int ReadTimeout { get { return 0; } set { } } + public override int WriteTimeout { get { return 0; } set { } } + public override long Position { + get { + return position; + } + set { + throw new NotImplementedException("FormDataStream is non-seekable stream"); + } + } + public override long Length { + get { + if (parts.Count == 0){ + return 0; + } + dirty = true; + long len = 0; + foreach (var part in parts){ + len += part.Length; + } + return len + footer.Length; + } + } + + public override void Flush(){ + throw new NotImplementedException("FormDataStream is readonly stream"); + } + + public override int Read(byte[] buffer, int offset, int count){ + dirty = true; + int writed = 0; + int bytesToWrite = 0; + + // write parts + long partsSize = 0; + foreach (var part in parts){ + partsSize += part.Length; + if (position > partsSize){ + continue; + } + bytesToWrite = part.Read(buffer, writed + offset, count - writed); + writed += bytesToWrite; + position += bytesToWrite; + if (writed >= count){ + return count; + } + } + + + // write footer + bytesToWrite = count - writed > footer.Length? footer.Length : count - writed; + Array.Copy (footer, 0, buffer, writed + offset, bytesToWrite); + position += bytesToWrite; + writed += bytesToWrite; + return writed; + } + + public override long Seek(long amount, SeekOrigin origin){ + throw new NotImplementedException("FormDataStream is non-seekable stream"); + } + + public override void SetLength (long len){ + throw new NotImplementedException("FormDataStream is readonly stream"); + } + + public override void Write(byte[] source, int offset, int count){ + throw new NotImplementedException("FormDataStream is readonly stream"); + } + + public void AddPart(string fieldName, string mimeType, Stream contents, string fileName=null){ + if (dirty){ + throw new InvalidOperationException("You can't change form data, form already readed"); + } + parts.Add(new FormPart(fieldName, mimeType, boundary, contents, fileName)); + } + + public void AddPart(FormPart part){ + if (dirty){ + throw new InvalidOperationException("You can't change form data, form already readed"); + } + parts.Add(part); + } + } + +} + + diff --git a/src/Request.cs b/src/Request.cs index c9b358d..1e4d988 100644 --- a/src/Request.cs +++ b/src/Request.cs @@ -26,6 +26,7 @@ public enum RequestState { public class Request { + public static bool LogAllRequests = false; public static bool VerboseLogging = false; public static string unityVersion = Application.unityVersion; @@ -34,7 +35,7 @@ public class Request public CookieJar cookieJar = CookieJar.Instance; public string method = "GET"; public string protocol = "HTTP/1.1"; - public byte[] bytes; + public Stream byteStream; public Uri uri; public static byte[] EOL = { (byte)'\r', (byte)'\n' }; public Response response = null; @@ -46,6 +47,7 @@ public class Request public RequestState state = RequestState.Waiting; public long responseTime = 0; // in milliseconds public bool synchronous = false; + public int bufferSize = 4 * 1024; public Action< HTTP.Request > completedCallback = null; @@ -69,25 +71,36 @@ public Request (string method, string uri, byte[] bytes) { this.method = method; this.uri = new Uri (uri); - this.bytes = bytes; + this.byteStream = new MemoryStream(bytes); + } + + public Request(string method, string uri, StreamedWWWForm form){ + this.method = method; + this.uri = new Uri (uri); + this.byteStream = form.stream; + foreach ( DictionaryEntry entry in form.headers ) + { + this.AddHeader( (string)entry.Key, (string)entry.Value ); + } } public Request( string method, string uri, WWWForm form ) { this.method = method; this.uri = new Uri (uri); - this.bytes = form.data; + this.byteStream = new MemoryStream(form.data); foreach ( DictionaryEntry entry in form.headers ) { this.AddHeader( (string)entry.Key, (string)entry.Value ); } + } public Request( string method, string uri, Hashtable data ) { this.method = method; this.uri = new Uri( uri ); - this.bytes = Encoding.UTF8.GetBytes( JSON.JsonEncode( data ) ); + this.byteStream = new MemoryStream(Encoding.UTF8.GetBytes( JSON.JsonEncode( data ) )); this.AddHeader( "Content-Type", "application/json" ); } @@ -267,8 +280,8 @@ public virtual void Send( Action< HTTP.Request > callback = null) SetHeader( "cookie", cookieString ); } - if ( bytes != null && bytes.Length > 0 && GetHeader ("Content-Length") == "" ) { - SetHeader( "Content-Length", bytes.Length.ToString() ); + if ( byteStream != null && byteStream.Length > 0 && GetHeader ("Content-Length") == "" ) { + SetHeader( "Content-Length", byteStream.Length.ToString() ); } if ( GetHeader( "User-Agent" ) == "" ) { @@ -298,7 +311,7 @@ public virtual void Send( Action< HTTP.Request > callback = null) } public string Text { - set { bytes = System.Text.Encoding.UTF8.GetBytes (value); } + set { byteStream = new MemoryStream(System.Text.Encoding.UTF8.GetBytes (value)); } } public static bool ValidateServerCertificate (object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors) @@ -328,8 +341,12 @@ void WriteToStream( Stream outputStream ) stream.Write( EOL ); - if ( bytes != null && bytes.Length > 0 ) { - stream.Write( bytes ); + long numBytesToRead = byteStream.Length; + byte[] buffer = new byte[bufferSize]; + while (numBytesToRead > 0){ + int readed = byteStream.Read(buffer, 0, bufferSize); + stream.Write(buffer, 0, readed); + numBytesToRead -= readed; } } diff --git a/src/StreamedWWWForm.cs b/src/StreamedWWWForm.cs new file mode 100644 index 0000000..f8ed954 --- /dev/null +++ b/src/StreamedWWWForm.cs @@ -0,0 +1,62 @@ +using System; +using System.IO; +using System.Text; +using System.Collections; + +namespace HTTP +{ + public class StreamedWWWForm { + string boundary; + public FormDataStream stream; + + public Hashtable headers { + get { + return new Hashtable { + { "Content-Type", "multipart/form-data; boundary=\"" + boundary + "\""} + }; + } + } + + public StreamedWWWForm(){ + byte[] bytes = new byte[40]; + var random = new Random(); + for (int i=0; i<40; i++){ + bytes[i] = (byte)(48 + random.Next(62)); + if (bytes[i] > 57){ + bytes[i] += 7; + } + if (bytes[i] > 90){ + bytes[i] += 6; + } + } + boundary = Encoding.ASCII.GetString(bytes); + stream = new FormDataStream(boundary); + } + + public void AddField(string fieldName, string fieldValue){ + var contentStream = new MemoryStream(Encoding.UTF8.GetBytes(fieldValue)); + stream.AddPart(fieldName, "text/plain; charset=\"utf-8\"", contentStream); + + } + public void AddBinaryData(string fieldName, byte[] contents=null, string mimeType = null){ + var contentStream = new MemoryStream(contents); + if (mimeType == null){ + mimeType = "application/octet-stream"; + } + stream.AddPart(fieldName, mimeType, contentStream, fieldName + ".dat"); + } + public void AddBinaryData(string fieldName, Stream contents=null, string mimeType = null){ + if (mimeType == null){ + mimeType = "application/octet-stream"; + } + stream.AddPart(fieldName, mimeType, contents, fieldName + ".dat"); + } + public void AddFile(string fieldName, string path, string mimeType=null){ + if (mimeType == null){ + mimeType = "application/octet-stream"; + } + var contents = new FileInfo(path).Open(FileMode.Open); + stream.AddPart(fieldName, mimeType, contents, fieldName + ".dat"); + } + } +} From d5482828f3aa721fb9897943f6d80dd91c21fbab Mon Sep 17 00:00:00 2001 From: Yakov Borevich Date: Wed, 10 Jun 2015 18:48:44 +0300 Subject: [PATCH 03/20] Fix request with empty body --- src/Request.cs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/Request.cs b/src/Request.cs index 1e4d988..62acff6 100644 --- a/src/Request.cs +++ b/src/Request.cs @@ -208,11 +208,17 @@ private void GetResponse() { } } catch (Exception e) { +#if !UNITY_EDITOR Console.WriteLine ("Unhandled Exception, aborting request."); Console.WriteLine (e); +#else + Debug.LogError("Unhandled Exception, aborting request."); + Debug.LogException(e); +#endif exception = e; response = null; } + state = RequestState.Done; isDone = true; responseTime = curcall.ElapsedMilliseconds; @@ -341,6 +347,10 @@ void WriteToStream( Stream outputStream ) stream.Write( EOL ); + if (byteStream == null){ + return; + } + long numBytesToRead = byteStream.Length; byte[] buffer = new byte[bufferSize]; while (numBytesToRead > 0){ @@ -348,6 +358,7 @@ void WriteToStream( Stream outputStream ) stream.Write(buffer, 0, readed); numBytesToRead -= readed; } + byteStream.Close(); } private static string[] sizes = { "B", "KB", "MB", "GB" }; From e4c297598dddb80b146ec97c5427c86d5aca8311 Mon Sep 17 00:00:00 2001 From: Yakov Borevich Date: Mon, 15 Jun 2015 12:09:57 +0300 Subject: [PATCH 04/20] Close input bytestream even in request with errors --- src/Request.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/Request.cs b/src/Request.cs index 62acff6..b665a2d 100644 --- a/src/Request.cs +++ b/src/Request.cs @@ -223,6 +223,11 @@ private void GetResponse() { isDone = true; responseTime = curcall.ElapsedMilliseconds; + if ( byteStream != null ) + { + byteStream.Close(); + } + if ( completedCallback != null ) { if (synchronous) { @@ -358,7 +363,6 @@ void WriteToStream( Stream outputStream ) stream.Write(buffer, 0, readed); numBytesToRead -= readed; } - byteStream.Close(); } private static string[] sizes = { "B", "KB", "MB", "GB" }; From bfe3a1a4e50147ceb8aea28ffd72d1ecf7a9aeec Mon Sep 17 00:00:00 2001 From: Yakov Borevich Date: Tue, 16 Jun 2015 11:54:57 +0300 Subject: [PATCH 05/20] Move to compact version of Ionic.Zlib --- lib/Ionic.Zlib.CF.dll | Bin 0 -> 74240 bytes lib/Ionic.Zlib.dll | Bin 102400 -> 0 bytes 2 files changed, 0 insertions(+), 0 deletions(-) create mode 100755 lib/Ionic.Zlib.CF.dll delete mode 100755 lib/Ionic.Zlib.dll diff --git a/lib/Ionic.Zlib.CF.dll b/lib/Ionic.Zlib.CF.dll new file mode 100755 index 0000000000000000000000000000000000000000..949f8047f3df186ae7c11033e244bc1e85a6e2ca GIT binary patch literal 74240 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 E17drsp8x;= literal 0 HcmV?d00001 diff --git a/lib/Ionic.Zlib.dll b/lib/Ionic.Zlib.dll deleted file mode 100755 index 0afce7f255db09bfd630fff75801480102e5d770..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 102400 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Π6l8sQ73kU=S2I2*09B>hL`B%;rZFA+p&EA)tcFMoxDy?MQv-xYD%F5 zPi8Uy0_m+<3pt(GSC&Nw-hk0_OI|w*d0J>8A&2UABN?983+L9n6xa^3e(~r)iMbB< z@;OeR*)?(7wC6D&_4UKs%zGc2wlk7W-d43FBKDkTtbB_cf6dW#hnnN5p~bahN3Vr<5ci(7yiM?bbfn8zK7iMe)!)hkWrg#nX2u@fAZue<_-X{^Yc(%eX1zD-1< zki|9(#<|>}Gg;|%{yhD#OattU*%;LSSirJ(m6njb1u&$FwG#STgV5 zpu3y7&O*8JoT!<>HoihEJg*!yvnyp)=lHU$3Jr|=W7tb^Qdvg0W4x}{mrzr zw|U~2&aXHfRna>bc@LCuqgk)w^Ilxxh-GDSc0W!^V@jb%fKLP!-FC{~ue+!D>xmaX za^q{C`!)H$wzGTPX*Dli=kk_&@FRC_Z)kLXAnaED;QC;<-{&n0m8+27@>(u$D1blw z_RuWObb}X3XDOr`*EC;|(PQJ%188w~W6wtlh6kKomy~*h}qNLvu>30M#pO$+{ybQ}d zKuXFz-0TSYRl@x(0sn*5Dp+fIOVFoU@P8?~QsTzPb?}3~T<@P4{1E`@VYdtM2+Tvq z3n0-F%ZuM)E%ySg!ry9y{rGd^moZo{1-pyG9uxKlyFo^j3SEb+7zV)xOU;^z z!l7lsNT`06&<-sNggs2$ADjo?gsOt;(J$rpmWQg`hdt86I&^0_{#u2@qx)yE>IB?K zB>Z$1fR8}{!18)d341}VT>eMD{h=EF)G*W6QK1@i0bFYay&7&MP-v3kr@M&h;0r?J zE@m)=!Mn`!cL1h`PhlENsPMlMblbr}qcj{iAqyg>lF5UN5uz z&yY<9a~CSEA5a_@Fr6kQ!5<2M8s~@nEq}nnO3p#$@w-U{FhGH#bf7#SCZrqzPWHq6 zl;cNZ*{JYf=Z6_nMHY+^n-!}F)M1xEGB~<>^e|reCHE-a)`iHt7{H9L>8!8DsKuaG z^z`6eU;V?3mX93$*M}FWKRkE(dF;(0?VvGn972q-vAk(JVX9sp9`r5K~ZZK3q;MD z;)8JjJxf{@^!Y#S;=5gszl^;K2%sGOvP!=mlc?m$M%7aj-3iSs9ek)*=`_J%AHnWGK7pFU2REn3A$(gq9Wa2E7**_aQljixX<8h zDXYZTe`q#pILzP<26r;}a>zG@XOUb5;0Tn%y_w=*%qC#Nac zn98=>S$r@c+#2sm^D86LuH0p&@Hg)Y7ZeIFtg2cZo{vX$we$=9C|2aFu3TDKU5W3h zoTjL>g+FU>PA071>+cKm>+<+GA%50(jodFF+N9`mL~?y$+{+7_`=4RFToC4K#$o3& z7;cbMh6l6R;R_cm*tTt3C10N7EB6QtEy%aMLce3OOw)(s4<`G-atW|sNrc~+Rur+O zcco*)cm*hTxQZ(%scjj_i(DnYUDnRId76Ue($Tb{qdf}qRb!|3n$0r@NnZx{@Pls>ZOXo%u-_6PMy9I6HBi>%zn9YC+-(u$bO?+=u z^FiOm;kv4Dj+Cdl4mk>L0V196hVo5Qe)891m*eZB3S49va9*aHC}@4Y?n>}O*HejF z`7Rs(OJMVxzZUA;mu0CAqyK!bYe2Y9BI&VlVY&@yA#-{^N1N zZS63$S?jp14*wX_9RI(yxe?#FRJf7Dw_y8l(#f}C+H<8@UgLG375(W!33D?Py3BkY zOXEatpUCSvDN_#_^8E+C^~m>~!x)KUrF3FBVe}-J Date: Tue, 16 Jun 2015 16:49:48 +0300 Subject: [PATCH 06/20] FormDataStream cleanup --- src/FormDataStream.cs | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/FormDataStream.cs b/src/FormDataStream.cs index 71da5ed..5e11922 100644 --- a/src/FormDataStream.cs +++ b/src/FormDataStream.cs @@ -5,8 +5,6 @@ namespace HTTP { public class FormPart { - string fieldName; - string mimeType; byte[] header; Stream contents; int position = 0; @@ -51,6 +49,11 @@ public int Read(byte[] buffer, int offset, int size){ position += bytesToWrite; return writed; } + + public void Dispose(){ + header = null; + contents.Close(); + } } public class FormDataStream: Stream { @@ -151,6 +154,13 @@ public void AddPart(FormPart part){ } parts.Add(part); } + + public override void Close(){ + foreach (var part in parts){ + part.Dispose(); + } + base.Close(); + } } } From 45dd8cd068285d7a28e5d42790f45c33d83e7eed Mon Sep 17 00:00:00 2001 From: Andy Burke Date: Mon, 22 Jun 2015 15:06:58 -0700 Subject: [PATCH 07/20] Add license to README Closes #36 --- README.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/README.md b/README.md index 444376f..081b288 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,13 @@ Based on Simon Wittber's UnityWeb code (http://code.google.com/p/unityweb/). +# LICENSE + +UnityHTTP falls under the GPL due to its basis on Simon Wittber's UnityWeb code, +which is licensed under the GPL. + +You should be aware of this license and determine if it is acceptable for your project. + # About This is a TcpClient-based HTTP library for use in Unity. It should work in From 7e6349dcfc61619763e81112fe6bc1189d68c598 Mon Sep 17 00:00:00 2001 From: wangwang <3wangyongwang123@163.com> Date: Tue, 30 Jun 2015 11:27:54 +0800 Subject: [PATCH 08/20] Fixed Request.cs line:92 Cannot convert type 'System.Collections.Generic.KeyValuePair' to 'System.Collections.DictionaryEntry' --- src/Request.cs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/Request.cs b/src/Request.cs index b665a2d..6cf22f9 100644 --- a/src/Request.cs +++ b/src/Request.cs @@ -89,11 +89,10 @@ public Request( string method, string uri, WWWForm form ) this.method = method; this.uri = new Uri (uri); this.byteStream = new MemoryStream(form.data); - foreach ( DictionaryEntry entry in form.headers ) + foreach ( KeyValuePair pair in form.headers ) { - this.AddHeader( (string)entry.Key, (string)entry.Value ); + this.AddHeader( pair.Key, pair.Value ); } - } public Request( string method, string uri, Hashtable data ) From 120de6ef1e52b310ec5d0821471832e94443f3f3 Mon Sep 17 00:00:00 2001 From: codeMonkeyWang <3wangyongwang123@163.com> Date: Tue, 30 Jun 2015 18:33:48 +0800 Subject: [PATCH 09/20] Align the code --- src/Request.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Request.cs b/src/Request.cs index 6cf22f9..528c5fd 100644 --- a/src/Request.cs +++ b/src/Request.cs @@ -89,10 +89,10 @@ public Request( string method, string uri, WWWForm form ) this.method = method; this.uri = new Uri (uri); this.byteStream = new MemoryStream(form.data); - foreach ( KeyValuePair pair in form.headers ) - { - this.AddHeader( pair.Key, pair.Value ); - } + foreach ( KeyValuePair pair in form.headers ) + { + this.AddHeader(pair.Key,pair.Value); + } } public Request( string method, string uri, Hashtable data ) From c9471b5c4d2c6980e1f10367fd4e6d653b0b902d Mon Sep 17 00:00:00 2001 From: Yakov Borevich Date: Wed, 8 Jul 2015 02:55:45 +0300 Subject: [PATCH 10/20] Support both unity 4 and 5 WWWForm.headers type --- src/Request.cs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/Request.cs b/src/Request.cs index b665a2d..ac21887 100644 --- a/src/Request.cs +++ b/src/Request.cs @@ -89,10 +89,17 @@ public Request( string method, string uri, WWWForm form ) this.method = method; this.uri = new Uri (uri); this.byteStream = new MemoryStream(form.data); +#if UNITY_5 + foreach ( var entry in form.headers ) + { + this.AddHeader( entry.Key, entry.Value ); + } +#else foreach ( DictionaryEntry entry in form.headers ) { this.AddHeader( (string)entry.Key, (string)entry.Value ); } +#endif } From 7e1b8b73e2d95f8096afba15976d53dec94c61e5 Mon Sep 17 00:00:00 2001 From: Adrian Rudnik Date: Thu, 31 Dec 2015 15:35:26 +0100 Subject: [PATCH 11/20] Increased verbosity on SSL authentication exceptions --- src/Request.cs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/Request.cs b/src/Request.cs index 68069f8..7c3126f 100644 --- a/src/Request.cs +++ b/src/Request.cs @@ -184,7 +184,13 @@ private void GetResponse() { var ssl = ostream as SslStream; ssl.AuthenticateAsClient (uri.Host); } catch (Exception e) { - Debug.LogError ("Exception: " + e.Message); +#if !UNITY_EDITOR + Console.WriteLine ("SSL authentication failed."); + Console.WriteLine (e); +#else + Debug.LogError ("SSL authentication failed."); + Debug.LogException(e); +#endif return; } } From fd501eaf8afe7a21eebec90d31a0439e435d94e9 Mon Sep 17 00:00:00 2001 From: Alejandro Huerta <1011415huerta@gmail.com> Date: Tue, 14 Jun 2016 13:29:13 -0700 Subject: [PATCH 12/20] Change namespace to prevent name conflicts --- src/CookieJar.cs | 2 +- src/DiskCache.cs | 5 ++--- src/FormDataStream.cs | 2 +- src/Request.cs | 6 +++--- src/Response.cs | 2 +- src/ResponseCallbackDispatcher.cs | 4 ++-- src/StreamedWWWForm.cs | 2 +- 7 files changed, 11 insertions(+), 12 deletions(-) diff --git a/src/CookieJar.cs b/src/CookieJar.cs index 8d6cc7a..d226e5c 100644 --- a/src/CookieJar.cs +++ b/src/CookieJar.cs @@ -4,7 +4,7 @@ // Based on node-cookiejar (https://github.com/bmeck/node-cookiejar) -namespace HTTP +namespace UnityHTTP { public class CookieAccessInfo { diff --git a/src/DiskCache.cs b/src/DiskCache.cs index 45ac010..f5357e3 100644 --- a/src/DiskCache.cs +++ b/src/DiskCache.cs @@ -2,9 +2,8 @@ using System.Collections; using System.IO; using System; -using HTTP; -namespace HTTP +namespace UnityHTTP { public class DiskCacheOperation { @@ -91,7 +90,7 @@ public DiskCacheOperation Fetch (Request request) IEnumerator DownloadAndSave (Request request, string filename, DiskCacheOperation handle) { var useCachedVersion = File.Exists(filename); - Action< HTTP.Request > callback = request.completedCallback; + Action< UnityHTTP.Request > callback = request.completedCallback; request.Send(); // will clear the completedCallback while (!request.isDone) yield return new WaitForEndOfFrame (); diff --git a/src/FormDataStream.cs b/src/FormDataStream.cs index 5e11922..02b44ca 100644 --- a/src/FormDataStream.cs +++ b/src/FormDataStream.cs @@ -2,7 +2,7 @@ using System.IO; using System.Text; using System.Collections.Generic; -namespace HTTP { +namespace UnityHTTP { public class FormPart { byte[] header; diff --git a/src/Request.cs b/src/Request.cs index 7c3126f..2d86473 100644 --- a/src/Request.cs +++ b/src/Request.cs @@ -11,7 +11,7 @@ using System.Security.Authentication; using System.Security.Cryptography.X509Certificates; -namespace HTTP +namespace UnityHTTP { public class HTTPException : Exception { @@ -49,7 +49,7 @@ public class Request public bool synchronous = false; public int bufferSize = 4 * 1024; - public Action< HTTP.Request > completedCallback = null; + public Action< UnityHTTP.Request > completedCallback = null; Dictionary> headers = new Dictionary> (); static Dictionary etags = new Dictionary (); @@ -271,7 +271,7 @@ private void GetResponse() { } } - public virtual void Send( Action< HTTP.Request > callback = null) + public virtual void Send( Action< UnityHTTP.Request > callback = null) { if (!synchronous && callback != null && ResponseCallbackDispatcher.Singleton == null ) diff --git a/src/Response.cs b/src/Response.cs index 7a1a9d7..22d51f1 100644 --- a/src/Response.cs +++ b/src/Response.cs @@ -6,7 +6,7 @@ using System.Globalization; using Ionic.Zlib; -namespace HTTP +namespace UnityHTTP { public class Response { diff --git a/src/ResponseCallbackDispatcher.cs b/src/ResponseCallbackDispatcher.cs index 2f857aa..d49a31e 100644 --- a/src/ResponseCallbackDispatcher.cs +++ b/src/ResponseCallbackDispatcher.cs @@ -2,7 +2,7 @@ using System; using System.Collections; -namespace HTTP +namespace UnityHTTP { public class ResponseCallbackDispatcher : MonoBehaviour { @@ -43,7 +43,7 @@ public void Update() { while( requests.Count > 0 ) { - HTTP.Request request = (Request)requests.Dequeue(); + UnityHTTP.Request request = (Request)requests.Dequeue(); request.completedCallback( request ); } } diff --git a/src/StreamedWWWForm.cs b/src/StreamedWWWForm.cs index f8ed954..0510e48 100644 --- a/src/StreamedWWWForm.cs +++ b/src/StreamedWWWForm.cs @@ -3,7 +3,7 @@ using System.Text; using System.Collections; -namespace HTTP +namespace UnityHTTP { public class StreamedWWWForm { string boundary; From bcee48fa41d53d8ddd4684cc8bdb013a85857246 Mon Sep 17 00:00:00 2001 From: andzdroid Date: Wed, 29 Jun 2016 16:03:41 +0100 Subject: [PATCH 13/20] Don't read body in HEAD requests --- src/Response.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Response.cs b/src/Response.cs index 22d51f1..f57b342 100644 --- a/src/Response.cs +++ b/src/Response.cs @@ -210,7 +210,7 @@ public void ReadFromStream( Stream inputStream ) AddHeader( parts[0], parts[1] ); } - } else { + } else if (request.method != "head") { // Read Body int contentLength = 0; From 3c8db7b606a9d13acb9c86bc4893a001ae6332a5 Mon Sep 17 00:00:00 2001 From: andzdroid Date: Wed, 29 Jun 2016 16:15:51 +0100 Subject: [PATCH 14/20] Fix case-sensitive request method check --- src/Response.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Response.cs b/src/Response.cs index f57b342..ac48e70 100644 --- a/src/Response.cs +++ b/src/Response.cs @@ -210,7 +210,7 @@ public void ReadFromStream( Stream inputStream ) AddHeader( parts[0], parts[1] ); } - } else if (request.method != "head") { + } else if (request.method.ToUpper() != "HEAD") { // Read Body int contentLength = 0; From f623acf0f1e6565c581e7f3c0dd51920bc2520ce Mon Sep 17 00:00:00 2001 From: Dmitry Radkovskiy Date: Wed, 19 Jul 2017 20:04:11 +0300 Subject: [PATCH 15/20] Fix Unity 2017 compiler define --- src/Request.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Request.cs b/src/Request.cs index 2d86473..e61bdfa 100644 --- a/src/Request.cs +++ b/src/Request.cs @@ -89,7 +89,7 @@ public Request( string method, string uri, WWWForm form ) this.method = method; this.uri = new Uri (uri); this.byteStream = new MemoryStream(form.data); -#if UNITY_5 +#if UNITY_5 || UNITY_5_3_OR_NEWER foreach ( var entry in form.headers ) { this.AddHeader( entry.Key, entry.Value ); From bf07dfaa34b9f1ccdb548298e1d44a62db673e17 Mon Sep 17 00:00:00 2001 From: "d.radkovskiy" Date: Fri, 8 Sep 2017 17:03:33 +0300 Subject: [PATCH 16/20] Added ILogger, ConsoleLogger, UnityLogger --- src/Logger.cs | 52 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 src/Logger.cs diff --git a/src/Logger.cs b/src/Logger.cs new file mode 100644 index 0000000..cdf9f0e --- /dev/null +++ b/src/Logger.cs @@ -0,0 +1,52 @@ +using System; + +namespace UnityHTTP +{ + public interface ILogger + { + void Log(string msg); + void LogError(string msg); + void LogException(Exception e); + void LogWarning(string msg); + } +#if UNITY_EDITOR + public class UnityLogger : ILogger + { + public void Log(string msg) + { + UnityEngine.Debug.Log(msg); + } + public void LogError(string msg) + { + UnityEngine.Debug.LogError(msg); + } + public void LogException(Exception e) + { + UnityEngine.Debug.LogException(msg); + } + public void LogWarning(string msg) + { + UnityEngine.Debug.LogWarning(msg); + } + } +#endif + public class ConsoleLogger : ILogger + { + public void Log(string msg) + { + Console.WriteLine(msg); + } + public void LogError(string msg) + { + Console.WriteLine(msg); + } + public void LogException(Exception e) + { + Console.WriteLine(msg); + } + public void LogWarning(string msg) + { + Console.WriteLine(msg); + } + } +} \ No newline at end of file From 5663f4a0e5b8d17a22e74291bb8d776fc40ba25a Mon Sep 17 00:00:00 2001 From: "d.radkovskiy" Date: Fri, 8 Sep 2017 17:04:03 +0300 Subject: [PATCH 17/20] refactored Request to use UnityLogger/ConsoleLogger where appropriate --- src/Request.cs | 39 ++++++++++++++++++--------------------- 1 file changed, 18 insertions(+), 21 deletions(-) diff --git a/src/Request.cs b/src/Request.cs index e61bdfa..38970b1 100644 --- a/src/Request.cs +++ b/src/Request.cs @@ -30,7 +30,14 @@ public class Request public static bool LogAllRequests = false; public static bool VerboseLogging = false; public static string unityVersion = Application.unityVersion; - public static string operatingSystem = SystemInfo.operatingSystem; + public static string operatingSystem = SystemInfo.operatingSystem; + public static ILogger logger = +#if !UNITY_EDITOR + new ConsoleLogger() +#else + new UnityLogger() +#endif + ; public CookieJar cookieJar = CookieJar.Instance; public string method = "GET"; @@ -184,13 +191,8 @@ private void GetResponse() { var ssl = ostream as SslStream; ssl.AuthenticateAsClient (uri.Host); } catch (Exception e) { -#if !UNITY_EDITOR - Console.WriteLine ("SSL authentication failed."); - Console.WriteLine (e); -#else - Debug.LogError ("SSL authentication failed."); - Debug.LogException(e); -#endif + logger.LogError ("SSL authentication failed."); + logger.LogException(e); return; } } @@ -220,13 +222,8 @@ private void GetResponse() { } } catch (Exception e) { -#if !UNITY_EDITOR - Console.WriteLine ("Unhandled Exception, aborting request."); - Console.WriteLine (e); -#else - Debug.LogError("Unhandled Exception, aborting request."); - Debug.LogException(e); -#endif + logger.LogError("Unhandled Exception, aborting request."); + logger.LogException(e); exception = e; response = null; } @@ -253,19 +250,19 @@ private void GetResponse() { if ( LogAllRequests ) { #if !UNITY_EDITOR - System.Console.WriteLine("NET: " + InfoString( VerboseLogging )); + logger.Log("NET: " + InfoString( VerboseLogging )); #else if ( response != null && response.status >= 200 && response.status < 300 ) { - Debug.Log( InfoString( VerboseLogging ) ); + logger.Log( InfoString( VerboseLogging ) ); } else if ( response != null && response.status >= 400 ) { - Debug.LogError( InfoString( VerboseLogging ) ); + logger.LogError( InfoString( VerboseLogging ) ); } else { - Debug.LogWarning( InfoString( VerboseLogging ) ); + logger.LogWarning( InfoString( VerboseLogging ) ); } #endif } @@ -340,9 +337,9 @@ public string Text { public static bool ValidateServerCertificate (object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors) { #if !UNITY_EDITOR - System.Console.WriteLine( "NET: SSL Cert: " + sslPolicyErrors.ToString() ); + logger.LogWarning( "NET: SSL Cert: " + sslPolicyErrors.ToString() ); #else - Debug.LogWarning("SSL Cert Error: " + sslPolicyErrors.ToString ()); + logger.LogWarning("SSL Cert Error: " + sslPolicyErrors.ToString ()); #endif return true; } From 51b0b3da5d348ab783aaeffac2844981aa25dc60 Mon Sep 17 00:00:00 2001 From: "d.radkovskiy" Date: Fri, 8 Sep 2017 17:05:59 +0300 Subject: [PATCH 18/20] added loggers for every request --- src/Request.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Request.cs b/src/Request.cs index 38970b1..78a9478 100644 --- a/src/Request.cs +++ b/src/Request.cs @@ -55,6 +55,8 @@ public class Request public long responseTime = 0; // in milliseconds public bool synchronous = false; public int bufferSize = 4 * 1024; + + public ILogger logger = Request.logger; public Action< UnityHTTP.Request > completedCallback = null; From 2ba38524bdc5cd46134389f63d4e6361a8717a25 Mon Sep 17 00:00:00 2001 From: "d.radkovskiy" Date: Fri, 8 Sep 2017 17:19:25 +0300 Subject: [PATCH 19/20] compiler errors fixes --- src/Logger.cs | 4 ++-- src/Request.cs | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/Logger.cs b/src/Logger.cs index cdf9f0e..193096f 100644 --- a/src/Logger.cs +++ b/src/Logger.cs @@ -22,7 +22,7 @@ public void LogError(string msg) } public void LogException(Exception e) { - UnityEngine.Debug.LogException(msg); + UnityEngine.Debug.LogException(e); } public void LogWarning(string msg) { @@ -42,7 +42,7 @@ public void LogError(string msg) } public void LogException(Exception e) { - Console.WriteLine(msg); + Console.WriteLine(e); } public void LogWarning(string msg) { diff --git a/src/Request.cs b/src/Request.cs index 78a9478..429a52d 100644 --- a/src/Request.cs +++ b/src/Request.cs @@ -31,7 +31,7 @@ public class Request public static bool VerboseLogging = false; public static string unityVersion = Application.unityVersion; public static string operatingSystem = SystemInfo.operatingSystem; - public static ILogger logger = + public static ILogger Logger = #if !UNITY_EDITOR new ConsoleLogger() #else @@ -56,7 +56,7 @@ public class Request public bool synchronous = false; public int bufferSize = 4 * 1024; - public ILogger logger = Request.logger; + public ILogger logger = Request.Logger; public Action< UnityHTTP.Request > completedCallback = null; @@ -339,9 +339,9 @@ public string Text { public static bool ValidateServerCertificate (object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors) { #if !UNITY_EDITOR - logger.LogWarning( "NET: SSL Cert: " + sslPolicyErrors.ToString() ); + Logger.LogWarning( "NET: SSL Cert: " + sslPolicyErrors.ToString() ); #else - logger.LogWarning("SSL Cert Error: " + sslPolicyErrors.ToString ()); + Logger.LogWarning("SSL Cert Error: " + sslPolicyErrors.ToString ()); #endif return true; } From f41bad5587ab6fdb7703c1c60e4bd5490f638665 Mon Sep 17 00:00:00 2001 From: "d.radkovskiy" Date: Fri, 8 Sep 2017 17:21:30 +0300 Subject: [PATCH 20/20] added DiscardLogger --- src/Logger.cs | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/src/Logger.cs b/src/Logger.cs index 193096f..d466a6f 100644 --- a/src/Logger.cs +++ b/src/Logger.cs @@ -49,4 +49,23 @@ public void LogWarning(string msg) Console.WriteLine(msg); } } + public class DiscardLogger : ILogger + { + public void Log(string msg) + { + // discard logs + } + public void LogError(string msg) + { + // discard logs + } + public void LogException(Exception e) + { + // discard logs + } + public void LogWarning(string msg) + { + // discard logs + } + } } \ No newline at end of file