I am trying to make a Soap call to a webservice hosted by business partner. The problem I am having is that our client is hosted on a virtual PC with multiple IPs. I would like to call the hosted webservice with a different (not default) IP address. Why is that? There is VPN connection between our client application and hosted webservice but it is set up LAN2LAN between two IPs. Now I have to change local source IP address to match with the VPN requirements.
I have tried using SoapHttpClientProtocol's WebProxy, setting its value to the new IP but it does not seem to work. I am getting HTTP 404 error.
Here is some of the code:
//soapApiClient is typeof SoapHttpClientProtocol
//endpoint url -> webservice, url from appSettings
var url = SettingsProvider.ClientSapGetUserDataUrl;
soapApiClient.Url = url;
//proxy settings -> setting new IP, defined in appSettings
var proxy = SettingsProvider.ClientProxyAddress;
soapApiClient.Proxy = new WebProxy(proxy);
//credentials
soapApiClient.Credentials = GetCredentials();
I HTTP post user code and return value should be user data from SAP, currently I am getting 404 http error code. For comparison, it works like a charm from SoapUI. Maybe setting proxy is not what I am looking for? Any help would be much appreciated.
EDIT: To be more clear
Currently, by default service is called from default ip 91.185.201.88. Service's IP is 10.67.145.70. I want to change it like so: service is called from 192.168.4.2 to service's 10.67.145.70.
I finally managed to make it work. If anyone else will have problem with this, just follow these instructions.
Before calling remote service, you have to find service point for it. This is done via ServicePointManager like so
Example:
var servicePointUserReader = ServicePointManager.FindServicePoint(new Uri(FULLY QUALIFIED REMOTE SERVICE URL));
servicePointUserReader.BindIPEndPointDelegate = (sp, remote, retryCount) => new IPEndPoint(IPAddress.Parse(SOURCE IP FROM WHICH YOU WANT TO SEND REQUEST), 0);
In my example, fully qualified remote service url was something like http://65.145.63.71:8010/sapService (this is the one we are trying to call). Then I wanted to make a call from a different IP on our virtual PC which has many IPs addressed to it. You just need to input desired IP as shown in the second line of the code, for example 192.168.5.1.
Make sure you use "http://" when calling FindServicePoint with new Uri() constrcutor otherwise it will not work!
After that just proceed with the call to the service. Two lines of code, that's all you need. :)
Related
Basically, I need to be able to make an HTTP Request to a Website on the same machine I am on, without modifying the host file to create a pointer to the domain name.
For example.
I am running the code on one website, let's say www.bobsoft.com which is on a server.
I need to make an HTTP request to www.tedsoft.com which is on the same server.
How can I make a call using a C# HttpClient without modifying the host file? Take into account that the websites are routed by bindings in IIS. I do know the domain I am going to use ahead of time, I just have to make it all internal in the code without server changes.
Thanks!
IIS bindings on the same port but different hostnames are routed based on the http Host header. The best solution here is really to configure local DNS so requests made to www.tedsoft.com don't leave the machine. That being said, if these kinds of configuration aren't an option you can easily set the host header as a part of your HttpRequestMessage.
I have 2 test sites configured on IIS.
Default Web Site - returns text "test1"
Default Web Site 2 - returns text "test2"
The following code uses http://127.0.0.1 (http://localhost also works) and sets the host header appropriately based on the IIS bindings to get the result you're looking for.
class Program
{
static HttpClient httpClient = new HttpClient();
static void Main(string[] args)
{
string test1 = GetContentFromHost("test1"); // gets content from Default Web Site - "test1"
string test2 = GetContentFromHost("test2"); // gets content from Default Web Site 2 - "test2"
}
static string GetContentFromHost(string host)
{
HttpRequestMessage msg = new HttpRequestMessage(HttpMethod.Get, "http://127.0.0.1");
msg.Headers.Add("Host", host);
return httpClient.SendAsync(msg).Result.Content.ReadAsStringAsync().Result;
}
}
Quick version
I'm sure many people have implemented a [RequireHttps] SSL check of some description (message handler, attribute, whatever) at some point in their Web API development. How do you guys and gals test that it works correctly both in terms of success and failure?
Not so quick version
I'm developing a REST service in a OWIN self-hosted ASP.NET Web API 2. I have already successfully secured the service with SSL and have implemented a custom [RequireHttps] attribute (derived from the answers to this SO question).
In the case when the client is calling the correct URL (e.g. https://my.server.com/api/values), if I add a breakpoint in the attribute definition, the debugger correctly breaks in the code (just calls the base and all is well, as expected).
The question is: how can I exercise the failure scenario for this attribute, such that the attribute code will return an error response without interfering with other server processes?
My Web API service listens on base address https://+:9443/. I've tried removing the s such that I connect to http://my.server.com:9443/api/values, but I get an error response status 502 (connection failed) after about a minute's timeout. Fair enough I suppose, but I was actually hoping to return a response ("SSL required") from my [RequireHttps] attribute.
Then I've tried creating the following StartOptions object:
var options = new StartOptions();
options.Urls.Add("https://+:9443/"); // listen on port 9443 with SSL
options.Urls.Add("http://+:80/"); // listen to standard HTTP port 80
and passing it to the WebApp like this:
WebApp.Start<Startup>(options)
Again, this didn't work when I connected to http://my.server.com:9443/api/values, but it worked when I connected to http://my.server.com:80/api/values.
However, this is not what I want to do. My production server hosts both secure (HTTPS) and insecure (HTTP on port 80) resources so my code will intercept legitimate calls to other processes that rely on port 80 and tell them to reconnect via https, which is wrong.
Can someone please advise on what options I have? Is there even a point to have [RequireHttps] given my situation, as it never seems to do anything useful?
What you are trying to do can't be done. Basically, you're trying to do the same thing as typing
http:443//www.google.com
Notice how that doesn't work either
The problem is that you're trying to access an http protocol over an SSL protocol port, and that is what's failing. Your code for the RequireHttps doesn't even get to execute because the request can't even be processed through IIS.
I'm writing a local Proxy server. It already works for the majority of the requests. But sometimes I have Problems when I want to resolve the Host-name. Here is what I do:
When the header of the request is received, I filter the first line out. Then I take the Request-URL (which is between the two spaces) out of that line and store it into an Uri object. After that I extract the hostname with: string host= uri.host;
At least I do the DNS-call: IPAddress[] ips = Dns.GetHostAddresses(host)[0];
(How do I know here, which IP of the array I should take. Whats the difference between those IP's)
Like I said, for the majority of the Requests that works fine. But there are some adresses, that cannot be resolved. Here an example: When I want to open www.gmx.net, I first get the HTML-File ( this works fine ). After that, the Browser reloads a couple of Web-Objects like pics, javascript and so on. Those Object of course have some URL. And one of those URLs, that cannot be resolved is: ipv4-cout.gmx.net .
The attempt to resolve this URL results in the warning: The stated Host is unknown.
Another thing I need to know is: How to handle Alias-Host-names? For example: When I enter the hostname gmx.de into the Browser, it automaticaly resolves it into www.gmx.net. I know, there are Recource Reccords on a DNS-Server with type CNAME, but I dont know how to implement this.
I would say that they come back in the order that the DNS server sends them, I can no find no reference to any particular ordering.
Dns.GetHostAddresses Method
In most cases, there would only be a single IP address. In the case of www.gmx.net, they do have 2 and in theory, this would mean that you would round-robin the requests.
www.gmx.net has address 212.227.223.5
www.gmx.net has address 212.227.223.4
For your information. pv4-cout.gmx.net does not resolve on my machine and would result in a 404 when accessed any other way.
gmx.de does not resolve to www.gmx.net, there is a URL redirect on the web server.
Connecting to www.gmx.de|212.227.223.10|:80... connected.
HTTP request sent, awaiting response... 301 Moved Permanently
Location: http://www.gmx.net/ [following]
I am using a WCF service client generated by slsvcutil form Silverlight toolkit version 4. I've also tried version 3 with the same problems. When I use a client instance running on http with no user credentials it runs without problems. But I need to switch to https for productive servers and send user credentials that are hardcoded for my application. I use the following code for that:
var binding = new BasicHttpBinding (BasicHttpSecurityMode.TransportCredentialOnly);
var endpoint = new EndpointAddress (AppSettings.FlareEndPoint);
_service = new TopicAnalystAPIClient(binding, endpoint);
_service.ClientCredentials.UserName.UserName = "xxx";
_service.ClientCredentials.UserName.Password = "xxx";
When I call a method on that service pointing to http with no authentication it works. When I use the this code against http/https with the credential I get "There was an error on processing web request: Status code 401(Unauthorized): Unauthorized" exception. I've checked that the credentials are correct, I am able to open the service reference in my browser. I've also tried several combinations of http/https and SecurityMode value. I've also tried it on four different servers always with the same result.
What can be the problem?
A lot of permutations are possible. BasicHttpSecurityMode.TransportCredentialOnly should be usable without SSL [1] using HTTP itself. This means the server will send one (or more) authentication method(s) to the client (e.g. basic, digest, ntlm) and Mono (including MonoTouch) should be providing support for the most of them.
It is possible that the linker (if used) removes one of them. In that case you could try building and testing without linking (or skip linking of System.Net.dll).
It's also possible that the authentication method that the serve insist on is not supported. You could find which one is used by running a network trace (e.g. wireshark) or, maybe, it will show up in more details in the server log (along with the 401 error).
[1] http://msdn.microsoft.com/en-us/library/system.servicemodel.basichttpsecuritymode%28v=vs.95%29.aspx
I have a service that is running in Amazon Ec2. The service exposes both a http endpoint and a https endpoint. I am doing some geo lookup on the user IP address when I log the data. Everything works just fine on requests coming into the http endpoint. I have to grab the X-Forwarded-For header so that I do not take the Amazon Load Balancer UP Address and I am always able to get what I need. However on requests that come in on the https endpoint all of the IP addresses are the same.
In order to pull the IP address I am using the following C# code:
public static string FetchClientIp(HttpRequest req)
{
var value = req.Headers["X-Forwarded-For"];
return string.IsNullOrEmpty(value) ? req.UserHostAddress : value;
}
I can't find anything else that I need to do that is specific to https requests so I'm hoping someone here has run into this before. I'm going to spin up a test on this to try to better isolate the problem.
Thanks
It depends how you have your ELB set up.
If you're terminating SSL on the ELB (new feature as of October 2010), then the client IP address will be in "X-Forwarded-For".
HttpContext.Current.Request.Headers["X-Forwarded-For"]
It sounds like you're terminating SSL on your web servers, then ELB can't decrypt the traffic and add the "X-Forwarded-For" header to the HTTP request. So the client IP address in the header "REMOTE_ADDR" (which is the header returned by HttpRequest.UserHostAddress) is the IP of the last hop -- in this case the internal IP address of the ELB.
Keep in mind, "X-Forwared-For" may contain multiple IP addresses as described at http://docs.amazonwebservices.com/ElasticLoadBalancing/latest/DeveloperGuide/index.html?SvcIntro.html#X-Forwarded-For. In that case, you're probably most interested in the first address listed.