Vimeo CORS Issue - ajax

I am trying to upload a video to Vimeo via Ajax but I am running into CORS problems with Firefox.
Here is the code I am using. It is only at the last stage of posting the file does CORS protection prevent the upload.
I have checked the headers and Cross Origin is set correctly.
$.ajax({
url:'https://api.vimeo.com/me',
crossDomain:true,
headers:{Authorization: 'bearer ',Accept:'application/vnd.vimeo.*+json;version=3.2'},
error:function(){
videoError('Couldn\'t get a quota');
},
success:function(uploadQuota){
if(uploadQuota.upload_quota.space.free > 0 && (uploadQuota.upload_quota.quota.sd == true || uploadQuota.upload_quota.quota.hd == true)){
//Get Upload Ticket
$.ajax({
url:'https://api.vimeo.com/me/videos',
data:{type:'POST'},
type:'POST',
dataType:'json',
crossDomain:true,
headers:{Authorization: 'bearer ',Accept:'application/vnd.vimeo.*+json;version=3.2'},
error:function(){
videoError('Couldn\'t get a ticket');
},
success:function(uploadTicket){
if(uploadTicket.ticket_id != ''){
//Upload File
var videoData = new FormData();
$.each($('#video_upload')[0].files, function(i, file) {
videoData.append('file_data', file);
});
$.ajax({
url:uploadTicket.upload_link_secure,
type:'POST',
headers:{Authorization: 'bearer ',Accept:'application/vnd.vimeo.*+json;version=3.2'},
data: videoData,
cache: false,
contentType: 'multipart/form-data',
processData: false,
crossDomain:true,
//dataType:'jsonp',
error:function(){
videoError('Error uploading video. Please contact FDN with the ticket id:'+uploadTicket.ticket_id);
},
success:function(uploadData,status){
//Copy id to text box
}
});
} else {
//If none, process error
}
}
});
} else {
//If none, process error
}
}
});
Is there anything obvious that I have missed or can try?

