Compare commits

..

45 Commits

Author SHA1 Message Date
Daniel García Aubert
6aebe26cc9 Release 2.32.0 2016-04-06 19:29:07 +02:00
Daniel García Aubert
f93794717e Upgrades windshaft to 1.17.0 2016-04-06 19:26:55 +02:00
Raul Ochoa
0ebf482936 Merge pull request #410 from CartoDB/named-dynamic-styling
Overrided cartocss in the instantiation of named maps
2016-04-06 18:09:11 +02:00
Daniel García Aubert
b5b8083acd Overrided cartocss in the instantiation of named maps 2016-04-06 17:43:25 +02:00
Javier Goizueta
219658761f Stub next version 2016-04-04 14:34:35 +02:00
Javier Goizueta
e3a68a6b4d Release 2.31.2
This fixes a couple of overviews-related bugs
2016-04-04 14:31:57 +02:00
Javier Goizueta
01218c6ea1 Merge pull request #409 from CartoDB/405-wrapped-overviews-queries
Support overviews for named layer wrapped queries
2016-04-04 14:18:57 +02:00
Javier Goizueta
83d27a8e29 Merge pull request #407 from CartoDB/400-named-layer-overviews
Fix overviews integration for named layers
2016-04-04 14:18:34 +02:00
Javier Goizueta
fa2e884605 Support overviews for named layer wrapped queries
Fix #405
2016-04-01 15:40:44 +02:00
Javier Goizueta
f4554f41d2 Add tests for named maps overviews 2016-03-31 18:36:50 +02:00
Javier Goizueta
b97a67b844 Fix overviews integration for named layers
Fixes #400
2016-03-31 18:33:41 +02:00
csobier
3b13fad5e7 Merge pull request #403 from CartoDB/docs-592-consistent-placeholder-examples
added tip about placeholder format and errors
2016-03-28 07:12:59 -04:00
Raul Ochoa
9a8964bd39 Stubs next version 2016-03-23 15:14:52 +01:00
Raul Ochoa
aae251b178 Release 2.31.1 2016-03-23 15:09:38 +01:00
Raul Ochoa
2db7a3d110 Merge pull request #404 from CartoDB/upgrade-windshaft
Upgrade windshaft to 1.16.1
2016-03-23 15:08:23 +01:00
Raul Ochoa
5fe96a618d Upgrade windshaft to 1.16.1 2016-03-23 15:01:30 +01:00
csobier
43d1e5c613 changed documentation variable to username throughout, and other clean-up 2016-03-22 11:23:04 -04:00
csobier
8547cb836f consistent placeholder examples with brackets 2016-03-22 09:19:50 -04:00
csobier
85e5a89298 added tip about placeholder format and errors 2016-03-17 17:42:57 -04:00
Daniel García Aubert
fc94f3ad94 Fixed stub next version 2016-03-16 18:07:28 +01:00
Daniel García Aubert
d43b766448 Merge branch 'master' of github.com:CartoDB/Windshaft-cartodb 2016-03-16 17:40:49 +01:00
Daniel García Aubert
6ceca348cb Stubs next version 2016-03-16 17:40:30 +01:00
Daniel García Aubert
bff6f056d0 Stubs next version 2016-03-16 17:33:26 +01:00
Daniel García Aubert
366a66b331 Release 2.31.0 2016-03-16 17:30:58 +01:00
Daniel García Aubert
c0370c5703 Stubs next version 2016-03-15 17:45:50 +01:00
Daniel García Aubert
8d5551343b Release 2.30.0 2016-03-15 17:40:26 +01:00
Daniel García Aubert
4089e8537a Upgraded windshaft to version 1.15.0 2016-03-15 17:35:13 +01:00
csobier
cf06c6e974 Merge pull request #401 from CartoDB/docs-685-named-map-tiles-and-cleanup
moved fetch tiles section up one heading level
2016-03-15 09:16:40 -04:00
csobier
2ebab4c89e moved fetch tiles section up one heading level 2016-03-15 09:08:28 -04:00
csobier
8023fbae24 Merge pull request #379 from CartoDB/docs-685-named-map-tiles-and-cleanup
Docs 685 named map tiles and cleanup
2016-03-15 08:50:20 -04:00
csobier
35cb652c6c edited token placeholder for consistency 2016-03-14 13:01:10 -04:00
csobier
c6085779a4 use the layergroupid, not SRID, as the mapnik token 2016-03-14 12:25:59 -04:00
csobier
86232eb239 clarified mapnik description and removed unnecessary content, as instructed by Carla 2016-03-14 11:51:07 -04:00
csobier
5cc3e914fa added missing bracket, removed note about API key 2016-03-14 11:34:52 -04:00
Daniel García Aubert
d52d3d909f Fixed double-check error in turbo-cartocss preprocesing. 2016-03-14 15:25:56 +01:00
Daniel García Aubert
e7da9a151b Stubs next version 2016-03-14 14:47:02 +01:00
Daniel García Aubert
f75ba9d2c3 Release 2.29.0 2016-03-14 14:42:40 +01:00
Daniel García Aubert
be61d41f5e Stubs next version 2016-03-14 12:12:56 +01:00
csobier
32223baaef removed internal code, displayed somexyz examples 2016-03-07 10:53:51 -05:00
csobier
2f038f006b applied consistent terminology and applied rest of Carla's edits 2016-03-07 09:08:38 -05:00
csobier
14f58e12bb moved response info from template.json section to the related Response section, and left the name description as part of the template.json description 2016-02-22 11:41:06 -05:00
csobier
adefa8b819 applied Carla's edits to date 2016-02-22 09:01:04 -05:00
csobier
cfa2714dbb added fetch tile in for Maps API 2016-02-19 11:45:06 -05:00
csobier
4d6b4b1755 added xyz tile info-first draft 2016-02-18 16:58:28 -05:00
csobier
0994571895 clean-up portion of Named Maps doc-WIP 2016-02-18 13:15:28 -05:00
19 changed files with 1279 additions and 660 deletions

52
NEWS.md
View File

