I just started to play around with RedditSharp (https://github.com/ddevault/RedditSharp) and I know I got a bit late to the party and I should be using OAuth instead, but I found it curious that this thing is still working by simply interacting with old.reddit.com.
My question is: is there any way I could connect to reddit using this library and a proxy?
I found this section (How to use a proxy with RedditSharp?), tried it but with no luck and couldn't find anything else besides that.
Thank you so much for the help.
I've tried the only solution found here: How to use a proxy with RedditSharp? but it seems is ignoring that I am using a proxy.
RedditSharp is a bit old ( 3 years old and un-maintained ). It seems RedditSharp is using WebRequest to make HTTP requests. In this case, you can use DefaultWebProxy property of WebRequest class.
WebRequest.DefaultWebProxy
The DefaultWebProxy property gets or sets the global proxy. The
DefaultWebProxy property determines the default proxy that all
WebRequest instances use if the request supports proxies and no proxy
is set explicitly using the Proxy property. Proxies are currently
supported by FtpWebRequest and HttpWebRequest.
The DefaultWebProxy property reads proxy settings from the app.config
file. If there is no config file, the current user's Internet Explorer
(IE) proxy settings are used.
If the DefaultWebProxy property is set to null, all subsequent
instances of the WebRequest class created by the Create or
CreateDefault methods do not have a proxy.
Example:
var proxyObject = new WebProxy("http://proxyserver:80/",true);
WebRequest.DefaultWebProxy = proxyObject;
// init RedditSharp stuff here
You can read more about WebProxy here.
Related
I have created REST resource using Web API running as a self-hosted process. For performance reasons I would like to be able to call it using persistent HTTP connections. I using OWIN self-hosting.
I really like the asnyc methods for GET, POST, PUT, DELETE in System.Net.Http.HttpClient. They are easy to call and deal with--they return a System.Threading.Tasks.Task which is convenient for what I'm trying to do. I prefer using HttpClient to System.Net.HttpWebRequest.
I'm probably missing something, but it isn't readily apparent to me how to create persistent connections with HttpClient. I'm digging through the System.Net.Http.HttpClientHandler and System.Net.Http.WebRequestHandler classes, but so far I haven't found an option for persistent connections. Google finds all sorts of examples of creating persistent connections using HttpWebRequest. It has a KeepAlive property that can be set to true. Is there a way to set this with HttpClient?
MSDN documentation for HttpClient:
By default, HttpWebRequest will be used to send requests to the server. This behavior can be modified by specifying a different channel in one of the constructor overloads taking a HttpMessageHandler instance as parameter. If features like authentication or caching are required, WebRequestHandler can be used to configure settings and the instance can be passed to the constructor. The returned handler can be passed to one of the constructor overloads taking a HttpMessageHandler parameter.
Is there a way to set the KeepAlive feature on the underlying HttpWebRequest?
The MSDN documentation also says:
The HttpClient class instance acts as a session to send HTTP requests. An HttpClient instance is a collection of settings applied to all requests executed by that instance. In addition, every HttpClient instance uses its own connection pool, isolating its requests from requests executed by other HttpClient instances.
Am I to understand from this that the connection pool will optimize for me using persistent connections when a performance benefit can be gained? What if I want there to only ever be a single connection from my client?
You will need to set the MaxIdle time on the ServicePoint for the client. The easiest way is to set the timeout for all service points:
ServicePointManager.MaxServicePointIdleTime = Timeout.Infinite;
You can also set it on the connection to the specific endpoint
var sp = ServicePointManager.FindServicePoint(targetUri);
sp.MasIdleTime = Timeout.Infinite;
I'm not sure what exactly you are trying to solve but have you looked at SignalR ? They have pretty fancy websocket api's that might do the job you are looking for.
If you are not using .NET 4.5 then they do have alternate mechanisms. One I'v seen being used is something like a server/event-stream.
This is how I have currently managed to consume a particular Microsoft web service. Notice that it is located on an HTTPS server and that it requires a username, a password, and a .cer file to be installed in the operating system's "root certificate authorities".
WSHttpBinding binding = new WSHttpBinding();
binding.Security.Mode = SecurityMode.TransportWithMessageCredential;
binding.Security.Message.ClientCredentialType = MessageCredentialType.UserName;
binding.Security.Message.NegotiateServiceCredential = true;
binding.Security.Message.AlgorithmSuite
= System.ServiceModel.Security.SecurityAlgorithmSuite.Default;
binding.Security.Message.EstablishSecurityContext = true;
EndpointAddress endpoint = new EndpointAddress("https://address.of.service");
//"GreatClient" was created for me automatically by running
//"svcutil.exe https://address.of.service?wsdl"
GreatClient client = new GreatClient(binding, endpoint);
//Username and password for the authentication. Notice that I have also installed
//the required .cer certificate into the system's "root certificate authorities".
client.ClientCredentials.UserName.UserName = "username";
client.ClientCredentials.UserName.Password = "password";
//Now I can start using the client as I wish.
My question is this: How can I obtain all the information necessary so that I can consume the web service with a direct POST to https://address.of.service, and how do I actually perform the POST with C#? I only want to use POST, where I can supply raw XML data using POST directly to https://address.of.service and get back the result as raw XML data. The question is, what is that raw XML data and how exactly should I send it using POST?
(The purpose of this question: The reason I ask is that I wish to consume this service using something other than C# and .NET (such as Ruby, or Cocoa on Mac OS X). I have no way of knowing how on earth to do that, since I don't have any easy-to-use "svcutil.exe" on other platforms to generate the required code for me. This is why I figured that just being able to consume the service using regular POST would allow me to more easily to consume the service on other platforms.)
What you are attempting to do sounds painful to do now and painful to maintain going forwards if anything changes in the server. It's really re-inventing the wheel.
If you haven't considered it already, I would:
(a) Research whether you can use the metadata you have for the service and use a proxy generator native to your target plaform. There aren't many platforms that don't have at least some tooling that might get you part of the way if not all of it. Perhaps repost a question targetting Ruby folk asking what frameworks exist to consume an HTTPS service given it's WSDL?
(b) Failing that, if your scenario allows it I would consider using a proxy written in C# that acts as a facade for the service which translates it into something easier to consume (for example, you might use something like ASP.NET MVC WebAPI which is flexible and can easily serve up standards compliant responses over which you can maintain total control).
I suspect one of these may prove easier and more valuable than the road you are on at the moment.
I had to go through something similar when porting .NET WCF code to other platforms. The easiest approach I found was to enable message logging on the WCF client. This can be configured to save both envelope and body and once everything is working on the .NET side of the house, you can use the message log to have "known-good" XML request/response to port to other platforms.
I found this approach to be more elegant since I didn't have to add an additional behavior to log messages, and it can be easily enabled/disabled/tweaked in the config. The Service Trace Viewer Tool that ships with Visual Studio is also handy for reviewing the log files.
I think when you say that the service should be consumed from other platforms, which do not have proxy class generation logic, you can go with REST services. This will allow you to create input as simple string concatenation instead of complex XML. Though its applicability depends on the situation.
Check this discussion : http://social.msdn.microsoft.com/Forums/en-US/wcf/thread/6907d765-7d4c-48e8-9e29-3ac5b4b9c405/
As far as the certificate is concerned, refer http://msdn.microsoft.com/en-us/library/ms733791.aspx on how to configure it.
I know this is not a very precise answer, but you will be the best person to evaluate above procedure, hence posted. Hope it helps.
What I'll do:
1- Create a small c# app that can post on this webservice (using svcutil). And modify it to show the XML send/received. To view the xml there are several ways: logging, wireshark etc. To add it directly to the small app there is another question here that give a good answer.
2- Once you know what you have to send, you can do it in c# like this:
// implement GetXmlString() to return the XML to post
string xml = GetXmlString();
// create the url
string url = new UriBuilder("http","address.of.service",80).ToString();
// create a client object
using(System.Net.WebClient client = new System.Net.WebClient()) {
// performs an HTTP POST
client.UploadString(url, xml);
}
I'm not a .NET programmer but I've had to interoperate with a few .NET services and have lots of SOAP/WSDL experience. Sounds like you've captured the XML for your service. The other problem you'll face is authentication. OOTB, .NET web services use NTLM for authentication. Open-source language support for NTLMv2 can be hit and miss (although a quick google search pulled up a few possibilities for ruby), and using NTLM auth over HTTP may be something that you have to wire together yourself. To answer a question above: where are the auth creds? If the service is using NTLM over the wire, authentication is happening at some layer below HTTP. If the service is using NTLM to authenticate HTTP, your NTLM creds are in the HTTP Authorization header. You should be able to tell with wireshark where they are. You'll also probably need a SOAPAction header; this can also be sniffed with wireshark. For the C# client, I'm sure there are docs explaining how to add headers to your request.
An application I'm writing needs to use .Net Remoting (I'm aware that WCF is the 'new thing', but it is unfortunately not an option available to us at this time).
Anyway, everything works fine if I don't try to use the application through a proxy. However, the application needs to be able to function through proxy web servers. I set up a HttpChannel and set the 'proxyName' and 'proxyPort' properties to their correct values. This allows the channel to use the proxy server no problem.
I have the following problems:
1: If the proxy server requires authentication, there seems to be no way to set the credentials the channel should use to auth with the proxy. I've tried both the 'credentials' property, and the 'username' and 'password' properties, but it doesn't seem to work. So the end result in a case where the proxy server requires authentication, and just returns an authentication error whenever the remote method is called.
2: I cannot seem to get the HttpChannel to use the default system web proxy. If Internet Explorer is configured to use a proxy, I should just be able to use WebRequest.GetSystemWebProxy() to get it. However, this returns an IWebProxy, and I cannot extract the host and port from this. If anybody knows of a way to do this, I would greatly appreciate it.
What is frustrating is that if you step through the code using Visual Studio and examine the HttpChannel class, there is a WebProxy object. Life would be so much easier if they provided access to that!
So basically what I'm asking is how on earth do I get a HttpChannel to use a web proxy correctly - bearing in mind that I need to be able to use a proxy which requires authentication, and the ability to auto-detect the Internet Explorer proxy settings? Is there a simpler way to instantiate the channel so that I can just pass it a proxy object as a parameter?
Any help is much appreciated!
I have found the solution to this problem (unfortunately I have lost the address of the blog which led me to this - if I can find it again I will give due credit), and it works perfectly. For anybody who is interested, add the following code:
private static void SetChannelProxy(HttpClientChannel channel, IWebProxy proxy)
{
FieldInfo proxyObjectFieldInfo = typeof(HttpClientChannel).GetField("_proxyObject", BindingFlags.Instance | BindingFlags.NonPublic);
proxyObjectFieldInfo.SetValue(channel, proxy);
}
You should first configure your proxy object using the credentials you wish to use, and then call this method with the channel you want to use with the proxy.
So I'm using the PayPal API. They require bigger companies to send an X509Certificate along with each SOAP API request. I've never heard of using a cert, it's always been just send the API signature along with an API request.
So I first created a class called Cerficate that implements the .NET ICerfiticatePolicy. One of the member methods, really the only one you have to implement is:
System.Net.ICertificatePolicy.CheckValidationResult(System.Net.ServicePoint, System.Security.Cryptography.X509Certificates.X509Certificate, System.Net.WebRequest, int)
So far I'm having trouble really understanding what to pass to this method. I guess the method simply validates that the Cerfiticate is valid. So I'm not sure what ServicePoint is and what to pass into it. I assumed it was my web service reference and a proxy class within such as the PayPalAPIAAInterfaceClient
I also see a very old example using ServicePointManager.S for something but I don't understand it, even after looking at MSDN. So I guess you are to use ServicePointManager.ServerCertificateValidationCallback and I suppose set the callback to the CheckValidationResult? If so, when do you do this? It's just very confusing to me.
Also, So I guess I create an instance of my Certificate class and set the certificate properties by reading the P12 certificate from my disk and then pass in that to this method to check if it's valid? I guess that's right.
I'm still trying to figure out this whole thing and I'm really stuck on the ServicePoint as well as WebRequest because really I'm using a proxy class in PayPal which does the under the hood sending of the request. So I don't see how I can even pass in type WebRequest because I'm using a proxy method for that anyway. So what would I even pass for the WebRequest param? I'm using a SOAP API WSDL, not NVP here so I'm not for example creating an HttpWebRequest variable like you do with REST services in order to send the API request over Http.
so far here's what I've tried:
PayPalAPIAAInterfaceClient client = new PayPalAPIAAInterfaceClient();
Certificate x509Certificate = new Certificate();
ServicePointManager.ServerCertificateValidationCallback = x509Certificate.CheckValidationResult();
client.ClientCredentials.ClientCertificate.Certificate = x509Certificate;
the problem is, what do I pass in for the ServicePiont and the rest of the params for CheckValidationResult?? I don't even know if I'm calling this right.
It's certainly not unheard of and in fact fairly common to secure SOAP services with X.509 certificates using the WS-Security spec - in fact, we do this for all of our internal and external web services. All web service frameworks including WCF are specifically designed to make this as easy as possible.
You should never have to use the ServicePointManager or ICertificatePolicy with a SOAP service using WS-Security. Unless there's something truly bizarre about PayPal's API, I think you're on the wrong track with that. All you have to do in WCF is this:
var client = new PayPalAPIInterfaceClient();
X509Certificate2 certificate = (...);
client.ClientCredentials.ClientCertificate.Certificate = certificate;
client.AddressVerify(...); // or whatever method you want to call
You don't even really need to write this code; if you have the certificate installed in the server's certificate store then you just edit the binding and behavior elements of the app.config - or use the WCF Service Configuration Editor, which is a lot easier.
Of course, in order to do this you have to have an X.509 certificate, and PayPal has to know about it. You can't just write new X509Certificate2(). You need to have a .pfx or .p12 file somewhere or, as mentioned above, have the certificate physically installed (this is the easiest way and the most secure because you're not hard-coding a password). And you need to upload the public key to PayPal.
You might be able to use OpenSSL to create a cert. PayPal's EWP page suggests that they'll accept these and gives instructions on how to create them, although it's not entirely clear whether or not the same process can be used for their SOAP API. It could be that they require a "real" certificate from Verisign, Thawte, etc. - I would try OpenSSL first and see, or just ask them.
There's a pretty comprehensive guide to the whole process here - you'll probably want to skip the sections on generating the certificate unless you have a Microsoft CA somewhere. Again, for that part, you'll probably want to try using the OpenSSL utility instead and follow PayPal's instructions, then install the cert on your server and skip to step 7 of that guide.
I have a dll which will retrieve certain information from internet. I'm calling this dll from my wrapper application. But the dll cannot access internet because it behind corporate proxy. Is there any way by which I can so authentication in the wrapper application, (eg by providing an interface to enter proxy username and password), so that the dll can access internet.
EDITED::
I'm accessing Google Data API dll which accepts username and password to login.
Do you control the code within the DLL? How does the DLL request the information? .NET certainly has proxy handling for things like WebClient and HttpWebRequest, but you'll need to give more information about the situation.
EDIT: Unfortunately I can't see anything in the GData API which exposes a proxy property.
You could try just setting the default proxy using GlobalProxySelection.Select. If that doesn't work, let me know and I'll try asking for suggestions internally.
You can assign the Proxy property of your WebRequest or WebClient object to a WebProxy object that has the required settings applied. It basically works as follows:
WebRequest request = WebRequest.Create("http://www.mysite.com");
request.Proxy = new WebProxy("127.0.0.1", 8080);
You can also assign a username/password using the Credentials property of the WebProxy.
See the examples associated with the WebProxy class on MSDN.
The GDATA Api uses your Global IE proxy, try setting your IE global proxy using the required registry keys from your wrapper application, GData api will pick it up automatically.