-
Notifications
You must be signed in to change notification settings - Fork 795
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Question about CORS enabled images support in ESRI Leaflet #563
Comments
CORS will be automatically used IF it is supported by the browser. If it is not supported by the browser (IE 9 and 10) a JSONP fallback will be used. Their is a To see if your browser supports CORS you can check // use whatever Esri Leaflet thinks is best (based on browser support)
L.esri.get('http://watersgeo.epa.gov/arcgis/rest/services/OWPROGRAM/SDWIS_WMERC/MapServer', {}, function(error, response){console.log(error, response);});
// make a CORS request
L.esri.Request.get.CORS('http://watersgeo.epa.gov/arcgis/rest/services/OWPROGRAM/SDWIS_WMERC/MapServer', {}, function(error, response){console.log(error, response);});
// make a JSONP request
L.esri.Request.get.JSONP('http://watersgeo.epa.gov/arcgis/rest/services/OWPROGRAM/SDWIS_WMERC/MapServer', {}, function(error, response){console.log(error, response);}); |
I was able to get a CORS response from your server with the above sample code in Chrome. |
Thanks, Thanks for the fast response, |
CORS restrictions don't apply to requests for images |
@jgravois is right you can ALWAYS request images cross domain wether or not the browser supports CORS. If you want to intercept the URL of the image I think you could probally listen to the layer = L.imageLayer(url, {
opacity: 0
});
layer.on('load', function(){
// do something with layer._currentImage._url and layer._currentImage._bounds
}); |
Thanks for the explanation, This is the issue I thought I was running into when scraping off the layer._currentImage._image into a canvas When I sought to canvas.toDataURL on the canvas in order to create a file object, I would get a cross domain error. However, at this point on a Friday I realize I need to redo my example and distill out a working example of the issue. Perhaps I missed something simple.. Thanks for your time, |
Now that I see what you are doing it looks like we aren't serving images from ArcGIS Server with the proper CORS headers so you might not be able to do this. I'll need to investigate more. |
Hi John and Patrick, Came back to the issue this morning. Here is a CodePen example that more succinctly shows the problem. Now it still seems to me that all you need to do is add an Origin header with the image request and then the CORS headers return fine from AGS. But I do see that this would entail digging into Leaflet itself via ImageOverlay. Thanks, |
I took another look at this this morning. I managed to get the sample from MDN working with just a raw image request. Take a look at this JS Bin http://jsbin.com/yudeda/1/edit?html,js,output. I haven't read the spec but I'm willing to bet that you have to set So I think something like this should work:
At this point your pretty much responsible for pulling the image out of local storage and drawing it again. |
Looks like my suspicions are correct if you set |
Thanks Patrick, So the img.crossOrigin="anonymous"; triggers the Origin header in the request which then triggers the CORS headers. So then as my goal here is to steal the image directly from Leaflet, is it possible to set the crossOrigin attribute before the layer image is requested from ArcGIS Server? Cheers, |
Extending the core I think this would probably do the trick:
However this would be INCREDIBLY DANGEROUS and probably subject to breaking at every future release of Leaflet. I would probably recommend extending var MyCrazyCanvasLayer = L.esri.DymanicMapLayer.extend({
//override the _renderImage function
_renderImage: function(url, bounds) {
// 1. load image (new Image(), set crossOrigin, set src to url)
// 2. load the image into your canvas, manupulate it
// 3. export your canvas to a data uri
// 4. call the original render image function with your data URI
// call the original _renderImage function with your new manipulated data uri
// this will create a new L.ImageOverlay with your data uri as the url and
// trigger all proper behavior for showing/hiding the overlays.
// you might run into issues with the load event not firing, but I'm not sure.
// http://stackoverflow.com/questions/4776670/should-setting-an-image-src-to-data-url-be-available-immediately
L.esri.DymanicMapLayer._renderImage.call(this, dataUri, bounds);
}
}); |
@pauldzy Its worth noting this is all how it would work in theory. Can I ask WHY you might want to manipulate the image data in canvas? There might be a better solution. |
Hi Patrick, I appreciate your help, I was not going to bore you with such things. :) Well, I don't have a well thought out usage case. We have several ArcGIS Servers on several platforms under several different administrators drawing from many data sources with many layers having many possible configurations. Being able to say with any kind of assurance that the services and data on server A are equal to the services and data on server B are equal to the services and data on server C in the cloud can be time consuming and often comes down to a matter of trust over any kind of verification. I was toying with an idea of a prototype tool for sampling images from AGS and saving them to local storage for comparison between servers and between updates. In this scenario I would use Leaflet and Esri-Leafet to do all the work of showing and navigating to the images I would want to stash. As you pointed out I can still do this, I just need to fetch the image myself a second time after grabbing the src. However this then tied into to some larger issue of CORS, CORS on AGS and if I should be pressing my organization to move on from JSONP. CORS on AGS is pretty much undocumented so thanks for helping me figure it out. Cheers, |
I'm glad someone else has been trying to do this. For my app, I need to use the canvas so that I can read the color of the map pixel currently under the mouse. I've been struggling to get past this CORS issue, even after setting up the server to have the correct headers and everything. The problem does indeed seem to be that src is being set before crossOrigin on the img elements (I'm using ArcGIS JS but it seems like the same problem is in Leaflet). Using @patrickarlt's trick to create a new Image object and then drawing that to the canvas worked perfectly, and due to browser caching it's totally fast too (400~ nanos by my measurement). |
Please do. Sometimes issues can be resolved in a totally different way. It's also nice to get a view into what people are doing with the libraries and tools I am building. @pauldzy since both you and @foolmoron have pretty legit use cases for this I'm going to pass this up to the backend teams to see if this can be enabled by default in future releases. |
@foolmoron @pauldzy if it really is as fast as @foolmoron suggests I could do this automatically in |
It's fast, but it does rely on the opaque browser caching behavior that might not be consistent. It's technically a new network request too. So i think ideally you would just set the crossOrigin tag before src. But it's been been working fine for my purpose so far. |
I've opened a PR for this on Leaflet. Leaflet/Leaflet#3594 so once that gets merged in I'll update Esri Leaflet to pass the At this point it would be REALLY trivial to just add a function to grab the current pixel from the image. |
👍 As a temporary thing I'd say go for it. |
Thanks! |
safe to close after fix in 85732a5 is merged from |
Hello,
I was looking at how to provoke a CORS response from my ArcGIS servers (10.2.2 and 10.3.1) and noticing that for what I think is the default security setup that the only way to get CORS headers Access-Control-Allow-Origin and Access-Control-Allow-Credentials is to pass an Origin header in the request.
If I just submit a request for either json or an image via
http://requestmaker.com/
say
http://watersgeo.epa.gov/arcgis/rest/services/OWPROGRAM/SDWIS_WMERC/MapServer?f=pjson
the only way to get a CORS response is by adding an Origin header (asterisk does the job).
Now in Esri-leaflet I looked for somewhere that useCors: true triggers this but don't seem to see anything anywhere. Is this an option that should be supported in the library?
Thanks,
Paul
The text was updated successfully, but these errors were encountered: