HttpWebRequest setting host to garbage but still getting OK response - c#

I am using an HttpWebRequest and passing in an Address which is an IP. I then set the host to a garbage value. When I call GetResponse() I am getting an OK even though I would expect this to fail since the host is garbage.
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(String.Format("http://10.10.10.10/Default.aspx"));
request.Host = "blah.blah.blah";
request.ContentType = "text/xml";
using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
{
if (response.StatusCode == HttpStatusCode.OK) { /*always enters here */ }
}
Why is the response coming back as OK? Shouldn't the garbage host cause this to fail?

HttpWebRequest.Host Property:
Get or set the Host header value to use in an HTTP request independent from the request URI.
Using the Host property to explicitly specify a custom Host header value also affects areas caching, cookies, and authentication. When an application provides credentials for a specific URI prefix, the applications needs to make sure to use the URI containing the value of the Host header, not the target server in the URI.
So there is no effect of .Host to the general request, you change some additional behavior.

Related

Stripe 401 - No valid API key provided - C#

I get following error: "The remote server returned an error: (401) Unauthorized" in this line:
using (HttpWebResponse httpResponse = request.GetResponse() as HttpWebResponse) {}
Here is the complete code:
string clientSecretKey = ConfigurationManager.AppSettings["ClientSecretKey"];
const string ChargeUrl = "https://api.stripe.com/v1/charges?amount={0}&currency={1}&source={2}&description={3}";
string requestUrl = HttpUtility.UrlPathEncode(
String.Format(ChargeUrl, 1000, "usd", "tok_19xLu8HN9aKw9vrkUsflNWOI", "Test charge to text#example.com") );
HttpWebRequest request = WebRequest.Create(requestUrl) as HttpWebRequest;
request.Headers.Add("Authorization", "sk_test_example");
request.ContentType = "application/x-www-form-urlencoded";
request.Method = "POST";
using (HttpWebResponse httpResponse = request.GetResponse() as HttpWebResponse)
{/* some code */}
At the beginning I thought the error was caused because the token can't used more than one time, but I changed it and got the same error. I'm not sure what is causing the error.
The issue here is that you are passing the API key but not using Bearer authentication which is what Stripe's API expects. You need to change your Authorization header like this:
request.Headers.Add("Authorization", "Bearer sk_test_example");
I know you mentioned in the comments that you can't use a third-party library but I wanted to mention one just in case. Stripe.net lets you use Stripe's API in .Net easily without having to rewrite the logic yourself. Handling errors, encoding parameters and sub-hashes properly, managing authentication and JSON decoding, all of this will take a lot of time and trial and error to build from scratch while this library would handle all of this for you.
You're initializing a variable for the secret key but not using it. Try modifying the request url to start with "https://" + clientSecretKey + ":#api..."
This is, of course, assuming clientSecretKey is the Stripe key.
Be careful putting a secret key somewhere on your server that it isn't hidden from a user / client.

c# HttpWebRequest.GetRequestStream Authorization

I got a web Api Controller which is flagged with the Authorize tag.
https://msdn.microsoft.com/de-de/library/system.web.http.authorizeattribute(v=vs.118).aspx
[Authorize()]
public class SomeController : ApiController {}
I'm using HttpWebRequest to do a Post-Request to that controller as follows:
(Please note, I do not provide an authorization header in order to show my issue)
var httpWebRequest = (HttpWebRequest)WebRequest.Create("SomeUrl");
httpWebRequest.ContentType = "text/json";
httpWebRequest.Method = "POST";
StreamWriter streamWriter;
// 1) no error here, works without authentication
using (streamWriter = new StreamWriter(httpWebRequest.GetRequestStream()))
{
string json = "{\"Message\":\"Test\"," + "\"Data\":\"\"}";
streamWriter.Write(json);
streamWriter.Flush();
streamWriter.Close();
}
// 2) here I get a 401: not authorized
var httpResponse = (HttpWebResponse)httpWebRequest.GetResponse();
Problem:
I expected to get a not authorized exception, when asking for the request stream. But I can call GetRequestStream and even write to that stream, without any issue.
Only when GetRespone is called, I get the 401 (Not Authorized) which I expected earlier.
I'm just wondering, if this is intended behaviour? And If there is any way to change that. For example, if I want to upload a huge file, all the data will be uploaded before the client is informed that it is not authorized to do so. Somehow that does not make sense to me? Or do I miss something?
You are right, ideally, the GetRequestStream() call should have resulted in the request being sent to the server, and the server responding with a 401.
I think what might be happening is that the server is waiting for you to post the data before replying with the final status. THat is why you get the final response when you call request.GetResponse()
In any case, you should handle exceptions and do the needful.

c# - httpwebrequest status code returns 200 instead of 404

I'm trying this code..
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create("http://www.goo4le.com/");
request.Method = "HEAD";
using (HttpWebResponse response = request.GetResponse() as HttpWebResponse)
{
Console.Write((int)response.StatusCode);
}
goo4le is a non existing domain. So its supposed to return 404. Instead it returns 200 status.
I think its because of my broadband provider using a custom 404 page.
This is what i see when i enter goo4le.com in my browser.
Can someone tell me how to get the real http status instead of my browser status?
I actually don't get any status code when running this, I get a DNS error saying I cant lookup the domain.
I imagine you are exactly right about the ISP, they may be doing this via a DNS redirection given you dont get this error. You could solve this by using a DNS server other than the one your ISP provides, try googles 8.8.8.8, 8.8.4.4 (https://developers.google.com/speed/public-dns/)
This from their FAQs
How is Google Public DNS different from my ISP's DNS service or other
open DNS resolvers? How can I tell if it is better?
Open resolvers and
your ISP all offer DNS resolution services. We invite you to try
Google Public DNS as your primary or secondary DNS resolver along with
any other alternate DNS services. There are many things to consider
when identifying a DNS resolver that works for you, such as speed,
reliability, security, and validity of responses. Unlike Google Public
DNS, some ISPs and open resolvers block, filter, or redirect DNS
responses.
How does Google Public DNS handle non-existent domains?
If
you issue a query for a domain name that does not exist, Google Public
DNS always returns an NXDOMAIN record, as per the DNS protocol
standards. The browser should show this response as a DNS error. If,
instead, you receive any response other than an error message (for
example, you are redirected to another page), this could be the result
of the following: A client-side application such as a browser plug-in
is displaying an alternate page for a non-existent domain. Some ISPs
may intercept and replace all NXDOMAIN responses with responses that
lead to their own servers. If you are concerned that your ISP is
intercepting Google Public DNS requests or responses, you should
contact your ISP.
You can try to disable redirecting, unfortunatelly i can't test it, since i got another provider (if that's the problem).
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create("http://www.goo4le.com/");
request.Method = "HEAD";
request.AllowAutoRedirect = false;
using (HttpWebResponse response = request.GetResponse() as HttpWebResponse)
{
Console.Write((int)response.StatusCode);
}
if it is working, it will most likely throw an exception, since everything that returns a statuscode that's not 200 throws one......
if you wanna catch it try this:
try
{
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create("http://www.goo4le.com/");
request.Method = "HEAD";
request.AllowAutoRedirect = false;
using (HttpWebResponse response = request.GetResponse() as HttpWebResponse)
{
Console.Write((int)response.StatusCode);
}
}
catch (WebException e)
{
// in this case it was a status code exception (not status 200...)
if (e.Response != null) Console.Write((int)e.Response.StatusCode);
else throw;
}

Can I send an empty HTTP POST WebRequest object from C# to IIS?

