How to POST data to an HTTP page from an HTTPS page - javascript

I know this is a long shot, but I figured I'd ask the question anyway.
I have an HTTPS page and am dynamically creating a form. I want to POST the form to an HTTP page. Is this possible without the browser popping up a warning? When I do this on IE8, I get the following message:
Do you want to view only the webpage content that was delivered securely?
Essentially, I'm asking about the inverse of question 1554237.

Sadly, I know of absolutely no way to not get warned when posting from HTTPS to HTTP. If you serve the form securely, the browser expects to submit the data securely as well. It would surprise the user if anything else was possible.

Nope, can't be done. Our good friend IE will always pop up that warning.

There is a way to do this if you write a back-end service of your own. So lets say you want to post an HTTP request to s1 using your front-end service fs1.
If you use Spring, you can use an ajax call from fs1 to a 'uri' that is recognized by your spring back-end, say bs1. Now, the service bs1 can make the call to the s1.
Pictorial representation here: http://i.stack.imgur.com/2lTxL.png
code:
$.ajax
({
type: "POST",
uri:/json/<methodName>
data: $('#Form').serialize(),
success: function(response)
{
//handle success here
},
error: function (errorResponse)
{
//handle failure here
}
})

You can solve this by either acting as a proxy for the form destination yourself (i.e. let the form submit to your server which in turn fires a normal HTTP request and returns the response), or to let access the page with the form by HTTP only.

If you don't need to actually redirect to the insecure page, you can provide a web service (authenticated) that fires off the request for you and returns the data.
For example:
From the authenticated page, you call doInsecure.action which you create as a web service over https. doInsecure.action then makes a manual POST request to the insecure page and outputs the response data.

You should be able to do this with the opensource project Forge, but it sounds like overkill. The Forge project provides a JavaScript interface (and XmlHttpRequest wrapper) that can do cross-domain requests. The underlying implementation uses Flash to enable cross-domain (including http <=> https) communication.
http://github.com/digitalbazaar/forge/blob/master/README
So you would load the Forge JavaScript and swf from your server over https and then do a Forge-based XmlHttpRequest over http to do the POST. This would save you from having to do any proxy work on the server, but again, it may be more work than just supporting the POST over https. Also, the assumption here is that there's nothing confidential in the form that is being posted.

Related

Make REST call in JavaScript without using JSON?

(extremely ignorant question, I freely admit)
I have a simple web page with a button and a label. When I click the button, I want to make a REST call to an entirely different domain (cross-domain, I know that much) and display the results (HTML) in the label.
With other APIs, I've played around with using JSON/P and adding a element on the fly, but this particular API doesn't support JSON so I'm not sure how to go about successfully getting through.
The code I have is:
function getESVData() {
$.get('http://www.esvapi.org/v2/rest/passageQuery?key=IP&passage=John+1', function (data) {
$('#bibleText').html(data);
app.showNotification("Note:", "Load performed.");
});
}
I get an "Access denied." Is there anyway to make this call successfully without JSON?
First off, JSON and JSONP are not the same. JSON is a way of representing information, and JSONP is a hack around the same-origin policy. JSONP works by requesting information from another domain, and that domain returns a script which calls a function (with the name you provided) with the information. You are indeed executing a script on your site that another domain gave to you, so you should trust this other domain.
Now when trying to make cross domain requests you basically have 3 options:
Use JSONP. This has limitations, including the fact that it only works for GET requests, and the server you are sending the request to has to support it.
Make a Cross Origin Resource Sharing (CORS) request. This also must be supported by the server you are sending the request to.
Set up a proxy on your own server. In this situation you set an endpoint on your site that simply relays requests. ie you request the information from your server, your server gets it from the other server and returns it to you.
For your situation, it the other server doesn't have support for other options, it seems like you will have to go with options 3.

jQuery cross domain image upload

