9

I am doing tests on a browser game. This post request is suppose to issue a command to build a building. As long as I am logged in, I can click on the Postman Send button and it works fine. This means non of the values expires. But if I log out and log back in then it wont work. I would have to generate another Postman post via the interceptor.

I want to simulate this post request using C#;

Here is how my post looks like in Postman;

Headers in Postman enter image description here

Body Parameters in Postman enter image description here

If you have postman installed, click here to import the request.

Here is my C# code. I am using the library called RestSharp;

var client = new RestClient(@"https://tr42.klanlar.org");
var request = new RestRequest("game.php", Method.POST);
request.AddQueryParameter("village", "31413"); // adds to POST or URL querystring based on Method
request.AddQueryParameter("screen", "main"); // adds to POST or URL querystring based on Method
request.AddQueryParameter("ajaxaction", "upgrade_building"); // adds to POST or URL querystring based on Method
request.AddQueryParameter("type", "main"); // adds to POST or URL querystring based on Method
request.AddQueryParameter("h", "98e34aa6"); // adds to POST or URL querystring based on Method
request.AddQueryParameter("", ""); // adds to POST or URL querystring based on Method
request.AddQueryParameter("client_time", "1505659914"); // adds to POST or URL querystring based on Method

request.AddParameter("destroy", "0"); // adds to POST or URL querystring based on Method
request.AddParameter("force", "1"); // adds to POST or URL querystring based on Method
request.AddParameter("id", "wood"); // adds to POST or URL querystring based on Method
request.AddParameter("source", "31413"); // adds to POST or URL querystring based on Method

//var p1 = new Parameter
//{
//    ContentType = "application/x-www-form-urlencoded",
//    Name = "destroy",
//    Value = "0"
//};
//request.AddParameter(p1);

//var p2 = new Parameter
//{
//    ContentType = "application/x-www-form-urlencoded",
//    Name = "force",
//    Value = "1"
//};
//request.AddParameter(p2);

//var p3 = new Parameter
//{
//    ContentType = "application/x-www-form-urlencoded",
//    Name = "id",
//    Value = "wood"
//};
//request.AddParameter(p3);

//var p4 = new Parameter
//{
//    ContentType = "application/x-www-form-urlencoded",
//    Name = "source",
//    Value = "31413"
//};
//request.AddParameter(p4);


request.AddHeader("Accept-Language", "en-US,en;q=0.8,tr;q=0.6,ht;q=0.4");
request.AddHeader("Accept-Encoding", "gzip, deflate, br");
request.AddHeader("Referer", "https://tr42.klanlar.org/game.php?village=31413&screen=main");
//request.AddHeader("Content-Type", "application/x-www-form-urlencoded");
request.AddHeader("Tribalwars-Ajax", "1");
request.AddHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.113 Safari/537.36");
request.AddHeader("X-Requested-With", "XMLHttpRequest");
request.AddHeader("Origin", "https://tr42.klanlar.org");
request.AddHeader("Accept", "application/json, text/javascript, */*; q=0.01");


//request.AddParameter("application/x-www-form-urlencoded", "destroy=&force=&id=&source=");
//request.AddParameter("application/x-www-form-urlencoded", "destroy=0&force=1&id=31413&source=wood", ParameterType.RequestBody);
//request.AddBody("application/x-www-form-urlencoded", "destroy=0&force=1&id=31413&source=wood");
IRestResponse response = client.Execute(request);
var data = response.Content;

When I click on the Send button inside Postman, the action works. However, even though I tried bunch of different methods, I could not get my C# function working.

Any kind of libraries dirty tricks and so on is allowed to be used. There are no rules as long as the request works in a programmatic way using the C# language.

I am expecting to see a response starting with;

