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
0
Question by renezuidhof · May 14, 2015 at 08:04 PM · wwwwwwform

WWW, WWWForm and SoundCloud

I am trying to upload a file to SoundCloud with the WWW class. When i run the code below i get a response '400 Bad Request'. Can someone tell me why or give me some hints what to look for?

Is it even possible to use the WWW class for this?

EDIT: I looked a bit with Fiddler. I get the following message when running the code: 'Content-Length mismatch: Request Header indicated 208.662 bytes, but client sent 0 bytes.'

 public IEnumerator UploadFileWebClient(FileInfo file)
 {
         byte[] fileContents = File.ReadAllBytes(file.FullName);
 
     WWWForm form = new WWWForm();
 
     form.AddField("track[title]", "Some title", System.Text.Encoding.UTF8);
     form.AddField("track[sharing]", "private", System.Text.Encoding.UTF8);
     form.AddField("oauth_token", soundCloudToken, System.Text.Encoding.UTF8);
     form.AddField("format", "json", System.Text.Encoding.UTF8);
     form.AddBinaryData("track[asset_data]", fileContents, "0.wav", "application/octet-stream");
 
     foreach(var header in form.headers)
     {
             Debug.Log ("Header: " + header);
     }
 
     WWW download = new WWW("https://api.soundcloud.com/tracks", form);
     yield return download;
 
     if(!string.IsNullOrEmpty(download.error)) 
     {
         Debug.Log ( "Error downloading: " + download.error );
     } 
     else 
     {
         Debug.Log(download.text);
     }
 }

UPDATE: the SoundCloud token request (just for the completeness of the question):

 public IEnumerator GetTokenAndUploadFile(MonoBehaviour mono, FileInfo file)
     {
         Debug.Log ( "GetTokenAndUploadFile() started");
         ServicePointManager.ServerCertificateValidationCallback = (p1, p2, p3, p4) => true;
 
         var form = new WWWForm ();
         form.AddField ("client_id", _clientId);
         form.AddField ("client_secret", _clientSecret);
         form.AddField ("grant_type", "password");
         form.AddField ("username", _username);
         form.AddField ("password", _password);
 
         //Authentication
         string soundCloudTokenRes = "https://api.soundcloud.com/oauth2/token";
 
         Debug.Log ( "Try to get token");
         WWW download = new WWW(soundCloudTokenRes, form);
 
         yield return download;
         
         if(!string.IsNullOrEmpty(download.error)) 
         {
             Debug.Log ( "Error downloading: " + download.error );
         } 
         else 
         {
             var tokenInfo = download.text;
             tokenInfo = tokenInfo.Remove(0, tokenInfo.IndexOf("token\":\"") + 8);
             soundCloudToken = tokenInfo.Remove(tokenInfo.IndexOf("\""));
             Debug.Log(string.Format("Token set: {0}", soundCloudToken));
         }
     }
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

1 Reply

· Add your reply
  • Sort: 
avatar image
0

Answer by hanger · May 18, 2015 at 06:13 AM

A 400 response means the server got the request, but there was something wrong with the format. Usually the response tells you more, but Unity won't let you access the response on anything but a 200. Anyway, as far as I can see, there are two problems.

  1. You need to specify the token in an Authorization header.

  2. You're sending the wrong verb; POST when you want a PUT.

    Dictionary<string, string> headers = new Dictionary<string, string>();
    headers.Add("Authorization", "Bearer " + token);
    headers.Add("X-HTTP-Method-Override", "PUT");
    WWW download = new WWW(same_url, form, headers);

Bearer is an OAuth thing. Make sure you get a "token" and not a "code"; a "code" is just used to retrieve a token via a server. (I don't think there's any worry of injection attacks here.)

HTTP has several different verbs; ways to call a url. Soundcloud uses GET, POST, PUT and DELETE. The WWW class only supports GET and POST, and you can't set headers for GET. To get around stupid limitations like Unity's WWW class has, SoundCloud supports the fairly common nonstandard header X-HTTP-Method-Override. The value for that header should be the (capitalized) verb you want to use.

