POST request na TestFlight Api končí chybou 400   otázka

C#

Zdravím,

snažím se udělat POST request s uploadem souboru na TestFlight Api, které je celkem jednoduché, viz zde:

https://testflightapp.com/api/doc/ Bohužel i přes veškerou snahu dostávám error 400 Bad Request.

HttpWebRequest request = WebRequest
    .Create('http://testflightapp.com/api/builds.json') as HttpWebRequest;
request.KeepAlive = false;
request.Headers.Add("api_token", "####");
request.Headers.Add("team_token", "####");
request.Headers.Add("notes", "notes");
request.Headers.Add("file", "@appName.ipa");
request.ContentType = "application/json";
request.AllowWriteStreamBuffering = true;
request.Method = WebRequestMethods.Http.Post;
byte[] messageArray = File.ReadAllBytes(filePath);
request.ContentLength = messageArray.Length;
Stream requestStream = request.GetRequestStream();
requestStream.Write(messageArray, 0, messageArray.Length);
requestStream.Close();

WebResponse response = request.GetResponse();
StreamReader responseReader = new StreamReader(response.GetResponseStream());
string result = responseReader.ReadToEnd();
responseReader.Close();
response.Close();
return result;

Nemám třeba špatně Content Type? Posílám data správně? Mám tokeny posílat v hlavičkách?

Requesty mi nikdy k srdci moc nepřirostly, takže budu rád za jakoukoliv pomoc.

Děkuji, s pozdravem Pooik

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Navrhuji použít WebClient ze jmenného prostoru System.Net.

http://msdn.microsoft.com/en-us/library/...

    Using client As New WebClient()
      client.Headers.Add("api_token", "…")
      client.UploadFile("http://testflightapp.com/api/builds.json", "myFile.file")
    End Using

Tato metoda vrátí byty těla odpovědi, takže z nich pak můžete naparsovat JSON. Metoda UploadFile blokuje vlákno, na kterém je volaná, pro produkční sestavení je vhodné použít UploadFileAsync. Také doporučuji nastavit hlavičku User-Agent, často jsem narazil na problémy při absenci této hlavičky i u API requestů.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Děkuji za pohotovou odpověď.

Upravil jsem tedy kód dle Vašeho návrhu, přidal jsem tam tokeny:

client.Headers.Add("api_token", "###");
client.Headers.Add("team_token", "###");
client.Headers.Add("notes", "Test");
client.Headers.Add("file", "MyApp.ipa");
client.Headers.Add("UserAgent", "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/535.2 (KHTML, like Gecko) Chrome/15.0.874.121 Safari/535.2");
byte[] bytes = client.UploadFile("http://testflightapp.com/api/builds.json", filePath);
					return System.Text.Encoding.Default.GetString(bytes);

Nicméně dostávám 401 Unauthorized access. Je to správně takto to poslat v hlavičce?

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Čtyřistajednička je speciálně určená pro oznámení, že request je v pořádku a přijatý ke zpracování, ale došlo k chybě při ověřování identity. Takže TestFlight API pravděpodobně už nemá problém se strukturou Vašeho requestu vytvořeného WebClientem, ale možná máte špatně nakopírované nebo expirované klíče pro API.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

To jsem si myslel taky. Ale teď jsem tokeny znovu vykopíroval (a byly správně). Hm...

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Zkuste ještě User-Agent hlavičku přidat takto:

client.Headers.Add(HttpRequestHeader.UserAgent, "…");

Standardní HTTP hlavičky by se měly přidávat pomocí té enumerace HttpRequest/ResponseHeaders. Navíc User-Agent hlavička by měla být s pomlčkou, ale jsem si celkem jistý, že v tom problém není, protože servery to určitě pochopí i tak.

Pokud jsou ty tokeny správně, nezbyde Vám, než se obrátit na support TestFlightu, protože pouze oni Vám mohou říct, kdy vracejí 401 a proč a budou v jejich lozích vidět Váš pokus o připojení, takže vyluští, proč Vás jejich sever odmítl.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Děkuji moc za pomoc, asi jim napíšu.