{"success":"Komut verildi.","date_complete":86,"date_complete_formated":"0:01:26","building_orders":"

Edit: I can use alternative ways to simulate this Post request. It does not have to be in RestSharp.

Edit 2: I will update my parameters every time I log in so that you can reproduce the problem I am having.

Edit 3: Postman is able to generate C# code using RestSharp. This is the code that Postman generates. However it does not work.

var client = new RestClient("https://tr42.klanlar.org/game.php?village=31413&screen=main&ajaxaction=upgrade_building&type=main&h=8951b405&=&client_time=1505062595");
var request = new RestRequest(Method.POST);
request.AddHeader("postman-token", "dab31db4-b243-c317-e585-19da84c11e62");
request.AddHeader("cache-control", "no-cache");
request.AddHeader("accept-language", "en-US,en;q=0.8,tr;q=0.6,ht;q=0.4");
request.AddHeader("accept-encoding", "gzip, deflate, br");
request.AddHeader("referer", "https://tr42.klanlar.org/game.php?village=31413&screen=main");
request.AddHeader("content-type", "application/x-www-form-urlencoded");
request.AddHeader("tribalwars-ajax", "1");
request.AddHeader("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.113 Safari/537.36");
request.AddHeader("x-requested-with", "XMLHttpRequest");
request.AddHeader("origin", "https://tr42.klanlar.org");
request.AddHeader("accept", "application/json, text/javascript, */*; q=0.01");
IRestResponse response = client.Execute(request);

What I noticed is Postman is not placing the body parameters into the generated code.

0014
  • 893
  • 4
  • 13
  • 40
  • why not use `HttpClient` ? – John Sep 09 '17 at 10:12
  • @John I am open to use anything as long as it works. If you can provide an answer using HttpClient Ill give it a try. RestSharp is widely being used and was suppose to make things easier. – 0014 Sep 09 '17 at 13:38
  • 1
    What is the problem you are facing? there are many "dynamic" parameters in the query,and I can not test it, such like the user token inside cookie might expired, timestamp. you need to descript it more specific. And your don't need add every header to your POST request, there are a few headers are requird, accept,cookie. and I think you don't need add `content-type` header , restSharp should add for you – John Sep 10 '17 at 16:50
  • @John I am doing tests on a browser game. The post request is suppose to issue a command to build a building. As long as I am logged in, I can click on the Postman post and it works fine. This means non of the values expires. But if I log out and log back in then it wont work. I would have to generate another Postman post via the interceptor. I am going to update my parameters in postman and leave my test account logged in. Then you might be able to test it as well. Thanks for your feedback. – 0014 Sep 10 '17 at 17:05
  • @John I removed the cookie parameter. It worked without it inside postman. I also tried removing the content-type header from my code. Still it didint work. – 0014 Sep 10 '17 at 17:51
  • 1
    `cookie` and `accept` headers are required (`Tribalwars-Ajax` header may required for this case too), I'm not familiar with RestSharp, but I think your code is fine to perform a POST query, you should be able to see it from Postman or Fiddler. If they look the same, then the problem will be the parameter's value or the game state. – John Sep 11 '17 at 01:21
  • @John I do also believe my code is fine I went over the RestSharp and Postman`s documentation. Postman has the ability to generate C# code using the RestSharp library. The interesting part is, the generated code from Postman does not work while postman itself does. This means there is some kind of bug either on Postmans side, or Restsharp API. – 0014 Sep 11 '17 at 01:56
  • 3
    There is no bug, Postman shares cookies with your browser which it doesn't put in the generated code. Fix your code so it correctly authenticates, and appropriately stores the tokens/cookies/whatever and send them with successive requests. Also, if you really want to see what goes over the wire, use Fiddler or WireShark, because Postman (or Chrome) cheats. – CodeCaster Sep 17 '17 at 16:50
  • @CodeCaster so you mean there might be additional headers that is not listed inside Postman ? – 0014 Sep 17 '17 at 16:59
  • 1
    I've seen Postman eat and send headers at its own convenience, so yeah. – CodeCaster Sep 17 '17 at 16:59
  • @CodeCaster Thanks, I was able to solve it using your advice :) – 0014 Sep 17 '17 at 21:36
  • 1
    @CodeCaster Hunh? There is no bug? What do you call it when a program supposedly generates C# code for your supposed benefit, but that CODE DOESN'T WORK? If it's gonna generate C# code, then you should be able to take that C# code and put it in a .NET program and it should just work. Especially w/o having to do a bunch of addl stuff to GET it to work, so that you eventually end up with C# code that is totally unrecognizable from the generated C# code. It should A) WORK, or B) it should come with a disclaimer that it ISN'T gonna work, or C) Postman shouldn't even HAVE C# code generation at all. –  Mar 26 '19 at 22:30

1 Answers1

8

Thanks to CodeCaster with his advice to use Fiddler, I was able to make the request using HttpWebRequest. There is this amazing Fiddler tool that converts the requests into C# code.

So this was how I solved this problem;

  • Installed Fiddler
  • Captured the post request using fiddler
  • Installed this fiddler extension
  • Converted the fiddler request into C# code which looks like this;

    private void MakeRequests()
    {
        HttpWebResponse response;
    
        if (Request_tr42_klanlar_org(out response))
        {
            response.Close();
        }
    }
    
    private bool Request_tr42_klanlar_org(out HttpWebResponse response)
    {
        response = null;
    
        try
        {
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create("https://tr42.klanlar.org/game.php?village=31413&screen=main&ajaxaction=upgrade_building&type=main&h=561d76fe&&client_time=1505677450");
    
            request.KeepAlive = true;
            request.Accept = "application/json, text/javascript, */*; q=0.01";
            request.Headers.Add("Origin", @"https://tr42.klanlar.org");
            request.Headers.Add("X-Requested-With", @"XMLHttpRequest");
            request.UserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.113 Safari/537.36";
            request.Headers.Add("TribalWars-Ajax", @"1");
            request.ContentType = "application/x-www-form-urlencoded; charset=UTF-8";
            request.Referer = "https://tr42.klanlar.org/game.php?village=31413&screen=main";
            request.Headers.Set(HttpRequestHeader.AcceptEncoding, "gzip, deflate, br");
            request.Headers.Set(HttpRequestHeader.AcceptLanguage, "en-US,en;q=0.8,tr;q=0.6,ht;q=0.4");
            request.Headers.Set(HttpRequestHeader.Cookie, @"cid=1584941605; tr_auth=e341b46da1e7:13bc09020be8c378853c70baaa54ed9849c029468a62a143d10868e4238fa1af; cid=1584941605; tr_auth=e341b46da1e7:13bc09020be8c378853c70baaa54ed9849c029468a62a143d10868e4238fa1af; ref4852238=start; _ga=GA1.2.766176105.1499529449; _gid=GA1.2.1638517063.1505659564; __utmt=1; __utma=37229925.766176105.1499529449.1505094554.1505659568.8; __utmb=37229925.10.10.1505659568; __utmc=37229925; __utmz=37229925.1505659568.8.3.utmcsr=klanlar.org|utmccn=(referral)|utmcmd=referral|utmcct=/; sid=0%3A12986160bd90; _ga=GA1.2.766176105.1499529449; _gid=GA1.2.1638517063.1505659564; __utma=37229925.766176105.1499529449.1505094554.1505659568.8; __utmb=37229925.11.10.1505659568; __utmc=37229925; __utmz=37229925.1505659568.8.3.utmcsr=klanlar.org|utmccn=(referral)|utmcmd=referral|utmcct=/; websocket_available=true; global_village_id=31413; mobile=0");
    
            request.Method = "POST";
            request.ServicePoint.Expect100Continue = false;
    
            string body = @"id=stone&force=1&destroy=0&source=31413";
            byte[] postBytes = System.Text.Encoding.UTF8.GetBytes(body);
            request.ContentLength = postBytes.Length;
            Stream stream = request.GetRequestStream();
            stream.Write(postBytes, 0, postBytes.Length);
            stream.Close();
    
            response = (HttpWebResponse)request.GetResponse();
        }
        catch (WebException e)
        {
            if (e.Status == WebExceptionStatus.ProtocolError) response = (HttpWebResponse)e.Response;
            else return false;
        }
        catch (Exception)
        {
            if (response != null) response.Close();
            return false;
        }
        return true;
    }
    
0014
  • 893
  • 4
  • 13
  • 40
  • 2
    This code will break when that cookie expires, and worse, you've now shown your auth cookie to the world. – CodeCaster Sep 17 '17 at 21:52
  • @codecaster Yes its a browser game test accout my frirnd, no need to worry. If you read the question you will see I was aware of the situation from the beginning. I ended my session anyway, the code does not work its there to give an idea. – 0014 Sep 17 '17 at 22:09
  • @0014 You can change this code to have 2 requests. One request to login to retrieve the auth cookie and then use the auth cookie in subsequent requests. – Robbie Chiha Sep 24 '17 at 11:58