maplibre / martin

Blazing fast and lightweight PostGIS, MBtiles and PMtiles tile server, tile generation, and mbtiles tooling.
https://martin.maplibre.org
Apache License 2.0
2.27k stars 213 forks source link

CORS policy: No 'Access-Control-Allow-Origin' within localhost and "http://0.0.0.0:3000" #19

Closed rrlara closed 4 years ago

rrlara commented 5 years ago

Running in some internal issue. I'm running a local docker docker run \ -p 3000:3000 \ -e DATABASE_URL=postgres://postgres@host.docker.internal/db \ urbica/martin on my Mac OS. I've added a table with points. I made a website with mapbox GL and followed the directions in the README. The website is running on localhost.

Looks like I am running into a CORS issue and need help to solve.

Screen Shot 2019-08-26 at 5 11 04 PM

Looks like the table is loading but when it fetched the "pbf" files is unreachable.

I'll appreciate the help.

Thanks

EverWinter23 commented 5 years ago

Try the same using firefox with this extension -- https://addons.mozilla.org/en-US/firefox/addon/cors-everywhere/

rrlara commented 5 years ago

I tried using Firefox with the extension and it didn't work either.

Is there any Environment Variables or Configuration setting I can pass through docker to disable this cors setting?

"actix_web=info" [2019-08-27T23:26:39Z INFO actix_web::middleware::logger] 172.17.0.1:52888 "GET /public.park_points/8/40/166.pbf HTTP/1.1" 500 0 "http://localhost:8082/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36" 0.007099

stepankuzmin commented 5 years ago

Well, that's strange because martin sets Access-Control-Allow-Origin: * by default.

I can't reproduce this issue:

curl -i "http://0.0.0.0:3000/public.points/0/0/0.pbf"

HTTP/1.1 200 OK
content-length: 98897
content-type: application/x-protobuf
access-control-allow-origin: *
date: Wed, 28 Aug 2019 13:49:50 GMT

Could you please provide a repo or step-by-step instructions for me to reproduce this issue?

EverWinter23 commented 5 years ago

@rrlara Make sure to click on the extension after installing; the icon will turn green from red to signify that its working. I have been fighting CORS for days across multiple projects, then I stumbled on this extension, works like a charm.

And if that doesn't work, could you share the console log-- with the extension enabled.

rrlara commented 5 years ago

@stepankuzmin Here's my steps: I created a database called "surveys" in postgres (PostgreSQL 10.3) with postgis (2.4.3). Created a table called "park_points" with geom (geometry(Point,4326))

  -p 3000:3000 \
  -e DATABASE_URL=postgres://postgres@host.docker.internal/surveys \
  urbica/martin

after the docker is running and connected to the database:

curl localhost:3000/index.json

{
public.park_points: {
id: "public.park_points",
schema: "public",
table: "park_points",
id_column: null,
geometry_column: "geom",
srid: 4326,
extent: 4096,
buffer: 64,
clip_geom: true,
geometry_type: "POINT",
properties: {
maintd_by: "varchar",
sitename: "varchar",
objectid: "int8",
owner: "varchar",
mainttype: "varchar",
managetype: "varchar",
f_type: "varchar",
sitetype: "varchar",
f_name: "varchar",
gid: "int4",
manager: "varchar",
ownertype: "varchar",
kc_fac_fid: "int8"
}
}
}```
curl localhost:3000/public.park_points.json

```{
tilejson: "2.2.0",
name: "public.park_points",
description: null,
version: "1.0.0",
attribution: null,
template: null,
legend: null,
scheme: "tms",
tiles: [
"http://0.0.0.0:3000/public.park_points/{z}/{x}/{y}.pbf"
],
grids: null,
data: null,
minzoom: 0,
maxzoom: 30,
bounds: [
-180,
-90,
180,
90
],
center: null
}

In the client-side using Mapbox:

map.addLayer({
            id: "public.park_points",
            type: "circle",
            source: {
              type: "vector",
              url: "http://localhost:3000/public.park_points.json"
            },
            "source-layer": "public.park_points",
            paint: {
              "circle-radius": 6,
              "circle-color": "#007cbf",
              "circle-stroke-color": "#fff",
              "circle-stroke-width": 1
            }
          })

let me know what I'm missing. Thanks you!

volkanunsal commented 5 years ago

Same issue here.