You need to use System.Collections.Hashtable instead of System.Collections.Generic.Dictionary<string, string> in older versions of Unity.

Comment
Add comment · Show 5 · 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 renezuidhof · May 18, 2015 at 12:43 PM 0
Share

Thanks for the response! I'll have a look at it tonight

avatar image renezuidhof · May 18, 2015 at 09:13 PM 0
Share

I can't get it to work, below the code as i have it now.

I have used the token before with other code (http://answers.unity3d.com/questions/966462/webrequest-receives-400-bad-request-on-android.html), it was working here. $$anonymous$$aybe the link will give you some more information about the things i have tried

In that code i use POST. I also tried POST in the code you provided but also didn't work.

 public IEnumerator UploadFileWebClient(FileInfo file)
     {
         ServicePoint$$anonymous$$anager.Expect100Continue = false;
         byte[] fileContents = File.ReadAllBytes(file.FullName);
 
         WWWForm form = new WWWForm();
 
         form.AddField("track[title]", "Some title");
         form.AddField("track[sharing]", "private");
         //form.AddField("oauth_token", soundCloudToken, System.Text.Encoding.UTF8);
         form.AddField("format", "json");
         form.AddBinaryData("track[asset_data]", fileContents, "3.wav", "application/octet-stream");
 
         Dictionary<string, string> headers = new Dictionary<string, string>();
         headers.Add("Authorization", "Bearer " + soundCloudToken);
         headers.Add("X-HTTP-$$anonymous$$ethod-Override", "PUT");
 
         //I don't know if this is needed. Doesn't work with or without it.
         foreach(var header in form.headers)
         {
             headers.Add(header.$$anonymous$$ey, header.Value);
         }
 
         WWW download = new WWW("https://api.soundcloud.com/tracks", form.data, headers);
         yield return download;
 
         if(!string.IsNullOrEmpty(download.error)) 
         {
             Debug.Log ( "Error downloading: " + download.error );
         } 
         else 
         {
             Debug.Log(download.text);
         }
     }
avatar image renezuidhof · May 18, 2015 at 09:16 PM 0
Share

Below the code of the token:

ServicePoint$$anonymous$$anager.ServerCertificateValidationCallback = (p1, p2, p3, p4) => true;

     //Authentication data
     string postData = "client_id=" + _clientId
         + "&client_secret=" + _clientSecret
         + "&grant_type=password&username=" + _username
         + "&password=" + _password;
     
     //Authentication
     string soundCloudTokenRes = "https://api.soundcloud.com/oauth2/token";
     string tokenInfo = _webclient.UploadString(soundCloudTokenRes, postData);

     //Parse the token
     tokenInfo = tokenInfo.Remove(0, tokenInfo.IndexOf("token\":\"") + 8);
     soundCloudToken = tokenInfo.Remove(tokenInfo.IndexOf("\""));
avatar image renezuidhof · May 18, 2015 at 09:35 PM 0
Share

Do you think Wireshark/Fiddler could give me some more useful information? I tried looking around but i'm not that experienced with the requests/responses

avatar image renezuidhof · May 18, 2015 at 09:45 PM 0
Share

For my original code (as posted in my question): If i remove the 'form.AddBinaryData(...);' it gives me other errors. For example: If i remove the token 'form.AddField("oauth_token", soundCloudToken);' it gives me an unauthorized exception. With the 'oauth_token' i get some other exception (so it seems to accept the token). Whenever i add the 'form.AddBinaryData(...);' line i get '400 Bad Request' (with or without the 'oauth_token').

If you want me to rephrase this let me know ;)

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

20 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

How do I make a simple POST request to Amazon S3? 2 Answers

WWW/WWWForm, does Unity validate SSL certificates? 1 Answer

How to Upload multiple files to a server using UnityWebRequest.Post(); 3 Answers

PUT with WWWform 3 Answers

How to use POST service using www class? 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