Orchestrator Authentication not working with Javascript XHR request - javascript

I try to build a website where I can internally control our UiPath Orchestrator. We are using an on-premise Orchestrator.
The connection was firstly tested in Postman/curl:
curl --location --request POST '{{url}}/api/Account/Authenticate' \
--header 'Content-Type: application/json' \
--data-raw '{
"tenancyName": "{{tenantName}}",
"usernameOrEmailAddress": "{{usernameOrEmailAddress}}",
"password": "{{password}}"
}'
This gives me back the authtoken without any issue. Perfect.
Then I tried to implement that curl as XHR in Javascript:
var data = JSON.stringify({"tenancyName":"...","usernameOrEmailAddress":"...","password":"..."});
var xhr = new XMLHttpRequest();
xhr.withCredentials = true;
xhr.addEventListener("readystatechange", function() {
if(this.readyState === 4) {
console.log(this.responseText);
}
});
xhr.open("POST", "https://.../api/account/authenticate");
xhr.setRequestHeader("Content-Type", "application/json");
xhr.send(data);
But Firefox and Chrome are trying to preflight. So I get a 404 statuscode back:
Firefox:
Chrome:
I'm confused now how to fix it. Actually it is obviously a CORS issue. So I tried to set:
<add name="Access-Control-Allow-Origin" value="*" />
<add name="Access-Control-Allow-Methods" value="GET,PUT,POST,DELETE,OPTIONS" />
<add name="Access-Control-Allow-Headers" value="Content-Type" />
on our IIS7 server. Without any change.
Also I tried to set this setting to allow everything on the Node.js server and on the XHR request. But 404 stays.
Then I tried using Chrome and Firefox Plugins to disable CORS. But 404 stays.
And again in Postman it works perfectly since the first try. So it just a CORS issue. But I want to let CORS enable, maybe just configure it in a way that specific server are allowed. How to do that?

One solution is to use the non-preflight request:
var data = "tenancyName=...&usernameOrEmailAddress=...&password=...";
var xhr = new XMLHttpRequest();
xhr.addEventListener("readystatechange", function() {
if(this.readyState === 4) {
console.log(this.responseText);
}
});
xhr.open("POST", "https://url/api/account/authenticate");
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
xhr.send(data);
As "Content-Type", "application/x-www-form-urlencoded" is one of the non-preflight we simply dodge the CORS mechanics with it. And for sure the data variable was changed so the JSON.stringify is gone now.
As the UiPath Orchestrator server is in a private Azure environment, this is not a huge security issue at all.
Anyway solutions that disable the CORS completely on the IIS7 server are still welcome.

Another solution is to disable cors on IIS10.
But be sure that this is only for testing and only kind of secure when you run it non-public! Later you should enable it again and restrict to your used domains.
First install the Cors module.
And the second step is adding this line to the web.config file of the IIS10 server:
<configuration>
<system.webServer>
<cors enabled="true" failUnlistedOrigins="true">
<add origin="*">
<allowHeaders allowAllRequestedHeaders="true" />
</add>
</cors>
</system.webServer>
</configuration>

Related

OPTIONS method not request with credentials, 401 [duplicate]

I'm trying to enable CORS support in my WebAPI project, and if I enable Anonymous Authentication then everything works fine, but with Windows Auth + disabled anonymous authentication, the OPTIONS request sent always returns a 401 unauthorized response. The site requesting it is on the DOMAIN so should be able to make the call, is there any way to get around the issue without disabling Windows Authentication?
You can allow only OPTIONS verb for anonymous users.
<system.web>
<authentication mode="Windows" />
<authorization>
<allow verbs="OPTIONS" users="*"/>
<deny users="?" />
</authorization>
</system.web>
According W3C specifications, browser excludes user credentials from CORS preflight: https://dvcs.w3.org/hg/cors/raw-file/tip/Overview.html#preflight-request
Several years later, but through the answer from #dariusriggins and #lex-li I have managed to add the following code to my Global.asax:
public void Application_BeginRequest(object sender, EventArgs e)
{
string httpOrigin = Request.Params["HTTP_ORIGIN"];
if (httpOrigin == null) httpOrigin = "*";
HttpContext.Current.Response.AddHeader("Access-Control-Allow-Origin", httpOrigin);
HttpContext.Current.Response.AddHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");
HttpContext.Current.Response.AddHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept, X-Token");
HttpContext.Current.Response.AddHeader("Access-Control-Allow-Credentials", "true");
if (Request.HttpMethod == "OPTIONS")
{
HttpContext.Current.Response.StatusCode = 200;
var httpApplication = sender as HttpApplication;
httpApplication.CompleteRequest();
}
}
the httpOrigin is actually looked up in a list of allowed hosts but that just complicated things. This means that all other requests are validated but options just returns.
Thanks for this question, I would have been lost without it!
From MS:
If you disable anonymous authentication, it’s by design that IIS would return a 401 to any request. If they have enabled Windows auth, the 401 response in that case would have a WWW-Authenticate header to allow the client to start an authentication handshake. The question then becomes whether the client that the customer is using can do Windows authentication or not.
Finally, it seems like there might be an underlying question about whether it’s possible or not to configure a URL such that anonymous access is allowed for one verb (OPTIONS, in this case), but require Windows authentication for other verbs. IIS does not support this through simple configuration. It might be possible to get this behavior by enabling both Anonymous and Windows authentication, setting ACLs on the content that deny access to the anonymous user, and then configuring the handler mapping for the URL in question so that it does not verify the existence of the file associated with the URL. But it would take some playing with it to confirm this.
The easiest way to fix this is to create a rewrite rule with the condition request_method = ^OPTIONS$. Then set the action to be a custom response, set that to 200 OK. Then all options requests will respond with 200 instead of 401. This will fix the CORS issue.
Of course you still need to make sure you have the correct cross origin request headers.
This will stop options requests (which dont have any credentials) responding with 401 when integrated auth is enabled.
The accepted answer is correct however I was troubleshooting a rest api with a "node with iisnode and npm cors module" setup for a while and was not comfortable with just enabling anonymous authentication for all users. Since its a node application the system.web tag does not do much. I ended up with the following addition to the web.config:
<system.webServer>
<security>
<requestFiltering>
<hiddenSegments>
<add segment="node_modules" />
</hiddenSegments>
</requestFiltering>
<authorization>
<add accessType="Allow" verbs="OPTIONS" users="?" />
<add accessType="Deny" verbs="GET, PUT, POST, DELETE" users="?" />
</authorization>
</security>
</system.webServer>
Extending the answer provided by #dariusriggins. Check this post: Microsoft | Developer: Putting it all together – CORS tutorial
For IIS Configurations:
Authorization rule
Authorization stage (or Authorization event), we need to make sure we only allow the anonymous requests from CORS preflight and require all other incoming requests have authentication credentials supplied. We can achieve this through Authorization Rules. A default authorization rule granting all users access to the site is already in place and supplied by default by IIS. We will start by modifying this rule to only allow anonymous users, if they send requests that are using the OPTIONS http verb. Below is the target configuration in IIS for this authorization rule:
Edit Authorization rule
Related Question: IIS hijacks CORS Preflight OPTIONS request
Merging info from answers found in multiple places. If you need to enable CORS on a ASP.net page method with Windows Authentication on the intranet, this is what seems to work. Without the changes to web.config, this doesn't work.
You need to add this to Global.asax
protected void Application_BeginRequest(object sender, EventArgs e)
{
string httpOrigin = HttpContext.Current.Request.Params["HTTP_ORIGIN"] ?? HttpContext.Current.Request.Params["ORIGIN"] ?? "*";
HttpContext.Current.Response.AddHeader("Access-Control-Allow-Origin", httpOrigin);
HttpContext.Current.Response.AddHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");
HttpContext.Current.Response.AddHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept, X-Token");
HttpContext.Current.Response.AddHeader("Access-Control-Allow-Credentials", "true");
if (HttpContext.Current.Request.HttpMethod == "OPTIONS")
{
HttpContext.Current.Response.StatusCode = 200;
var httpApplication = sender as HttpApplication;
httpApplication.CompleteRequest();
}
}
And this to web.config
<system.webServer>
<handlers>
<remove name="ExtensionlessUrlHandler-Integrated-4.0" />
<remove name="OPTIONSVerbHandler" />
<remove name="TRACEVerbHandler" />
<add name="ExtensionlessUrlHandler-Integrated-4.0" path="*."
verb="*" type="System.Web.Handlers.TransferRequestHandler"
preCondition="integratedMode,runtimeVersionv4.0" />
</handlers>
</system.webServer>
I've run into same issue today due to bug in IE 10 and 11, I'm using ServiceStack instead of WebApi, but the approach can work for you as well.
Enabled Windows Integrated and Anonymous Authentication on IIS Web Site.
Have a series of filters on the ServiceStack Pipeline,
For handling Cors and OPTIONS request, On Options request, I add necessary headers and end the request,
Filter for checking includng HttpRequest is Authenticated?,
etc filter,
After passing through all the filters, it executes the service.
CorsFeature.cs
AuthenticateFilter
In my AppHost,
appHost.Plugins.Add(new CorsFeature());
appHost.RequestFilters.Add(AuthenticateFilter.Authenticate);
I have modified the CorsFeature to handle OptionsRequest's in addition to adding headers, Authenticate Filter to check for requests authenticated!
What worked for me (when working with AngularJS or JQuery) is to add withCredentials:true to each request on client:
$http.get("http://localhost:88/api/tests", {withCredentials :true})
And enabling CORS on server, this was done with Microsoft.Owin.Cors from nuget and adding it in Startup like below:
public void Configuration(IAppBuilder app)
{
HttpConfiguration config = new HttpConfiguration();
ConfigureOAuth(app);
WebApiConfig.Register(config);
app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);
app.UseWebApi(config);
}
References:
CORS on server (see step 11): http://bitoftech.net/2014/06/01/token-based-authentication-asp-net-web-api-2-owin-asp-net-identity/
CORS on client: http://brockallen.com/2012/12/15/cors-and-windows-authentication/
I'm using Web API and OWIN and I tried every suggested solution but the only thing that worked was the following
//use it in your startup class
app.Use((context, next) =>
{
if (context.Request.Headers.Any(k => k.Key.Contains("Origin")) && context.Request.Method == "OPTIONS")
{
context.Response.StatusCode = 200;
context.Response.Headers.Add("Access-Control-Allow-Origin", new string[1] { "ALLOWED_ORIGIN" });
context.Response.Headers.Add("Access-Control-Allow-Headers", new string[4] { "Origin", "X-Requested-With", "Content-Type", "Accept" });
context.Response.Headers.Add("Access-Control-Allow-Methods", new string[5] { "GET", "POST", "PUT", "DELETE", "OPTIONS" });
context.Response.Headers.Add("Access-Control-Allow-Credentials", new string[1] { "true" });
return context.Response.WriteAsync("");
}
return next.Invoke();
});
//this is important! Without it, it didn't work (probably because the middleware was too late)
app.UseStageMarker(PipelineStage.Authenticate);
you need to insert this code somewhere in one of your OWIN startup classes.
It's important to call app.UseStageMarker(PipelineStage.Authenticate) because otherwise the preflight check failed.
Further infos for UseStageMarker -> https://learn.microsoft.com/en-us/aspnet/aspnet/overview/owin-and-katana/owin-middleware-in-the-iis-integrated-pipeline
It's also important that you need to explicitly define the allowed headers. It will fail if you use * as a placeholder.
Maybe it helps somebody.
I understand this is an old question with several possible solutions (as well as more questions), but in case anyone else comes across this, IIS CORS 1.0 is available as of Nov '17:
https://blogs.iis.net/iisteam/introducing-iis-cors-1-0
https://learn.microsoft.com/en-us/iis/extensions/cors-module/cors-module-configuration-reference
You can download it through IIS Windows Platform Installer (WPI). This should resolve many of your CORS authentication issues. Enjoy!
This IIS extension (IIS CORS Module) helped me to solve the 401-Unauthorized preflight request to an IIS-hosted app with Windows Authentication enabled. After installing this module I did IISRESET and in the Web.config file of my web-application I added the following:
<configuration>
<configSections>
<!-- ... (configSections must be the first element!) -->
</configSections>
<system.webServer>
<cors enabled="true">
<add origin="http://localhost:3000" allowCredentials="true" maxAge="120">
<allowHeaders allowAllRequestedHeaders="true"/>
<!-- Added 'allowMethods' just in case. -->
<allowMethods>
<add method="HEAD"/>
<add method="GET"/>
<add method="POST"/>
<add method="PUT"/>
<add method="DELETE"/>
<add method="OPTIONS"/>
</allowMethods>
</add>
</cors>
</system.webServer>
</configuration>
Here you can find more information on how to configure the IIS CORS Module:
Getting started with the IIS CORS Module.
instal iis cors module on your iis.
in case of WebApi add :
public static void Register(HttpConfiguration config)
{
var cors = new EnableCorsAttribute("*", "*", "*");
cors.SupportsCredentials = true;
config.EnableCors(cors);
}
add this lines to your web.config:
<configuration>
<system.webServer>
<cors enabled="true" failUnlistedOrigins="true">
<add origin="*">
<allowHeaders allowAllRequestedHeaders="true">
<add header="Access-Control-Allow-Origin" />
<add header="Access-Control-Allow-Headers" />
<add header="Access-Control-Allow-Methods" />
</allowHeaders>
</add>
</cors>
</system.webServer>
</configuration>
more info. in this article.
add xhrFields: {withCredentials: true} to your ajax call.
Enabling SupportCredentials on EnableCorsAttribute in WebApiConfig.cs did the trick for me:
public static void Register(HttpConfiguration config)
{
//enable cors request just from localhost:15136
var cors = new EnableCorsAttribute("http://localhost:15136", "*", "*");
cors.SupportsCredentials = true;
config.EnableCors(cors);
//other stuff
}
https://www.asp.net/web-api/overview/security/enabling-cross-origin-requests-in-web-api
Make sure you send credentials when calling from javascript ({withCredentials :true})