volkanunsal commented 5 years ago

It looks like Access-Control-Allow-Origin: * is not set in the response headers of .pbf requests.

Screen Shot 2019-09-23 at 4 03 36 PM

stepankuzmin commented 5 years ago

Unfortunately, I still cannot reproduce this issue.

Eg. this is my setup on macOS:

brew install postgresql
brew install postgis
brew services start postgresql
createuser -s postgres
createdb db
psql -U postgres -d db
db=# create extension postgis;
CREATE EXTENSION
db=# create table points(gid serial PRIMARY KEY, geom geometry(GEOMETRY, 4326));
CREATE TABLE
db=# insert into points
db-#     select
db-#         generate_series(1, 5000) as id,
db-#         (st_dump(st_generatepoints(st_geomfromtext('POLYGON ((-180 90, 180 90, 180 -90, -180 -90, -180 90))', 4326), 5000))).geom;
INSERT 0 5000
db=# create index on points using gist(geom);
CREATE INDEX
docker run \
  -p 3000:3000 \
  -e DATABASE_URL=postgres://postgres@host.docker.internal/db \
  urbica/martin

open tests/debug.html

@rrlara @volkanunsal could you please provide steps to reproducible this? What OS do you use? Did you try to pull the latest version of docker image with docker pull urbica/martin?

volkanunsal commented 5 years ago

You’re testing in a file served from the file system. Try starting a server at port 3001 from tests directory and then navigate to localhost:3001/debug.html.

stepankuzmin commented 5 years ago

@volkanunsal I've tried to start web-server and serve debug page with

npx serve tests

And I still can access tiles from http://localhost:5000/debug

volkanunsal commented 5 years ago

That worked for me, too. But it doesn't work when I use my own table instead of the test table. The only difference as far as I can see is the name of the geometry_column and the name of the table.

Modify tests/config.yaml

---
pool_size: 20
keep_alive: 75
worker_processes: 8
listen_addresses: "0.0.0.0:3000"

table_sources:
  public.tenants:
    id: public.tenants
    schema: public
    table: tenants
    geometry_column: the_geom
    srid: 4326
    extent: 4096
    buffer: 64
    clip_geom: true
    geometry_type: GEOMETRY
    properties:
      gid: int4

Modify tests/debug.html to update public.points to public.tenants.

Then

martin --config=./tests/config.yaml postgres://newuser@localhost:5433/my_db

(My postgres is at port 5433.)

npx serve tests
stepankuzmin commented 5 years ago

@volkanunsal what distribution do you use? Are you using martin from homebrew or did you compiled it from the master branch?

volkanunsal commented 5 years ago

Martin from homebrew.

brew upgrade martin
Updating Homebrew...
Error: urbica/tap/martin 86.64 already installed
stepankuzmin commented 5 years ago

@volkanunsal it seems that there was a problem with homebrew distribution, could you please reinstall martin from the tap?

brew uninstall martin
brew untap urbica/tap
brew tap urbica/tap
brew install martin
volkanunsal commented 5 years ago

No, actually it works. My bad, I forgot to change the port number.

stepankuzmin commented 5 years ago

@rrlara can you still reproduce this issue with the latest docker image?

stepankuzmin commented 5 years ago

Hi everyone! Could you please try to reproduce this with the latest version of martin?

korywka commented 4 years ago

@stepankuzmin Yes. json file with CORS header *, and .pbf files are without.

stepankuzmin commented 4 years ago

@bravecow what kind of distribution are you using? Docker or some platform binaries?

korywka commented 4 years ago

@stepankuzmin Docker. martin runs on http behind https with nginx.

But inside https://lun-16.lun.in.ua/rpc/public.source_lun_contours.json tiles are served by http.

stepankuzmin commented 4 years ago

@bravecow could you please try to rewrite request URL?

korywka commented 4 years ago

@stepankuzmin

map.addSource('contours', {
      "type": "vector",
      "url": "https://lun-16.lun.in.ua/rpc/public.source_lun_contours.json"
});

map.addLayer({
      'id': 'contours',
      'type': 'fill',
      'source': 'contours',
      'source-layer': 'contours',
      'paint': {
        'fill-color': '#f00',
        'fill-opacity': 0.5
      }
});

