Merge branch 'master' into 257-remove-old-api

Conflicts:
	lib/cartodb/cartodb_windshaft.js
	lib/cartodb/server_options.js
	package.json
This commit is contained in:
Raul Ochoa 2015-03-23 12:24:10 +01:00
commit 5f6185dd51
26 changed files with 602 additions and 355 deletions

1
.gitignore vendored
View File

@ -7,3 +7,4 @@ logs/
pids/
redis.pid
test.log
npm-debug.log

92
.jshintrc Normal file
View File

@ -0,0 +1,92 @@
{
// // JSHint Default Configuration File (as on JSHint website)
// // See http://jshint.com/docs/ for more details
//
// "maxerr" : 50, // {int} Maximum error before stopping
//
// // Enforcing
// "bitwise" : true, // true: Prohibit bitwise operators (&, |, ^, etc.)
// "camelcase" : false, // true: Identifiers must be in camelCase
// "curly" : true, // true: Require {} for every new block or scope
// "eqeqeq" : true, // true: Require triple equals (===) for comparison
"forin" : true, // true: Require filtering for..in loops with obj.hasOwnProperty()
"freeze" : true, // true: prohibits overwriting prototypes of native objects such as Array, Date etc.
"immed" : true, // true: Require immediate invocations to be wrapped in parens e.g. `(function () { } ());`
// "indent" : 4, // {int} Number of spaces to use for indentation
// "latedef" : false, // true: Require variables/functions to be defined before being used
"newcap" : true, // true: Require capitalization of all constructor functions e.g. `new F()`
"noarg" : true, // true: Prohibit use of `arguments.caller` and `arguments.callee`
// "noempty" : true, // true: Prohibit use of empty blocks
"nonbsp" : true, // true: Prohibit "non-breaking whitespace" characters.
"nonew" : true, // true: Prohibit use of constructors for side-effects (without assignment)
// "plusplus" : false, // true: Prohibit use of `++` & `--`
// "quotmark" : false, // Quotation mark consistency:
// // false : do nothing (default)
// // true : ensure whatever is used is consistent
// // "single" : require single quotes
// // "double" : require double quotes
"undef" : true, // true: Require all non-global variables to be declared (prevents global leaks)
"unused" : true, // true: Require all defined variables be used
// "strict" : true, // true: Requires all functions run in ES5 Strict Mode
// "maxparams" : false, // {int} Max number of formal params allowed per function
// "maxdepth" : false, // {int} Max depth of nested blocks (within functions)
// "maxstatements" : false, // {int} Max number statements per function
"maxcomplexity" : 8, // {int} Max cyclomatic complexity per function
"maxlen" : 120, // {int} Max number of characters per line
//
// // Relaxing
// "asi" : false, // true: Tolerate Automatic Semicolon Insertion (no semicolons)
// "boss" : false, // true: Tolerate assignments where comparisons would be expected
"debug" : false, // true: Allow debugger statements e.g. browser breakpoints.
// "eqnull" : false, // true: Tolerate use of `== null`
// "es5" : false, // true: Allow ES5 syntax (ex: getters and setters)
// "esnext" : false, // true: Allow ES.next (ES6) syntax (ex: `const`)
// "moz" : false, // true: Allow Mozilla specific syntax (extends and overrides esnext features)
// // (ex: `for each`, multiple try/catch, function expression…)
// "evil" : false, // true: Tolerate use of `eval` and `new Function()`
// "expr" : false, // true: Tolerate `ExpressionStatement` as Programs
// "funcscope" : false, // true: Tolerate defining variables inside control statements
// "globalstrict" : false, // true: Allow global "use strict" (also enables 'strict')
// "iterator" : false, // true: Tolerate using the `__iterator__` property
// "lastsemic" : false, // true: Tolerate omitting a semicolon for the last statement of a 1-line block
// "laxbreak" : false, // true: Tolerate possibly unsafe line breakings
// "laxcomma" : false, // true: Tolerate comma-first style coding
// "loopfunc" : false, // true: Tolerate functions being defined in loops
// "multistr" : false, // true: Tolerate multi-line strings
// "noyield" : false, // true: Tolerate generator functions with no yield statement in them.
// "notypeof" : false, // true: Tolerate invalid typeof operator values
// "proto" : false, // true: Tolerate using the `__proto__` property
// "scripturl" : false, // true: Tolerate script-targeted URLs
// "shadow" : false, // true: Allows re-define variables later in code e.g. `var x=1; x=2;`
// "sub" : false, // true: Tolerate using `[]` notation when it can still be expressed in dot notation
// "supernew" : false, // true: Tolerate `new function () { ... };` and `new Object;`
// "validthis" : false, // true: Tolerate using this in a non-constructor function
//
// // Environments
// "browser" : true, // Web Browser (window, document, etc)
// "browserify" : false, // Browserify (node.js code in the browser)
// "couch" : false, // CouchDB
// "devel" : true, // Development/debugging (alert, confirm, etc)
// "dojo" : false, // Dojo Toolkit
// "jasmine" : false, // Jasmine
// "jquery" : false, // jQuery
// "mocha" : true, // Mocha
// "mootools" : false, // MooTools
"node" : true, // Node.js
// "nonstandard" : false, // Widely adopted globals (escape, unescape, etc)
// "prototypejs" : false, // Prototype and Scriptaculous
// "qunit" : false, // QUnit
// "rhino" : false, // Rhino
// "shelljs" : false, // ShellJS
// "worker" : false, // Web Workers
// "wsh" : false, // Windows Scripting Host
// "yui" : false, // Yahoo User Interface
// Custom Globals
"globals" : { // additional predefined global variables
"suite": true,
"suiteSetup": true,
"test": true,
"suiteTeardown": true
}
}

View File

