diff --git a/lib/assets/javascripts/cdb b/lib/assets/javascripts/cdb
index d01b7f1c5a..0595a66098 160000
--- a/lib/assets/javascripts/cdb
+++ b/lib/assets/javascripts/cdb
@@ -1 +1 @@
-Subproject commit d01b7f1c5af23202307a54534024596baa3a81bd
+Subproject commit 0595a660981e45469f9824a6f10db275d2c859f3
diff --git a/services/wms/proxy.rb b/services/wms/proxy.rb
new file mode 100644
index 0000000000..73a0dd042d
--- /dev/null
+++ b/services/wms/proxy.rb
@@ -0,0 +1,103 @@
+# encoding: utf-8
+require 'uri'
+require 'nokogiri'
+require 'typhoeus'
+
+module CartoDB
+ module WMS
+ class Proxy
+ SERVER_XPATH = "//OnlineResource[1]"
+ FORMATS_XPATH = "//GetMap/Format"
+ LAYERS_XPATH = "//Layer/Layer[BoundingBox or LatLonBoundingBox]"
+
+ def initialize(url, preloaded_xml=nil)
+ @url = url
+ @response = preloaded_xml
+ end
+
+ def serialize
+ run
+ { server: server, formats: formats, layers: layers }
+ end
+
+ def run
+ request_capabilities unless response
+ self
+ end
+
+ def request_capabilities
+ response = Typhoeus.get(url)
+ raise URI::InvalidURIError unless [200, 201].include?(response.code)
+ @response = response.response_body
+ nil
+ end
+
+ def document
+ Nokogiri::XML::Document.parse(response).remove_namespaces!
+ end
+
+ def server
+ (document.at_xpath(SERVER_XPATH) || {})['href']
+ end
+
+ def formats
+ document.xpath(FORMATS_XPATH).map(&:text)
+ end
+
+ def layers
+
+ document.xpath(LAYERS_XPATH).map { |element|
+ name = element.xpath("./Name").first
+ title = element.xpath("./Title").first
+ {
+ name: (name.text if name),
+ title: (title.text if title),
+ crs: crs_for_element(element),
+ srs: srs_for_element(element),
+ bounding_boxes: bounding_boxes_for(element),
+ attribution: nil
+ }
+ }
+ end
+
+ def crs_for_element(element)
+ crs = element.xpath("./CRS").map { |element|
+ element.text
+ }.compact
+ end
+
+ def srs_for_element(element)
+ srs = element.xpath("./SRS").map { |element|
+ element.text
+ }.compact
+ end
+
+ def bounding_boxes_for(element)
+ bounding_boxes = element.xpath("./BoundingBox").map { |element|
+ srs = element.xpath("./@SRS").first
+ crs = element.xpath("./@CRS").first
+ minx = element.xpath("./@minx").first
+ miny = element.xpath("./@miny").first
+ maxx = element.xpath("./@maxx").first
+ maxy = element.xpath("./@maxy").first
+
+ {
+ srs: (srs.value if srs),
+ crs: (crs.value if crs),
+ minx: (minx.value if minx),
+ miny: (miny.value if miny),
+ maxx: (maxx.value if maxx),
+ maxy: (maxy.value if maxy),
+ }
+ }
+ end
+
+ attr_reader :response
+
+ private
+
+ attr_reader :url
+ end # Proxy
+ end # WMS
+end # CartoDB
+
diff --git a/services/wms/spec/fixtures/wms.xml b/services/wms/spec/fixtures/wms.xml
new file mode 100644
index 0000000000..0b7685936e
--- /dev/null
+++ b/services/wms/spec/fixtures/wms.xml
@@ -0,0 +1,657 @@
+
+
+
+ USGSImageryTopo WMS
+ USGSImageryTopo
+ WMS
+
+
+
+
+ >
+ >
+
+ >
+
+ >
+
+
+
+
+
+
+
+
+
+
+
+
+ 2048
+ 2048
+
+
+
+
+ application/vnd.ogc.wms_xml
+ text/xml
+
+
+
+
+
+ image/bmp
+ image/jpeg
+ image/tiff
+ image/png
+ image/png8
+ image/png24
+ image/png32
+ image/gif
+ image/svg+xml
+
+
+
+
+
+ application/vnd.esri.wms_raw_xml
+ application/vnd.esri.wms_featureinfo_xml
+ application/vnd.ogc.wms_xml
+ text/xml
+ text/html
+ text/plain
+
+
+
+
+
+ application/vnd.ogc.sld+xml
+
+
+
+
+
+
+ application/vnd.ogc.se_xml
+ application/vnd.ogc.se_inimage
+ application/vnd.ogc.se_blank
+ text/xml
+ XML
+
+
+ Layers
+ CRS:84
+ EPSG:4326
+ EPSG:4269
+ EPSG:4267
+ EPSG:54004
+ EPSG:54008
+ EPSG:3785
+ EPSG:102113
+ EPSG:3857
+ EPSG:102100
+ EPSG:900913
+ EPSG:7250
+ EPSG:102016
+ EPSG:102017
+ EPSG:3571
+ EPSG:3572
+ EPSG:3573
+ EPSG:3574
+ EPSG:3575
+ EPSG:3576
+ EPSG:3338
+ -179.999999999987179.999999999987-88.999999999999988.9999999999999
+
+
+
+
+ Level 15 - 1:18K - 24k QUAD
+ Level 15 - 1:18K - 24k QUAD
+ 17060.900298
+ 25564.419643
+
+ Elevation (Relief)
+ Elevation (Relief)
+
+
+ Hydrography (Fill)
+ Hydrography (Fill)
+
+
+ Boundary (Fill)
+ Boundary (Fill)
+
+
+ Elevation (Line)
+ Elevation (Line)
+
+
+ Hydrography (Outline)
+ Hydrography (Outline)
+
+
+ Boundary (Outline)
+ Boundary (Outline)
+
+
+ Transportation
+ Transportation
+
+
+ Structure
+ Structure
+
+
+ Geographic Name
+ Geographic Name
+
+
+
+ Level 14 - 1:36k - Town QUAD
+ Level 14 - 1:36k - Town QUAD
+ 25565.364583
+ 51127.894345
+
+ Elevation (Relief)
+ Elevation (Relief)
+
+
+ Hydrography (Fill)
+ Hydrography (Fill)
+
+
+ Boundary (Fill)
+ Boundary (Fill)
+
+
+ Elevation (Line)
+ Elevation (Line)
+
+
+ Hydrography (Outline)
+ Hydrography (Outline)
+
+
+ Boundary (Outline)
+ Boundary (Outline)
+
+
+ Transportation
+ Transportation
+
+
+ Structure
+ Structure
+
+
+ Geographic Name
+ Geographic Name
+
+
+
+ Level 13 - 1:72k - City
+ Level 13 - 1:72k - City
+ 51128.839286
+ 102255.788690
+
+ Elevation (Relief)
+ Elevation (Relief)
+
+
+ Hydrography (Fill)
+ Hydrography (Fill)
+
+
+ Boundary (Fill)
+ Boundary (Fill)
+
+
+ Elevation (Line)
+ Elevation (Line)
+
+
+ Hydrography (Outline)
+ Hydrography (Outline)
+
+
+ Boundary (Outline)
+ Boundary (Outline)
+
+
+ Transportation
+ Transportation
+
+
+ Structure
+ Structure
+
+
+ Geographic Name
+ Geographic Name
+
+
+
+ Level 12 - 1:144k - Cities
+ Level 12 - 1:144k - Cities
+ 102256.733631
+ 204512.522321
+
+ Elevation (Relief)
+ Elevation (Relief)
+
+
+ Hydrography (Fill)
+ Hydrography (Fill)
+
+
+ Boundary (Fill)
+ Boundary (Fill)
+
+
+ Elevation (Line)
+ Elevation (Line)
+
+
+ Hydrography (Outline)
+ Hydrography (Outline)
+
+
+ Boundary (Outline)
+ Boundary (Outline)
+
+
+ Transportation
+ Transportation
+
+
+ Structure
+ Structure
+
+
+ Geographic Name
+ Geographic Name
+
+
+
+ Level 11 - 1:288k - Metro
+ Level 11 - 1:288k - Metro
+ 204513.467262
+ 409025.044643
+
+ Elevation (Relief)
+ Elevation (Relief)
+
+
+ Hydrography (Fill)
+ Hydrography (Fill)
+
+
+ Boundary (Fill)
+ Boundary (Fill)
+
+
+ Elevation (Line)
+ Elevation (Line)
+
+
+ Hydrography (Outline)
+ Hydrography (Outline)
+
+
+ Boundary (Outline)
+ Boundary (Outline)
+
+
+ Transportation
+ Transportation
+
+
+ Structure
+ Structure
+
+
+
+ Level 10 - 1:577k - County
+ Level 10 - 1:577k - County
+ 409025.989583
+ 818050.089286
+
+ Elevation (Relief)
+ Elevation (Relief)
+
+
+ Hydrography (Fill)
+ Hydrography (Fill)
+
+
+ Boundary (Fill)
+ Boundary (Fill)
+
+
+ Elevation (Line)
+ Elevation (Line)
+
+
+ Hydrography (Outline)
+ Hydrography (Outline)
+
+
+ Boundary (Outline)
+ Boundary (Outline)
+
+
+ Transportation
+ Transportation
+
+
+ Structure
+ Structure
+
+
+
+ Level 9 - 1:1.15M - Counties
+ Level 9 - 1:1.15M - Counties
+ 818051.034226
+ 1636099.233631
+
+ Elevation (Relief)
+ Elevation (Relief)
+
+
+ Hydrography (Fill)
+ Hydrography (Fill)
+
+
+ Boundary (Fill)
+ Boundary (Fill)
+
+
+ Hydrography (Outline)
+ Hydrography (Outline)
+
+
+ Boundary (Outline)
+ Boundary (Outline)
+
+
+ Transportation
+ Transportation
+
+
+ Structure
+ Structure
+
+
+
+ Level 8 - 1:2.3M - States
+ Level 8 - 1:2.3M - States
+ 1636100.178571
+ 3272198.467262
+
+ Elevation (Relief)
+ Elevation (Relief)
+
+
+ Hydrography (Fill)
+ Hydrography (Fill)
+
+
+ Boundary (Fill)
+ Boundary (Fill)
+
+
+ Hydrography (Outline)
+ Hydrography (Outline)
+
+
+ Boundary (Outline)
+ Boundary (Outline)
+
+
+ Transportation
+ Transportation
+
+
+ Structure
+ Structure
+
+
+ Geographic Name
+ Geographic Name
+
+
+
+ Level 7 - 1:4.6M - Region
+ Level 7 - 1:4.6M - Region
+ 3272199.412202
+ 6544397.879464
+
+ Elevation (Relief)
+ Elevation (Relief)
+
+
+ Hydrography (Fill)
+ Hydrography (Fill)
+
+
+ Boundary (Fill)
+ Boundary (Fill)
+
+
+ Hydrography (Outline)
+ Hydrography (Outline)
+
+
+ Boundary (Outline)
+ Boundary (Outline)
+
+
+ Transportation
+ Transportation
+
+
+ Geographic Name
+ Geographic Name
+
+
+
+ Level 6 - 1:9.2M - Time Zone
+ Level 6 - 1:9.2M - Time Zone
+ 6544398.824405
+ 13088795.758929
+
+ Elevation (Relief)
+ Elevation (Relief)
+
+
+ Hydrography (Fill)
+ Hydrography (Fill)
+
+
+ Boundary (Fill)
+ Boundary (Fill)
+
+
+ Hydrography (Outline)
+ Hydrography (Outline)
+
+
+ Boundary (Outline)
+ Boundary (Outline)
+
+
+ Transportation
+ Transportation
+
+
+ Geographic Name
+ Geographic Name
+
+
+
+ Level 5 - 1:18M - Continental US
+ Level 5 - 1:18M - Continental US
+ 13088796.703869
+ 26177591.517857
+
+ Elevation (Relief)
+ Elevation (Relief)
+
+
+ Hydrography (Fill)
+ Hydrography (Fill)
+
+
+ Boundary (Fill)
+ Boundary (Fill)
+
+
+ Hydrography (Outline)
+ Hydrography (Outline)
+
+
+ Boundary (Outline)
+ Boundary (Outline)
+
+
+ Transportation
+ Transportation
+
+
+ Geographic Name
+ Geographic Name
+
+
+
+ Level 4 - 1:37M - Continent
+ Level 4 - 1:37M - Continent
+ 26177592.462798
+ 52355183.035714
+
+ Elevation (Relief)
+ Elevation (Relief)
+
+
+ Hydrography (Fill)
+ Hydrography (Fill)
+
+
+ Boundary (Fill)
+ Boundary (Fill)
+
+
+ Hydrography (Outline)
+ Hydrography (Outline)
+
+
+ Boundary (Outline)
+ Boundary (Outline)
+
+
+ Transportation
+ Transportation
+
+
+ Geographic Name
+ Geographic Name
+
+
+
+ Level 3 - 1:73M - Hemisphere
+ Level 3 - 1:73M - Hemisphere
+ 52355183.980655
+ 104710365.126488
+
+ Elevation (Relief)
+ Elevation (Relief)
+
+
+ Hydrography (Fill)
+ Hydrography (Fill)
+
+
+ Boundary (Fill)
+ Boundary (Fill)
+
+
+ Hydrography (Outline)
+ Hydrography (Outline)
+
+
+ Boundary (Outline)
+ Boundary (Outline)
+
+
+
+ Level 2 - 1:147M - World
+ Level 2 - 1:147M - World
+ 104710366.071429
+ 167962034.769345
+
+ Elevation (Relief)
+ Elevation (Relief)
+
+
+ Hydrography (Fill)
+ Hydrography (Fill)
+
+
+ Boundary (Fill)
+ Boundary (Fill)
+
+
+ Boundary (Outline)
+ Boundary (Outline)
+
+
+
+ Level 0 and 1 - 1:584M and 1:292M Globe
+ Level 0 and 1 - 1:584M and 1:292M Globe
+ CRS:84
+ EPSG:4326
+ EPSG:3857
+ -179.999988541187179.999988541187-88.999999999999983.6041545451803
+
+
+
+ 167962035.714286
+
+ Hydrography (Fill)
+ Hydrography (Fill)
+
+
+ Boundary (Outline)
+ Boundary (Outline)
+ CRS:84
+ EPSG:4326
+ EPSG:3857
+ -179.999988541187179.999988541187-88.999999999999983.6041545451803
+
+
+
+
+ 121
+ _
+ _
+ CRS:84
+ EPSG:4326
+ EPSG:3857
+ -179.999988541187179.999988541187-88.999999999999983.6041545451803
+
+
+
+
+
+
+
+
+
+
diff --git a/services/wms/spec/fixtures/wms2.xml b/services/wms/spec/fixtures/wms2.xml
new file mode 100644
index 0000000000..65ad425735
--- /dev/null
+++ b/services/wms/spec/fixtures/wms2.xml
@@ -0,0 +1,18 @@
+WMSTile_ServerWMS-based access to NRL's GIDB Portal. Try NRL's GIDB Portal System at http://dmap.nrlssc.navy.milNRL
+
+ John T. Sample
+ Naval Research Lab
+
+
+
+ postal
+ NRL Code 7440
+ Stennis Space Center
+ MS
+ 39529
+ USA
+
+ +1 228 688-4995
+ +1 228 688-4853
+ sample@nrlssc.navy.mil
+ nonenoneapplication/vnd.ogc.wms_xmlimage/pngimage/jpegtext/htmltext/xmlapplication/vnd.ogc.se_xmlTile_ServerEPSG:4326DRGMosaicDRGMosaicLayer Update Time = 2013-10-28T09:16:50EPSG:4326EPSG:3395EPSG:3857EPSG:900913DRG_AUTODRG_AUTOLayer Update Time = 2013-07-04T09:20:26EPSG:4326EPSG:3395EPSG:3857EPSG:900913DRG_AUTO_LABELEDDRG_AUTO_LABELEDLayer Update Time = 2013-07-04T09:20:26EPSG:4326EPSG:3395EPSG:3857EPSG:900913DRG_US_100KDRG_US_100KLayer Update Time = 2013-07-03T01:01:50EPSG:4326EPSG:3395EPSG:3857EPSG:900913DRG_US_24KDRG_US_24KLayer Update Time = 2013-07-03T03:35:02EPSG:4326EPSG:3395EPSG:3857EPSG:900913DRG_US_25KDRG_US_25KLayer Update Time = 2013-07-04T09:09:57EPSG:4326EPSG:3395EPSG:3857EPSG:900913DRG_US_Alaska_63KDRG_US_Alaska_63KLayer Update Time = 2013-07-04T09:20:26EPSG:4326EPSG:3395EPSG:3857EPSG:900913FAASectionalsFAASectionalsLayer Update Time = 2013-07-03T10:11:32EPSG:4326EPSG:3395EPSG:3857EPSG:900913FAATerminalAreaChartFAATerminalAreaChartLayer Update Time = 2013-07-03T10:17:10EPSG:4326EPSG:3395EPSG:3857EPSG:900913FAAWorldAeronauticalChartsFAAWorldAeronauticalChartsLayer Update Time = 2013-07-03T10:18:11EPSG:4326EPSG:3395EPSG:3857EPSG:900913GLORIASideScanGLORIASideScanLayer Update Time = 2013-07-02T03:24:34EPSG:4326EPSG:3395EPSG:3857EPSG:900913Landsat7Landsat7Layer Update Time = 2013-07-02T12:31:34EPSG:4326EPSG:3395EPSG:3857EPSG:900913MOON_ICONMOON_ICONLayer Update Time = 2013-10-28T09:15:00EPSG:4326MOON_SUN_TERMINATORMOON_SUN_TERMINATORLayer Update Time = 2013-10-28T09:15:00EPSG:4326NAIPNAIPLayer Update Time = 2013-07-11T02:08:37EPSG:4326EPSG:3395EPSG:3857EPSG:900913OSM_BASEMAPOSM_BASEMAPLayer Update Time = 2013-10-09T05:54:17EPSG:4326EPSG:3395EPSG:3857EPSG:900913OSM_BASEMAP_OVERLAYOSM_BASEMAP_OVERLAYLayer Update Time = 2013-10-09T05:54:17EPSG:4326EPSG:3395EPSG:3857EPSG:900913OpenStreetMapLayersEPSG:4326AEROWAY_AREASAEROWAY_AREASLayer Update Time = 2013-10-09T05:54:17EPSG:4326EPSG:3395EPSG:3857EPSG:900913AEROWAY_LINESAEROWAY_LINESLayer Update Time = 2013-10-09T05:54:17EPSG:4326EPSG:3395EPSG:3857EPSG:900913AEROWAY_MISC_AREASAEROWAY_MISC_AREASLayer Update Time = 2013-10-09T05:54:17EPSG:4326EPSG:3395EPSG:3857EPSG:900913AEROWAY_MISC_LINESAEROWAY_MISC_LINESLayer Update Time = 2013-10-09T05:54:17EPSG:4326EPSG:3395EPSG:3857EPSG:900913AEROWAY_POINTSAEROWAY_POINTSLayer Update Time = 2013-10-09T05:54:17EPSG:4326EPSG:3395EPSG:3857EPSG:900913AMENITY_POINTS_GRP_AAMENITY_POINTS_GRP_ALayer Update Time = 2013-10-09T05:54:17EPSG:4326EPSG:3395EPSG:3857EPSG:900913AMENITY_POINTS_GRP_BAMENITY_POINTS_GRP_BLayer Update Time = 2013-10-09T05:54:17EPSG:4326EPSG:3395EPSG:3857EPSG:900913AMENITY_POINTS_GRP_CAMENITY_POINTS_GRP_CLayer Update Time = 2013-10-09T05:54:17EPSG:4326EPSG:3395EPSG:3857EPSG:900913AMENITY_POINTS_GRP_DAMENITY_POINTS_GRP_DLayer Update Time = 2013-10-09T05:54:17EPSG:4326EPSG:3395EPSG:3857EPSG:900913AMENITY_POINTS_GRP_EAMENITY_POINTS_GRP_ELayer Update Time = 2013-10-09T05:54:17EPSG:4326EPSG:3395EPSG:3857EPSG:900913AMENITY_POINTS_GRP_FAMENITY_POINTS_GRP_FLayer Update Time = 2013-10-09T05:54:17EPSG:4326EPSG:3395EPSG:3857EPSG:900913AMENITY_POINTS_MISCAMENITY_POINTS_MISCLayer Update Time = 2013-10-09T05:54:17EPSG:4326EPSG:3395EPSG:3857EPSG:900913BOUNDARY_AREA_ADMIN_10BOUNDARY_AREA_ADMIN_10Layer Update Time = 2013-10-09T05:54:17EPSG:4326EPSG:3395EPSG:3857EPSG:900913BOUNDARY_AREA_ADMIN_2BOUNDARY_AREA_ADMIN_2Layer Update Time = 2013-10-09T05:54:17EPSG:4326EPSG:3395EPSG:3857EPSG:900913BOUNDARY_AREA_ADMIN_4BOUNDARY_AREA_ADMIN_4Layer Update Time = 2013-10-09T05:54:17EPSG:4326EPSG:3395EPSG:3857EPSG:900913BOUNDARY_AREA_ADMIN_5BOUNDARY_AREA_ADMIN_5Layer Update Time = 2013-10-09T05:54:17EPSG:4326EPSG:3395EPSG:3857EPSG:900913BOUNDARY_AREA_ADMIN_6BOUNDARY_AREA_ADMIN_6Layer Update Time = 2013-10-09T05:54:17EPSG:4326EPSG:3395EPSG:3857EPSG:900913BOUNDARY_AREA_ADMIN_8BOUNDARY_AREA_ADMIN_8Layer Update Time = 2013-10-09T05:54:17EPSG:4326EPSG:3395EPSG:3857EPSG:900913BOUNDARY_AREA_ADMIN_MISCBOUNDARY_AREA_ADMIN_MISCLayer Update Time = 2013-10-09T05:54:17EPSG:4326EPSG:3395EPSG:3857EPSG:900913BOUNDARY_LINE_ADMIN_10BOUNDARY_LINE_ADMIN_10Layer Update Time = 2013-10-09T05:54:17EPSG:4326EPSG:3395EPSG:3857EPSG:900913BOUNDARY_LINE_ADMIN_2BOUNDARY_LINE_ADMIN_2Layer Update Time = 2013-10-09T05:54:17EPSG:4326EPSG:3395EPSG:3857EPSG:900913BOUNDARY_LINE_ADMIN_4BOUNDARY_LINE_ADMIN_4Layer Update Time = 2013-10-09T05:54:17EPSG:4326EPSG:3395EPSG:3857EPSG:900913BOUNDARY_LINE_ADMIN_5BOUNDARY_LINE_ADMIN_5Layer Update Time = 2013-10-09T05:54:17EPSG:4326EPSG:3395EPSG:3857EPSG:900913BOUNDARY_LINE_ADMIN_6BOUNDARY_LINE_ADMIN_6Layer Update Time = 2013-10-09T05:54:17EPSG:4326EPSG:3395EPSG:3857EPSG:900913BOUNDARY_LINE_ADMIN_8BOUNDARY_LINE_ADMIN_8Layer Update Time = 2013-10-09T05:54:17EPSG:4326EPSG:3395EPSG:3857EPSG:900913BOUNDARY_LINE_ADMIN_MISCBOUNDARY_LINE_ADMIN_MISCLayer Update Time = 2013-10-09T05:54:17EPSG:4326EPSG:3395EPSG:3857EPSG:900913EMERGENCY_POINTSEMERGENCY_POINTSLayer Update Time = 2013-10-09T05:54:17EPSG:4326EPSG:3395EPSG:3857EPSG:900913HIGHWAY_BRIDLEWAY_LINESHIGHWAY_BRIDLEWAY_LINESLayer Update Time = 2013-10-09T05:54:17EPSG:4326EPSG:3395EPSG:3857EPSG:900913HIGHWAY_CYCLEWAY_LINESHIGHWAY_CYCLEWAY_LINESLayer Update Time = 2013-10-09T05:54:17EPSG:4326EPSG:3395EPSG:3857EPSG:900913HIGHWAY_FOOTWAY_LINESHIGHWAY_FOOTWAY_LINESLayer Update Time = 2013-10-09T05:54:17EPSG:4326EPSG:3395EPSG:3857EPSG:900913HIGHWAY_LIVING_STREET_LINESHIGHWAY_LIVING_STREET_LINESLayer Update Time = 2013-10-09T05:54:17EPSG:4326EPSG:3395EPSG:3857EPSG:900913HIGHWAY_MISC_LINESHIGHWAY_MISC_LINESLayer Update Time = 2013-10-09T05:54:17EPSG:4326EPSG:3395EPSG:3857EPSG:900913HIGHWAY_MOTORWAY_LINESHIGHWAY_MOTORWAY_LINESLayer Update Time = 2013-10-09T05:54:17EPSG:4326EPSG:3395EPSG:3857EPSG:900913HIGHWAY_MOTORWAY_LINES_SHIELDSHIGHWAY_MOTORWAY_LINES_SHIELDSLayer Update Time = 2013-10-09T05:54:17EPSG:4326EPSG:3395EPSG:3857EPSG:900913HIGHWAY_MOTORWAY_LINK_LINESHIGHWAY_MOTORWAY_LINK_LINESLayer Update Time = 2013-10-09T05:54:17EPSG:4326EPSG:3395EPSG:3857EPSG:900913HIGHWAY_PATH_LINESHIGHWAY_PATH_LINESLayer Update Time = 2013-10-09T05:54:17EPSG:4326EPSG:3395EPSG:3857EPSG:900913HIGHWAY_PEDESTRIAN_LINESHIGHWAY_PEDESTRIAN_LINESLayer Update Time = 2013-10-09T05:54:17EPSG:4326EPSG:3395EPSG:3857EPSG:900913HIGHWAY_PRIMARY_LINESHIGHWAY_PRIMARY_LINESLayer Update Time = 2013-10-09T05:54:17EPSG:4326EPSG:3395EPSG:3857EPSG:900913HIGHWAY_PRIMARY_LINES_SHIELDSHIGHWAY_PRIMARY_LINES_SHIELDSLayer Update Time = 2013-10-09T05:54:17EPSG:4326EPSG:3395EPSG:3857EPSG:900913HIGHWAY_PRIMARY_LINK_LINESHIGHWAY_PRIMARY_LINK_LINESLayer Update Time = 2013-10-09T05:54:17EPSG:4326EPSG:3395EPSG:3857EPSG:900913HIGHWAY_RACEWAY_LINESHIGHWAY_RACEWAY_LINESLayer Update Time = 2013-10-09T05:54:17EPSG:4326EPSG:3395EPSG:3857EPSG:900913HIGHWAY_RESIDENTIAL_LINESHIGHWAY_RESIDENTIAL_LINESLayer Update Time = 2013-10-09T05:54:17EPSG:4326EPSG:3395EPSG:3857EPSG:900913HIGHWAY_ROAD_LINESHIGHWAY_ROAD_LINESLayer Update Time = 2013-10-09T05:54:17EPSG:4326EPSG:3395EPSG:3857EPSG:900913HIGHWAY_SECONDARY_LINESHIGHWAY_SECONDARY_LINESLayer Update Time = 2013-10-09T05:54:17EPSG:4326EPSG:3395EPSG:3857EPSG:900913HIGHWAY_SECONDARY_LINES_SHIELDSHIGHWAY_SECONDARY_LINES_SHIELDSLayer Update Time = 2013-10-09T05:54:17EPSG:4326EPSG:3395EPSG:3857EPSG:900913HIGHWAY_SECONDARY_LINK_LINESHIGHWAY_SECONDARY_LINK_LINESLayer Update Time = 2013-10-09T05:54:17EPSG:4326EPSG:3395EPSG:3857EPSG:900913HIGHWAY_SERVICE_LINESHIGHWAY_SERVICE_LINESLayer Update Time = 2013-10-09T05:54:17EPSG:4326EPSG:3395EPSG:3857EPSG:900913HIGHWAY_TERTIARY_LINESHIGHWAY_TERTIARY_LINESLayer Update Time = 2013-10-09T05:54:17EPSG:4326EPSG:3395EPSG:3857EPSG:900913HIGHWAY_TERTIARY_LINES_SHIELDSHIGHWAY_TERTIARY_LINES_SHIELDSLayer Update Time = 2013-10-09T05:54:17EPSG:4326EPSG:3395EPSG:3857EPSG:900913HIGHWAY_TERTIARY_LINK_LINESHIGHWAY_TERTIARY_LINK_LINESLayer Update Time = 2013-10-09T05:54:17EPSG:4326EPSG:3395EPSG:3857EPSG:900913HIGHWAY_TRACK_LINESHIGHWAY_TRACK_LINESLayer Update Time = 2013-10-09T05:54:17EPSG:4326EPSG:3395EPSG:3857EPSG:900913HIGHWAY_TRUNK_LINESHIGHWAY_TRUNK_LINESLayer Update Time = 2013-10-09T05:54:17EPSG:4326EPSG:3395EPSG:3857EPSG:900913HIGHWAY_TRUNK_LINES_SHIELDSHIGHWAY_TRUNK_LINES_SHIELDSLayer Update Time = 2013-10-09T05:54:17EPSG:4326EPSG:3395EPSG:3857EPSG:900913HIGHWAY_TRUNK_LINK_LINESHIGHWAY_TRUNK_LINK_LINESLayer Update Time = 2013-10-09T05:54:17EPSG:4326EPSG:3395EPSG:3857EPSG:900913HIGHWAY_UNCLASSIFIED_LINESHIGHWAY_UNCLASSIFIED_LINESLayer Update Time = 2013-10-09T05:54:17EPSG:4326EPSG:3395EPSG:3857EPSG:900913LANDUSE_AREASLANDUSE_AREASLayer Update Time = 2013-10-09T05:54:17EPSG:4326EPSG:3395EPSG:3857EPSG:900913LEISURE_AREASLEISURE_AREASLayer Update Time = 2013-10-09T05:54:17EPSG:4326EPSG:3395EPSG:3857EPSG:900913MAN_MADE_AREASMAN_MADE_AREASLayer Update Time = 2013-10-09T05:54:17EPSG:4326EPSG:3395EPSG:3857EPSG:900913MAN_MADE_MISC_POINTSMAN_MADE_MISC_POINTSLayer Update Time = 2013-10-09T05:54:17EPSG:4326EPSG:3395EPSG:3857EPSG:900913MAN_MADE_POINTSMAN_MADE_POINTSLayer Update Time = 2013-10-09T05:54:17EPSG:4326EPSG:3395EPSG:3857EPSG:900913MILITARY_AREASMILITARY_AREASLayer Update Time = 2013-10-09T05:54:17EPSG:4326EPSG:3395EPSG:3857EPSG:900913MISC_LINESMISC_LINESLayer Update Time = 2013-10-09T05:54:17EPSG:4326EPSG:3395EPSG:3857EPSG:900913NATURAL_AREASNATURAL_AREASLayer Update Time = 2013-10-09T05:54:17EPSG:4326EPSG:3395EPSG:3857EPSG:900913NATURAL_MISC_POINTSNATURAL_MISC_POINTSLayer Update Time = 2013-10-09T05:54:17EPSG:4326EPSG:3395EPSG:3857EPSG:900913NATURAL_POINTSNATURAL_POINTSLayer Update Time = 2013-10-09T05:54:17EPSG:4326EPSG:3395EPSG:3857EPSG:900913PLACE_CITY_POINTSPLACE_CITY_POINTSLayer Update Time = 2013-10-09T05:54:17EPSG:4326EPSG:3395EPSG:3857EPSG:900913PLACE_HAMLET_POINTSPLACE_HAMLET_POINTSLayer Update Time = 2013-10-09T05:54:17EPSG:4326EPSG:3395EPSG:3857EPSG:900913PLACE_LOCALITY_POINTSPLACE_LOCALITY_POINTSLayer Update Time = 2013-10-09T05:54:17EPSG:4326EPSG:3395EPSG:3857EPSG:900913PLACE_MISC_POINTSPLACE_MISC_POINTSLayer Update Time = 2013-10-09T05:54:17EPSG:4326EPSG:3395EPSG:3857EPSG:900913PLACE_TOWN_POINTSPLACE_TOWN_POINTSLayer Update Time = 2013-10-09T05:54:17EPSG:4326EPSG:3395EPSG:3857EPSG:900913PLACE_VILLAGE_SUBURB_POINTSPLACE_VILLAGE_SUBURB_POINTSLayer Update Time = 2013-10-09T05:54:17EPSG:4326EPSG:3395EPSG:3857EPSG:900913RAILWAY_LINESRAILWAY_LINESLayer Update Time = 2013-10-09T05:54:17EPSG:4326EPSG:3395EPSG:3857EPSG:900913SHOP_POINTSSHOP_POINTSLayer Update Time = 2013-10-09T05:54:17EPSG:4326EPSG:3395EPSG:3857EPSG:900913TOURISM_MISC_POINTSTOURISM_MISC_POINTSLayer Update Time = 2013-10-09T05:54:17EPSG:4326EPSG:3395EPSG:3857EPSG:900913TOURISM_POINTSTOURISM_POINTSLayer Update Time = 2013-10-09T05:54:17EPSG:4326EPSG:3395EPSG:3857EPSG:900913WATERWAY_AREASWATERWAY_AREASLayer Update Time = 2013-10-09T05:54:17EPSG:4326EPSG:3395EPSG:3857EPSG:900913WATERWAY_AREAS_MISCWATERWAY_AREAS_MISCLayer Update Time = 2013-10-09T05:54:17EPSG:4326EPSG:3395EPSG:3857EPSG:900913WATERWAY_LINES_MAJORWATERWAY_LINES_MAJORLayer Update Time = 2013-10-09T05:54:17EPSG:4326EPSG:3395EPSG:3857EPSG:900913WATERWAY_LINES_MINORWATERWAY_LINES_MINORLayer Update Time = 2013-10-09T05:54:17EPSG:4326EPSG:3395EPSG:3857EPSG:900913WATERWAY_LINES_MISCWATERWAY_LINES_MISCLayer Update Time = 2013-10-09T05:54:17EPSG:4326EPSG:3395EPSG:3857EPSG:900913OrdnanceSurvey(British)NationalGridOrdnanceSurvey(British)NationalGridLayer Update Time = 1969-12-31T06:00:01EPSG:4326RNC_10KRNC_10KLayer Update Time = 2013-07-02T09:25:44EPSG:4326EPSG:3395EPSG:3857EPSG:900913RNC_10MRNC_10MLayer Update Time = 2013-07-02T09:25:45EPSG:4326EPSG:3395EPSG:3857EPSG:900913RNC_120KRNC_120KLayer Update Time = 2013-07-02T09:25:48EPSG:4326EPSG:3395EPSG:3857EPSG:900913RNC_1MRNC_1MLayer Update Time = 2013-07-02T09:26:03EPSG:4326EPSG:3395EPSG:3857EPSG:900913RNC_20KRNC_20KLayer Update Time = 2013-07-02T09:26:43EPSG:4326EPSG:3395EPSG:3857EPSG:900913RNC_300KRNC_300KLayer Update Time = 2013-07-02T09:50:36EPSG:4326EPSG:3395EPSG:3857EPSG:900913RNC_300K_OilAndGasLeasesRNC_300K_OilAndGasLeasesLayer Update Time = 2013-07-02T09:51:31EPSG:4326EPSG:3395EPSG:3857EPSG:900913RNC_3MRNC_3MLayer Update Time = 2013-07-02T09:51:34EPSG:4326EPSG:3395EPSG:3857EPSG:900913RNC_40KRNC_40KLayer Update Time = 2013-07-02T09:51:58EPSG:4326EPSG:3395EPSG:3857EPSG:900913RNC_4MRNC_4MLayer Update Time = 2013-07-02T09:55:25EPSG:4326EPSG:3395EPSG:3857EPSG:900913RNC_80KRNC_80KLayer Update Time = 2013-07-02T09:55:33EPSG:4326EPSG:3395EPSG:3857EPSG:900913SUN_ICONSUN_ICONLayer Update Time = 2013-10-28T09:15:00EPSG:4326SUN_TERMINATORSUN_TERMINATORLayer Update Time = 2013-10-28T09:15:00EPSG:4326US_CANADA_BorderImageryUS_CANADA_BorderImageryLayer Update Time = 2013-07-02T01:29:50EPSG:4326EPSG:3395EPSG:3857EPSG:900913US_MEXICO_BorderImageryUS_MEXICO_BorderImageryLayer Update Time = 2013-07-02T06:53:20EPSG:4326EPSG:3395EPSG:3857EPSG:900913bluemarblebluemarbleLayer Update Time = 2013-04-23T12:09:07EPSG:4326EPSG:3395EPSG:3857EPSG:900913
\ No newline at end of file
diff --git a/services/wms/spec/fixtures/wms3.xml b/services/wms/spec/fixtures/wms3.xml
new file mode 100644
index 0000000000..056e195125
--- /dev/null
+++ b/services/wms/spec/fixtures/wms3.xml
@@ -0,0 +1,219 @@
+
+
+ is
+defined. -->
+
+
+
+
+
+
+
+
+ ]>
+
+
+
+
+
+ GetMap
+
+ World Map
+
+ None
+
+
+ http://www2.demis.nl
+
+ none
+ none
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ World Map
+
+ EPSG:4326
+
+
+
+ Bathymetry
+ Bathymetry
+
+
+
+
+ Countries
+ Countries
+
+
+
+
+ Topography
+ Topography
+
+
+
+
+ Hillshading
+ Hillshading
+
+
+
+
+ Builtup areas
+ Builtup areas
+
+
+
+
+ Coastlines
+ Coastlines
+
+
+
+
+ Waterbodies
+ Waterbodies
+
+
+
+
+ Inundated
+ Inundated
+
+
+
+
+ Rivers
+ Rivers
+
+
+
+
+ Streams
+ Streams
+
+
+
+
+ Railroads
+ Railroads
+
+
+
+
+ Highways
+ Highways
+
+
+
+
+ Roads
+ Roads
+
+
+
+
+ Trails
+ Trails
+
+
+
+
+ Borders
+ Borders
+
+
+
+
+ Cities
+ Cities
+
+
+
+
+ Settlements
+ Settlements
+
+
+
+
+ Spot elevations
+ Spot elevations
+
+
+
+
+ Airports
+ Airports
+
+
+
+
+ Ocean features
+ Ocean features
+
+
+
+
+
+
+
diff --git a/services/wms/spec/unit/wms_spec.rb b/services/wms/spec/unit/wms_spec.rb
new file mode 100644
index 0000000000..63d49d4d9d
--- /dev/null
+++ b/services/wms/spec/unit/wms_spec.rb
@@ -0,0 +1,110 @@
+# encoding: utf-8
+gem 'minitest'
+require 'minitest/autorun'
+require_relative '../../proxy'
+
+include CartoDB::WMS
+
+describe Proxy do
+ before do
+ @endpoint = "http://basemap.nationalmap.gov" +
+ "/arcgis/services/USGSImageryTopo/MapServer/WMSServer"
+ @query_params = "?service=WMS&request=GetCapabilities"
+ @url = @endpoint + @query_params
+ @fixture_xml = File.expand_path('../../fixtures/wms.xml', __FILE__)
+ @xml = File.read(@fixture_xml)
+
+ sample_response = {
+ server: @url,
+ formats: ["image/jpeg", "image/png"],
+ layers: [
+ {
+ name: "layer 1",
+ attribution: "attribution message"
+ },
+ {
+ name: "layer 2",
+ attribution: "attribution message"
+ }
+ ]
+ }
+ end
+
+ describe '#initialize' do
+ it 'takes a URL for the service capabilities' do
+ lambda { Proxy.new }.must_raise ArgumentError
+ Proxy.new(@url)
+ end
+
+ it 'accepts an optional preloaded response' do
+ proxy = Proxy.new(@url, @xml)
+ proxy.response.must_equal @xml
+ end
+ end
+
+ describe '#serialize' do
+ it 'returns a hash representation of the WMS capabilities' do
+ proxy = Proxy.new(@url, @xml)
+ representation = proxy.serialize
+ representation.fetch(:server).wont_be_nil
+ representation.fetch(:formats).wont_be_empty
+ representation.fetch(:layers).wont_be_empty
+ end
+ end
+
+ describe '#run' do
+ it 'will not touch the preloaded response if passed at initialization' do
+ proxy = Proxy.new(@url, @xml)
+ proxy.response.must_equal @xml
+ proxy.run
+ proxy.response.must_equal @xml
+ end
+ end
+
+ describe '#server' do
+ it 'returns the HTTP/HTTPS entry point for the services' do
+ proxy = Proxy.new(@url, @xml)
+ proxy.run
+ proxy.server.must_equal @endpoint
+ end
+ end
+
+ describe '#layers' do
+ it 'returns available layers' do
+ proxy = Proxy.new(@url, @xml)
+ proxy.run
+ proxy.layers.length.must_equal 3
+
+ url = "http://www2.demis.nl/worldmap/wms.asp?request=GetCapabilities&version=1.0.0"
+ proxy = Proxy.new(url)
+ proxy.run
+ proxy.layers.wont_be_empty
+
+ url = "http://nowcoast.noaa.gov/wms/com.esri.wms.Esrimap/obs?service=WMS&request=GetCapabilities"
+ proxy = Proxy.new(url)
+ proxy.run
+ proxy.layers.wont_be_empty
+ end
+ end
+
+ describe '#formats' do
+ it 'returns the supported formats' do
+ expected_formats = [
+ 'image/bmp',
+ 'image/jpeg',
+ 'image/tiff',
+ 'image/png',
+ 'image/png8',
+ 'image/png24',
+ 'image/png32',
+ 'image/gif',
+ 'image/svg+xml'
+ ]
+
+ proxy = Proxy.new(@url, @xml)
+ proxy.run
+ proxy.formats.sort.must_equal expected_formats.sort
+ end
+ end
+end # Proxy
+