our nginx config:

    location / {
        add_header 'access-control-allow-origin' '*';
        try_files $uri @martin;
    }

    location @martin {
        proxy_set_header  X-Rewrite-URL $request_uri;
        proxy_set_header  X-Forwarded-Host $host;
        proxy_pass        http://127.0.0.1:3000;
}
korywka commented 4 years ago

rewrite fixes localhost => real host, but not http => https.

korywka commented 4 years ago

for now who have the same issue, you can use martin with tiles source:

map.addSource('contours', {
  "type": "vector",
  "tiles": [
    "https://lun-16.lun.in.ua/rpc/public.source_lun_contours/{z}/{x}/{y}.pbf"
  ],
  "minzoom": 0,
  "maxzoom": 14,
  "bounds": [
    22.0856083513,
    44.3614785833,
    40.0807890155,
    52.3350745713
  ],
});
stepankuzmin commented 4 years ago

@bravecow could you please create a separate issue for that as the problem is not with the CORS, but with scheme rewrite?

korywka commented 4 years ago

@stepankuzmin Please look at the first screenshot. Tiles are requested by http. If author's json is served by https, and tiles by http, I think we have the same problem.

korywka commented 4 years ago

So this http <=> https can cause this header to be lost. I don't know πŸ€·β€β™€

stepankuzmin commented 4 years ago

It seems that the request scheme is not propagated correctly to the martin instance. Could you please try adding X-Forwarded-Proto header?

location @martin {
  proxy_set_header  X-Rewrite-URL $request_uri;
  proxy_set_header  X-Forwarded-Host $host;
  proxy_set_header  X-Forwarded-Proto $proxy_x_forwarded_proto;
  proxy_pass        http://127.0.0.1:3000;
}

Or try something like this in your nginx config?

http {
  ...

  # If we receive X-Forwarded-Proto, pass it through; otherwise, pass along the
  # scheme used to connect to this server
  map $http_x_forwarded_proto $proxy_x_forwarded_proto {
  default $http_x_forwarded_proto;
  ''      $scheme;
  }

  server {
    ...

    location @martin {
      proxy_set_header  X-Rewrite-URL $request_uri;
      proxy_set_header  X-Forwarded-Host $host;
      proxy_set_header  X-Forwarded-Proto $proxy_x_forwarded_proto;
      proxy_pass        http://127.0.0.1:3000;
    }
  }
}
korywka commented 4 years ago
    location @martin {
        proxy_set_header  X-Rewrite-URL $request_uri;
        proxy_set_header  X-Forwarded-Host $host;
        proxy_set_header  X-Forwarded-Proto $proxy_x_forwarded_proto;
        proxy_pass        http://127.0.0.1:3000;
    }

sudo /etc/init.d/nginx reload

[ ok ] Reloading nginx configuration (via systemctl): nginx.service.

sudo docker restart 6c9709507152

https://lun-16.lun.in.ua/rpc/public.lun_contours.json