@ -1,7 +1,10 @@
srcdir=$(shell pwd)
SHELL=/bin/bash
pre-install:
@$(SHELL) ./scripts/check-node-canvas.sh
all:
npm install
@$(SHELL) ./scripts/install.sh
clean:
rm -rf node_modules/*
@ -15,24 +18,21 @@ config.status--test:
config/environments/test.js: config.status--test
./config.status--test
check-local: config/environments/test.js
./run_tests.sh ${RUNTESTFLAGS} \
test/unit/cartodb/*.js \
test/unit/cartodb/cache/model/*.js \
test/integration/*.js \
test/acceptance/*.js \
test/acceptance/cache/*.js
test: config/environments/test.js
@echo "***tests***"
@$(SHELL) ./run_tests.sh ${RUNTESTFLAGS} \
test/unit/cartodb/*.js \
test/unit/cartodb/cache/model/*.js \
test/integration/*.js \
test/acceptance/*.js \
test/acceptance/cache/*.js
check-submodules:
PATH="$$PATH:$(srcdir)/node_modules/.bin/"; \
for sub in windshaft grainstore node-varnish mapnik; do \
if test -e node_modules/$${sub}; then \
echo "Testing submodule $${sub}"; \
make -C node_modules/$${sub} check || exit 1; \
fi; \
done
jshint:
@echo "***jshint***"
@./node_modules/.bin/jshint lib/
check-full: check-local check-submodules
test-all: jshint test
check: check-local
check: test
.PHONY: pre-install test

16
NEWS.md
View File

@ -1,7 +1,21 @@
1.28.6 -- 2015-mm-dd
1.30.1 -- 2015-mm-dd
--------------------
1.30.0 -- 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
--------------------
Announcements:
- Upgrades windshaft to [0.39.0](https://github.com/CartoDB/Windshaft/releases/tag/0.39.0)
1.28.5 -- 2015-02-20
--------------------

View File

@ -3,36 +3,36 @@ Windshaft-CartoDB
[![Build Status](https://travis-ci.org/CartoDB/Windshaft-cartodb.svg?branch=master)](https://travis-ci.org/CartoDB/Windshaft-cartodb)
This is the CartoDB map tiler. It extends Windshaft with some extra
functionality and custom filters for authentication
This is the [CartoDB Maps API](http://docs.cartodb.com/cartodb-platform/maps-api.html) tiler. It extends
[Windshaft](https://github.com/CartoDB/Windshaft) with some extra functionality and custom filters for authentication.
* reads dbname from subdomain and cartodb redis for pretty tile urls
* configures windshaft to publish ``cartodb_id`` as the interactivity layer
* configures windshaft to publish `cartodb_id` as the interactivity layer
* gets the default geometry type from the cartodb redis store
* allows tiles to be styled individually
* provides a link to varnish high speed cache
* provides a ``infowindow`` endpoint for windshaft (DEPRECATED)
* provides a ``map_metadata`` endpoint for windshaft (DEPRECATED)
* provides signed template maps API
(http://github.com/CartoDB/Windshaft-cartodb/wiki/Template-maps)
* provides a [template maps API](https://github.com/CartoDB/Windshaft-cartodb/blob/master/docs/Template-maps.md)
Requirements
------------
- Core
- Node.js >=0.8
- npm >=1.2.1
- PostgreSQL >8.3.x, PostGIS >1.5.x
- Redis >2.4.0 (http://www.redis.io)
- Mapnik 2.0.1, 2.0.2, 2.1.0, 2.2.0, 2.3.0. See Installing Mapnik.
- Windshaft: check [Windshaft dependencies and installation notes](https://github.com/CartoDB/Windshaft#dependencies)
- libcairo2-dev, libpango1.0-dev, libjpeg8-dev and libgif-dev for server side canvas support
[core]
- node-0.8.x+
- PostgreSQL-8.3+
- PostGIS-1.5.0+
- Redis 2.4.0+ (http://www.redis.io)
- Mapnik 2.0 or 2.1
- For cache control (optional)
- CartoDB-SQL-API 1.0.0+
- CartoDB 0.9.5+ (for `CDB_QueryTables`)
- Varnish (http://www.varnish-cache.org)
[for cache control]
- CartoDB-SQL-API 1.0.0+
- CartoDB 0.9.5+ (for ``CDB_QueryTables``)
- Varnish (http://www.varnish-cache.org)
[for running the testsuite]
- Imagemagick (http://www.imagemagick.org)
- For running the testsuite
- ImageMagick (http://www.imagemagick.org)
Configure
---------
@ -74,59 +74,16 @@ there may be out-of-sync records in there.
Take a look: http://redis.io/commands
URLs
----
Documentation
-------------
**TILES**
[GET] subdomain.cartodb.com/tiles/:table_name/:z/:x/:y.[png|png8|grid.json]
Args:
* sql - plain SQL arguments
* interactivity - specify the column to use in UTFGrid
* cache_buster - Specify an identifier for the internal tile cache.
Requesting tiles with the same cache_buster value may
result in being served a cached version of the tile
(even when requesting a tile for the first time, as tiles
can be prepared in advance)
* cache_policy - Set to "persist" to have the server send an Cache-Control
header requesting caching devices to keep the response
cached as much as possible. This is best used with a
timestamp value in cache_buster for manual control of
updates.
* geom_type - override the cartodb default
* style - override the default map style with Carto
The [docs directory](https://github.com/CartoDB/Windshaft-cartodb/tree/master/docs) contains different documentation
resources, from higher level to more detailed ones:
The [Maps API](https://github.com/CartoDB/Windshaft-cartodb/blob/master/docs/Map-API.md) defined the endpoints and their
expected parameters and outputs.
**STYLE**
Examples
--------
[GET/POST] subdomain.cartodb.com/tiles/:table_name/style
Args:
* style - the style in CartoCSS you want to set
* style_version - the version of the style for POST
* style_convert - request conversion to target version (both POST and GET)
**INFOWINDOW**
[GET] subdomain.cartodb.com/tiles/:table_name/infowindow
Args:
* infowindow - returns contents of infowindow from CartoDB.
**MAP METADATA**
[GET] subdomain.cartodb.com/tiles/:table_name/map_metadata
Args:
* infowindow - returns contents of infowindow from CartoDB.
All GET requests are wrappable with JSONP using callback argument,
including the UTFGrid map tile call.
[CartoDB's Map Gallery](http://cartodb.com/gallery/) showcases several examples of visualisations built on top of this.

View File

@ -14,11 +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)'
,base_url_templated: '(?:/api/v1/map/named|/tiles/template|/u/:user/api/v1/map/named|/u/:user/tiles/template)'
// 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)'
,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'
@ -174,6 +174,12 @@ var config = {
x: 0,
y: 0
}
// Use this as a feature flags enabling/disabling mechanism
,enabledFeatures: {
// whether the affected tables for a given SQL must query directly postgresql or use the SQL API
cdbQueryTablesFromPostgres: true
}
};
module.exports = config;

View File

@ -14,11 +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)'
,base_url_templated: '(?:/api/v1/map/named|/tiles/template|/u/:user/api/v1/map/named|/u/:user/tiles/template)'
// 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)'
,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'
@ -183,6 +183,12 @@ var config = {
x: 0,
y: 0
}
// Use this as a feature flags enabling/disabling mechanism
,enabledFeatures: {
// whether the affected tables for a given SQL must query directly postgresql or use the SQL API
cdbQueryTablesFromPostgres: true
}
};
module.exports = config;

View File

@ -14,11 +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/maps/named|/tiles/template)'
,base_url_templated: '(?:/api/v1/map/named|/tiles/template|/u/:user/api/v1/map/named|/u/:user/tiles/template)'
// 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/maps|/tiles/layergroup)'
,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'
@ -183,6 +183,12 @@ var config = {
x: 0,
y: 0
}
// Use this as a feature flags enabling/disabling mechanism
,enabledFeatures: {
// whether the affected tables for a given SQL must query directly postgresql or use the SQL API
cdbQueryTablesFromPostgres: true
}
};
module.exports = config;

View File

@ -14,11 +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)'
,base_url_templated: '(?:/api/v1/map/named|/tiles/template|/u/:user/api/v1/map/named|/u/:user/tiles/template)'
// 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)'
,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'
@ -172,6 +172,12 @@ var config = {
x: 0,
y: 0
}
// Use this as a feature flags enabling/disabling mechanism
,enabledFeatures: {
// whether the affected tables for a given SQL must query directly postgresql or use the SQL API
cdbQueryTablesFromPostgres: true
}
};
module.exports = config;

View File

@ -34,10 +34,10 @@ $.ajax({
type: 'POST',
dataType: 'json',
contentType: 'application/json',
url: 'http://documentation.cartodb.com/api/v1/map',
url: 'https://documentation.cartodb.com/api/v1/map',
data: JSON.stringify(mapconfig),
success: function(data) {
var templateUrl = 'http://documentation.cartodb.com/api/v1/map/' + data.layergroupid + '/{z}/{x}/{y}.png'
var templateUrl = 'https://documentation.cartodb.com/api/v1/map/' + data.layergroupid + '/{z}/{x}/{y}.png'
console.log(templateUrl);
}
})
@ -79,7 +79,7 @@ To get the `URL` to fetch the tiles you need to instantiate the map, where `temp
<div class="code-title notitle code-request"></div>
```bash
curl -X POST 'http://{account}.cartodb.com/api/v1/map/named/:template_id' -H 'Content-Type: application/json'
curl -X POST 'https://{account}.cartodb.com/api/v1/map/named/:template_id' -H 'Content-Type: application/json'
```
The response will return JSON with properties for the `layergroupid` and the timestamp (`last_updated`) of the last data modification.
@ -96,7 +96,7 @@ Here is an example response:
You can use the `layergroupid` to instantiate a URL template for accessing tiles on the client. Here we use the `layergroupid` from the example response above in this URL template:
```bash
http://documentation.cartodb.com/api/v1/map/c01a54877c62831bb51720263f91fb33:0/{z}/{x}/{y}.png
https://documentation.cartodb.com/api/v1/map/c01a54877c62831bb51720263f91fb33:0/{z}/{x}/{y}.png
```
## General Concepts
@ -107,7 +107,7 @@ The following concepts are the same for every endpoint in the API except when it
By default, users do not have access to private tables in CartoDB. In order to instantiate a map from private table data an API Key is required. Additionally, to include some endpoints, an API Key must be included (e.g. creating a named map).
To execute an authorized request, api_key=YOURAPIKEY should be added to the request URL. The param can be also passed as POST param. We **strongly advise** using HTTPS when you are performing requests that include your `api_key`.
To execute an authorized request, `api_key=YOURAPIKEY` should be added to the request URL. The param can be also passed as POST param. Using HTTPS is mandatory when you are performing requests that include your `api_key`.
### Errors
@ -167,7 +167,7 @@ The response includes:
The ID for that map, used to compose the URL for the tiles. The final URL is:
```html
http://{account}.cartodb.com/api/v1/map/:layergroupid/{z}/{x}/{y}.png
https://{account}.cartodb.com/api/v1/map/:layergroupid/{z}/{x}/{y}.png
```
- **updated_at**
@ -183,7 +183,7 @@ The response includes:
<div class="code-title code-request with-result">REQUEST</div>
```bash
curl 'http://documentation.cartodb.com/api/v1/map' -H 'Content-Type: application/json' -d @mapconfig.json
curl 'https://documentation.cartodb.com/api/v1/map' -H 'Content-Type: application/json' -d @mapconfig.json
```
<div class="code-title">RESPONSE</div>
@ -201,19 +201,19 @@ curl 'http://documentation.cartodb.com/api/v1/map' -H 'Content-Type: application
The tiles can be accessed using:
```bash
http://documentation.cartodb.com/api/v1/map/c01a54877c62831bb51720263f91fb33:0/{z}/{x}/{y}.png
https://documentation.cartodb.com/api/v1/map/c01a54877c62831bb51720263f91fb33:0/{z}/{x}/{y}.png
```
For UTF grid tiles:
```bash
http://documentation.cartodb.com/api/v1/map/c01a54877c62831bb51720263f91fb33:0/:layer/{z}/{x}/{y}.grid.json
https://documentation.cartodb.com/api/v1/map/c01a54877c62831bb51720263f91fb33:0/:layer/{z}/{x}/{y}.grid.json
```
For attributes defined in `attributes` section:
```bash
http://documentation.cartodb.com/api/v1/map/c01a54877c62831bb51720263f91fb33:0/:layer/attributes/:feature_id
https://documentation.cartodb.com/api/v1/map/c01a54877c62831bb51720263f91fb33:0/:layer/attributes/:feature_id
```
Which returns JSON with the attributes defined, like:

128
docs/Routes.md Normal file
View File

@ -0,0 +1,128 @@
This document list all routes available in Windshaft-cartodb Maps API server.
## Routes list
1. `GET (?:/api/v1/map|/tiles/layergroup)/:token/:z/:x/:y@:scale_factor?x.:format {:token(f),:z(f),:x(f),:y(f),:scale_factor(t),:format(f)} (1)`
<br/>Notes: Mapnik retina tiles [0]
1. `GET (?:/api/v1/map|/tiles/layergroup)/:token/:z/:x/:y.:format {:token(f),:z(f),:x(f),:y(f),:format(f)} (1)`
<br/>Notes: Mapnik tiles [0]
1. `GET (?:/api/v1/map|/tiles/layergroup)/:token/:layer/:z/:x/:y.(:format) {:token(f),:layer(f),:z(f),:x(f),:y(f),:format(f)} (1)`
<br/>Notes: Per :layer rendering based on :format [0]
1. `GET (?:/api/v1/map|/tiles/layergroup) {} (1)`
<br/>Notes: Map instantiation [0]
1. `GET (?:/api/v1/map|/tiles/layergroup)/:token/:layer/attributes/:fid {:token(f),:layer(f),:fid(f)} (1)`
<br/>Notes: Endpoint for info windows data, alternative for sql api when tables are private [0]
1. `GET (?:/api/v1/map|/tiles/layergroup)/static/center/:token/:z/:lat/:lng/:width/:height.:format {:token(f),:z(f),:lat(f),:lng(f),:width(f),:height(f),:format(f)} (1)`
<br/>Notes: Static Maps API [0]
1. `GET (?:/api/v1/map|/tiles/layergroup)/static/bbox/:token/:west,:south,:east,:north/:width/:height.:format {:token(f),:west(f),:south(f),:east(f),:north(f),:width(f),:height(f),:format(f)} (1)`
<br/>Notes: Static Maps API [0]
1. `GET / {} (1)`
<br/>Notes: Welcome message
1. `GET /version {} (1)`
<br/>Notes: Return relevant module versions: mapnik, grainstore, etc
1. `GET /tiles/:table/:z/:x/:y.* {:table(f),:z(f),:x(f),:y(f)} (1)`
<br/>Notes: **[DEPRECATED]** Per :table tiles rendering
1. `GET /tiles/:table/style {:table(f)} (1)`
<br/>Notes: **[DEPRECATED]** Style for :table
1. `GET (?:/api/v1/map/named|/tiles/template)/:template_id/jsonp {:template_id(f)} (1)`
<br/>Notes: Named maps JSONP instantiation [1]
1. `GET (?:/api/v1/map/named|/tiles/template)/:template_id {:template_id(f)} (1)`
<br/>Notes: Named map retrieval (w/ API KEY) [1]
1. `GET (?:/api/v1/map/named|/tiles/template) {} (1)`
<br/>Notes: List named maps (w/ API KEY) [1]
1. `GET /tiles/:table/infowindow {:table(f)} (1)`
<br/>Notes: **[DEPRECATED]** retrieve info window template for :table
1. `GET /tiles/:table/map_metadata {:table(f)} (1)`
<br/>Notes: **[DEPRECATED]** retrieve map metadata for :table
1. `GET /health {} (1)`
<br/>Notes: Healt check
1. `OPTIONS (?:/api/v1/map|/tiles/layergroup) {} (1)`
<br/>Notes: CORS [0]
1. `OPTIONS /tiles/:table/:z/:x/:y.* {:table(f),:z(f),:x(f),:y(f)} (1)`
<br/>Notes: **[DEPRECATED]** CORS
1. `OPTIONS /tiles/:table/style {:table(f)} (1)`
<br/>Notes: **[DEPRECATED]** CORS
1. `OPTIONS (?:/api/v1/map/named|/tiles/template)/:template_id {:template_id(f)} (1)`
<br/>Notes: CORS [1]
1. `POST (?:/api/v1/map|/tiles/layergroup) {} (1)`
<br/>Notes: Map instantiation [0]
1. `POST /tiles/:table/style {:table(f)} (1)`
<br/>Notes: **[DEPRECATED]** Create style for :table
1. `POST (?:/api/v1/map/named|/tiles/template) {} (1)`
<br/>Notes: Create named map (w/ API KEY) [1]
1. `POST (?:/api/v1/map/named|/tiles/template)/:template_id {:template_id(f)} (1)`
<br/>Notes: Instantiate named map [1]
1. `DELETE /tiles/:table/style {:table(f)} (1)`
<br/>Notes: **[DEPRECATED]** Delete :table style
1. `DELETE (?:/api/v1/map/named|/tiles/template)/:template_id {:template_id(f)} (1)`
<br/>Notes: Delete named map (w/ API KEY) [1]
1. `DELETE /tiles/:table/flush_cache {:table(f)} (1)`
<br/>Notes: **[DEPRECATED]** Flush internal caches for :table
1. `PUT (?:/api/v1/map/named|/tiles/template)/:template_id {:template_id(f)} (1)`
<br/>Notes: Update a named map (w/ API KEY) [1]
## Optional deprecated routes
- [0] `/tiles/layergroup` is deprecated and `/api/v1/map` should be used but we keep it for now.
- [1] `/tiles/template` is deprecated and `/api/v1/map/named` should be used but we keep it for now.
## How to generate the list of routes
Something like the following patch should do the trick
```javascript
diff --git a/lib/cartodb/cartodb_windshaft.js b/lib/cartodb/cartodb_windshaft.js
index 477a4c2..f69eebb 100644
--- a/lib/cartodb/cartodb_windshaft.js
+++ b/lib/cartodb/cartodb_windshaft.js
@@ -242,6 +242,20 @@ var CartodbWindshaft = function(serverOptions) {
}
});
+ var format = require('util').format;
+ var routesNotes = Object.keys(ws.routes.routes)
+ .map(function(method) { return ws.routes.routes[method]; })
+ .reduce(function(previous, current) { current.map(function(r) { previous.push(r) }); return previous;}, [])
+ .map(function(route) {
+ return format("\n1. `%s %s {%s} (%d)`\n<br/>Notes: [DEPRECATED]? ",
+ route.method.toUpperCase(),
+ route.path,
+ route.keys.map(function(k) { return format(':%s(%s)', k.name, k.optional ? 't' : 'f'); } ).join(','),
+ route.callbacks.length
+ );
+ });
+ console.log(routesNotes.join('\n'));
+
return ws;
};
```

View File

@ -1,6 +1,6 @@
var sqlApi = require('../sql/sql_api');
var PSQL = require('cartodb-psql');
var Step = require('step');
var step = require('step');
function QueryTablesApi(pgConnection, metadataBackend) {
this.pgConnection = pgConnection;
@ -78,7 +78,7 @@ QueryTablesApi.prototype.runQuery = function(username, query, queryHandler, call
var params = {};
Step(
step(
function setAuth() {
self.pgConnection.setDBAuth(username, params, this);
},
@ -109,7 +109,7 @@ QueryTablesApi.prototype.runQuery = function(username, query, queryHandler, call
} else {
Step(
step(
function getApiKey() {
self.metadataBackend.getUserMapKey(username, this);
},
@ -138,7 +138,7 @@ function prepareSql(sql) {
function shouldQueryPostgresDirectly() {
return global.environment
&& global.environment.enabledFeatures
&& global.environment.enabledFeatures.cdbQueryTablesFromPostgres;
return global.environment &&
global.environment.enabledFeatures &&
global.environment.enabledFeatures.cdbQueryTablesFromPostgres;
}

View File

@ -1,4 +1,4 @@
var Step = require('step');
var step = require('step');
var _ = require('underscore');
function PgConnection(metadataBackend) {
@ -24,13 +24,13 @@ PgConnection.prototype.setDBAuth = function(username, params, callback) {
var user_params = {};
var auth_user = global.environment.postgres_auth_user;
var auth_pass = global.environment.postgres_auth_pass;
Step(
step(
function getId() {
self.metadataBackend.getUserId(username, this);
},
function(err, user_id) {
if (err) throw err;
user_params['user_id'] = user_id;
user_params.user_id = user_id;
var dbuser = _.template(auth_user, user_params);
_.extend(params, {dbuser:dbuser});
@ -42,7 +42,7 @@ PgConnection.prototype.setDBAuth = function(username, params, callback) {
},
function(err, user_password) {
if (err) throw err;
user_params['user_password'] = user_password;
user_params.user_password = user_password;
if ( auth_pass ) {
var dbpass = _.template(auth_pass, user_params);
_.extend(params, {dbpassword:dbpass});
@ -76,7 +76,7 @@ PgConnection.prototype.setDBConn = function(dbowner, params, callback) {
dbhost: global.environment.postgres.host,
dbport: global.environment.postgres.port
});
Step(
step(
function getConnectionParams() {
self.metadataBackend.getUserDBConnectionParams(dbowner, this);
},

View File

@ -1,6 +1,5 @@
var _ = require('underscore'),
Varnish = require('node-varnish'),
varnish_queue = null;
var Varnish = require('node-varnish');
var varnish_queue = null;
function init(host, port, secret) {
varnish_queue = new Varnish.VarnishQueue(host, port, secret);
@ -23,4 +22,4 @@ function invalidate_db(dbname, table) {
module.exports = {
init: init,
invalidate_db: invalidate_db
}
};

View File

@ -1,12 +1,11 @@
var _ = require('underscore');
var Step = require('step');
var step = require('step');
var Windshaft = require('windshaft');
var Cache = require('./cache_validator');
var os = require('os');
var HealthCheck = require('./monitoring/health_check');
if ( ! process.env['PGAPPNAME'] )
process.env['PGAPPNAME']='cartodb_tiler';
if ( ! process.env.PGAPPNAME )
process.env.PGAPPNAME='cartodb_tiler';
var CartodbWindshaft = function(serverOptions) {
// Perform keyword substitution in statsd
@ -18,8 +17,8 @@ var CartodbWindshaft = function(serverOptions) {
}
}
var redisPool = serverOptions.redis.pool
|| require('redis-mpool')(_.extend(global.environment.redis, {name: 'windshaft:cartodb'}));
var redisPool = serverOptions.redis.pool ||
require('redis-mpool')(_.extend(global.environment.redis, {name: 'windshaft:cartodb'}));
var cartoData = require('cartodb-redis')({pool: redisPool});
@ -34,18 +33,21 @@ var CartodbWindshaft = function(serverOptions) {
var SurrogateKeysCache = require('./cache/surrogate_keys_cache'),
NamedMapsCacheEntry = require('./cache/model/named_maps_entry'),
VarnishHttpCacheBackend = require('./cache/backend/varnish_http'),
varnishHttpCacheBackend = new VarnishHttpCacheBackend(serverOptions.varnish_host, serverOptions.varnish_http_port),
varnishHttpCacheBackend = new VarnishHttpCacheBackend(
serverOptions.varnish_host,
serverOptions.varnish_http_port
),
surrogateKeysCache = new SurrogateKeysCache(varnishHttpCacheBackend);
if (serverOptions.varnish_purge_enabled) {
function invalidateNamedMap(owner, templateName) {
surrogateKeysCache.invalidate(new NamedMapsCacheEntry(owner, templateName), function(err) {
if (err) {
console.warn('Cache: surrogate key invalidation failed');
}
});
}
function invalidateNamedMap (owner, templateName) {
surrogateKeysCache.invalidate(new NamedMapsCacheEntry(owner, templateName), function(err) {
if (err) {
console.warn('Cache: surrogate key invalidation failed');
}
});
}
if (serverOptions.varnish_purge_enabled) {
['update', 'delete'].forEach(function(eventType) {
templateMaps.on(eventType, invalidateNamedMap);
});
@ -85,7 +87,7 @@ var CartodbWindshaft = function(serverOptions) {
}
}
var req = res.req;
Step (
step (
function addCacheChannel() {
if ( ! req ) {
// having no associated request can happen when
@ -107,10 +109,11 @@ var CartodbWindshaft = function(serverOptions) {
//console.log("Skipping cache channel in route:\n" + req.route.path);
return false;
}
//console.log("Adding cache channel to route\n" + req.route.path + " not matching any in:\n" + mapCreateRoutes.join("\n"));
//console.log("Adding cache channel to route\n" + req.route.path + " not matching any in:\n" +
// mapCreateRoutes.join("\n"));
serverOptions.addCacheChannel(that, req, this);
},
function sendResponse(err, added) {
function sendResponse(err/*, added*/) {
if ( err ) console.log(err + err.stack);
ws_sendResponse.apply(that, thatArgs);
return null;

View File

@ -1,4 +1,4 @@
var Step = require('step');
var step = require('step');
var _ = require('underscore');
function TemplateMapsController(app, serverOptions, templateMaps, metadataBackend, templateBaseUrl, surrogateKeysCache,
@ -35,7 +35,7 @@ TemplateMapsController.prototype.create = function(req, res) {
var cdbuser = self.serverOptions.userByReq(req);
Step(
step(
function checkPerms(){
self.serverOptions.authorizedByAPIKey(req, this);
},
@ -83,7 +83,7 @@ TemplateMapsController.prototype.update = function(req, res) {
var cdbuser = this.serverOptions.userByReq(req);
var template;
var tpl_id;
Step(
step(
function checkPerms(){
self.serverOptions.authorizedByAPIKey(req, this);
},
@ -100,8 +100,7 @@ TemplateMapsController.prototype.update = function(req, res) {
tpl_id = req.params.template_id.split('@');
if ( tpl_id.length > 1 ) {
if ( tpl_id[0] != cdbuser ) {
err = new Error("Invalid template id '"
+ req.params.template_id + "' for user '" + cdbuser + "'");
err = new Error("Invalid template id '" + req.params.template_id + "' for user '" + cdbuser + "'");
err.http_status = 404;
throw err;
}
@ -142,9 +141,8 @@ TemplateMapsController.prototype.retrieve = function(req, res) {
this.app.doCORS(res);
var cdbuser = this.serverOptions.userByReq(req);
var template;
var tpl_id;
Step(
step(
function checkPerms(){
self.serverOptions.authorizedByAPIKey(req, this);
},
@ -158,10 +156,10 @@ TemplateMapsController.prototype.retrieve = function(req, res) {
tpl_id = req.params.template_id.split('@');
if ( tpl_id.length > 1 ) {
if ( tpl_id[0] != cdbuser ) {
var err = new Error("Cannot get template id '"
+ req.params.template_id + "' for user '" + cdbuser + "'");
err.http_status = 404;
throw err;
var templateNotFoundErr = new Error("Cannot get template id '" + req.params.template_id +
"' for user '" + cdbuser + "'");
templateNotFoundErr.http_status = 404;
throw templateNotFoundErr;
}
tpl_id = tpl_id[1];
}
@ -204,9 +202,8 @@ TemplateMapsController.prototype.destroy = function(req, res) {
this.app.doCORS(res);
var cdbuser = this.serverOptions.userByReq(req);
var template;
var tpl_id;
Step(
step(
function checkPerms(){
self.serverOptions.authorizedByAPIKey(req, this);
},
@ -220,16 +217,16 @@ TemplateMapsController.prototype.destroy = function(req, res) {
tpl_id = req.params.template_id.split('@');
if ( tpl_id.length > 1 ) {
if ( tpl_id[0] != cdbuser ) {
var err = new Error("Cannot find template id '"
+ req.params.template_id + "' for user '" + cdbuser + "'");
err.http_status = 404;
throw err;
var templateNotFoundErr = new Error("Cannot find template id '" + req.params.template_id +
"' for user '" + cdbuser + "'");
templateNotFoundErr.http_status = 404;
throw templateNotFoundErr;
}
tpl_id = tpl_id[1];
}
self.templateMaps.delTemplate(cdbuser, tpl_id, this);
},
function prepareResponse(err, tpl_val){
function prepareResponse(err/*, tpl_val*/){
if ( err ) throw err;
return { status: 'ok' };
},
@ -259,7 +256,7 @@ TemplateMapsController.prototype.list = function(req, res) {
var cdbuser = this.serverOptions.userByReq(req);
Step(
step(
function checkPerms(){
self.serverOptions.authorizedByAPIKey(req, this);
},
@ -299,7 +296,7 @@ TemplateMapsController.prototype.instantiate = function(req, res) {
if ( req.profiler && req.profiler.statsd_client) {
req.profiler.start('windshaft-cartodb.instance_template_post');
}
Step(
step(
function() {
if ( ! req.headers['content-type'] || req.headers['content-type'].split(';')[0] != 'application/json') {
throw new Error('template POST data must be of type application/json, it is instead ');
@ -311,7 +308,7 @@ TemplateMapsController.prototype.instantiate = function(req, res) {
);
};
TemplateMapsController.prototype.options = function(req, res) {
TemplateMapsController.prototype.options = function(req, res, next) {
this.app.doCORS(res, "Content-Type");
return next();
};
@ -326,7 +323,7 @@ TemplateMapsController.prototype.jsonp = function(req, res) {
if ( req.profiler && req.profiler.statsd_client) {
req.profiler.start('windshaft-cartodb.instance_template_get');
}
Step(
step(
function() {
if ( req.query.callback === undefined || req.query.callback.length === 0) {
throw new Error('callback parameter should be present and be a function name');
@ -361,9 +358,8 @@ TemplateMapsController.prototype.instantiateTemplate = function(req, res, templa
var tpl_id = req.params.template_id.split('@');
if ( tpl_id.length > 1 ) {
if ( tpl_id[0] && tpl_id[0] != cdbuser ) {
var err = new Error('Cannot instanciate map of user "'
+ tpl_id[0] + '" on database of user "'
+ cdbuser + '"');
var err = new Error('Cannot instanciate map of user "' + tpl_id[0] + '" on database of user "' + cdbuser +
'"');
err.http_status = 403;
callback(err);
return;
@ -371,7 +367,7 @@ TemplateMapsController.prototype.instantiateTemplate = function(req, res, templa
tpl_id = tpl_id[1];
}
var auth_token = req.query.auth_token;
Step(
step(
function getTemplate(){
self.templateMaps.getTemplate(cdbuser, tpl_id, this);
},
@ -464,7 +460,7 @@ TemplateMapsController.prototype.finish_instantiation = function(err, response,
TemplateMapsController.prototype.setDBParams = function(cdbuser, params, callback) {
var self = this;
Step(
step(
function setAuth() {
self.pgConnection.setDBAuth(cdbuser, params, this);
},

View File

@ -1,8 +1,7 @@
var _ = require('underscore'),
dot = require('dot'),
fs = require('fs'),
path = require('path'),
Step = require('step');
var dot = require('dot');
var fs = require('fs');
var path = require('path');
var step = require('step');
function HealthCheck(metadataBackend, tilelive) {
this.metadataBackend = metadataBackend;
@ -40,9 +39,9 @@ HealthCheck.prototype.check = function(config, callback) {
ok: false
}
};
mapnikXmlParams = config;
var mapnikXmlParams = config;
Step(
step(
function getDBParams() {
startTime = Date.now();
self.metadataBackend.getAllUserDBParams(config.username, this);

View File

@ -1,5 +1,5 @@
var _ = require('underscore');
var Step = require('step');
var step = require('step');
var QueryTablesApi = require('./api/query_tables_api');
var PgConnection = require('./backends/pg_connection');
var crypto = require('crypto');
@ -18,6 +18,7 @@ if ( _.isUndefined(global.environment.sqlapi.domain) ) {
// Whitelist query parameters and attach format
var REQUEST_QUERY_PARAMS_WHITELIST = [
'user',
'sql',
'geom_type',
'cache_buster',
@ -35,8 +36,8 @@ var REQUEST_QUERY_PARAMS_WHITELIST = [
];
module.exports = function(redisPool) {
redisPool = redisPool
|| require('redis-mpool')(_.extend(global.environment.redis, {name: 'windshaft:server_options'}));
redisPool = redisPool ||
require('redis-mpool')(_.extend(global.environment.redis, {name: 'windshaft:server_options'}));
var cartoData = require('cartodb-redis')({ pool: redisPool }),
lzmaWorker = new LZMA(),
@ -147,7 +148,7 @@ module.exports = function(redisPool) {
var that = this;
Step (
step (
function checkCached() {
if ( me.channelCache.hasOwnProperty(cacheKey) ) {
callback(null, me.channelCache[cacheKey]);
@ -167,7 +168,7 @@ module.exports = function(redisPool) {
}
var next = this;
var mapStore = app.mapStore;
Step(
step(
function loadFromStore() {
mapStore.load(req.params.token, this);
},
@ -196,7 +197,7 @@ module.exports = function(redisPool) {
// strip out windshaft/mapnik inserted sql if present
var sql = req.params.sql.match(/^\((.*)\)\sas\scdbq$/);
sql = (sql != null) ? sql[1] : req.params.sql;
sql = (sql !== null) ? sql[1] : req.params.sql;
return sql;
},
@ -281,14 +282,16 @@ module.exports = function(redisPool) {
};
me.beforeLayergroupCreate = function(req, requestMapConfig, callback) {
mapConfigNamedLayersAdapter.getLayers(this.userByReq(req), requestMapConfig.layers, pgConnection, function(err, layers, datasource) {
if (err) {
return callback(err);
}
mapConfigNamedLayersAdapter.getLayers(this.userByReq(req), requestMapConfig.layers, pgConnection,
function(err, layers, datasource) {
if (err) {
return callback(err);
}
requestMapConfig.layers = layers;
return callback(null, requestMapConfig, datasource)
});
requestMapConfig.layers = layers;
return callback(null, requestMapConfig, datasource);
}
);
};
me.afterLayergroupCreate = function(req, mapconfig, response, callback) {
@ -333,7 +336,7 @@ module.exports = function(redisPool) {
var dbName = req.params.dbname;
var cacheKey = dbName + ':' + token;
Step(
step(
function getAffectedTablesAndLastUpdatedTime() {
queryTablesApi.getAffectedTablesAndLastUpdatedTime(username, sql, this);
},
@ -375,16 +378,18 @@ module.exports = function(redisPool) {
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 + "'");
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);
if ( mat.length !== 2 ) {
console.error("ERROR: pattern '" + this.re_userFromHost + "' gave unexpected matches against '" + host + "': " +
mat);
return;
}
return mat[1];
@ -409,7 +414,8 @@ module.exports = function(redisPool) {
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);
//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');
@ -445,7 +451,7 @@ module.exports = function(redisPool) {
}
//console.log("given ApiKey: " + givenKey);
var user = me.userByReq(req);
Step(
step(
function (){
cartoData.getUserMapKey(user, this);
},
@ -469,7 +475,7 @@ module.exports = function(redisPool) {
var that = this;
var user = me.userByReq(req);
Step(
step(
function (){
that.authorizedByAPIKey(req, this);
},
@ -545,6 +551,7 @@ module.exports = function(redisPool) {
);
};
// jshint maxcomplexity:10
/**
* Whitelist input and get database name & default geometry type from
* subdomain/user metadata held in CartoDB Redis
@ -559,7 +566,12 @@ module.exports = function(redisPool) {
//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')).split('').map(function(c) { return c.charCodeAt(0) - 128 });
var lzma = new Buffer(req.query.lzma, 'base64')
.toString('binary')
.split('')
.map(function(c) {
return c.charCodeAt(0) - 128;
});
// Decompress
lzmaWorker.decompress(
@ -574,7 +586,7 @@ module.exports = function(redisPool) {
callback(new Error('Error parsing lzma as JSON: ' + err));
}
},
function(percent) { // progress
function(/*percent*/) { // progress
//console.log("LZMA decompression " + percent + "%");
}
);
@ -597,14 +609,15 @@ module.exports = function(redisPool) {
if ( tksplit.length > 1 ) {
req.params.signer = tksplit.shift();
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 + '"');
else if ( req.params.signer !== user ) {
var err = new Error('Cannot use map signature of user "' + req.params.signer + '" on database of user "' +
user + '"');
err.http_status = 403;
callback(err);
return;
}
if ( tksplit.length > 1 ) {
var template_hash = tksplit.shift(); // unused
/*var template_hash = */tksplit.shift(); // unused
}
req.params.token = tksplit.shift();
//console.log("Request for token " + req.params.token + " with signature from " + req.params.signer);
@ -617,11 +630,9 @@ module.exports = function(redisPool) {
// for cartodb, ensure interactivity is cartodb_id or user specified
req.params.interactivity = req.params.interactivity || 'cartodb_id';
var that = this;
if (req.profiler) req.profiler.done('req2params.setup');
Step(
step(
function getPrivacy(){
me.authorize(req, this);
},

View File

@ -16,7 +16,7 @@ module.exports.query = function (username, api_key, sql, callback) {
var qs = { q: sql };
// add api_key if given
if (_.isString(api_key) && api_key != '') { qs.api_key = api_key; }
if (_.isString(api_key) && api_key !== '') { qs.api_key = api_key; }
// call sql api
//
@ -36,11 +36,11 @@ module.exports.query = function (username, api_key, sql, callback) {
var reqSpec = {
url:sqlapi,
json:true,
headers:{host: sqlapihostname}
headers:{host: sqlapihostname},
// http://nodejs.org/api/http.html#http_agent_maxsockets
,pool:{maxSockets:maxSockets}
pool:{maxSockets:maxSockets},
// timeout in milliseconds
,timeout:maxSQLTime
timeout:maxSQLTime
};
if ( sql.length > maxGetLen ) {
reqSpec.method = 'POST';

View File

@ -1,7 +1,7 @@
var crypto = require('crypto'),
Step = require('step'),
_ = require('underscore'),
dot = require('dot');
var crypto = require('crypto');
var step = require('step');
var _ = require('underscore');
var dot = require('dot');
var EventEmitter = require('events').EventEmitter;
@ -56,7 +56,7 @@ var o = TemplateMaps.prototype;
//--------------- PRIVATE METHODS --------------------------------
o._userTemplateLimit = function() {
return this.opts['max_user_templates'] || 0;
return this.opts.max_user_templates || 0;
};
/**
@ -71,7 +71,7 @@ o._redisCmd = function(redisFunc, redisArgs, callback) {
var that = this;
var db = that.db_signatures;
Step(
step(
function getRedisClient() {
that.redis_pool.acquire(db, this);
},
@ -89,6 +89,7 @@ o._redisCmd = function(redisFunc, redisArgs, callback) {
};
var _reValidIdentifier = /^[a-zA-Z][0-9a-zA-Z_]*$/;
// jshint maxcomplexity:15
o._checkInvalidTemplate = function(template) {
if ( template.version != '0.0.1' ) {
return new Error("Unsupported template version " + template.version);
@ -136,7 +137,6 @@ o._checkInvalidTemplate = function(template) {
break;
default:
return new Error("Unsupported authentication method: " + auth.method);
break;
}
return false;
@ -205,7 +205,7 @@ o.addTemplate = function(owner, template, callback) {
var userTemplatesKey = this.key_usr_tpl({ owner:owner });
var limit = this._userTemplateLimit();
Step(
step(
function checkLimit() {
if ( ! limit ) {
return 0;
@ -253,7 +253,7 @@ o.addTemplate = function(owner, template, callback) {
//
o.delTemplate = function(owner, tpl_id, callback) {
var self = this;
Step(
step(
function deleteTemplate() {
self._redisCmd('HDEL', [ self.key_usr_tpl({ owner:owner }), tpl_id ], this);
},
@ -311,7 +311,7 @@ o.updTemplate = function(owner, tpl_id, template, callback) {
var userTemplatesKey = this.key_usr_tpl({ owner:owner });
Step(
step(
function getExistingTemplate() {
self._redisCmd('HGET', [ userTemplatesKey, tpl_id ], this);
},
@ -366,7 +366,7 @@ o.listTemplates = function(owner, callback) {
//
o.getTemplate = function(owner, tpl_id, callback) {
var self = this;
Step(
step(
function getTemplate() {
self._redisCmd('HGET', [ self.key_usr_tpl({owner:owner}), tpl_id ], this);
},
@ -424,14 +424,14 @@ var _reNumber = /^([-+]?[\d\.]?\d+([eE][+-]?\d+)?)$/,
_reCSSColorName = /^[a-zA-Z]+$/,
_reCSSColorVal = /^#[0-9a-fA-F]{3,6}$/;
_replaceVars = function(str, params) {
function _replaceVars (str, params) {
//return _.template(str, params); // lazy way, possibly dangerous
// Construct regular expressions for each param
Object.keys(params).forEach(function(k) {
str = str.replace(new RegExp("<%=\\s*" + k + "\\s*%>", "g"), params[k]);
});
return str;
};
}
o.instance = function(template, params) {
var all_params = {};
var phold = template.placeholders || {};
@ -450,16 +450,14 @@ o.instance = function(template, params) {
else if ( type === 'number' ) {
// check it's a number
if ( typeof(val) !== 'number' && ! val.match(_reNumber) ) {
throw new Error("Invalid number value for template parameter '"
+ k + "': " + val);
throw new Error("Invalid number value for template parameter '" + k + "': " + val);
}
}
else if ( type === 'css_color' ) {
// check it only contains letters or
// starts with # and only contains hexdigits
if ( ! val.match(_reCSSColorName) && ! val.match(_reCSSColorVal) ) {
throw new Error("Invalid css_color value for template parameter '"
+ k + "': " + val);
throw new Error("Invalid css_color value for template parameter '" + k + "': " + val);
}
}
else {

149
npm-shrinkwrap.json generated
View File

@ -1,11 +1,11 @@
{
"name": "windshaft-cartodb",
"version": "1.28.6",
"version": "1.30.1",
"dependencies": {
"cartodb-psql": {
"version": "0.4.0",
"from": "cartodb-psql@~0.4.0",
"resolved": "https://github.com/CartoDB/node-cartodb-psql/tarball/0.4.0",
"resolved": "https://registry.npmjs.org/cartodb-psql/-/cartodb-psql-0.4.0.tgz",
"dependencies": {
"pg": {
"version": "2.6.2-cdb1",
@ -87,7 +87,8 @@
},
"isarray": {
"version": "0.0.1",
"from": "isarray@0.0.1"
"from": "isarray@0.0.1",
"resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz"
},
"string_decoder": {
"version": "0.10.31",
@ -95,7 +96,7 @@
},
"inherits": {
"version": "2.0.1",
"from": "inherits@~2.0.1"
"from": "inherits@2"
}
}
}
@ -119,7 +120,7 @@
"redis-mpool": {
"version": "0.3.0",
"from": "redis-mpool@~0.3.0",
"resolved": "https://github.com/CartoDB/node-redis-mpool/tarball/0.3.0",
"resolved": "https://registry.npmjs.org/redis-mpool/-/redis-mpool-0.3.0.tgz",
"dependencies": {
"generic-pool": {
"version": "2.1.1",
@ -157,9 +158,9 @@
"resolved": "https://registry.npmjs.org/rollbar/-/rollbar-0.3.13.tgz",
"dependencies": {
"node-uuid": {
"version": "1.4.2",
"version": "1.4.3",
"from": "node-uuid@1.4.x",
"resolved": "https://registry.npmjs.org/node-uuid/-/node-uuid-1.4.2.tgz"
"resolved": "https://registry.npmjs.org/node-uuid/-/node-uuid-1.4.3.tgz"
},
"lru-cache": {
"version": "2.2.4",
@ -181,8 +182,8 @@
"resolved": "https://registry.npmjs.org/underscore/-/underscore-1.6.0.tgz"
},
"windshaft": {
"version": "0.37.5",
"from": "windshaft@~0.37.5",
"version": "0.40.0",
"from": "windshaft@~0.40.0",
"dependencies": {
"chronograph": {
"version": "0.1.0",
@ -193,6 +194,36 @@
"version": "0.23.0",
"from": "grainstore@~0.23.0",
"dependencies": {
"redis-mpool": {
"version": "0.1.0",
"from": "https://github.com/CartoDB/node-redis-mpool/tarball/0.1.0",
"resolved": "https://github.com/CartoDB/node-redis-mpool/tarball/0.1.0",
"dependencies": {
"generic-pool": {
"version": "2.1.1",
"from": "generic-pool@~2.1.1"
},
"redis": {
"version": "0.12.1",
"from": "redis@~0.12.1"
},
"hiredis": {
"version": "0.1.17",
"from": "hiredis@~0.1.17",
"dependencies": {
"bindings": {
"version": "1.2.1",
"from": "bindings@*"
},
"nan": {
"version": "1.1.2",
"from": "nan@~1.1.0",
"resolved": "https://registry.npmjs.org/nan/-/nan-1.1.2.tgz"
}
}
}
}
},
"carto": {
"version": "0.9.5-cdb2",
"from": "https://github.com/CartoDB/carto/tarball/0.9.5-cdb2",
@ -264,9 +295,9 @@
"from": "forever-agent@~0.5.0"
},
"node-uuid": {
"version": "1.4.2",
"version": "1.4.3",
"from": "node-uuid@~1.4.0",
"resolved": "https://registry.npmjs.org/node-uuid/-/node-uuid-1.4.2.tgz"
"resolved": "https://registry.npmjs.org/node-uuid/-/node-uuid-1.4.3.tgz"
},
"tough-cookie": {
"version": "0.12.1",
@ -1680,7 +1711,7 @@
}
},
"tilelive-mapnik": {
"version": "0.6.12",
"version": "0.6.15",
"from": "https://github.com/CartoDB/tilelive-mapnik/tarball/cdb",
"resolved": "https://github.com/CartoDB/tilelive-mapnik/tarball/cdb",
"dependencies": {
@ -2080,50 +2111,21 @@
}
},
"canvas": {
"version": "1.1.6",
"from": "canvas@1.1.6",
"resolved": "https://registry.npmjs.org/canvas/-/canvas-1.1.6.tgz",
"version": "1.2.1",
"from": "canvas@1.2.1",
"resolved": "https://registry.npmjs.org/canvas/-/canvas-1.2.1.tgz",
"dependencies": {
"nan": {
"version": "1.2.0",
"from": "nan@~1.2.0"
}
}
},
"redis-mpool": {
"version": "0.1.0",
"from": "redis-mpool@git://github.com/CartoDB/node-redis-mpool.git#0.1.0",
"resolved": "git://github.com/CartoDB/node-redis-mpool.git#47510b8d4525ee24aa2e5328976372274a1d144e",
"dependencies": {
"generic-pool": {
"version": "2.1.1",
"from": "generic-pool@~2.1.1"
},
"redis": {
"version": "0.12.1",
"from": "redis@~0.12.1"
},
"hiredis": {
"version": "0.1.17",
"from": "hiredis@~0.1.17",
"dependencies": {
"bindings": {
"version": "1.2.1",
"from": "bindings@*"
},
"nan": {
"version": "1.1.2",
"from": "nan@~1.1.0",
"resolved": "https://registry.npmjs.org/nan/-/nan-1.1.2.tgz"
}
}
"version": "1.5.3",
"from": "nan@~1.5.1",
"resolved": "https://registry.npmjs.org/nan/-/nan-1.5.3.tgz"
}
}
},
"carto": {
"version": "0.14.0",
"from": "https://github.com/CartoDB/carto/tarball/update_to_master",
"resolved": "https://github.com/CartoDB/carto/tarball/update_to_master",
"version": "0.15.1-cdb1",
"from": "https://github.com/CartoDB/carto/tarball/0.15.1-cdb1",
"resolved": "https://github.com/CartoDB/carto/tarball/0.15.1-cdb1",
"dependencies": {
"mapnik-reference": {
"version": "6.0.5",
@ -2149,44 +2151,12 @@
}
},
"step-profiler": {
"version": "0.1.0",
"from": "step-profiler@git://github.com/CartoDB/node-step-profiler.git#0.1.0",
"resolved": "git://github.com/CartoDB/node-step-profiler.git#9b97881e450445bd8a307a9cc372b5129cb4529a"
"version": "0.2.1",
"from": "step-profiler@~0.2.1"
},
"torque.js": {
"version": "2.7.1",
"from": "https://github.com/CartoDB/torque/tarball/2.8",
"resolved": "https://github.com/CartoDB/torque/tarball/2.8",
"dependencies": {
"carto": {
"version": "0.15.1",
"from": "https://github.com/CartoDB/carto/archive/master.tar.gz",
"resolved": "https://github.com/CartoDB/carto/archive/master.tar.gz",
"dependencies": {
"mapnik-reference": {
"version": "6.0.5",
"from": "mapnik-reference@~6.0.2",
"resolved": "https://registry.npmjs.org/mapnik-reference/-/mapnik-reference-6.0.5.tgz"
},
"optimist": {
"version": "0.6.1",
"from": "optimist@~0.6.0",
"resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz",
"dependencies": {
"wordwrap": {
"version": "0.0.2",
"from": "wordwrap@~0.0.2",
"resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz"
},
"minimist": {
"version": "0.0.10",
"from": "minimist@~0.0.1"
}
}
}
}
}
}
"version": "2.11.0",
"from": "torque.js@~2.11.0"
},
"request": {
"version": "2.48.0",
@ -2209,7 +2179,8 @@
},
"isarray": {
"version": "0.0.1",
"from": "isarray@0.0.1"
"from": "isarray@0.0.1",
"resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz"
},
"string_decoder": {
"version": "0.10.31",
@ -2258,9 +2229,9 @@
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-1.0.2.tgz"
},
"node-uuid": {
"version": "1.4.2",
"version": "1.4.3",
"from": "node-uuid@~1.4.0",
"resolved": "https://registry.npmjs.org/node-uuid/-/node-uuid-1.4.2.tgz"
"resolved": "https://registry.npmjs.org/node-uuid/-/node-uuid-1.4.3.tgz"
},
"qs": {
"version": "2.3.3",

View File

@ -1,7 +1,7 @@
{
"private": true,
"name": "windshaft-cartodb",
"version": "1.28.6",
"version": "1.30.1",
"description": "A map tile server for CartoDB",
"keywords": [
"cartodb"
@ -25,7 +25,7 @@
"node-varnish": "https://github.com/Vizzuality/node-varnish/tarball/0.3.0",
"underscore" : "~1.6.0",
"dot": "~1.0.2",
"windshaft": "https://github.com/CartoDB/Windshaft/tarball/259-remove-old-api",
"windshaft": "https://github.com/CartoDB/Windshaft/tarball/master",
"step": "~0.0.5",
"queue-async": "~1.0.7",
"request": "~2.9.203",
@ -38,12 +38,14 @@
},
"devDependencies": {
"mocha": "~1.21.4",
"jshint": "~2.6.0",
"redis": "~0.8.6",
"strftime": "~0.8.2",
"semver": "~1.1.4"
},
"scripts": {
"test": "make check"
"preinstall": "make pre-install",
"test": "make test-all"
},
"engines": {
"node": ">=0.8 <0.11",

View File

@ -0,0 +1,24 @@
#!/bin/bash
if [[ "$OSTYPE" == "darwin"* ]]; then
CAIRO_PKG_CONFIG=`pkg-config cairo --cflags-only-I 2> /dev/null`
RESULT=$?
if [[ ${RESULT} -ne 0 ]]; then
echo "###################################################################################"
echo "# PREINSTALL HOOK ERROR #"
echo "#---------------------------------------------------------------------------------#"
echo "# #"
echo "# node-canvas install error: some packages required by 'cairo' are not found #"
echo "# #"
echo -e "# Use '\033[1mmake all\033[0m', it will take care of common/known issues #"
echo "# #"
echo "# As an alternative try: #"
echo "# Try to 'export PKG_CONFIG_PATH=/usr/local/lib/pkgconfig:/opt/X11/lib/pkgconfig' #"
echo "# #"
echo "# If problems persist visit: https://github.com/Automattic/node-canvas/wiki #"
echo "# #"
echo "###################################################################################"
exit 1
fi
fi

7
scripts/install.sh Normal file
View File

@ -0,0 +1,7 @@
#!/bin/bash
if [[ "$OSTYPE" == "darwin"* ]]; then
export PKG_CONFIG_PATH=/usr/local/lib/pkgconfig:/opt/X11/lib/pkgconfig
fi
npm install

18
scripts/lzma2config.js Normal file
View File

@ -0,0 +1,18 @@
if (process.argv.length !== 3) {
console.error('Usage: node %s lzma_string', __filename);
process.exit(1);
}
var LZMA = require('lzma').LZMA;
var lzmaWorker = new LZMA();
var lzmaInput = decodeURIComponent(process.argv[2]);
var lzmaBuffer = new Buffer(lzmaInput, 'base64')
.toString('binary')
.split('')
.map(function(c) {
return c.charCodeAt(0) - 128
});
lzmaWorker.decompress(lzmaBuffer, function(result) {
console.log(JSON.stringify(JSON.parse(JSON.parse(result).config), null, 4));
});

View File

@ -22,9 +22,11 @@ serverOptions = ServerOptions();
var server = new CartodbWindshaft(serverOptions);
server.setMaxListeners(0);
['/tiles/layergroup', '/u/localhost/tiles/layergroup'].forEach(function(layergroup_url) {
[true, false].forEach(function(cdbQueryTablesFromPostgresEnabledValue) {
suite('multilayer:postgres=' + cdbQueryTablesFromPostgresEnabledValue, function() {
var suiteName = 'multilayer:postgres=' + cdbQueryTablesFromPostgresEnabledValue + ";layergroup_url=" + layergroup_url;
suite(suiteName, function() {
var redis_client = redis.createClient(global.environment.redis.port);
var sqlapi_server;
@ -66,7 +68,7 @@ suite('multilayer:postgres=' + cdbQueryTablesFromPostgresEnabledValue, function(
{
var next = this;
assert.response(server, {
url: '/tiles/layergroup',
url: layergroup_url,
method: 'POST',
headers: {host: 'localhost', 'Content-Type': 'application/json' },
data: JSON.stringify(layergroup)
@ -94,7 +96,7 @@ suite('multilayer:postgres=' + cdbQueryTablesFromPostgresEnabledValue, function(
if ( err ) throw err;
var next = this;
assert.response(server, {
url: '/tiles/layergroup/' + expected_token + ':cb0/0/0/0.png',
url: layergroup_url + "/" + expected_token + ':cb0/0/0/0.png',
method: 'GET',
headers: {host: 'localhost' },
encoding: 'binary'
@ -135,7 +137,7 @@ suite('multilayer:postgres=' + cdbQueryTablesFromPostgresEnabledValue, function(
if ( err ) throw err;
var next = this;
assert.response(server, {
url: '/tiles/layergroup/localhost@' + expected_token + ':cb0/0/0/0.png',
url: layergroup_url + '/localhost@' + expected_token + ':cb0/0/0/0.png',
method: 'GET',
headers: {host: 'localhost' },
encoding: 'binary'
@ -152,7 +154,7 @@ suite('multilayer:postgres=' + cdbQueryTablesFromPostgresEnabledValue, function(
if ( err ) throw err;
var next = this;
assert.response(server, {
url: '/tiles/layergroup/' + expected_token
url: layergroup_url + "/" + expected_token
+ '/0/0/0/0.grid.json',
headers: {host: 'localhost' },
method: 'GET'
@ -170,7 +172,7 @@ suite('multilayer:postgres=' + cdbQueryTablesFromPostgresEnabledValue, function(
if ( err ) throw err;
var next = this;
assert.response(server, {
url: '/tiles/layergroup/' + expected_token
url: layergroup_url + "/" + expected_token
+ '/1/0/0/0.grid.json',
headers: {host: 'localhost' },
method: 'GET'
@ -222,7 +224,7 @@ suite('multilayer:postgres=' + cdbQueryTablesFromPostgresEnabledValue, function(
{
var next = this;
assert.response(server, {
url: '/tiles/layergroup?config=' + encodeURIComponent(JSON.stringify(layergroup)),
url: layergroup_url + '?config=' + encodeURIComponent(JSON.stringify(layergroup)),
method: 'GET',
headers: {host: 'localhost'}
}, {}, function(res, err) { next(err, res); });
@ -255,7 +257,7 @@ suite('multilayer:postgres=' + cdbQueryTablesFromPostgresEnabledValue, function(
{
var next = this;
assert.response(server, {
url: '/tiles/layergroup?config=' + encodeURIComponent(JSON.stringify(layergroup)),
url: layergroup_url + '?config=' + encodeURIComponent(JSON.stringify(layergroup)),
method: 'GET',
headers: {host: 'localhost'}
}, {}, function(res, err) { next(err, res); });
@ -299,7 +301,7 @@ suite('multilayer:postgres=' + cdbQueryTablesFromPostgresEnabledValue, function(
]
};
assert.response(server, {
url: '/tiles/layergroup?config=' + encodeURIComponent(JSON.stringify(layergroup)),
url: layergroup_url + '?config=' + encodeURIComponent(JSON.stringify(layergroup)),
method: 'GET',
headers: {host: 'localhost'}
}, {}, function(res) {
@ -321,7 +323,7 @@ suite('multilayer:postgres=' + cdbQueryTablesFromPostgresEnabledValue, function(
]
};
assert.response(server, {
url: '/tiles/layergroup?config=' + encodeURIComponent(JSON.stringify(layergroup)),
url: layergroup_url + '?config=' + encodeURIComponent(JSON.stringify(layergroup)),
method: 'GET',
headers: {host: 'localhost'}
}, {}, function(res) {
@ -352,7 +354,7 @@ suite('multilayer:postgres=' + cdbQueryTablesFromPostgresEnabledValue, function(
{
var next = this;
assert.response(server, {
url: '/tiles/layergroup',
url: layergroup_url,
method: 'POST',
headers: {host: 'localhost', 'Content-Type': 'application/json' },
data: JSON.stringify(layergroup)
@ -379,7 +381,7 @@ suite('multilayer:postgres=' + cdbQueryTablesFromPostgresEnabledValue, function(
if ( err ) throw err;
var next = this;
assert.response(server, {
url: '/tiles/layergroup/' + expected_token + ':cb10/1/0/0.png',
url: layergroup_url + "/" + expected_token + ':cb10/1/0/0.png',
method: 'GET',
headers: {host: 'localhost' },
encoding: 'binary'
@ -418,7 +420,7 @@ suite('multilayer:postgres=' + cdbQueryTablesFromPostgresEnabledValue, function(
if ( err ) throw err;
var next = this;
assert.response(server, {
url: '/tiles/layergroup/' + expected_token + ':cb11/4/0/0.png',
url: layergroup_url + "/" + expected_token + ':cb11/4/0/0.png',
method: 'GET',
headers: {host: 'localhost' },
encoding: 'binary'
@ -457,7 +459,7 @@ suite('multilayer:postgres=' + cdbQueryTablesFromPostgresEnabledValue, function(
if ( err ) throw err;
var next = this;
assert.response(server, {
url: '/tiles/layergroup/' + expected_token
url: layergroup_url + "/" + expected_token
+ '/0/1/0/0.grid.json',
headers: {host: 'localhost' },
method: 'GET'
@ -475,7 +477,7 @@ suite('multilayer:postgres=' + cdbQueryTablesFromPostgresEnabledValue, function(
if ( err ) throw err;
var next = this;
assert.response(server, {
url: '/tiles/layergroup/' + expected_token
url: layergroup_url + "/" + expected_token
+ '/0/4/0/0.grid.json',
headers: {host: 'localhost' },
method: 'GET'
@ -539,7 +541,7 @@ suite('multilayer:postgres=' + cdbQueryTablesFromPostgresEnabledValue, function(
if ( err ) throw err;
var next = this;
assert.response(server, {
url: '/tiles/layergroup',
url: layergroup_url,
method: 'POST',
headers: {host: 'localhost', 'Content-Type': 'application/json' },
data: JSON.stringify(layergroup)
@ -561,7 +563,7 @@ suite('multilayer:postgres=' + cdbQueryTablesFromPostgresEnabledValue, function(
+ statskey + ":stat_tag:" + layergroup.stat_tag + " to be 1, got " + val);
var next = this;
assert.response(server, {
url: '/tiles/layergroup',
url: layergroup_url,
method: 'POST',
headers: {host: 'localhost', 'Content-Type': 'application/json' },
data: JSON.stringify(layergroup)
@ -620,7 +622,7 @@ suite('multilayer:postgres=' + cdbQueryTablesFromPostgresEnabledValue, function(
]
};
assert.response(server, {
url: '/tiles/layergroup',
url: layergroup_url,
method: 'POST',
headers: {host: 'localhost', 'Content-Type': 'application/json' },
data: JSON.stringify(layergroup)
@ -648,7 +650,7 @@ suite('multilayer:postgres=' + cdbQueryTablesFromPostgresEnabledValue, function(
]
};
assert.response(server, {
url: '/tiles/layergroup',
url: layergroup_url,
method: 'POST',
headers: {host: 'localhost', 'Content-Type': 'application/json' },
data: JSON.stringify(layergroup)
@ -688,7 +690,7 @@ suite('multilayer:postgres=' + cdbQueryTablesFromPostgresEnabledValue, function(
{
var next = this;
assert.response(server, {
url: '/tiles/layergroup?map_key=1234',
url: layergroup_url + '?map_key=1234',
method: 'POST',
headers: {host: 'localhost', 'Content-Type': 'application/json' },
data: JSON.stringify(layergroup)
@ -716,7 +718,7 @@ suite('multilayer:postgres=' + cdbQueryTablesFromPostgresEnabledValue, function(
if ( err ) throw err;
var next = this;
assert.response(server, {
url: '/tiles/layergroup/' + expected_token + ':cb0/0/0/0.png?map_key=1234',
url: layergroup_url + "/" + expected_token + ':cb0/0/0/0.png?map_key=1234',
method: 'GET',
headers: {host: 'localhost' },
encoding: 'binary'
@ -737,7 +739,7 @@ suite('multilayer:postgres=' + cdbQueryTablesFromPostgresEnabledValue, function(
if ( err ) throw err;
var next = this;
assert.response(server, {
url: '/tiles/layergroup/' + expected_token
url: layergroup_url + "/" + expected_token
+ '/0/0/0/0.grid.json?map_key=1234',
headers: {host: 'localhost' },
method: 'GET'
@ -751,7 +753,7 @@ suite('multilayer:postgres=' + cdbQueryTablesFromPostgresEnabledValue, function(
if ( err ) throw err;
var next = this;
assert.response(server, {
url: '/tiles/layergroup/' + expected_token
url: layergroup_url + "/" + expected_token
+ '/1/0/0/0.grid.json?map_key=1234',
headers: {host: 'localhost' },
method: 'GET'
@ -766,7 +768,7 @@ suite('multilayer:postgres=' + cdbQueryTablesFromPostgresEnabledValue, function(
if ( err ) throw err;
var next = this;
assert.response(server, {
url: '/tiles/layergroup/' + expected_token + ':cb0/0/0/0.png',
url: layergroup_url + "/" + expected_token + ':cb0/0/0/0.png',
method: 'GET',
headers: {host: 'localhost' },
encoding: 'binary'
@ -782,7 +784,7 @@ suite('multilayer:postgres=' + cdbQueryTablesFromPostgresEnabledValue, function(
if ( err ) throw err;
var next = this;
assert.response(server, {
url: '/tiles/layergroup/' + expected_token
url: layergroup_url + "/" + expected_token
+ '/0/0/0/0.grid.json',
headers: {host: 'localhost' },
method: 'GET'
@ -798,7 +800,7 @@ suite('multilayer:postgres=' + cdbQueryTablesFromPostgresEnabledValue, function(
if ( err ) throw err;
var next = this;
assert.response(server, {
url: '/tiles/layergroup/' + expected_token
url: layergroup_url + "/" + expected_token
+ '/1/0/0/0.grid.json',
headers: {host: 'localhost' },
method: 'GET'
@ -849,7 +851,7 @@ suite('multilayer:postgres=' + cdbQueryTablesFromPostgresEnabledValue, function(
{
var next = this;
assert.response(server, {
url: '/tiles/layergroup?map_key=1234',
url: layergroup_url + '?map_key=1234',
method: 'POST',
headers: {host: 'localhost', 'Content-Type': 'application/json' },
data: JSON.stringify(layergroup)
@ -878,7 +880,7 @@ suite('multilayer:postgres=' + cdbQueryTablesFromPostgresEnabledValue, function(
if ( err ) throw err;
var next = this;
assert.response(server, {
url: '/tiles/layergroup/' + expected_token + ':cb0/0/0/0.png?map_key=1234',
url: layergroup_url + "/" + expected_token + ':cb0/0/0/0.png?map_key=1234',
method: 'GET',
headers: {host: 'localhost' },
encoding: 'binary'
@ -908,7 +910,7 @@ suite('multilayer:postgres=' + cdbQueryTablesFromPostgresEnabledValue, function(
if ( err ) throw err;
var next = this;
assert.response(server, {
url: '/tiles/layergroup/' + expected_token + ':cb0/0/0/0.png?map_key=1234',
url: layergroup_url + "/" + expected_token + ':cb0/0/0/0.png?map_key=1234',
method: 'GET',
headers: {host: 'localhost' },
encoding: 'binary'
@ -1044,7 +1046,7 @@ suite('multilayer:postgres=' + cdbQueryTablesFromPostgresEnabledValue, function(
{
var next = this;
assert.response(server, {
url: '/tiles/layergroup',
url: layergroup_url,
method: 'POST',
headers: {host: 'localhost', 'Content-Type': 'application/json' },
data: JSON.stringify(layergroup)
@ -1068,7 +1070,7 @@ suite('multilayer:postgres=' + cdbQueryTablesFromPostgresEnabledValue, function(
if ( err ) throw err;
var next = this;
assert.response(server, {
url: '/tiles/layergroup/' + expected_token + ':cb0/0/0/0.png',
url: layergroup_url + "/" + expected_token + ':cb0/0/0/0.png',
method: 'GET',
headers: {host: 'localhost' },
encoding: 'binary'
@ -1120,7 +1122,7 @@ suite('multilayer:postgres=' + cdbQueryTablesFromPostgresEnabledValue, function(
{
var next = this;
assert.response(server, {
url: '/tiles/layergroup?api_key=1234',
url: layergroup_url + '?api_key=1234',
method: 'POST',
headers: {host: 'localhost', 'Content-Type': 'application/json' },
data: JSON.stringify(layergroup)
@ -1146,7 +1148,7 @@ suite('multilayer:postgres=' + cdbQueryTablesFromPostgresEnabledValue, function(
if ( err ) throw err;
var next = this;
assert.response(server, {
url: '/tiles/layergroup/' + expected_token + ':cb0/0/0/0.png?api_key=1234',
url: layergroup_url + "/" + expected_token + ':cb0/0/0/0.png?api_key=1234',
method: 'GET',
headers: {host: 'localhost' },
encoding: 'binary'
@ -1211,7 +1213,7 @@ suite('multilayer:postgres=' + cdbQueryTablesFromPostgresEnabledValue, function(
assert.ok(data.length > 1024*64);
var next = this;
assert.response(server, {
url: '/tiles/layergroup?api_key=1234',
url: layergroup_url + '?api_key=1234',
method: 'POST',
headers: {host: 'localhost', 'Content-Type': 'application/json' },
data: data
@ -1268,7 +1270,7 @@ suite('multilayer:postgres=' + cdbQueryTablesFromPostgresEnabledValue, function(
{
var next = this;
assert.response(server, {
url: '/tiles/layergroup',
url: layergroup_url,
method: 'POST',
headers: {host: 'localhost', 'Content-Type': 'application/json' },
data: JSON.stringify(layergroup)
@ -1310,7 +1312,7 @@ suite('multilayer:postgres=' + cdbQueryTablesFromPostgresEnabledValue, function(
{
var next = this;
assert.response(server, {
url: '/tiles/layergroup',
url: layergroup_url,
method: 'POST',
headers: {host: 'localhost', 'Content-Type': 'application/json' },
data: JSON.stringify(layergroup)
@ -1334,7 +1336,7 @@ suite('multilayer:postgres=' + cdbQueryTablesFromPostgresEnabledValue, function(
}
var layergroupTtlRequest = {
url: '/tiles/layergroup?config=' + encodeURIComponent(JSON.stringify({
url: layergroup_url + '?config=' + encodeURIComponent(JSON.stringify({
version: '1.0.0',
layers: [
{ options: {
@ -1442,3 +1444,4 @@ suite('multilayer:postgres=' + cdbQueryTablesFromPostgresEnabledValue, function(
});
});
});