Ok, so basically.
I inject some javascript code into a web page and it uploads an image on that page to another server.
Now I have it working when I run it on my domain (of course), but I need to post the multipart/form-data request to a PHP file that I do not own.
Since it is a upload and not a simple request to just get data, I cannot use jsonp in the initial call since the response would not be in json.
Using James Padolsey's cross domain script, I am able to do $.get and $.post request across domains, but since I am using $.ajax it does not work.
He uses the Yahoo Query Language to acomplish this
This is basically how I am making the request
$.ajax({
url: 'http://website.com/upload.php',
type: 'POST',
contentType:'multipart/form-data',
data: postData,
success: successCallback,
error : function(XMLHttpRequest, textStatus, errorThrown) {
console.log('Error');
}
});
I want to make it completely JavaScript based to avoid making my server do the request.
So to re-cap, I can get the image bytes and make the request with javascript. But so far I cannot make it cross domain since I am $.ajax to set the content Type to "multipart/form-data".
Is there another way to make the request cross domain with or without the YQL?
Making the request with an iframe will not work since the domain of the iframe would change and I would not have access to the response.
This is a well known and difficult problem for web development, know as the Same Origin Policy
Javascript prevents access to most methods and properties to pages across different origins. The term "origin" is defined using the domain name, application layer protocol, and (in most browsers) port number of the HTML document running the script. Two resources are considered to be of the same origin if and only if all these values are exactly the same.
There are several ways around this.
Create your own proxy
Create a page that simply forwards the request to the other server, and returns its response
or, Use Apache's rules to form a proxy (see above link)
Use someone else's proxy
For GET requests which are typical Use YQL to access yahoo's proxy
For POST requests, if the 3rd party supports Open Data Tables
or, Use some other public proxy
See if the 3rd party conforms to the CORS specification
Cross domain POST query using Cross-Origin Resource Sharing getting no data back
If you are willing to allow a little flash on your page, try flXHR
it claims to implement the exact XHR api and also has a jquery plugin
These are pretty much your only options

How to prevent ajax requests to follow redirects using jQuery

I use the jQuery ajax functions to access a web service, but the server, instead of returning a response with a status code describing a problem, the request is redirected to a page with a 200 header, describing the problem. I can't make any changes to this, so I need to solve it on the client somehow.
Example:
A request goes to some URL which is not found, so I receive a 302 Redirect to another location. A new request is sent, and I receive a 200 OK, thus preventing the error callback to fire.
Is there some way I can prevent the ajax request to follow redirects and instead invoke a callback, preferably the error method. Alternatively, is it possible to detect if a redirect has happened in the client?
I find your question interesting, but the problem in whole seems me more a misunderstanding. At least I'll try to explain my understanding of the problem.
The silent (transparent) redirection is the part of XMLHttpRequest specification (see here especially the words "... transparently follow the redirect ..."). The standard mention only that the user agent (the web browser) can prevent or notify of certain kinds of automatic redirections, but it's not a part of XMLHttpRequest. It's the part of HTTP client configuration (OS configuration) or the web browser configuration. So jQuery.ajax can't have any option where you can prevent redirection.
You can see that HTTP redirection is the part of HTTP protocol and not a part of XMLHttpRequest. So it's on the another level of abstraction or the network stack. For example the data from the XMLHttpRequest can be retrieved from the HTTP proxy or from the local browser cache, and it's the part of HTTP protocol. Mostly the server which provide the data and not the client can influence on caching.
You can compare the requirement from your question with the requirement to prevent changing of IP address of the web server or the changing of the IP route during the communication. All the things can be interesting in some scenarios, but there are parts of another level of the communication stack and can't be managed by jQuery.ajax or XMLHttpRequest.
The XMLHttpRequest standard say that the client configuration can have options which prevent redirection. In case of "Microsoft world", which I better know, you can look at WinHttpSetOption function which can be used to set WINHTTP_OPTION_DISABLE_FEATURE option with the WINHTTP_DISABLE_REDIRECTS value. Another way are the usage of WINHTTP_OPTION_REDIRECT_POLICY option with the WINHTTP_OPTION_REDIRECT_POLICY_NEVER value. One more feature which one can use in Windows is the WinHttpSetStatusCallback function which can set callback function received some notifications like WINHTTP_CALLBACK_FLAG_REDIRECT.
So it's do possible to implement your requirements in general, but the solution will be probably not independent from the operation system or the web browser and be not on the level of jQuery.ajax or XMLHttpRequest.
I don't believe it is possible. The underlying library (XHR) makes the new request transparently. That being said, what I have done in these situations (usually a session-timeout type of deal that takes me to a login page) is send back a custom response header. I also have setup a global ajax handler that checks for the presence of that header, and responds appropriately when present (for example, redirecting the whole page to the login screen).
In case you're interested, here's the jQuery code I have to watch for that custom header:
/* redirects main window when AJAX request indicates that the session has expired on the backend. */
function checkSession(event, xhr, ajaxOptions)
{
if (xhr.readyState == 4)
{
if(xhr.getResponseHeader("Login-Screen") != null && xhr.getResponseHeader("Login-Screen").length)
{
window.location.href='sessionExpired.html'; //whatever
}
}
}
$(document).ajaxComplete(checkSession)
I found a feature to check if your call has been redirected. It's xhr.state(): if it's "rejected" then a redirection happened.
Example with success callback:
request.success(function(data, textStatus, xhr)
{
if(xhr.state() == "resolved")
{
//no redirection
}
if(xhr.state() == "rejected")
{
//redirection
}
});
Example with error callback:
request.error(function(xhr, textStatus)
{
if (xhr.state() == "rejected")
{
//redirection
location.href = "loginpage";
} else
{
//some other error happened
alert("error");
}
});
I can't possibly add to the insightful wisdom of the previous coders who've responded, but I will add a specific case that others may find useful to know about.
I came across this 302 silent redirect in the context of SharePoint. I have some simple Javascript client code that pings a SharePoint sub-site, and if it receives a 200 HTTP response, it relocates to that site, via window.location. If it receives anything else, it gives the user a notice that the site doesn't exist.
However, in the case where the site exists but the user does not have permission, SharePoint silently redirects to an AccessDenied.aspx page. SharePoint has already done the HTTP 401 authentication handshake at the server/farm level - the user has access to SharePoint. But the access to the sub-site is handled I suppose using database flags of some sort. The silent redirect bypasses my "else" clause, so I can't throw up my own error. In my case, this is not a show-stopper - it is consistent predictable behavior. But it was a little surprising, and I learned something about HTTP requests in the process!
I was interested in the same thing and could not find the state() method mentioned by Takman and did a little digging for myself. For the sake of people turning up here in search of an answer, here are my findings:
As stated multiple times, you cannot prevent redirects, but you can detect them. According to MDN you can use the responseURL of the XMLHttpRequestObject, which will contain the final URL the response came from, after all redirects. Only caveat is that it is not supported by Internet Explorer (Edge has it). Since the xhr/jqXHR passed into the success/done function of jquery is an extension of the actual XMLHttpRequest, it should be available there, too.
While it is not possible to disable location redirect following in XmlHttpRequests, it is when using fetch():
fetch('url', {redirect: manual});
I suppose you receive a 200 response because the second time there is no redirection, because the 404 page does not expire, it is saved in the cache. That is to say that the second time the browser gives you the page in the cache.
There is a property "cache" in the ajax jquery.
http://api.jquery.com/jQuery.ajax/
You should write it to "false"
I'm not sure if this will apply in your case, but you can write code to respond to specific status codes in AJAX function -
$.ajax({
url: '/admin/secret/data',
type: 'POST',
contentType: 'application/json; charset=utf-8',
statusCode: {
200: function (data) {
alert('302: Occurred');
// Bind the JSON data to the UI
},
401: function (data) {
alert('401: Occurred');
// Handle the 401 error here.
}
}
});
In the request headers in the case of ajax request you will have the following
X-Requested-With XMLHttpRequest
By this criteria on the server side you can filter requests.