Short Answer: Vimeo POST uploads were not designed for client side JavaScript. The PUT upload system has 100% support for CORS.
Long Answer:
Vimeo POST uploads were developed to provide an incredibly easy upload experience. We give you a form. You put the form in the html of your page, The user uses the form, and everything is set. This does not support progress bars. This is not resumable.
When uploading videos, we must perform some post-processing before the video will become available. The current POST upload system handles this automatically, by redirecting the client after the upload is complete. Unfortunately there are some problems with CORS and redirects (I'm having trouble finding the details, but if I remember right the spec states to handle certain redirects as an error case).
Right now you must complete the upload yourself. We are working on improving this, but for the moment you have to find the url in the "location" header of the response from your POST. Make a GET request to this url and your upload will be complete.
Vimeo PUT uploads were designed as the fully featured advanced upload system. They are resumable, the streaming design easily supports progress bars. You can query the status of the upload, and start and stop everything on command. CORS is 100% supported. This will require use of the HTML5 file object, which has limited support for ie 9 and lower.
[Edit] There is now an unofficial Client side video upload script for the streaming workflow. You can find it here: https://github.com/websemantics/vimeo-upload

As #Dashron mentioned, the "Simple HTTP POST uploading" should be used for simple cases. For example, if you want to resume an upload you should use the "Resumable HTTP PUT uploads".
However, there are two pieces of information missing on almost all references to similar problems that I would like to share.
1) Be Careful when using vimeo-upload
As #PaulLoomijmans mentioned in a comment to #Dashron the vimeo-upload (github.com/websemantics/vimeo-upload) requires you to expose your token, which is not good for security reasons.
I actually just left a suggestion in the repository that it would still be very useful if we were able to use it with an upload_url from vimeo since then we would not have to expose our token.
2) You can check upload progress using the POST upload method
If like myself, you just want to be able to report to the user the upload progress while using the simplified upload process of the "Simple HTTP POST uploading" you can actually do so without the PUT method.
Even though not clearly documented, when using the "Simple HTTP POST uploading" you also have an "upload_link_secure" in the initial response (https://developer.vimeo.com/api/upload/videos#generate-an-upload-ticket) and you can use this as you would to with the "Resumable HTTP PUT uploads" to check your upload progress.
As such, even when using "Simple HTTP POST uploading" you can follow the information on "verify the upload" from "Resumable HTTP PUT uploads" (here: https://developer.vimeo.com/api/upload/videos#verify-the-upload). Probably the resume functionality described there will not work but you can check the upload progress and show it to the user while the upload is being made. I actually implemented it to show a progress bar in my webapp.
I hope this helps someone, as I went back and forth between the two upload methods due to the limitations/complexity that each entails.

Related

Shopify app with proxy extension POST requests not working

Following the guide here: https://shopify.dev/tutorials/display-data-on-an-online-store-with-an-application-proxy-app-extension
GET requests are working fine for me.
But when I try to do a POST request, my parameters are not coming through.
I'm building a simple wishlist app, where a user can click on a heart on a product and it adds it to a database.
So my code, when they click the heart, looks something like this:
$.ajax({
url: '/apps/wishlist/save',
type: 'POST',
data: {
shop: shop,
customerId: customerId,
productId: productId
},
dataType: 'json',
success: function (data) {
console.info(data);
}
});
When I inspect this post in Network tab in Chrome Dev Tools, the original POST is hitting a 301, then Shopify is creating a GET request to the original URL with different/missing parameters that look like this:
shop: example.myshopify.com
path_prefix: /apps/wishlist
timestamp: 1585769299
signature: examplesignature
If I change my original AJAX request to a GET, then my original parameters are passed as expected.
Are POST requests not allowed here?
Try to add / to the end of your url i.e. change it to /apps/wishlist/save/.
Just to give a clearification.
Vladimir answer works, why?
It seems that Shopify changed their authentication flow for some POSTs request.
You have to send requests without cookies or you can send requests with X-Shopify-Access-Token header and use your app's password for it. They should work both but there are some cases of use that doesn't permit you to send request without cookie or only uses basic auth (depending on wich method and software you use to send request). Shopify's devs are not crazy of course, this was implemented due to avoid some kind of hackers attack based on specific attacking methods, but maybe it should be better clearly specified in their documentation. Even if the solution explained above should be preferred, as said it could not work in some cases so the Vladimir 's solution is a valid alternative (you could also add a dot at the end of the URL so for example: www.example.com./etc/etc), this because this way "blocks" the cookie seending.
You can know more about that following Sopify's community discussion here

cross domain request with dojo

I am attempting a cross domain request with dojo. External url is of MIME type text/html the only content on the page is something like 1236. I tried
dojo.require("dojo.io.script");
dojo.ready(function() {
dojo.io.script.get({
url: "theexternalurl",
callbackParamName: "jsoncallback",
load: function(data) {
console.log(data);
}
});
});,
But that was no good. Any ideas on how this can be done with dojo?
I suspect you are bumping into the browser security here. Cross-domain requests will only work when using iframes or injecting scripts (as you have done) and when the content of that script is valid "text/javascript".
If you are trying to load "text/html" into the script, it won't work as it isn't a valid script. It is something most of us have tried to do at some point. I have spent hours trying to get around cross-domain restrictions and found the security blocking it to be solid.
See my answer here for more details.
If all you are trying to do is load the content onto the page then you could use an <iframe>. However, if you are trying to parse the loaded content in some way than I'm afraid it is a dead-end. Probably not the answer you were hoping for but it'll save you hours of frustration.

Screen scraping and proxies using Ruby

I know there are several screen scraping threads on here but none of the answers quite satisfied me.
I am trying to scrape the HTML from an external web page using javascript. I am using $.ajax and everything should work fine. Here is my code:
$.ajax({
url: "my.url/path",
dataType: 'text',
success: function(data) {
var myVar = $.get(url);
alert(myVar);
}
});
The only problem is that it is looking for the specified url within my web server. How do I use a proxy to get to an external web page?
Due to Cross Site Scripting restrictions, you're going to have to pass the desired URL to a page on your server that will query the URL in question from serverside, and then return the results to you. Take a look at the thread below and the incorporate that into your application and have it return the source when that page is hit by your AJAX function.
How to get the HTML source of a webpage in Ruby
Using a GET request is going to the be easiest way to transfer the URL of the page you want to fetch your server so you'll be able to call something like:
$.ajax("fetchPage.rb" + encodeURI(http://www.google.com))
Because you can't access the side in question directly from the server, you're going to have to pipe the serverside script through a proxy for the request to work, which really kind of depends on your setup. Taking a look at the Proxy class in Ruby:
http://ruby-doc.org/stdlib-1.9.3/libdoc/net/http/rdoc/Net/HTTP.html#method-c-Proxy

jquery $.ajax() in safari and chrome doesn't work

I want use $.ajax to read some infomation from xml file,here is my js code :
$.ajax({
type: "get",
url: "Database/App_all.xml",
dataType: "xml",
timeout: 2000,
beforeSend: function () {
},
success: function (xml) {
$(xml).find("app[id='id-1']").appendTo($("#contain"));
},
error: function () {
alert("ajax failed!");
}
});
However, the code only work great in firefox and opera.
It doesn't work in chrome(7.0.517.24 ) and safari(5.0.1),failed without any alert,not even the alert("ajax failed").
Is there any bug in $.ajax in chrome and safari?so how to solve the problem?
thank you very much:)
You should use chrome's or safari's built-in developer tools (ctrl+shift+i) to track JS errors and track actual AJAX requests.
Is your code wrapped in document.ready? Is there any erros in javascript console? Also try to output something after success callback line.
Another cause for this could be incorrect mime-type for your XML file returned by server. It should be [Content-type: text/xml]. You can check that in chrome's or safari's built-in developer tools - just look for headers tab when xml resource is selected. If it 's actual problem, you may need to tweak web-server configuration (main config or .htaccess for apache) to return correct mime-type.
First thank you gajendra.bang and Māris Kiseļovs give me your advices,I have konw what's wrong with my code,after I get a bad resault ,I trying to know what the $.ajax get from xml exactly,so I use firebug check the div#contain I found that:
 <div id="contain">
<auther>cocept</auther>
 </div>
yes,I think the <auther></auther> must the problem,I don't even konw the $.ajax would get the tagname as well
so I rewrite it :
success: function (xml) {
$("#contain").html($(xml).find("app[id='id-1']").find("auther").text());
}
then the div$contain is:
 <div id="contain">
cocept
 </div>
so ,the chrome and safari could show again!
I suppose you have problem with reading of the local file per ajax. Ajax can be used to read a file from the same web server, but there are some security restriction if you read it not per HTTP.
In firefox and opera you can read local files (with url like file:///C:/Program%20Files/My/Database/App_all.xml) per ajax without any problem.
In Internet Explorer you should use dataType: 'text' and then convert the text to XML (read more here).
To be able to read local files in Chrome you have to restart chrome with another parameters:
chrome.exe --allow-file-access-from-files
(Be sure that all other instances of chorme closed before starting Chrome.exe in the way).
This is a problem for local files... You should try uploading them on a web server and check from there
$(xml).find("app[id='id-1']").appendTo($("#contain"));
what is xml basically returning, an element with "#" like "#mydiv" or class like ".mydiv"
I think you are trying to access an element and if you are not returning it with "#", try
$("#"+xml).find("app[id='id-1']").appendTo($("#contain"));

JQuery .ajax request does not hit the server

I am making an ajax request using JQuery that looks like this:
var data = createXMLdata();
$.ajax({
url: 'http://localhost:8080/foo/bar',
type: "PUT",
data: data,
processData: false,
contentType: "application/text",
error: function(xhr, status, error) {
alert("Error: " + status);
},
success: function() {
alert("Success!");
}
});
When the code executes, I get the success alert, but the service is never executed on the server!
Here's some more data:
If I make the same request using a separate REST client, the service is executed correctly
If I shut down the server (nothing is running) so that hitting that URL gives me a 404, I still get a success message.
I have tried replacing the data with "foo". This works from the REST client, but gives the same result from the code.
Any ideas are greatly appreciated!
The documentation about .ajax()'s type attribute says:
The type of request to make ("POST" or "GET"), default is "GET". Note: Other HTTP request methods, such as PUT and DELETE, can also be used here, but they are not supported by all browsers.
So probably your browser does not support PUT and the data is sent via POST instead (and therefore not recognized by your service).
Use Firebug or similar to find out which method is used.
One idea to make it working:
Send the data using POST but add an additional field e.g. __http_method=PUT. On the server side, your service has to recognize this and perform the PUT functionality.
This might be not the nicest solution but it is also used by other frameworks I have encountered (e.g. symfony for PHP).
PUT isn't supported by all browsers
Nick Craver made a comment on my question:
Is the page you're running this in served from port 8080?
It turns out this led to me solving the problem. When both the app and the service were hosted on the same server (and port), the problem went away.
This post suggests that if I comment answers the question, and the commenter does not re-post as an answer, I am to post my own answer and accept it. Nick, if you return to post this as an answer, I will accept it over my own.

Resources