I'm trying to get list of torrents from uTorrent using Web API. Getting required token goes O.K.:
WebClient client = new WebClient() { Credentials = new NetworkCredential(UserName, pass) };
StreamReader Reader = new StreamReader(client.OpenRead("http://localhost:" + port + "/gui/token.html"));
string token = Reader.ReadToEnd();
token = token.Split('>')[2].Split('<')[0];
// token is now something like 3LemfrO_-A-SNBXlnQ2QcQWTYydx7qOqKb1W1S54JJW74Ly3EYGgu0xQSU4AAAAA
But when I try to use it to get list of torrents:
Reader = new StreamReader(client.OpenRead("http://localhost:" + port + "/gui/?list=1&token=" + token));
all I get is "Error 400 Bad request".
I've tried to get token manually. In browser page "http://localhost:30303/gui/?list=1&token=3LemfrO_-A-SNBXlnQ2QcQWTYydx7qOqKb1W1S54JJW74Ly3EYGgu0xQSU4AAAAA" opens as it should, but in C# with the same link without any variables I still get error 400.
The interesting part is that if switch off token authentication WebClient load page perfectly with and without
"&token=3LemfrO_-A-SNBXlnQ2QcQWTYydx7qOqKb1W1S54JJW74Ly3EYGgu0xQSU4AAAAA"
but token auth enabled by default, so my and any app should use it.
And yes, WebRequest/HttpWebRequest didn't help also.
P.S. sorry for my English, I was never able to make it work right
you have to save the cookie from the request
Classes.CookieAwareWebClient client = new Classes.CookieAwareWebClient() { Credentials = new NetworkCredential("shehab", "shehab") };
StreamReader Reader = new StreamReader(client.OpenRead("http://localhost:" + "8080" + "/gui/token.html"));
string token = HtmlRemoval.StripTagsRegexCompiled(Reader.ReadToEnd());
MessageBox.Show(token);
Reader = new StreamReader(client.OpenRead("http://localhost:" + "8080" + "/gui/?list=1&token=" + token));
MessageBox.Show(Reader.ReadToEnd());
and for the cookie aware class go to the following link(Using CookieContainer with WebClient class) as web client doesn't support cookies.
You should save cookies from request
WebRequest request = WebRequest.Create("http://localhost:" + port + "/gui/token.html");
CookieContainer cookies = new CookieContainer();
(request as HttpWebRequest).CookieContainer = cookies;
And then use it in every other request to uTorrent when using the same token:
request = WebRequest.Create("http://localhost:" + port + "/gui/?list=1&token=" + token);
(request as HttpWebRequest).CookieContainer = cookies;
I have a simple 3-step suggestion:
When you use your browser with the token, use Fiddler2 to analyze the HTTP traffic between the server and browser.
Open up your C# app and use Fiddler2 to analyze the HTTP traffic between the server and your app.
Compare the HTTP requests and responses for the browser with the requests and responses for the C# app. If you see a significant difference, there is a good chance that could be the problem.
Related
I'm trying to get the cookies from here: https://www.etoro.com/people/wesl3y/portfolio
If I call the Webpage with my Edge Browser, there are a lot of cookies, which are not flagged as "HTTP". For example the follwing cookie:
TMIS2 9a74f8b353780f2fbe59d8dc1d9cd901437be0b823f8ee60d0ab3637053d1bd9675fd2caa6404a74b4fc2a8779e1e7d486862875b11af976466a696de4a89c87e0e942f11ceed91c952d629646dc9cb71bdc2c2fd95a0a71698729f733717a775675add1a06bd9883e47c30e3bd162fabd836467a1cc16870a752373581adfd2ca .etoro.com / 2021-03-20T17:40:43.000Z 263 Medium
I want to get this cookie in my c# Program via HttpClient also, but until now I don't know how :( As far as I understood this cookies are not accessed via http, else Javascript is used to set this cookies on clientside.
Currently I used the following code for accessing the page and show the found cookies:
public void Test()
{
CookieContainer CookieJar = new CookieContainer();
var handler = new HttpClientHandler
{
CookieContainer = CookieJar,
UseCookies = true,
};
HttpClient client = new HttpClient(handler);
HttpResponseMessage response = client.GetAsync("https://www.etoro.com/people/wesl3y/portfolio").Result;
Uri uri = new Uri("https://www.etoro.com/people/wesl3y/portfolio");
IEnumerable<Cookie> responseCookies = CookieJar.GetCookies(uri).Cast<Cookie>();
foreach (Cookie cookie in responseCookies)
Console.WriteLine(cookie.Name + ": " + cookie.Value);
}
With my code I got all Cookies with Parameter HTTP=true, but miss all the other ones. Is there a way to get the missing cookies from that site with HttpClient? Or is there any other type of c# integrated Browser i have to use? The Main focus of my Tool is getting Json Information from the etoro.com API. But the API Access is very Rate limited when the right cookies are not in place :(
Thanks, Mag.
I have a CLR function getting data from cookie authorized website. The first request gets a login cookies and the second request gets xml data I need. The problem is in that I am always getting 401 unauthorized on a second request when run it from SQL Server as a function. The testing console app using the same DLL is working fine. Looks like the second request has no cookies but I checked in exception the amount of cookie container of the second request, it is not empty.
String encoded = Convert.ToBase64String(Encoding.UTF8.GetBytes(UserName + ":" + Password));
try
{
HttpWebRequest loginrequest = (HttpWebRequest)WebRequest.Create(string.Format("{0}", BaseOrdersAddress));
CookieContainer logincookies = new CookieContainer();
loginrequest.Headers.Add(HttpRequestHeader.Authorization, "Basic " + encoded);
loginrequest.AllowAutoRedirect = false;
loginrequest.CookieContainer = logincookies;
loginrequest.Method = WebRequestMethods.Http.Get;
HttpWebResponse loginresponse = (HttpWebResponse)loginrequest.GetResponse();
loginresponse.Close();
if (loginresponse.StatusCode == HttpStatusCode.Found)
{
location = loginresponse.Headers[HttpResponseHeader.Location];
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(location);
request.CookieContainer = logincookies;
request.Method = WebRequestMethods.Http.Get;
HttpWebResponse response1 = request.GetResponse() as HttpWebResponse;
var xresult = new XmlSerializer(typeof(Local_Response));
r = (Local_Response)xresult.Deserialize(response1.GetResponseStream());
}
Solved.
The problem was in using HttpWebRequest.CookieContainer, don't know why but it does not work while running as a CLR function, no cookies are sent. Have to do it manually adding HttpRequestHeader.Cookie to request headers collection.
Don't forget, your SQLCLR code executes in the context of SQL Server. I see you have a username, password in the code - what does that do and where is the username/password retrieved from. My bet is that there is something wrong with this based on what I said earlier.
I am completely new to REST API.
I would like to retrieve ListItems in xml format from an external site in C#.
I have got the username and password for the site (which uses Mixed authentication by the way).
HttpWebRequest endpointRequest = (HttpWebRequest)HttpWebRequest.Create("https://<site>/_api/web/lists");
endpointRequest.Method = "GET";
endpointRequest.Accept = "application/atom+xml";
//endpointRequest.Headers.Add("Authorization", "Bearer " + accessToken);
endpointRequest.Headers["Authorization"] = "Basic " + Convert.ToBase64String(Encoding.Default.GetBytes("<domain>\\<username>:<password>"));
HttpWebResponse endpointResponse = (HttpWebResponse)endpointRequest.GetResponse();
I am using this piece of code that I found on MSDN.
Would anybody please be kind enough to tell me how do I get an access token?
Why am I getting 403 Forbidden error?
I think you can better use the NetworkCredential class:
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri);
NetworkCredential credentials = new NetworkCredential("testuser", "testpass");
request.Credentials = credentials;
No need to send the Authorization header
When I have to use REST API I use Tiny.RestClient 1
In your case you have to write the call like that :
var client = new TinyRestClient(new HttpClient(), "https://<site>/_api/");
client.GetRequest("web/lists")
Hopes that help.
WithBasicAuthentication("username", "password").
ExecuteAsync();
When I am using HttpWebRequest I use the following code to set the Credentials
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(urlToCall);
request.Method = "GET";
request.Credentials = new NetworkCredential(username, pass);
How do I do the same when I am using BackgroundTransferService in Windows Phone 8.
For reference I am using the following.
http://msdn.microsoft.com/en-us/library/windowsphone/develop/hh202955%28v=vs.105%29.aspx
http://msdn.microsoft.com/en-us/library/windowsphone/develop/hh202959%28v=vs.105%29.aspx
*Edit:
The authentication method is Digest
This is what I get in the Authorization Header when I use my browser to download the file.
Digest username="adf", realm="bcd", nonce="XXXXXXXXX", uri="/ans/1268e52399.txt", algorithm=MD5, response="XXXXXXXXXXXXXXX", qop=auth, nc=00000001, cnonce="XXXXXXXXXXXX"
Unfortunately this isn't supported on the BackgroundTranserService. One possible solution might be to manually create a header for your request like below:
var credentials = new UTF8Encoding().GetBytes(username + ":" +password);
var transferRequest = new BackgroundTransferRequest(transferUri);
transferRequest.Headers["Authorization"] ="Basic " + convert.ToBase64String(credentials);
Unfortunately I'm unable to test this at the minute, give it a try and let me know how you get on.
I created RESTful webservice (WCF) where I check credentials on each request. One of my clients is Android app and everything seems to be great on server side. I get request and if it's got proper header - I process it, etc..
Now I created client app that uses this service. This is how I do GET:
// Create the web request
var request = WebRequest.Create(Context.ServiceURL + uri) as HttpWebRequest;
if (request != null)
{
request.ContentType = "application/json";
// Add authentication to request
request.Credentials = new NetworkCredential(Context.UserName, Context.Password);
// Get response
using (var response = request.GetResponse() as HttpWebResponse)
{
// Get the response stream
if (response != null)
{
var reader = new StreamReader(response.GetResponseStream());
// Console application output
var s = reader.ReadToEnd();
var serializer = new JavaScriptSerializer();
var returnValue = (T)serializer.Deserialize(s, typeof(T));
return returnValue;
}
}
}
So, this code get's my resource and deserializes it. As you see - I'm passing credentials in my call.
Then when debugging on server-side I noticed that I get 2 requests every time - one without authentication header and then server sends back response and second request comes bach with credentials. I think it's bad for my server - I'd rather don't make any roundtrips. How should I change client so it doesn't happen? See screenshot of Fiddler
EDIT:
This is JAVA code I use from Android - it doesn't do double-call:
MyHttpResponse response = new MyHttpResponse();
HttpClient client = mMyApplication.getHttpClient();
try
{
HttpGet request = new HttpGet(serviceURL + url);
request.setHeader(new BasicHeader(HTTP.CONTENT_TYPE, "application/json"));
request.addHeader("Authorization", "Basic " + Preferences.getAuthorizationTicket(mContext));
ResponseHandler<String> handler = new BasicResponseHandler();
response.Body = client.execute(request, handler);
response.Code = HttpURLConnection.HTTP_OK;
response.Message = "OK";
}
catch (HttpResponseException e)
{
response.Code = e.getStatusCode();
response.Message = e.getMessage();
LogData.InsertError(mContext, e);
}
The initial request doesn't ever specify the basic header for authentication. Additionally, since a realm is specified, you have to get that from the server. So you have to ask once: "hey, I need this stuff" and the server goes "who are you? the realm of answering is 'secure area'." (because realm means something here) Just because you added it here:
request.Credentials = new NetworkCredential(Context.UserName, Context.Password);
doesn't mean that it's going to be for sure attached everytime to the request.
Then you respond with the username/password (in this case you're doing BASIC so it's base64 encoded as name:password) and the server decodes it and says "ok, you're all clear, here's your data".
This is going to happen on a regular basis, and there's not a lot you can do about it. I would suggest that you also turn on HTTPS since the authentication is happening in plain text over the internet. (actually what you show seems to be over the intranet, but if you do go over the internet make it https).
Here's a link to Wikipedia that might help you further: http://en.wikipedia.org/wiki/Basic_access_authentication
Ok, I got it. I manually set HttpHeader instead of using request.Credentials
request.Headers.Add(HttpRequestHeader.Authorization, "Basic " + Convert.ToBase64String(Encoding.UTF8.GetBytes(Context.UserName + ":" + Context.Password)));
Now I see only single requests as expected..
As an option you can use PreAuthenticate property of HttpClientHandler. This would require a couple of lines more
var client = new HttpClient(new HttpClientHandler
{
Credentials = yourCredentials,
PreAuthenticate = true
});
With using this approach, only the first request is sent without credentials, but all the rest requests are OK.