How to do cross domain ajax in jQuery with dataType 'text'?

In my javacript function I call this ajax. It works fine but only when I access the web page from firebird server. I have the same code on my testing server. The ajax asks to download some files but only firebird server has its ip registers with our clients to be able to scp there. I need to do the same if I access the php files from testing server. All the servers are inside intranet.
is it possbile to use dataType text to do so?
do I need to do any changes on the server side?
ajax call:
url = "https://firebird"+path+"/tools.php?";
jQuery.ajax({
type: 'get',
dataType: 'text',
url: url,
data: {database: database_name, what: 'download', files: files, t: Math.random() },
success: function(data, textStatus){
document.getElementById("downloading").innerHTML+=data;
}
});
Update 1
My little web application restores databases so I can do my testing on them. Now I want to enhance it so I can connect to our customers and download a particular backup. Our customer allowed only firebird server to connect to their networks. But I have my own server dedicated to testing. So every time I want to download a database I need to connect firebird. The source of my web application and the folder with all backups are mounted into the same location on both servers firebird and testing. Right now my solution (for downloading) works but only from firebird. I work basically only testing server though.
Update 2
I make two ajax calls. One is pure jQuery call (I guess I can apply any solution to this one) and the other one is ajax call from jsTree. I created new question for that one. I seems to me that I have to go for #zzzz's option b).
To do cross domain requests, your options are fairly limited. As #Mrchief mentioned, you could do server side proxy and jsonp.
Another option is Cross-Origin Resource Sharing (CORS), a W3C working draft. Quoting from this blog post:
The basic idea behind CORS is to use custom HTTP headers to allow both
the browser and the server to know enough about each other to
determine if the request or response should succeed or fail.
For a simple request, one that uses either GET or POST with no custom
headers and whose body is text/plain, the request is sent with an
extra header called Origin. The Origin header contains the origin
(protocol, domain name, and port) of the requesting page so that the
server can easily determine whether or not it should serve a response.
You can find some live examples on this site.
You will need to make changes to the server side, to accept the CORS requests. Since you have control over the server, this shouldn't be a problem. Another downside with CORS is that, it might not be compatible with older browsers. So, if some of your essential audiences use incompatible browsers, the server side proxy may actually be a better option for you.
I just want to offer an alternative.
I am not too sure regarding your network setup, but if you have access to the DNS, maybe it would be easiest if you just give your servers some arbitrary subdomain of the same domain. Something like www.foo.com for the webfront and firebird.private.foo.com for the firebird server. This way, it becomes cross subdomain instead of cross domain. Then somewhere in your JavaScript on both pages,
document.domain = "foo.com";
This gentleman achieved this solution here.
You have the following options with you
a) You use jsonp type as your datatype but this involves making changes on the server side to pass the data back as json and not as txt.. this change might be as simple as
{
"text":<your current text json encoded>
}
and on your js side you use this as response.text; Having said that if you are getting the textis for you file from sm other domain I am not sure how easy it is for you to change the code.
b) The other option is you write a handler/end point on your server i.e within your domain that will make an HTTP request to this third domain gets the file and you send the file back to your client and effectively now your client talks to your domain only and you have control over everything. as most of yoyr questions are based on ruby here is an example:
req = Net::HTTP.get_response(URI.parse('http://www.domain.com/coupons.txt'))
#play = req.body
you can find more details about the same here.
Hope this helps.
Another idea is to use you web server as a proxy. You will need to consider the security implications for this route.

