{"html_url": "https://github.com/simonw/datasette/issues/1024#issuecomment-709589297", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/1024", "id": 709589297, "node_id": "MDEyOklzc3VlQ29tbWVudDcwOTU4OTI5Nw==", "user": {"value": 9599, "label": "simonw"}, "created_at": "2020-10-15T21:04:31Z", "updated_at": "2020-10-15T21:04:31Z", "author_association": "OWNER", "body": "I think nginx or Apache would be the best tools for this. I'm inclined to try with nginx first since I know it better.", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 722674708, "label": "Figure out how to run an environment that exercises the base_url proxy setting"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/issues/1024#issuecomment-709590337", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/1024", "id": 709590337, "node_id": "MDEyOklzc3VlQ29tbWVudDcwOTU5MDMzNw==", "user": {"value": 9599, "label": "simonw"}, "created_at": "2020-10-15T21:06:24Z", "updated_at": "2020-10-15T21:07:19Z", "author_association": "OWNER", "body": "From https://stackoverflow.com/questions/32549684/nginx-proxy-and-remove-proxy-pass-prefix/32550251 it looks like the config I should use is:\r\n```\r\nserver {\r\n listen 80;\r\n server_name example.com;\r\n\r\n location /datasette/ {\r\n proxy_pass http://127.0.0.1:8001;\r\n proxy_set_header X-Real-IP $remote_addr;\r\n proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;\r\n proxy_set_header X-Forwarded-Proto $scheme;\r\n proxy_read_timeout 90;\r\n }\r\n}\r\n```", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 722674708, "label": "Figure out how to run an environment that exercises the base_url proxy setting"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/issues/1024#issuecomment-709590941", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/1024", "id": 709590941, "node_id": "MDEyOklzc3VlQ29tbWVudDcwOTU5MDk0MQ==", "user": {"value": 9599, "label": "simonw"}, "created_at": "2020-10-15T21:07:47Z", "updated_at": "2020-10-15T21:07:47Z", "author_association": "OWNER", "body": "On macOS I ran `brew install nginx`. I'm going to try running it on port 8000 so I don't have to run it as root.", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 722674708, "label": "Figure out how to run an environment that exercises the base_url proxy setting"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/issues/1024#issuecomment-709595960", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/1024", "id": 709595960, "node_id": "MDEyOklzc3VlQ29tbWVudDcwOTU5NTk2MA==", "user": {"value": 9599, "label": "simonw"}, "created_at": "2020-10-15T21:18:14Z", "updated_at": "2020-10-15T21:18:14Z", "author_association": "OWNER", "body": "Typing `nginx` starts it running as a daemon listening on port `http-alt` aka 8080. It uses the config file from ` /usr/local/etc/nginx/nginx.conf`.", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 722674708, "label": "Figure out how to run an environment that exercises the base_url proxy setting"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/issues/1024#issuecomment-709597589", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/1024", "id": 709597589, "node_id": "MDEyOklzc3VlQ29tbWVudDcwOTU5NzU4OQ==", "user": {"value": 9599, "label": "simonw"}, "created_at": "2020-10-15T21:21:53Z", "updated_at": "2020-10-15T21:23:25Z", "author_association": "OWNER", "body": "Here's a recipe for running nginx against a custom config file: https://gist.github.com/simonw/35f0ebf9c1d6df158759\r\n\r\n```\r\ndaemon off;\r\n\r\nevents {\r\n worker_connections 1024;\r\n}\r\n\r\nhttp {\r\n access_log /dev/stdout;\r\n error_log /dev/stderr;\r\n\r\n types {\r\n text/html html htm shtml;\r\n text/css css;\r\n image/gif gif;\r\n image/jpeg jpeg jpg;\r\n application/javascript js;\r\n }\r\n\r\n server {\r\n listen 8002;\r\n index index.html;\r\n root app;\r\n }\r\n}\r\n```\r\n```\r\nnginx -p `pwd` -c `pwd`/nginx.conf\r\n```\r\n\r\n", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 722674708, "label": "Figure out how to run an environment that exercises the base_url proxy setting"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/issues/1024#issuecomment-709598324", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/1024", "id": 709598324, "node_id": "MDEyOklzc3VlQ29tbWVudDcwOTU5ODMyNA==", "user": {"value": 9599, "label": "simonw"}, "created_at": "2020-10-15T21:23:33Z", "updated_at": "2020-10-15T21:26:55Z", "author_association": "OWNER", "body": "Combining these two examples, here's the config file I am going to use for this. I'll save this as `nginx.conf`:\r\n```\r\ndaemon off;\r\n\r\nevents {\r\n worker_connections 1024;\r\n}\r\n\r\nhttp {\r\n server {\r\n listen 8000;\r\n\r\n location /datasette {\r\n proxy_pass http://127.0.0.1:8001;\r\n proxy_set_header X-Real-IP $remote_addr;\r\n proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;\r\n }\r\n }\r\n}\r\n```\r\nThen start the server with:\r\n```\r\nnginx -p `pwd` -c `pwd`/nginx.conf\r\n```\r\nAnd start Datasette like this:\r\n```\r\ndatasette fixtures.db --config base_url:/datasette/\r\n```", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 722674708, "label": "Figure out how to run an environment that exercises the base_url proxy setting"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/issues/1024#issuecomment-709600335", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/1024", "id": 709600335, "node_id": "MDEyOklzc3VlQ29tbWVudDcwOTYwMDMzNQ==", "user": {"value": 9599, "label": "simonw"}, "created_at": "2020-10-15T21:28:02Z", "updated_at": "2020-10-15T22:25:43Z", "author_association": "OWNER", "body": "This is working OK so far:\r\n\r\n\"fixtures__compound_three_primary_keys__1_001_rows_where_sorted_by_pk2\"\r\n\r\nI'll try crawling it with `wget -r` to see if I get any errors.", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 722674708, "label": "Figure out how to run an environment that exercises the base_url proxy setting"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/issues/1024#issuecomment-709622973", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/1024", "id": 709622973, "node_id": "MDEyOklzc3VlQ29tbWVudDcwOTYyMjk3Mw==", "user": {"value": 9599, "label": "simonw"}, "created_at": "2020-10-15T22:27:31Z", "updated_at": "2020-10-15T22:27:31Z", "author_association": "OWNER", "body": "Here's how I tested it:\r\n```\r\ntime wget -r 'http://localhost:8000/datasette/' 2>&1 | grep -i -C 5 \"failed\\|error\" > /tmp/errors.txt\r\n```\r\nThis wrote out any errors (plus context) to the `errors.txt` log - and reported that the full crawl took 33s.\r\n\r\nHere's what I got in `errors.txt`:\r\n```\r\n\r\n 0K . 71.6M=0s\r\n\r\n2020-10-15 15:23:09 (71.6 MB/s) - \u2018localhost:8000/datasette/index.html\u2019 saved [1276]\r\n\r\nLoading robots.txt; please ignore errors.\r\n--2020-10-15 15:23:09-- http://localhost:8000/robots.txt\r\nReusing existing connection to localhost:8000.\r\nHTTP request sent, awaiting response... 404 Not Found\r\n--\r\n--2020-10-15 15:23:09-- http://localhost:8000/robots.txt\r\nReusing existing connection to localhost:8000.\r\nHTTP request sent, awaiting response... 404 Not Found\r\n2020-10-15 15:23:09 ERROR 404: Not Found.\r\n\r\n--2020-10-15 15:23:09-- http://localhost:8000/datasette/-/static/app.css?b576be\r\nReusing existing connection to localhost:8000.\r\nHTTP request sent, awaiting response... 200 OK\r\nLength: 8563 (8.4K) [text/css]\r\n--\r\n--\r\n2020-10-15 15:23:13 (7.90 MB/s) - \u2018localhost:8000/datasette/fixtures/primary_key_multiple_columns_explicit_label.json?_shape=object\u2019 saved [58]\r\n\r\n--2020-10-15 15:23:13-- http://localhost:8000/-/static-plugins/datasette_cluster_map/datasette-cluster-map.js\r\nReusing existing connection to localhost:8000.\r\nHTTP request sent, awaiting response... 404 Not Found\r\n2020-10-15 15:23:13 ERROR 404: Not Found.\r\n\r\n--2020-10-15 15:23:13-- http://localhost:8000/datasette/fixtures?sql=select+pk%2C+name%2C+address%2C+latitude%2C+longitude+from+roadside_attractions+order+by+pk+limit+101\r\nReusing existing connection to localhost:8000.\r\nHTTP request sent, awaiting response... 200 OK\r\nLength: unspecified [text/html]\r\n--\r\n--\r\n2020-10-15 15:23:13 (84.3 MB/s) - \u2018localhost:8000/datasette/fixtures/roadside_attractions.json?_shape=object\u2019 saved [619]\r\n\r\n--2020-10-15 15:23:13-- http://localhost:8000/datasette/fixtures/%5C%22https://www.openstreetmap.org/copyright%5C%22\r\nReusing existing connection to localhost:8000.\r\nHTTP request sent, awaiting response... 404 Not Found\r\n2020-10-15 15:23:13 ERROR 404: Not Found.\r\n\r\n--2020-10-15 15:23:13-- http://localhost:8000/datasette/fixtures?sql=select+pk%2C+text1%2C+text2%2C+%5Bname+with+.+and+spaces%5D+from+searchable+order+by+pk+limit+101\r\nReusing existing connection to localhost:8000.\r\nHTTP request sent, awaiting response... 200 OK\r\nLength: unspecified [text/html]\r\n--\r\n--\r\n2020-10-15 15:23:14 (28.6 MB/s) - \u2018localhost:8000/datasette/fixtures/searchable_view_configured_by_metadata.json?_shape=array&_nl=on\u2019 saved [180]\r\n\r\n--2020-10-15 15:23:14-- http://localhost:8000/\r\nReusing existing connection to localhost:8000.\r\nHTTP request sent, awaiting response... 404 Not Found\r\n2020-10-15 15:23:14 ERROR 404: Not Found.\r\n\r\n--2020-10-15 15:23:14-- http://localhost:8000/datasette/fixtures?sql=select+pk1%2C+pk2%2C+pk3%2C+content+from+compound_three_primary_keys+order+by+pk1%2C+pk2%2C+pk3+limit+101&_hide_sql=1\r\nReusing existing connection to localhost:8000.\r\nHTTP request sent, awaiting response... 200 OK\r\nLength: unspecified [text/html]\r\n--\r\n--\r\n2020-10-15 15:23:21 (64.1 MB/s) - \u2018localhost:8000/datasette/fixtures.csv?sql=select+pk,+name,+address,+latitude,+longitude+from+roadside_attractions+order+by+pk+limit+101&_size=max\u2019 saved [403]\r\n\r\n--2020-10-15 15:23:21-- http://localhost:8000/datasette/%5C%22https://www.openstreetmap.org/copyright%5C%22\r\nReusing existing connection to localhost:8000.\r\nHTTP request sent, awaiting response... 404 Not Found\r\n2020-10-15 15:23:21 ERROR 404: Not Found.\r\n\r\n--2020-10-15 15:23:21-- http://localhost:8000/datasette/fixtures?sql=select+pk%2C+name%2C+address%2C+latitude%2C+longitude+from+roadside_attractions+order+by+pk+desc+limit+101\r\nReusing existing connection to localhost:8000.\r\nHTTP request sent, awaiting response... 200 OK\r\nLength: unspecified [text/html]\r\n```", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 722674708, "label": "Figure out how to run an environment that exercises the base_url proxy setting"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/issues/1024#issuecomment-709625063", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/1024", "id": 709625063, "node_id": "MDEyOklzc3VlQ29tbWVudDcwOTYyNTA2Mw==", "user": {"value": 9599, "label": "simonw"}, "created_at": "2020-10-15T22:33:22Z", "updated_at": "2020-10-15T22:33:22Z", "author_association": "OWNER", "body": "Of those errors...\r\n\r\n`http://localhost:8000/robots.txt` 404 is fine.\r\n\r\n`http://localhost:8000/datasette/%5C%22https://www.openstreetmap.org/copyright%5C%22` looks to me like a `wget` parsing bug where it got confused by this JavaScript:\r\n\r\n```\r\nwindow.DATASETTE_CLUSTER_MAP_TILE_LAYER_OPTIONS = {\"maxZoom\": 19, \"detectRetina\": true, \"attribution\": \"© OpenStreetMap contributors\"};\r\n```\r\n\r\n`http://localhost:8000/-/static-plugins/datasette_cluster_map/datasette-cluster-map.js` is a real bug. It's a bug in `datasette-cluster-map` but also requires me to solve #988 - mechanism for plugins to construct URLs that obey `base_url`.\r\n\r\nI'm not sure why I'm getting a hit to `http://localhost:8000/` since I wouldn't expect to link to `/` anywhere.", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 722674708, "label": "Figure out how to run an environment that exercises the base_url proxy setting"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/issues/1025#issuecomment-709629920", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/1025", "id": 709629920, "node_id": "MDEyOklzc3VlQ29tbWVudDcwOTYyOTkyMA==", "user": {"value": 9599, "label": "simonw"}, "created_at": "2020-10-15T22:48:20Z", "updated_at": "2020-10-15T22:48:20Z", "author_association": "OWNER", "body": "Also these:\r\n```\r\ndatasette % git grep '\"/' -- '*.html' ':(exclude)*/patterns.html'\r\ndatasette/templates/allow_debug.html:
\r\ndatasette/templates/base.html: \r\ndatasette/templates/error.html: home\r\ndatasette/templates/logout.html:\r\ndatasette/templates/messages_debug.html:\r\ndatasette/templates/query.html: home /\r\n```", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 722724086, "label": "Fix last remaining links to \"/\" that do not respect base_url"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/issues/1025#issuecomment-709632136", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/1025", "id": 709632136, "node_id": "MDEyOklzc3VlQ29tbWVudDcwOTYzMjEzNg==", "user": {"value": 9599, "label": "simonw"}, "created_at": "2020-10-15T22:55:44Z", "updated_at": "2020-10-15T22:55:44Z", "author_association": "OWNER", "body": "It looks like there are also some generated redirect responses that don't take `base_url` into account:\r\n```\r\ndatasette % git grep '\"/' -- '*.py' ':(exclude)*test_*.py' ':(exclude)datasette/app.py'\r\ndatasette/_version.py: for i in cfg.versionfile_source.split(\"/\"):\r\ndatasette/utils/asgi.py: path=\"/\",\r\ndatasette/views/base.py: should_redirect = \"/{}-{}\".format(name, expected)\r\ndatasette/views/base.py: should_redirect += \"/\" + urllib.parse.quote_plus(kwargs[\"table\"])\r\ndatasette/views/base.py: should_redirect += \"/\" + kwargs[\"pk_path\"]\r\ndatasette/views/special.py: response = Response.redirect(\"/\")\r\ndatasette/views/special.py: return Response.redirect(\"/\")\r\ndatasette/views/special.py: response = Response.redirect(\"/\")\r\ndatasette/views/special.py: return Response.redirect(\"/\")\r\n```", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 722724086, "label": "Fix last remaining links to \"/\" that do not respect base_url"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/issues/1025#issuecomment-709632314", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/1025", "id": 709632314, "node_id": "MDEyOklzc3VlQ29tbWVudDcwOTYzMjMxNA==", "user": {"value": 9599, "label": "simonw"}, "created_at": "2020-10-15T22:56:25Z", "updated_at": "2020-10-15T22:56:34Z", "author_association": "OWNER", "body": "That `utils/asgi.py` line is the default path for setting cookies. That should likely take `base_url` into account too:\r\nhttps://github.com/simonw/datasette/blob/4f7c0ebd85ccd8c1853d7aa0147628f7c1b749cc/datasette/utils/asgi.py#L331-L342", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 722724086, "label": "Fix last remaining links to \"/\" that do not respect base_url"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/issues/1026#issuecomment-709636372", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/1026", "id": 709636372, "node_id": "MDEyOklzc3VlQ29tbWVudDcwOTYzNjM3Mg==", "user": {"value": 9599, "label": "simonw"}, "created_at": "2020-10-15T23:09:34Z", "updated_at": "2020-10-15T23:09:34Z", "author_association": "OWNER", "body": "I'm inclined to say that internal requests should ignore `base_url` - since that seems like the right thing for plugins that need to access default Datasette APIs.\r\n\r\nThe one catch here is plugins that might want to proxy the current incoming URL for some reason - where that incoming `request.path` could include the `base_url`.\r\n\r\nActually those should be fine - because it will have been stripped off earlier:\r\n\r\nhttps://github.com/simonw/datasette/blob/4f7c0ebd85ccd8c1853d7aa0147628f7c1b749cc/datasette/app.py#L963-L968", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 722738988, "label": "How should datasette.client interact with base_url"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/issues/1027#issuecomment-709646865", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/1027", "id": 709646865, "node_id": "MDEyOklzc3VlQ29tbWVudDcwOTY0Njg2NQ==", "user": {"value": 9599, "label": "simonw"}, "created_at": "2020-10-15T23:47:08Z", "updated_at": "2020-10-15T23:47:08Z", "author_association": "OWNER", "body": "It should cover both nginx and Apache. nginx config is here: https://github.com/simonw/datasette/issues/1024#issuecomment-709598324", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 722758132, "label": "Add documentation on serving Datasette behind a proxy using base_url"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/issues/1027#issuecomment-709647525", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/1027", "id": 709647525, "node_id": "MDEyOklzc3VlQ29tbWVudDcwOTY0NzUyNQ==", "user": {"value": 9599, "label": "simonw"}, "created_at": "2020-10-15T23:49:51Z", "updated_at": "2020-10-15T23:51:39Z", "author_association": "OWNER", "body": "I'll install Apache on macOS to figure this out using https://formulae.brew.sh/formula/httpd\r\n\r\n`brew install httpd` output this at the end:\r\n\r\n```\r\n==> httpd\r\nDocumentRoot is /usr/local/var/www.\r\n\r\nThe default ports have been set in /usr/local/etc/httpd/httpd.conf to 8080 and in\r\n/usr/local/etc/httpd/extra/httpd-ssl.conf to 8443 so that httpd can run without sudo.\r\n\r\nTo have launchd start httpd now and restart at login:\r\n brew services start httpd\r\nOr, if you don't want/need a background service you can just run:\r\n apachectl start\r\n```", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 722758132, "label": "Add documentation on serving Datasette behind a proxy using base_url"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/issues/690#issuecomment-709497595", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/690", "id": 709497595, "node_id": "MDEyOklzc3VlQ29tbWVudDcwOTQ5NzU5NQ==", "user": {"value": 9599, "label": "simonw"}, "created_at": "2020-10-15T18:04:35Z", "updated_at": "2020-10-15T18:12:15Z", "author_association": "OWNER", "body": "For the table actions: attaching it to a cog icon next to the table name could make sense.\r\n\r\n\"data__faa-wildlife-strikes__26_rows_where_where_AIRPORT____OIL_RIG__sorted_by_rowid_and_Fix_table_name_in_spatialite_example_command_by_jsfenfen_\u00b7_Pull_Request__1022_\u00b7_simonw_datasette\"\r\n\r\nThis is the column action icon at twice the size, color `#666`.", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 573755726, "label": "Mechanism for plugins to add action menu items for various things"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/issues/690#issuecomment-709498425", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/690", "id": 709498425, "node_id": "MDEyOklzc3VlQ29tbWVudDcwOTQ5ODQyNQ==", "user": {"value": 9599, "label": "simonw"}, "created_at": "2020-10-15T18:06:08Z", "updated_at": "2020-10-15T18:06:08Z", "author_association": "OWNER", "body": "And for instance-level actions (linking to `datasette-import-csv` for example) an actions menu anchored against a burger-bar menu icon in the navigation bar.", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 573755726, "label": "Mechanism for plugins to add action menu items for various things"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/issues/690#issuecomment-709499944", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/690", "id": 709499944, "node_id": "MDEyOklzc3VlQ29tbWVudDcwOTQ5OTk0NA==", "user": {"value": 9599, "label": "simonw"}, "created_at": "2020-10-15T18:09:06Z", "updated_at": "2020-10-15T18:09:06Z", "author_association": "OWNER", "body": "I'm going to dedicate this issue to thinking about action menus. #981 added column action menus, others to build could be:\r\n\r\n- Table action menus (for things like configure FTS, edit schema)\r\n- Database action menus (import CSV file into this table)\r\n- Instance action menus (manage users, import CSV into this instance)\r\n- Column action menus (already there, plugins could include extract this column)\r\n- Row action menus?\r\n", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 573755726, "label": "Mechanism for plugins to add action menu items for various things"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/issues/690#issuecomment-709500715", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/690", "id": 709500715, "node_id": "MDEyOklzc3VlQ29tbWVudDcwOTUwMDcxNQ==", "user": {"value": 9599, "label": "simonw"}, "created_at": "2020-10-15T18:10:32Z", "updated_at": "2020-10-15T18:10:32Z", "author_association": "OWNER", "body": "Row action menus are a question mark for me. Adding them to the table page itself could get really noisy - though maybe they're a vertical ... menu at the end of the row? They could also go on the `row.html` template, though that page is rarely used at the moment.\r\n\r\nI'm going to skip row actions for the moment and concentrate on the other four, which I know I have use-cases for.", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 573755726, "label": "Mechanism for plugins to add action menu items for various things"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/issues/838#issuecomment-709588425", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/838", "id": 709588425, "node_id": "MDEyOklzc3VlQ29tbWVudDcwOTU4ODQyNQ==", "user": {"value": 9599, "label": "simonw"}, "created_at": "2020-10-15T21:02:37Z", "updated_at": "2020-10-15T21:02:37Z", "author_association": "OWNER", "body": "Tracking ticket: #1023", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 637395097, "label": "Incorrect URLs when served behind a proxy with base_url set"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/issues/865#issuecomment-709588373", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/865", "id": 709588373, "node_id": "MDEyOklzc3VlQ29tbWVudDcwOTU4ODM3Mw==", "user": {"value": 9599, "label": "simonw"}, "created_at": "2020-10-15T21:02:31Z", "updated_at": "2020-10-15T21:02:31Z", "author_association": "OWNER", "body": "Tracking ticket: #1023", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 644582921, "label": "base_url doesn't seem to work when adding criteria and clicking \"apply\""}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/issues/865#issuecomment-709626786", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/865", "id": 709626786, "node_id": "MDEyOklzc3VlQ29tbWVudDcwOTYyNjc4Ng==", "user": {"value": 9599, "label": "simonw"}, "created_at": "2020-10-15T22:38:38Z", "updated_at": "2020-10-15T22:38:38Z", "author_association": "OWNER", "body": "I managed to recreate proxying using `nginx` in #1024 - but I could not replicate this bug. I did NOT use `ProxyPassReverse` though. I think that may be what caused the problem.\r\n\r\nI'll add a section to the documentation about this shortly.", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 644582921, "label": "base_url doesn't seem to work when adding criteria and clicking \"apply\""}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/issues/865#issuecomment-709633080", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/865", "id": 709633080, "node_id": "MDEyOklzc3VlQ29tbWVudDcwOTYzMzA4MA==", "user": {"value": 9599, "label": "simonw"}, "created_at": "2020-10-15T22:58:51Z", "updated_at": "2020-10-15T22:58:51Z", "author_association": "OWNER", "body": "It looks like there are places where Datasette might return a redirect that doesn't take `base_url` into account - I'm planning on fixing those here, after which I think `ProxyPassReverse` should no longer be necessary. https://github.com/simonw/datasette/issues/1025#issuecomment-709632136", "reactions": "{\"total_count\": 1, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 1, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 644582921, "label": "base_url doesn't seem to work when adding criteria and clicking \"apply\""}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/issues/878#issuecomment-709502889", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/878", "id": 709502889, "node_id": "MDEyOklzc3VlQ29tbWVudDcwOTUwMjg4OQ==", "user": {"value": 9599, "label": "simonw"}, "created_at": "2020-10-15T18:14:34Z", "updated_at": "2020-10-15T18:14:34Z", "author_association": "OWNER", "body": "The `BaseView` class does this for Datasette internals at the moment, but I'm not convinced it works as well as it could.\r\n\r\nI'd like to turn this into a class that is documented and available to plugins as well.", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 648435885, "label": "New pattern for views that return either JSON or HTML, available for plugins"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/issues/878#issuecomment-709503359", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/878", "id": 709503359, "node_id": "MDEyOklzc3VlQ29tbWVudDcwOTUwMzM1OQ==", "user": {"value": 9599, "label": "simonw"}, "created_at": "2020-10-15T18:15:28Z", "updated_at": "2020-10-15T18:15:28Z", "author_association": "OWNER", "body": "I think this is blocking #619", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 648435885, "label": "New pattern for views that return either JSON or HTML, available for plugins"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/issues/894#issuecomment-709505147", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/894", "id": 709505147, "node_id": "MDEyOklzc3VlQ29tbWVudDcwOTUwNTE0Nw==", "user": {"value": 9599, "label": "simonw"}, "created_at": "2020-10-15T18:18:45Z", "updated_at": "2020-10-15T18:50:50Z", "author_association": "OWNER", "body": "This needs querystring parameter design. Some options:\r\n\r\n* `?_sort_clause=cast(mycol+as+integer)` and `?_sort_clause_desc=cast(mycol+as+integer)` - allowing any expression. This would need to be disabled if arbitrary SQL was turned off, similar to the restrictions on `?_where=`.\r\n* `?_sort_numeric=mycol` and `?_sort_numeric_desc=mycol` - this would cast to `real` which would work on integer values as well. It could be allowed even when arbitrary SQL was disabled.", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 657572753, "label": "?sort=colname~numeric to sort by by column cast to real"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/issues/894#issuecomment-709505608", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/894", "id": 709505608, "node_id": "MDEyOklzc3VlQ29tbWVudDcwOTUwNTYwOA==", "user": {"value": 9599, "label": "simonw"}, "created_at": "2020-10-15T18:19:35Z", "updated_at": "2020-10-15T18:19:35Z", "author_association": "OWNER", "body": "I could even let plugins define new sort types. Imagine a plugin that enables this:\r\n\r\n`?_sort_date_desc=mycol` - where it knows how to handle specific date formats, or even uses `dateutil.parser.parse`.", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 657572753, "label": "?sort=colname~numeric to sort by by column cast to real"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/issues/894#issuecomment-709505953", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/894", "id": 709505953, "node_id": "MDEyOklzc3VlQ29tbWVudDcwOTUwNTk1Mw==", "user": {"value": 9599, "label": "simonw"}, "created_at": "2020-10-15T18:20:13Z", "updated_at": "2020-10-15T18:20:13Z", "author_association": "OWNER", "body": "Sorting by date when the column has a junk date format in it is such a column need it should maybe ship in Datasette by default - though I've been trying to avoid adding heavy dependencies like `dateutil` if I can get away with it.", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 657572753, "label": "?sort=colname~numeric to sort by by column cast to real"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/issues/894#issuecomment-709509635", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/894", "id": 709509635, "node_id": "MDEyOklzc3VlQ29tbWVudDcwOTUwOTYzNQ==", "user": {"value": 9599, "label": "simonw"}, "created_at": "2020-10-15T18:24:57Z", "updated_at": "2020-10-15T18:24:57Z", "author_association": "OWNER", "body": "This does feel like a weird plugin hook just because there aren't really THAT many different use-cases that plugins could solve. The ones I can think of are:\r\n\r\n- Sort numeric\r\n- Sort by parsed date\r\n- Sort by FTS rank\r\n\r\nCould this work if I just allow `_sort_clause=`?\r\n\r\nOne possible solution for the no-arbitrary-SQL case: users can define sort orders in `metadata.json/yml`. So if you want to enable sort-by-distance without enabling arbitrary SQL you could add something like this:\r\n\r\n```yaml\r\ndatabases:\r\n mydb:\r\n tables:\r\n museums:\r\n sort_clause: bm25(fts)\r\n```", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 657572753, "label": "?sort=colname~numeric to sort by by column cast to real"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/issues/894#issuecomment-709510422", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/894", "id": 709510422, "node_id": "MDEyOklzc3VlQ29tbWVudDcwOTUxMDQyMg==", "user": {"value": 9599, "label": "simonw"}, "created_at": "2020-10-15T18:26:25Z", "updated_at": "2020-10-15T18:26:25Z", "author_association": "OWNER", "body": "There's something interesting about figuring out which sort options should be offered in the column actions menu.\r\n\r\nTwo options:\r\n\r\n- Try to detect if a text column is all-integers or all-floats, either by scanning the entire table (if it's small enough) or by scanning the first X rows, where X might be the size of the first page or maybe the first 1,000 or similar.\r\n- Could also let users define this in `metadata.yml` for the table.", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 657572753, "label": "?sort=colname~numeric to sort by by column cast to real"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/issues/894#issuecomment-709511399", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/894", "id": 709511399, "node_id": "MDEyOklzc3VlQ29tbWVudDcwOTUxMTM5OQ==", "user": {"value": 9599, "label": "simonw"}, "created_at": "2020-10-15T18:28:09Z", "updated_at": "2020-10-15T18:28:09Z", "author_association": "OWNER", "body": "The simplest solution would be for Python code to scan all of the visible values on the current page and show the column action for \"sort by this numeric\" based purely on that. I already do that in the JavaScript for \"are there any blank values in the first page?\" here:\r\n\r\nhttps://github.com/simonw/datasette/blob/4f7c0ebd85ccd8c1853d7aa0147628f7c1b749cc/datasette/static/table.js#L106-L118\r\n\r\n", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 657572753, "label": "?sort=colname~numeric to sort by by column cast to real"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/issues/894#issuecomment-709513483", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/894", "id": 709513483, "node_id": "MDEyOklzc3VlQ29tbWVudDcwOTUxMzQ4Mw==", "user": {"value": 9599, "label": "simonw"}, "created_at": "2020-10-15T18:31:56Z", "updated_at": "2020-10-15T18:31:56Z", "author_association": "OWNER", "body": "I think the first version of this feature involves implementing `?_sort_numeric=col` and `?_sort_numeric_desc=col` plus the JavaScript to detect if those values should be shown in the column actions menu.\r\n\r\nOne question: how to reflect that this is happening in the current sort UI. This menu here for example:\r\n\r\n\"fixtures__compound_three_primary_keys__1_001_rows_where_sorted_by_pk3_descending\"\r\n\r\nAnd this interface: how should it indicate that a text is currently sorted numerically v.s. sorted alphabetically, and allow the user to switch from one to the other?\r\n\r\n\"fixtures__sortable__201_rows_where_sorted_by_sortable_with_nulls_descending\"\r\n", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 657572753, "label": "?sort=colname~numeric to sort by by column cast to real"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/issues/894#issuecomment-709524123", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/894", "id": 709524123, "node_id": "MDEyOklzc3VlQ29tbWVudDcwOTUyNDEyMw==", "user": {"value": 9599, "label": "simonw"}, "created_at": "2020-10-15T18:50:25Z", "updated_at": "2020-10-15T18:50:25Z", "author_association": "OWNER", "body": "For the \"Sort by X\" select menu case... I could automatically expand that menu to contain extra options for \"Sort numerically by X\" for each TEXT column in the table. That's a pretty good option.\r\n\r\nFor the action cog menu, I can add the extra options to the cog menu - and rely on the fact that the title of the page will say \"Sorted numerically by colname descending\".", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 657572753, "label": "?sort=colname~numeric to sort by by column cast to real"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/issues/894#issuecomment-709525082", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/894", "id": 709525082, "node_id": "MDEyOklzc3VlQ29tbWVudDcwOTUyNTA4Mg==", "user": {"value": 9599, "label": "simonw"}, "created_at": "2020-10-15T18:51:59Z", "updated_at": "2020-10-15T18:51:59Z", "author_association": "OWNER", "body": "This is enough of a design to build a working prototype.", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 657572753, "label": "?sort=colname~numeric to sort by by column cast to real"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/issues/894#issuecomment-709531343", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/894", "id": 709531343, "node_id": "MDEyOklzc3VlQ29tbWVudDcwOTUzMTM0Mw==", "user": {"value": 9599, "label": "simonw"}, "created_at": "2020-10-15T19:03:12Z", "updated_at": "2020-10-15T19:03:12Z", "author_association": "OWNER", "body": "The Sort by `