@@ -84,6 +84,10 @@
|
||||
|
||||
// Custom Globals
|
||||
"globals" : { // additional predefined global variables
|
||||
"describe": true,
|
||||
"before": true,
|
||||
"after": true,
|
||||
"it": true,
|
||||
"suite": true,
|
||||
"suiteSetup": true,
|
||||
"test": true,
|
||||
|
||||
@@ -38,4 +38,4 @@ coverage:
|
||||
|
||||
check: test
|
||||
|
||||
.PHONY: pre-install test
|
||||
.PHONY: pre-install test jshint coverage
|
||||
|
||||
@@ -1,58 +1,90 @@
|
||||
1.30.1 -- 2015-mm-dd
|
||||
--------------------
|
||||
# Changelog
|
||||
|
||||
|
||||
1.30.0 -- 2015-03-11
|
||||
--------------------
|
||||
## 2.0.0
|
||||
|
||||
Released 2015-mm-dd
|
||||
|
||||
Announcements:
|
||||
- Major release with **BREAKING CHANGES**:
|
||||
* Removes `/:table/infowindow`, `/:table/map_metadata` and `/:table/flush_cache` endpoints
|
||||
* Sample configuration removes `/tiles/template` and `/tiles/layergroup`
|
||||
* URLs to use from now on are: `/api/v1/map/named` and `/api/v1/map`
|
||||
* No more state changes for styles
|
||||
* No more dump stats for renderers: SIGUSR1 and SIGUSR2 signals
|
||||
* Removes query params:
|
||||
- sql
|
||||
- geom_type
|
||||
- cache_buster
|
||||
- cache_policy
|
||||
- interactivity
|
||||
- style
|
||||
- style_version
|
||||
- style_convert
|
||||
- scale_factor
|
||||
* Affected tables for x-cache-channel will use direct connection to postgresql
|
||||
* Removes some metrics: authorized times ones
|
||||
|
||||
|
||||
## 1.30.0
|
||||
|
||||
Released 2015-03-11
|
||||
|
||||
Announcements:
|
||||
- Upgrades windshaft to [0.40.0](https://github.com/CartoDB/Windshaft/releases/tag/0.40.0)
|
||||
|
||||
|
||||
1.29.0 -- 2015-03-09
|
||||
--------------------
|
||||
## 1.29.0
|
||||
|
||||
Released 2015-03-09
|
||||
|
||||
Announcements:
|
||||
- Upgrades windshaft to [0.39.0](https://github.com/CartoDB/Windshaft/releases/tag/0.39.0)
|
||||
|
||||
|
||||
1.28.5 -- 2015-02-20
|
||||
--------------------
|
||||
## 1.28.5
|
||||
|
||||
Released 2015-02-20
|
||||
|
||||
Announcements:
|
||||
- Upgrades windshaft to [0.37.5](https://github.com/CartoDB/Windshaft/releases/tag/0.37.5)
|
||||
|
||||
|
||||
1.28.4 -- 2015-02-18
|
||||
--------------------
|
||||
## 1.28.4
|
||||
|
||||
Released 2015-02-18
|
||||
|
||||
Announcements:
|
||||
- Upgrades windshaft to [0.37.4](https://github.com/CartoDB/Windshaft/releases/tag/0.37.4)
|
||||
|
||||
|
||||
1.28.3 -- 2015-02-17
|
||||
--------------------
|
||||
## 1.28.3
|
||||
|
||||
Released 2015-02-17
|
||||
|
||||
Announcements:
|
||||
- Upgrades windshaft to [0.37.3](https://github.com/CartoDB/Windshaft/releases/tag/0.37.3)
|
||||
|
||||
|
||||
1.28.2 -- 2015-02-17
|
||||
--------------------
|
||||
## 1.28.2
|
||||
|
||||
Released 2015-02-17
|
||||
|
||||
Announcements:
|
||||
- Upgrades windshaft to [0.37.2](https://github.com/CartoDB/Windshaft/releases/tag/0.37.2)
|
||||
|
||||
|
||||
1.28.1 -- 2015-02-17
|
||||
--------------------
|
||||
## 1.28.1
|
||||
|
||||
Released 2015-02-17
|
||||
|
||||
Announcements:
|
||||
- Upgrades windshaft to [0.37.1](https://github.com/CartoDB/Windshaft/releases/tag/0.37.1)
|
||||
|
||||
|
||||
1.28.0 -- 2015-02-17
|
||||
--------------------
|
||||
## 1.28.0
|
||||
|
||||
Released 2015-02-17
|
||||
|
||||
Announcements:
|
||||
- Upgrades windshaft to [0.37.0](https://github.com/CartoDB/Windshaft/releases/tag/0.37.0)
|
||||
@@ -62,8 +94,9 @@ New features:
|
||||
tables last update (#253)
|
||||
|
||||
|
||||
1.27.0 -- 2015-02-16
|
||||
--------------------
|
||||
## 1.27.0
|
||||
|
||||
Released 2015-02-16
|
||||
|
||||
Announcements:
|
||||
- Adds default image placeholder for http renderer to use as fallback
|
||||
@@ -76,29 +109,33 @@ Bugfixes:
|
||||
- Fixes tests with beforeEach and afterEach triggers
|
||||
|
||||
|
||||
1.26.2 -- 2015-01-28
|
||||
--------------------
|
||||
## 1.26.2
|
||||
|
||||
Released 2015-01-28
|
||||
|
||||
Bugfixes:
|
||||
- Accept 'open' string in templates' `auth` as authorized.
|
||||
|
||||
|
||||
1.26.1 -- 2015-01-28
|
||||
--------------------
|
||||
## 1.26.1
|
||||
|
||||
Released 2015-01-28
|
||||
|
||||
Announcements:
|
||||
- Upgrades windshaft to 0.35.1, see https://github.com/CartoDB/Windshaft/pull/254
|
||||
|
||||
|
||||
1.26.0 -- 2015-01-27
|
||||
--------------------
|
||||
## 1.26.0
|
||||
|
||||
Released 2015-01-27
|
||||
|
||||
Announcements:
|
||||
- Upgrades windshaft to 0.35.0, supports mapconfig version `1.3.0`
|
||||
|
||||
|
||||
1.25.0 -- 2015-01-26
|
||||
--------------------
|
||||
## 1.25.0
|
||||
|
||||
Released 2015-01-26
|
||||
|
||||
Announcements:
|
||||
- No more signed maps (#227 and #238)
|
||||
@@ -134,22 +171,25 @@ New features:
|
||||
- SurrogateKeysCache is subscribed to TemplateMaps events to do the invalidations
|
||||
|
||||
|
||||
1.24.0 -- 2015-01-15
|
||||
--------------------
|
||||
## 1.24.0
|
||||
|
||||
Released 2015-01-15
|
||||
|
||||
Announcements:
|
||||
- Upgrades windshaft to 0.34.0 for retina support
|
||||
|
||||
|
||||
1.23.1 -- 2015-01-14
|
||||
--------------------
|
||||
## 1.23.1
|
||||
|
||||
Released 2015-01-14
|
||||
|
||||
Announcements:
|
||||
- Regenerate npm-shrinkwrap.json
|
||||
|
||||
|
||||
1.23.0 -- 2015-01-14
|
||||
--------------------
|
||||
## 1.23.0
|
||||
|
||||
Released 2015-01-14
|
||||
|
||||
Announcements:
|
||||
- Upgrades windshaft to 0.33.0
|
||||
@@ -158,22 +198,25 @@ New features:
|
||||
- Sets HTTP renderer configuration in server_options
|
||||
|
||||
|
||||
1.22.0 -- 2015-01-13
|
||||
--------------------
|
||||
## 1.22.0
|
||||
|
||||
Released 2015-01-13
|
||||
|
||||
New features:
|
||||
- Health check endpoint
|
||||
|
||||
|
||||
1.21.2 -- 2014-12-15
|
||||
--------------------
|
||||
## 1.21.2
|
||||
|
||||
Released 2014-12-15
|
||||
|
||||
Announcements:
|
||||
- Upgrades windshaft to 0.32.4
|
||||
|
||||
|
||||
1.21.1 -- 2014-12-11
|
||||
--------------------
|
||||
## 1.21.1
|
||||
|
||||
Released 2014-12-11
|
||||
|
||||
Announcements:
|
||||
- Upgrades windshaft to 0.32.2
|
||||
@@ -183,29 +226,33 @@ Bugfixes:
|
||||
|
||||
|
||||
|
||||
1.21.0 -- 2014-10-24
|
||||
--------------------
|
||||
## 1.21.0
|
||||
|
||||
Released 2014-10-24
|
||||
|
||||
New features:
|
||||
- Allow a different cache-control max-age for layergroup responses
|
||||
|
||||
|
||||
1.20.2 -- 2014-10-20
|
||||
--------------------
|
||||
## 1.20.2
|
||||
|
||||
Released 2014-10-20
|
||||
|
||||
Announcements:
|
||||
- Upgrades windshaft to 0.31.0
|
||||
|
||||
|
||||
1.20.1 -- 2014-10-17
|
||||
--------------------
|
||||
## 1.20.1
|
||||
|
||||
Released 2014-10-17
|
||||
|
||||
Announcements:
|
||||
- Upgrades redis-mpool to 0.3.0
|
||||
|
||||
|
||||
1.20.0 -- 2014-10-15
|
||||
--------------------
|
||||
## 1.20.0
|
||||
|
||||
Released 2014-10-15
|
||||
|
||||
New features:
|
||||
- Report to statsd the status of redis pools
|
||||
@@ -215,8 +262,9 @@ Enhancements:
|
||||
- Share one redis-mpool across the application
|
||||
|
||||
|
||||
1.19.0 -- 2014-10-14
|
||||
--------------------
|
||||
## 1.19.0
|
||||
|
||||
Released 2014-10-14
|
||||
|
||||
Announcements:
|
||||
- Dropping support for npm <1.2.1
|
||||
@@ -225,8 +273,9 @@ Announcements:
|
||||
- Generates npm-shrinkwrap.json with npm >1.2.0
|
||||
|
||||
|
||||
1.18.2 -- 2014-10-13
|
||||
--------------------
|
||||
## 1.18.2
|
||||
|
||||
Released 2014-10-13
|
||||
|
||||
Bug fixes:
|
||||
- Defaults resultSet to object if undefined in QueryTablesApi
|
||||
@@ -235,29 +284,33 @@ Announcements:
|
||||
- Upgrades windshaft to 0.28.1
|
||||
|
||||
|
||||
1.18.1 -- 2014-10-13
|
||||
--------------------
|
||||
## 1.18.1
|
||||
|
||||
Released 2014-10-13
|
||||
|
||||
New features:
|
||||
- Allow to add more node.js' threadpool workers via process.env.UV_THREADPOOL_SIZE
|
||||
|
||||
|
||||
1.18.0 -- 2014-10-03
|
||||
--------------------
|
||||
## 1.18.0
|
||||
|
||||
Released 2014-10-03
|
||||
|
||||
Announcements:
|
||||
- Comes back to use mapnik 2.3.x based on cartodb/node-mapnik@1.4.15-cdb from windshaft@0.28.0
|
||||
|
||||
|
||||
1.17.2 -- 2014-10-01
|
||||
--------------------
|
||||
## 1.17.2
|
||||
|
||||
Released 2014-10-01
|
||||
|
||||
Announcements:
|
||||
- Upgrades windshaft to 0.27.2 which downgrades node-mapnik to 0.7.26-cdb1
|
||||
|
||||
|
||||
1.17.1 -- 2014-09-30
|
||||
--------------------
|
||||
## 1.17.1
|
||||
|
||||
Released 2014-09-30
|
||||
|
||||
Announcements:
|
||||
- Upgrades windshaft to 0.27.1 which downgrades node-mapnik to 1.4.10
|
||||
@@ -267,8 +320,9 @@ Enhancements:
|
||||
- Upgrades mocha
|
||||
|
||||
|
||||
1.17.0 -- 2014-09-25
|
||||
--------------------
|
||||
## 1.17.0
|
||||
|
||||
Released 2014-09-25
|
||||
|
||||
New features:
|
||||
- Starts using mapnik 2.3.x
|
||||
@@ -279,14 +333,16 @@ Enhancements:
|
||||
- Metrics revamp: removes and adds some metrics
|
||||
- Adds poolSize configuration for mapnik
|
||||
|
||||
1.16.1 -- 2014-08-19
|
||||
--------------------
|
||||
## 1.16.1
|
||||
|
||||
Released 2014-08-19
|
||||
|
||||
Enhancements:
|
||||
- Upgrades cartodb-redis
|
||||
|
||||
1.16.0 -- 2014-08-18
|
||||
--------------------
|
||||
## 1.16.0
|
||||
|
||||
Released 2014-08-18
|
||||
|
||||
New features:
|
||||
- Configurable QueryTablesAPI to call directly postgresql using cartodb-psql
|
||||
@@ -302,8 +358,9 @@ Enhancements:
|
||||
- windshaft
|
||||
- request
|
||||
|
||||
1.15.0 -- 2014-08-13
|
||||
--------------------
|
||||
## 1.15.0
|
||||
|
||||
Released 2014-08-13
|
||||
Enhancements:
|
||||
- Upgrades dependencies:
|
||||
- redis-mpool
|
||||
@@ -313,8 +370,9 @@ Enhancements:
|
||||
- Slow pool configuration in example configurations
|
||||
|
||||
|
||||
1.14.0 -- 2014-08-07
|
||||
--------------------
|
||||
## 1.14.0
|
||||
|
||||
Released 2014-08-07
|
||||
|
||||
Enhancements:
|
||||
- SQL API requests moved to its own entity
|
||||
@@ -326,43 +384,49 @@ New features:
|
||||
dependencies for this matter
|
||||
|
||||
|
||||
1.13.1 -- 2014-08-04
|
||||
--------------------
|
||||
## 1.13.1
|
||||
|
||||
Released 2014-08-04
|
||||
|
||||
Enhancements:
|
||||
- Profiler header sent as JSON string
|
||||
|
||||
|
||||
1.13.0 -- 2014-07-30
|
||||
--------------------
|
||||
## 1.13.0
|
||||
|
||||
Released 2014-07-30
|
||||
|
||||
New features:
|
||||
- Support for postgresql schemas
|
||||
- Use public user from redis
|
||||
- Support for several auth tokens
|
||||
|
||||
1.12.1 -- 2014-06-24
|
||||
--------------------
|
||||
## 1.12.1
|
||||
|
||||
Released 2014-06-24
|
||||
|
||||
Enhancements:
|
||||
- Caches layergroup and sets X-Cache-Channel in GET requests also in named maps
|
||||
|
||||
1.12.0 -- 2014-06-24
|
||||
--------------------
|
||||
## 1.12.0
|
||||
|
||||
Released 2014-06-24
|
||||
|
||||
New features:
|
||||
- Caches layergroup and sets X-Cache-Channel in GET requests
|
||||
|
||||
1.11.1 -- 2014-05-07
|
||||
--------------------
|
||||
## 1.11.1
|
||||
|
||||
Released 2014-05-07
|
||||
|
||||
Enhancements:
|
||||
|
||||
- Upgrade Windshaft to 0.21.0, see
|
||||
http://github.com/CartoDB/Windshaft/blob/0.21.0/NEWS
|
||||
|
||||
1.11.0 -- 2014-04-28
|
||||
--------------------
|
||||
## 1.11.0
|
||||
|
||||
Released 2014-04-28
|
||||
|
||||
New features:
|
||||
|
||||
@@ -373,23 +437,26 @@ Enhancements:
|
||||
|
||||
- Set default PostgreSQL application name to "cartodb_tiler"
|
||||
|
||||
1.10.2 -- 2014-04-08
|
||||
--------------------
|
||||
## 1.10.2
|
||||
|
||||
Released 2014-04-08
|
||||
|
||||
Bug fixes:
|
||||
|
||||
- Fix show_style tool broken since 1.8.1
|
||||
- Fix X-Cache-Channel of tiles accessed via signed token (#188)
|
||||
|
||||
1.10.1 -- 2014-03-21
|
||||
--------------------
|
||||
## 1.10.1
|
||||
|
||||
Released 2014-03-21
|
||||
|
||||
Bug fixes:
|
||||
|
||||
- Do not cache non-success jsonp responses (#186)
|
||||
|
||||
1.10.0 -- 2014-03-20
|
||||
--------------------
|
||||
## 1.10.0
|
||||
|
||||
Released 2014-03-20
|
||||
|
||||
New features:
|
||||
|
||||
@@ -410,15 +477,17 @@ Other changes:
|
||||
|
||||
- Switch to 3-clause BSD license (#184)
|
||||
|
||||
1.9.0 -- 2014-03-10
|
||||
-------------------
|
||||
## 1.9.0
|
||||
|
||||
Released 2014-03-10
|
||||
|
||||
New features:
|
||||
|
||||
- Allow to set server related configuration in serverMetadata (#182)
|
||||
|
||||
1.8.5 -- 2014-03-10
|
||||
-------------------
|
||||
## 1.8.5
|
||||
|
||||
Released 2014-03-10
|
||||
|
||||
Enhancements:
|
||||
|
||||
@@ -436,8 +505,9 @@ Bug fixes:
|
||||
|
||||
- Do not cache map creation responses (#176)
|
||||
|
||||
1.8.4 -- 2014-03-03
|
||||
-------------------
|
||||
## 1.8.4
|
||||
|
||||
Released 2014-03-03
|
||||
|
||||
Enhancements:
|
||||
|
||||
@@ -454,8 +524,9 @@ Bug fixes:
|
||||
|
||||
- Fix database connection settings on template instanciation (#174)
|
||||
|
||||
1.8.3 -- 2014-02-27
|
||||
-------------------
|
||||
## 1.8.3
|
||||
|
||||
Released 2014-02-27
|
||||
|
||||
Enhancements:
|
||||
|
||||
@@ -468,8 +539,9 @@ Enhancements:
|
||||
[ new sqlapi.timeout directive, defaults to 100 ms ]
|
||||
- Do not query CDB_TableMetadata for queries affected by no tables (#168)
|
||||
|
||||
1.8.2 -- 2014-02-25
|
||||
-------------------
|
||||
## 1.8.2
|
||||
|
||||
Released 2014-02-25
|
||||
|
||||
Enhancements:
|
||||
|
||||
@@ -483,8 +555,9 @@ Bug fixes:
|
||||
|
||||
* Fix munin plugin after log format changes (#154)
|
||||
|
||||
1.8.1 -- 2014-02-19
|
||||
-------------------
|
||||
## 1.8.1
|
||||
|
||||
Released 2014-02-19
|
||||
|
||||
Enhancements:
|
||||
|
||||
@@ -494,8 +567,9 @@ Bug fixes:
|
||||
|
||||
* Always generate X-Cache-Channel for token-based tile responses (#152)
|
||||
|
||||
1.8.0 -- 2014-02-18
|
||||
-------------------
|
||||
## 1.8.0
|
||||
|
||||
Released 2014-02-18
|
||||
|
||||
Enhancements:
|
||||
|
||||
@@ -510,16 +584,18 @@ Enhancements:
|
||||
* Allow limiting number of templates for each user (#136)
|
||||
* Allow configuring TTL of mapConfigs via "mapConfigTTL"
|
||||
|
||||
1.7.1 -- 2014-02-11
|
||||
-------------------
|
||||
## 1.7.1
|
||||
|
||||
Released 2014-02-11
|
||||
|
||||
Enhancements:
|
||||
|
||||
* Disable debug logging unless "debug" config param evaluates to true (#137)
|
||||
* Require windshaft 0.17.2 for further reducing log noise (#137)
|
||||
|
||||
1.7.0 -- 2014-02-11
|
||||
-------------------
|
||||
## 1.7.0
|
||||
|
||||
Released 2014-02-11
|
||||
|
||||
New features:
|
||||
|
||||
@@ -540,8 +616,9 @@ Bug fixes:
|
||||
* Allow passing numbers as values for numeric template variables (#130)
|
||||
|
||||
|
||||
1.6.3 -- 2014-01-30
|
||||
-------------------
|
||||
## 1.6.3
|
||||
|
||||
Released 2014-01-30
|
||||
|
||||
Bug fixes:
|
||||
|
||||
@@ -556,8 +633,9 @@ Enhancements:
|
||||
* Stop processing XML on renderer creation, not needed anymore since 1.6.1
|
||||
introduced on-demand XML generation.
|
||||
|
||||
1.6.2 -- 2014-01-23
|
||||
-------------------
|
||||
## 1.6.2
|
||||
|
||||
Released 2014-01-23
|
||||
|
||||
Bug fixes:
|
||||
|
||||
@@ -569,16 +647,18 @@ Enhancements:
|
||||
print XML style now it is not in redis anymore (#110)
|
||||
* Support CORS in template instanciation endpoint (#113)
|
||||
|
||||
1.6.1 -- 2014-01-15
|
||||
-------------------
|
||||
## 1.6.1
|
||||
|
||||
Released 2014-01-15
|
||||
|
||||
Bug fixes:
|
||||
|
||||
* Drop cache headers from error responses (#107)
|
||||
* Localize external CartoCSS resources at renderer creation time (#108)
|
||||
|
||||
1.6.0 -- 2014-01-10
|
||||
-------------------
|
||||
## 1.6.0
|
||||
|
||||
Released 2014-01-10
|
||||
|
||||
New features:
|
||||
|
||||
@@ -591,24 +671,27 @@ Other changes:
|
||||
* Update cartodb-redis dependency to "~0.3.0"
|
||||
* Update redis-server dependency to "2.4.0+"
|
||||
|
||||
1.5.2 -- 2013-12-05
|
||||
-------------------
|
||||
## 1.5.2
|
||||
|
||||
Released 2013-12-05
|
||||
|
||||
Bug fixes:
|
||||
|
||||
* Fix configuration-level compatibility with versions prior to 1.5 (#96)
|
||||
* Fix use of old layergroups on mapnik upgrade (#97)
|
||||
|
||||
1.5.1 -- 2013-11-28
|
||||
-------------------
|
||||
## 1.5.1
|
||||
|
||||
Released 2013-11-28
|
||||
|
||||
Bug fixes:
|
||||
|
||||
* Survive presence of malformed CartoCSS in redis (#94)
|
||||
* Accept useless point-transform:scale directives (#93)
|
||||
|
||||
1.5.0 -- 2013-11-19
|
||||
-------------------
|
||||
## 1.5.0
|
||||
|
||||
Released 2013-11-19
|
||||
|
||||
NOTE: new configuration directives `postgres_auth_pass` and
|
||||
`postgres.password` added; see config/environments/*.example
|
||||
@@ -632,24 +715,28 @@ Other changes:
|
||||
* CartoDB redis interaction delegated to "cartodb-redis" module
|
||||
|
||||
|
||||
1.4.1 -- 2013-11-08
|
||||
-------------------
|
||||
## 1.4.1
|
||||
|
||||
Released 2013-11-08
|
||||
|
||||
* Fix support for exponential notation in CartoCSS filter values (#87)
|
||||
|
||||
1.4.0 -- 2013-10-31
|
||||
-------------------
|
||||
## 1.4.0
|
||||
|
||||
Released 2013-10-31
|
||||
|
||||
* Add Support for Mapnik-2.2.0 (#78)
|
||||
|
||||
1.3.6 -- 2013-10-11
|
||||
-------------------
|
||||
## 1.3.6
|
||||
|
||||
Released 2013-10-11
|
||||
|
||||
* Restore support for node-0.8.9 accidentally dropped by 1.3.5
|
||||
NOTE: needs removing node_modules/windshaft and re-running npm install
|
||||
|
||||
1.3.5 -- 2013-10-03
|
||||
-------------------
|
||||
## 1.3.5
|
||||
|
||||
Released 2013-10-03
|
||||
|
||||
* Fixing apostrophes in CartoCSS
|
||||
* Fix "sql/table must contain zoom variable" error when using
|
||||
@@ -658,8 +745,8 @@ Other changes:
|
||||
* Fix error for invalid text-name in CartoCSS (#81)
|
||||
* Do not let anonymous requests use authorized renderer caches
|
||||
|
||||
1.3.4
|
||||
------
|
||||
## 1.3.4
|
||||
|
||||
|
||||
NOTE: configuration sqlapi.host renamed to sqlapi.domain
|
||||
(support for "sqlapi.host" is retained for backward compatibility)
|
||||
@@ -668,38 +755,38 @@ NOTE: configuration sqlapi.host renamed to sqlapi.domain
|
||||
* Improve invalid mapnik-geometry-type CSS error message
|
||||
* Fix race condition in localization of network resources
|
||||
|
||||
1.3.3
|
||||
------
|
||||
## 1.3.3
|
||||
|
||||
* Set Last-Modified header to allow for 304 responses
|
||||
* Add profiling support (needs useProfiler in env config file)
|
||||
* Fix double-checking for layergroups with no interactivity
|
||||
* Log full layergroup config at creation time (#76)
|
||||
|
||||
1.3.2
|
||||
------
|
||||
## 1.3.2
|
||||
|
||||
* Set default layergroup TTL to 2 hours
|
||||
* Serve multilayer tiles and grid with persistent cache control
|
||||
|
||||
1.3.1
|
||||
------
|
||||
## 1.3.1
|
||||
|
||||
* Fix deadlock on new style creation
|
||||
* Fix database authentication with multi-table layergroups
|
||||
* Add tile and grid fetching checks at layergroup creation time
|
||||
* Fix SQL error reporting to NOT split on newline
|
||||
* Fix support for CartoCSS attachments
|
||||
|
||||
1.3.0
|
||||
------
|
||||
## 1.3.0
|
||||
|
||||
* Change stats format for multilayer map token request, see
|
||||
http://github.com/Vizzuality/Windshaft-cartodb/wiki/Redis-stats-format
|
||||
|
||||
1.2.1
|
||||
------
|
||||
## 1.2.1
|
||||
|
||||
* Fix multilayer post from firefox
|
||||
* Fix multilayer cartocss layer name handling
|
||||
|
||||
1.2.0
|
||||
------
|
||||
## 1.2.0
|
||||
|
||||
* Multilayer API changes
|
||||
* Layers passed by index in grid fetching url
|
||||
* Interactivity only specified in layergroup config
|
||||
@@ -707,14 +794,14 @@ NOTE: configuration sqlapi.host renamed to sqlapi.domain
|
||||
* Use ISO format for last_modified timestamp
|
||||
* Expected LZMA encoding changed to base64
|
||||
|
||||
1.1.10
|
||||
------
|
||||
## 1.1.10
|
||||
|
||||
* Fix regression with default interactivity parameter (#74)
|
||||
* More verbose logging for SQL api connection errors
|
||||
* Write stats for multilayer map token request
|
||||
|
||||
1.1.9
|
||||
-----
|
||||
## 1.1.9
|
||||
|
||||
* Handle SQL API errors by requesting no Varnish cache
|
||||
* Fix X-Cache-Channel for multilayer (by token) responses
|
||||
* Add last_modified field to layergroup creation response (#72)
|
||||
@@ -723,18 +810,22 @@ NOTE: configuration sqlapi.host renamed to sqlapi.domain
|
||||
* Add support for LZMA compressed GET parameters
|
||||
* Add support for creating layergroups via GET
|
||||
|
||||
1.1.8
|
||||
-----
|
||||
## 1.1.8
|
||||
|
||||
* Require Windshaft-0.9.1, to reduce harmfulness of cache_buster param
|
||||
|
||||
1.1.7 (DD//MM//YY)
|
||||
-----
|
||||
## 1.1.7
|
||||
|
||||
Released DD//MM//YY
|
||||
|
||||
* Do not let /etc/services confuse FD checker (munin plugin)
|
||||
* Multilayer support (#72)
|
||||
* Expose renderer settings in the environment config files
|
||||
|
||||
1.1.6 (19//02//13)
|
||||
-----
|
||||
## 1.1.6
|
||||
|
||||
Released 19//02//13
|
||||
|
||||
* Require windshaft 0.8.5, fixing some stability issues
|
||||
and providing cache info on request
|
||||
* Require grainstore 0.10.9, fixing an issue with multi-geom markers
|
||||
@@ -743,20 +834,26 @@ NOTE: configuration sqlapi.host renamed to sqlapi.domain
|
||||
* Survive connection refusals from redis
|
||||
* Add maxConnection environment configuration, default to 128
|
||||
|
||||
1.1.5 (DD//MM//YY)
|
||||
-----
|
||||
## 1.1.5
|
||||
|
||||
Released DD//MM//YY
|
||||
|
||||
* Fix bogus cached return of utf grid for fully contained tiles (#67)
|
||||
|
||||
1.1.4 (DD//MM//YY)
|
||||
-----
|
||||
## 1.1.4
|
||||
|
||||
Released DD//MM//YY
|
||||
|
||||
* Reduce default extent to allow for consistent proj4 round-tripping
|
||||
* Enhance reset_styles script to use full configuration (#62)
|
||||
* Have reset_styles script also drop extended keys (#58)
|
||||
* Fix example postgis parameter for simplifying input geoms (#63)
|
||||
* Add row_limit to example config (#64)
|
||||
|
||||
1.1.3 (30//11//12)
|
||||
-----
|
||||
## 1.1.3
|
||||
|
||||
Released 30//11//12
|
||||
|
||||
* Fix reset_styles script to really skip extended keys
|
||||
* CartoCSS versioning
|
||||
* Mapnik-version dependent default styles
|
||||
@@ -764,16 +861,20 @@ NOTE: configuration sqlapi.host renamed to sqlapi.domain
|
||||
* styles with conditional markers
|
||||
* scale arrow markers by 50%
|
||||
|
||||
1.1.2 (DD//MM//YY)
|
||||
-----
|
||||
## 1.1.2
|
||||
|
||||
Released DD//MM//YY
|
||||
|
||||
* CartoCSS versioning
|
||||
* Fix use of "style_version" with GET (inline styles)
|
||||
* Enhance 2.0 -> 2.1 transforms:
|
||||
* styles with no semicolon
|
||||
* markers shift due to geometry clipping
|
||||
|
||||
1.1.1 (DD//MM//YY)
|
||||
-----
|
||||
## 1.1.1
|
||||
|
||||
Released DD//MM//YY
|
||||
|
||||
* Add support for persistent client cache headers
|
||||
* Fix crash on unknown user (#55)
|
||||
* Add /version entry point
|
||||
@@ -782,8 +883,10 @@ NOTE: configuration sqlapi.host renamed to sqlapi.domain
|
||||
* Support style_version and style_convert parameters in POST /style request
|
||||
* Support style_version in GET /:z/:x/:y request
|
||||
|
||||
1.1.0 (30/10/12)
|
||||
=======
|
||||
## 1.1.0
|
||||
|
||||
Released (30/10/12)
|
||||
|
||||
* Add /version entry point
|
||||
* CartoCSS versioning
|
||||
* Include version in GET /style response
|
||||
@@ -800,12 +903,16 @@ NOTE: configuration sqlapi.host renamed to sqlapi.domain
|
||||
* Replaced environment configs by .example ones
|
||||
* Fixed some issues with cluster2
|
||||
|
||||
1.0.0 (03/10/12)
|
||||
-----
|
||||
## 1.0.0
|
||||
|
||||
Released 03/10/12
|
||||
|
||||
* Migrated to node 0.8.x.
|
||||
|
||||
0.9.0 (25/09/12)
|
||||
-----
|
||||
## 0.9.0
|
||||
|
||||
Released 25/09/12
|
||||
|
||||
* External resources in CartoCSS
|
||||
* Added X-Cache-Channel header in all the tiler GET requests
|
||||
* Small fixes
|
||||
|
||||
@@ -105,16 +105,6 @@ ws.on('listening', function() {
|
||||
+ " (" + ENV + ")");
|
||||
});
|
||||
|
||||
// DEPRECATED, use SIGUSR2
|
||||
process.on('SIGUSR1', function() {
|
||||
console.log('WARNING: handling of SIGUSR1 by Windshaft-CartoDB is deprecated, please send SIGUSR2 instead');
|
||||
ws.dumpCacheStats();
|
||||
});
|
||||
|
||||
process.on('SIGUSR2', function() {
|
||||
ws.dumpCacheStats();
|
||||
});
|
||||
|
||||
process.on('SIGHUP', function() {
|
||||
global.log4js.clearAndShutdownAppenders(function() {
|
||||
global.log4js.configure(log4js_config);
|
||||
|
||||
@@ -14,13 +14,11 @@ var config = {
|
||||
// Base url for the Templated Maps API
|
||||
// "/api/v1/map/named" is the new API,
|
||||
// "/tiles/template" is for compatibility with versions up to 1.6.x
|
||||
,base_url_templated: '(?:/api/v1/map/named|/tiles/template|/u/:user/api/v1/map/named|/u/:user/tiles/template)'
|
||||
,base_url_templated: '(?:/api/v1/map/named|/u/:user/api/v1/map/named)'
|
||||
// Base url for the Detached Maps API
|
||||
// "maps" is the the new API,
|
||||
// "tiles/layergroup" is for compatibility with versions up to 1.6.x
|
||||
,base_url_detached: '(?:/api/v1/map|/tiles/layergroup|/u/:user/api/v1/map|/u/:user/tiles/layergroup)'
|
||||
// Base url for the Inline Maps and Table Maps API
|
||||
,base_url_legacy: '/tiles/:table'
|
||||
,base_url_detached: '(?:/api/v1/map|/u/:user/api/v1/map)'
|
||||
|
||||
// Maximum number of connections for one process
|
||||
// 128 is a good value with a limit of 1024 open file descriptors
|
||||
@@ -133,26 +131,6 @@ var config = {
|
||||
statusInterval: 5000 // time, in ms, between each status report is emitted from the pool, status is sent to statsd
|
||||
}
|
||||
}
|
||||
,sqlapi: {
|
||||
protocol: 'http',
|
||||
// If "host" is given, it will be used
|
||||
// to connect to the SQL-API without a
|
||||
// DNS lookup
|
||||
host: '127.0.0.1',
|
||||
port: 8080,
|
||||
// The "domain" part will be appended to
|
||||
// the cartodb username and passed to
|
||||
// SQL-API requests in the Host HTTP header
|
||||
domain: 'localhost.lan',
|
||||
version: 'v1',
|
||||
// Maximum lenght of SQL query for GET
|
||||
// requests. Longer queries will be sent
|
||||
// using POST. Defaults to 2048
|
||||
max_get_sql_length: 2048,
|
||||
// Maximum time to wait for a response,
|
||||
// in milliseconds. Defaults to 100.
|
||||
timeout: 100
|
||||
}
|
||||
,varnish: {
|
||||
host: 'localhost',
|
||||
port: 6082, // the por for the telnet interface where varnish is listening to
|
||||
|
||||
@@ -14,13 +14,11 @@ var config = {
|
||||
// Base url for the Templated Maps API
|
||||
// "/api/v1/map/named" is the new API,
|
||||
// "/tiles/template" is for compatibility with versions up to 1.6.x
|
||||
,base_url_templated: '(?:/api/v1/map/named|/tiles/template|/u/:user/api/v1/map/named|/u/:user/tiles/template)'
|
||||
,base_url_templated: '(?:/api/v1/map/named|/u/:user/api/v1/map/named)'
|
||||
// Base url for the Detached Maps API
|
||||
// "maps" is the the new API,
|
||||
// "tiles/layergroup" is for compatibility with versions up to 1.6.x
|
||||
,base_url_detached: '(?:/api/v1/map|/tiles/layergroup|/u/:user/api/v1/map|/u/:user/tiles/layergroup)'
|
||||
// Base url for the Inline Maps and Table Maps API
|
||||
,base_url_legacy: '/tiles/:table'
|
||||
,base_url_detached: '(?:/api/v1/map|/u/:user/api/v1/map)'
|
||||
|
||||
// Maximum number of connections for one process
|
||||
// 128 is a good value with a limit of 1024 open file descriptors
|
||||
@@ -127,26 +125,6 @@ var config = {
|
||||
statusInterval: 5000 // time, in ms, between each status report is emitted from the pool, status is sent to statsd
|
||||
}
|
||||
}
|
||||
,sqlapi: {
|
||||
protocol: 'https',
|
||||
// If "host" is given, it will be used
|
||||
// to connect to the SQL-API without a
|
||||
// DNS lookup
|
||||
//host: '127.0.0.1',
|
||||
port: 8080,
|
||||
// The "domain" part will be appended to
|
||||
// the cartodb username and passed to
|
||||
// SQL-API requests in the Host HTTP header
|
||||
domain: 'cartodb.com',
|
||||
version: 'v2',
|
||||
// Maximum lenght of SQL query for GET
|
||||
// requests. Longer queries will be sent
|
||||
// using POST. Defaults to 2048
|
||||
max_get_sql_length: 2048,
|
||||
// Maximum time to wait for a response,
|
||||
// in milliseconds. Defaults to 100.
|
||||
timeout: 100
|
||||
}
|
||||
,varnish: {
|
||||
host: 'localhost',
|
||||
port: 6082, // the por for the telnet interface where varnish is listening to
|
||||
|
||||
@@ -14,13 +14,11 @@ var config = {
|
||||
// Base url for the Templated Maps API
|
||||
// "/api/v1/maps/named" is the new API,
|
||||
// "/tiles/template" is for compatibility with versions up to 1.6.x
|
||||
,base_url_templated: '(?:/api/v1/map/named|/tiles/template|/u/:user/api/v1/map/named|/u/:user/tiles/template)'
|
||||
,base_url_templated: '(?:/api/v1/map/named|/u/:user/api/v1/map/named)'
|
||||
// Base url for the Detached Maps API
|
||||
// "/api/v1/maps" is the the new API,
|
||||
// "/tiles/layergroup" is for compatibility with versions up to 1.6.x
|
||||
,base_url_detached: '(?:/api/v1/map|/tiles/layergroup|/u/:user/api/v1/map|/u/:user/tiles/layergroup)'
|
||||
// Base url for the Inline Maps and Table Maps API
|
||||
,base_url_legacy: '/tiles/:table'
|
||||
,base_url_detached: '(?:/api/v1/map|/u/:user/api/v1/map)'
|
||||
|
||||
// Maximum number of connections for one process
|
||||
// 128 is a good value with a limit of 1024 open file descriptors
|
||||
@@ -127,26 +125,6 @@ var config = {
|
||||
statusInterval: 5000 // time, in ms, between each status report is emitted from the pool, status is sent to statsd
|
||||
}
|
||||
}
|
||||
,sqlapi: {
|
||||
protocol: 'https',
|
||||
// If "host" is given, it will be used
|
||||
// to connect to the SQL-API without a
|
||||
// DNS lookup
|
||||
//host: '127.0.0.1',
|
||||
port: 8080,
|
||||
// The "domain" part will be appended to
|
||||
// the cartodb username and passed to
|
||||
// SQL-API requests in the Host HTTP header
|
||||
domain: 'cartodb.com',
|
||||
version: 'v2',
|
||||
// Maximum lenght of SQL query for GET
|
||||
// requests. Longer queries will be sent
|
||||
// using POST. Defaults to 2048
|
||||
max_get_sql_length: 2048,
|
||||
// Maximum time to wait for a response,
|
||||
// in milliseconds. Defaults to 100.
|
||||
timeout: 100
|
||||
}
|
||||
,varnish: {
|
||||
host: 'localhost',
|
||||
port: 6082, // the por for the telnet interface where varnish is listening to
|
||||
|
||||
@@ -14,13 +14,11 @@ var config = {
|
||||
// Base url for the Templated Maps API
|
||||
// "/api/v1/map/named" is the new API,
|
||||
// "/tiles/template" is for compatibility with versions up to 1.6.x
|
||||
,base_url_templated: '(?:/api/v1/map/named|/tiles/template|/u/:user/api/v1/map/named|/u/:user/tiles/template)'
|
||||
,base_url_templated: '(?:/api/v1/map/named|/u/:user/api/v1/map/named)'
|
||||
// Base url for the Detached Maps API
|
||||
// "maps" is the the new API,
|
||||
// "tiles/layergroup" is for compatibility with versions up to 1.6.x
|
||||
,base_url_detached: '(?:/api/v1/map|/tiles/layergroup|/u/:user/api/v1/map|/u/:user/tiles/layergroup)'
|
||||
// Base url for the Inline Maps and Table Maps API
|
||||
,base_url_legacy: '/tiles/:table'
|
||||
,base_url_detached: '(?:/api/v1/map|/u/:user/api/v1/map)'
|
||||
|
||||
// Maximum number of connections for one process
|
||||
// 128 is a good value with a limit of 1024 open file descriptors
|
||||
@@ -129,28 +127,6 @@ var config = {
|
||||
statusInterval: 5000 // time, in ms, between each status report is emitted from the pool, status is sent to statsd
|
||||
}
|
||||
}
|
||||
,sqlapi: {
|
||||
protocol: 'http',
|
||||
// If "host" is given, it will be used
|
||||
// to connect to the SQL-API without a
|
||||
// DNS lookup
|
||||
host: '127.0.0.1',
|
||||
port: 1080,
|
||||
// The "domain" part will be appended to
|
||||
// the cartodb username and passed to
|
||||
// SQL-API requests in the Host HTTP header
|
||||
domain: 'donot_look_this_up',
|
||||
// This port will be used by "make check" for testing purposes
|
||||
// It must be available
|
||||
version: 'v1',
|
||||
// Maximum lenght of SQL query for GET
|
||||
// requests. Longer queries will be sent
|
||||
// using POST. Defaults to 2048
|
||||
max_get_sql_length: 2048,
|
||||
// Maximum time to wait for a response,
|
||||
// in milliseconds. Defaults to 100.
|
||||
timeout: 100
|
||||
}
|
||||
,varnish: {
|
||||
host: '',
|
||||
port: null, // the por for the telnet interface where varnish is listening to
|
||||
|
||||
@@ -25,9 +25,7 @@ Again, each inner timer may have several inner timers.
|
||||
- **TemplateMaps_instance**: time to retrieve a map template instance, see *getTemplate* and *authorizedByCert*
|
||||
- **affectedTables**: time to check what are the affected tables for adding the cache channel, see *addCacheChannel*
|
||||
- **authorize**: time to authorize a request, see *authorizedByAPIKey*, *authorizedByCert*, *authorizedBySigner*
|
||||
- **authorizedByAPIKey**: time to authorize using an API KEY
|
||||
- **authorizedByCert**: time to authorize a template instantiation
|
||||
- **authorizedBySigner**: time to authorize a request with auth_token
|
||||
- **findLastUpdated**: time to retrieve the last update time for a list of tables, see *affectedTables*
|
||||
- **generateCacheChannel**: time to generate the headers for the cache channel based on the request, see *addCacheChannel*
|
||||
- **getSignerMapKey**: time to retrieve from redis the authorized user for a template map
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
var sqlApi = require('../sql/sql_api');
|
||||
var PSQL = require('cartodb-psql');
|
||||
var step = require('step');
|
||||
|
||||
@@ -74,56 +73,36 @@ function handleAffectedTablesAndLastUpdatedTimeRows(err, rows, callback) {
|
||||
QueryTablesApi.prototype.runQuery = function(username, query, queryHandler, callback) {
|
||||
var self = this;
|
||||
|
||||
if (shouldQueryPostgresDirectly()) {
|
||||
var params = {};
|
||||
|
||||
var params = {};
|
||||
|
||||
step(
|
||||
function setAuth() {
|
||||
self.pgConnection.setDBAuth(username, params, this);
|
||||
},
|
||||
function setConn(err) {
|
||||
if (err) {
|
||||
throw err;
|
||||
}
|
||||
self.pgConnection.setDBConn(username, params, this);
|
||||
},
|
||||
function executeQuery(err) {
|
||||
if (err) {
|
||||
throw err;
|
||||
}
|
||||
var psql = new PSQL({
|
||||
user: params.dbuser,
|
||||
pass: params.dbpass,
|
||||
host: params.dbhost,
|
||||
port: params.dbport,
|
||||
dbname: params.dbname
|
||||
});
|
||||
psql.query(query, function(err, resultSet) {
|
||||
resultSet = resultSet || {};
|
||||
var rows = resultSet.rows || [];
|
||||
queryHandler(err, rows, callback);
|
||||
});
|
||||
step(
|
||||
function setAuth() {
|
||||
self.pgConnection.setDBAuth(username, params, this);
|
||||
},
|
||||
function setConn(err) {
|
||||
if (err) {
|
||||
throw err;
|
||||
}
|
||||
);
|
||||
|
||||
} else {
|
||||
|
||||
step(
|
||||
function getApiKey() {
|
||||
self.metadataBackend.getUserMapKey(username, this);
|
||||
},
|
||||
function executeQuery(err, apiKey) {
|
||||
if (err) {
|
||||
throw err;
|
||||
}
|
||||
sqlApi.query(username, apiKey, query, function(err, rows) {
|
||||
queryHandler(err, rows, callback);
|
||||
});
|
||||
self.pgConnection.setDBConn(username, params, this);
|
||||
},
|
||||
function executeQuery(err) {
|
||||
if (err) {
|
||||
throw err;
|
||||
}
|
||||
);
|
||||
|
||||
}
|
||||
var psql = new PSQL({
|
||||
user: params.dbuser,
|
||||
pass: params.dbpass,
|
||||
host: params.dbhost,
|
||||
port: params.dbport,
|
||||
dbname: params.dbname
|
||||
});
|
||||
psql.query(query, function(err, resultSet) {
|
||||
resultSet = resultSet || {};
|
||||
var rows = resultSet.rows || [];
|
||||
queryHandler(err, rows, callback);
|
||||
});
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -135,10 +114,3 @@ function prepareSql(sql) {
|
||||
.replace(affectedTableRegexCache.pixel_height, '1')
|
||||
;
|
||||
}
|
||||
|
||||
|
||||
function shouldQueryPostgresDirectly() {
|
||||
return global.environment &&
|
||||
global.environment.enabledFeatures &&
|
||||
global.environment.enabledFeatures.cdbQueryTablesFromPostgres;
|
||||
}
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
var Varnish = require('node-varnish');
|
||||
var varnish_queue = null;
|
||||
|
||||
function init(host, port, secret) {
|
||||
varnish_queue = new Varnish.VarnishQueue(host, port, secret);
|
||||
varnish_queue.on('error', function(e) {
|
||||
console.log("[CACHE VALIDATOR ERROR] " + e);
|
||||
});
|
||||
}
|
||||
|
||||
function invalidate_db(dbname, table) {
|
||||
var cmd = 'purge obj.http.X-Cache-Channel ~ "^' + dbname +
|
||||
':(.*'+ table +'.*)|(table)$"';
|
||||
try{
|
||||
varnish_queue.run_cmd(cmd, false);
|
||||
} catch (e) {
|
||||
console.log("[CACHE VALIDATOR ERROR] could not queue command " +
|
||||
cmd + " -- " + e);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
init: init,
|
||||
invalidate_db: invalidate_db
|
||||
};
|
||||
@@ -1,7 +1,6 @@
|
||||
var _ = require('underscore');
|
||||
var step = require('step');
|
||||
var Windshaft = require('windshaft');
|
||||
var Cache = require('./cache_validator');
|
||||
var os = require('os');
|
||||
var HealthCheck = require('./monitoring/health_check');
|
||||
|
||||
@@ -25,24 +24,6 @@ var CartodbWindshaft = function(serverOptions) {
|
||||
|
||||
var templateMaps = serverOptions.templateMaps;
|
||||
|
||||
if(serverOptions.cache_enabled) {
|
||||
console.log("cache invalidation enabled, varnish on ", serverOptions.varnish_host, ' ',
|
||||
serverOptions.varnish_port);
|
||||
Cache.init(serverOptions.varnish_host, serverOptions.varnish_port, serverOptions.varnish_secret);
|
||||
serverOptions.afterStateChange = function(req, data, callback) {
|
||||
Cache.invalidate_db(req.params.dbname, req.params.table);
|
||||
callback(null, data);
|
||||
};
|
||||
}
|
||||
|
||||
serverOptions.beforeStateChange = function(req, callback) {
|
||||
var err = null;
|
||||
if ( ! req.params.hasOwnProperty('_authorizedByApiKey') ) {
|
||||
err = new Error("map state cannot be changed by unauthenticated request!");
|
||||
}
|
||||
callback(err, req);
|
||||
};
|
||||
|
||||
// This is for Templated maps
|
||||
//
|
||||
// "named" is the official, "template" is for backward compatibility up to 1.6.x
|
||||
@@ -172,56 +153,6 @@ var CartodbWindshaft = function(serverOptions) {
|
||||
* END Routing
|
||||
******************************************************************************************************************/
|
||||
|
||||
/**
|
||||
* Helper to allow access to the layer to be used in the maps infowindow popup.
|
||||
*/
|
||||
ws.get(serverOptions.base_url + '/infowindow', function(req, res){
|
||||
ws.doCORS(res);
|
||||
step(
|
||||
function(){
|
||||
serverOptions.getInfowindow(req, this);
|
||||
},
|
||||
function(err, data){
|
||||
if (err){
|
||||
ws.sendError(res, {error: err.message}, 500, 'GET INFOWINDOW', err);
|
||||
//ws.sendResponse(res, [{error: err.message}, 500]);
|
||||
} else {
|
||||
ws.sendResponse(res, [{infowindow: data}, 200]);
|
||||
}
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* Helper to allow access to metadata to be used in embedded maps.
|
||||
*/
|
||||
ws.get(serverOptions.base_url + '/map_metadata', function(req, res){
|
||||
ws.doCORS(res);
|
||||
step(
|
||||
function(){
|
||||
serverOptions.getMapMetadata(req, this);
|
||||
},
|
||||
function(err, data){
|
||||
if (err){
|
||||
ws.sendError(res, {error: err.message}, 500, 'GET MAP_METADATA', err);
|
||||
//ws.sendResponse(res, [err.message, 500]);
|
||||
} else {
|
||||
ws.sendResponse(res, [{map_metadata: data}, 200]);
|
||||
}
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
/**
|
||||
* Helper API to allow per table tile cache (and sql cache) to be invalidated remotely.
|
||||
* Keep endpoint for backwards compatibility
|
||||
*/
|
||||
ws.del(serverOptions.base_url + '/flush_cache', function(req, res){
|
||||
ws.doCORS(res);
|
||||
ws.sendResponse(res, [{status: 'ok'}, 200]);
|
||||
});
|
||||
|
||||
var healthCheck = new HealthCheck(cartoData, Windshaft.tilelive);
|
||||
ws.get('/health', function(req, res) {
|
||||
var healthConfig = global.environment.health || {};
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
var step = require('step');
|
||||
var _ = require('underscore');
|
||||
var CdbRequest = require('../models/cdb_request');
|
||||
|
||||
function TemplateMapsController(app, serverOptions, templateMaps, metadataBackend, templateBaseUrl, surrogateKeysCache,
|
||||
NamedMapsCacheEntry, pgConnection) {
|
||||
@@ -15,6 +16,7 @@ function TemplateMapsController(app, serverOptions, templateMaps, metadataBacken
|
||||
|
||||
module.exports = TemplateMapsController;
|
||||
|
||||
var cdbRequest = new CdbRequest();
|
||||
|
||||
TemplateMapsController.prototype.register = function(app) {
|
||||
app.get(this.templateBaseUrl + '/:template_id/jsonp', this.jsonp.bind(this));
|
||||
@@ -33,7 +35,7 @@ TemplateMapsController.prototype.create = function(req, res) {
|
||||
|
||||
this.app.doCORS(res);
|
||||
|
||||
var cdbuser = self.serverOptions.userByReq(req);
|
||||
var cdbuser = cdbRequest.userByReq(req);
|
||||
|
||||
step(
|
||||
function checkPerms(){
|
||||
@@ -80,7 +82,7 @@ TemplateMapsController.prototype.update = function(req, res) {
|
||||
|
||||
this.app.doCORS(res);
|
||||
|
||||
var cdbuser = this.serverOptions.userByReq(req);
|
||||
var cdbuser = cdbRequest.userByReq(req);
|
||||
var template;
|
||||
var tpl_id;
|
||||
step(
|
||||
@@ -140,7 +142,7 @@ TemplateMapsController.prototype.retrieve = function(req, res) {
|
||||
|
||||
this.app.doCORS(res);
|
||||
|
||||
var cdbuser = this.serverOptions.userByReq(req);
|
||||
var cdbuser = cdbRequest.userByReq(req);
|
||||
var tpl_id;
|
||||
step(
|
||||
function checkPerms(){
|
||||
@@ -201,7 +203,7 @@ TemplateMapsController.prototype.destroy = function(req, res) {
|
||||
}
|
||||
this.app.doCORS(res);
|
||||
|
||||
var cdbuser = this.serverOptions.userByReq(req);
|
||||
var cdbuser = cdbRequest.userByReq(req);
|
||||
var tpl_id;
|
||||
step(
|
||||
function checkPerms(){
|
||||
@@ -254,7 +256,7 @@ TemplateMapsController.prototype.list = function(req, res) {
|
||||
}
|
||||
this.app.doCORS(res);
|
||||
|
||||
var cdbuser = this.serverOptions.userByReq(req);
|
||||
var cdbuser = cdbRequest.userByReq(req);
|
||||
|
||||
step(
|
||||
function checkPerms(){
|
||||
@@ -353,7 +355,7 @@ TemplateMapsController.prototype.instantiateTemplate = function(req, res, templa
|
||||
var template;
|
||||
var layergroup;
|
||||
var fakereq; // used for call to createLayergroup
|
||||
var cdbuser = self.serverOptions.userByReq(req);
|
||||
var cdbuser = cdbRequest.userByReq(req);
|
||||
// Format of template_id: [<template_owner>]@<template_id>
|
||||
var tpl_id = req.params.template_id.split('@');
|
||||
if ( tpl_id.length > 1 ) {
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
function CdbRequest() {
|
||||
this.RE_USER_FROM_HOST = new RegExp(global.environment.user_from_host ||
|
||||
'^([^\\.]+)\\.' // would extract "strk" from "strk.cartodb.com"
|
||||
);
|
||||
}
|
||||
|
||||
module.exports = CdbRequest;
|
||||
|
||||
|
||||
CdbRequest.prototype.userByReq = function(req) {
|
||||
var host = req.headers.host;
|
||||
if (req.params.user) {
|
||||
return req.params.user;
|
||||
}
|
||||
var mat = host.match(this.RE_USER_FROM_HOST);
|
||||
if ( ! mat ) {
|
||||
console.error("Pattern '" + this.RE_USER_FROM_HOST + "' does not match hostname '" + host + "'");
|
||||
return;
|
||||
}
|
||||
// console.log("Matches: "); console.dir(mat);
|
||||
if ( mat.length !== 2 ) {
|
||||
console.error("Pattern '" + this.RE_USER_FROM_HOST + "' gave unexpected matches against '" + host + "': ", mat);
|
||||
return;
|
||||
}
|
||||
return mat[1];
|
||||
};
|
||||
+151
-311
@@ -2,37 +2,19 @@ var _ = require('underscore');
|
||||
var step = require('step');
|
||||
var QueryTablesApi = require('./api/query_tables_api');
|
||||
var PgConnection = require('./backends/pg_connection');
|
||||
var crypto = require('crypto');
|
||||
var LZMA = require('lzma').LZMA;
|
||||
var TemplateMaps = require('./template_maps.js');
|
||||
var MapConfigNamedLayersAdapter = require('./models/mapconfig_named_layers_adapter');
|
||||
|
||||
// This is for backward compatibility with 1.3.3
|
||||
if ( _.isUndefined(global.environment.sqlapi.domain) ) {
|
||||
// Only use "host" as "domain" if it contains alphanumeric characters
|
||||
var host = global.environment.sqlapi.host;
|
||||
if ( host && host.match(/[a-zA-Z]/) ) {
|
||||
global.environment.sqlapi.domain = host;
|
||||
}
|
||||
}
|
||||
var CdbRequest = require('./models/cdb_request');
|
||||
var assert = require('assert');
|
||||
|
||||
// Whitelist query parameters and attach format
|
||||
var REQUEST_QUERY_PARAMS_WHITELIST = [
|
||||
'user',
|
||||
'sql',
|
||||
'geom_type',
|
||||
'cache_buster',
|
||||
'cache_policy',
|
||||
'callback',
|
||||
'interactivity',
|
||||
'config',
|
||||
'map_key',
|
||||
'api_key',
|
||||
'auth_token',
|
||||
'style',
|
||||
'style_version',
|
||||
'style_convert',
|
||||
'config',
|
||||
'scale_factor'
|
||||
'callback'
|
||||
];
|
||||
|
||||
module.exports = function(redisPool) {
|
||||
@@ -42,7 +24,8 @@ module.exports = function(redisPool) {
|
||||
var cartoData = require('cartodb-redis')({ pool: redisPool }),
|
||||
lzmaWorker = new LZMA(),
|
||||
pgConnection = new PgConnection(cartoData),
|
||||
queryTablesApi = new QueryTablesApi(pgConnection, cartoData);
|
||||
queryTablesApi = new QueryTablesApi(pgConnection, cartoData),
|
||||
cdbRequest = new CdbRequest();
|
||||
|
||||
var rendererConfig = _.defaults(global.environment.renderer || {}, {
|
||||
cache_ttl: 60000, // milliseconds
|
||||
@@ -74,8 +57,7 @@ module.exports = function(redisPool) {
|
||||
cachedir: global.environment.millstone.cache_basedir,
|
||||
mapnik_version: global.environment.mapnik_version,
|
||||
mapnik_tile_format: global.environment.mapnik_tile_format || 'png',
|
||||
default_layergroup_ttl: global.environment.mapConfigTTL || 7200,
|
||||
gc_prob: 0.01 // @deprecated since Windshaft-1.8.0
|
||||
default_layergroup_ttl: global.environment.mapConfigTTL || 7200
|
||||
},
|
||||
mapnik: {
|
||||
poolSize: rendererConfig.poolSize,
|
||||
@@ -131,106 +113,81 @@ module.exports = function(redisPool) {
|
||||
return dbName + ':' + tableNames.join(',');
|
||||
};
|
||||
|
||||
me.generateMD5 = function(data){
|
||||
var hash = crypto.createHash('md5');
|
||||
hash.update(data);
|
||||
return hash.digest('hex');
|
||||
};
|
||||
|
||||
me.generateCacheChannel = function(app, req, callback){
|
||||
// Build channelCache key
|
||||
var dbName = req.params.dbname;
|
||||
var cacheKey = [ dbName, req.params.token ].join(':');
|
||||
|
||||
// Build channelCache key
|
||||
var dbName = req.params.dbname;
|
||||
var cacheKey = [ dbName ];
|
||||
if ( req.params.token ) cacheKey.push(req.params.token);
|
||||
else if ( req.params.sql ) cacheKey.push( me.generateMD5(req.params.sql) );
|
||||
cacheKey = cacheKey.join(':');
|
||||
|
||||
var that = this;
|
||||
|
||||
step (
|
||||
function checkCached() {
|
||||
if ( me.channelCache.hasOwnProperty(cacheKey) ) {
|
||||
callback(null, me.channelCache[cacheKey]);
|
||||
return;
|
||||
}
|
||||
return null;
|
||||
},
|
||||
function extractSQL(err) {
|
||||
if ( err ) throw err;
|
||||
|
||||
if ( req.params.token ) {
|
||||
// TODO: cached cache channel for token-based access should
|
||||
// be constructed at renderer cache creation time
|
||||
// See http://github.com/CartoDB/Windshaft-cartodb/issues/152
|
||||
if ( ! app.mapStore ) {
|
||||
throw new Error('missing channel cache for token ' + req.params.token);
|
||||
}
|
||||
var next = this;
|
||||
var mapStore = app.mapStore;
|
||||
step(
|
||||
function loadFromStore() {
|
||||
mapStore.load(req.params.token, this);
|
||||
},
|
||||
function getSQL(err, mapConfig) {
|
||||
if (req.profiler) req.profiler.done('mapStore_load');
|
||||
if ( err ) throw err;
|
||||
var sql = [];
|
||||
_.each(mapConfig.obj().layers, function(lyr) {
|
||||
sql.push(lyr.options.sql);
|
||||
});
|
||||
sql = sql.join(';');
|
||||
return sql;
|
||||
},
|
||||
function finish(err, sql) {
|
||||
next(err, sql);
|
||||
}
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
if ( ! req.params.sql ) {
|
||||
return null; // no sql
|
||||
}
|
||||
|
||||
// We have sql, and no token...
|
||||
|
||||
// strip out windshaft/mapnik inserted sql if present
|
||||
var sql = req.params.sql.match(/^\((.*)\)\sas\scdbq$/);
|
||||
sql = (sql !== null) ? sql[1] : req.params.sql;
|
||||
|
||||
return sql;
|
||||
},
|
||||
function findAffectedTables(err, sql) {
|
||||
if ( err ) throw err;
|
||||
if ( ! sql ) {
|
||||
if ( ! req.params.table ) {
|
||||
throw new Error("this request doesn't need an X-Cache-Channel generated");
|
||||
}
|
||||
return [req.params.table];
|
||||
}
|
||||
|
||||
queryTablesApi.getAffectedTablesInQuery(that.userByReq(req), sql, this); // in addCacheChannel
|
||||
},
|
||||
function buildCacheChannel(err, tableNames) {
|
||||
if ( err ) throw err;
|
||||
if (req.profiler && ! req.params.table ) {
|
||||
req.profiler.done('affectedTables');
|
||||
}
|
||||
|
||||
var dbName = req.params.dbname;
|
||||
var cacheChannel = me.buildCacheChannel(dbName,tableNames);
|
||||
// store for caching from me.generateCacheChannel
|
||||
// (not worth when table was specified in params)
|
||||
if ( ! req.params.table ) {
|
||||
me.channelCache[cacheKey] = cacheChannel;
|
||||
}
|
||||
return cacheChannel;
|
||||
},
|
||||
function finish(err, cacheChannel) {
|
||||
callback(err, cacheChannel);
|
||||
// no token means no tables associated
|
||||
if (!req.params.token) {
|
||||
return callback(null, this.buildCacheChannel(dbName, []));
|
||||
}
|
||||
);
|
||||
|
||||
step(
|
||||
function checkCached() {
|
||||
if ( me.channelCache.hasOwnProperty(cacheKey) ) {
|
||||
return callback(null, me.channelCache[cacheKey]);
|
||||
}
|
||||
return null;
|
||||
},
|
||||
function extractSQL(err) {
|
||||
assert.ifError(err);
|
||||
|
||||
// TODO: cached cache channel for token-based access should
|
||||
// be constructed at renderer cache creation time
|
||||
// See http://github.com/CartoDB/Windshaft-cartodb/issues/152
|
||||
if ( ! app.mapStore ) {
|
||||
throw new Error('missing channel cache for token ' + req.params.token);
|
||||
}
|
||||
var mapStore = app.mapStore;
|
||||
step(
|
||||
function loadFromStore() {
|
||||
mapStore.load(req.params.token, this);
|
||||
},
|
||||
function getSQL(err, mapConfig) {
|
||||
if (req.profiler) {
|
||||
req.profiler.done('mapStore_load');
|
||||
}
|
||||
assert.ifError(err);
|
||||
|
||||
var queries = mapConfig.getLayers()
|
||||
.map(function(lyr) {
|
||||
return lyr.options.sql;
|
||||
})
|
||||
.filter(function(sql) {
|
||||
return !!sql;
|
||||
});
|
||||
|
||||
return queries.length ? queries.join(';') : null;
|
||||
},
|
||||
this
|
||||
);
|
||||
},
|
||||
function findAffectedTables(err, sql) {
|
||||
assert.ifError(err);
|
||||
|
||||
if ( ! sql ) {
|
||||
throw new Error("this request doesn't need an X-Cache-Channel generated");
|
||||
}
|
||||
|
||||
queryTablesApi.getAffectedTablesInQuery(cdbRequest.userByReq(req), sql, this); // in addCacheChannel
|
||||
},
|
||||
function buildCacheChannel(err, tableNames) {
|
||||
assert.ifError(err);
|
||||
|
||||
if (req.profiler) {
|
||||
req.profiler.done('affectedTables');
|
||||
}
|
||||
|
||||
var cacheChannel = me.buildCacheChannel(dbName,tableNames);
|
||||
me.channelCache[cacheKey] = cacheChannel;
|
||||
|
||||
return cacheChannel;
|
||||
},
|
||||
function finish(err, cacheChannel) {
|
||||
callback(err, cacheChannel);
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
// Set the cache chanel info to invalidate the cache on the frontend server
|
||||
@@ -245,11 +202,11 @@ module.exports = function(redisPool) {
|
||||
me.addCacheChannel = function(app, req, cb) {
|
||||
// skip non-GET requests, or requests for which there's no response
|
||||
if ( req.method != 'GET' || ! req.res ) { cb(null, null); return; }
|
||||
if (req.profiler) req.profiler.start('addCacheChannel');
|
||||
if (req.profiler) {
|
||||
req.profiler.start('addCacheChannel');
|
||||
}
|
||||
var res = req.res;
|
||||
var cache_policy = req.query.cache_policy;
|
||||
if ( req.params.token ) cache_policy = 'persist';
|
||||
if ( cache_policy == 'persist' ) {
|
||||
if ( req.params.token ) {
|
||||
res.header('Cache-Control', 'public,max-age=31536000'); // 1 year
|
||||
} else {
|
||||
var ttl = global.environment.varnish.ttl || 86400;
|
||||
@@ -268,8 +225,10 @@ module.exports = function(redisPool) {
|
||||
res.header('Last-Modified', lastUpdated.toUTCString());
|
||||
|
||||
me.generateCacheChannel(app, req, function(err, channel){
|
||||
if (req.profiler) req.profiler.done('generateCacheChannel');
|
||||
if (req.profiler) req.profiler.end();
|
||||
if (req.profiler) {
|
||||
req.profiler.done('generateCacheChannel');
|
||||
req.profiler.end();
|
||||
}
|
||||
if ( ! err ) {
|
||||
res.header('X-Cache-Channel', channel);
|
||||
cb(null, channel);
|
||||
@@ -282,7 +241,7 @@ module.exports = function(redisPool) {
|
||||
};
|
||||
|
||||
me.beforeLayergroupCreate = function(req, requestMapConfig, callback) {
|
||||
mapConfigNamedLayersAdapter.getLayers(this.userByReq(req), requestMapConfig.layers, pgConnection,
|
||||
mapConfigNamedLayersAdapter.getLayers(cdbRequest.userByReq(req), requestMapConfig.layers, pgConnection,
|
||||
function(err, layers, datasource) {
|
||||
if (err) {
|
||||
return callback(err);
|
||||
@@ -297,7 +256,7 @@ module.exports = function(redisPool) {
|
||||
me.afterLayergroupCreate = function(req, mapconfig, response, callback) {
|
||||
var token = response.layergroupid;
|
||||
|
||||
var username = this.userByReq(req);
|
||||
var username = cdbRequest.userByReq(req);
|
||||
|
||||
var tasksleft = 2; // redis key and affectedTables
|
||||
var errors = [];
|
||||
@@ -324,8 +283,12 @@ module.exports = function(redisPool) {
|
||||
// take place before proceeding. Error will be logged
|
||||
// asyncronously
|
||||
cartoData.incMapviewCount(username, mapconfig.stat_tag, function(err) {
|
||||
if (req.profiler) req.profiler.done('incMapviewCount');
|
||||
if ( err ) console.log("ERROR: failed to increment mapview count for user '" + username + "': " + err);
|
||||
if (req.profiler) {
|
||||
req.profiler.done('incMapviewCount');
|
||||
}
|
||||
if ( err ) {
|
||||
console.log("ERROR: failed to increment mapview count for user '" + username + "': " + err);
|
||||
}
|
||||
done();
|
||||
});
|
||||
|
||||
@@ -341,19 +304,17 @@ module.exports = function(redisPool) {
|
||||
queryTablesApi.getAffectedTablesAndLastUpdatedTime(username, sql, this);
|
||||
},
|
||||
function handleAffectedTablesAndLastUpdatedTime(err, result) {
|
||||
if (req.profiler) req.profiler.done('queryTablesAndLastUpdated');
|
||||
if ( err ) throw err;
|
||||
if (req.profiler) {
|
||||
req.profiler.done('queryTablesAndLastUpdated');
|
||||
}
|
||||
assert.ifError(err);
|
||||
var cacheChannel = me.buildCacheChannel(dbName, result.affectedTables);
|
||||
me.channelCache[cacheKey] = cacheChannel;
|
||||
|
||||
if (req.res && req.method == 'GET') {
|
||||
var res = req.res;
|
||||
if ( req.query && req.query.cache_policy == 'persist' ) {
|
||||
res.header('Cache-Control', 'public,max-age=31536000'); // 1 year
|
||||
} else {
|
||||
var ttl = global.environment.varnish.layergroupTtl || 86400;
|
||||
res.header('Cache-Control', 'public,max-age='+ttl+',must-revalidate');
|
||||
}
|
||||
var ttl = global.environment.varnish.layergroupTtl || 86400;
|
||||
res.header('Cache-Control', 'public,max-age='+ttl+',must-revalidate');
|
||||
res.header('Last-Modified', (new Date()).toUTCString());
|
||||
res.header('X-Cache-Channel', cacheChannel);
|
||||
}
|
||||
@@ -371,30 +332,6 @@ module.exports = function(redisPool) {
|
||||
|
||||
/* X-Cache-Channel generation } */
|
||||
|
||||
me.re_userFromHost = new RegExp(
|
||||
global.environment.user_from_host ||
|
||||
'^([^\\.]+)\\.' // would extract "strk" from "strk.cartodb.com"
|
||||
);
|
||||
|
||||
me.userByReq = function(req) {
|
||||
var host = req.headers.host;
|
||||
if (req.params.user) {
|
||||
return req.params.user;
|
||||
}
|
||||
var mat = host.match(this.re_userFromHost);
|
||||
if ( ! mat ) {
|
||||
console.error("ERROR: user pattern '" + this.re_userFromHost + "' does not match hostname '" + host + "'");
|
||||
return;
|
||||
}
|
||||
// console.log("Matches: "); console.dir(mat);
|
||||
if ( mat.length !== 2 ) {
|
||||
console.error("ERROR: pattern '" + this.re_userFromHost + "' gave unexpected matches against '" + host + "': " +
|
||||
mat);
|
||||
return;
|
||||
}
|
||||
return mat[1];
|
||||
};
|
||||
|
||||
// Check if a request is authorized by a signer
|
||||
//
|
||||
// @param req express request object
|
||||
@@ -402,34 +339,27 @@ module.exports = function(redisPool) {
|
||||
// null if the request is not signed by anyone
|
||||
// or will be a string cartodb username otherwise.
|
||||
//
|
||||
me.authorizedBySigner = function(req, callback)
|
||||
{
|
||||
if ( ! req.params.token || ! req.params.signer ) {
|
||||
//console.log("No signature provided"); // debugging
|
||||
callback(null, null); // no signer requested
|
||||
return;
|
||||
}
|
||||
|
||||
var signer = req.params.signer;
|
||||
var layergroup_id = req.params.token;
|
||||
var auth_token = req.params.auth_token;
|
||||
|
||||
//console.log("Checking authorization from signer " + signer + " for resource " + layergroup_id +
|
||||
// " with auth_token " + auth_token);
|
||||
var mapStore = req.app.mapStore;
|
||||
if (!mapStore) {
|
||||
throw new Error('Unable to retrieve map configuration token');
|
||||
}
|
||||
|
||||
mapStore.load(layergroup_id, function(err, mapConfig) {
|
||||
if (err) {
|
||||
throw err;
|
||||
me.authorizedBySigner = function(req, callback) {
|
||||
if ( ! req.params.token || ! req.params.signer ) {
|
||||
return callback(null, null); // no signer requested
|
||||
}
|
||||
|
||||
var authorized = me.templateMaps.isAuthorized(mapConfig.obj().template, auth_token);
|
||||
callback(null, authorized ? signer : null);
|
||||
});
|
||||
var signer = req.params.signer;
|
||||
var layergroup_id = req.params.token;
|
||||
var auth_token = req.params.auth_token;
|
||||
|
||||
var mapStore = req.app.mapStore;
|
||||
if (!mapStore) {
|
||||
throw new Error('Unable to retrieve map configuration token');
|
||||
}
|
||||
|
||||
mapStore.load(layergroup_id, function(err, mapConfig) {
|
||||
assert.ifError(err);
|
||||
|
||||
var authorized = me.templateMaps.isAuthorized(mapConfig.obj().template, auth_token);
|
||||
|
||||
return callback(null, authorized ? signer : null);
|
||||
});
|
||||
};
|
||||
|
||||
// Check if a request is authorized by api_key
|
||||
@@ -450,13 +380,13 @@ module.exports = function(redisPool) {
|
||||
return;
|
||||
}
|
||||
//console.log("given ApiKey: " + givenKey);
|
||||
var user = me.userByReq(req);
|
||||
var user = cdbRequest.userByReq(req);
|
||||
step(
|
||||
function (){
|
||||
cartoData.getUserMapKey(user, this);
|
||||
},
|
||||
function checkApiKey(err, val){
|
||||
if (err) throw err;
|
||||
assert.ifError(err);
|
||||
return ( val && givenKey == val ) ? 1 : 0;
|
||||
},
|
||||
function finish(err, authorized) {
|
||||
@@ -473,15 +403,17 @@ module.exports = function(redisPool) {
|
||||
*/
|
||||
me.authorize = function(req, callback) {
|
||||
var that = this;
|
||||
var user = me.userByReq(req);
|
||||
var user = cdbRequest.userByReq(req);
|
||||
|
||||
step(
|
||||
function (){
|
||||
that.authorizedByAPIKey(req, this);
|
||||
},
|
||||
function checkApiKey(err, authorized){
|
||||
if (req.profiler) req.profiler.done('authorizedByAPIKey');
|
||||
if (err) throw err;
|
||||
if (req.profiler) {
|
||||
req.profiler.done('authorizedByAPIKey');
|
||||
}
|
||||
assert.ifError(err);
|
||||
|
||||
// if not authorized by api_key, continue
|
||||
if (authorized !== 1) {
|
||||
@@ -491,28 +423,16 @@ module.exports = function(redisPool) {
|
||||
return;
|
||||
}
|
||||
|
||||
_.extend(req.params, { _authorizedByApiKey: true });
|
||||
|
||||
// authorized by api key, login as the given username and stop
|
||||
pgConnection.setDBAuth(user, req.params, function(err) {
|
||||
callback(err, true); // authorized (or error)
|
||||
});
|
||||
},
|
||||
function checkSignAuthorized(err, signed_by){
|
||||
if (err) throw err;
|
||||
if (req.profiler) {
|
||||
if ( req.params._authorizedByApiKey ) {
|
||||
req.profiler.done('setDBAuth');
|
||||
} else {
|
||||
req.profiler.done('authorizedBySigner');
|
||||
}
|
||||
}
|
||||
assert.ifError(err);
|
||||
|
||||
if ( ! signed_by ) {
|
||||
// request not authorized by signer.
|
||||
|
||||
// if table was given, continue to check table privacy
|
||||
if ( req.params.table ) return null;
|
||||
|
||||
// if no signer name was given, let dbparams and
|
||||
// PostgreSQL do the rest.
|
||||
@@ -527,26 +447,12 @@ module.exports = function(redisPool) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Authorized by "signed_by" !
|
||||
_.extend(req.params, { _authorizedBySigner: signed_by });
|
||||
pgConnection.setDBAuth(signed_by, req.params, function(err) {
|
||||
if (req.profiler) req.profiler.done('setDBAuth');
|
||||
if (req.profiler) {
|
||||
req.profiler.done('setDBAuth');
|
||||
}
|
||||
callback(err, true); // authorized (or error)
|
||||
});
|
||||
},
|
||||
function getDatabase(err){
|
||||
if (err) throw err;
|
||||
// NOTE: only used to get to table privacy
|
||||
cartoData.getUserDBName(user, this);
|
||||
},
|
||||
function getPrivacy(err, dbname){
|
||||
if (err) throw err;
|
||||
if (req.profiler) req.profiler.done('tablePrivacy_getUserDBName');
|
||||
cartoData.getTablePrivacy(dbname, req.params.table, this);
|
||||
},
|
||||
function(err, privacy){
|
||||
if (req.profiler) req.profiler.done('getTablePrivacy');
|
||||
callback(err, privacy !== "0");
|
||||
}
|
||||
);
|
||||
};
|
||||
@@ -562,9 +468,6 @@ module.exports = function(redisPool) {
|
||||
|
||||
if ( req.query.lzma ) {
|
||||
|
||||
// TODO: check ?
|
||||
//console.log("type of req.query.lzma is " + typeof(req.query.lzma));
|
||||
|
||||
// Decode (from base64)
|
||||
var lzma = new Buffer(req.query.lzma, 'base64')
|
||||
.toString('binary')
|
||||
@@ -577,7 +480,9 @@ module.exports = function(redisPool) {
|
||||
lzmaWorker.decompress(
|
||||
lzma,
|
||||
function(result) {
|
||||
if (req.profiler) req.profiler.done('LZMA decompress');
|
||||
if (req.profiler) {
|
||||
req.profiler.done('lzma');
|
||||
}
|
||||
try {
|
||||
delete req.query.lzma;
|
||||
_.extend(req.query, JSON.parse(result));
|
||||
@@ -585,30 +490,29 @@ module.exports = function(redisPool) {
|
||||
} catch (err) {
|
||||
callback(new Error('Error parsing lzma as JSON: ' + err));
|
||||
}
|
||||
},
|
||||
function(/*percent*/) { // progress
|
||||
//console.log("LZMA decompression " + percent + "%");
|
||||
}
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
var bad_query = _.difference(_.keys(req.query), REQUEST_QUERY_PARAMS_WHITELIST);
|
||||
req.query = _.pick(req.query, REQUEST_QUERY_PARAMS_WHITELIST);
|
||||
req.params = _.extend({}, req.params); // shuffle things as request is a strange array/object
|
||||
|
||||
_.each(bad_query, function(key){ delete req.query[key]; });
|
||||
req.params = _.extend({}, req.params); // shuffle things as request is a strange array/object
|
||||
|
||||
var user = me.userByReq(req);
|
||||
var user = cdbRequest.userByReq(req);
|
||||
|
||||
if ( req.params.token ) {
|
||||
//console.log("Request parameters include token " + req.params.token);
|
||||
var tksplit = req.params.token.split(':');
|
||||
req.params.token = tksplit[0];
|
||||
if ( tksplit.length > 1 ) req.params.cache_buster= tksplit[1];
|
||||
if ( tksplit.length > 1 ) {
|
||||
req.params.cache_buster= tksplit[1];
|
||||
}
|
||||
tksplit = req.params.token.split('@');
|
||||
if ( tksplit.length > 1 ) {
|
||||
req.params.signer = tksplit.shift();
|
||||
if ( ! req.params.signer ) req.params.signer = user;
|
||||
if ( ! req.params.signer ) {
|
||||
req.params.signer = user;
|
||||
}
|
||||
else if ( req.params.signer !== user ) {
|
||||
var err = new Error('Cannot use map signature of user "' + req.params.signer + '" on database of user "' +
|
||||
user + '"');
|
||||
@@ -627,18 +531,19 @@ module.exports = function(redisPool) {
|
||||
// bring all query values onto req.params object
|
||||
_.extend(req.params, req.query);
|
||||
|
||||
// for cartodb, ensure interactivity is cartodb_id or user specified
|
||||
req.params.interactivity = req.params.interactivity || 'cartodb_id';
|
||||
|
||||
if (req.profiler) req.profiler.done('req2params.setup');
|
||||
if (req.profiler) {
|
||||
req.profiler.done('req2params.setup');
|
||||
}
|
||||
|
||||
step(
|
||||
function getPrivacy(){
|
||||
me.authorize(req, this);
|
||||
},
|
||||
function gatekeep(err, authorized){
|
||||
if (req.profiler) req.profiler.done('authorize');
|
||||
if(err) throw err;
|
||||
if (req.profiler) {
|
||||
req.profiler.done('authorize');
|
||||
}
|
||||
assert.ifError(err);
|
||||
if(!authorized) {
|
||||
err = new Error("Sorry, you are unauthorized (permission denied)");
|
||||
err.http_status = 403;
|
||||
@@ -647,21 +552,12 @@ module.exports = function(redisPool) {
|
||||
return null;
|
||||
},
|
||||
function getDatabase(err){
|
||||
if(err) throw err;
|
||||
assert.ifError(err);
|
||||
pgConnection.setDBConn(user, req.params, this);
|
||||
},
|
||||
function getGeometryType(err){
|
||||
if (req.profiler) req.profiler.done('setDBConn');
|
||||
if (err) throw err;
|
||||
if ( ! req.params.table ) return null;
|
||||
cartoData.getTableGeometryType(req.params.dbname, req.params.table, this);
|
||||
},
|
||||
function finishSetup(err, data){
|
||||
function finishSetup(err) {
|
||||
if ( err ) { callback(err, req); return; }
|
||||
|
||||
if (!_.isNull(data))
|
||||
_.extend(req.params, {geom_type: data});
|
||||
|
||||
// Add default database connection parameters
|
||||
// if none given
|
||||
_.defaults(req.params, {
|
||||
@@ -676,61 +572,5 @@ module.exports = function(redisPool) {
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* Little helper method to get the current list of infowindow variables and return to client
|
||||
* @param req
|
||||
* @param callback
|
||||
*/
|
||||
me.getInfowindow = function(req, callback){
|
||||
var that = this;
|
||||
var user = me.userByReq(req);
|
||||
|
||||
step(
|
||||
function(){
|
||||
// TODO: if this step really needed ?
|
||||
that.req2params(req, this);
|
||||
},
|
||||
function getDatabase(err){
|
||||
if (err) throw err;
|
||||
cartoData.getUserDBName(user, this);
|
||||
},
|
||||
function getInfowindow(err, dbname){
|
||||
if (err) throw err;
|
||||
cartoData.getTableInfowindow(dbname, req.params.table, this);
|
||||
},
|
||||
function(err, data){
|
||||
callback(err, data);
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* Little helper method to get map metadata and return to client
|
||||
* @param req
|
||||
* @param callback
|
||||
*/
|
||||
me.getMapMetadata = function(req, callback){
|
||||
var that = this;
|
||||
var user = me.userByReq(req);
|
||||
|
||||
step(
|
||||
function(){
|
||||
// TODO: if this step really needed ?
|
||||
that.req2params(req, this);
|
||||
},
|
||||
function getDatabase(err){
|
||||
if (err) throw err;
|
||||
cartoData.getUserDBName(user, this);
|
||||
},
|
||||
function getMapMetadata(err, dbname){
|
||||
if (err) throw err;
|
||||
cartoData.getTableMapMetadata(dbname, req.params.table, this);
|
||||
},
|
||||
function(err, data){
|
||||
callback(err, data);
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
return me;
|
||||
};
|
||||
|
||||
@@ -1,66 +0,0 @@
|
||||
var _ = require('underscore'),
|
||||
request = require('request');
|
||||
|
||||
module.exports.query = function (username, api_key, sql, callback) {
|
||||
var api = global.environment.sqlapi;
|
||||
|
||||
// build up api string
|
||||
var sqlapihostname = username;
|
||||
if ( api.domain ) sqlapihostname += '.' + api.domain;
|
||||
|
||||
var sqlapi = api.protocol + '://';
|
||||
if ( api.host && api.host != api.domain ) sqlapi += api.host;
|
||||
else sqlapi += sqlapihostname;
|
||||
sqlapi += ':' + api.port + '/api/' + api.version + '/sql';
|
||||
|
||||
var qs = { q: sql };
|
||||
|
||||
// add api_key if given
|
||||
if (_.isString(api_key) && api_key !== '') { qs.api_key = api_key; }
|
||||
|
||||
// call sql api
|
||||
//
|
||||
// NOTE: using POST to avoid size limits:
|
||||
// See http://github.com/CartoDB/Windshaft-cartodb/issues/111
|
||||
//
|
||||
// NOTE: uses "host" header to allow IP based specification
|
||||
// of sqlapi address (and avoid a DNS lookup)
|
||||
//
|
||||
// NOTE: allows for keeping up to "maxConnections" concurrent
|
||||
// sockets opened per SQL-API host.
|
||||
// See http://nodejs.org/api/http.html#http_agent_maxsockets
|
||||
//
|
||||
var maxSockets = global.environment.maxConnections || 128;
|
||||
var maxGetLen = api.max_get_sql_length || 2048;
|
||||
var maxSQLTime = api.timeout || 100; // 1/10 of a second by default
|
||||
var reqSpec = {
|
||||
url:sqlapi,
|
||||
json:true,
|
||||
headers:{host: sqlapihostname},
|
||||
// http://nodejs.org/api/http.html#http_agent_maxsockets
|
||||
pool:{maxSockets:maxSockets},
|
||||
// timeout in milliseconds
|
||||
timeout:maxSQLTime
|
||||
};
|
||||
if ( sql.length > maxGetLen ) {
|
||||
reqSpec.method = 'POST';
|
||||
reqSpec.body = qs;
|
||||
} else {
|
||||
reqSpec.method = 'GET';
|
||||
reqSpec.qs = qs;
|
||||
}
|
||||
request(reqSpec, function(err, res, body) {
|
||||
if (err){
|
||||
console.log('ERROR connecting to SQL API on ' + sqlapi + ': ' + err);
|
||||
callback(err);
|
||||
return;
|
||||
}
|
||||
if (res.statusCode != 200) {
|
||||
var msg = res.body.error ? res.body.error : res.body;
|
||||
callback(new Error(msg));
|
||||
console.log('unexpected response status (' + res.statusCode + ') for sql query: ' + sql + ': ' + msg);
|
||||
return;
|
||||
}
|
||||
callback(null, body.rows);
|
||||
});
|
||||
};
|
||||
Generated
+106
-56
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "windshaft-cartodb",
|
||||
"version": "1.30.1",
|
||||
"version": "2.0.0",
|
||||
"dependencies": {
|
||||
"cartodb-psql": {
|
||||
"version": "0.4.0",
|
||||
@@ -14,11 +14,13 @@
|
||||
"dependencies": {
|
||||
"generic-pool": {
|
||||
"version": "2.0.3",
|
||||
"from": "generic-pool@2.0.3"
|
||||
"from": "generic-pool@2.0.3",
|
||||
"resolved": "https://registry.npmjs.org/generic-pool/-/generic-pool-2.0.3.tgz"
|
||||
},
|
||||
"buffer-writer": {
|
||||
"version": "1.0.0",
|
||||
"from": "buffer-writer@1.0.0"
|
||||
"from": "buffer-writer@1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/buffer-writer/-/buffer-writer-1.0.0.tgz"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -36,19 +38,23 @@
|
||||
"dependencies": {
|
||||
"generic-pool": {
|
||||
"version": "2.1.1",
|
||||
"from": "generic-pool@~2.1.1"
|
||||
"from": "generic-pool@~2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/generic-pool/-/generic-pool-2.1.1.tgz"
|
||||
},
|
||||
"redis": {
|
||||
"version": "0.12.1",
|
||||
"from": "redis@~0.12.1"
|
||||
"from": "redis@~0.12.1",
|
||||
"resolved": "https://registry.npmjs.org/redis/-/redis-0.12.1.tgz"
|
||||
},
|
||||
"hiredis": {
|
||||
"version": "0.1.17",
|
||||
"from": "hiredis@~0.1.17",
|
||||
"resolved": "https://registry.npmjs.org/hiredis/-/hiredis-0.1.17.tgz",
|
||||
"dependencies": {
|
||||
"bindings": {
|
||||
"version": "1.2.1",
|
||||
"from": "bindings@*"
|
||||
"from": "bindings@*",
|
||||
"resolved": "https://registry.npmjs.org/bindings/-/bindings-1.2.1.tgz"
|
||||
},
|
||||
"nan": {
|
||||
"version": "1.1.2",
|
||||
@@ -83,7 +89,8 @@
|
||||
"dependencies": {
|
||||
"core-util-is": {
|
||||
"version": "1.0.1",
|
||||
"from": "core-util-is@~1.0.0"
|
||||
"from": "core-util-is@~1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.1.tgz"
|
||||
},
|
||||
"isarray": {
|
||||
"version": "0.0.1",
|
||||
@@ -92,11 +99,13 @@
|
||||
},
|
||||
"string_decoder": {
|
||||
"version": "0.10.31",
|
||||
"from": "string_decoder@~0.10.x"
|
||||
"from": "string_decoder@~0.10.x",
|
||||
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz"
|
||||
},
|
||||
"inherits": {
|
||||
"version": "2.0.1",
|
||||
"from": "inherits@2"
|
||||
"from": "inherits@~2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -107,11 +116,6 @@
|
||||
"from": "lzma@~1.3.7",
|
||||
"resolved": "https://registry.npmjs.org/lzma/-/lzma-1.3.7.tgz"
|
||||
},
|
||||
"node-varnish": {
|
||||
"version": "0.3.0",
|
||||
"from": "https://github.com/Vizzuality/node-varnish/tarball/0.3.0",
|
||||
"resolved": "https://github.com/Vizzuality/node-varnish/tarball/0.3.0"
|
||||
},
|
||||
"queue-async": {
|
||||
"version": "1.0.7",
|
||||
"from": "queue-async@~1.0.7",
|
||||
@@ -124,19 +128,23 @@
|
||||
"dependencies": {
|
||||
"generic-pool": {
|
||||
"version": "2.1.1",
|
||||
"from": "generic-pool@~2.1.1"
|
||||
"from": "generic-pool@~2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/generic-pool/-/generic-pool-2.1.1.tgz"
|
||||
},
|
||||
"redis": {
|
||||
"version": "0.12.1",
|
||||
"from": "redis@~0.12.1"
|
||||
"from": "redis@~0.12.1",
|
||||
"resolved": "https://registry.npmjs.org/redis/-/redis-0.12.1.tgz"
|
||||
},
|
||||
"hiredis": {
|
||||
"version": "0.1.17",
|
||||
"from": "hiredis@~0.1.17",
|
||||
"resolved": "https://registry.npmjs.org/hiredis/-/hiredis-0.1.17.tgz",
|
||||
"dependencies": {
|
||||
"bindings": {
|
||||
"version": "1.2.1",
|
||||
"from": "bindings@*"
|
||||
"from": "bindings@*",
|
||||
"resolved": "https://registry.npmjs.org/bindings/-/bindings-1.2.1.tgz"
|
||||
},
|
||||
"nan": {
|
||||
"version": "1.1.2",
|
||||
@@ -164,17 +172,20 @@
|
||||
},
|
||||
"lru-cache": {
|
||||
"version": "2.2.4",
|
||||
"from": "lru-cache@~2.2.1"
|
||||
"from": "lru-cache@~2.2.1",
|
||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.2.4.tgz"
|
||||
},
|
||||
"json-stringify-safe": {
|
||||
"version": "5.0.0",
|
||||
"from": "json-stringify-safe@~5.0.0"
|
||||
"from": "json-stringify-safe@~5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.0.tgz"
|
||||
}
|
||||
}
|
||||
},
|
||||
"step": {
|
||||
"version": "0.0.5",
|
||||
"from": "step@~0.0.5"
|
||||
"from": "step@~0.0.5",
|
||||
"resolved": "https://registry.npmjs.org/step/-/step-0.0.5.tgz"
|
||||
},
|
||||
"underscore": {
|
||||
"version": "1.6.0",
|
||||
@@ -182,8 +193,9 @@
|
||||
"resolved": "https://registry.npmjs.org/underscore/-/underscore-1.6.0.tgz"
|
||||
},
|
||||
"windshaft": {
|
||||
"version": "0.40.0",
|
||||
"from": "windshaft@~0.40.0",
|
||||
"version": "0.41.0",
|
||||
"from": "https://github.com/CartoDB/Windshaft/tarball/master",
|
||||
"resolved": "https://github.com/CartoDB/Windshaft/tarball/master",
|
||||
"dependencies": {
|
||||
"chronograph": {
|
||||
"version": "0.1.0",
|
||||
@@ -193,6 +205,7 @@
|
||||
"grainstore": {
|
||||
"version": "0.23.0",
|
||||
"from": "grainstore@~0.23.0",
|
||||
"resolved": "https://registry.npmjs.org/grainstore/-/grainstore-0.23.0.tgz",
|
||||
"dependencies": {
|
||||
"redis-mpool": {
|
||||
"version": "0.1.0",
|
||||
@@ -201,19 +214,23 @@
|
||||
"dependencies": {
|
||||
"generic-pool": {
|
||||
"version": "2.1.1",
|
||||
"from": "generic-pool@~2.1.1"
|
||||
"from": "generic-pool@~2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/generic-pool/-/generic-pool-2.1.1.tgz"
|
||||
},
|
||||
"redis": {
|
||||
"version": "0.12.1",
|
||||
"from": "redis@~0.12.1"
|
||||
"from": "redis@~0.12.1",
|
||||
"resolved": "https://registry.npmjs.org/redis/-/redis-0.12.1.tgz"
|
||||
},
|
||||
"hiredis": {
|
||||
"version": "0.1.17",
|
||||
"from": "hiredis@~0.1.17",
|
||||
"resolved": "https://registry.npmjs.org/hiredis/-/hiredis-0.1.17.tgz",
|
||||
"dependencies": {
|
||||
"bindings": {
|
||||
"version": "1.2.1",
|
||||
"from": "bindings@*"
|
||||
"from": "bindings@*",
|
||||
"resolved": "https://registry.npmjs.org/bindings/-/bindings-1.2.1.tgz"
|
||||
},
|
||||
"nan": {
|
||||
"version": "1.1.2",
|
||||
@@ -246,7 +263,8 @@
|
||||
"dependencies": {
|
||||
"sax": {
|
||||
"version": "0.5.8",
|
||||
"from": "sax@0.5.x"
|
||||
"from": "sax@0.5.x",
|
||||
"resolved": "https://registry.npmjs.org/sax/-/sax-0.5.8.tgz"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -262,7 +280,8 @@
|
||||
},
|
||||
"minimist": {
|
||||
"version": "0.0.10",
|
||||
"from": "minimist@~0.0.1"
|
||||
"from": "minimist@~0.0.1",
|
||||
"resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -275,7 +294,8 @@
|
||||
"dependencies": {
|
||||
"generic-pool": {
|
||||
"version": "2.0.4",
|
||||
"from": "generic-pool@~2.0.3"
|
||||
"from": "generic-pool@~2.0.3",
|
||||
"resolved": "https://registry.npmjs.org/generic-pool/-/generic-pool-2.0.4.tgz"
|
||||
},
|
||||
"request": {
|
||||
"version": "2.34.0",
|
||||
@@ -284,15 +304,18 @@
|
||||
"dependencies": {
|
||||
"qs": {
|
||||
"version": "0.6.6",
|
||||
"from": "qs@~0.6.0"
|
||||
"from": "qs@~0.6.0",
|
||||
"resolved": "https://registry.npmjs.org/qs/-/qs-0.6.6.tgz"
|
||||
},
|
||||
"json-stringify-safe": {
|
||||
"version": "5.0.0",
|
||||
"from": "json-stringify-safe@~5.0.0"
|
||||
"from": "json-stringify-safe@~5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.0.tgz"
|
||||
},
|
||||
"forever-agent": {
|
||||
"version": "0.5.2",
|
||||
"from": "forever-agent@~0.5.0"
|
||||
"from": "forever-agent@~0.5.0",
|
||||
"resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.5.2.tgz"
|
||||
},
|
||||
"node-uuid": {
|
||||
"version": "1.4.3",
|
||||
@@ -302,6 +325,7 @@
|
||||
"tough-cookie": {
|
||||
"version": "0.12.1",
|
||||
"from": "tough-cookie@>=0.12.0",
|
||||
"resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-0.12.1.tgz",
|
||||
"dependencies": {
|
||||
"punycode": {
|
||||
"version": "1.3.2",
|
||||
@@ -313,6 +337,7 @@
|
||||
"form-data": {
|
||||
"version": "0.1.4",
|
||||
"from": "form-data@~0.1.0",
|
||||
"resolved": "https://registry.npmjs.org/form-data/-/form-data-0.1.4.tgz",
|
||||
"dependencies": {
|
||||
"combined-stream": {
|
||||
"version": "0.0.7",
|
||||
@@ -335,7 +360,8 @@
|
||||
},
|
||||
"tunnel-agent": {
|
||||
"version": "0.3.0",
|
||||
"from": "tunnel-agent@~0.3.0"
|
||||
"from": "tunnel-agent@~0.3.0",
|
||||
"resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.3.0.tgz"
|
||||
},
|
||||
"http-signature": {
|
||||
"version": "0.10.1",
|
||||
@@ -361,7 +387,8 @@
|
||||
},
|
||||
"oauth-sign": {
|
||||
"version": "0.3.0",
|
||||
"from": "oauth-sign@~0.3.0"
|
||||
"from": "oauth-sign@~0.3.0",
|
||||
"resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.3.0.tgz"
|
||||
},
|
||||
"hawk": {
|
||||
"version": "1.0.0",
|
||||
@@ -380,17 +407,20 @@
|
||||
},
|
||||
"cryptiles": {
|
||||
"version": "0.2.2",
|
||||
"from": "cryptiles@0.2.x"
|
||||
"from": "cryptiles@0.2.x",
|
||||
"resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-0.2.2.tgz"
|
||||
},
|
||||
"sntp": {
|
||||
"version": "0.2.4",
|
||||
"from": "sntp@0.2.x"
|
||||
"from": "sntp@0.2.x",
|
||||
"resolved": "https://registry.npmjs.org/sntp/-/sntp-0.2.4.tgz"
|
||||
}
|
||||
}
|
||||
},
|
||||
"aws-sign2": {
|
||||
"version": "0.5.0",
|
||||
"from": "aws-sign2@~0.5.0"
|
||||
"from": "aws-sign2@~0.5.0",
|
||||
"resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.5.0.tgz"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -1631,7 +1661,8 @@
|
||||
},
|
||||
"mkdirp": {
|
||||
"version": "0.3.5",
|
||||
"from": "mkdirp@~0.3.3"
|
||||
"from": "mkdirp@~0.3.3",
|
||||
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.3.5.tgz"
|
||||
},
|
||||
"optimist": {
|
||||
"version": "0.6.1",
|
||||
@@ -1645,7 +1676,8 @@
|
||||
},
|
||||
"minimist": {
|
||||
"version": "0.0.10",
|
||||
"from": "minimist@~0.0.1"
|
||||
"from": "minimist@~0.0.1",
|
||||
"resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1704,7 +1736,8 @@
|
||||
},
|
||||
"minimist": {
|
||||
"version": "0.0.10",
|
||||
"from": "minimist@~0.0.1"
|
||||
"from": "minimist@~0.0.1",
|
||||
"resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1717,7 +1750,8 @@
|
||||
"dependencies": {
|
||||
"generic-pool": {
|
||||
"version": "2.1.1",
|
||||
"from": "generic-pool@~2.1.1"
|
||||
"from": "generic-pool@~2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/generic-pool/-/generic-pool-2.1.1.tgz"
|
||||
},
|
||||
"mime": {
|
||||
"version": "1.2.11",
|
||||
@@ -1733,7 +1767,8 @@
|
||||
"dependencies": {
|
||||
"nan": {
|
||||
"version": "1.2.0",
|
||||
"from": "nan@~1.2.0"
|
||||
"from": "nan@~1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/nan/-/nan-1.2.0.tgz"
|
||||
},
|
||||
"mapnik-vector-tile": {
|
||||
"version": "0.5.5",
|
||||
@@ -2144,7 +2179,8 @@
|
||||
},
|
||||
"minimist": {
|
||||
"version": "0.0.10",
|
||||
"from": "minimist@~0.0.1"
|
||||
"from": "minimist@~0.0.1",
|
||||
"resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2152,11 +2188,13 @@
|
||||
},
|
||||
"step-profiler": {
|
||||
"version": "0.2.1",
|
||||
"from": "step-profiler@~0.2.1"
|
||||
"from": "step-profiler@~0.2.1",
|
||||
"resolved": "https://registry.npmjs.org/step-profiler/-/step-profiler-0.2.1.tgz"
|
||||
},
|
||||
"torque.js": {
|
||||
"version": "2.11.0",
|
||||
"from": "torque.js@~2.11.0"
|
||||
"from": "torque.js@~2.11.0",
|
||||
"resolved": "https://registry.npmjs.org/torque.js/-/torque.js-2.11.0.tgz"
|
||||
},
|
||||
"request": {
|
||||
"version": "2.48.0",
|
||||
@@ -2175,7 +2213,8 @@
|
||||
"dependencies": {
|
||||
"core-util-is": {
|
||||
"version": "1.0.1",
|
||||
"from": "core-util-is@~1.0.0"
|
||||
"from": "core-util-is@~1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.1.tgz"
|
||||
},
|
||||
"isarray": {
|
||||
"version": "0.0.1",
|
||||
@@ -2184,11 +2223,13 @@
|
||||
},
|
||||
"string_decoder": {
|
||||
"version": "0.10.31",
|
||||
"from": "string_decoder@~0.10.x"
|
||||
"from": "string_decoder@~0.10.x",
|
||||
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz"
|
||||
},
|
||||
"inherits": {
|
||||
"version": "2.0.1",
|
||||
"from": "inherits@~2.0.1"
|
||||
"from": "inherits@~2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2201,11 +2242,13 @@
|
||||
},
|
||||
"forever-agent": {
|
||||
"version": "0.5.2",
|
||||
"from": "forever-agent@~0.5.0"
|
||||
"from": "forever-agent@~0.5.0",
|
||||
"resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.5.2.tgz"
|
||||
},
|
||||
"form-data": {
|
||||
"version": "0.1.4",
|
||||
"from": "form-data@~0.1.0",
|
||||
"resolved": "https://registry.npmjs.org/form-data/-/form-data-0.1.4.tgz",
|
||||
"dependencies": {
|
||||
"mime": {
|
||||
"version": "1.2.11",
|
||||
@@ -2221,7 +2264,8 @@
|
||||
},
|
||||
"json-stringify-safe": {
|
||||
"version": "5.0.0",
|
||||
"from": "json-stringify-safe@~5.0.0"
|
||||
"from": "json-stringify-safe@~5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.0.tgz"
|
||||
},
|
||||
"mime-types": {
|
||||
"version": "1.0.2",
|
||||
@@ -2240,11 +2284,13 @@
|
||||
},
|
||||
"tunnel-agent": {
|
||||
"version": "0.4.0",
|
||||
"from": "tunnel-agent@~0.4.0"
|
||||
"from": "tunnel-agent@~0.4.0",
|
||||
"resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.4.0.tgz"
|
||||
},
|
||||
"tough-cookie": {
|
||||
"version": "0.12.1",
|
||||
"from": "tough-cookie@>=0.12.0",
|
||||
"resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-0.12.1.tgz",
|
||||
"dependencies": {
|
||||
"punycode": {
|
||||
"version": "1.3.2",
|
||||
@@ -2297,21 +2343,25 @@
|
||||
},
|
||||
"cryptiles": {
|
||||
"version": "0.2.2",
|
||||
"from": "cryptiles@0.2.x"
|
||||
"from": "cryptiles@0.2.x",
|
||||
"resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-0.2.2.tgz"
|
||||
},
|
||||
"sntp": {
|
||||
"version": "0.2.4",
|
||||
"from": "sntp@0.2.x"
|
||||
"from": "sntp@0.2.x",
|
||||
"resolved": "https://registry.npmjs.org/sntp/-/sntp-0.2.4.tgz"
|
||||
}
|
||||
}
|
||||
},
|
||||
"aws-sign2": {
|
||||
"version": "0.5.0",
|
||||
"from": "aws-sign2@~0.5.0"
|
||||
"from": "aws-sign2@~0.5.0",
|
||||
"resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.5.0.tgz"
|
||||
},
|
||||
"stringstream": {
|
||||
"version": "0.0.4",
|
||||
"from": "stringstream@~0.0.4"
|
||||
"from": "stringstream@~0.0.4",
|
||||
"resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.4.tgz"
|
||||
},
|
||||
"combined-stream": {
|
||||
"version": "0.0.7",
|
||||
@@ -2329,8 +2379,8 @@
|
||||
},
|
||||
"abaculus": {
|
||||
"version": "1.1.0",
|
||||
"from": "https://github.com/CartoDB/abaculus/tarball/cdb",
|
||||
"resolved": "https://github.com/CartoDB/abaculus/tarball/cdb"
|
||||
"from": "https://github.com/CartoDB/abaculus/tarball/cdb-stats",
|
||||
"resolved": "https://github.com/CartoDB/abaculus/tarball/cdb-stats"
|
||||
},
|
||||
"sphericalmercator": {
|
||||
"version": "1.0.2",
|
||||
|
||||
+3
-3
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"private": true,
|
||||
"name": "windshaft-cartodb",
|
||||
"version": "1.30.1",
|
||||
"version": "2.0.0",
|
||||
"description": "A map tile server for CartoDB",
|
||||
"keywords": [
|
||||
"cartodb"
|
||||
@@ -22,10 +22,9 @@
|
||||
"Sandro Santilli <strk@vizzuality.com>"
|
||||
],
|
||||
"dependencies": {
|
||||
"node-varnish": "https://github.com/Vizzuality/node-varnish/tarball/0.3.0",
|
||||
"underscore" : "~1.6.0",
|
||||
"dot": "~1.0.2",
|
||||
"windshaft": "~0.40.0",
|
||||
"windshaft": "https://github.com/CartoDB/Windshaft/tarball/master",
|
||||
"step": "~0.0.5",
|
||||
"queue-async": "~1.0.7",
|
||||
"request": "~2.9.203",
|
||||
@@ -39,6 +38,7 @@
|
||||
"devDependencies": {
|
||||
"istanbul": "~0.3.6",
|
||||
"mocha": "~1.21.4",
|
||||
"nock": "~1.3.0",
|
||||
"jshint": "~2.6.0",
|
||||
"redis": "~0.8.6",
|
||||
"strftime": "~0.8.2",
|
||||
|
||||
+105
-45
@@ -1,27 +1,24 @@
|
||||
require(__dirname + '/../../support/test_helper');
|
||||
|
||||
var assert = require('../../support/assert');
|
||||
var redis = require('redis');
|
||||
var Step = require('step');
|
||||
|
||||
var helper = require(__dirname + '/../../support/test_helper');
|
||||
|
||||
var SqlApiEmulator = require(__dirname + '/../../support/SQLAPIEmu.js');
|
||||
var step = require('step');
|
||||
|
||||
var NamedMapsCacheEntry = require(__dirname + '/../../../lib/cartodb/cache/model/named_maps_entry');
|
||||
var SurrogateKeysCache = require(__dirname + '/../../../lib/cartodb/cache/surrogate_keys_cache');
|
||||
|
||||
var CartodbWindshaft = require(__dirname + '/../../../lib/cartodb/cartodb_windshaft');
|
||||
var ServerOptions = require(__dirname + '/../../../lib/cartodb/server_options');
|
||||
var serverOptions = ServerOptions();
|
||||
|
||||
|
||||
suite('templates surrogate keys', function() {
|
||||
describe('templates surrogate keys', function() {
|
||||
|
||||
var sqlApiServer;
|
||||
var redisClient = redis.createClient(global.environment.redis.port);
|
||||
|
||||
// Enable Varnish purge for tests
|
||||
serverOptions.varnish_purge_enabled = true;
|
||||
var varnishHost = global.environment.varnish.host;
|
||||
global.environment.varnish.host = '127.0.0.1';
|
||||
var varnishPurgeEnabled = global.environment.varnish.purge_enabled;
|
||||
global.environment.varnish.purge_enabled = true;
|
||||
|
||||
var serverOptions = require('../../../lib/cartodb/server_options')();
|
||||
var server = new CartodbWindshaft(serverOptions);
|
||||
|
||||
var templateOwner = 'localhost',
|
||||
@@ -48,15 +45,28 @@ suite('templates surrogate keys', function() {
|
||||
},
|
||||
expectedBody = { template_id: expectedTemplateId };
|
||||
|
||||
suiteSetup(function(done) {
|
||||
sqlApiServer = new SqlApiEmulator(global.environment.sqlapi.port, done);
|
||||
});
|
||||
var varnishHttpUrl = [
|
||||
'http://', global.environment.varnish.host, ':', global.environment.varnish.http_port
|
||||
].join('');
|
||||
|
||||
var surrogateKeysCacheInvalidateFn = SurrogateKeysCache.prototype.invalidate;
|
||||
var cacheEntryKey = new NamedMapsCacheEntry(templateOwner, templateName).key();
|
||||
var invalidationMatchHeader = '\\b' + cacheEntryKey + '\\b';
|
||||
|
||||
var nock = require('nock');
|
||||
nock.enableNetConnect(/(127.0.0.1:5555|cartocdn.com)/);
|
||||
|
||||
after(function(done) {
|
||||
serverOptions.varnish_purge_enabled = false;
|
||||
global.environment.varnish.host = varnishHost;
|
||||
global.environment.varnish.purge_enabled = varnishPurgeEnabled;
|
||||
|
||||
nock.restore();
|
||||
done();
|
||||
});
|
||||
|
||||
function createTemplate(callback) {
|
||||
var postTemplateRequest = {
|
||||
url: '/tiles/template?api_key=1234',
|
||||
url: '/api/v1/map/named?api_key=1234',
|
||||
method: 'POST',
|
||||
headers: {
|
||||
host: templateOwner,
|
||||
@@ -65,7 +75,7 @@ suite('templates surrogate keys', function() {
|
||||
data: JSON.stringify(template)
|
||||
};
|
||||
|
||||
Step(
|
||||
step(
|
||||
function postTemplate() {
|
||||
var next = this;
|
||||
assert.response(server,
|
||||
@@ -92,15 +102,14 @@ suite('templates surrogate keys', function() {
|
||||
);
|
||||
}
|
||||
|
||||
test("update template calls surrogate keys invalidation", function(done) {
|
||||
var cacheEntryKey;
|
||||
var surrogateKeysCacheInvalidateMethodInvoked = false;
|
||||
SurrogateKeysCache.prototype.invalidate = function(cacheEntry) {
|
||||
cacheEntryKey = cacheEntry.key();
|
||||
surrogateKeysCacheInvalidateMethodInvoked = true;
|
||||
};
|
||||
it("invalidates surrogate keys on template update", function(done) {
|
||||
|
||||
Step(
|
||||
var scope = nock(varnishHttpUrl)
|
||||
.intercept('/key', 'PURGE')
|
||||
.matchHeader('Invalidation-Match', invalidationMatchHeader)
|
||||
.reply(204, '');
|
||||
|
||||
step(
|
||||
function createTemplateToUpdate() {
|
||||
createTemplate(this);
|
||||
},
|
||||
@@ -109,7 +118,7 @@ suite('templates surrogate keys', function() {
|
||||
throw err;
|
||||
}
|
||||
var updateTemplateRequest = {
|
||||
url: '/tiles/template/' + expectedTemplateId + '/?api_key=1234',
|
||||
url: '/api/v1/map/named/' + expectedTemplateId + '/?api_key=1234',
|
||||
method: 'PUT',
|
||||
headers: {
|
||||
host: templateOwner,
|
||||
@@ -135,8 +144,7 @@ suite('templates surrogate keys', function() {
|
||||
var parsedBody = JSON.parse(res.body);
|
||||
assert.deepEqual(parsedBody, expectedBody);
|
||||
|
||||
assert.ok(surrogateKeysCacheInvalidateMethodInvoked);
|
||||
assert.equal(cacheEntryKey, new NamedMapsCacheEntry(templateOwner, templateName).key());
|
||||
assert.equal(scope.pendingMocks().length, 0);
|
||||
|
||||
return null;
|
||||
},
|
||||
@@ -156,16 +164,14 @@ suite('templates surrogate keys', function() {
|
||||
);
|
||||
});
|
||||
|
||||
test("delete template calls surrogate keys invalidation", function(done) {
|
||||
it("invalidates surrogate on template deletion", function(done) {
|
||||
|
||||
var cacheEntryKey;
|
||||
var surrogateKeysCacheInvalidateMethodInvoked = false;
|
||||
SurrogateKeysCache.prototype.invalidate = function(cacheEntry) {
|
||||
cacheEntryKey = cacheEntry.key();
|
||||
surrogateKeysCacheInvalidateMethodInvoked = true;
|
||||
};
|
||||
var scope = nock(varnishHttpUrl)
|
||||
.intercept('/key', 'PURGE')
|
||||
.matchHeader('Invalidation-Match', invalidationMatchHeader)
|
||||
.reply(204, '');
|
||||
|
||||
Step(
|
||||
step(
|
||||
function createTemplateToDelete() {
|
||||
createTemplate(this);
|
||||
},
|
||||
@@ -174,7 +180,7 @@ suite('templates surrogate keys', function() {
|
||||
throw err;
|
||||
}
|
||||
var deleteTemplateRequest = {
|
||||
url: '/tiles/template/' + expectedTemplateId + '/?api_key=1234',
|
||||
url: '/api/v1/map/named/' + expectedTemplateId + '/?api_key=1234',
|
||||
method: 'DELETE',
|
||||
headers: {
|
||||
host: templateOwner,
|
||||
@@ -197,8 +203,7 @@ suite('templates surrogate keys', function() {
|
||||
throw err;
|
||||
}
|
||||
|
||||
assert.ok(surrogateKeysCacheInvalidateMethodInvoked);
|
||||
assert.equal(cacheEntryKey, new NamedMapsCacheEntry(templateOwner, templateName).key());
|
||||
assert.equal(scope.pendingMocks().length, 0);
|
||||
|
||||
return null;
|
||||
},
|
||||
@@ -208,11 +213,66 @@ suite('templates surrogate keys', function() {
|
||||
);
|
||||
});
|
||||
|
||||
suiteTeardown(function(done) {
|
||||
SurrogateKeysCache.prototype.invalidate = surrogateKeysCacheInvalidateFn;
|
||||
// Enable Varnish purge for tests
|
||||
serverOptions.varnish_purge_enabled = false;
|
||||
sqlApiServer.close(done);
|
||||
it("should update template even if surrogate key invalidation fails", function(done) {
|
||||
|
||||
var scope = nock(varnishHttpUrl)
|
||||
.intercept('/key', 'PURGE')
|
||||
.matchHeader('Invalidation-Match', invalidationMatchHeader)
|
||||
.reply(503, '');
|
||||
|
||||
step(
|
||||
function createTemplateToUpdate() {
|
||||
createTemplate(this);
|
||||
},
|
||||
function putValidTemplate(err) {
|
||||
if (err) {
|
||||
throw err;
|
||||
}
|
||||
var updateTemplateRequest = {
|
||||
url: '/api/v1/map/named/' + expectedTemplateId + '/?api_key=1234',
|
||||
method: 'PUT',
|
||||
headers: {
|
||||
host: templateOwner,
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
data: JSON.stringify(template)
|
||||
};
|
||||
var next = this;
|
||||
assert.response(server,
|
||||
updateTemplateRequest,
|
||||
{
|
||||
status: 200
|
||||
},
|
||||
function(res) {
|
||||
next(null, res);
|
||||
}
|
||||
);
|
||||
},
|
||||
function checkValidUpdate(err, res) {
|
||||
if (err) {
|
||||
throw err;
|
||||
}
|
||||
var parsedBody = JSON.parse(res.body);
|
||||
assert.deepEqual(parsedBody, expectedBody);
|
||||
|
||||
assert.equal(scope.pendingMocks().length, 0);
|
||||
|
||||
return null;
|
||||
},
|
||||
function finish(err) {
|
||||
if ( err ) {
|
||||
return done(err);
|
||||
}
|
||||
redisClient.keys("map_*|localhost", function(err, keys) {
|
||||
if ( err ) {
|
||||
return done(err);
|
||||
}
|
||||
redisClient.del(keys, function(err) {
|
||||
return done(err);
|
||||
});
|
||||
});
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
var assert = require('../support/assert');
|
||||
require(__dirname + '/../support/test_helper');
|
||||
var CacheValidator = require(__dirname + '/../../lib/cartodb/cache_validator');
|
||||
|
||||
var VarnishEmu = require('../support/VarnishEmu');
|
||||
|
||||
suite('cache_validator', function() {
|
||||
|
||||
test('should call purge on varnish when invalidate database', function(done) {
|
||||
var varnish = new VarnishEmu(function(cmds) {
|
||||
assert.ok(cmds.length == 1);
|
||||
assert.equal('purge obj.http.X-Cache-Channel ~ \"^test_db:(.*test_cache.*)|(table)$\"\n', cmds[0].toString('utf8'));
|
||||
done();
|
||||
},
|
||||
function() {
|
||||
CacheValidator.init('localhost', 1337);
|
||||
CacheValidator.invalidate_db('test_db', 'test_cache');
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
+110
-159
@@ -1,12 +1,8 @@
|
||||
var assert = require('../support/assert');
|
||||
var tests = module.exports = {};
|
||||
var _ = require('underscore');
|
||||
var redis = require('redis');
|
||||
var querystring = require('querystring');
|
||||
var semver = require('semver');
|
||||
var Step = require('step');
|
||||
var step = require('step');
|
||||
var strftime = require('strftime');
|
||||
var SQLAPIEmu = require(__dirname + '/../support/SQLAPIEmu.js');
|
||||
var redis_stats_db = 5;
|
||||
|
||||
var helper = require(__dirname + '/../support/test_helper');
|
||||
@@ -17,44 +13,39 @@ var IMAGE_EQUALS_TOLERANCE_PER_MIL = 20;
|
||||
var IMAGE_EQUALS_HIGHER_TOLERANCE_PER_MIL = 25;
|
||||
|
||||
var CartodbWindshaft = require(__dirname + '/../../lib/cartodb/cartodb_windshaft');
|
||||
var ServerOptions = require(__dirname + '/../../lib/cartodb/server_options');
|
||||
serverOptions = ServerOptions();
|
||||
var server = new CartodbWindshaft(serverOptions);
|
||||
var serverOptions = require(__dirname + '/../../lib/cartodb/server_options');
|
||||
var server = new CartodbWindshaft(serverOptions());
|
||||
server.setMaxListeners(0);
|
||||
|
||||
['/tiles/layergroup', '/u/localhost/tiles/layergroup'].forEach(function(layergroup_url) {
|
||||
[true, false].forEach(function(cdbQueryTablesFromPostgresEnabledValue) {
|
||||
['/api/v1/map', '/u/localhost/api/v1/map'].forEach(function(layergroup_url) {
|
||||
|
||||
var suiteName = 'multilayer:postgres=' + cdbQueryTablesFromPostgresEnabledValue + ";layergroup_url=" + layergroup_url;
|
||||
var suiteName = 'multilayer:postgres=layergroup_url=' + layergroup_url;
|
||||
suite(suiteName, function() {
|
||||
|
||||
var cdbQueryTablesFromPostgresEnabledValue = true;
|
||||
|
||||
var redis_client = redis.createClient(global.environment.redis.port);
|
||||
var sqlapi_server;
|
||||
var expected_last_updated_epoch = 1234567890123; // this is hard-coded into SQLAPIEmu
|
||||
var expected_last_updated = new Date(expected_last_updated_epoch).toISOString();
|
||||
|
||||
var test_user = _.template(global.environment.postgres_auth_user, {user_id:1});
|
||||
var test_pubuser = global.environment.postgres.user;
|
||||
var test_database = test_user + '_db';
|
||||
|
||||
suiteSetup(function(done){
|
||||
global.environment.enabledFeatures = { cdbQueryTablesFromPostgres: cdbQueryTablesFromPostgresEnabledValue };
|
||||
sqlapi_server = new SQLAPIEmu(global.environment.sqlapi.port, done);
|
||||
});
|
||||
|
||||
test("layergroup with 2 layers, each with its style", function(done) {
|
||||
|
||||
var layergroup = {
|
||||
version: '1.0.0',
|
||||
layers: [
|
||||
{ options: {
|
||||
sql: 'select cartodb_id, ST_Translate(the_geom_webmercator, 5e6, 0) as the_geom_webmercator from test_table limit 2',
|
||||
sql: 'select cartodb_id, ST_Translate(the_geom_webmercator, 5e6, 0) as the_geom_webmercator' +
|
||||
' from test_table limit 2',
|
||||
cartocss: '#layer { marker-fill:red; marker-width:32; marker-allow-overlap:true; }',
|
||||
cartocss_version: '2.0.1',
|
||||
interactivity: 'cartodb_id'
|
||||
} },
|
||||
{ options: {
|
||||
sql: 'select cartodb_id, ST_Translate(the_geom_webmercator, -5e6, 0) as the_geom_webmercator from test_table limit 2 offset 2',
|
||||
sql: 'select cartodb_id, ST_Translate(the_geom_webmercator, -5e6, 0) as the_geom_webmercator' +
|
||||
' from test_table limit 2 offset 2',
|
||||
cartocss: '#layer { marker-fill:blue; marker-allow-overlap:true; }',
|
||||
cartocss_version: '2.0.2',
|
||||
interactivity: 'cartodb_id'
|
||||
@@ -63,7 +54,7 @@ suite(suiteName, function() {
|
||||
};
|
||||
|
||||
var expected_token; // = "e34dd7e235138a062f8ba7ad051aa3a7";
|
||||
Step(
|
||||
step(
|
||||
function do_post()
|
||||
{
|
||||
var next = this;
|
||||
@@ -75,14 +66,6 @@ suite(suiteName, function() {
|
||||
}, {}, function(res) {
|
||||
assert.equal(res.statusCode, 200, res.body);
|
||||
var parsedBody = JSON.parse(res.body);
|
||||
var expectedBody = { layergroupid: expected_token };
|
||||
// check last modified
|
||||
var qTables = JSON.stringify({
|
||||
'q': 'SELECT CDB_QueryTables($windshaft$'
|
||||
+ layergroup.layers[0].options.sql + ';'
|
||||
+ layergroup.layers[1].options.sql
|
||||
+ '$windshaft$)'
|
||||
});
|
||||
assert.equal(parsedBody.last_updated, expected_last_updated);
|
||||
if ( expected_token ) {
|
||||
assert.equal(parsedBody.layergroupid, expected_token + ':' + expected_last_updated_epoch);
|
||||
@@ -116,19 +99,23 @@ suite(suiteName, function() {
|
||||
if (!cdbQueryTablesFromPostgresEnabledValue) { // only test if it was using the SQL API
|
||||
var jsonquery = cc.substring(dbname.length + 1);
|
||||
var sentquery = JSON.parse(jsonquery);
|
||||
var expectedQuery = [layergroup.layers[0].options.sql, ';', layergroup.layers[1].options.sql].join('');
|
||||
assert.equal(sentquery.q, 'WITH querytables AS ( SELECT * FROM CDB_QueryTables($windshaft$'
|
||||
+ expectedQuery
|
||||
+ '$windshaft$) as tablenames )'
|
||||
+ ' SELECT (SELECT tablenames FROM querytables), EXTRACT(EPOCH FROM max(updated_at)) as max'
|
||||
+ ' FROM CDB_TableMetadata m'
|
||||
+ ' WHERE m.tabname = any ((SELECT tablenames from querytables)::regclass[])');
|
||||
var expectedQuery = [
|
||||
layergroup.layers[0].options.sql, ';',
|
||||
layergroup.layers[1].options.sql
|
||||
].join('');
|
||||
assert.equal(sentquery.q, 'WITH querytables AS ( SELECT * FROM CDB_QueryTables($windshaft$' +
|
||||
expectedQuery +
|
||||
'$windshaft$) as tablenames )' +
|
||||
' SELECT (SELECT tablenames FROM querytables), EXTRACT(EPOCH FROM max(updated_at)) as max' +
|
||||
' FROM CDB_TableMetadata m' +
|
||||
' WHERE m.tabname = any ((SELECT tablenames from querytables)::regclass[])');
|
||||
}
|
||||
|
||||
assert.imageEqualsFile(res.body, 'test/fixtures/test_table_0_0_0_multilayer1.png', IMAGE_EQUALS_HIGHER_TOLERANCE_PER_MIL,
|
||||
function(err, similarity) {
|
||||
next(err);
|
||||
});
|
||||
assert.imageEqualsFile(res.body, 'test/fixtures/test_table_0_0_0_multilayer1.png',
|
||||
IMAGE_EQUALS_HIGHER_TOLERANCE_PER_MIL, function(err/*, similarity*/) {
|
||||
next(err);
|
||||
}
|
||||
);
|
||||
});
|
||||
},
|
||||
// See https://github.com/CartoDB/Windshaft-cartodb/issues/170
|
||||
@@ -154,15 +141,14 @@ suite(suiteName, function() {
|
||||
if ( err ) throw err;
|
||||
var next = this;
|
||||
assert.response(server, {
|
||||
url: layergroup_url + "/" + expected_token
|
||||
+ '/0/0/0/0.grid.json',
|
||||
url: layergroup_url + "/" + expected_token + '/0/0/0/0.grid.json',
|
||||
headers: {host: 'localhost' },
|
||||
method: 'GET'
|
||||
}, {}, function(res) {
|
||||
assert.equal(res.statusCode, 200, res.body);
|
||||
assert.equal(res.headers['content-type'], "application/json; charset=utf-8");
|
||||
assert.utfgridEqualsFile(res.body, 'test/fixtures/test_table_0_0_0_multilayer1.layer0.grid.json', 2,
|
||||
function(err, similarity) {
|
||||
function(err/*, similarity*/) {
|
||||
next(err);
|
||||
});
|
||||
});
|
||||
@@ -172,15 +158,14 @@ suite(suiteName, function() {
|
||||
if ( err ) throw err;
|
||||
var next = this;
|
||||
assert.response(server, {
|
||||
url: layergroup_url + "/" + expected_token
|
||||
+ '/1/0/0/0.grid.json',
|
||||
url: layergroup_url + "/" + expected_token + '/1/0/0/0.grid.json',
|
||||
headers: {host: 'localhost' },
|
||||
method: 'GET'
|
||||
}, {}, function(res) {
|
||||
assert.equal(res.statusCode, 200, res.body);
|
||||
assert.equal(res.headers['content-type'], "application/json; charset=utf-8");
|
||||
assert.utfgridEqualsFile(res.body, 'test/fixtures/test_table_0_0_0_multilayer1.layer1.grid.json', 2,
|
||||
function(err, similarity) {
|
||||
function(err/*, similarity*/) {
|
||||
next(err);
|
||||
});
|
||||
});
|
||||
@@ -206,20 +191,20 @@ suite(suiteName, function() {
|
||||
|
||||
|
||||
test("should include serverMedata in the response", function(done) {
|
||||
global.environment.serverMetadata = { cdn_url : { http:'test', https: 'tests' } }
|
||||
global.environment.serverMetadata = { cdn_url : { http:'test', https: 'tests' } };
|
||||
var layergroup = {
|
||||
version: '1.0.0',
|
||||
layers: [
|
||||
{ options: {
|
||||
sql: 'select cartodb_id, ST_Translate(the_geom_webmercator, 5e6, 0) as the_geom_webmercator from test_table limit 2',
|
||||
sql: 'select cartodb_id, ST_Translate(the_geom_webmercator, 5e6, 0) as the_geom_webmercator' +
|
||||
' from test_table limit 2',
|
||||
cartocss: '#layer { marker-fill:red; marker-width:32; marker-allow-overlap:true; }',
|
||||
cartocss_version: '2.0.1'
|
||||
} }
|
||||
]
|
||||
};
|
||||
|
||||
var expected_token;
|
||||
Step(
|
||||
step(
|
||||
function do_create_get()
|
||||
{
|
||||
var next = this;
|
||||
@@ -234,7 +219,7 @@ suite(suiteName, function() {
|
||||
assert.ok(_.isEqual(parsed.cdn_url, global.environment.serverMetadata.cdn_url));
|
||||
done();
|
||||
}
|
||||
)
|
||||
);
|
||||
});
|
||||
|
||||
|
||||
@@ -244,7 +229,8 @@ suite(suiteName, function() {
|
||||
version: '1.0.0',
|
||||
layers: [
|
||||
{ options: {
|
||||
sql: 'select cartodb_id, ST_Translate(the_geom_webmercator, 5e6, 0) as the_geom_webmercator from test_table limit 2',
|
||||
sql: 'select cartodb_id, ST_Translate(the_geom_webmercator, 5e6, 0) as the_geom_webmercator' +
|
||||
' from test_table limit 2',
|
||||
cartocss: '#layer { marker-fill:red; marker-width:32; marker-allow-overlap:true; }',
|
||||
cartocss_version: '2.0.1'
|
||||
} }
|
||||
@@ -252,7 +238,7 @@ suite(suiteName, function() {
|
||||
};
|
||||
|
||||
var expected_token;
|
||||
Step(
|
||||
step(
|
||||
function do_create_get()
|
||||
{
|
||||
var next = this;
|
||||
@@ -316,7 +302,8 @@ suite(suiteName, function() {
|
||||
version: '1.0.0',
|
||||
layers: [
|
||||
{ options: {
|
||||
sql: 'select cartodb_id, ST_Translate(the_geom_webmercator, 5e6, 0) as the_geom_webmercator from test_table limit 2',
|
||||
sql: 'select cartodb_id, ST_Translate(the_geom_webmercator, 5e6, 0) as the_geom_webmercator' +
|
||||
' from test_table limit 2',
|
||||
cartocss: '#layer { invalid-rule:red; }',
|
||||
cartocss_version: '2.0.1'
|
||||
} }
|
||||
@@ -339,8 +326,8 @@ suite(suiteName, function() {
|
||||
version: '1.0.0',
|
||||
layers: [
|
||||
{ options: {
|
||||
sql: 'select 1 as cartodb_id, '
|
||||
+ 'ST_Buffer(!bbox!, -32*greatest(!pixel_width!,!pixel_height!)) as the_geom_webmercator from test_table limit 1',
|
||||
sql: 'select 1 as cartodb_id, ST_Buffer(!bbox!, -32*greatest(!pixel_width!,!pixel_height!))' +
|
||||
' as the_geom_webmercator from test_table limit 1',
|
||||
cartocss: '#layer { polygon-fill:red; }',
|
||||
cartocss_version: '2.0.1',
|
||||
interactivity: 'cartodb_id'
|
||||
@@ -349,7 +336,7 @@ suite(suiteName, function() {
|
||||
};
|
||||
|
||||
var expected_token; // = "6d8e4ad5458e2d25cf0eef38e38717a6";
|
||||
Step(
|
||||
step(
|
||||
function do_post()
|
||||
{
|
||||
var next = this;
|
||||
@@ -361,13 +348,6 @@ suite(suiteName, function() {
|
||||
}, {}, function(res) {
|
||||
assert.equal(res.statusCode, 200, res.body);
|
||||
var parsedBody = JSON.parse(res.body);
|
||||
var expectedBody = { layergroupid: expected_token };
|
||||
// check last modified
|
||||
var qTables = JSON.stringify({
|
||||
'q': 'SELECT CDB_QueryTables($windshaft$'
|
||||
+ layergroup.layers[0].options.sql
|
||||
+ '$windshaft$)'
|
||||
});
|
||||
assert.equal(parsedBody.last_updated, expected_last_updated);
|
||||
if ( expected_token ) {
|
||||
assert.equal(parsedBody.layergroupid, expected_token + ':' + expected_last_updated_epoch);
|
||||
@@ -401,16 +381,16 @@ suite(suiteName, function() {
|
||||
.replace(/!bbox!/g, 'ST_MakeEnvelope(0,0,0,0)')
|
||||
.replace(/!pixel_width!/g, '1')
|
||||
.replace(/!pixel_height!/g, '1');
|
||||
assert.equal(sentquery.q, 'WITH querytables AS ( SELECT * FROM CDB_QueryTables($windshaft$'
|
||||
+ expectedQuery
|
||||
+ '$windshaft$) as tablenames )'
|
||||
+ ' SELECT (SELECT tablenames FROM querytables), EXTRACT(EPOCH FROM max(updated_at)) as max'
|
||||
+ ' FROM CDB_TableMetadata m'
|
||||
+ ' WHERE m.tabname = any ((SELECT tablenames from querytables)::regclass[])');
|
||||
assert.equal(sentquery.q, 'WITH querytables AS ( SELECT * FROM CDB_QueryTables($windshaft$' +
|
||||
expectedQuery +
|
||||
'$windshaft$) as tablenames )' +
|
||||
' SELECT (SELECT tablenames FROM querytables), EXTRACT(EPOCH FROM max(updated_at)) as max' +
|
||||
' FROM CDB_TableMetadata m' +
|
||||
' WHERE m.tabname = any ((SELECT tablenames from querytables)::regclass[])');
|
||||
}
|
||||
|
||||
assert.imageEqualsFile(res.body, 'test/fixtures/test_multilayer_bbox.png', IMAGE_EQUALS_TOLERANCE_PER_MIL,
|
||||
function(err, similarity) {
|
||||
function(err/*, similarity*/) {
|
||||
next(err);
|
||||
});
|
||||
});
|
||||
@@ -440,16 +420,16 @@ suite(suiteName, function() {
|
||||
.replace('!bbox!', 'ST_MakeEnvelope(0,0,0,0)')
|
||||
.replace('!pixel_width!', '1')
|
||||
.replace('!pixel_height!', '1');
|
||||
assert.equal(sentquery.q, 'WITH querytables AS ( SELECT * FROM CDB_QueryTables($windshaft$'
|
||||
+ expectedQuery
|
||||
+ '$windshaft$) as tablenames )'
|
||||
+ ' SELECT (SELECT tablenames FROM querytables), EXTRACT(EPOCH FROM max(updated_at)) as max'
|
||||
+ ' FROM CDB_TableMetadata m'
|
||||
+ ' WHERE m.tabname = any ((SELECT tablenames from querytables)::regclass[])');
|
||||
assert.equal(sentquery.q, 'WITH querytables AS ( SELECT * FROM CDB_QueryTables($windshaft$' +
|
||||
expectedQuery +
|
||||
'$windshaft$) as tablenames )' +
|
||||
' SELECT (SELECT tablenames FROM querytables), EXTRACT(EPOCH FROM max(updated_at)) as max' +
|
||||
' FROM CDB_TableMetadata m' +
|
||||
' WHERE m.tabname = any ((SELECT tablenames from querytables)::regclass[])');
|
||||
}
|
||||
|
||||
assert.imageEqualsFile(res.body, 'test/fixtures/test_multilayer_bbox.png', IMAGE_EQUALS_TOLERANCE_PER_MIL,
|
||||
function(err, similarity) {
|
||||
function(err/*, similarity*/) {
|
||||
next(err);
|
||||
});
|
||||
});
|
||||
@@ -459,15 +439,14 @@ suite(suiteName, function() {
|
||||
if ( err ) throw err;
|
||||
var next = this;
|
||||
assert.response(server, {
|
||||
url: layergroup_url + "/" + expected_token
|
||||
+ '/0/1/0/0.grid.json',
|
||||
url: layergroup_url + "/" + expected_token + '/0/1/0/0.grid.json',
|
||||
headers: {host: 'localhost' },
|
||||
method: 'GET'
|
||||
}, {}, function(res) {
|
||||
assert.equal(res.statusCode, 200, res.body);
|
||||
assert.equal(res.headers['content-type'], "application/json; charset=utf-8");
|
||||
assert.utfgridEqualsFile(res.body, 'test/fixtures/test_multilayer_bbox.grid.json', 2,
|
||||
function(err, similarity) {
|
||||
function(err/*, similarity*/) {
|
||||
next(err);
|
||||
});
|
||||
});
|
||||
@@ -477,15 +456,14 @@ suite(suiteName, function() {
|
||||
if ( err ) throw err;
|
||||
var next = this;
|
||||
assert.response(server, {
|
||||
url: layergroup_url + "/" + expected_token
|
||||
+ '/0/4/0/0.grid.json',
|
||||
url: layergroup_url + "/" + expected_token + '/0/4/0/0.grid.json',
|
||||
headers: {host: 'localhost' },
|
||||
method: 'GET'
|
||||
}, {}, function(res) {
|
||||
assert.equal(res.statusCode, 200, res.body);
|
||||
assert.equal(res.headers['content-type'], "application/json; charset=utf-8");
|
||||
assert.utfgridEqualsFile(res.body, 'test/fixtures/test_multilayer_bbox.grid.json', 2,
|
||||
function(err, similarity) {
|
||||
function(err/*, similarity*/) {
|
||||
next(err);
|
||||
});
|
||||
});
|
||||
@@ -515,8 +493,8 @@ suite(suiteName, function() {
|
||||
version: '1.0.0',
|
||||
layers: [
|
||||
{ options: {
|
||||
sql: 'select 1 as cartodb_id, !pixel_height! as h, '
|
||||
+ 'ST_Buffer(!bbox!, -32*greatest(!pixel_width!,!pixel_height!)) as the_geom_webmercator',
|
||||
sql: 'select 1 as cartodb_id, !pixel_height! as h,' +
|
||||
' ST_Buffer(!bbox!, -32*greatest(!pixel_width!,!pixel_height!)) as the_geom_webmercator',
|
||||
cartocss: '#layer { polygon-fill:red; }',
|
||||
cartocss_version: '2.0.1'
|
||||
} }
|
||||
@@ -527,7 +505,7 @@ suite(suiteName, function() {
|
||||
var expected_token; // will be set on first post and checked on second
|
||||
var now = strftime("%Y%m%d", new Date());
|
||||
var errors = [];
|
||||
Step(
|
||||
step(
|
||||
function clean_stats()
|
||||
{
|
||||
var next = this;
|
||||
@@ -553,14 +531,13 @@ suite(suiteName, function() {
|
||||
},
|
||||
function check_global_stats_1(err, val) {
|
||||
if ( err ) throw err;
|
||||
assert.equal(val, 1, "Expected score of " + now + " in "
|
||||
+ statskey + ":global to be 1, got " + val);
|
||||
assert.equal(val, 1, "Expected score of " + now + " in " + statskey + ":global to be 1, got " + val);
|
||||
redis_stats_client.zscore(statskey+':stat_tag:random_tag', now, this);
|
||||
},
|
||||
function check_tag_stats_1_do_post_2(err, val) {
|
||||
if ( err ) throw err;
|
||||
assert.equal(val, 1, "Expected score of " + now + " in "
|
||||
+ statskey + ":stat_tag:" + layergroup.stat_tag + " to be 1, got " + val);
|
||||
assert.equal(val, 1, "Expected score of " + now + " in " + statskey + ":stat_tag:" + layergroup.stat_tag +
|
||||
" to be 1, got " + val);
|
||||
var next = this;
|
||||
assert.response(server, {
|
||||
url: layergroup_url,
|
||||
@@ -576,15 +553,14 @@ suite(suiteName, function() {
|
||||
function check_global_stats_2(err, val)
|
||||
{
|
||||
if ( err ) throw err;
|
||||
assert.equal(val, 2, "Expected score of " + now + " in "
|
||||
+ statskey + ":global to be 2, got " + val);
|
||||
assert.equal(val, 2, "Expected score of " + now + " in " + statskey + ":global to be 2, got " + val);
|
||||
redis_stats_client.zscore(statskey+':stat_tag:' + layergroup.stat_tag, now, this);
|
||||
},
|
||||
function check_tag_stats_2(err, val)
|
||||
{
|
||||
if ( err ) throw err;
|
||||
assert.equal(val, 2, "Expected score of " + now + " in "
|
||||
+ statskey + ":stat_tag:" + layergroup.stat_tag + " to be 2, got " + val);
|
||||
assert.equal(val, 2, "Expected score of " + now + " in " + statskey + ":stat_tag:" + layergroup.stat_tag +
|
||||
" to be 2, got " + val);
|
||||
return 1;
|
||||
},
|
||||
function cleanup_map_style(err) {
|
||||
@@ -614,8 +590,8 @@ suite(suiteName, function() {
|
||||
version: '1.0.0',
|
||||
layers: [
|
||||
{ options: {
|
||||
sql: 'select 1 as cartodb_id, !pixel_height! as h'
|
||||
+ 'ST_Buffer(!bbox!, -32*greatest(!pixel_width!,!pixel_height!)) as the_geom_webmercator',
|
||||
sql: 'select 1 as cartodb_id, !pixel_height! as h' +
|
||||
'ST_Buffer(!bbox!, -32*greatest(!pixel_width!,!pixel_height!)) as the_geom_webmercator',
|
||||
cartocss: '#layer { polygon-fit:red; }',
|
||||
cartocss_version: '2.0.1'
|
||||
} }
|
||||
@@ -685,7 +661,7 @@ suite(suiteName, function() {
|
||||
};
|
||||
|
||||
var expected_token; // = "b4ed64d93a411a59f330ab3d798e4009";
|
||||
Step(
|
||||
step(
|
||||
function do_post()
|
||||
{
|
||||
var next = this;
|
||||
@@ -697,14 +673,6 @@ suite(suiteName, function() {
|
||||
}, {}, function(res) {
|
||||
assert.equal(res.statusCode, 200, res.body);
|
||||
var parsedBody = JSON.parse(res.body);
|
||||
var expectedBody = { layergroupid: expected_token };
|
||||
// check last modified
|
||||
var qTables = JSON.stringify({
|
||||
'q': 'SELECT CDB_QueryTables($windshaft$'
|
||||
+ layergroup.layers[0].options.sql + ';'
|
||||
+ layergroup.layers[1].options.sql
|
||||
+ '$windshaft$)'
|
||||
});
|
||||
assert.equal(parsedBody.last_updated, expected_last_updated);
|
||||
if ( expected_token ) {
|
||||
assert.equal(parsedBody.layergroupid, expected_token + ':' + expected_last_updated_epoch);
|
||||
@@ -739,8 +707,7 @@ suite(suiteName, function() {
|
||||
if ( err ) throw err;
|
||||
var next = this;
|
||||
assert.response(server, {
|
||||
url: layergroup_url + "/" + expected_token
|
||||
+ '/0/0/0/0.grid.json?map_key=1234',
|
||||
url: layergroup_url + "/" + expected_token + '/0/0/0/0.grid.json?map_key=1234',
|
||||
headers: {host: 'localhost' },
|
||||
method: 'GET'
|
||||
}, {}, function(res) {
|
||||
@@ -753,8 +720,7 @@ suite(suiteName, function() {
|
||||
if ( err ) throw err;
|
||||
var next = this;
|
||||
assert.response(server, {
|
||||
url: layergroup_url + "/" + expected_token
|
||||
+ '/1/0/0/0.grid.json?map_key=1234',
|
||||
url: layergroup_url + "/" + expected_token + '/1/0/0/0.grid.json?map_key=1234',
|
||||
headers: {host: 'localhost' },
|
||||
method: 'GET'
|
||||
}, {}, function(res) {
|
||||
@@ -774,7 +740,7 @@ suite(suiteName, function() {
|
||||
encoding: 'binary'
|
||||
}, {}, function(res) {
|
||||
assert.equal(res.statusCode, 403);
|
||||
var re = RegExp('permission denied');
|
||||
var re = new RegExp('permission denied');
|
||||
assert.ok(res.body.match(re), 'No "permission denied" error: ' + res.body);
|
||||
next(err);
|
||||
});
|
||||
@@ -784,13 +750,12 @@ suite(suiteName, function() {
|
||||
if ( err ) throw err;
|
||||
var next = this;
|
||||
assert.response(server, {
|
||||
url: layergroup_url + "/" + expected_token
|
||||
+ '/0/0/0/0.grid.json',
|
||||
url: layergroup_url + "/" + expected_token + '/0/0/0/0.grid.json',
|
||||
headers: {host: 'localhost' },
|
||||
method: 'GET'
|
||||
}, {}, function(res) {
|
||||
assert.equal(res.statusCode, 403);
|
||||
var re = RegExp('permission denied');
|
||||
var re = new RegExp('permission denied');
|
||||
assert.ok(res.body.match(re), 'No "permission denied" error: ' + res.body);
|
||||
next(err);
|
||||
});
|
||||
@@ -800,13 +765,12 @@ suite(suiteName, function() {
|
||||
if ( err ) throw err;
|
||||
var next = this;
|
||||
assert.response(server, {
|
||||
url: layergroup_url + "/" + expected_token
|
||||
+ '/1/0/0/0.grid.json',
|
||||
url: layergroup_url + "/" + expected_token + '/1/0/0/0.grid.json',
|
||||
headers: {host: 'localhost' },
|
||||
method: 'GET'
|
||||
}, {}, function(res) {
|
||||
assert.equal(res.statusCode, 403);
|
||||
var re = RegExp('permission denied');
|
||||
var re = new RegExp('permission denied');
|
||||
assert.ok(res.body.match(re), 'No "permission denied" error: ' + res.body);
|
||||
next(err);
|
||||
});
|
||||
@@ -846,7 +810,7 @@ suite(suiteName, function() {
|
||||
};
|
||||
|
||||
var expected_token; // = "b4ed64d93a411a59f330ab3d798e4009";
|
||||
Step(
|
||||
step(
|
||||
function do_post()
|
||||
{
|
||||
var next = this;
|
||||
@@ -861,13 +825,6 @@ suite(suiteName, function() {
|
||||
if ( err ) throw err;
|
||||
assert.equal(res.statusCode, 200, res.body);
|
||||
var parsedBody = JSON.parse(res.body);
|
||||
var expectedBody = { layergroupid: expected_token };
|
||||
// check last modified
|
||||
var qTables = JSON.stringify({
|
||||
'q': 'SELECT CDB_QueryTables($windshaft$'
|
||||
+ layergroup.layers[0].options.sql
|
||||
+ '$windshaft$)'
|
||||
});
|
||||
assert.equal(parsedBody.last_updated, expected_last_updated);
|
||||
if ( expected_token ) {
|
||||
assert.equal(parsedBody.layergroupid, expected_token + ':' + expected_last_updated_epoch);
|
||||
@@ -898,11 +855,10 @@ suite(suiteName, function() {
|
||||
assert.equal(cc.substring(0, dbname.length), dbname);
|
||||
return null;
|
||||
},
|
||||
function do_restart_server(err, res) {
|
||||
function do_restart_server(err/*, res*/) {
|
||||
if ( err ) throw err;
|
||||
// hack simulating restart...
|
||||
serverOptions = ServerOptions();
|
||||
server = new CartodbWindshaft(serverOptions);
|
||||
server = new CartodbWindshaft(serverOptions());
|
||||
return null;
|
||||
},
|
||||
function do_get1(err)
|
||||
@@ -956,13 +912,13 @@ suite(suiteName, function() {
|
||||
{ options: {
|
||||
sql: "select 1 as cartodb_id, 'SRID=3857;POINT(0 0)'::geometry as the_geom_webmercator",
|
||||
cartocss: '#sample { text-name: cartodb_id; text-face-name: "Dejagnu"; }',
|
||||
cartocss_version: '2.1.0',
|
||||
cartocss_version: '2.1.0'
|
||||
} }
|
||||
]
|
||||
};
|
||||
|
||||
assert.response(server, {
|
||||
url: '/tiles/layergroup?',
|
||||
url: layergroup_url,
|
||||
method: 'POST',
|
||||
headers: {host: 'localhost', 'Content-Type': 'application/json' },
|
||||
data: JSON.stringify(layergroup)
|
||||
@@ -984,18 +940,18 @@ suite(suiteName, function() {
|
||||
{ options: {
|
||||
sql: "select 'single''quote' as n, 'SRID=3857;POINT(0 0)'::geometry as the_geom_webmercator",
|
||||
cartocss: '#s [n="single\'quote" ] { marker-fill:red; }',
|
||||
cartocss_version: '2.1.0',
|
||||
cartocss_version: '2.1.0'
|
||||
} },
|
||||
{ options: {
|
||||
sql: "select 'double\"quote' as n, 'SRID=3857;POINT(2 0)'::geometry as the_geom_webmercator",
|
||||
cartocss: '#s [n="double\\"quote" ] { marker-fill:red; }',
|
||||
cartocss_version: '2.1.0',
|
||||
cartocss_version: '2.1.0'
|
||||
} }
|
||||
]
|
||||
};
|
||||
|
||||
assert.response(server, {
|
||||
url: '/tiles/layergroup?',
|
||||
url: layergroup_url,
|
||||
method: 'POST',
|
||||
headers: {host: 'localhost', 'Content-Type': 'application/json' },
|
||||
data: JSON.stringify(layergroup)
|
||||
@@ -1013,12 +969,12 @@ suite(suiteName, function() {
|
||||
{ options: {
|
||||
sql: "select .4 as n, 'SRID=3857;POINT(0 0)'::geometry as the_geom_webmercator",
|
||||
cartocss: '#s [n<=.2e-2] { marker-fill:red; }',
|
||||
cartocss_version: '2.1.0',
|
||||
cartocss_version: '2.1.0'
|
||||
} }
|
||||
]
|
||||
};
|
||||
assert.response(server, {
|
||||
url: '/tiles/layergroup?',
|
||||
url: layergroup_url,
|
||||
method: 'POST',
|
||||
headers: {host: 'localhost', 'Content-Type': 'application/json' },
|
||||
data: JSON.stringify(layergroup)
|
||||
@@ -1041,7 +997,7 @@ suite(suiteName, function() {
|
||||
]
|
||||
};
|
||||
var expected_token; // = "e34dd7e235138a062f8ba7ad051aa3a7";
|
||||
Step(
|
||||
step(
|
||||
function do_post()
|
||||
{
|
||||
var next = this;
|
||||
@@ -1053,7 +1009,6 @@ suite(suiteName, function() {
|
||||
}, {}, function(res) {
|
||||
assert.equal(res.statusCode, 200, res.body);
|
||||
var parsedBody = JSON.parse(res.body);
|
||||
var expectedBody = { layergroupid: expected_token };
|
||||
if ( expected_token ) {
|
||||
assert.equal(parsedBody.layergroupid, expected_token + ':' + expected_last_updated_epoch);
|
||||
}
|
||||
@@ -1077,10 +1032,11 @@ suite(suiteName, function() {
|
||||
}, {}, function(res) {
|
||||
assert.equal(res.statusCode, 200, res.body);
|
||||
assert.equal(res.headers['content-type'], "image/png");
|
||||
assert.imageEqualsFile(res.body, windshaft_fixtures + '/test_default_mapnik_point.png', IMAGE_EQUALS_TOLERANCE_PER_MIL,
|
||||
function(err, similarity) {
|
||||
next(err);
|
||||
});
|
||||
assert.imageEqualsFile(res.body, windshaft_fixtures + '/test_default_mapnik_point.png',
|
||||
IMAGE_EQUALS_TOLERANCE_PER_MIL, function(err/*, similarity*/) {
|
||||
next(err);
|
||||
}
|
||||
);
|
||||
});
|
||||
},
|
||||
function finish(err) {
|
||||
@@ -1117,7 +1073,7 @@ suite(suiteName, function() {
|
||||
]
|
||||
};
|
||||
var expected_token; // = "e34dd7e235138a062f8ba7ad051aa3a7";
|
||||
Step(
|
||||
step(
|
||||
function do_post()
|
||||
{
|
||||
var next = this;
|
||||
@@ -1156,7 +1112,6 @@ suite(suiteName, function() {
|
||||
},
|
||||
function check_get_tile(err, res) {
|
||||
if ( err ) throw err;
|
||||
var next = this;
|
||||
assert.equal(res.statusCode, 200, res.body);
|
||||
return null;
|
||||
},
|
||||
@@ -1188,10 +1143,10 @@ suite(suiteName, function() {
|
||||
// See https://github.com/CartoDB/Windshaft-cartodb/issues/111
|
||||
test("sql string can be very long", function(done){
|
||||
var long_val = 'pretty';
|
||||
for (var i=0; i<1024; ++i) long_val += ' long'
|
||||
for (var i=0; i<1024; ++i) long_val += ' long';
|
||||
long_val += ' string';
|
||||
var sql = "SELECT ";
|
||||
for (var i=0; i<16; ++i)
|
||||
for (i=0; i<16; ++i)
|
||||
sql += "'" + long_val + "'::text as pretty_long_field_name_" + i + ", ";
|
||||
sql += "cartodb_id, the_geom_webmercator FROM gadm4 g";
|
||||
var layergroup = {
|
||||
@@ -1206,7 +1161,7 @@ suite(suiteName, function() {
|
||||
};
|
||||
var errors = [];
|
||||
var expected_token;
|
||||
Step(
|
||||
step(
|
||||
function do_post()
|
||||
{
|
||||
var data = JSON.stringify(layergroup);
|
||||
@@ -1225,10 +1180,6 @@ suite(suiteName, function() {
|
||||
var parsedBody = JSON.parse(res.body);
|
||||
var token_components = parsedBody.layergroupid.split(':');
|
||||
expected_token = token_components[0];
|
||||
if (!cdbQueryTablesFromPostgresEnabledValue) { // only test if it was using the SQL API
|
||||
var last_request = sqlapi_server.getLastRequest();
|
||||
assert.equal(last_request.method, 'POST');
|
||||
}
|
||||
return null;
|
||||
},
|
||||
function cleanup(err) {
|
||||
@@ -1259,13 +1210,14 @@ suite(suiteName, function() {
|
||||
version: '1.0.0',
|
||||
layers: [
|
||||
{ options: {
|
||||
sql: 'select cartodb_id, ST_Translate(the_geom_webmercator, 5e6, 0) as the_geom_webmercator from test_table limit 2',
|
||||
sql: 'select cartodb_id, ST_Translate(the_geom_webmercator, 5e6, 0) as the_geom_webmercator' +
|
||||
' from test_table limit 2',
|
||||
interactivity: 'cartodb_id'
|
||||
} }
|
||||
]
|
||||
};
|
||||
|
||||
Step(
|
||||
step(
|
||||
function do_post()
|
||||
{
|
||||
var next = this;
|
||||
@@ -1307,7 +1259,7 @@ suite(suiteName, function() {
|
||||
]
|
||||
};
|
||||
|
||||
Step(
|
||||
step(
|
||||
function do_post()
|
||||
{
|
||||
var next = this;
|
||||
@@ -1415,7 +1367,7 @@ suite(suiteName, function() {
|
||||
{
|
||||
status: 403
|
||||
},
|
||||
function(res, err) {
|
||||
function(res) {
|
||||
assert.ok(res.body.match(/permission denied for relation test_table_private_1/));
|
||||
done();
|
||||
}
|
||||
@@ -1428,11 +1380,11 @@ suite(suiteName, function() {
|
||||
// This test will add map_style records, like
|
||||
// 'map_style|null|publicuser|my_table',
|
||||
redis_client.keys("map_style|*", function(err, matches) {
|
||||
redis_client.del(matches, function(err) {
|
||||
redis_client.select(5, function(err, matches) {
|
||||
redis_client.del(matches, function() {
|
||||
redis_client.select(5, function() {
|
||||
redis_client.keys("user:localhost:mapviews*", function(err, matches) {
|
||||
redis_client.del(matches, function(err) {
|
||||
sqlapi_server.close(done);
|
||||
redis_client.del(matches, function() {
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -1444,4 +1396,3 @@ suite(suiteName, function() {
|
||||
});
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
@@ -0,0 +1,338 @@
|
||||
var testHelper = require('../support/test_helper');
|
||||
|
||||
var assert = require('../support/assert');
|
||||
|
||||
var redis = require('redis');
|
||||
var _ = require('underscore');
|
||||
|
||||
|
||||
var QueryTablesApi = require('../../lib/cartodb/api/query_tables_api');
|
||||
var CartodbWindshaft = require('../../lib/cartodb/cartodb_windshaft');
|
||||
var serverOptions = require('../../lib/cartodb/server_options')();
|
||||
var server = new CartodbWindshaft(serverOptions);
|
||||
server.setMaxListeners(0);
|
||||
|
||||
describe('tests from old api translated to multilayer', function() {
|
||||
|
||||
var layergroupUrl = '/api/v1/map';
|
||||
|
||||
var redisClient = redis.createClient(global.environment.redis.port);
|
||||
after(function(done) {
|
||||
// This test will add map_style records, like
|
||||
// 'map_style|null|publicuser|my_table',
|
||||
redisClient.keys("map_style|*", function(err, matches) {
|
||||
redisClient.del(matches, function() {
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
var wadusSql = 'select 1 as cartodb_id, null::geometry as the_geom_webmercator';
|
||||
var pointSql = "SELECT 'SRID=3857;POINT(0 0)'::geometry as the_geom_webmercator, 1::int as cartodb_id";
|
||||
|
||||
function singleLayergroupConfig(sql, cartocss) {
|
||||
return {
|
||||
version: '1.0.0',
|
||||
layers: [
|
||||
{
|
||||
type: 'mapnik',
|
||||
options: {
|
||||
sql: sql,
|
||||
cartocss: cartocss,
|
||||
cartocss_version: '2.0.1'
|
||||
}
|
||||
}
|
||||
]
|
||||
};
|
||||
}
|
||||
|
||||
function createRequest(layergroup, userHost, apiKey) {
|
||||
var url = layergroupUrl;
|
||||
if (apiKey) {
|
||||
url += '?api_key=' + apiKey;
|
||||
}
|
||||
return {
|
||||
url: url,
|
||||
method: 'POST',
|
||||
headers: {
|
||||
host: userHost || 'localhost',
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
data: JSON.stringify(layergroup)
|
||||
};
|
||||
}
|
||||
|
||||
it("layergroup creation fails if CartoCSS is bogus", function(done) {
|
||||
var layergroup = singleLayergroupConfig(wadusSql, '#my_table3{');
|
||||
assert.response(server,
|
||||
createRequest(layergroup),
|
||||
{
|
||||
status: 400
|
||||
},
|
||||
function(res) {
|
||||
var parsed = JSON.parse(res.body);
|
||||
assert.ok(parsed.errors[0].match(/^style0/));
|
||||
assert.ok(parsed.errors[0].match(/missing closing/));
|
||||
done();
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
it("multiple bad styles returns 400 with all errors", function(done) {
|
||||
var layergroup = singleLayergroupConfig(wadusSql, '#my_table4{backgxxxxxround-color:#fff;foo:bar}');
|
||||
assert.response(server,
|
||||
createRequest(layergroup),
|
||||
{
|
||||
status: 400
|
||||
},
|
||||
function(res) {
|
||||
var parsed = JSON.parse(res.body);
|
||||
assert.equal(parsed.errors.length, 1);
|
||||
assert.ok(parsed.errors[0].match(/^style0/));
|
||||
assert.ok(parsed.errors[0].match(/Unrecognized rule: backgxxxxxround-color/));
|
||||
assert.ok(parsed.errors[0].match(/Unrecognized rule: foo/));
|
||||
done();
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
// Zoom is a special variable
|
||||
it("Specifying zoom level in CartoCSS does not need a 'zoom' variable in SQL output", function(done) {
|
||||
var layergroup = singleLayergroupConfig(pointSql, '#gadm4 [ zoom>=3] { marker-fill:red; }');
|
||||
|
||||
assert.response(server,
|
||||
createRequest(layergroup),
|
||||
{
|
||||
status: 200
|
||||
},
|
||||
function(res) {
|
||||
var parsed = JSON.parse(res.body);
|
||||
assert.ok(parsed.layergroupid);
|
||||
done();
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
// See https://github.com/CartoDB/Windshaft-cartodb/issues/88
|
||||
it("getting a tile from a user-specific database should return an expected tile", function(done) {
|
||||
var layergroup = singleLayergroupConfig(pointSql, '#layer { marker-fill:red; }');
|
||||
|
||||
var backupDBHost = global.environment.postgres.host;
|
||||
global.environment.postgres.host = '6.6.6.6';
|
||||
|
||||
assert.response(server,
|
||||
createRequest(layergroup, 'cartodb250user'),
|
||||
{
|
||||
status: 200
|
||||
},
|
||||
function(res) {
|
||||
var parsed = JSON.parse(res.body);
|
||||
assert.ok(parsed.layergroupid);
|
||||
|
||||
global.environment.postgres.host = backupDBHost;
|
||||
done();
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
// See https://github.com/CartoDB/Windshaft-cartodb/issues/89
|
||||
it("getting a tile with a user-specific database password", function(done) {
|
||||
var layergroup = singleLayergroupConfig(pointSql, '#layer { marker-fill:red; }');
|
||||
|
||||
var backupDBPass = global.environment.postgres_auth_pass;
|
||||
global.environment.postgres_auth_pass = '<%= user_password %>';
|
||||
|
||||
assert.response(server,
|
||||
createRequest(layergroup, 'cartodb250user', '4321'),
|
||||
{
|
||||
status: 200
|
||||
},
|
||||
function(res) {
|
||||
var parsed = JSON.parse(res.body);
|
||||
assert.ok(parsed.layergroupid);
|
||||
|
||||
global.environment.postgres_auth_pass = backupDBPass;
|
||||
done();
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
it("creating a layergroup from lzma param", function(done){
|
||||
var params = {
|
||||
config: JSON.stringify(singleLayergroupConfig(pointSql, '#layer { marker-fill:red; }'))
|
||||
};
|
||||
|
||||
testHelper.lzma_compress_to_base64(JSON.stringify(params), 1, function(err, lzma) {
|
||||
if (err) {
|
||||
return done(err);
|
||||
}
|
||||
assert.response(server,
|
||||
{
|
||||
url: layergroupUrl + '?lzma=' + encodeURIComponent(lzma),
|
||||
method: 'GET',
|
||||
headers: {
|
||||
host: 'localhost'
|
||||
},
|
||||
encoding: 'binary'
|
||||
},
|
||||
{
|
||||
status: 200
|
||||
},
|
||||
function(res) {
|
||||
var parsed = JSON.parse(res.body);
|
||||
assert.ok(parsed.layergroupid);
|
||||
|
||||
done();
|
||||
}
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
it("creating a layergroup from lzma param, invalid json input", function(done) {
|
||||
var params = {
|
||||
config: 'WADUS'
|
||||
};
|
||||
|
||||
testHelper.lzma_compress_to_base64(JSON.stringify(params), 1, function(err, lzma) {
|
||||
if (err) {
|
||||
return done(err);
|
||||
}
|
||||
assert.response(server,
|
||||
{
|
||||
url: layergroupUrl + '?lzma=' + encodeURIComponent(lzma),
|
||||
method: 'GET',
|
||||
headers: {
|
||||
host: 'localhost'
|
||||
},
|
||||
encoding: 'binary'
|
||||
},
|
||||
{
|
||||
status: 400
|
||||
},
|
||||
function(res) {
|
||||
var parsed = JSON.parse(res.body);
|
||||
assert.deepEqual(parsed, { errors: [ 'Unexpected token W' ] });
|
||||
|
||||
done();
|
||||
}
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
it("uses queries postgresql to figure affected tables in query", function(done) {
|
||||
var tableName = 'gadm4';
|
||||
var expectedCacheChannel = _.template('<%= databaseName %>:public.<%= tableName %>', {
|
||||
databaseName: _.template(global.environment.postgres_auth_user, {user_id:1}) + '_db',
|
||||
tableName: tableName
|
||||
});
|
||||
|
||||
var layergroup = singleLayergroupConfig('select * from ' + tableName, '#gadm4 { marker-fill: red; }');
|
||||
|
||||
assert.response(server,
|
||||
{
|
||||
url: layergroupUrl + '?config=' + encodeURIComponent(JSON.stringify(layergroup)),
|
||||
method: 'GET',
|
||||
headers: {
|
||||
host: 'localhost'
|
||||
}
|
||||
},
|
||||
{
|
||||
status: 200
|
||||
},
|
||||
function(res) {
|
||||
var parsed = JSON.parse(res.body);
|
||||
assert.ok(parsed.layergroupid);
|
||||
|
||||
assert.ok(res.headers.hasOwnProperty('x-cache-channel'));
|
||||
assert.equal(res.headers['x-cache-channel'], expectedCacheChannel);
|
||||
|
||||
done();
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
it("creates layergroup fails when postgresql queries fail to figure affected tables in query", function(done) {
|
||||
|
||||
var runQueryFn = QueryTablesApi.prototype.runQuery;
|
||||
QueryTablesApi.prototype.runQuery = function(username, query, queryHandler, callback) {
|
||||
return queryHandler(new Error('fake error message'), [], callback);
|
||||
};
|
||||
|
||||
var layergroup = singleLayergroupConfig('select * from gadm4', '#gadm4 { marker-fill: red; }');
|
||||
|
||||
assert.response(server,
|
||||
{
|
||||
url: layergroupUrl + '?config=' + encodeURIComponent(JSON.stringify(layergroup)),
|
||||
method: 'GET',
|
||||
headers: {
|
||||
host: 'localhost'
|
||||
}
|
||||
},
|
||||
{
|
||||
status: 400
|
||||
},
|
||||
function(res) {
|
||||
QueryTablesApi.prototype.runQuery = runQueryFn;
|
||||
|
||||
assert.ok(!res.headers.hasOwnProperty('x-cache-channel'));
|
||||
|
||||
var parsed = JSON.parse(res.body);
|
||||
assert.deepEqual(parsed, {
|
||||
errors: ["Error: could not fetch affected tables and last updated time: fake error message"]
|
||||
});
|
||||
|
||||
done();
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
it("tile requests works when postgresql queries fail to figure affected tables in query", function(done) {
|
||||
var layergroup = singleLayergroupConfig('select * from gadm4', '#gadm4 { marker-fill: red; }');
|
||||
assert.response(server,
|
||||
{
|
||||
url: layergroupUrl + '?config=' + encodeURIComponent(JSON.stringify(layergroup)),
|
||||
method: 'GET',
|
||||
headers: {
|
||||
host: 'localhost'
|
||||
}
|
||||
},
|
||||
{
|
||||
status: 200
|
||||
},
|
||||
function(res) {
|
||||
var runQueryFn = QueryTablesApi.prototype.runQuery;
|
||||
QueryTablesApi.prototype.runQuery = function(username, query, queryHandler, callback) {
|
||||
return queryHandler(new Error('failed to query database for affected tables'), [], callback);
|
||||
};
|
||||
|
||||
// reset internal cacheChannel cache
|
||||
serverOptions.channelCache = {};
|
||||
|
||||
assert.response(server,
|
||||
{
|
||||
url: layergroupUrl + _.template('/<%= layergroupId %>/<%= z %>/<%= x %>/<%= y %>.png', {
|
||||
layergroupId: JSON.parse(res.body).layergroupid,
|
||||
z: 0,
|
||||
x: 0,
|
||||
y: 0
|
||||
}),
|
||||
method: 'GET',
|
||||
headers: {
|
||||
host: 'localhost'
|
||||
},
|
||||
encoding: 'binary'
|
||||
},
|
||||
{
|
||||
status: 200
|
||||
},
|
||||
function(res) {
|
||||
assert.ok(!res.headers.hasOwnProperty('x-cache-channel'));
|
||||
QueryTablesApi.prototype.runQuery = runQueryFn;
|
||||
done();
|
||||
}
|
||||
);
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
});
|
||||
@@ -130,7 +130,7 @@ suite('named_layers', function() {
|
||||
var next = this;
|
||||
assert.response(server,
|
||||
{
|
||||
url: '/tiles/layergroup',
|
||||
url: '/api/v1/map',
|
||||
method: 'POST',
|
||||
headers: {
|
||||
host: 'localhost',
|
||||
@@ -183,7 +183,7 @@ suite('named_layers', function() {
|
||||
var next = this;
|
||||
assert.response(server,
|
||||
{
|
||||
url: '/tiles/layergroup',
|
||||
url: '/api/v1/map',
|
||||
method: 'POST',
|
||||
headers: {
|
||||
host: 'localhost',
|
||||
@@ -240,7 +240,7 @@ suite('named_layers', function() {
|
||||
var next = this;
|
||||
assert.response(server,
|
||||
{
|
||||
url: '/tiles/layergroup',
|
||||
url: '/api/v1/map',
|
||||
method: 'POST',
|
||||
headers: {
|
||||
host: 'localhost',
|
||||
@@ -293,7 +293,7 @@ suite('named_layers', function() {
|
||||
var next = this;
|
||||
assert.response(server,
|
||||
{
|
||||
url: '/tiles/layergroup',
|
||||
url: '/api/v1/map',
|
||||
method: 'POST',
|
||||
headers: {
|
||||
host: 'localhost',
|
||||
@@ -373,7 +373,7 @@ suite('named_layers', function() {
|
||||
var next = this;
|
||||
assert.response(server,
|
||||
{
|
||||
url: '/tiles/layergroup',
|
||||
url: '/api/v1/map',
|
||||
method: 'POST',
|
||||
headers: {
|
||||
host: 'localhost',
|
||||
@@ -408,7 +408,7 @@ suite('named_layers', function() {
|
||||
var next = this;
|
||||
assert.response(server,
|
||||
{
|
||||
url: '/tiles/layergroup/' + layergroupId + '/0/0/0.png',
|
||||
url: '/api/v1/map/' + layergroupId + '/0/0/0.png',
|
||||
method: 'GET',
|
||||
headers: {
|
||||
host: 'localhost'
|
||||
@@ -501,7 +501,7 @@ suite('named_layers', function() {
|
||||
var next = this;
|
||||
assert.response(server,
|
||||
{
|
||||
url: '/tiles/layergroup',
|
||||
url: '/api/v1/map',
|
||||
method: 'POST',
|
||||
headers: {
|
||||
host: 'localhost',
|
||||
@@ -536,7 +536,7 @@ suite('named_layers', function() {
|
||||
var next = this;
|
||||
assert.response(server,
|
||||
{
|
||||
url: '/tiles/layergroup/' + layergroupId + '/0/0/0.png',
|
||||
url: '/api/v1/map/' + layergroupId + '/0/0/0.png',
|
||||
method: 'GET',
|
||||
headers: {
|
||||
host: 'localhost'
|
||||
@@ -602,7 +602,7 @@ suite('named_layers', function() {
|
||||
var next = this;
|
||||
assert.response(server,
|
||||
{
|
||||
url: '/tiles/layergroup',
|
||||
url: '/api/v1/map',
|
||||
method: 'POST',
|
||||
headers: {
|
||||
host: 'localhost',
|
||||
|
||||
+9
-1331
File diff suppressed because it is too large
Load Diff
@@ -6,7 +6,6 @@ var semver = require('semver');
|
||||
var Step = require('step');
|
||||
var strftime = require('strftime');
|
||||
var NamedMapsCacheEntry = require(__dirname + '/../../lib/cartodb/cache/model/named_maps_entry');
|
||||
var SQLAPIEmu = require(__dirname + '/../support/SQLAPIEmu.js');
|
||||
var redis_stats_db = 5;
|
||||
|
||||
// Pollute the PG environment to make sure
|
||||
@@ -25,22 +24,13 @@ var serverOptions = ServerOptions();
|
||||
var server = new CartodbWindshaft(serverOptions);
|
||||
server.setMaxListeners(0);
|
||||
|
||||
[true, false].forEach(function(cdbQueryTablesFromPostgresEnabledValue) {
|
||||
|
||||
suite('template_api:postgres=' + cdbQueryTablesFromPostgresEnabledValue, function() {
|
||||
suite('template_api', function() {
|
||||
serverOptions.channelCache = {};
|
||||
|
||||
var redis_client = redis.createClient(global.environment.redis.port);
|
||||
var sqlapi_server;
|
||||
var expected_last_updated_epoch = 1234567890123; // this is hard-coded into SQLAPIEmu
|
||||
var expected_last_updated = new Date(expected_last_updated_epoch).toISOString();
|
||||
|
||||
suiteSetup(function(done){
|
||||
global.environment.enabledFeatures = { cdbQueryTablesFromPostgres: cdbQueryTablesFromPostgresEnabledValue };
|
||||
sqlapi_server = new SQLAPIEmu(global.environment.sqlapi.port, done);
|
||||
// TODO: check redis is clean ?
|
||||
});
|
||||
|
||||
var template_acceptance1 = {
|
||||
version: '0.0.1',
|
||||
name: 'acceptance1',
|
||||
@@ -87,7 +77,7 @@ suite('template_api:postgres=' + cdbQueryTablesFromPostgresEnabledValue, functio
|
||||
var expected_failure = false;
|
||||
var expected_tpl_id = "localhost@acceptance1";
|
||||
var post_request_1 = {
|
||||
url: '/tiles/template',
|
||||
url: '/api/v1/map/named',
|
||||
method: 'POST',
|
||||
headers: {host: 'localhost', 'Content-Type': 'application/json' },
|
||||
data: JSON.stringify(template_acceptance1)
|
||||
@@ -174,7 +164,7 @@ suite('template_api:postgres=' + cdbQueryTablesFromPostgresEnabledValue, functio
|
||||
broken_template.auth.method = 'token';
|
||||
delete broken_template.auth.tokens;
|
||||
var post_request_1 = {
|
||||
url: '/tiles/template?api_key=1234',
|
||||
url: '/api/v1/map/named?api_key=1234',
|
||||
method: 'POST',
|
||||
headers: {host: 'localhost', 'Content-Type': 'application/json' },
|
||||
data: JSON.stringify(broken_template)
|
||||
@@ -204,7 +194,7 @@ suite('template_api:postgres=' + cdbQueryTablesFromPostgresEnabledValue, functio
|
||||
broken_template.auth.method = 'token';
|
||||
broken_template.auth.tokens = [];
|
||||
var post_request_1 = {
|
||||
url: '/tiles/template?api_key=1234',
|
||||
url: '/api/v1/map/named?api_key=1234',
|
||||
method: 'POST',
|
||||
headers: {host: 'localhost', 'Content-Type': 'application/json' },
|
||||
data: JSON.stringify(broken_template)
|
||||
@@ -231,7 +221,7 @@ suite('template_api:postgres=' + cdbQueryTablesFromPostgresEnabledValue, functio
|
||||
var broken_template = JSON.parse(JSON.stringify(template_acceptance1));
|
||||
broken_template.name = 'broken1';
|
||||
var post_request_1 = {
|
||||
url: '/tiles/template?api_key=1234',
|
||||
url: '/api/v1/map/named?api_key=1234',
|
||||
method: 'POST',
|
||||
headers: {host: 'localhost', 'Content-Type': 'application/json' },
|
||||
data: JSON.stringify(broken_template)
|
||||
@@ -255,7 +245,7 @@ suite('template_api:postgres=' + cdbQueryTablesFromPostgresEnabledValue, functio
|
||||
broken_template.auth.method = 'token';
|
||||
broken_template.auth.tokens = [];
|
||||
var put_request_1 = {
|
||||
url: '/tiles/template/' + tpl_id + '/?api_key=1234',
|
||||
url: '/api/v1/map/named/' + tpl_id + '/?api_key=1234',
|
||||
method: 'PUT',
|
||||
headers: {host: 'localhost', 'Content-Type': 'application/json' },
|
||||
data: JSON.stringify(broken_template)
|
||||
@@ -276,7 +266,7 @@ suite('template_api:postgres=' + cdbQueryTablesFromPostgresEnabledValue, functio
|
||||
'Error for invalid authentication on PUT does not match ' +
|
||||
re + ': ' + parsed.error);
|
||||
var del_request = {
|
||||
url: '/tiles/template/' + tpl_id + '?api_key=1234',
|
||||
url: '/api/v1/map/named/' + tpl_id + '?api_key=1234',
|
||||
method: 'DELETE',
|
||||
headers: {host: 'localhost'}
|
||||
}
|
||||
@@ -312,7 +302,7 @@ suite('template_api:postgres=' + cdbQueryTablesFromPostgresEnabledValue, functio
|
||||
Step(function postTemplate1(err, res) {
|
||||
var next = this;
|
||||
var post_request = {
|
||||
url: '/tiles/template?api_key=1234',
|
||||
url: '/api/v1/map/named?api_key=1234',
|
||||
method: 'POST',
|
||||
headers: {host: 'localhost.localhost', 'Content-Type': 'application/json' },
|
||||
data: JSON.stringify(template_acceptance1)
|
||||
@@ -321,7 +311,7 @@ suite('template_api:postgres=' + cdbQueryTablesFromPostgresEnabledValue, functio
|
||||
},
|
||||
function testCORS() {
|
||||
assert.response(server, {
|
||||
url: '/tiles/template/acceptance1',
|
||||
url: '/api/v1/map/named/acceptance1',
|
||||
method: 'OPTIONS'
|
||||
},{
|
||||
status: 200,
|
||||
@@ -341,7 +331,7 @@ suite('template_api:postgres=' + cdbQueryTablesFromPostgresEnabledValue, functio
|
||||
Step(function postTemplate1(err, res) {
|
||||
var next = this;
|
||||
var post_request = {
|
||||
url: '/tiles/template?api_key=1234',
|
||||
url: '/api/v1/map/named?api_key=1234',
|
||||
method: 'POST',
|
||||
headers: {host: 'localhost', 'Content-Type': 'application/json' },
|
||||
data: JSON.stringify(tmpl)
|
||||
@@ -353,7 +343,7 @@ suite('template_api:postgres=' + cdbQueryTablesFromPostgresEnabledValue, functio
|
||||
function testCORS() {
|
||||
var next = this;
|
||||
assert.response(server, {
|
||||
url: '/tiles/template/' + tmpl.name,
|
||||
url: '/api/v1/map/named/' + tmpl.name,
|
||||
method: 'POST',
|
||||
headers: {host: 'localhost', 'Content-Type': 'application/json' },
|
||||
},{
|
||||
@@ -367,7 +357,7 @@ suite('template_api:postgres=' + cdbQueryTablesFromPostgresEnabledValue, functio
|
||||
function deleteTemplate(err) {
|
||||
if ( err ) throw err;
|
||||
var del_request = {
|
||||
url: '/tiles/template/' + tmpl.name + '?api_key=1234',
|
||||
url: '/api/v1/map/named/' + tmpl.name + '?api_key=1234',
|
||||
method: 'DELETE',
|
||||
headers: {host: 'localhost', 'Content-Type': 'application/json' }
|
||||
}
|
||||
@@ -390,7 +380,7 @@ suite('template_api:postgres=' + cdbQueryTablesFromPostgresEnabledValue, functio
|
||||
{
|
||||
var next = this;
|
||||
var post_request = {
|
||||
url: '/tiles/template?api_key=1234',
|
||||
url: '/api/v1/map/named?api_key=1234',
|
||||
method: 'POST',
|
||||
headers: {host: 'localhost', 'Content-Type': 'application/json' },
|
||||
data: JSON.stringify(template_acceptance1)
|
||||
@@ -411,7 +401,7 @@ suite('template_api:postgres=' + cdbQueryTablesFromPostgresEnabledValue, functio
|
||||
var backup_name = template_acceptance1.name;
|
||||
template_acceptance1.name += '_new';
|
||||
var post_request = {
|
||||
url: '/tiles/template?api_key=1234',
|
||||
url: '/api/v1/map/named?api_key=1234',
|
||||
method: 'POST',
|
||||
headers: {host: 'localhost', 'Content-Type': 'application/json' },
|
||||
data: JSON.stringify(template_acceptance1)
|
||||
@@ -430,7 +420,7 @@ suite('template_api:postgres=' + cdbQueryTablesFromPostgresEnabledValue, functio
|
||||
tplid2 = parsed.template_id;
|
||||
var next = this;
|
||||
var get_request = {
|
||||
url: '/tiles/template',
|
||||
url: '/api/v1/map/named',
|
||||
method: 'GET',
|
||||
headers: {host: 'localhost'}
|
||||
}
|
||||
@@ -448,7 +438,7 @@ suite('template_api:postgres=' + cdbQueryTablesFromPostgresEnabledValue, functio
|
||||
assert.ok(err.match(/authenticated user/), err);
|
||||
var next = this;
|
||||
var get_request = {
|
||||
url: '/tiles/template?api_key=1234',
|
||||
url: '/api/v1/map/named?api_key=1234',
|
||||
method: 'GET',
|
||||
headers: {host: 'localhost'}
|
||||
}
|
||||
@@ -507,7 +497,7 @@ suite('template_api:postgres=' + cdbQueryTablesFromPostgresEnabledValue, functio
|
||||
{
|
||||
var next = this;
|
||||
var post_request = {
|
||||
url: '/tiles/template?api_key=1234',
|
||||
url: '/api/v1/map/named?api_key=1234',
|
||||
method: 'POST',
|
||||
headers: {host: 'localhost', 'Content-Type': 'application/json' },
|
||||
data: JSON.stringify(makeTemplate())
|
||||
@@ -526,7 +516,7 @@ suite('template_api:postgres=' + cdbQueryTablesFromPostgresEnabledValue, functio
|
||||
var backup_name = template_acceptance1.name;
|
||||
template_acceptance1.name = 'changed_name';
|
||||
var put_request = {
|
||||
url: '/tiles/template/' + tpl_id + '/?api_key=1234',
|
||||
url: '/api/v1/map/named/' + tpl_id + '/?api_key=1234',
|
||||
method: 'PUT',
|
||||
headers: {host: 'localhost', 'Content-Type': 'application/json' },
|
||||
data: JSON.stringify(template_acceptance1)
|
||||
@@ -545,7 +535,7 @@ suite('template_api:postgres=' + cdbQueryTablesFromPostgresEnabledValue, functio
|
||||
assert.ok(parsedBody.error.match(/cannot update name/i),
|
||||
'Unexpected error for invalid update: ' + parsedBody.error);
|
||||
var put_request = {
|
||||
url: '/tiles/template/unexistent/?api_key=1234',
|
||||
url: '/api/v1/map/named/unexistent/?api_key=1234',
|
||||
method: 'PUT',
|
||||
headers: {host: 'localhost', 'Content-Type': 'application/json' },
|
||||
data: JSON.stringify(makeTemplate())
|
||||
@@ -563,7 +553,7 @@ suite('template_api:postgres=' + cdbQueryTablesFromPostgresEnabledValue, functio
|
||||
assert.ok(parsedBody.error.match(/cannot update name/i),
|
||||
'Unexpected error for invalid update: ' + parsedBody.error);
|
||||
var put_request = {
|
||||
url: '/tiles/template/' + tpl_id + '/?api_key=1234',
|
||||
url: '/api/v1/map/named/' + tpl_id + '/?api_key=1234',
|
||||
method: 'PUT',
|
||||
headers: {host: 'localhost', 'Content-Type': 'application/json' },
|
||||
data: JSON.stringify(makeTemplate())
|
||||
@@ -619,7 +609,7 @@ suite('template_api:postgres=' + cdbQueryTablesFromPostgresEnabledValue, functio
|
||||
{
|
||||
var next = this;
|
||||
var post_request = {
|
||||
url: '/tiles/template?api_key=1234',
|
||||
url: '/api/v1/map/named?api_key=1234',
|
||||
method: 'POST',
|
||||
headers: {host: 'localhost', 'Content-Type': 'application/json' },
|
||||
data: JSON.stringify(makeTemplate())
|
||||
@@ -636,7 +626,7 @@ suite('template_api:postgres=' + cdbQueryTablesFromPostgresEnabledValue, functio
|
||||
"Missing 'template_id' from response body: " + res.body);
|
||||
tpl_id = parsed.template_id;
|
||||
var get_request = {
|
||||
url: '/tiles/template/' + tpl_id,
|
||||
url: '/api/v1/map/named/' + tpl_id,
|
||||
method: 'GET',
|
||||
headers: {host: 'localhost'}
|
||||
}
|
||||
@@ -653,7 +643,7 @@ suite('template_api:postgres=' + cdbQueryTablesFromPostgresEnabledValue, functio
|
||||
assert.ok(parsedBody.error.match(/only.*authenticated.*user/i),
|
||||
'Unexpected error for unauthenticated template get: ' + parsedBody.error);
|
||||
var get_request = {
|
||||
url: '/tiles/template/' + tpl_id + '?api_key=1234',
|
||||
url: '/api/v1/map/named/' + tpl_id + '?api_key=1234',
|
||||
method: 'GET',
|
||||
headers: {host: 'localhost'}
|
||||
}
|
||||
@@ -708,7 +698,7 @@ suite('template_api:postgres=' + cdbQueryTablesFromPostgresEnabledValue, functio
|
||||
{
|
||||
var next = this;
|
||||
var post_request = {
|
||||
url: '/tiles/template?api_key=1234',
|
||||
url: '/api/v1/map/named?api_key=1234',
|
||||
method: 'POST',
|
||||
headers: {host: 'localhost', 'Content-Type': 'application/json' },
|
||||
data: JSON.stringify(makeTemplate())
|
||||
@@ -725,7 +715,7 @@ suite('template_api:postgres=' + cdbQueryTablesFromPostgresEnabledValue, functio
|
||||
"Missing 'template_id' from response body: " + res.body);
|
||||
tpl_id = parsed.template_id;
|
||||
var get_request = {
|
||||
url: '/tiles/template/' + tpl_id + '?api_key=1234',
|
||||
url: '/api/v1/map/named/' + tpl_id + '?api_key=1234',
|
||||
method: 'GET',
|
||||
headers: {host: 'localhost'}
|
||||
}
|
||||
@@ -742,7 +732,7 @@ suite('template_api:postgres=' + cdbQueryTablesFromPostgresEnabledValue, functio
|
||||
"Missing 'template' from response body: " + res.body);
|
||||
assert.deepEqual(extendDefaultsTemplate(makeTemplate()), parsed.template);
|
||||
var del_request = {
|
||||
url: '/tiles/template/' + tpl_id,
|
||||
url: '/api/v1/map/named/' + tpl_id,
|
||||
method: 'DELETE',
|
||||
headers: {host: 'localhost'}
|
||||
}
|
||||
@@ -760,7 +750,7 @@ suite('template_api:postgres=' + cdbQueryTablesFromPostgresEnabledValue, functio
|
||||
assert.ok(parsed.error.match(/only.*authenticated.*user/i),
|
||||
'Unexpected error for unauthenticated template get: ' + parsed.error);
|
||||
var del_request = {
|
||||
url: '/tiles/template/' + tpl_id + '?api_key=1234',
|
||||
url: '/api/v1/map/named/' + tpl_id + '?api_key=1234',
|
||||
method: 'DELETE',
|
||||
headers: {host: 'localhost'}
|
||||
}
|
||||
@@ -774,7 +764,7 @@ suite('template_api:postgres=' + cdbQueryTablesFromPostgresEnabledValue, functio
|
||||
assert.equal(res.statusCode, 204, res.statusCode + ': ' + res.body);
|
||||
assert.ok(!res.body, 'Unexpected body in DELETE /template response');
|
||||
var get_request = {
|
||||
url: '/tiles/template/' + tpl_id + '?api_key=1234',
|
||||
url: '/api/v1/map/named/' + tpl_id + '?api_key=1234',
|
||||
method: 'GET',
|
||||
headers: {host: 'localhost'}
|
||||
}
|
||||
@@ -852,7 +842,7 @@ suite('template_api:postgres=' + cdbQueryTablesFromPostgresEnabledValue, functio
|
||||
{
|
||||
var next = this;
|
||||
var post_request = {
|
||||
url: '/tiles/template?api_key=1234',
|
||||
url: '/api/v1/map/named?api_key=1234',
|
||||
method: 'POST',
|
||||
headers: {host: 'localhost', 'Content-Type': 'application/json' },
|
||||
data: JSON.stringify(template_acceptance2)
|
||||
@@ -869,7 +859,7 @@ suite('template_api:postgres=' + cdbQueryTablesFromPostgresEnabledValue, functio
|
||||
"Missing 'template_id' from response body: " + res.body);
|
||||
tpl_id = parsed.template_id;
|
||||
var post_request = {
|
||||
url: '/tiles/template/' + tpl_id,
|
||||
url: '/api/v1/map/named/' + tpl_id,
|
||||
method: 'POST',
|
||||
headers: {host: 'localhost', 'Content-Type': 'application/json' },
|
||||
data: JSON.stringify(template_params)
|
||||
@@ -890,7 +880,7 @@ suite('template_api:postgres=' + cdbQueryTablesFromPostgresEnabledValue, functio
|
||||
assert.ok(parsed.error.match(/unauthorized/i),
|
||||
'Unexpected error for unauthorized instance : ' + parsed.error);
|
||||
var post_request = {
|
||||
url: '/tiles/template/' + tpl_id + '?auth_token=valid2',
|
||||
url: '/api/v1/map/named/' + tpl_id + '?auth_token=valid2',
|
||||
method: 'POST',
|
||||
headers: {host: 'foreign', 'Content-Type': 'application/json' },
|
||||
data: JSON.stringify(template_params)
|
||||
@@ -909,7 +899,7 @@ suite('template_api:postgres=' + cdbQueryTablesFromPostgresEnabledValue, functio
|
||||
assert.ok(parsed.error.match(/cannot instanciate/i),
|
||||
'Unexpected error for forbidden instance : ' + parsed.error);
|
||||
var post_request = {
|
||||
url: '/tiles/template/' + tpl_id + '?auth_token=valid2',
|
||||
url: '/api/v1/map/named/' + tpl_id + '?auth_token=valid2',
|
||||
method: 'POST',
|
||||
headers: {host: 'localhost', 'Content-Type': 'application/json' },
|
||||
data: JSON.stringify(template_params)
|
||||
@@ -933,7 +923,7 @@ suite('template_api:postgres=' + cdbQueryTablesFromPostgresEnabledValue, functio
|
||||
"Missing 'last_updated' from response body: " + res.body);
|
||||
// TODO: check value of last_updated ?
|
||||
var get_request = {
|
||||
url: '/tiles/layergroup/' + layergroupid + ':cb0/0/0/0.png',
|
||||
url: '/api/v1/map/' + layergroupid + ':cb0/0/0/0.png',
|
||||
method: 'GET',
|
||||
headers: {host: 'localhost' },
|
||||
encoding: 'binary'
|
||||
@@ -953,7 +943,7 @@ suite('template_api:postgres=' + cdbQueryTablesFromPostgresEnabledValue, functio
|
||||
'Unexpected error for unauthorized instance '
|
||||
+ '(expected /permission denied/): ' + parsed.error);
|
||||
var get_request = {
|
||||
url: '/tiles/layergroup/' + layergroupid + '/0/0/0.png?auth_token=valid1',
|
||||
url: '/api/v1/map/' + layergroupid + '/0/0/0.png?auth_token=valid1',
|
||||
method: 'GET',
|
||||
headers: {host: 'localhost' },
|
||||
encoding: 'binary'
|
||||
@@ -975,7 +965,7 @@ suite('template_api:postgres=' + cdbQueryTablesFromPostgresEnabledValue, functio
|
||||
if ( err ) throw err;
|
||||
var foreignsigned = layergroupid.replace(/[^@]*@/, 'foreign@');
|
||||
var get_request = {
|
||||
url: '/tiles/layergroup/' + foreignsigned + '/0/0/0.png?auth_token=valid1',
|
||||
url: '/api/v1/map/' + foreignsigned + '/0/0/0.png?auth_token=valid1',
|
||||
method: 'GET',
|
||||
headers: {host: 'localhost' },
|
||||
encoding: 'binary'
|
||||
@@ -1001,7 +991,7 @@ suite('template_api:postgres=' + cdbQueryTablesFromPostgresEnabledValue, functio
|
||||
{
|
||||
if ( err ) throw err;
|
||||
var del_request = {
|
||||
url: '/tiles/template/' + tpl_id + '?api_key=1234',
|
||||
url: '/api/v1/map/named/' + tpl_id + '?api_key=1234',
|
||||
method: 'DELETE',
|
||||
headers: {host: 'localhost'}
|
||||
}
|
||||
@@ -1014,7 +1004,7 @@ suite('template_api:postgres=' + cdbQueryTablesFromPostgresEnabledValue, functio
|
||||
assert.equal(res.statusCode, 204,
|
||||
'Deleting template: ' + res.statusCode + ':' + res.body);
|
||||
var get_request = {
|
||||
url: '/tiles/layergroup/' + layergroupid + '/0/0/0.png?auth_token=valid1',
|
||||
url: '/api/v1/map/' + layergroupid + '/0/0/0.png?auth_token=valid1',
|
||||
method: 'GET',
|
||||
headers: {host: 'localhost' },
|
||||
encoding: 'binary'
|
||||
@@ -1086,7 +1076,7 @@ suite('template_api:postgres=' + cdbQueryTablesFromPostgresEnabledValue, functio
|
||||
{
|
||||
var next = this;
|
||||
var post_request = {
|
||||
url: '/tiles/template?api_key=1234',
|
||||
url: '/api/v1/map/named?api_key=1234',
|
||||
method: 'POST',
|
||||
headers: {host: 'localhost', 'Content-Type': 'application/json' },
|
||||
data: JSON.stringify(template)
|
||||
@@ -1103,7 +1093,7 @@ suite('template_api:postgres=' + cdbQueryTablesFromPostgresEnabledValue, functio
|
||||
"Missing 'template_id' from response body: " + res.body);
|
||||
tpl_id = parsed.template_id;
|
||||
var post_request = {
|
||||
url: '/tiles/template/' + tpl_id,
|
||||
url: '/api/v1/map/named/' + tpl_id,
|
||||
method: 'POST',
|
||||
headers: {host: 'localhost', 'Content-Type': 'application/json' },
|
||||
data: JSON.stringify(template_params)
|
||||
@@ -1124,7 +1114,7 @@ suite('template_api:postgres=' + cdbQueryTablesFromPostgresEnabledValue, functio
|
||||
assert.ok(parsed.error.match(/unauthorized/i),
|
||||
'Unexpected error for unauthorized instance : ' + parsed.error);
|
||||
var post_request = {
|
||||
url: '/tiles/template/' + tpl_id + '?auth_token=valid2',
|
||||
url: '/api/v1/map/named/' + tpl_id + '?auth_token=valid2',
|
||||
method: 'POST',
|
||||
headers: {host: 'localhost', 'Content-Type': 'application/json' },
|
||||
data: JSON.stringify(template_params)
|
||||
@@ -1148,7 +1138,7 @@ suite('template_api:postgres=' + cdbQueryTablesFromPostgresEnabledValue, functio
|
||||
"Missing 'last_updated' from response body: " + res.body);
|
||||
// TODO: check value of last_updated ?
|
||||
var get_request = {
|
||||
url: '/tiles/layergroup/' + layergroupid + ':cb0/0/0/0/0.json.torque',
|
||||
url: '/api/v1/map/' + layergroupid + ':cb0/0/0/0/0.json.torque',
|
||||
method: 'GET',
|
||||
headers: {host: 'localhost' },
|
||||
encoding: 'binary'
|
||||
@@ -1168,7 +1158,7 @@ suite('template_api:postgres=' + cdbQueryTablesFromPostgresEnabledValue, functio
|
||||
'Unexpected error for unauthorized instance '
|
||||
+ '(expected /permission denied): ' + parsed.error);
|
||||
var get_request = {
|
||||
url: '/tiles/layergroup/' + layergroupid + ':cb1/0/0/0/0.json.torque?auth_token=valid1',
|
||||
url: '/api/v1/map/' + layergroupid + ':cb1/0/0/0/0.json.torque?auth_token=valid1',
|
||||
method: 'GET',
|
||||
headers: {host: 'localhost' },
|
||||
encoding: 'binary'
|
||||
@@ -1190,7 +1180,7 @@ suite('template_api:postgres=' + cdbQueryTablesFromPostgresEnabledValue, functio
|
||||
serverOptions = ServerOptions(); // need to clean channel cache
|
||||
server = new CartodbWindshaft(serverOptions);
|
||||
var get_request = {
|
||||
url: '/tiles/layergroup/' + layergroupid + ':cb1/0/0/0/1.json.torque?auth_token=valid1',
|
||||
url: '/api/v1/map/' + layergroupid + ':cb1/0/0/0/1.json.torque?auth_token=valid1',
|
||||
method: 'GET',
|
||||
headers: {host: 'localhost' },
|
||||
encoding: 'binary'
|
||||
@@ -1214,7 +1204,7 @@ suite('template_api:postgres=' + cdbQueryTablesFromPostgresEnabledValue, functio
|
||||
{
|
||||
if ( err ) throw err;
|
||||
var del_request = {
|
||||
url: '/tiles/template/' + tpl_id + '?api_key=1234',
|
||||
url: '/api/v1/map/named/' + tpl_id + '?api_key=1234',
|
||||
method: 'DELETE',
|
||||
headers: {host: 'localhost'}
|
||||
}
|
||||
@@ -1227,7 +1217,7 @@ suite('template_api:postgres=' + cdbQueryTablesFromPostgresEnabledValue, functio
|
||||
assert.equal(res.statusCode, 204,
|
||||
'Deleting template: ' + res.statusCode + ':' + res.body);
|
||||
var get_request = {
|
||||
url: '/tiles/layergroup/' + layergroupid + ':cb2/0/0/0/0.json.torque?auth_token=valid1',
|
||||
url: '/api/v1/map/' + layergroupid + ':cb2/0/0/0/0.json.torque?auth_token=valid1',
|
||||
method: 'GET',
|
||||
headers: {host: 'localhost' },
|
||||
encoding: 'binary'
|
||||
@@ -1301,7 +1291,7 @@ suite('template_api:postgres=' + cdbQueryTablesFromPostgresEnabledValue, functio
|
||||
{
|
||||
var next = this;
|
||||
var post_request = {
|
||||
url: '/tiles/template?api_key=1234',
|
||||
url: '/api/v1/map/named?api_key=1234',
|
||||
method: 'POST',
|
||||
headers: {host: 'localhost', 'Content-Type': 'application/json' },
|
||||
data: JSON.stringify(template)
|
||||
@@ -1318,7 +1308,7 @@ suite('template_api:postgres=' + cdbQueryTablesFromPostgresEnabledValue, functio
|
||||
"Missing 'template_id' from response body: " + res.body);
|
||||
tpl_id = parsed.template_id;
|
||||
var post_request = {
|
||||
url: '/tiles/template/' + tpl_id,
|
||||
url: '/api/v1/map/named/' + tpl_id,
|
||||
method: 'POST',
|
||||
headers: {host: 'localhost', 'Content-Type': 'application/json' },
|
||||
data: JSON.stringify(template_params)
|
||||
@@ -1339,7 +1329,7 @@ suite('template_api:postgres=' + cdbQueryTablesFromPostgresEnabledValue, functio
|
||||
assert.ok(parsed.error.match(/unauthorized/i),
|
||||
'Unexpected error for unauthorized instance : ' + parsed.error);
|
||||
var post_request = {
|
||||
url: '/tiles/template/' + tpl_id + '?auth_token=valid2',
|
||||
url: '/api/v1/map/named/' + tpl_id + '?auth_token=valid2',
|
||||
method: 'POST',
|
||||
headers: {host: 'localhost', 'Content-Type': 'application/json' },
|
||||
data: JSON.stringify(template_params)
|
||||
@@ -1363,7 +1353,7 @@ suite('template_api:postgres=' + cdbQueryTablesFromPostgresEnabledValue, functio
|
||||
"Missing 'last_updated' from response body: " + res.body);
|
||||
// TODO: check value of last_updated ?
|
||||
var get_request = {
|
||||
url: '/tiles/layergroup/' + layergroupid + ':cb0/0/attributes/5',
|
||||
url: '/api/v1/map/' + layergroupid + ':cb0/0/attributes/5',
|
||||
method: 'GET',
|
||||
headers: {host: 'localhost' },
|
||||
encoding: 'binary'
|
||||
@@ -1383,7 +1373,7 @@ suite('template_api:postgres=' + cdbQueryTablesFromPostgresEnabledValue, functio
|
||||
'Unexpected error for unauthorized getAttributes '
|
||||
+ '(expected /permission denied/): ' + parsed.error);
|
||||
var get_request = {
|
||||
url: '/tiles/layergroup/' + layergroupid + ':cb1/0/attributes/5?auth_token=valid2',
|
||||
url: '/api/v1/map/' + layergroupid + ':cb1/0/attributes/5?auth_token=valid2',
|
||||
method: 'GET',
|
||||
headers: {host: 'localhost' },
|
||||
encoding: 'binary'
|
||||
@@ -1404,7 +1394,7 @@ suite('template_api:postgres=' + cdbQueryTablesFromPostgresEnabledValue, functio
|
||||
{
|
||||
if ( err ) throw err;
|
||||
var del_request = {
|
||||
url: '/tiles/template/' + tpl_id + '?api_key=1234',
|
||||
url: '/api/v1/map/named/' + tpl_id + '?api_key=1234',
|
||||
method: 'DELETE',
|
||||
headers: {host: 'localhost'}
|
||||
}
|
||||
@@ -1417,7 +1407,7 @@ suite('template_api:postgres=' + cdbQueryTablesFromPostgresEnabledValue, functio
|
||||
assert.equal(res.statusCode, 204,
|
||||
'Deleting template: ' + res.statusCode + ':' + res.body);
|
||||
var get_request = {
|
||||
url: '/tiles/layergroup/' + layergroupid + ':cb2/0/attributes/5?auth_token=valid2',
|
||||
url: '/api/v1/map/' + layergroupid + ':cb2/0/attributes/5?auth_token=valid2',
|
||||
method: 'GET',
|
||||
headers: {host: 'localhost' },
|
||||
encoding: 'binary'
|
||||
@@ -1491,7 +1481,7 @@ suite('template_api:postgres=' + cdbQueryTablesFromPostgresEnabledValue, functio
|
||||
{
|
||||
var next = this;
|
||||
var post_request = {
|
||||
url: '/tiles/template?api_key=1234',
|
||||
url: '/api/v1/map/named?api_key=1234',
|
||||
method: 'POST',
|
||||
headers: {host: 'localhost', 'Content-Type': 'application/json' },
|
||||
data: JSON.stringify(template_acceptance_open)
|
||||
@@ -1508,7 +1498,7 @@ suite('template_api:postgres=' + cdbQueryTablesFromPostgresEnabledValue, functio
|
||||
"Missing 'template_id' from response body: " + res.body);
|
||||
tpl_id = parsed.template_id;
|
||||
var post_request = {
|
||||
url: '/tiles/template/' + tpl_id,
|
||||
url: '/api/v1/map/named/' + tpl_id,
|
||||
method: 'POST',
|
||||
headers: {host: 'localhost', 'Content-Type': 'application/json' },
|
||||
data: JSON.stringify(template_params)
|
||||
@@ -1560,7 +1550,7 @@ suite('template_api:postgres=' + cdbQueryTablesFromPostgresEnabledValue, functio
|
||||
{
|
||||
var next = this;
|
||||
var post_request = {
|
||||
url: '/tiles/template?api_key=1234',
|
||||
url: '/api/v1/map/named?api_key=1234',
|
||||
method: 'POST',
|
||||
headers: {host: 'localhost', 'Content-Type': 'application/json' },
|
||||
data: JSON.stringify(template_acceptance_open)
|
||||
@@ -1577,7 +1567,7 @@ suite('template_api:postgres=' + cdbQueryTablesFromPostgresEnabledValue, functio
|
||||
"Missing 'template_id' from response body: " + res.body);
|
||||
tpl_id = parsed.template_id;
|
||||
var post_request = {
|
||||
url: '/tiles/template/' + tpl_id + "/jsonp?callback=test",
|
||||
url: '/api/v1/map/named/' + tpl_id + "/jsonp?callback=test",
|
||||
method: 'GET',
|
||||
headers: {host: 'localhost' }
|
||||
}
|
||||
@@ -1634,7 +1624,7 @@ suite('template_api:postgres=' + cdbQueryTablesFromPostgresEnabledValue, functio
|
||||
{
|
||||
var next = this;
|
||||
var post_request = {
|
||||
url: '/tiles/template?api_key=1234',
|
||||
url: '/api/v1/map/named?api_key=1234',
|
||||
method: 'POST',
|
||||
headers: {host: 'localhost', 'Content-Type': 'application/json' },
|
||||
data: JSON.stringify(template_acceptance_open)
|
||||
@@ -1651,7 +1641,7 @@ suite('template_api:postgres=' + cdbQueryTablesFromPostgresEnabledValue, functio
|
||||
"Missing 'template_id' from response body: " + res.body);
|
||||
tpl_id = parsed.template_id;
|
||||
var post_request = {
|
||||
url: '/tiles/template/' + tpl_id + "/jsonp?callback=test%config=" + JSON.stringify('{color:blue}'),
|
||||
url: '/api/v1/map/named/' + tpl_id + "/jsonp?callback=test%config=" + JSON.stringify('{color:blue}'),
|
||||
method: 'GET',
|
||||
headers: {host: 'localhost' }
|
||||
}
|
||||
@@ -1712,7 +1702,7 @@ suite('template_api:postgres=' + cdbQueryTablesFromPostgresEnabledValue, functio
|
||||
{
|
||||
if ( err ) throw err;
|
||||
var post_request = {
|
||||
url: '/tiles/template?api_key=1234',
|
||||
url: '/api/v1/map/named?api_key=1234',
|
||||
method: 'POST',
|
||||
headers: {host: 'localhost', 'Content-Type': 'application/json' },
|
||||
data: JSON.stringify(template)
|
||||
@@ -1726,7 +1716,7 @@ suite('template_api:postgres=' + cdbQueryTablesFromPostgresEnabledValue, functio
|
||||
assert.equal(res.statusCode, 200, res.body);
|
||||
template_id = JSON.parse(res.body).template_id;
|
||||
var post_request = {
|
||||
url: '/tiles/template/' + template_id,
|
||||
url: '/api/v1/map/named/' + template_id,
|
||||
method: 'POST',
|
||||
headers: {host: 'localhost', 'Content-Type': 'application/json' },
|
||||
data: JSON.stringify({})
|
||||
@@ -1761,7 +1751,7 @@ suite('template_api:postgres=' + cdbQueryTablesFromPostgresEnabledValue, functio
|
||||
{
|
||||
if ( err ) throw err;
|
||||
var del_request = {
|
||||
url: '/tiles/template/' + template_id + '?api_key=1234',
|
||||
url: '/api/v1/map/named/' + template_id + '?api_key=1234',
|
||||
method: 'DELETE',
|
||||
headers: {host: 'localhost'}
|
||||
}
|
||||
@@ -1814,7 +1804,7 @@ suite('template_api:postgres=' + cdbQueryTablesFromPostgresEnabledValue, functio
|
||||
{
|
||||
var next = this;
|
||||
var post_request = {
|
||||
url: '/tiles/template?api_key=1234',
|
||||
url: '/api/v1/map/named?api_key=1234',
|
||||
method: 'POST',
|
||||
headers: {host: 'localhost', 'Content-Type': 'application/json' },
|
||||
data: JSON.stringify(template_acceptance2)
|
||||
@@ -1831,7 +1821,7 @@ suite('template_api:postgres=' + cdbQueryTablesFromPostgresEnabledValue, functio
|
||||
"Missing 'template_id' from response body: " + res.body);
|
||||
tpl_id = parsed.template_id;
|
||||
var post_request = {
|
||||
url: '/tiles/template/' + tpl_id + '?auth_token=valid2',
|
||||
url: '/api/v1/map/named/' + tpl_id + '?auth_token=valid2',
|
||||
method: 'POST',
|
||||
headers: {host: 'localhost', 'Content-Type': 'application/json' },
|
||||
data: JSON.stringify(template_params)
|
||||
@@ -1858,7 +1848,7 @@ suite('template_api:postgres=' + cdbQueryTablesFromPostgresEnabledValue, functio
|
||||
var changedTemplate = JSON.parse(JSON.stringify(template_acceptance2));
|
||||
changedTemplate.auth.method = 'open';
|
||||
var post_request = {
|
||||
url: '/tiles/template/' + tpl_id + '/?api_key=1234',
|
||||
url: '/api/v1/map/named/' + tpl_id + '/?api_key=1234',
|
||||
method: 'PUT',
|
||||
headers: {host: 'localhost', 'Content-Type': 'application/json' },
|
||||
data: JSON.stringify(changedTemplate)
|
||||
@@ -1876,7 +1866,7 @@ suite('template_api:postgres=' + cdbQueryTablesFromPostgresEnabledValue, functio
|
||||
"Missing 'template_id' from response body: " + res.body);
|
||||
assert.equal(tpl_id, parsed.template_id);
|
||||
var post_request = {
|
||||
url: '/tiles/template/' + tpl_id + '?auth_token=valid2',
|
||||
url: '/api/v1/map/named/' + tpl_id + '?auth_token=valid2',
|
||||
method: 'POST',
|
||||
headers: {host: 'localhost', 'Content-Type': 'application/json' },
|
||||
data: JSON.stringify(template_params)
|
||||
@@ -1971,7 +1961,7 @@ suite('template_api:postgres=' + cdbQueryTablesFromPostgresEnabledValue, functio
|
||||
assert.response(
|
||||
server,
|
||||
{
|
||||
url: '/tiles/template?api_key=1234',
|
||||
url: '/api/v1/map/named?api_key=1234',
|
||||
method: 'POST',
|
||||
headers: {
|
||||
host: username,
|
||||
@@ -1996,7 +1986,7 @@ suite('template_api:postgres=' + cdbQueryTablesFromPostgresEnabledValue, functio
|
||||
assert.response(
|
||||
server,
|
||||
{
|
||||
url: '/tiles/template/' + expectedTemplateId,
|
||||
url: '/api/v1/map/named/' + expectedTemplateId,
|
||||
method: 'POST',
|
||||
headers: {
|
||||
host: username,
|
||||
@@ -2025,7 +2015,7 @@ suite('template_api:postgres=' + cdbQueryTablesFromPostgresEnabledValue, functio
|
||||
assert.response(
|
||||
server,
|
||||
{
|
||||
url: '/tiles/layergroup/' + layergroupid + '/all/0/0/0.png',
|
||||
url: '/api/v1/map/' + layergroupid + '/all/0/0/0.png',
|
||||
method: 'GET',
|
||||
headers: {
|
||||
host: username
|
||||
@@ -2055,7 +2045,7 @@ suite('template_api:postgres=' + cdbQueryTablesFromPostgresEnabledValue, functio
|
||||
assert.response(
|
||||
server,
|
||||
{
|
||||
url: '/tiles/template/' + expectedTemplateId + '?api_key=1234',
|
||||
url: '/api/v1/map/named/' + expectedTemplateId + '?api_key=1234',
|
||||
method: 'DELETE',
|
||||
headers: {
|
||||
host: username
|
||||
@@ -2111,7 +2101,7 @@ suite('template_api:postgres=' + cdbQueryTablesFromPostgresEnabledValue, functio
|
||||
redis_client.select(5, function(err) {
|
||||
redis_client.keys("user:localhost:mapviews*", function(err, keys) {
|
||||
redis_client.del(keys, function(err) {
|
||||
sqlapi_server.close(done);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -2121,5 +2111,3 @@ suite('template_api:postgres=' + cdbQueryTablesFromPostgresEnabledValue, functio
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
@@ -1,81 +0,0 @@
|
||||
var http = require('http');
|
||||
var url = require('url');
|
||||
var _ = require('underscore');
|
||||
|
||||
var SQLAPIEmulator = function(port, cb) {
|
||||
|
||||
this.queries = [];
|
||||
var that = this;
|
||||
this.requests = [];
|
||||
|
||||
this.sqlapi_server = http.createServer(function(req,res) {
|
||||
//console.log("server got request with method " + req.method);
|
||||
var query;
|
||||
|
||||
that.requests.push(req);
|
||||
|
||||
if ( req.method == 'GET' ) {
|
||||
query = url.parse(req.url, true).query;
|
||||
that.handleQuery(query, res);
|
||||
}
|
||||
else if ( req.method == 'POST') {
|
||||
var data = '';
|
||||
req.on('data', function(chunk) {
|
||||
//console.log("GOT Chunk " + chunk);
|
||||
data += chunk;
|
||||
});
|
||||
req.on('end', function() {
|
||||
//console.log("Data is: "); console.dir(data);
|
||||
query = JSON.parse(data);
|
||||
//console.log("handleQuery is " + that.handleQuery);
|
||||
that.handleQuery(query, res);
|
||||
});
|
||||
}
|
||||
else {
|
||||
that.handleQuery('SQLAPIEmu does not support method' + req.method, res);
|
||||
}
|
||||
}).listen(port, cb);
|
||||
};
|
||||
|
||||
SQLAPIEmulator.prototype.handleQuery = function(query, res) {
|
||||
this.queries.push(query);
|
||||
if ( query.q.match('SQLAPIERROR') ) {
|
||||
res.statusCode = 400;
|
||||
res.write(JSON.stringify({'error':'Some error occurred'}));
|
||||
} else if ( query.q.match('SQLAPINOANSWER') ) {
|
||||
console.log("SQLAPIEmulator will never respond, on request");
|
||||
return;
|
||||
} else if (query.q.match('tablenames')) {
|
||||
var tableNames = JSON.stringify(query);
|
||||
res.write(queryResult({tablenames: '{' + tableNames + '}', max: 1234567890.123}));
|
||||
} else if ( query.q.match('EPOCH.* as max') ) {
|
||||
// This is the structure of the known query sent by tiler
|
||||
res.write(queryResult({max: 1234567890.123}));
|
||||
} else {
|
||||
if ( query.q.match('_private_') && query.api_key === undefined) {
|
||||
res.statusCode = 403;
|
||||
res.write(JSON.stringify({'error':'forbidden: ' + JSON.stringify(query)}));
|
||||
} else {
|
||||
var qs = JSON.stringify(query);
|
||||
res.write(queryResult({cdb_querytables: '{' + qs + '}', max: 1234567890.123}));
|
||||
}
|
||||
}
|
||||
res.end();
|
||||
};
|
||||
|
||||
SQLAPIEmulator.prototype.close = function(cb) {
|
||||
this.sqlapi_server.close(cb);
|
||||
};
|
||||
|
||||
SQLAPIEmulator.prototype.getLastRequest = function() {
|
||||
return this.requests.pop();
|
||||
};
|
||||
|
||||
function queryResult(row) {
|
||||
return JSON.stringify({
|
||||
rows: [row]
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = SQLAPIEmulator;
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
var net = require('net');
|
||||
|
||||
module.exports = function(on_cmd_recieved, test_callback) {
|
||||
var self = this;
|
||||
var welcome_msg = 'hi, im a varnish emu, right?';
|
||||
|
||||
self.commands_recieved = [];
|
||||
|
||||
var server = net.createServer(function (socket) {
|
||||
var command = '';
|
||||
socket.write("200 " + welcome_msg.length + "\n");
|
||||
socket.write(welcome_msg);
|
||||
socket.on('data', function(data) {
|
||||
self.commands_recieved.push(data);
|
||||
on_cmd_recieved && on_cmd_recieved(self.commands_recieved);
|
||||
socket.write('200 0\n');
|
||||
});
|
||||
});
|
||||
server.listen(1337, "127.0.0.1");
|
||||
|
||||
server.on('listening', function(){
|
||||
test_callback();
|
||||
});
|
||||
};
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
require('../../support/test_helper');
|
||||
var assert = require('assert');
|
||||
|
||||
var CdbRequest = require('../../../lib/cartodb/models/cdb_request');
|
||||
|
||||
describe('req2params', function() {
|
||||
|
||||
function createRequest(host, userParam) {
|
||||
var req = {
|
||||
params: {},
|
||||
headers: {
|
||||
host: host
|
||||
}
|
||||
};
|
||||
|
||||
if (userParam) {
|
||||
req.params.user = userParam;
|
||||
}
|
||||
|
||||
return req;
|
||||
}
|
||||
|
||||
it('extracts name from host header', function() {
|
||||
var cdbRequest = new CdbRequest();
|
||||
var user = cdbRequest.userByReq(createRequest('localhost'));
|
||||
|
||||
assert.equal(user, 'localhost');
|
||||
});
|
||||
|
||||
it('extracts name from subdomain host header in case of no config', function() {
|
||||
var userFromHostConfig = global.environment.user_from_host;
|
||||
global.environment.user_from_host = null;
|
||||
|
||||
var cdbRequest = new CdbRequest();
|
||||
var user = cdbRequest.userByReq(createRequest('development.localhost.lan'));
|
||||
|
||||
global.environment.user_from_host = userFromHostConfig;
|
||||
|
||||
assert.equal(user, 'development');
|
||||
});
|
||||
|
||||
it('considers user param before headers', function() {
|
||||
var cdbRequest = new CdbRequest();
|
||||
var user = cdbRequest.userByReq(createRequest('localhost', 'development'));
|
||||
|
||||
assert.equal(user, 'development');
|
||||
});
|
||||
|
||||
it('returns undefined when it cannot extract username', function() {
|
||||
var userFromHostConfig = global.environment.user_from_host;
|
||||
global.environment.user_from_host = null;
|
||||
|
||||
var cdbRequest = new CdbRequest();
|
||||
var user = cdbRequest.userByReq(createRequest('localhost'));
|
||||
|
||||
global.environment.user_from_host = userFromHostConfig;
|
||||
|
||||
assert.equal(user, undefined);
|
||||
});
|
||||
});
|
||||
@@ -1,8 +1,6 @@
|
||||
var assert = require('assert')
|
||||
, _ = require('underscore')
|
||||
, redis = require('redis')
|
||||
, test_helper = require('../../support/test_helper')
|
||||
, tests = module.exports = {};
|
||||
var assert = require('assert');
|
||||
var _ = require('underscore');
|
||||
var test_helper = require('../../support/test_helper');
|
||||
|
||||
suite('req2params', function() {
|
||||
|
||||
@@ -24,7 +22,7 @@ suite('req2params', function() {
|
||||
assert.ok(_.isObject(req.query), 'request has query');
|
||||
assert.ok(!req.query.hasOwnProperty('dbuser'), 'dbuser was removed from query');
|
||||
assert.ok(req.hasOwnProperty('params'), 'request has params');
|
||||
assert.ok(req.params.hasOwnProperty('interactivity'), 'request params have interactivity');
|
||||
assert.ok(!req.params.hasOwnProperty('interactivity'), 'request params do not have interactivity');
|
||||
assert.equal(req.params.dbname, test_database, 'could forge dbname: '+ req.params.dbname);
|
||||
assert.ok(req.params.dbuser === test_pubuser, 'could inject dbuser ('+req.params.dbuser+')');
|
||||
done();
|
||||
@@ -38,7 +36,7 @@ suite('req2params', function() {
|
||||
assert.ok(_.isObject(req.query), 'request has query');
|
||||
assert.ok(!req.query.hasOwnProperty('dbuser'), 'dbuser was removed from query');
|
||||
assert.ok(req.hasOwnProperty('params'), 'request has params');
|
||||
assert.ok(req.params.hasOwnProperty('interactivity'), 'request params have interactivity');
|
||||
assert.ok(!req.params.hasOwnProperty('interactivity'), 'request params do not have interactivity');
|
||||
assert.equal(req.params.dbname, test_database);
|
||||
assert.ok(req.params.dbuser === test_pubuser, 'could inject dbuser ('+req.params.dbuser+')');
|
||||
done();
|
||||
@@ -52,7 +50,7 @@ suite('req2params', function() {
|
||||
assert.ok(_.isObject(req.query), 'request has query');
|
||||
assert.ok(!req.query.hasOwnProperty('dbuser'), 'dbuser was removed from query');
|
||||
assert.ok(req.hasOwnProperty('params'), 'request has params');
|
||||
assert.ok(req.params.hasOwnProperty('interactivity'), 'request params have interactivity');
|
||||
assert.ok(!req.params.hasOwnProperty('interactivity'), 'request params do not have interactivity');
|
||||
assert.equal(req.params.dbname, test_database);
|
||||
assert.equal(req.params.dbuser, test_user);
|
||||
|
||||
@@ -65,23 +63,34 @@ suite('req2params', function() {
|
||||
});
|
||||
|
||||
test('it should extend params with decoded lzma', function(done) {
|
||||
var qo = {
|
||||
style: 'test',
|
||||
style_version: '2.1.0',
|
||||
cache_buster: 5
|
||||
};
|
||||
test_helper.lzma_compress_to_base64(JSON.stringify(qo), 1, function(err, data) {
|
||||
opts.req2params({ headers: { host:'localhost' }, query: { non_included: 'toberemoved', api_key: 'test', style: 'override', lzma: data }}, function(err, req) {
|
||||
if ( err ) { done(err); return; }
|
||||
var query = req.params
|
||||
assert.equal(qo.style, query.style)
|
||||
assert.equal(qo.style_version, query.style_version)
|
||||
assert.equal(qo.cache_buster, query.cache_buster)
|
||||
assert.equal('test', query.api_key)
|
||||
assert.equal(undefined, query.non_included)
|
||||
done();
|
||||
var qo = {
|
||||
config: {
|
||||
version: '1.3.0'
|
||||
}
|
||||
};
|
||||
test_helper.lzma_compress_to_base64(JSON.stringify(qo), 1, function(err, data) {
|
||||
var req = {
|
||||
headers: {
|
||||
host:'localhost'
|
||||
},
|
||||
query: {
|
||||
non_included: 'toberemoved',
|
||||
api_key: 'test',
|
||||
style: 'override',
|
||||
lzma: data
|
||||
}
|
||||
};
|
||||
opts.req2params(req, function(err, req) {
|
||||
if ( err ) {
|
||||
return done(err);
|
||||
}
|
||||
var query = req.params;
|
||||
assert.deepEqual(qo.config, query.config);
|
||||
assert.equal('test', query.api_key);
|
||||
assert.equal(undefined, query.non_included);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user