Sending POST message with AJAX Problem

I am currently trying to send a POST message which works fine except for the error that there are not correct credentials. However, after I add the credentials header, the message type is changed into OPTIONS and fails. I do not understand how adding a header causes the type to change to OPTIONS. Any help would be appreciated.
ajaxRequest = $j.ajax({
url: url,
type: 'POST',
beforeSend : function(req) {
req.setRequestHeader('Authorization', auth),
}
success: function(data, status) {
console.log("Success!!");
console.log(data);
console.log(status);
},
error: function(xhr, desc, err) {
console.log(xhr);
alert('fail')
console.log("Desc: " + desc + "\nErr:" + err);
}
});
EDIT: just to be more clear, I can literally go in and comment out the setRequestHeader function and it sends the message POST.
The problem you're encountering is because of cross-domain restrictions when using AJAX. When you try to set an authorization header, the browser issues what's known as a pre-flight request to see if the server will accept requests from this domain.
A pre-flight request is typically sent as an OPTIONS request. If the server you're invoking doesn't return an Access-Control-Allow-Origin header that matches your domain, the AJAX request is blocked.
There's more on this here: Cross-Origin Resource Sharing
"User agents can discover via a preflight request whether a cross-origin resource is prepared to accept requests, using a non-simple method, from a given origin."
I've run into the same problem- there are a few possible workarounds depending on your scenario.
If you have any way of setting the above mentioned header on the 3rd party server (some applications/services offer this) then that's probably the easiest way.
There's also a javascript library called EasyXDM that may work for you, but again, it will only be of use if you have access to the 3rd party server to upload a configuration file for this library.
Other options to investigate are PostMessage and Cross Domain Iframe communication. The latter is more of an old-school hack, the former is the recommended approach for newer browsers. It won't work for IE6/7.
The option we will probably end up using is a simple proxy- invoke our own server with the AJAX request, and on the server invoke the 3rd party server. This avoids the cross domain issue entirely, and has other advantages for our scenario.
I guess this is a problem in Internet Explorer. without explicitly telling the request-method (POST|GET) the request header doesn't contain the custom-header in IE, but it works in other browsers.
Yet try to post this in the bugs for jquery. Also try in other browsers.
Edit 1 : I saw this as a bug in jQuery 1.4.x .... I reported a bug report now.
The OPTIONS response happens when the server does not know how to respond to the ajax request.
I've seen it happen often when trying to post to a third-party domain (i.e. cross-site posting)
The OPTIONS method represents a request for information about the communication options available on the request/response chain identified by the Request-URI. This method allows the client to determine the options and/or requirements associated with a resource, or the capabilities of a server, without implying a resource action or initiating a resource retrieval.
Have you tried:
Having some sort of callback on the url that is being posted to?
Explicitly setting the headers (I'm assuming you're using PHP) on the url that is being posted to?

Categories

Resources