405. That\u2019s an error.\r\n
The request method OPTIONS
is inappropriate for the URL /
. That\u2019s all we know.\r\n~ % curl -X OPTIONS https://www.mozilla.org/ -i\r\nHTTP/2 405 \r\ncontent-type: text/html; charset=utf-8\r\ncontent-length: 0\r\nserver: meinheld/1.0.2\r\ndate: Wed, 30 Nov 2022 18:18:38 GMT\r\nallow: GET, HEAD\r\nx-frame-options: DENY\r\ncontent-security-policy: child-src 'self' *.mozilla.net *.mozilla.org *.mozilla.com www.googletagmanager.com www.google-analytics.com www.youtube-nocookie.com trackertest.org www.surveygizmo.com accounts.firefox.com accounts.firefox.com.cn www.youtube.com; connect-src 'self' *.mozilla.net *.mozilla.org *.mozilla.com www.googletagmanager.com www.google-analytics.com region1.google-analytics.com logs.convertexperiments.com 1003350.metrics.convertexperiments.com 1003343.metrics.convertexperiments.com sentry.prod.mozaws.net o1069899.sentry.io o1069899.ingest.sentry.io https://accounts.firefox.com/ stage.cjms.nonprod.cloudops.mozgcp.net cjms.services.mozilla.com; frame-src 'self' *.mozilla.net *.mozilla.org *.mozilla.com www.googletagmanager.com www.google-analytics.com www.youtube-nocookie.com trackertest.org www.surveygizmo.com accounts.firefox.com accounts.firefox.com.cn www.youtube.com; script-src 'self' *.mozilla.net *.mozilla.org *.mozilla.com 'unsafe-inline' 'unsafe-eval' www.googletagmanager.com www.google-analytics.com tagmanager.google.com www.youtube.com s.ytimg.com cdn-3.convertexperiments.com app.convert.com data.track.convertexperiments.com 1003350.track.convertexperiments.com 1003343.track.convertexperiments.com; img-src 'self' *.mozilla.net *.mozilla.org *.mozilla.com data: mozilla.org www.googletagmanager.com www.google-analytics.com adservice.google.com adservice.google.de adservice.google.dk creativecommons.org cdn-3.convertexperiments.com logs.convertexperiments.com images.ctfassets.net ad.doubleclick.net; style-src 'self' *.mozilla.net *.mozilla.org *.mozilla.com 'unsafe-inline' app.convert.com; default-src 'self' *.mozilla.net *.mozilla.org *.mozilla.com; font-src 'self'\r\ncache-control: max-age=600\r\nexpires: Wed, 30 Nov 2022 18:28:38 GMT\r\nx-backend-server: bedrock-prod-web-b95bc569d-grd25.iowa-a\r\nstrict-transport-security: max-age=31536000\r\nx-content-type-options: nosniff\r\nx-xss-protection: 1; mode=block\r\nreferrer-policy: strict-origin-when-cross-origin\r\nvia: 1.1 google, 1.1 6c90b631453c435bd0022caa657b67e8.cloudfront.net (CloudFront)\r\nx-cache: Error from cloudfront\r\nx-amz-cf-pop: SFO5-P2\r\nx-amz-cf-id: A6-9mLztaE2tz840CbV9bXYiBMZRKEamDj6jGGEl1U7sg8egWfsDqg==\r\n\r\n~ % curl -X OPTIONS https://example.com -i \r\nHTTP/2 200 \r\nallow: OPTIONS, GET, HEAD, POST\r\ncache-control: max-age=604800\r\ncontent-type: text/html; charset=UTF-8\r\ndate: Wed, 30 Nov 2022 18:18:59 GMT\r\nexpires: Wed, 07 Dec 2022 18:18:59 GMT\r\nserver: EOS (vny/0451)\r\ncontent-length: 0\r\n```", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 1469973742, "label": "Make sure CORS works for write APIs"}, "performed_via_github_app": null}
{"html_url": "https://github.com/simonw/datasette/issues/1922#issuecomment-1332561813", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/1922", "id": 1332561813, "node_id": "IC_kwDOBm6k_c5PbUeV", "user": {"value": 9599, "label": "simonw"}, "created_at": "2022-11-30T18:20:05Z", "updated_at": "2022-11-30T18:20:05Z", "author_association": "OWNER", "body": "Weird, GitHub reply with a 404!\r\n```\r\n~ % curl -X OPTIONS https://github.com/ -i\r\nHTTP/2 404 \r\nserver: GitHub.com\r\ndate: Wed, 30 Nov 2022 18:19:39 GMT\r\ncontent-type: text/html; charset=utf-8\r\ncontent-length: 0\r\nstrict-transport-security: max-age=31536000; includeSubdomains; preload\r\nx-frame-options: deny\r\nx-content-type-options: nosniff\r\nx-xss-protection: 0\r\nreferrer-policy: origin-when-cross-origin, strict-origin-when-cross-origin\r\ncontent-security-policy: default-src 'none'; base-uri 'self'; block-all-mixed-content; child-src github.com/assets-cdn/worker/ gist.github.com/assets-cdn/worker/; connect-src 'self' uploads.github.com objects-origin.githubusercontent.com www.githubstatus.com collector.github.com raw.githubusercontent.com api.github.com github-cloud.s3.amazonaws.com github-production-repository-file-5c1aeb.s3.amazonaws.com github-production-upload-manifest-file-7fdce7.s3.amazonaws.com github-production-user-asset-6210df.s3.amazonaws.com cdn.optimizely.com logx.optimizely.com/v1/events; font-src github.githubassets.com; form-action 'self' github.com gist.github.com objects-origin.githubusercontent.com; frame-ancestors 'none'; frame-src viewscreen.githubusercontent.com notebooks.githubusercontent.com; img-src 'self' data: github.githubassets.com media.githubusercontent.com camo.githubusercontent.com identicons.github.com avatars.githubusercontent.com github-cloud.s3.amazonaws.com objects.githubusercontent.com objects-origin.githubusercontent.com secured-user-images.githubusercontent.com/ opengraph.githubassets.com github-production-user-asset-6210df.s3.amazonaws.com customer-stories-feed.github.com spotlights-feed.github.com; manifest-src 'self'; media-src github.com user-images.githubusercontent.com/ secured-user-images.githubusercontent.com/; script-src github.githubassets.com; style-src 'unsafe-inline' github.githubassets.com; worker-src github.com/assets-cdn/worker/ gist.github.com/assets-cdn/worker/\r\nvary: Accept-Encoding, Accept, X-Requested-With\r\nx-github-request-id: DD6B:5ACA:102E8A6:1164A99:63879EBB\r\n```", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 1469973742, "label": "Make sure CORS works for write APIs"}, "performed_via_github_app": null}
{"html_url": "https://github.com/simonw/datasette/issues/1922#issuecomment-1332572453", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/1922", "id": 1332572453, "node_id": "IC_kwDOBm6k_c5PbXEl", "user": {"value": 9599, "label": "simonw"}, "created_at": "2022-11-30T18:30:38Z", "updated_at": "2022-11-30T18:30:54Z", "author_association": "OWNER", "body": "Started a conversation about how OPTIONS should work on Mastodon: https://fedi.simonwillison.net/@simon/109434148676475291", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 1469973742, "label": "Make sure CORS works for write APIs"}, "performed_via_github_app": null}
{"html_url": "https://github.com/simonw/datasette/issues/1922#issuecomment-1332580395", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/1922", "id": 1332580395, "node_id": "IC_kwDOBm6k_c5PbZAr", "user": {"value": 9599, "label": "simonw"}, "created_at": "2022-11-30T18:38:22Z", "updated_at": "2022-11-30T18:38:22Z", "author_association": "OWNER", "body": "> [@simon](https://fedi.simonwillison.net/@simon) IMO, it should always be a 2XX series response, typically with no content & an extra `Allow` header with a list of HTTP verbs it responds to.\r\n\r\nhttps://mastodon.social/@daniellindsley/109434186252099323", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 1469973742, "label": "Make sure CORS works for write APIs"}, "performed_via_github_app": null}
{"html_url": "https://github.com/simonw/datasette/issues/1922#issuecomment-1332585861", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/1922", "id": 1332585861, "node_id": "IC_kwDOBm6k_c5PbaWF", "user": {"value": 9599, "label": "simonw"}, "created_at": "2022-11-30T18:43:46Z", "updated_at": "2022-11-30T18:43:46Z", "author_association": "OWNER", "body": "Here's what Django Rest Framework does: https://github.com/encode/django-rest-framework/blob/1ae812ea209392ad76cc5d2f35f9f7fb337f63e4/rest_framework/views.py#L514-L521\r\n\r\n```python\r\n def options(self, request, *args, **kwargs):\r\n \"\"\"\r\n Handler method for HTTP 'OPTIONS' request.\r\n \"\"\"\r\n if self.metadata_class is None:\r\n return self.http_method_not_allowed(request, *args, **kwargs)\r\n data = self.metadata_class().determine_metadata(request, self)\r\n return Response(data, status=status.HTTP_200_OK)\r\n```\r\nThat default `determine_metadata` method looks like this: https://github.com/encode/django-rest-framework/blob/1ae812ea209392ad76cc5d2f35f9f7fb337f63e4/rest_framework/metadata.py#L61-L71\r\n\r\n```python\r\n def determine_metadata(self, request, view):\r\n metadata = OrderedDict()\r\n metadata['name'] = view.get_view_name()\r\n metadata['description'] = view.get_view_description()\r\n metadata['renders'] = [renderer.media_type for renderer in view.renderer_classes]\r\n metadata['parses'] = [parser.media_type for parser in view.parser_classes]\r\n if hasattr(view, 'get_serializer'):\r\n actions = self.determine_actions(request, view)\r\n if actions:\r\n metadata['actions'] = actions\r\n return metadata\r\n```", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 1469973742, "label": "Make sure CORS works for write APIs"}, "performed_via_github_app": null}
{"html_url": "https://github.com/simonw/datasette/issues/1922#issuecomment-1332688245", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/1922", "id": 1332688245, "node_id": "IC_kwDOBm6k_c5PbzV1", "user": {"value": 9599, "label": "simonw"}, "created_at": "2022-11-30T20:15:08Z", "updated_at": "2022-11-30T20:15:08Z", "author_association": "OWNER", "body": "Still getting a CORS error:\r\n\r\n\r\n\r\nMy hunch is this is because I'm not sending `Access-Control-Allow-Methods: GET,HEAD,POST`.", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 1469973742, "label": "Make sure CORS works for write APIs"}, "performed_via_github_app": null}
{"html_url": "https://github.com/simonw/datasette/issues/1922#issuecomment-1332689547", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/1922", "id": 1332689547, "node_id": "IC_kwDOBm6k_c5PbzqL", "user": {"value": 9599, "label": "simonw"}, "created_at": "2022-11-30T20:16:21Z", "updated_at": "2022-11-30T20:16:46Z", "author_association": "OWNER", "body": "That notebook:\r\n```javascript\r\nviewof token = Inputs.text({\r\n label: \"Your API token\"\r\n})\r\n```\r\n```javascript\r\nviewof createResponse = Inputs.button(\"Create table\", {\r\n value: null,\r\n reduce: async () => {\r\n const response = await fetch(\r\n \"https://latest.datasette.io/ephemeral/-/create\",\r\n {\r\n method: \"POST\",\r\n mode: \"cors\",\r\n headers: {\r\n Authorization: `Bearer {$token}`,\r\n \"Content-Type\": \"application/json\"\r\n },\r\n body: JSON.stringify({\r\n table: \"my_new_table\",\r\n row: {\r\n task: \"Demonstrate a JSON creation from another domain\"\r\n }\r\n })\r\n }\r\n );\r\n return await response.json();\r\n }\r\n})\r\n```\r\nBased on this tip: https://talk.observablehq.com/t/best-pattern-for-click-here-to-submit-your-results-to-an-api-backend/7353/3", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 1469973742, "label": "Make sure CORS works for write APIs"}, "performed_via_github_app": null}
{"html_url": "https://github.com/simonw/datasette/issues/1922#issuecomment-1332698636", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/1922", "id": 1332698636, "node_id": "IC_kwDOBm6k_c5Pb14M", "user": {"value": 9599, "label": "simonw"}, "created_at": "2022-11-30T20:25:50Z", "updated_at": "2022-11-30T20:25:50Z", "author_association": "OWNER", "body": "I just shipped this:\r\n\r\n Access-Control-Allow-Methods: GET, POST, HEAD, OPTIONS\r\n\r\nI'll try this out on `latest.datasette.io` - but I need to research more to check if this is a safe thing to do or not.", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 1469973742, "label": "Make sure CORS works for write APIs"}, "performed_via_github_app": null}
{"html_url": "https://github.com/simonw/datasette/issues/1922#issuecomment-1332855687", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/1922", "id": 1332855687, "node_id": "IC_kwDOBm6k_c5PccOH", "user": {"value": 9599, "label": "simonw"}, "created_at": "2022-11-30T23:09:31Z", "updated_at": "2022-11-30T23:09:31Z", "author_association": "OWNER", "body": "Still getting a CORS header.\r\n\r\nI tried it in Chrome, which outputs helpful messages to the console:\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": 1469973742, "label": "Make sure CORS works for write APIs"}, "performed_via_github_app": null}
{"html_url": "https://github.com/simonw/datasette/issues/1922#issuecomment-1332903011", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/1922", "id": 1332903011, "node_id": "IC_kwDOBm6k_c5Pcnxj", "user": {"value": 9599, "label": "simonw"}, "created_at": "2022-11-30T23:45:29Z", "updated_at": "2022-11-30T23:45:29Z", "author_association": "OWNER", "body": "That worked for the preflight request - got this now:\r\n\r\n\r\n\r\nSo it looks like error responses (in this case for permission denied) are missing CORS headers.", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 1469973742, "label": "Make sure CORS works for write APIs"}, "performed_via_github_app": null}