"tiles":["http://lun-16.lun.in.ua

Didn't help πŸ€·β€β™‚

korywka commented 4 years ago

@stepankuzmin it works with this variable:

proxy_set_header X-Forwarded-Proto $scheme;

from: https://www.digitalocean.com/community/tutorials/how-to-configure-nginx-with-ssl-as-a-reverse-proxy-for-jenkins

now it loads tiles by https, and no CORS errors πŸ‘

thanks for your quick responses πŸ˜‰

stepankuzmin commented 4 years ago

Great! I've added a note on X-Forwarded-Proto to README.md, hope this helps.

rrlara commented 4 years ago

Hello All - Sorry for the absents. Came back to jump starting this after awhile and I am still having issues displaying vector circles on a MapboxGL map with both docker (urbica/martin:latest) and locally install of Martin (v.0.5.0). This time around I getting 500 error to load "GET /public.park_points/0/0/0.pbf" for an example. Looks like it is not the COR issues anymore. Here's some details.

I'm running a local instance on my mac with Martin (v.0.5.0) to take advantage of the Debugging mode: export RUST_LOG=actix_web=info,martin=debug,postgres=debug martin --listen-addresses="0.0.0.0:4545" postgres://postgres@localhost/surveys

Results of curl -i "http://0.0.0.0:4545/public.park_points/0/0/0.pbf: HTTP/1.1 500 Internal Server Error content-length: 0 access-control-allow-origin: * date: Wed, 22 Apr 2020 21:56:17 GMT

Results from Debugging RUST_LOG: export RUST_LOG=actix_web=info,martin=debug,postgres=debug martin --listen-addresses="0.0.0.0:4545" postgres://postgres@localhost/surveys [2020-04-22T21:56:05Z INFO martin] Starting martin v0.5.0 [2020-04-22T21:56:05Z INFO martin] Config is not set, scanning database [2020-04-22T21:56:05Z INFO martin] Connected to postgres://postgres@localhost/surveys [2020-04-22T21:56:05Z DEBUG postgres] executing query: [2020-04-22T21:56:05Z DEBUG postgres] preparing query with name ``: WITH columns AS ( SELECT ns.nspname AS table_schema, class.relname AS table_name, attr.attname AS column_name, trim(leading '_' from tp.typname) AS type_name FROM pg_attribute attr JOIN pg_catalog.pg_class AS class ON class.oid = attr.attrelid JOIN pg_catalog.pg_namespace AS ns ON ns.oid = class.relnamespace JOIN pg_catalog.pg_type AS tp ON tp.oid = attr.atttypid WHERE NOT attr.attisdropped AND attr.attnum > 0) SELECT f_table_schema, f_table_name, f_geometry_column, srid, type, COALESCE( jsonb_object_agg(columns.column_name, columns.type_name) FILTER (WHERE columns.column_name IS NOT NULL), '{}'::jsonb ) as properties FROM geometry_columns LEFT JOIN columns ON geometry_columns.f_table_schema = columns.table_schema AND geometry_columns.f_table_name = columns.table_name AND geometry_columns.f_geometry_column != columns.column_name GROUP BY f_table_schema, f_table_name, f_geometry_column, srid, type; [2020-04-22T21:56:05Z DEBUG postgres] executing statement with parameters: [] [2020-04-22T21:56:05Z INFO martin::table_source] Found public.park_points table source [2020-04-22T21:56:05Z DEBUG postgres] preparing query with name ``: SELECT routines.specific_schema, routines.routine_name FROM information_schema.routines LEFT JOIN information_schema.parameters ON routines.specific_name=parameters.specific_name WHERE routines.data_type = 'bytea' GROUP BY routines.specific_schema, routines.routine_name, routines.data_type HAVING array_agg(array[parameters.parameter_name::text, parameters.data_type::text]) @> array[array['z', 'integer'], array['x', 'integer'], array['y', 'integer'], array['query_params', 'json']]; [2020-04-22T21:56:05Z DEBUG postgres] executing statement with parameters: [] [2020-04-22T21:56:05Z DEBUG postgres] executing query: [2020-04-22T21:56:05Z DEBUG postgres] preparing query with name ``: select (regexp_matches(postgis_lib_version(), '^(\d+\.\d+\.\d+)', 'g'))[1] as postgis_lib_version [2020-04-22T21:56:05Z DEBUG postgres] executing statement with parameters: [] [2020-04-22T21:56:05Z INFO martin] Martin has been started on 0.0.0.0:4545. [2020-04-22T21:56:17Z DEBUG postgres] executing query: [2020-04-22T21:56:17Z DEBUG postgres] preparing query with name ``: WITH bounds AS (SELECT ST_MakeEnvelope(-20037508.34, 20037508.34, 20037508.34, -20037508.34, 3857) as mercator, ST_Transform(ST_MakeEnvelope(-20037508.34, 20037508.34, 20037508.34, -20037508.34, 3857), 4326) as original) SELECT ST_AsMVT(tile, 'public.park_points', 4096, 'geom' ) FROM ( SELECT ST_AsMVTGeom(ST_Transform(geom, 3857), bounds.mercator, 4096, 64, true) AS geom , "f_name","manager","objectid","maintd_by","gid","kc_fac_fid","mainttype","managetype","sitetype","sitename","owner","f_type","ownertype" FROM public.park_points, bounds WHERE geom && bounds.original ) AS tile WHERE geom IS NOT NULL [2020-04-22T21:56:17Z DEBUG postgres] executing statement with parameters: [] [2020-04-22T21:56:17Z INFO actix_web::middleware::logger] 127.0.0.1:52729 "GET /public.park_points/0/0/0.pbf HTTP/1.1" 500 0 "-" "curl/7.54.0" 0.012476

I've researched extensively to fix with all the issues in this repo and comments as well and no luck. Thanks!!