@@ -1,5 +1,56 @@
# Changelog
## 2.32.0
Released 2016-04-06
New features:
- Added support for dynamic styling for widgets in named maps
Announcements:
- Upgrades windshaft to [1.17.0](https://github.com/CartoDB/Windshaft/releases/tag/1.17.0)
## 2.31.2
Released 2016-04-04
Bug fixes:
- Overviews integration for named layers #400
- Support wrapped queries in named layers #405
## 2.31.1
Released 2016-03-23
Announcements:
- Upgrades windshaft to [1.16.1](https://github.com/CartoDB/Windshaft/releases/tag/1.16.1)
## 2.31.0
Released 2016-03-16
Announcements:
- Upgrades windshaft to [1.16.0](https://github.com/CartoDB/Windshaft/releases/tag/1.16.0)
## 2.30.0
Released 2016-03-15
Announcements:
- Upgrades windshaft to [1.15.0](https://github.com/CartoDB/Windshaft/releases/tag/1.15.0)
## 2.29.0
Released 2016-03-14
Announcements:
- Upgrades windshaft to [1.14.0](https://github.com/CartoDB/Windshaft/releases/tag/1.14.0)
## 2.28.0
@@ -8,6 +59,7 @@ Released 2016-03-14
New features:
- Added [turbo-cartocss](https://github.com/CartoDB/turbo-cartocss) to preprocess CartoCSS.
## 2.27.0
Released 2016-03-09

View File

@@ -4,10 +4,10 @@ The CartoDB Maps API allows you to generate maps based on data hosted in your Ca
You can create two types of maps with the Maps API:
- **Anonymous maps**
- **Anonymous Maps**
You can create maps using your CartoDB public data. Any client can change the read-only SQL and CartoCSS parameters that generate the map tiles. These maps can be created from a JavaScript application alone and no authenticated calls are needed. See [this CartoDB.js example](/cartodb-platform/cartodb-js/getting-started/).
- **Named maps**
- **Named Maps**
There are also maps that have access to your private data. These maps require an owner to setup and modify any SQL and CartoCSS parameters and are not modifiable without new setup calls.
## Documentation

View File

@@ -6,7 +6,7 @@ This specification describes an extension for
# 2. Changes over specification
This extension introduces a new layer type so it's possible to use a named map by its name as a layer.
This extension introduces a new layer type so it's possible to use a Named Map by its name as a layer.
## 2.1 Named layers definition
@@ -21,18 +21,18 @@ This extension introduces a new layer type so it's possible to use a named map b
options: {
// REQUIRED
// string, the name for the named map to use
// string, the name for the Named Map to use
name: "world_borders",
// OPTIONAL
// object, the replacement values for the named map's template placeholders
// object, the replacement values for the Named Map's template placeholders
// See https://github.com/CartoDB/Windshaft-cartodb/blob/master/docs/Map-API.md#instantiate-1 for more details
config: {
"color": "#000"
},
// OPTIONAL
// string array, the authorized tokens in case the named map has auth method set to `token`
// string array, the authorized tokens in case the Named Map has auth method set to `token`
// See https://github.com/CartoDB/Windshaft-cartodb/blob/master/docs/Map-API.md#named-maps-1 for more details
auth_tokens: [
"token1",

View File

@@ -1,6 +1,6 @@
# Anonymous Maps
Anonymous maps allows you to instantiate a map given SQL and CartoCSS. It also allows you to add interaction capabilities using [UTF Grid.](https://github.com/mapbox/utfgrid-spec)
Anonymous Maps allows you to instantiate a map given SQL and CartoCSS. It also allows you to add interaction capabilities using [UTF Grid.](https://github.com/mapbox/utfgrid-spec)
## Instantiate
@@ -36,7 +36,7 @@ The response includes:
Attributes | Description
--- | ---
layergroupid | The ID for that map, used to compose the URL for the tiles. The final URL is: `https://{account}.cartodb.com/api/v1/map/:layergroupid/{z}/{x}/{y}.png`
layergroupid | The ID for that map, used to compose the URL for the tiles. The final URL is: `https://{username}.cartodb.com/api/v1/map/{layergroupid}/{z}/{x}/{y}.png`
updated_at | The ISO date of the last time the data involved in the query was updated.
metadata | Includes information about the layers.
cdn_url | URLs to fetch the data using the best CDN for your zone.
@@ -46,7 +46,7 @@ cdn_url | URLs to fetch the data using the best CDN for your zone.
#### Call
```bash
curl 'https://documentation.cartodb.com/api/v1/map' -H 'Content-Type: application/json' -d @mapconfig.json
curl 'https://{username}.cartodb.com/api/v1/map' -H 'Content-Type: application/json' -d @mapconfig.json
```
#### Response
@@ -72,12 +72,14 @@ curl 'https://documentation.cartodb.com/api/v1/map' -H 'Content-Type: applicatio
### Retrieve resources from the layergroup
#### Mapnik tiles can be accessed using
When you have a layergroup, there are several resources for retrieving layergoup details such as, accessing Mapnik tiles, getting individual layers, accessing defined Attributes, and blending and layer selection.
These tiles will get just the mapnik layers. To get individual layers see next section.
#### Mapnik tiles
These tiles will get just the Mapnik layers. To get individual layers, see the following section.
```bash
https://documentation.cartodb.com/api/v1/map/c01a54877c62831bb51720263f91fb33:0/{z}/{x}/{y}.png
https://{username}.cartodb.com/api/v1/map/{layergroupid}/{z}/{x}/{y}.png
```
#### Individual layers
@@ -87,21 +89,21 @@ The MapConfig specification holds the layers definition in a 0-based index. Laye
Individual layers can be accessed using that 0-based index. For UTF grid tiles:
```bash
https://documentation.cartodb.com/api/v1/map/c01a54877c62831bb51720263f91fb33:0/:layer/{z}/{x}/{y}.grid.json
https://{username}.cartodb.com/api/v1/map/{layergroupid}/{layer}/{z}/{x}/{y}.grid.json
```
In this case, `:layer` as 0 returns the UTF grid tiles/attributes for layer 0, the only layer in the example MapConfig.
In this case, `layer` as 0 returns the UTF grid tiles/attributes for layer 0, the only layer in the example MapConfig.
If the MapConfig had a Torque layer at index 1 it could be possible to request it with:
```bash
https://documentation.cartodb.com/api/v1/map/c01a54877c62831bb51720263f91fb33:0/1/{z}/{x}/{y}.torque.json
https://{username}.cartodb.com/api/v1/map/{layergroupid}/1/{z}/{x}/{y}.torque.json
```
#### Attributes defined in `attributes` section
```bash
https://documentation.cartodb.com/api/v1/map/c01a54877c62831bb51720263f91fb33:0/:layer/attributes/:feature_id
https://{username}.cartodb.com/api/v1/map/{layergroupid}/{layer}/attributes/{feature_id}
```
Which returns JSON with the attributes defined, like:
@@ -113,19 +115,19 @@ Which returns JSON with the attributes defined, like:
#### Blending and layer selection
```bash
https://documentation.cartodb.com/api/v1/map/c01a54877c62831bb51720263f91fb33:0/:layer_filter/{z}/{x}/{y}.png
https://{username}.cartodb.com/api/v1/map/{layergroupid}/{layer_filter}/{z}/{x}/{y}.png
```
Note: currently format is limited to `png`.
`:layer_filter` can be used to select some layers to be rendered together. `:layer_filter` supports two formats:
`layer_filter` can be used to select some layers to be rendered together. `layer_filter` supports two formats:
- `all` alias
Using `all` as `:layer_filter` will blend all layers in the layergroup
Using `all` as `layer_filter` will blend all layers in the layergroup
```bash
https://documentation.cartodb.com/api/v1/map/c01a54877c62831bb51720263f91fb33:0/all/{z}/{x}/{y}.png
https://{username}.cartodb.com/api/v1/map/{layergroupid}/all/{z}/{x}/{y}.png
```
- Filter by layer index
@@ -133,14 +135,14 @@ https://documentation.cartodb.com/api/v1/map/c01a54877c62831bb51720263f91fb33:0/
A list of comma separated layer indexes can be used to just render a subset of layers. For example `0,3,4` will filter and blend layers with indexes 0, 3, and 4.
```bash
https://documentation.cartodb.com/api/v1/map/c01a54877c62831bb51720263f91fb33:0/0,3,4/{z}/{x}/{y}.png
https://{username}.cartodb.com/api/v1/map/{layergroupid}/0,3,4/{z}/{x}/{y}.png
```
Some notes about filtering:
- Invalid index values or out of bounds indexes will end in `Invalid layer filtering` errors.
- Once a mapnik layer is selected, all mapnik layers will get blended. As this may change in the future **it is
recommended** to always select all mapnik layers if you want to select at least one so you will get a consistent
- Once a Mapnik layer is selected, all Mapnik layers will get blended. As this may change in the future **it is
recommended** to always select all Mapnik layers if you want to select at least one so you will get a consistent
behavior in the future.
- Ordering is not considered. So right now filtering layers 0,3,4 is the very same thing as filtering 3,4,0. As this
may change in the future **it is recommended** to always select the layers in ascending order so you will get a
@@ -161,7 +163,7 @@ GET /api/v1/map?callback=method
Param | Description
--- | ---
config | Encoded JSON with the params for creating named maps (the variables defined in the template).
config | Encoded JSON with the params for creating Named Maps (the variables defined in the template).
lmza | This attribute contains the same as config but LZMA compressed. It cannot be used at the same time as `config`.
callback | JSON callback name.
@@ -170,7 +172,7 @@ callback | JSON callback name.
#### Call
```bash
curl "https://documentation.cartodb.com/api/v1/map?callback=callback&config=%7B%22version%22%3A%221.0.1%22%2C%22layers%22%3A%5B%7B%22type%22%3A%22cartodb%22%2C%22options%22%3A%7B%22sql%22%3A%22select+%2A+from+european_countries_e%22%2C%22cartocss%22%3A%22%23european_countries_e%7B+polygon-fill%3A+%23FF6600%3B+%7D%22%2C%22cartocss_version%22%3A%222.3.0%22%2C%22interactivity%22%3A%5B%22cartodb_id%22%5D%7D%7D%5D%7D"
curl "https://{username}.cartodb.com/api/v1/map?callback=callback&config=%7B%22version%22%3A%221.0.1%22%2C%22layers%22%3A%5B%7B%22type%22%3A%22cartodb%22%2C%22options%22%3A%7B%22sql%22%3A%22select+%2A+from+european_countries_e%22%2C%22cartocss%22%3A%22%23european_countries_e%7B+polygon-fill%3A+%23FF6600%3B+%7D%22%2C%22cartocss_version%22%3A%222.3.0%22%2C%22interactivity%22%3A%5B%22cartodb_id%22%5D%7D%7D%5D%7D"
```
#### Response
@@ -189,4 +191,4 @@ callback({
## Remove
Anonymous maps cannot be removed by an API call. They will expire after about five minutes but sometimes longer. If an anonymous map expires and tiles are requested from it, an error will be raised. This could happen if a user leaves a map open and after time, returns to the map and attempts to interact with it in a way that requires new tiles (e.g. zoom). The client will need to go through the steps of creating the map again to fix the problem.
Anonymous Maps cannot be removed by an API call. They will expire after about five minutes, or sometimes longer. If an Anonymous Map expires and tiles are requested from it, an error will be raised. This could happen if a user leaves a map open and after time, returns to the map and attempts to interact with it in a way that requires new tiles (e.g. zoom). The client will need to go through the steps of creating the map again to fix the problem.

View File

@@ -4,7 +4,7 @@ The following concepts are the same for every endpoint in the API except when it
## Auth
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).
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. Using HTTPS is mandatory when you are performing requests that include your `api_key`.

View File

@@ -1,18 +1,24 @@
# Named Maps
Named maps are essentially the same as anonymous maps except the MapConfig is stored on the server, and the map is given a unique name. You can create named maps from private data, and users without an API Key can view your Named Map (while keeping your data private). The Named map workflow consists of making a call to your database, referencing a table, inserting your variables into the template where placeholders are defined, and creating custom queries.
Named Maps are essentially the same as Anonymous Maps except the MapConfig is stored on the server, and the map is given a unique name. You can create Named Maps from private data, and users without an API Key can view your Named Map (while keeping your data private).
The main two differences compared to anonymous maps are:
The Named Map workflow consists of uploading a MapConfig file to CartoDB servers, to select data from your CartoDB user database by using SQL, and specifying the CartoCSS for your map.
- **auth layer**
This allows you to control who is able to see the map based on a token auth
The response back from the API provides the template_id of your Named Map as the `name` (the identifier of your Named Map), which is the name that you specified in the MapConfig. You can which you can then use to create your Named Map details, or [fetch XYZ tiles](#fetching-xyz-tiles-for-named-maps) directly for Named Maps.
- **templates**
Since the MapConfig is static it can contain some variables so the client can modify the map's appearance using those variables.
**Tip:** You can also use a Named Map that you created (which is defined by its `name`), to create a map using CartoDB.js. This is achieved by adding the [`namedmap` type](http://docs.cartodb.com/cartodb-platform/cartodb-js/layer-source-object/#named-maps-layer-source-object-type-namedmap) layer source object to draw the Named Map.
Template maps are persistent with no preset expiration. They can only be created or deleted by a CartoDB user with a valid API_KEY (see auth section).
The main differences, compared to Anonymous Maps, is that Named Maps include:
**Note:** There is a limit of 4,096 named maps allowed per account. If you need to create more Named maps, it is recommended to use templates.
- **auth token**
This allows you to control who is able to see the map based on an auth token, and create a secure Named Map with password-protection.
- **template map**
The template map is static and may contain placeholders, enabling you to modify your maps appearance by using variables. Templates maps are persistent with no preset expiration. They can only be created, or deleted, by a CartoDB user with a valid API KEY (See [auth argument](#arguments)).
Uploading a MapConfig creates a Named Map. MapConfigs are uploaded to the server by sending the server a "template".json file, which contain the [MapConfig specifications](http://docs.cartodb.com/cartodb-platform/maps-api/mapconfig/).
**Note:** There is a limit of 4,096 Named Maps allowed per account. If you need to create more Named Maps, it is recommended to use a single Named Map and change the variables using [placeholders](#placeholder-format), instead of uploading multiple [Named Map MapConfigs](http://docs.cartodb.com/cartodb-platform/maps-api/mapconfig/#named-map-layer-options).
## Create
@@ -27,9 +33,12 @@ POST /api/v1/map/named
Params | Description
--- | ---
api_key | is required
MapConfig | a [Named Map MapConfig](http://docs.cartodb.com/cartodb-platform/maps-api/mapconfig/#named-map-layer-options) is required to create a Named Map
#### template.json
The `name` argument defines how to name this "template_name".json. Note that there are some requirements for how to name a Named Map template. See the [`name`](#arguments) argument description for details.
```javascript
{
"version": "0.0.1",
@@ -84,16 +93,15 @@ api_key | is required
Params | Description
--- | ---
name | There can be at most _one_ template with the same name for any user. Valid names start with a letter or a number, and only contain letters, numbers, dashes (-) or underscores (_).
name | There can only be _one_ template with the same name for any user. Valid names start with a letter or a number, and only contain letters, numbers, dashes (-), or underscores (_). _This is specific to the name of your Named Map that is specified in the `name` property of the template file_.
auth |
--- | ---
|_ method | `"token"` or `"open"` (the default if no `"method"` is given).
|_ valid_tokens | when `"method"` is set to `"token"`, the values listed here allow you to instantiate the named map.
placeholders | Variables not listed here are not substituted. Variables not provided at instantiation time trigger an error. A default is required for optional variables. Type specification is used for quoting, to avoid injections see template format section below.
layergroup | the layer list definition. This is the MapConfig explained in anonymous maps. See [MapConfig File Format](http://docs.cartodb.com/cartodb-platform/maps-api/mapconfig/) for more info.
view (optional) | extra keys to specify the compelling area for the map. It can be used to have a static preview of a named map without having to instantiate it. It is possible to specify it with `center` + `zoom` or with a bounding box `bbox`. Center+zoom takes precedence over bounding box.
|_ method | `"token"` or `"open"` (`"open"` is the default if no method is specified. Use `"token"` to password-protect your map)
|_ valid_tokens | when `"method"` is set to `"token"`, the values listed here allow you to instantiate the Named Map. See this [example](http://docs.cartodb.com/faqs/manipulating-your-data/#how-to-create-a-password-protected-named-map) for how to create a password-protected map.
placeholders | Placeholders are variables that can be placed in your template.json file's SQL or CartoCSS.
layergroup | the layergroup configurations, as specified in the template. See [MapConfig File Format](http://docs.cartodb.com/cartodb-platform/maps-api/mapconfig/) for more information.
view (optional) | extra keys to specify the view area for the map. It can be used to have a static preview of a Named Map without having to instantiate it. It is possible to specify it with `center` + `zoom` or with a bounding box `bbox`. Center+zoom takes precedence over bounding box.
--- | ---
|_ zoom | The zoom level to use
@@ -109,11 +117,12 @@ view (optional) | extra keys to specify the compelling area for the map. It can
|_ |_ east | UpperCorner longitude for the bounding box, in decimal degrees (aka most eastern)
|_ |_ north | UpperCorner latitude for the bounding box, in decimal degrees (aka most northern)
### Template Format
A templated `layergroup` allows the use of placeholders in the "cartocss" and "sql" elements of the "option" object in any "layer" of a `layergroup` configuration
### Placeholder Format
Valid placeholder names start with a letter and can only contain letters, numbers, or underscores. They have to be written between the `<%=` and `%>` strings in order to be replaced.
Placeholders are variables that can be placed in your template.json file. Placeholders need to be defined with a `type` and a default value for MapConfigs. See details about defining a MapConfig `type` for [Layergoup configurations](http://docs.cartodb.com/cartodb-platform/maps-api/mapconfig/#layergroup-configurations).
Valid placeholder names start with a letter and can only contain letters, numbers, or underscores. They have to be written between the `<%=` and `%>` strings in order to be replaced inside the Named Maps API.
#### Example
@@ -121,7 +130,7 @@ Valid placeholder names start with a letter and can only contain letters, number
<%= my_color %>
```
The set of supported placeholders for a template will need to be explicitly defined with a specific type and default value for each.
The set of supported placeholders for a template need to be explicitly defined with a specific type, and default value, for each placeholder.
### Placeholder Types
@@ -134,60 +143,64 @@ sql_ident | internal double-quotes will be sql-escaped
number | can only contain numerical representation
css_color | can only contain color names or hex-values
Placeholder default values will be used whenever new values are not provided as options at the time of creation on the client. They can also be used to test the template by creating a default version with new options provided.
Placeholder default values will be used whenever new values are not provided as options, at the time of creation on the client. They can also be used to test the template by creating a default version with new options provided.
When using templates, be very careful about your selections as they can give broad access to your data if they are defined losely.
When using templates, be very careful about your selections as they can give broad access to your data if they are defined loosely.
#### Call
```html
This is the call for creating the Named Map. It is sending the template.json file to the service, and the server responds with the template id.
```bash
curl -X POST \
-H 'Content-Type: application/json' \
-d @template.json \
'https://documentation.cartodb.com/api/v1/map/named?api_key=APIKEY'
'https://{username}.cartodb.com/api/v1/map/named?api_key={api_key}'
```
#### Response
The response back from the API provides the name of your MapConfig as a template, enabling you to edit the Named Map details by inserting your variables into the template where placeholders are defined, and create custom queries using SQL.
```javascript
{
"template_id":"name",
"template_id":"name"
}
```
## Instantiate
Instantiating a map allows you to get the information needed to fetch tiles. That temporal map is an anonymous map.
Instantiating a Named Map allows you to fetch the map tiles. You can use the Maps API to instantiate, or use the CartoDB.js `createLayer()` function. The result is an Anonymous Map.
#### Definition
```html
POST /api/v1/map/named/:template_name
POST /api/v1/map/named/{template_name}
```
#### Param
Param | Description
--- | ---
auth_token | optional, but required when `"method"` is set to `"token"`
auth_token | `"token"` or `"open"` (`"open"` is the default if not specified. Use `"token"` to password-protect your map)
```javascript
// params.json
// params.json, this is required if the Named Map allows variables (if placeholders were defined in the template.json by the user)
{
"color": "#ff0000",
"cartodb_id": 3
}
```
The fields you pass as `params.json` depend on the variables allowed by the named map. If there are variables missing it will raise an error (HTTP 400)
The fields you pass as `params.json` depend on the variables allowed by the Named Map. If there are variables missing, it will raise an error (HTTP 400).
- **auth_token** *optional* if the named map needs auth
**Note:** It is required that you include a `params.json` file to instantiate a Named Map that contains variables, even if you have no fields to pass and the JSON is empty. (This is specific to when a Named Map allows variables (if placeholders were defined in the template.json by the user).
### Example
#### Example
You can initialize a template map by passing all of the required parameters in a POST to `/api/v1/map/named/:template_name`.
You can initialize a template map by passing all of the required parameters in a POST to `/api/v1/map/named/{template_name}`.
Valid credentials will be needed if required by the template.
Valid auth token will be needed, if required by the template.
#### Call
@@ -196,7 +209,7 @@ Valid credentials will be needed if required by the template.
curl -X POST \
-H 'Content-Type: application/json' \
-d @params.json \
'https://documentation.cartodb.com/api/v1/map/named/@template_name?auth_token=AUTH_TOKEN'
'https://{username}.cartodb.com/api/v1/map/named/{template_name}?auth_token={auth_token}'
```
#### Response
@@ -216,68 +229,14 @@ curl -X POST \
}
```
You can then use the `layergroupid` for fetching tiles and grids as you would normally (see anonymous map section). However you'll need to show the `auth_token`, if required by the template.
## Using JSONP
There is also a special endpoint to be able to initialize a map using JSONP (for old browsers).
#### Definition
```bash
GET /api/v1/map/named/:template_name/jsonp
```
#### Params
Params | Description
--- | ---
auth_token | optional, but required when `"method"` is set to `"token"`
config | Encoded JSON with the params for creating named maps (the variables defined in the template)
lmza | This attribute contains the same as config but LZMA compressed. It cannot be used at the same time than `config`.
callback | JSON callback name
#### Call
```bash
curl 'https://documentation.cartodb.com/api/v1/map/named/:template_name/jsonp?auth_token=AUTH_TOKEN&callback=callback&config=template_params_json'
```
#### Response
```javascript
callback({
"layergroupid":"c01a54877c62831bb51720263f91fb33:0",
"last_updated":"1970-01-01T00:00:00.000Z"
"cdn_url": {
"http": "http://cdb.com",
"https": "https://cdb.com"
}
})
```
This takes the `callback` function (required), `auth_token` if the template needs auth, and `config` which is the variable for the template (in cases where it has variables).
```javascript
url += "config=" + encodeURIComponent(
JSON.stringify({ color: 'red' });
```
The response is in this format:
```javascript
callback({
layergroupid: "dev@744bd0ed9b047f953fae673d56a47b4d:1390844463021.1401",
last_updated: "2014-01-27T17:41:03.021Z"
})
```
You can then use the `layergroupid` for fetching tiles and grids as you would normally (see [Anonymous Maps](http://docs.cartodb.com/cartodb-platform/maps-api/anonymous-maps/)).
## Update
#### Definition
```bash
PUT /api/v1/map/named/:template_name
PUT /api/v1/map/named/{template_name}
```
#### Params
@@ -290,9 +249,9 @@ api_key | is required
Same as updating a map.
### Other Info
### Other Information
Updating a named map removes all the named map instances so they need to be initialized again.
Updating a Named Map removes all the Named Map instances, so they need to be initialized again.
### Example
@@ -302,7 +261,7 @@ Updating a named map removes all the named map instances so they need to be init
curl -X PUT \
-H 'Content-Type: application/json' \
-d @template.json \
'https://documentation.cartodb.com/api/v1/map/named/:template_name?api_key=APIKEY'
'https://{username}.cartodb.com/api/v1/map/named/{template_name}?api_key={api_key}'
```
#### Response
@@ -325,12 +284,12 @@ If a template with the same name does NOT exist, a 400 HTTP response is generate
## Delete
Delete the specified template map from the server and it disables any previously initialized versions of the map.
Deletes the specified template map from the server, and disables any previously initialized versions of the map.
#### Definition
```bash
DELETE /api/v1/map/named/:template_name
DELETE /api/v1/map/named/{template_name}
```
#### Params
@@ -344,7 +303,7 @@ api_key | is required
#### Call
```bash
curl -X DELETE 'https://documentation.cartodb.com/api/v1/map/named/:template_name?api_key=APIKEY'
curl -X DELETE 'https://{username}.cartodb.com/api/v1/map/named/{template_name}?api_key={api_key}'
```
#### Response
@@ -378,7 +337,7 @@ api_key | is required
#### Call
```bash
curl -X GET 'https://documentation.cartodb.com/api/v1/map/named?api_key=APIKEY'
curl -X GET 'https://{username}.cartodb.com/api/v1/map/named?api_key={api_key}'
```
#### Response
@@ -397,14 +356,14 @@ curl -X GET 'https://documentation.cartodb.com/api/v1/map/named?api_key=APIKEY'
}
```
## Getting a Specific Template
## Get Template Definition
This gets the definition of a template.
This gets the definition of a requested template.
#### Definition
```bash
GET /api/v1/map/named/:template_name
GET /api/v1/map/named/{template_name}
```
#### Params
@@ -418,14 +377,14 @@ api_key | is required
#### Call
```bash
curl -X GET 'https://documentation.cartodb.com/api/v1/map/named/:template_name?api_key=APIKEY'
curl -X GET 'https://{username}.cartodb.com/api/v1/map/named/{template_name}?api_key={api_key}'
```
#### Response
```javascript
{
"template": {...} // see template.json above
"template": {...} // see [template.json](#templatejson)
}
```
@@ -437,39 +396,136 @@ curl -X GET 'https://documentation.cartodb.com/api/v1/map/named/:template_name?a
}
```
## Use CartoDB.js to Create Named Maps
Named maps can be used with CartoDB.js by specifying a named map in a layer source as follows. Named maps are treated almost the same as other layer source types in most other ways.
## JSONP for Named Maps
```js
var layerSource = {
user_name: '{your_user_name}',
type: 'namedmap',
named_map: {
name: '{template_name}',
layers: [{
layer_name: "layer1",
interactivity: "column1, column2, ..."
}]
}
}
If using a [JSONP](https://en.wikipedia.org/wiki/JSONP) (for old browsers) request, there is a special endpoint used to initialize and create a Named Map.
cartodb.createLayer('map_dom_id',layerSource)
.addTo(map_object);
#### Definition
```bash
GET /api/v1/map/named/{template_name}/jsonp
```
[CartoDB.js](http://docs.cartodb.com/cartodb-platform/cartodb-js/) has methods for accessing your named maps.
#### Params
Params | Description
--- | ---
auth_token | `"token"` or `"open"` (`"open"` is the default if no method is specified. Use `"token"` to password-protect your map)
params | Encoded JSON with the params (variables) needed for the Named Map
lmza | You can use an LZMA compressed file instead of a params JSON file
callback | JSON callback name
#### Call
```bash
curl 'https://{username}.cartodb.com/api/v1/map/named/{template_name}/jsonp?auth_token={auth_token}&callback=callback&config=template_params_json'
```
#### Response
```javascript
callback({
"layergroupid":"c01a54877c62831bb51720263f91fb33:0",
"last_updated":"1970-01-01T00:00:00.000Z"
"cdn_url": {
"http": "http://cdb.com",
"https": "https://cdb.com"
}
})
```
This takes the `callback` function (required), `auth_token` if the template needs auth, and `config` which is the variable for the template (in cases where it has variables).
```javascript
url += "config=" + encodeURIComponent(
JSON.stringify({ color: 'red' });
```
The response is:
```javascript
callback({
layergroupid: "dev@744bd0ed9b047f953fae673d56a47b4d:1390844463021.1401",
last_updated: "2014-01-27T17:41:03.021Z"
})
```
## CartoDB.js for Named Maps
You can use a Named Map that you created (which is defined by its `name`), to create a map using CartoDB.js. This is achieved by adding the [`namedmap` type](http://docs.cartodb.com/cartodb-platform/cartodb-js/layer-source-object/#named-maps-layer-source-object-type-namedmap) layer source object to draw the Named Map.
```javascript
{
user_name: '{username}', // Required
type: 'namedmap', // Required
named_map: {
name: '{name_of_map}', // Required, the 'name' of the Named Map that you have created
// Optional
layers: [{
layer_name: "sublayer0", // Optional
interactivity: "column1, column2, ..." // Optional
},
{
layer_name: "sublayer1",
interactivity: "column1, column2, ..."
},
...
],
// Optional
params: {
color: "hex_value",
num: 2
}
}
}
```
**Note:** Instantiating a Named Map over a `createLayer` does not require an API Key and by default, does not include auth tokens. _If_ you defined auth tokens for the Named Map configuration, then you will have to include them.
[CartoDB.js](http://docs.cartodb.com/cartodb-platform/cartodb-js/) has methods for accessing your Named Maps.
1. [layer.setParams()](http://docs.cartodb.com/cartodb-platform/cartodb-js/api-methods/#layersetparamskey-value) allows you to change the template variables (in the placeholders object) via JavaScript
**Note:** The CartoDB.js `layer.setParams()` function is not supported when using Named maps for Torque.
**Note:** The CartoDB.js `layer.setParams()` function is not supported when using Named Maps for Torque.
2. [layer.setAuthToken()](http://docs.cartodb.com/cartodb-platform/cartodb-js/api-methods/#layersetauthtokenauthtoken) allows you to set the auth tokens to create the layer
### Complete Examples of Named Maps created with CartoDB.js
#### Examples of Named Maps created with CartoDB.js
- [Named map selectors with interaction](http://bl.ocks.org/ohasselblad/515a8af1f99d5e690484)
- [Named Map selectors with interaction](http://bl.ocks.org/ohasselblad/515a8af1f99d5e690484)
- [Named map with interactivity and config file used to create it](http://bl.ocks.org/ohasselblad/d1a45b8ff5e7bd90cd68)
- [Named Map with interactivity](http://bl.ocks.org/ohasselblad/d1a45b8ff5e7bd90cd68)
- [Toggling sublayers in a Named Map](http://bl.ocks.org/ohasselblad/c1a0f4913610eec53cd3)
## Fetching XYZ Tiles for Named Maps
Optionally, authenticated users can fetch projected tiles (XYZ tiles or Mapnik Retina tiles) for your Named Map.
### Fetch XYZ Tiles Directly with a URL
Authenticated users, with an auth token, can use XYZ-based URLs to fetch tiles directly, and instantiate the Named Map as part of the request to your application. You do not have to do any other steps to initialize your map.
To call a template_id in a URL:
`/{template_id}/{layer}/{z}/{x}/{y}.{format}`
For example, a complete URL might appear as:
"https://{username}.cartodb.com/api/v1/map/named/{template_id}/{layer}/{z}/{x}/{y}.png"
The placeholders indicate the following:
- [`template_id`](http://docs.cartodb.com/cartodb-platform/maps-api/named-maps/#response) is the response of your Named Map.
- layers can be a number (referring to the # layer of your map), all layers of your map, or a list of layers.
- To show just the basemap layer, enter the number value `0` in the layer placeholder "https://{username}.cartodb.com/api/v1/map/named/{template_id}/0/{z}/{x}/{y}.png"
- To show the first layer, enter the number value `1` in the layer placeholder "https://{username}.cartodb.com/api/v1/map/named/{template_id}/1/{z}/{x}/{y}.png"
- To show all layers, enter the value `all` for the layer placeholder "https://{username}.cartodb.com/api/v1/map/named/{template_id}/all/{z}/{x}/{y}.png"
- To show a [list of layers](http://docs.cartodb.com/cartodb-platform/maps-api/anonymous-maps/#blending-and-layer-selection), enter the comma separated layer value as 0,1,2 in the layer placeholder. For example, to show the basemap and the first layer, "https://{username}.cartodb.com/api/v1/map/named/{template_id}/0,1/{z}/{x}/{y}.png"
### Get Mapnik Retina Tiles
Mapnik Retina tiles are not directly supported for Named Maps, so you cannot use the Named Map template_id. To fetch Mapnik Retina tiles, get the [layergroupid](http://docs.cartodb.com/cartodb-platform/maps-api/named-maps/#response-1) to initialize the map.
Instantiate the map by using your `layergroupid` in the token placeholder:
`{token}/{z}/{x}/{y}@{scale_factor}?{x}.{format}`

View File

@@ -1,8 +1,8 @@
# Quickstart
## Anonymous maps
## Anonymous Maps
Here is an example of how to create an anonymous map with JavaScript:
Here is an example of how to create an Anonymous Map with JavaScript:
```javascript
var mapconfig = {
@@ -22,18 +22,18 @@ $.ajax({
type: 'POST',
dataType: 'json',
contentType: 'application/json',
url: 'https://documentation.cartodb.com/api/v1/map',
url: 'https://{username}.cartodb.com/api/v1/map',
data: JSON.stringify(mapconfig),
success: function(data) {
var templateUrl = 'https://documentation.cartodb.com/api/v1/map/' + data.layergroupid + '/{z}/{x}/{y}.png'
var templateUrl = 'https://{username}.cartodb.com/api/v1/map/' + data.layergroupid + '/{z}/{x}/{y}.png'
console.log(templateUrl);
}
})
```
## Named maps
## Named Maps
Let's create a named map using some private tables in a CartoDB account.
Let's create a Named Map using some private tables in a CartoDB account.
The following map config sets up a map of European countries that have a white fill color:
```javascript
@@ -56,12 +56,12 @@ The following map config sets up a map of European countries that have a white f
}
```
The map config needs to be sent to CartoDB's Map API using an authenticated call. Here we will use a command line tool called `curl`. For more info about this tool, see [this blog post](http://quickleft.com/blog/command-line-tutorials-curl), or type `man curl` in bash. Using `curl`, and storing the config from above in a file `mapconfig.json`, the call would look like:
The MapConfig needs to be sent to CartoDB's Map API using an authenticated call. Here we will use a command line tool called `curl`. For more info about this tool, see [this blog post](http://quickleft.com/blog/command-line-tutorials-curl), or type `man curl` in bash. Using `curl`, and storing the config from above in a file `MapConfig.json`, the call would look like:
#### Call
```bash
curl 'https://{account}.cartodb.com/api/v1/map/named?api_key=APIKEY' -H 'Content-Type: application/json' -d @mapconfig.json
curl 'https://{username}.cartodb.com/api/v1/map/named?api_key={api_key}' -H 'Content-Type: application/json' -d @mapconfig.json
```
To get the `URL` to fetch the tiles you need to instantiate the map, where `template_id` is the template name from the previous response.
@@ -69,7 +69,7 @@ To get the `URL` to fetch the tiles you need to instantiate the map, where `temp
#### Call
```bash
curl -X POST 'https://{account}.cartodb.com/api/v1/map/named/:template_id' -H 'Content-Type: application/json'
curl -X POST 'https://{username}.cartodb.com/api/v1/map/named/{template_id}' -H 'Content-Type: application/json'
```
The response will return JSON with properties for the `layergroupid`, the timestamp (`last_updated`) of the last data modification and some key/value pairs with `metadata` for the `layers`.
@@ -96,5 +96,5 @@ Note: all `layers` in `metadata` will always have a `type` string and a `meta` d
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
https://documentation.cartodb.com/api/v1/map/c01a54877c62831bb51720263f91fb33:0/{z}/{x}/{y}.png
https://{username}.cartodb.com/api/v1/map/{layergroupid}/{z}/{x}/{y}.png
```

View File

@@ -1,28 +1,28 @@
# Static Maps API
The Static Maps API can be initiated using both named and anonymous maps using the 'layergroupid' token. The API can be used to create static images of parts of maps and thumbnails for use in web design, graphic design, print, field work, and many other applications that require standard image formats.
The Static Maps API can be initiated using both Named and Anonymous Maps using the 'layergroupid' token. The API can be used to create static images of parts of maps and thumbnails for use in web design, graphic design, print, field work, and many other applications that require standard image formats.
## Maps API endpoints
Begin by instantiating either a named or anonymous map using the `layergroupid token` as demonstrated in the Maps API documentation above. The `layergroupid` token calls to the map and allows for parameters in the definition to generate static images.
Begin by instantiating either a Named or Anonymous Map using the `layergroupid token` as demonstrated in the Maps API documentation above. The `layergroupid` token calls to the map and allows for parameters in the definition to generate static images.
### Zoom + center
#### Definition
```bash
GET /api/v1/map/static/center/:token/:z/:lat/:lng/:width/:height.:format
GET /api/v1/map/static/center/{token}/{z}/{lat}/{lng}/{width}/{height}.{format}
```
#### Params
Param | Description
--- | ---
:token | the layergroupid token from the map instantiation
:z | the zoom level of the map
:lat | the latitude for the center of the map
token | the layergroupid token from the map instantiation
z | the zoom level of the map
lat | the latitude for the center of the map
:format | the format for the image, supported types: `png`, `jpg`
format | the format for the image, supported types: `png`, `jpg`
--- | ---
&#124;_ jpg | will have a default quality of 85.
@@ -31,57 +31,56 @@ Param | Description
#### Definition
```bash
GET /api/v1/map/static/bbox/:token/:bbox/:width/:height.:format`
GET /api/v1/map/static/bbox/{token}/{bbox}/{width}/{height}.{format}`
```
#### Params
Param | Description
--- | ---
:token | the layergroupid token from the map instantiation
token | the layergroupid token from the map instantiation
:bbox | the bounding box in WGS 84 (EPSG:4326), comma separated values for:
bbox | the bounding box in WGS 84 (EPSG:4326), comma separated values for:
--- | ---
| LowerCorner longitude, in decimal degrees (aka most western)
| LowerCorner latitude, in decimal degrees (aka most southern)
| UpperCorner longitude, in decimal degrees (aka most eastern)
| UpperCorner latitude, in decimal degrees (aka most northern)
:width | the width in pixels for the output image
:height | the height in pixels for the output image
:format | the format for the image, supported types: `png`, `jpg`
width | the width in pixels for the output image
height | the height in pixels for the output image
format | the format for the image, supported types: `png`, `jpg`
:format | the bounding box in WGS 84 (EPSG:4326), comma separated values for:
format | the bounding box in WGS 84 (EPSG:4326), comma separated values for:
--- | ---
&#124;_ jpg | will have a default quality of 85.
Note: you can see this endpoint as
```bash
GET /api/v1/map/static/bbox/:token/:west,:south,:east,:north/:width/:height.:format`
GET /api/v1/map/static/bbox/{token}/{west},{south},{east},{north}/{width}/{height}.{format}`
```
### Named map
### Named Map
#### Definition
```bash
GET /api/v1/map/static/named/:name/:width/:height.:format
GET /api/v1/map/static/named/{name}/{width}/{height}.{format}
```
#### Params
Param | Description
--- | ---
:name | the name of the named map
:width | the width in pixels for the output image
:height | the height in pixels for the output image
:height | the height in pixels for the output image
name | the name of the Named Map
width | the width in pixels for the output image
height | the height in pixels for the output image
:format | the format for the image, supported types: `png`, `jpg`
format | the format for the image, supported types: `png`, `jpg`
--- | ---
&#124;_ jpg | will have a default quality of 85.
A named maps static image will get its constraints from the [view in the template](#Arguments), if `view` is not present it will estimate the extent based on the involved tables otherwise it fallback to `"zoom": 1`, `"lng": 0` and `"lat": 0`.
A Named Maps static image will get its constraints from the [`view` argument of the Create Named Map function](http://docs.cartodb.com/cartodb-platform/maps-api/named-maps/#arguments). If `view` is not defined, it will estimate the extent based on the involved tables, otherwise it fallbacks to `"zoom": 1`, `"lng": 0` and `"lat": 0`.
#### Layers
@@ -161,7 +160,7 @@ After instantiating a map from a CartoDB account:
#### Call
```bash
GET /api/v1/map/static/center/4b615ff367e498e770e7d05e99181873:1420231989550.8699/14/40.71502926732618/-73.96039009094238/600/400.png
GET /api/v1/map/static/center/{layergroupid}/{z}/{x}/{y}/{width}/{height}.png
```
#### Response

View File

@@ -477,7 +477,11 @@ o.instance = function(template, params) {
var layergroup = JSON.parse(JSON.stringify(template.layergroup));
for (var i=0; i<layergroup.layers.length; ++i) {
var lyropt = layergroup.layers[i].options;
if ( lyropt.cartocss ) {
if ( params.styles && params.styles[i] ) {
// dynamic styling for this layer
lyropt.cartocss = params.styles[i];
} else if ( lyropt.cartocss ) {
lyropt.cartocss = _replaceVars(lyropt.cartocss, all_params);
}
if ( lyropt.sql) {

View File

@@ -7,12 +7,13 @@ var queue = require('queue-async');
var LruCache = require("lru-cache");
function NamedMapProviderCache(templateMaps, pgConnection, userLimitsApi, turboCartocssAdapter) {
function NamedMapProviderCache(templateMaps, pgConnection, userLimitsApi, overviewsAdapter, turboCartocssAdapter) {
this.templateMaps = templateMaps;
this.pgConnection = pgConnection;
this.userLimitsApi = userLimitsApi;
this.namedLayersAdapter = new MapConfigNamedLayersAdapter(templateMaps);
this.overviewsAdapter = overviewsAdapter;
this.turboCartocssAdapter = turboCartocssAdapter;
this.providerCache = new LruCache({ max: 2000 });
@@ -31,6 +32,7 @@ NamedMapProviderCache.prototype.get = function(user, templateId, config, authTok
this.pgConnection,
this.userLimitsApi,
this.namedLayersAdapter,
this.overviewsAdapter,
this.turboCartocssAdapter,
user,
templateId,

View File

@@ -18,7 +18,6 @@ var NamedMapsCacheEntry = require('../cache/model/named_maps_entry');
var MapConfigNamedLayersAdapter = require('../models/mapconfig_named_layers_adapter');
var NamedMapMapConfigProvider = require('../models/mapconfig/named_map_provider');
var CreateLayergroupMapConfigProvider = require('../models/mapconfig/create_layergroup_provider');
var MapConfigOverviewsAdapter = require('../models/mapconfig_overviews_adapter');
/**
* @param {AuthApi} authApi
@@ -33,8 +32,8 @@ var MapConfigOverviewsAdapter = require('../models/mapconfig_overviews_adapter')
* @constructor
*/
function MapController(authApi, pgConnection, templateMaps, mapBackend, metadataBackend,
overviewsMetadataApi,
surrogateKeysCache, userLimitsApi, layergroupAffectedTables, turboCartoCssAdapter) {
surrogateKeysCache, userLimitsApi, layergroupAffectedTables,
overviewsAdapter, turboCartoCssAdapter) {
BaseController.call(this, authApi, pgConnection);
@@ -42,14 +41,13 @@ function MapController(authApi, pgConnection, templateMaps, mapBackend, metadata
this.templateMaps = templateMaps;
this.mapBackend = mapBackend;
this.metadataBackend = metadataBackend;
this.overviewsMetadataApi = overviewsMetadataApi;
this.surrogateKeysCache = surrogateKeysCache;
this.userLimitsApi = userLimitsApi;
this.layergroupAffectedTables = layergroupAffectedTables;
this.turboCartoCssAdapter = turboCartoCssAdapter;
this.namedLayersAdapter = new MapConfigNamedLayersAdapter(templateMaps);
this.overviewsAdapter = new MapConfigOverviewsAdapter(this.overviewsMetadataApi);
this.overviewsAdapter = overviewsAdapter;
}
util.inherits(MapController, BaseController);
@@ -231,6 +229,7 @@ MapController.prototype.instantiateTemplate = function(req, res, prepareParamsFn
self.pgConnection,
self.userLimitsApi,
self.namedLayersAdapter,
self.overviewsAdapter,
self.turboCartoCssAdapter,
cdbuser,
req.params.template_id,
@@ -240,22 +239,6 @@ MapController.prototype.instantiateTemplate = function(req, res, prepareParamsFn
);
mapConfigProvider.getMapConfig(this);
},
function addOverviewsInformation(err, requestMapConfig, rendererParams/*, context*/) {
assert.ifError(err);
var next = this;
self.overviewsAdapter.getLayers(req.context.user, requestMapConfig.layers,
function(err, layers) {
if (err) {
return next(err);
}
if (layers) {
requestMapConfig.layers = layers;
}
return next(null, requestMapConfig, rendererParams);
}
);
},
function createLayergroup(err, mapConfig_, rendererParams) {
assert.ifError(err);
mapConfig = mapConfig_;

View File

@@ -11,13 +11,15 @@ var QueryTables = require('cartodb-query-tables');
* @constructor
* @type {NamedMapMapConfigProvider}
*/
function NamedMapMapConfigProvider(templateMaps, pgConnection, userLimitsApi, namedLayersAdapter,
turboCartoCssAdapter, owner, templateId, config, authToken, params) {
function NamedMapMapConfigProvider(templateMaps, pgConnection, userLimitsApi,
namedLayersAdapter, overviewsAdapter, turboCartoCssAdapter,
owner, templateId, config, authToken, params) {
this.templateMaps = templateMaps;
this.pgConnection = pgConnection;
this.userLimitsApi = userLimitsApi;
this.namedLayersAdapter = namedLayersAdapter;
this.turboCartoCssAdapter = turboCartoCssAdapter;
this.overviewsAdapter = overviewsAdapter;
this.owner = owner;
this.templateName = templateName(templateId);
@@ -92,12 +94,32 @@ NamedMapMapConfigProvider.prototype.getMapConfig = function(callback) {
}
);
},
function addOverviewsInformation(err, _mapConfig, datasource) {
assert.ifError(err);
var next = this;
self.overviewsAdapter.getLayers(self.owner, _mapConfig.layers, function(err, layers) {
if (err) {
return next(err);
}
if (layers) {
_mapConfig.layers = layers;
}
return next(null, _mapConfig, datasource);
});
},
function parseTurboCartoCss(err, _mapConfig, datasource) {
assert.ifError(err);
var next = this;
self.turboCartoCssAdapter.getLayers(self.owner, _mapConfig.layers, function (err, layers) {
if (!err && layers) {
if (err) {
return next(err);
}
if (layers) {
_mapConfig.layers = layers;
}

View File

@@ -30,6 +30,8 @@ var PgConnection = require('./backends/pg_connection');
var timeoutErrorTilePath = __dirname + '/../../assets/render-timeout-fallback.png';
var timeoutErrorTile = require('fs').readFileSync(timeoutErrorTilePath, {encoding: null});
var MapConfigOverviewsAdapter = require('./models/mapconfig_overviews_adapter');
var TurboCartocssParser = require('./utils/style/turbo-cartocss-parser');
var TurboCartocssAdapter = require('./utils/style/turbo-cartocss-adapter');
@@ -142,6 +144,8 @@ module.exports = function(serverOptions) {
var layergroupAffectedTablesCache = new LayergroupAffectedTablesCache();
app.layergroupAffectedTablesCache = layergroupAffectedTablesCache;
var overviewsAdapter = new MapConfigOverviewsAdapter(overviewsMetadataApi);
var turboCartoCssParser = new TurboCartocssParser(pgQueryRunner);
var turboCartocssAdapter = new TurboCartocssAdapter(turboCartoCssParser);
@@ -149,6 +153,7 @@ module.exports = function(serverOptions) {
templateMaps,
pgConnection,
userLimitsApi,
overviewsAdapter,
turboCartocssAdapter
);
@@ -184,10 +189,10 @@ module.exports = function(serverOptions) {
templateMaps,
mapBackend,
metadataBackend,
overviewsMetadataApi,
surrogateKeysCache,
userLimitsApi,
layergroupAffectedTablesCache,
overviewsAdapter,
turboCartocssAdapter
).register(app);

View File

@@ -168,9 +168,16 @@ OverviewsQueryRewriter.prototype.query = function(query, data) {
};
OverviewsQueryRewriter.prototype.is_supported_query = function(sql) {
return !!sql.match(
/^\s*SELECT\s+[\*a-z0-9_,\s]+?\s+FROM\s+((\"[^"]+\"|[a-z0-9_]+)\.)?(\"[^"]+\"|[a-z0-9_]+)\s*;?\s*$/i
var basic_query = /\s*SELECT\s+[\*a-z0-9_,\s]+?\s+FROM\s+((\"[^"]+\"|[a-z0-9_]+)\.)?(\"[^"]+\"|[a-z0-9_]+)\s*;?\s*/i;
var unwrapped_query = new RegExp("^"+basic_query.source+"$", 'i');
// queries for named maps are wrapped like this:
var wrapped_query = new RegExp(
"^\\s*SELECT\\s+\\*\\s+FROM\\s+\\(" +
basic_query.source +
"\\)\\s+AS\\s+wrapped_query\\s+WHERE\\s+\\d+=1\\s*$",
'i'
);
return !!(sql.match(unwrapped_query) || sql.match(wrapped_query));
};
OverviewsQueryRewriter.prototype.overviews_metadata = function(data) {

1005
npm-shrinkwrap.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,7 +1,7 @@
{
"private": true,
"name": "windshaft-cartodb",
"version": "2.28.0",
"version": "2.32.0",
"description": "A map tile server for CartoDB",
"keywords": [
"cartodb"
@@ -26,7 +26,7 @@
"node-statsd": "~0.0.7",
"underscore" : "~1.6.0",
"dot": "~1.0.2",
"windshaft": "1.13.2",
"windshaft": "1.17.0",
"step": "~0.0.6",
"queue-async": "~1.0.7",
"request": "~2.62.0",

View File

@@ -0,0 +1,169 @@
var assert = require('../support/assert');
var step = require('step');
var LayergroupToken = require('../../lib/cartodb/models/layergroup_token');
var testHelper = require(__dirname + '/../support/test_helper');
var CartodbWindshaft = require(__dirname + '/../../lib/cartodb/server');
var serverOptions = require(__dirname + '/../../lib/cartodb/server_options');
var server = new CartodbWindshaft(serverOptions);
describe('dynamic styling for named maps', function() {
var keysToDelete;
beforeEach(function() {
keysToDelete = {};
});
afterEach(function(done) {
testHelper.deleteRedisKeys(keysToDelete, done);
});
var templateId = 'dynamic-styling-template-1';
var template = {
version: '0.0.1',
name: templateId,
auth: { method: 'open' },
placeholders: {
color: {
type: "css_color",
default: "Reds"
}
},
layergroup: {
version: '1.0.0',
layers: [{
options: {
sql: 'SELECT * FROM test_table',
cartocss: [
'#layer {',
' marker-fill: #000;',
'}'
].join('\n'),
cartocss_version: '2.0.2'
}
}, {
options: {
sql: 'SELECT * FROM test_table',
cartocss: [
'#layer {',
' marker-fill: #000;',
'}'
].join('\n'),
cartocss_version: '2.0.2'
}
}, {
options: {
sql: 'SELECT * FROM test_table',
cartocss: [
'#layer {',
' marker-fill: #000;',
'}'
].join('\n'),
cartocss_version: '2.0.2'
}
}]
}
};
var templateParams = {
styles: {
0: [
'#layer {',
' marker-fill: #fabada;',
'}'
].join('\n'),
2: [
'#layer {',
' marker-fill: #cebada;',
'}'
].join('\n')
}
};
it('should instantiate a template applying cartocss dynamicly', function (done) {
step(
function postTemplate() {
var next = this;
assert.response(server, {
url: '/api/v1/map/named?api_key=1234',
method: 'POST',
headers: { host: 'localhost', 'Content-Type': 'application/json' },
data: JSON.stringify(template)
}, {},
function (res, err) {
next(err, res);
});
},
function checkTemplate(err, res) {
assert.ifError(err);
assert.equal(res.statusCode, 200);
assert.deepEqual(JSON.parse(res.body), {
template_id: templateId
});
return null;
},
function instantiateTemplate(err) {
assert.ifError(err);
var next = this;
assert.response(server, {
url: '/api/v1/map/named/' + templateId,
method: 'POST',
headers: {
host: 'localhost',
'Content-Type': 'application/json'
},
data: JSON.stringify(templateParams)
}, {},
function (res, err) {
return next(err, res);
});
},
function checkInstanciation(err, res) {
assert.ifError(err);
assert.equal(res.statusCode, 200);
var parsedBody = JSON.parse(res.body);
keysToDelete['map_cfg|' + LayergroupToken.parse(parsedBody.layergroupid).token] = 0;
keysToDelete['user:localhost:mapviews:global'] = 5;
assert.equal(parsedBody.metadata.layers[0].meta.cartocss, templateParams.styles['0']);
assert.equal(
parsedBody.metadata.layers[1].meta.cartocss,
template.layergroup.layers[1].options.cartocss
);
assert.equal(parsedBody.metadata.layers[2].meta.cartocss, templateParams.styles['2']);
return parsedBody.layergroupid;
},
function deleteTemplate(err) {
assert.ifError(err);
var next = this;
assert.response(server, {
url: '/api/v1/map/named/' + templateId + '?api_key=1234',
method: 'DELETE',
headers: { host: 'localhost' }
}, {}, function (res, err) {
next(err, res);
});
},
function checkDeleteTemplate(err, res) {
assert.ifError(err);
assert.equal(res.statusCode, 204);
assert.ok(!res.body);
return null;
},
function finish(err) {
done(err);
}
);
});
});

View File

@@ -0,0 +1,174 @@
var test_helper = require('../support/test_helper');
var assert = require('../support/assert');
var CartodbWindshaft = require(__dirname + '/../../lib/cartodb/server');
var serverOptions = require(__dirname + '/../../lib/cartodb/server_options');
var server = new CartodbWindshaft(serverOptions);
var LayergroupToken = require('../../lib/cartodb/models/layergroup_token');
var RedisPool = require('redis-mpool');
var step = require('step');
var windshaft = require('windshaft');
describe('overviews metadata for named maps', function() {
// configure redis pool instance to use in tests
var redisPool = new RedisPool(global.environment.redis);
var overviews_layer = {
type: 'cartodb',
options: {
sql: 'SELECT * FROM test_table_overviews',
cartocss: '#layer { marker-fill: black; }',
cartocss_version: '2.3.0'
}
};
var non_overviews_layer = {
type: 'cartodb',
options: {
sql: 'SELECT * FROM test_table',
cartocss: '#layer { marker-fill: black; }',
cartocss_version: '2.3.0'
}
};
var keysToDelete;
beforeEach(function() {
keysToDelete = {};
});
afterEach(function(done) {
test_helper.deleteRedisKeys(keysToDelete, done);
});
var templateId = 'overviews-template-1';
var template = {
version: '0.0.1',
name: templateId,
auth: { method: 'open' },
layergroup: {
version: '1.0.0',
layers: [overviews_layer, non_overviews_layer]
}
};
it("should add overviews data to layers", function(done) {
step(
function postTemplate()
{
var next = this;
assert.response(server, {
url: '/api/v1/map/named?api_key=1234',
method: 'POST',
headers: {host: 'localhost', 'Content-Type': 'application/json' },
data: JSON.stringify(template)
}, {}, function(res, err) {
next(err, res);
});
},
function checkTemplate(err, res) {
assert.ifError(err);
var next = this;
assert.equal(res.statusCode, 200);
assert.deepEqual(JSON.parse(res.body), {
template_id: templateId
});
next(null);
},
function instantiateTemplate(err) {
assert.ifError(err);
var next = this;
assert.response(server, {
url: '/api/v1/map/named/' + templateId,
method: 'POST',
headers: {
host: 'localhost',
'Content-Type': 'application/json'
}
}, {},
function(res, err) {
return next(err, res);
});
},
function checkInstanciation(err, res) {
assert.ifError(err);
var next = this;
assert.equal(res.statusCode, 200);
var parsedBody = JSON.parse(res.body);
keysToDelete['map_cfg|' + LayergroupToken.parse(parsedBody.layergroupid).token] = 0;
keysToDelete['user:localhost:mapviews:global'] = 5;
assert.ok(parsedBody.layergroupid);
assert.ok(parsedBody.last_updated);
next(null, parsedBody.layergroupid);
},
function checkMapconfig(err, layergroupId)
{
assert.ifError(err);
var next = this;
var mapStore = new windshaft.storage.MapStore({
pool: redisPool,
expire_time: 500000
});
mapStore.load(LayergroupToken.parse(layergroupId).token, function(err, mapConfig) {
assert.ifError(err);
assert.deepEqual(non_overviews_layer, mapConfig._cfg.layers[1]);
assert.equal(mapConfig._cfg.layers[0].type, 'cartodb');
assert.ok(mapConfig._cfg.layers[0].options.query_rewrite_data);
var expected_data = {
overviews: {
test_table_overviews: {
1: { table: '_vovw_1_test_table_overviews' },
2: { table: '_vovw_2_test_table_overviews' }
}
}
};
assert.deepEqual(mapConfig._cfg.layers[0].options.query_rewrite_data, expected_data);
});
next(err);
},
function deleteTemplate(err) {
assert.ifError(err);
var next = this;
assert.response(server, {
url: '/api/v1/map/named/' + templateId + '?api_key=1234',
method: 'DELETE',
headers: { host: 'localhost' }
}, {}, function (res, err) {
next(err, res);
});
},
function checkDeleteTemplate(err, res) {
assert.ifError(err);
assert.equal(res.statusCode, 204);
assert.ok(!res.body);
return null;
},
function finish(err) {
done(err);
}
);
});
});

View File

@@ -395,5 +395,32 @@ describe('Overviews query rewriter', function() {
done();
});
it('generates overviews for wrapped query', function(done){
var sql = "SELECT * FROM (SELECT * FROM table1) AS wrapped_query WHERE 1=1";
var data = {
overviews: {
table1: {
0: { table: 'table1_ov0' },
1: { table: 'table1_ov1' },
2: { table: 'table1_ov2' }
}
}
};
var overviews_sql = overviewsQueryRewriter.query(sql, data);
var expected_sql = "\
WITH\
_vovw_scale AS ( SELECT ZoomLevel() AS _vovw_z )\
SELECT * FROM (SELECT * FROM (\
SELECT * FROM table1_ov0, _vovw_scale WHERE _vovw_z = 0\
UNION ALL\
SELECT * FROM table1_ov1, _vovw_scale WHERE _vovw_z = 1\
UNION ALL\
SELECT * FROM table1_ov2, _vovw_scale WHERE _vovw_z = 2\
UNION ALL\
SELECT * FROM table1, _vovw_scale WHERE _vovw_z > 2\
) AS _vovw_table1) AS wrapped_query WHERE 1=1\
";
assertSameSql(overviews_sql, expected_sql);
done();
});
});