Javascript post to external site from Dynamics Online

I've been trying for most of the day to post data to an external WebAPI endpoint when the OnSave event is triggered from a Microsoft Dynamics 365 form. Unfortunately, despite an extraordinary amount of research, I haven't been able to successfully post the data.
Having spent about an hour stumbling around getting the javascript library referenced in the right form, I tried reference jQuery from within my script, and trying to use $.ajax to trigger the post, using a declared alias. Here's a redacted version of the code:
function UpdateSupplierStatus()
{
var $jQ = jQuery.noConflict();
var MembershipNumber =
Xrm.Page.data.entity.attributes.get("membershipnumber").getValue();
var StatusCode = Xrm.Page.data.entity.attributes.get("statuscode").getText();
$jQ.ajax({
url: 'http://myurl.com/api/MembershipAPI/UpdateMembershipStatus',
type: 'POST',
data: {
'membershipNumber' : MembershipNumber,
'statusCode' : StatusCode
},
datatype: 'json',
success: function() {},
error: alert("There was an error performing the update.")
});
}
No matter what I try, it seems that as soon as I try to execute the post, I fall straight into the 'error' clause. I've run Fiddler in the background whilst debugging the script using Internet Explorer, and there's no attempt made to hit the endpoint specified - it simply doesn't try, just errors.
I did some research, and came across a number of articles like this that suggest using XmlHttpRequest instead of trying to poke posts around the internet using jQuery, and so I tried using this instead:
function UpdateSupplierStatus()
{
var MembershipNumber = Xrm.Page.data.entity.attributes.get("membershipnumber").getValue();
var StatusCode = Xrm.Page.data.entity.attributes.get("statuscode").getText();
var Query = "?membershipNumber=" + MembershipNumber + "&statusCode=" + StatusCode;
var URL = "http://myurl.com/api/MembershipAPI/UpdateMembershipStatus";
var req = new XMLHttpRequest();
req.open("POST", URL + Query, true);
req.setRequestHeader("Accept", "application/json");
req.setRequestHeader("Content-Type", "application/json; charset=utf-8");
req.setRequestHeader("OData-MaxVersion", "4.0");
req.setRequestHeader("OData-Version", "4.0");
req.send(JSON.stringify(data));
}
Again, if I debug this it's unsuccessful, however this time it seems that the offending line is 'req.open(...' - from what I've read, the suggestion is that I can't use XmlHttpRequest to make requests to resources outside of the hosts domain. The problem here is that CRM is hosted and the related website is obviously elsewhere. There is a question around this problem that describes the 'fix' as requiring users to alter their security settings, but frankly I find this to be madness - I cannot, and will not, require my customers to alter their security settings to allow this to work.
What am I missing here? Is it really this difficult to post data to an external site using Dynamics 365, or is there some process that I'm missing that facilitates exactly this?
Edit
So I've tried testing this with a different browser and I get further using the XmlHttpRequest method than I was getting with the $.ajax method. However, I've not self-signed localhost, and our staging environment has no SSL certificate, and so I can't supply the content via HTTPS. I now have two issues:
I can't require people to not use IE
I can't easily get HTTPS working in either my development environment, or in my staging environment
I'm starting to feel more and more like this isn't a problem with Dynamics!
This is not an issue related to Dynamics 365 but related to CORS:
For security reasons, browsers restrict cross-origin HTTP requests
initiated from within scripts. For example, XMLHttpRequest and Fetch
follow the same-origin policy. So, a web application using
XMLHttpRequest or Fetch could only make HTTP requests to its own
domain.
The Cross-Origin Resource Sharing (CORS) mechanism gives web servers
cross-domain access controls, which enable secure cross-domain data
transfers. Modern browsers use CORS in an API container - such as
XMLHttpRequest or Fetch - to mitigate risks of cross-origin HTTP
requests.
More information...
You will find a lot of examples about different scenarios and different ways to perform a cross-domain request (in the previous link you will find a lot of these information).
The following it's a "simple request", which I think it will work in your scenario (the allowed methods are GET, HEAD and POST), and you can test it directly from CRM if you want (I've done it without problems as you can see in the screenshot that I've also uploaded):
function callOtherDomain() {
var req = new XMLHttpRequest();
var url = 'https://httpbin.org/get';
req.open('GET', url, true);
req.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
alert(req.responseText);
}
};
req.send();
}
This "simple request" will use CORS headers to handle the privileges:
As you can see, the server (http://myurl.com in your scenario) also has to be configured to explicitly allow cross-domain requests. You can see a very detailed tutorial to enable this option in the following MSDN article (assuming that you're using WebAPI).
Your jQuery ajax call is not working because you are not passing a function definition to your error handler, but rather executing some code (alert...) directly.
Try wrapping the code in an inline function definition like this:
$jQ.ajax({
url: 'http://myurl.com/api/MembershipAPI/UpdateMembershipStatus',
type: 'POST',
data: {
'membershipNumber' : MembershipNumber,
'statusCode' : StatusCode
},
datatype: 'json',
success: function() {},
error: function() { alert("There was an error performing the update."); }
});
Also, add this line in the beginning of your code (after the .noConflict):
$jQ.support.cors = true;
Furthermore, please make sure your webservice accepts Cross Origin Requests.To do so in your Web API project, make the following changes:
Install the Nuget Package Microsoft.AspNet.WebApi.Cors
Add the following attribute to your class:
[EnableCors(origins: "*", headers: "*", methods: "*", exposedHeaders: "")]
public class MembershipAPIController : ApiController
Add the following in your web.config under the tag:
<httpProtocol>
<customHeaders>
<add name="Access-Control-Allow-Origin" value="*" />
<add name="Access-Control-Allow-Methods" value="*" />
</customHeaders>
<httpProtocol>
The last step is needed to include both headers in the response. When these headers are missing, the response will be blocked by the browser. I'm pretty sure you're missing the xml-tags in your web.config.

CORS Post request working locally but not on server

I have two projects in the same solution. One is an ASP.NET MVC project and the other is a Web API project. On my local machine the MVC project is running on http://localhost:2302/ I have enabled CORS in the Web API project using the following code in the WebApiConfig.cs file:
namespace WebServices
{
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
var cors = new EnableCorsAttribute("http://localhost:2302", "*", "*");
config.EnableCors(cors);
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute("ActionApi", "{controller}/{action}/");
}
}
}
I also have a controller where I have a controller like the following:
namespace WebServices.Controllers
{
public class UploadController : ApiController
{
private readonly IUploadManager _uploadManager;
public UploadController(IUploadManager uploadManager)
{
_uploadManager = uploadManager;
}
[HttpPost]
public async Task<HttpResponseMessage> UploadImage()
{
var result = await _uploadManager.UploadImage(Request);
return result.Success
? Request.CreateResponse(HttpStatusCode.OK, result)
: Request.CreateResponse(HttpStatusCode.Conflict);
}
}
}
UploadImage method exists inside a repository class where I have the upload logic there. Finally I call my service using the XMLHttpRequest JavaScript object like the following:
var xhr = new window.XMLHttpRequest();
var uploadPercent;
xhr.upload.addEventListener('progress', function (event) {
var percent = Math.floor((event.loaded / event.total) * 100);
uploadPercent = percent;
}, false);
xhr.onreadystatechange = function (event) {
if (event.target.readyState === event.target.DONE) {
if (event.target.status !== 200) {
console.log('error in uploading image');
} else {
var status = JSON.parse(event.target.response);
var imageGuid = status.returnId;
var imageUrl = status.returnString;
}
}
};
xhr.open('post', 'http://localhost:4797/Upload/UploadImage', true);
var data = new FormData();
var files = $('#uploadInput')[0].files;
for (var i = 0; i < files.length; i++) {
data.append('file' + i, files[i]);
}
xhr.send(data);
The above code works good when I test it on my local machine. But when I deploy it on an actual server it does not (Of course I have changed all the links to the respective links for my domain - also the projects are deployed separately but on the same server). When the OPTIONS request is sent I receive 400 Bad Request status code. I have read a lot of information on the internet but nothing seems to help me. This is the request sent by the browser:
Accept:*/*
Accept-Encoding:gzip, deflate, sdch
Accept-Language:en-US,en;q=0.8,el;q=0.6
Access-Control-Request-Headers:content-type
Access-Control-Request-Method:POST
Connection:keep-alive
Host:api.example.com
Origin:http://example.com
Referer:http://example.com/Account/ExtraDetails/91a832ee-496c-46a7-ac4b-dfb89bbc8fc5
User-Agent:Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36
and the response received:
Cache-Control:no-cache
Content-Length:69
Content-Type:application/json; charset=utf-8
Date:Mon, 15 Dec 2014 22:42:11 GMT
Expires:-1
Pragma:no-cache
Server:Microsoft-IIS/7.5
X-AspNet-Version:4.0.30319
X-Powered-By:ASP.NET
I noticed that no Access-Control-Allow-Origin header is created in the response when the application is deployed but as far as I know it should be. Do I need to do any further configuration on the server or am I missing something? Thank you in advance.
You don't seem to be handling the preflight Options requests.
Web API needs to respond to the Options request in order to confirm that it is indeed configured to support CORS.
To handle this, all you need to do is send an empty response back. You can do this inside your actions, or you can do it globally like this:
protected void Application_BeginRequest()
{
if (Request.Headers.AllKeys.Contains("Origin") && Request.HttpMethod == "OPTIONS")
{
Response.Flush();
}
}
This extra check was added to ensure that old APIs that were designed to accept only GET and POST requests will not be exploited. Imagine sending a DELETE request to an API designed when this verb didn't exist. The outcome is unpredictable and the results might be dangerous.
Also I suggest enabling Cors by web.config instead of config.EnableCors(cors);
<httpProtocol>
<customHeaders>
<add name="Access-Control-Allow-Origin" value="*" />
<add name="Access-Control-Allow-Headers" value="Content-Type" />
<add name="Access-Control-Allow-Methods" value="GET, POST, PUT, DELETE, OPTIONS" />
</customHeaders>
</httpProtocol>
Please note that the Methods are all individually specified, instead of using *. This is because there is a bug occurring when using *.

js php, ajax remembers previously loaded content

I have the weird issue, I have been looking for the solution for a while with no result. I'm developing a website, decided to load every subpage(content) dynamically via AJAX(also .js and .css files for each subpage). Now, when I'm working on it and change scripts/css for some file and refresh the page, it doesn't load them. It's like AJAX remembers the previous version, because when I turn it all of and come back after few hours it changes (!). Any ideas for this one? I want to avoid remembering anything by site memory(or anything) so I could work on this normally. I don't use jquery, I use pure js and my own function for ajax connection, maybe I should add there something? Here it is:
function sendQuery( data )
{
var http = new XMLHttpRequest();
var url = data["url"];
var params = "";
var query = data["params"];
for(var key in query)
params+=key+"="+query[key]+"&";
params=params.substring(0,params.length-1);
http.open("POST", url, true);
http.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
http.setRequestHeader("Content-length", params.length);
http.setRequestHeader("Connection", "close");
http.send(params);
http.onreadystatechange = function()
{
if(http.readyState == 4 && http.status == 200)
{
data["result"](http.responseText);
}
}
}
Not sure entirely what you mean, but this sounds like a caching issue, why not append the current time or a similar random string to the request as a separate parameter? This level of uniqueness should prevent the request response from being cached by the browser.
e.g. '?nocache='+new Date().getTime()
You may also want to prevent the server side response from caching the content returned by the call by setting the appropriate headers (e.g.):
response.setHeader( "Pragma", "no-cache" );
response.setHeader( "Cache-Control", "no-cache" );
response.setDateHeader( "Expires", 0 );
It seems highly related with your caching policy.
If you're hosting site with apache,
Check .htaccess in your root directory you might see something like this:
# Set up 2 Hour caching on commonly updated files
<FilesMatch "\.(xml|txt|html|js|css)$">
ExpiresDefault A7200
Header append Cache-Control "proxy-revalidate"
</FilesMatch>
The setting above set expire time to 7200 seconds = 2 hours.
To disable cache under development:
# Force no caching for dynamic files
<FilesMatch "\.(xml|txt|html|js|css)$">
ExpiresActive Off
Header set Cache-Control "private, no-cache, no-store, proxy-revalidate, no-transform"
Header set Pragma "no-cache"
</FilesMatch>
Then it should works properly.
Another way is to change this line:
var url = data["url"];
To:
var url = data["url"]+"&ts="+(new Date().valueOf());
To avoid the cache. Note: it's just pseudo code. "?" Should be handled if there hasn't one.
Hope it helps :)

AJAX post error : Refused to set unsafe header "Connection"

I have the following custom ajax function that posts data back to a PHP file. Everytime the post of data happens I get the following two errors :
Refused to set unsafe header "Content-length"
Refused to set unsafe header "Connection"
Code :
function passposturl(url1, params, obj)
{
//url1 = url1+"&sid="+Math.random();
xmlHttp = get_xmlhttp_obj();
xmlHttp.loadflag = obj;
xmlHttp.open("POST", url1, true);
//alert(url1);
//alert(params);
//alert(obj);
//alert(params.length);
xmlHttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
xmlHttp.setRequestHeader("Content-length", params.length);
xmlHttp.setRequestHeader("Connection", "close");
xmlHttp.onreadystatechange = function ()
{
stateChanged(xmlHttp);
};
xmlHttp.send(params);
}
What am I doing wrong?
Remove these two lines:
xmlHttp.setRequestHeader("Content-length", params.length);
xmlHttp.setRequestHeader("Connection", "close");
XMLHttpRequest isn't allowed to set these headers, they are being set automatically by the browser. The reason is that by manipulating these headers you might be able to trick the server into accepting a second request through the same connection, one that wouldn't go through the usual security checks - that would be a security vulnerability in the browser.
Section 4.6.2 of the W3C XMLHttpRequest Level 1 spec lists headers that "are controlled by the user agent" and not allowed to be set with the setRequestHeader() method. Both Connection and Content-length are in that list.
Accept-Charset
Accept-Encoding
Access-Control-Request-Headers
Access-Control-Request-Method
Connection
Content-Length
Cookie
Cookie2
Date
DNT
Expect
Host
Keep-Alive
Origin
Referer
TE
Trailer
Transfer-Encoding
Upgrade
User-Agent
Via

Categories

Resources