Každopádně díky za ochotu.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Tak jsem to nakonec rozlouskl. WebClient.UploadFile() neumožňuje spolu se soubory poslat i pole s hodnotami. Musel jsem nakonec odchytit úspěšný $curl post ve fiddlerovi a pak ho vytvořit 1:1 v C#. Tady je výsledek, sice dost neuhlazený, ale to už si každý zvládne případně upravit sám:

string boundary = DateTime.Now.Ticks.ToString("x", System.Globalization.NumberFormatInfo.InvariantInfo);
var request = WebRequest.Create(url);
request.Method = "POST";
request.ContentType = "multipart/form-data; boundary=----------------------------" + boundary;
var requestStream = request.GetRequestStream();
var buffer = Encoding.ASCII.GetBytes("------------------------------" + boundary);
requestStream.Write(buffer, 0, buffer.Length);
buffer = Encoding.ASCII.GetBytes(string.Format("{0}Content-Disposition: form-data; name=\"file\"; filename=\"_temp.ipa\"{0}", Environment.NewLine));
requestStream.Write(buffer, 0, buffer.Length);
buffer = Encoding.ASCII.GetBytes(string.Format("Content-Type: application/octet-stream{0}{0}", Environment.NewLine));
requestStream.Write(buffer, 0, buffer.Length);
buffer = File.ReadAllBytes(filePath);
requestStream.Write(buffer, 0, buffer.Length);
buffer = Encoding.ASCII.GetBytes("------------------------------" + boundary);
requestStream.Write(buffer, 0, buffer.Length);
buffer = Encoding.ASCII.GetBytes(string.Format("{0}Content-Disposition: form-data; name=\"api_token\"{0}{0}", Environment.NewLine));
requestStream.Write(buffer, 0, buffer.Length);
buffer = Encoding.ASCII.GetBytes(string.Format("#####{0}", Environment.NewLine));
requestStream.Write(buffer, 0, buffer.Length);
buffer = Encoding.ASCII.GetBytes("------------------------------" + boundary);
requestStream.Write(buffer, 0, buffer.Length);
buffer = Encoding.ASCII.GetBytes(string.Format("{0}Content-Disposition: form-data; name=\"team_token\"{0}{0}", Environment.NewLine));
requestStream.Write(buffer, 0, buffer.Length);
buffer = Encoding.ASCII.GetBytes(string.Format("#####{0}", Environment.NewLine));
requestStream.Write(buffer, 0, buffer.Length);
buffer = Encoding.ASCII.GetBytes("------------------------------" + boundary);
requestStream.Write(buffer, 0, buffer.Length);
buffer = Encoding.ASCII.GetBytes(string.Format("{0}Content-Disposition: form-data; name=\"notes\"{0}{0}", Environment.NewLine));
requestStream.Write(buffer, 0, buffer.Length);
buffer = Encoding.ASCII.GetBytes(string.Format("test{0}", Environment.NewLine));
requestStream.Write(buffer, 0, buffer.Length);
buffer = Encoding.ASCII.GetBytes("------------------------------" + boundary + "--");
requestStream.Write(buffer, 0, buffer.Length);
requestStream.Close();
WebResponse response = request.GetResponse();
StreamReader responseReader = new StreamReader(response.GetResponseStream());
string result = responseReader.ReadToEnd();
responseReader.Close();
response.Close();
return result;
nahlásit spamnahlásit spam 1 / 1 odpovědětodpovědět
                       
Nadpis:
Antispam: Komu se občas házejí perly?
Příspěvek bude publikován pod identitou   anonym.
  • Administrátoři si vyhrazují právo komentáře upravovat či mazat bez udání důvodu.
    Mazány budou zejména komentáře obsahující vulgarity nebo porušující pravidla publikování.
  • Pokud nejste zaregistrováni, Vaše IP adresa bude zveřejněna. Pokud s tímto nesouhlasíte, příspěvek neodesílejte.

přihlásit pomocí externího účtu

přihlásit pomocí jména a hesla

Uživatel:
Heslo:

zapomenuté heslo

 

založit nový uživatelský účet

zaregistrujte se

 
zavřít

Nahlásit spam

Opravdu chcete tento příspěvek nahlásit pro porušování pravidel fóra?

Nahlásit Zrušit

Chyba

zavřít

feedback