由于 MIME 类型与传单地图不匹配,资源被阻止
Resource blocked due to MIME type mismatch with leaflet map
我创建了一张传单地图,我想在上面绘制 this NOAA map server 的河道状态。当我最初加载我的地图时,我在控制台中看到所有相关标记,没有任何错误。但是,如果我开始在地图上平移(结果加载更多标记),则无法加载这些点。如果我删除并 re-add 图层,则同上。
在我的控制台中,我看到以下错误。 Chrome 给我:
Request.js:187 Cross-Origin Read Blocking (CORB) blocked cross-origin response https://idpgis.ncep.noaa.gov/arcgis/rest/services/NWS_Observations/ahps_riv_gauges/MapServer/0/query?returnGeometry=true&where=1%3D1&outSR=4326&outFields=*&inSr=4326&geometry=%7B%22xmin%22%3A-90%2C%22ymin%22%3A40.979898069620155%2C%22xmax%22%3A-67.50000000000001%2C%22ymax%22%3A55.7765730186677%2C%22spatialReference%22%3A%7B%22wkid%22%3A4326%7D%7D&geometryType=esriGeometryEnvelope&spatialRel=esriSpatialRelIntersects&geometryPrecision=6&resultType=tile&f=geojson&callback=window._EsriLeafletCallbacks.c56 with MIME type text/plain. See https://www.chromestatus.com/feature/5629709824032768 for more details.
Firefox 也引发错误:
The resource from “https://idpgis.ncep.noaa.gov/arcgis/rest/services/NWS_Observations/ahps_riv_gauges/MapServer/0/query?returnGeometry=true&where=1%3D1&outSR=4326&outFields=*&inSr=4326&geometry=%7B%22xmin%22%3A-90%2C%22ymin%22%3A55.7765730186677%2C%22xmax%22%3A-67.50000000000001%2C%22ymax%22%3A66.51326044311188%2C%22spatialReference%22%3A%7B%22wkid%22%3A4326%7D%7D&geometryType=esriGeometryEnvelope&spatialRel=esriSpatialRelIntersects&geometryPrecision=6&resultType=tile&f=geojson&callback=window._EsriLeafletCallbacks.c7” was blocked due to MIME type (“text/plain”) mismatch (X-Content-Type-Options: nosniff).
在这两种浏览器中,我都可以加载我的地图的初始视图,但是一旦它被加载并开始与之交互,我就开始遇到这些错误。
我大致理解是 X-Content-Type-Options 导致了我这个问题。如果我查看 Firefox 中的响应 headers,我可以确认 x-content-type-options
是 nosniff
并且 content-type
是 text/plain; charset=UTF-8
。
由于我无法控制服务器,因此无法直接影响响应 headers,我可以做些什么来克服这种行为吗?
我创建了一个可以重现错误的工作 CodePen here。实际的 CodePen 控制台不会显示错误,但如果您打开浏览器控制台,它会如广告所示显示。
相关代码如下:
HTML
<head>
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.6.0/dist/leaflet.css"
integrity="sha512-xwE/Az9zrjBIphAcBb3F6JVqxf46+CDLwfLMHloNu6KEQCAWi6HcDUbeOfBIptF7tcCzusKFjFw2yuvEpDL9wQ=="
crossorigin=""/>
<script src="https://unpkg.com/leaflet@1.6.0/dist/leaflet.js"
integrity="sha512-gZwIG9x3wUXg2hdXF6+rVkLF/0Vi9U8D2Ntg4Ga5I5BZpVkVxlJWbSQtXPSiUTtC0TjtGOmxa1AJPuV0CPthew=="
crossorigin=""></script>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
<script src="https://kit.fontawesome.com/369cdded93.js" crossorigin="anonymous"></script>
<script src="https://unpkg.com/esri-leaflet@2.4.1/dist/esri-leaflet.js"
integrity="sha512-xY2smLIHKirD03vHKDJ2u4pqeHA7OQZZ27EjtqmuhDguxiUvdsOuXMwkg16PQrm9cgTmXtoxA6kwr8KBy3cdcw=="
crossorigin=""></script>
<script src="https://unpkg.com/esri-leaflet-renderers@2.0.6"></script>
</head
<body>
<div class="col-xl-9 m-0 p-0" id="mapdiv">
<div id="mapid"></div>
</div>
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script>
</body>
CSS
body {
background-color: rgb(25,26,26);
}
#mapid {
height:100vh;
width: 100vw;
}
Javascript
var mymap = L.map('mapid', {
center: [63.2008, -155.00],
zoom: 5,
dragging: !L.Browser.mobile,
tap: !L.Browser.mobile,
scrollWheelZoom: false,
});
L.tileLayer('https://{s}.tile.jawg.io/jawg-dark/{z}/{x}/{y}{r}.png?access-token={accessToken}', {
attribution: '<a href="https://www.jawg.io" title="Tiles Courtesy of Jawg Maps" target="_blank">© <b>Jawg</b>Maps</a> © <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors',
minZoom: 0,
maxZoom: 22,
subdomains: 'abcd',
accessToken: 'shsyk3yIdzeeE6ZnSv1Da78AItybRtOzvOvOgxaYEJBScuSbR7d2LbMsIKOw1dqN'
}).addTo(mymap);
var riverGauges = L.esri.featureLayer({
url: 'https://idpgis.ncep.noaa.gov/arcgis/rest/services/NWS_Observations/ahps_riv_gauges/MapServer/0',
ignoreRenderer: false,
useCors: false,
cacheLayers: true,
onEachFeature: function(feature, layer) {
layer.feature.properties.gaugelid = layer.feature.properties.gaugelid.toLowerCase();
layer.feature.properties.url = "https://water.weather.gov/resources/hydrographs/" + layer.feature.properties.gaugelid + "_hg.png";
layer.bindPopup(function(layer) {
return L.Util.template(
`<iframe style="border:none; height:100%; width:100%;" src={url}></iframe>
`
,layer.feature.properties)
},
{
minWidth: 600,
})
},
/*
pointToLayer: function(feature, latlng) {
return L.marker(latlng, {icon:floodIcon});
},*/
attribution: 'River Gauges: <a href="https://water.weather.gov/ahps/region.php?state=ak" target="_blank">NWS/NOAA</a>',
}).addTo(mymap);
let overlays = {};
let points = {
"River Gauges" : riverGauges
};
L.control.layers(overlays, points).addTo(mymap);
郑重声明,因为我知道这会让人们烦恼:我在这里使用的访问令牌只是针对此问题的临时访问令牌。一旦不再需要它,我会撤销它。
我能想到的最佳解决方案是从 featureLayer
更改为 dynamicMapLayer
。然而,这需要一些权衡:
缺点
- 无法自定义图标
- 很难用 css
设计风格
优点
- 加载速度更快
- 没有 MIME 类型或 CORB 问题
let riverGauges = L.esri.dynamicMapLayer({
url: 'https://idpgis.ncep.noaa.gov/arcgis/rest/services/NWS_Observations/ahps_riv_gauges/MapServer',
useCors: false,
f: 'image',
layers: [0],
layerDefs: {0:
"status IN ('no_flooding') AND state='AK'", //"status IN ('major', 'moderate', 'minor', 'action') AND state='AK'"
},
disableCache: false,
attribution: 'River Gauges: <a href="https://water.weather.gov/ahps/region.php?state=ak" target="_blank">NWS/NOAA</a>',
}).addTo(mymap);
riverGauges.bindPopup(function(error, featureCollection) {
if (error || featureCollection.features.length === 0) {
return false;
} else {
let gaugelid = featureCollection.features[0].properties.gaugelid.toLowerCase();
let url = "https://water.weather.gov/resources/hydrographs/" + gaugelid + "_hg.png";
return L.Util.template(
`<iframe style="border:none; height:465; width:600;" src={url}></iframe>`,
{'url':url}
);
}},
{
minWidth: 600,
},
);
我创建了一张传单地图,我想在上面绘制 this NOAA map server 的河道状态。当我最初加载我的地图时,我在控制台中看到所有相关标记,没有任何错误。但是,如果我开始在地图上平移(结果加载更多标记),则无法加载这些点。如果我删除并 re-add 图层,则同上。
在我的控制台中,我看到以下错误。 Chrome 给我:
Request.js:187 Cross-Origin Read Blocking (CORB) blocked cross-origin response https://idpgis.ncep.noaa.gov/arcgis/rest/services/NWS_Observations/ahps_riv_gauges/MapServer/0/query?returnGeometry=true&where=1%3D1&outSR=4326&outFields=*&inSr=4326&geometry=%7B%22xmin%22%3A-90%2C%22ymin%22%3A40.979898069620155%2C%22xmax%22%3A-67.50000000000001%2C%22ymax%22%3A55.7765730186677%2C%22spatialReference%22%3A%7B%22wkid%22%3A4326%7D%7D&geometryType=esriGeometryEnvelope&spatialRel=esriSpatialRelIntersects&geometryPrecision=6&resultType=tile&f=geojson&callback=window._EsriLeafletCallbacks.c56 with MIME type text/plain. See https://www.chromestatus.com/feature/5629709824032768 for more details.
Firefox 也引发错误:
The resource from “https://idpgis.ncep.noaa.gov/arcgis/rest/services/NWS_Observations/ahps_riv_gauges/MapServer/0/query?returnGeometry=true&where=1%3D1&outSR=4326&outFields=*&inSr=4326&geometry=%7B%22xmin%22%3A-90%2C%22ymin%22%3A55.7765730186677%2C%22xmax%22%3A-67.50000000000001%2C%22ymax%22%3A66.51326044311188%2C%22spatialReference%22%3A%7B%22wkid%22%3A4326%7D%7D&geometryType=esriGeometryEnvelope&spatialRel=esriSpatialRelIntersects&geometryPrecision=6&resultType=tile&f=geojson&callback=window._EsriLeafletCallbacks.c7” was blocked due to MIME type (“text/plain”) mismatch (X-Content-Type-Options: nosniff).
在这两种浏览器中,我都可以加载我的地图的初始视图,但是一旦它被加载并开始与之交互,我就开始遇到这些错误。
我大致理解是 X-Content-Type-Options 导致了我这个问题。如果我查看 Firefox 中的响应 headers,我可以确认 x-content-type-options
是 nosniff
并且 content-type
是 text/plain; charset=UTF-8
。
由于我无法控制服务器,因此无法直接影响响应 headers,我可以做些什么来克服这种行为吗?
我创建了一个可以重现错误的工作 CodePen here。实际的 CodePen 控制台不会显示错误,但如果您打开浏览器控制台,它会如广告所示显示。
相关代码如下:
HTML
<head>
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.6.0/dist/leaflet.css"
integrity="sha512-xwE/Az9zrjBIphAcBb3F6JVqxf46+CDLwfLMHloNu6KEQCAWi6HcDUbeOfBIptF7tcCzusKFjFw2yuvEpDL9wQ=="
crossorigin=""/>
<script src="https://unpkg.com/leaflet@1.6.0/dist/leaflet.js"
integrity="sha512-gZwIG9x3wUXg2hdXF6+rVkLF/0Vi9U8D2Ntg4Ga5I5BZpVkVxlJWbSQtXPSiUTtC0TjtGOmxa1AJPuV0CPthew=="
crossorigin=""></script>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
<script src="https://kit.fontawesome.com/369cdded93.js" crossorigin="anonymous"></script>
<script src="https://unpkg.com/esri-leaflet@2.4.1/dist/esri-leaflet.js"
integrity="sha512-xY2smLIHKirD03vHKDJ2u4pqeHA7OQZZ27EjtqmuhDguxiUvdsOuXMwkg16PQrm9cgTmXtoxA6kwr8KBy3cdcw=="
crossorigin=""></script>
<script src="https://unpkg.com/esri-leaflet-renderers@2.0.6"></script>
</head
<body>
<div class="col-xl-9 m-0 p-0" id="mapdiv">
<div id="mapid"></div>
</div>
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script>
</body>
CSS
body {
background-color: rgb(25,26,26);
}
#mapid {
height:100vh;
width: 100vw;
}
Javascript
var mymap = L.map('mapid', {
center: [63.2008, -155.00],
zoom: 5,
dragging: !L.Browser.mobile,
tap: !L.Browser.mobile,
scrollWheelZoom: false,
});
L.tileLayer('https://{s}.tile.jawg.io/jawg-dark/{z}/{x}/{y}{r}.png?access-token={accessToken}', {
attribution: '<a href="https://www.jawg.io" title="Tiles Courtesy of Jawg Maps" target="_blank">© <b>Jawg</b>Maps</a> © <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors',
minZoom: 0,
maxZoom: 22,
subdomains: 'abcd',
accessToken: 'shsyk3yIdzeeE6ZnSv1Da78AItybRtOzvOvOgxaYEJBScuSbR7d2LbMsIKOw1dqN'
}).addTo(mymap);
var riverGauges = L.esri.featureLayer({
url: 'https://idpgis.ncep.noaa.gov/arcgis/rest/services/NWS_Observations/ahps_riv_gauges/MapServer/0',
ignoreRenderer: false,
useCors: false,
cacheLayers: true,
onEachFeature: function(feature, layer) {
layer.feature.properties.gaugelid = layer.feature.properties.gaugelid.toLowerCase();
layer.feature.properties.url = "https://water.weather.gov/resources/hydrographs/" + layer.feature.properties.gaugelid + "_hg.png";
layer.bindPopup(function(layer) {
return L.Util.template(
`<iframe style="border:none; height:100%; width:100%;" src={url}></iframe>
`
,layer.feature.properties)
},
{
minWidth: 600,
})
},
/*
pointToLayer: function(feature, latlng) {
return L.marker(latlng, {icon:floodIcon});
},*/
attribution: 'River Gauges: <a href="https://water.weather.gov/ahps/region.php?state=ak" target="_blank">NWS/NOAA</a>',
}).addTo(mymap);
let overlays = {};
let points = {
"River Gauges" : riverGauges
};
L.control.layers(overlays, points).addTo(mymap);
郑重声明,因为我知道这会让人们烦恼:我在这里使用的访问令牌只是针对此问题的临时访问令牌。一旦不再需要它,我会撤销它。
我能想到的最佳解决方案是从 featureLayer
更改为 dynamicMapLayer
。然而,这需要一些权衡:
缺点
- 无法自定义图标
- 很难用 css 设计风格
优点
- 加载速度更快
- 没有 MIME 类型或 CORB 问题
let riverGauges = L.esri.dynamicMapLayer({
url: 'https://idpgis.ncep.noaa.gov/arcgis/rest/services/NWS_Observations/ahps_riv_gauges/MapServer',
useCors: false,
f: 'image',
layers: [0],
layerDefs: {0:
"status IN ('no_flooding') AND state='AK'", //"status IN ('major', 'moderate', 'minor', 'action') AND state='AK'"
},
disableCache: false,
attribution: 'River Gauges: <a href="https://water.weather.gov/ahps/region.php?state=ak" target="_blank">NWS/NOAA</a>',
}).addTo(mymap);
riverGauges.bindPopup(function(error, featureCollection) {
if (error || featureCollection.features.length === 0) {
return false;
} else {
let gaugelid = featureCollection.features[0].properties.gaugelid.toLowerCase();
let url = "https://water.weather.gov/resources/hydrographs/" + gaugelid + "_hg.png";
return L.Util.template(
`<iframe style="border:none; height:465; width:600;" src={url}></iframe>`,
{'url':url}
);
}},
{
minWidth: 600,
},
);