Do I need to just slap some random garbage data in a WebRequest object to get by the HTTP status code 411 restriction on IIS?
I have an HttpPost action method in an MVC 3 app that consumes a POST request with all the relevant information passed in the querystring (no body needed).
[HttpPost] public ActionResult SignUp(string email) { ... }
It worked great from Visual Studio's built in web host, Cassini. Unfortunately, once the MVC code was live on IIS [7.5 on 2008 R2], the server is pitching back an HTTP error code when I hit it from my outside C# form app.
The remote server returned an error:
(411) Length Required.
Here is the calling code:
WebRequest request = WebRequest.Create("http://somewhere.com/signup/?email=a#b.com");
request.Method = "POST";
using (WebResponse response = request.GetResponse())
using (Stream responseStream = response.GetResponseStream())
using (StreamReader responseReader = new StreamReader(responseStream)) {
// Do something with responseReader.ReadToEnd();
}
Turns out you can get this to go through by simply slapping an empty content length on the request before you send it.
WebRequest request = WebRequest.Create("http://somewhere.com/signup/?email=a#b.com");
request.Method = "POST";
request.ContentLength = 0;
Not sure how explicitly giving an empty length vs. implying one makes a difference, but IIS was happy after I did. There are probably other ways around this, but this seems simple enough.
I believe you are required to set a Content-Length header anytime you post a request to a web server:
http://msdn.microsoft.com/en-us/library/system.web.httprequest.contentlength.aspx
You could try a GET request to test it.

Difficulty with BugzScout.net from behind a proxy

I'm attempting to use Fogbugz's BugzScout in order to automatically submit unhanded application exceptions to my Fogbugz on demand Account. I've written up a wrapper class for it and everything appears to be just groovy - on my box. Testing the same code in the production environment, behind a Proxy that requires authentication, I have had nothing but issues.
I went to work modifying the BugzScout code in order to get it to authenticate with the Proxy, and after trying many different methods suggested via a Google search, found one that works! But now I'm getting an "Connection actively refused" error from Fogbugz itself, and I don't know what to do.
Here is the code where the BugzScout connects via a .net WebClient to submit a new case, with my modifications to deal with our Proxy. What am I doing that would cause Fogbugz to refuse my request? I've removed all non web-client related code from the procedure for ease of reading.
public string Submit(){
WebClient client = new WebClient();
WebProxy proxy = new WebProxy();
proxy.UseDefaultCredentials = true;
client.Proxy = proxy;
Byte[] response = client.DownloadData(fogBugzUrl);
string responseText = System.Text.Encoding.UTF8.GetString(response);
return (responseText == "") ? this.defaultMsg : responseText;
}
The url is correct and the case is filled in properly- this has been verified.
EDIT: Additional info.
Using Fogbugz on Demand.
Using FogBugz.net code in it's entirety, with only these additions
WebProxy proxy = new WebProxy();
proxy.UseDefaultCredentials = true;
client.Proxy = proxy;
Error occurs when attempting to connect to both https://oursite.fogbugz.com/scoutsubmit.asp and http://oursite.fogbugz.com//scoutsubmit.asp (except one says port 443, and the other port 80, obviously)
I don't know anything about web authentication so I can't tell you what kind I'm using- if you tell me where to look I'd be happy to answer that for you.
Got the fix from Fogbugz- this is the appropriate network code to get though the proxy authentication and not mis-authenticate with Bugzscout.
WebRequest.DefaultWebProxy.Credentials = CredentialCache.DefaultNetworkCredentials;
WebRequest request = WebRequest.Create(fogBugzUrl);
request.ContentType = "application/x-www-form-urlencoded";
request.Method = "POST";
request.Proxy.Credentials = CredentialCache.DefaultNetworkCredentials;
Stream requestStream = request.GetRequestStream();
requestStream.Write(bytes, 0, bytes.Length);
requestStream.Close();
Is your fogbugzUrl using HTTP Basic Authentication? Is it SSL (hosted on On Demand?)
The connection actively refused message would be coming from the web server itself, not really FogBugz.
Can you post the HTTP Status Code?
One thing to note if you are using FogBugz On Demand is you HAVE to use the https:// url (not the http url).

Categories