Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 13 Next capture
2021 2022 2023
1 capture
13 Jun 22 - 13 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
2
Question by fractiv · Oct 20, 2014 at 12:08 AM · bugwwwcookiecookies

Workaround for SET-COOKIE bug in www.responseHeaders?

There is a bug in the way Unity handles the HTTP response headers. A typical HTTP response might look like this:

 HTTP/1.1 200 OK
 Content-Type: application/json
 Date: Sun, 19 Oct 2014 19:48:07 GMT
 Set-Cookie: session-data=a3izTzllfjmJvIAedFWH8_RF1VUoTVbszM-4KtITK8QBZwE
 Set-Cookie: AWSELB=8FCF616716267D5222A365F68CB5F524241ADC40F2A79E054E56BD41E6C10E5921CA9D8BE1291E904BD712CDA6EB211CD74D6780AE1E44EE07A58093B97B9C3AA5121EF17E09420E;PATH=/
 transfer-encoding: chunked
 Connection: keep-alive

However, since Unity parses this as a Dictionary, only one Set-Cookie header gets parsed. In other words, only one cookie will get through and the others will be ignored / removed.

I submitted a bug report about this. In the meantime, does anyone know of a workaround?

Comment
Add comment
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

2 Replies

· Add your reply
  • Sort: 
avatar image
5
Wiki

Answer by fractiv · Oct 20, 2014 at 04:32 AM

Answering my own question. Discovered a gross hack that lets me get at the data by using reflection to access the responseHeadersString property of the WWW class, which is a protected member. Below is an extension method class I wrote that provides methods for getting, parsing and sending cookies. Enjoy!

 //
 // UnityCookies.cs
 // by Sam McGrath
 //
 // Use as you please.
 //
 // Usage:
 //    Dictionary<string,string> cookies = www.ParseCookies();
 //
 // To send cookies in a WWW response:
 //    var www = new WWW( url, null, UnityCookies.GetCookieRequestHeader(cookies) );
 //    (if other headers are needed, merge them with the dictionary returned by GetCookieRequestHeader)
 //
 
 using UnityEngine;
 using System;
 using System.Collections.Generic;
 using System.Reflection;
 using System.Text;
 using System.Text.RegularExpressions;
 
 public static class UnityCookies {
 
     public static string GetRawCookieString( this WWW www ) {
         if ( !www.responseHeaders.ContainsKey("SET-COOKIE") ) {
             return null;
         }
 
         // HACK: workaround for Unity bug that doesn't allow multiple SET-COOKIE headers
         var rhsPropInfo = typeof(WWW).GetProperty( "responseHeadersString",BindingFlags.Public|BindingFlags.NonPublic|BindingFlags.Instance );
         if ( rhsPropInfo == null ) {
             Debug.LogError( "www.responseHeadersString not found in WWW class." );
             return null;
         }
         var headersString = rhsPropInfo.GetValue( www, null ) as string;
         if ( headersString == null ) {
             return null;
         }
 
         // concat cookie headers
         var allCookies = new StringBuilder();
         string[] lines = headersString.Split( new string[] { "\r\n", "\n" }, StringSplitOptions.RemoveEmptyEntries );
         foreach( var l in lines ) {
             var colIdx = l.IndexOf( ':' );
             if ( colIdx < 1 ) {
                 continue;
             }
             var headerType = l.Substring( 0,colIdx ).Trim();
             if ( headerType.ToUpperInvariant() != "SET-COOKIE" ) {
                 continue;
             }
             var headerVal = l.Substring( colIdx+1 ).Trim();
             if ( allCookies.Length > 0 ) {
                 allCookies.Append( "; " );
             }
             allCookies.Append( headerVal );
         }
 
         return allCookies.ToString();
     }
 
     public static Dictionary<string,string> ParseCookies( this WWW www ) {
         return ParseCookies( www.GetRawCookieString() );
     }
 
     public static Dictionary<string,string> ParseCookies( string str ) {
         // cookie parsing adapted from node.js cookie module, so it should be pretty robust.
         var dict = new Dictionary<string,string>();
         if ( str != null ) {
             var pairs = Regex.Split( str, "; *" );
             foreach( var pair in pairs ) {
                 var eqIdx = pair.IndexOf( '=' );
                 if ( eqIdx == -1 ) {
                     continue;
                 }
                 var key = pair.Substring( 0,eqIdx ).Trim();
                 if ( dict.ContainsKey(key) ) {
                     continue;
                 }
                 var val = pair.Substring( eqIdx+1 ).Trim();
                 if ( val[0] == '"' ) {
                     val = val.Substring( 1, val.Length-2 );
                 }
                 dict[ key ] = WWW.UnEscapeURL( val );
             }
         }
 
         return dict;
     }
 
     public static Dictionary<string,string> GetCookieRequestHeader( Dictionary<string,string> cookies ) {
         var str = new StringBuilder();
         foreach( var c in cookies ) {
             if ( str.Length > 0 )
                 str.Append( "; " );
             str.Append( c.Key ).Append( '=' ).Append( WWW.EscapeURL(c.Value) );
         }
         return new Dictionary<string,string>{ {"Cookie", str.ToString() } };
     }
 }

Comment
Add comment · Show 2 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image polytropoi · May 29, 2015 at 10:27 PM 0
Share

thanks for posting this fractiv, very helpful!

avatar image Fenrirson · Apr 29, 2016 at 02:55 AM 0
Share

Works like a charm! It's really sad this issue has not been addressed, but in the meantime, your solution works very well. I will use your code in my project, please let me know how to credit you, in the mean time I'll use your user name.

Cheers!

avatar image
0

Answer by Bunny83 · Oct 20, 2014 at 02:39 AM

Sure, there are a few, however not all are available in all situations. If you're in a webplayer you can use the browsers webinterface (via site-javascript code) to perform webrequests and read manually read the headers.

For the other platforms you can use any .NET / Mono web class (System.Net) that actually works with headerfields. However since those classes requires Sockets to work, it's not available for Android and iOS Free. Only for the pro version. Standalone builds should work fine.

See the license comparison page (seciont "code": .NET Socket Support)

You probably want to use either the HttpWebRequest if you do single requests or the WebClient class which actually handles cookies itself and is designed for multiple requests on the same domain.

Comment
Add comment · Show 3 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Bunny83 · Oct 20, 2014 at 02:41 AM 0
Share

ps: If someone comes across and still has some votes on the feedback site left, feel free to vote it up ;)

avatar image fractiv · Oct 20, 2014 at 03:01 AM 1
Share

I gave it 10 votes. In the meantime, I discovered a workaround that lets you get at all the cookies from the WWW object. It's a gross hack that uses reflection to get at the data of the protected responseHeadersString property. I wrote an extension library here. Enjoy! https://s3.amazonaws.com/fractiv.unitystuff/UnityCookies.cs

avatar image Bunny83 · Oct 20, 2014 at 03:14 AM 0
Share

Sure ;) That's also possible, however the internal implementation of the WWW class already has changed a few times in the past, so use it with caution.

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

4 People are following this question.

avatar image avatar image avatar image avatar image

Related Questions

WWW responseHeaders not giving me cookie in web-player, but does in editor 1 Answer

HttpWebRequest No longer working? 0 Answers

Sending cookie to XML-RPC protocol 0 Answers

Flashlight Cookie Not Displaying 1 Answer

WWW http request loads way to long on IOS 0 Answers


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges