Is it possible to overide the way that the Accept/Content-Type/User-Agent headers are set?
I am asking because I have a program that uses HttpWebRequest to login to an account on a website, check the stats of my account & report all data in a program. The website that this is used on also gets a lot of spam & they have now started blocking any requests that do not explicitly send "accept:" in a header, whereas HttpWebRequest sends "Accept:" (Upper Case A).
Using CharlesProxy to check, repeat & change the code I can confirm that the issue is down to the capital/lower case A in the 'Accept' header only.
Using request.Accept='' always sets the header to "Accept".
Setting custom headers is not allowed either: request.headers.add("accept","xx")
Related
As the title says I am wondering if it possible to return information from the controller based on the success of the PUT request.
In this case I am using the put request to use my email service to send emails. Is there a way to return a results object that lists the statuses for each email so I can display on the front end which emails failed and why?
Thanks in advance for any advice.
Ideally PUT request(successful) is used to:
1.) Update an existing resource -200 OK with NO response body
2.) Creation of new resource (If the Request-URI does not point to an existing resource, origin server can create the resource with that URI) - 201 Created with some meta data ,resource identifier in the response body.
So as per the recommendation ,it should not be returned in the response of PUT request and a subsequent GET call should be made to get the status of the emails.
Refer the HTTP specification :
RF2616 -https://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9.6
I am testing a web api and I am setting the From header in the request with Postman, like this:
But in my controller, when I evaluate this.Request.Headers.From, I'm getting a false result:
But when I am evaluating only the Request.Headers and I'm scrolling to the ResultView, I see that U have a header with the key From.
So what's the point of the member From from the this.Request.Headers.From?
It looks like the From header is standardized to an email address. Likely the .NET code is excluding it since it is not an email address.
Consider using a different header.
Sorry for my english.
In Delphi I have an idHttp component with the hoWaitForUnexpectedData option activated.
When I send a POST request to a URL, it redirects the client to a second URL with the same POST request and headers. Also, the server response contains "Connection: keep-alive" in its header.
However, when I try to do the same request in C# with a HttpWebRequest component, it redirects to the second URL using the method GET.
I need the C# HttpWebRequest component to work like the Delphi idHTTP one does. I don't understand why it uses a GET instead of a POST when following the redirection.
Here's my code in Delphi, using hoWaitForUnexpectedData:
// The server is supposed to send a 'Content-Length' header without sending
// the actual data. 1xx, 204, and 304 replies are not supposed to contain
// entity bodies, either...
if TextIsSame(ARequest.Method, Id_HTTPMethodHead) or
TextIsSame(ARequest.MethodOverride, Id_HTTPMethodHead) or
((AResponse.ResponseCode div 100) = 1) or
(AResponse.ResponseCode = 204) or
(AResponse.ResponseCode = 304) then
begin
// Have noticed one case where a non-conforming server did send an
// entity body in response to a HEAD request. If requested, ignore
// anything the server may send by accident
if not (hoWaitForUnexpectedData in FOptions) then begin
Exit;
end;
Result := CheckForPendingData(100);
end
else if (AResponse.ResponseCode div 100) = 3 then
begin
// This is a workaround for buggy HTTP 1.1 servers which
// does not return any body with 302 response code
Result := CheckForPendingData(5000);
end else begin
Result := True;
end;
An HTTP redirect, by definition from the standard, should be handled using a GET. Therefore, if you send a POST and get a redirect as an answer, the expected behavior is to perform a GET to the redirect address. I suspect the old Delphi component is following old practices and replicates the call including with the POST verb.
I would try to disable AllowAutoRedirect in the HttpWebRequest object and handle this manually, as your case seems to differ from the standard.
The hoWaitForUnexpectedData option has no effect on how TIdHTTP handles redirects, and neither does the section of code you quoted.
However, the hoTreat302Like303 option does affect redirect handling. If TIdHTTP receives a 303 redirect, or receives a 302 redirect with hoTreat302Like303 enabled, TIdHTTP sends the new request as a GET. Otherwise, it sends the new request using the same verb as the redirected request. This is by design, and there is a series of comments in the implementation code of the TIdHTTPProtocol.ProcessResponse() method explaining the rational behind this behavior:
// GDG 21/11/2003. If it's a 303, we should do a get this time
// RLebeau 7/15/2004 - do a GET on 302 as well, as mentioned in RFC 2616
// RLebeau 1/11/2008 - turns out both situations are WRONG! RFCs 2068 and
// 2616 specifically state that changing the method to GET in response
// to 302 and 303 is errorneous. Indy 9 did it right by reusing the
// original method and source again and only changing the URL, so lets
// revert back to that same behavior!
// RLebeau 12/28/2012 - one more time. RFCs 2068 and 2616 actually say that
// changing the method in response to 302 is erroneous, but changing the
// method to GET in response to 303 is intentional and why 303 was introduced
// in the first place. Erroneous clients treat 302 as 303, though. Now
// encountering servers that actually expect this 303 behavior, so we have
// to enable it again! Adding an optional HTTPOption flag so clients can
// enable the erroneous 302 behavior if they really need it.
The jist of it is that the HTTP spec says to send a GET for a 303 redirect, whereas it is ambiguous about whether to send a GET for 302. Some browsers do, some do not. That is why the hoTreat302Like303 option was added, though it is disabled by default for backwards compatibility with earlier Indy versions.
So, the behavior you describe means you must be encountering a 302 redirect, with hoTreat302Like303 disabled (which it is default). If you enable that option, TIdHTTP will behave more like HttpWebRequest, not the other way around.
I am having some trouble adding a value to the Page.Request & Page.Response headers and have the key & value stay/persist through a redirect.
I have an enum tracking code that I want to place in the headers to trace how a user goes through my site prior to their checkout.
I am using this code to add the headers to response and request context.
var RequestSessionVariable = context.Request.Headers["SessionTrackingCode"];
if (RequestSessionVariable == null)
{
context.Response.AddHeader("SessionTrackingCode", ((int)tracker).ToString());
context.Request.Headers.Add("SessionTrackingCode", ((int)tracker).ToString());
}
else
{
if(!RequestSessionVariable.Contains(((int)tracker).ToString()))
{
RequestSessionVariable += ("," + ((int)tracker).ToString());
context.Request.Headers["SessionTrackingCode"] = RequestSessionVariable;
context.Response.Headers["SessionTrackingCode"] = RequestSessionVariable;
}
}
The method call that occurs in Page_Load of the necessary controls within the website:
trackingcodes.AddPageTrackingCode(TrackingCode.TrackingCodes.ShoppingCart, this.Context);
The header SessionTrackingCode is their but after a Response.Redirect("~/value.aspx") the RequestSessionVariable is always null. Is there something that happens on the redirect that will wipe out the headers that I add? Or what am I doing wrong on the addition of the header key and value?
this equals:
public partial class Cart : System.Web.UI.UserControl
Headers send by client on every request, so any redirect will require client to send headers again.
Unless you are using some special client (not a browser) any special headers will be essentially ignored/lost during requests. Browser only will send known headers (cookies, authentication, referrer) in requests and act on other set of known headers in response (setCookies). You are using custom header that not known to browser so browser will not read in from response nor send it in request.
Your options:
switch to use cookies for your tracking (same as everyone else)
use AJAX requests to send/receive custom headers (probably not what you are looking for as urls look like regular GET/POST ones)
build custom client that will pay attention to your headers (purely theoretical, unless you building some sort of sales terminal no one will install your client to visit your site)
Note: adding headers to request in page code does no make much sense as request will not be send anywhere (it is what come from browser).
This looks like a job for cookies, rather than http headers. The browser will not return your custom headers to you, but it will return your cookies.
I have an application that contains a button, on click of this button, it will open a browser window using a URL with querystring parameters (the url of a page that i am coding).
Is there a way to ensure that the URL is coming from my application and only from my application - and not just anyone typing the URL manually in a webbrowser?
If not, what is the best way to ensure that a specific URL is coming from a specific application - and not just manually entered in the address bar or a web browser-
Im using asp.net.
You can check if the request was made from one of the pages of your application using:
Request.UrlReferrer.Contains("mywebsite.com")
That's the simple way.
The secure way is to put a cookie on the client containing a value encrypted using a secure key or hashed using a secure salt. If the cookie is set to expire when the page is closed it should be impossible for someone to forge.
Here's an example:
On the pages that would redirect to the page you are trying to protect:
HttpCookie cookie = new HttpCookie("SecureCheck");
//don't set the cookie's expiration so it's deleted when the browser is closed
cookie.Value = System.Web.Security.FormsAuthentication.HashPasswordForStoringInConfigFile(Session.SessionID, "SHA1");
Response.Cookies.Add(cookie);
On the page you are trying to protect:
//check to see if the cookie is there and it has the correct value
if (string.IsNullOrEmpty(Request.Cookies["SecureCheck"]) || System.Web.Security.FormsAuthentication.HashPasswordForStoringInConfigFile(Session.SessionID, "SHA1") != Request.Cookies["SecureCheck"])
throw Exception("Invalid request. Please access this page only from the application.");
//if we got this far the exception was not thrown and we are safe to continue
//insert whatever code here
There's no reliable way to do this for a GET request, nor is their any reason to try for a legitimate user. What you should do instead is ensure that regardless of where the request comes from the user has the proper permissions and access rights and that the session is protected appropriately (HTTP only cookies, SSL, etc.) If the request is changing data, then it should be a POST, not a GET, and it should be accompanied by some suitable cross-site request forgery prevention techniques (such as a cookie containing a nonce that is verified against a matching nonce on the form itself).
There is no way, other than rejecting the request if it doesn't contain a previously generated random one-time token in the parameters (that would be stored in the session, for example).
While there is no 100% secure way to do this, what I am suggesting might at least take care of your basic needs.
This is what you can do .
Client: Add a HTTP header with an encoded string that is like hash (sha256) of some word.
Then make your client always do a POST request instead of GET.
Server: Check the HTTP Header for encoded string. Also make sure it is a POST request.
This is not 100% as ofcourse someone smart enough could figure out and still generate a request, but depending on your need you might find this enough or not
You can check the referer, the user agent, add an additional header to the request, always do post requests to that url. However, considering HTTP is transmitted in plain text, somebody is always able to let wireshark or fiddler run, capture the HTTP packets and recreate the requests with your measures in place.
Pass parameters from your application so that you can verify on the server side.
I suggest you use an encryption algorithm and generate random text using a password(key). Then, decrypt the param on the server side and check if it matches your expectation.
I am not very clear though. sorry about that, If had to do something like this, then, I would do something similar to mentioned above.
You can use to check the header on MVC controller like Request.Headers["Accept"]; if it is coming from your code in angularjs or jquery:
sample angularjs like this:
var url = ServiceServerPath + urlSearchService + '/SearchCustomer?input=' + $scope.strInput;
$http({
method: 'GET',
url: url,
headers: {
'Content-Type': 'application/json'
},.....
And on the MVC [HttpGet] Action method
[HttpGet]
[PreventDirectAccess]//It is my custom filters
// ---> /Index/SearchCustomer?input={input}/
public string SearchCustomer(string input)
{
try
{
var isJsonRequestOnMVC = Request.Headers["Accept"];//TODO: This will check if the request comes from MVC else comes from Browser
if (!isJsonRequestOnMVC.Contains("application/json")) return "Error Request on server!";
var serialize = new JavaScriptSerializer();
ISearch customer = new SearchCustomer();
IEnumerable<ContactInfoResult> returnSearch = customer.GetCustomerDynamic(input);
return serialize.Serialize(returnSearch);
}
catch (Exception err)
{
throw;
}
}