I am trying to make a call to below URL and it works just fine in Browser (Chrome) and also in Postman, but for some reason, it doesn't work in C#.
Working in browser:
http://AJWKBLWT47VR26QWPNFCPJLXC6217F6F#presta.craftingcrow.com/api/categories
Working in Postman:
http://AJWKBLWT47VR26QWPNFCPJLXC6217F6F#presta.craftingcrow.com/api/categories
Not working in C# (RestSharp):
var client = new RestClient("http://AJWKBLWT47VR26QWPNFCPJLXC6217F6F#presta.craftingcrow.com/api/categories");
var request = new RestRequest(Method.GET);
request.AddHeader("cache-control", "no-cache");
request.AddHeader("User-Agent", #"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36");
IRestResponse response = client.Execute(request);
Response:
401 Unauthorized
P.S. If I remove User-Agent it still doesn't work. Why am I doing wrong here?
Go into postman and, after you submit the request, check the Headers tab for anything that may have been added in the "temporary headers" section if you haven't specified anything in the Authorization tab.
In this example, I haven't called out an Authorization header but Postman is supplying one anyway:
Then add the missing relevant header(s) into your code. I like to click the "Code" button to the far right of the request. It gives you a dropdown so that you can choose pre-generated code in your desired language. This will most likely give you a reproducible example.
Thanks to Joshua & Vhoang!
It's working after I changed code to below:
var client = new RestClient("http://presta.craftingcrow.com/api/categories");
var request = new RestRequest(Method.GET);
request.AddHeader("cache-control", "no-cache");
request.AddHeader("Authorization", "Basic " + Convert.ToBase64String(Encoding.Default.GetBytes("AJWKBLWT47VR26QWPNFCPJLXC6217F6F:"));
IRestResponse response = client.Execute(request);
There was no need to add user-agent or include key in the hostname (URL)
RestClient constructor accepts URI that doesn't include userinfo
userinfo host port
┌──┴───┐ ┌──────┴──────┐ ┌┴┐
https://john.doe#www.example.com:123/forum/questions/?tag=networking&order=newest#top
└─┬─┘ └───────────┬──────────────┘└───────┬───────┘ └───────────┬─────────────┘ └┬┘
scheme authority path query fragment
See: https://en.wikipedia.org/wiki/Uniform_Resource_Identifier
In order to make it work with RestSharp, we'll need to do a little bit of extra work here:
// Old:
// var client = new RestClient("http://AJWKBLWT47VR26QWPNFCPJLXC6217F6F#presta.craftingcrow.com/api/categories");
// New:
var client = new RestClient("http://presta.craftingcrow.com/api/categories")
{
Authenticator = new HttpBasicAuthenticator("AJWKBLWT47VR26QWPNFCPJLXC6217F6F", "")
};
Related
so basically i started learning http request with restsharp and to be honest there is a total confusion.
So i managed to log into my reddit account, catch upvote post request and i tried to post the method and it actually worked on the active session.(yayy after a week...)
Here is my code:
var client = new RestClient("https://www.reddit.com/")
CookieContainer cookieContainer = new CookieContainer();
var options = new RestClientOptions()
{
MaxTimeout = -1
};
var request = new RestRequest("https://oauth.reddit.com/api/vote?redditWebClient=desktop2x&app=desktop2x-client-production&raw_json=1&gilding_detail=1", Method.Post);
request.AddHeader("accept", "*/*");
request.AddHeader("accept-language", "en-US,en;q=0.9");
request.AddHeader("authorization", "Bearer 1909307768910-Y9YshL45Wi1uTiaXGIDzIYS1CvawRw");
request.AddHeader("content-type", "application/x-www-form-urlencoded");
request.AddHeader("origin", "https://www.reddit.com");
request.AddHeader("referer", "https://www.reddit.com/");
request.AddHeader("sec-ch-ua", "\".Not/A)Brand\";v=\"99\", \"Google Chrome\";v=\"103\", \"Chromium\";v=\"103\"");
request.AddHeader("sec-ch-ua-mobile", "?0");
request.AddHeader("sec-ch-ua-platform", "\"Windows\"");
request.AddHeader("sec-fetch-dest", "empty");
request.AddHeader("sec-fetch-mode", "cors");
request.AddHeader("sec-fetch-site", "same-site");
request.AddHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36");
request.AddHeader("x-reddit-loid", "0000000000od4gjr66.2.1654778423000.Z0FBQUFBQmlzX05MUTZyNUxqOW4wcnNLNzhiNjFWeG5kR21saVptZXl6RllTcmVuMTJLV2hneEVBU3Z6SDB0VUJOQzJORzE3d0R2aWRHT1YxWFN2akdmbjg4T2Z2RVBUaWR4VjNHRk1paEFaUU9HblQydDBIbXFXZjY3WDAyaS10dGRRaDU0aWFoS2I");
request.AddHeader("x-reddit-session", "infdgnamhcklpjejeb.0.1656153357171.Z0FBQUFBQml0dVVORWozUVZwQ2RqTGdMc3MwbGJQczJvWW1UVUdmdjVHVjJqMElFV2ZwUlhOaGxmSlh0Wm02aDZsWmx2a0NtVXJKNHEyRG1Hc25tQ0FKMVdlbGlPcDN3aGVXdS1xaXJJRU9KMGVKRFQ1ZXJHTEFzSXpqSm1RUmFIa0dCNFBjU2tnYlo");
request.AddHeader("Cookie", "csv=2; edgebucket=EzrHckI9fWuza20bDr; loid=0000000000p5fofqq6.2.1656153609022.Z0FBQUFBQml0dVlKM2FDVUo5NUN2eEZBRDk4NDV5WWtDNk1mU01vRmktRnB1eWYwMzY4X3ZCdkx1eXZUNERzTVN1MkhDZXdnZFpHblMwU0k4LTc4M1VnNGRkQ3hOQUp3dTVxaFZYbndFQ19WN3NUaUFsX21MaE1SNTRaQWRsQU1sZFBUTDJQWlBoRnM; session_tracker=zoCNAuHADuPm2Hy4AF.0.1656153616293.Z0FBQUFBQml0dVlRRTZCc2NBNHRmV2xxUWhwVFllT0JaUGhDN3JDNTYxRk1DLURsTmJ4U1ZVOUNLRjN4RjZHNExpZUZjcVd6MzktMGVZMS12X193SDJ2OUd0R19kVjJ3dEtnWGFPOEVHSWd5dHBIWFVZcWNReEZPb0Q5UG9mRVlyWUFXOC1lMEYxZ20");
request.AddParameter("id", "t3_qbl6b2");
request.AddParameter("id", "t3_vk7gmb");
request.AddParameter("dir", "1");
request.AddParameter("api_type", "json");
RestResponse response = client.Execute(request);
Console.WriteLine(response.Content);
Ok the thing here is im not really interested into official reddit api or any official api as im only trying to learn and i have no precise goal. I have some questions that i need to be precised. I found some explanations on youtube, here or google but its not really clear and i seen that restsharp have updated recently.
1- So far what i understand, its that i can do this post request because the active session is using the same Bearer and cookies but i guess intercepting the post request each time to generate these data aint really practical so how you actually get the session id/loid/cookies/bearer and all dynamic data that you need to make succesful request before actually doing the request(logic lol)?
2- How to handle cookies?
3- Do you need to make a get request before a post?
4- How to handle objects and data from the response?
I want to learn so if you guys have some knowledge to share, it will be appreciated!
Ok so it was totally not about oauth at all.
-So basically, you need to make a GET request that will deliver an html code.
-In this html code you will find an csrf token. You will use regex to put it in a string.
-You will create a POST login request that return username, password and csrf token.
You're now logged!!!
About handling cookies, restsharp do it automatically as long as you keep the same RestClient object. I put them in a string array and use them in the request using String.Format
I know that similar questions have been already posted in the past but I read a lot on the subject and still couldn't find an answer to my problem.
I have a GET request that works fine on Postman:
I translated it with the Code tool in C# - RestSharp and tested it with my plugin but somehow I always get the same error:
My C# - RestSharp code (It's the one I get with the Postman translator):
var client = new RestClient("https://..........."); //my url
client.Timeout = -1;
var request = new RestRequest(Method.GET);
request.AddHeader("Cookie", ".........."); //my cookie
IRestResponse response = client.Execute(request);
I tried adding all the headers visible in the Headers section:
request.AddHeader("User-Agent", "PostmanRuntime/7.29.0");
request.AddHeader("Accept", "*/*");
request.AddHeader("Accept-Encoding", "gzip, deflate, br");
request.AddHeader("Connection", "keep-alive");
without result. The Authorization type is No Auth. Any idea?
Maybe it has something to do with the fact that the response body in Postman is a plain text? The other requests I send that have a JSON response works perfectly fine.
Thank you for your help!
Use request.AddCookie(cookiename, cookievalue);
I am posting the following JSON to my Flask server:
{"comment": "astute observation", "ua": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36", "cookie": "ua=f8256d37159e3faf28ae61a6406601c3; platform=pc; bs=bxa7ziiq07dufk31prvoo0mbfm44sayh; ss=994139249854417186; il=v1qyca8PU7X6jSwgiqceXsySwWB60HnCjSJ1HjNmsSxRUxNjQzNjA3OTEycUVTTFoxWUpSZDFTZ3kwclIzenBHa19FbnlmMTlIN0hZeHNDQ1FOLQ..; expiredEnterModalShown=1", "parent": "860245961"}
When sent from Postman, the request works flawlessly. However, when sent from my C# app, like so, the server returns a 400 Bad Request error code.
var data = $"{{\"comment\": \"{text}\", \"ua\": \"{userAgent}\", \"cookie\": \"{cookie}\", \"parent\": \"{parent}\"}}";
var url = "http://127.0.0.1:5000/";
var request = HttpWebRequest.CreateHttp(url);
request.Method = "POST";
request.ContentType = "application/json";
await using var sw = new StreamWriter(request.GetRequestStream());
await sw.WriteAsync(data);
var response = await request.GetResponseAsync();
To make sure that the JSON is properly formatted, I set a breakpoint and inspected the "data" variable. I copied/pasted that value into Postman, set the Content-Type to application/json, and the request succeeds from there, but fails from my C# application.
Server code:
from flask import Flask, request
app = Flask(__name__)
#app.route('/', methods=['GET', 'POST'])
def process():
print(request.json)
return 'Hello'
app.run(debug=True)
Edit: After posting this, I realized I wasn't sending a user agent from my C# app. I tried adding one and the server still responds with a 400 Bad Request error.
Edit 2: I tried simplifying the data variable for testing purposes. var data = "{\"msg\": \"david\"}"; and setting request.ContentLength = data.Length, still having the same problem. Really strange.
Very odd, but this solved the problem. Using the StreamWriter class was causing the issue. Doing this instead results in a 200 OK response finally.
using var stream = request.GetRequestStream();
await stream.WriteAsync(Encoding.UTF8.GetBytes(data));
I've created my app in Yelp, got my api key, and things work fine from Postman when executing a business search.
However, when testing from c#, I receive a 401 unauthorized error with a TOKEN_MISSING error that says ""{\"error\": {\"code\": \"TOKEN_MISSING\", \"description\": \"An access token must be supplied in order to use this endpoint.\"}}"".
I'm supplying my api key correctly though, and the Yelp documentation says that's all I need, so I'm not sure what the problem is. Here are 2 separate c# code samples that do NOT work (I've replaced my actual api key with for security concerns):
Example using WebRequest:
var webRequest = WebRequest.Create("http://api.yelp.com/v3/businesses/search?term=Clayton+Bicycle+Center&location=5411+Clayton+Rd%2c+Clayton%2c+CA+94517%2c+US");
webRequest.Method = "GET";
webRequest.Headers.Add("Cache-Control", "no-cache");
webRequest.Headers.Add("Authorization", "Bearer <my_api_key>");
HttpWebResponse webResponse = (HttpWebResponse)webRequest.GetResponse();
var stream = new StreamReader(webResponse.GetResponseStream(), Encoding.UTF8);
var content = stream.ReadToEnd();
Console.Write(content);
Example using RestSharp:
var client = new RestClient("http://api.yelp.com/v3/businesses/search?term=Clayton+Bicycle+Center&location=5411+Clayton+Rd%2c+Clayton%2c+CA+94517%2c+US");
var request = new RestRequest(Method.GET);
request.AddHeader("Cache-Control", "no-cache");
request.AddHeader("Authorization", "Bearer <my_api_key>");
var response = client.Execute(request);
Console.Write(response.Content);
I've examined the requests in Fiddler, and both are sending the same headers as the working Postman search, but both return 401 unauthorized error while Postman returns the search results. Any ideas?
Edit:
Well this is embarrassing, apparently my issue was I was attempting to access the Yelp API via http instead of https. Once I changed to https, everything worked as expected.
Changed endpoint to use https instead of http, works now.
I have a webclient that calls to a URL that works fine when i view it in a browser, which led me to believe i would need to add headers in to my call
I have done this, but am still getting the error.
I do have other calls to the same API that work fine, and have checked that all the parameters I am passing across are exactly the same as expected(case, spelling)
using (var wb = new WebClient())
{
wb.Proxy = proxy;
wb.Headers.Add("Accept-Language", " en-US");
wb.Headers.Add("Accept", " text/html, application/xhtml+xml, */*");
wb.Headers.Add("User-Agent", "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)");
byte[] response = wb.UploadValues("http://myserver/api/account/GetUser",
new NameValueCollection()
{
{ "email", register.Email },
});
userDetails = Encoding.UTF8.GetString(response);
}
Does anyone have an idea why I am still getting the protocol error on a call that works perfectly fine in a browser?
UploadValue uses a HTTP POST. Are you sure that it what you want? If you are viewing it in a browser it is likely a GET, unless you are filling out some sort of web form.
One might surmise that what you are trying to do is GET this response "http://myserver/api/account/GetUser?email=blah#blah.com"
in which case you would just formulate that url, with query parameters, and execute a GET using one of the DownloadString overloads.
using (var wb = new WebClient())
{
wb.Proxy = proxy;
userDetails = wb.DownloadString("http://myserver/api/account/GetUser?email=" + register.Email);
}
The Wikipedia article on REST has a nice table that outlines the semantics of each HTTP verb, which may help choosing the appropriate WebClient method to use for your use cases.