Title: WebCmdlets should read the encoding of Content-Type application/json per RFC · Issue #5530 · PowerShell/PowerShell · GitHub
Open Graph Title: WebCmdlets should read the encoding of Content-Type application/json per RFC · Issue #5530 · PowerShell/PowerShell
X Title: WebCmdlets should read the encoding of Content-Type application/json per RFC · Issue #5530 · PowerShell/PowerShell
Description: Steps to reproduce Invoke-RestMethod 'http://api.forismatic.com/api/1.0/?method=getQuote&format=json&lang=ru' -verbose Expected behavior It should detect the utf-8 encoding, and produce the same output as this: $resp = Invoke-WebRequest ...
Open Graph Description: Steps to reproduce Invoke-RestMethod 'http://api.forismatic.com/api/1.0/?method=getQuote&format=json&lang=ru' -verbose Expected behavior It should detect the utf-8 encoding, and produce the same ou...
X Description: Steps to reproduce Invoke-RestMethod 'http://api.forismatic.com/api/1.0/?method=getQuote&format=json&lang=ru' -verbose Expected behavior It should detect the utf-8 encoding, and pro...
Opengraph URL: https://github.com/PowerShell/PowerShell/issues/5530
X: @github
Domain: github.com
{"@context":"https://schema.org","@type":"DiscussionForumPosting","headline":"WebCmdlets should read the encoding of Content-Type application/json per RFC","articleBody":"Steps to reproduce\r\n------------------\r\n\r\n```powershell\r\nInvoke-RestMethod 'http://api.forismatic.com/api/1.0/?method=getQuote\u0026format=json\u0026lang=ru' -verbose\r\n```\r\n\r\nExpected behavior\r\n-----------------\r\n\r\nIt should **detect** the utf-8 encoding, and produce the same output as this:\r\n\r\n```posh\r\n$resp = Invoke-WebRequest 'http://api.forismatic.com/api/1.0/?method=getQuote\u0026format=json\u0026lang=ru'\r\n$char = $resp.RawContentStream.ToArray()\r\n$str = [Text.Encoding]::UTF8.GetString($char)\r\nConvertFrom-Json $str\r\n```\r\n\r\ni.e. something like this:\r\n\r\n```none\r\nVERBOSE: GET http://api.forismatic.com/api/1.0/?method=getQuote\u0026format=json with 0-byte payload\r\nVERBOSE: received 536-byte response of content type application/json\r\nVERBOSE: Content encoding: utf-8\r\n\r\nquoteText : Именно внутренний диалог прижимает к земле людей в повседневной жизни. Мир для нас такой-то и такой-то или этакий и этакий лишь потому, что мы сами себе говорим о нем, что он такой-то и такой-то или этакий и этакий.\r\nquoteAuthor : Карлос Кастанеда\r\nsenderName :\r\nsenderLink :\r\nquoteLink : http://forismatic.com/ru/6309006412/\r\n```\r\n\r\nActual behavior\r\n---------------\r\n\r\nIt falls back to iso-8859-1 encoding and produces gobbledygook with a lot of Ð's in it. Also, it utterly fails to produce a number for the `#-byte response` string in the verbose output.\r\n\r\n```none\r\nVERBOSE: GET http://api.forismatic.com/api/1.0/?method=getQuote\u0026format=json with 0-byte payload\r\nVERBOSE: received -byte response of content type application/json\r\nVERBOSE: Content encoding: iso-8859-1\r\n\r\nquoteText : Ðо вÑÑÐºÐ¾Ð¼Ñ Ð¿ÑибежиÑÑ Ð¾Ð±ÑаÑаÑÑÑÑ Ð»Ñди, мÑÑимÑе ÑÑÑаÑ
ом: к гоÑам\r\n и к леÑам, к деÑевÑÑм в ÑоÑе, к гÑобниÑам.\r\nquoteAuthor : ÐÑдда ÐаÑÑама\r\nsenderName :\r\nsenderLink :\r\nquoteLink : http://forismatic.com/ru/804c7d14d9/\r\n```\r\n\r\nDiscussion\r\n----------\r\n\r\nWhen calling an HTTP endpoint that returns a header: `Content-Type: application/json` the WebCmdlets are **incorrectly** defaulting to `iso-8859-1` rather than a proper unicode encoding, and are *disregarding* the application/json RFC's simple specification for how to determine the content encoding.\r\n\r\n1. The JSON standard [ECMA-404 (PDF)](http://ecma-international.org/publications/files/ECMA-ST/ECMA-404.pdf) clearly states that JSON must be unicode\r\n2. The [application/json RFC (in section 3)](https://tools.ietf.org/html/rfc4627#section-3) clearly indicates how the encoding should be determined from the first 4 bytes of the content.\r\n\r\n**NOTE:** Please don't work around this by just defaulting to utf-8. I'm sure that 90% of the time, you could probably get away with that, but it's not actually correct, and the RFC implementation is _trivial_.\r\n\r\n**ALSO NOTE:** The WebCmdlets *do* respect the [`; charset=utf-8`](https://github.com/PowerShell/PowerShell/blob/f5f3fab1ea8a51dd2e5d34e0e580ab39176eb696/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/StreamHelper.cs#L442) attribute if it's present on the content-type header -- which makes sense, but isn't technically standards compliant for an `application/*` content-type, as far as I can tell.\r\n\r\nTo get started: [`ProcessResponse`](https://github.com/PowerShell/PowerShell/blob/f5f3fab1ea8a51dd2e5d34e0e580ab39176eb696/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/CoreCLR/InvokeRestMethodCommand.CoreClr.cs#L54) and [`TryGetEncoding`](https://github.com/PowerShell/PowerShell/blob/f5f3fab1ea8a51dd2e5d34e0e580ab39176eb696/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/StreamHelper.cs#L411) \r\n\r\nSee also #5528 which was a specific instance of this problem. @lipkau was incorrectly convinced by early responders that the problem was in the webserver, but it's actually in PowerShell's cmdlets. If you invoke the rest API against the Atlassian wiki, you can see the problem happening in the Verbose stream:\r\n\r\n```posh\r\n$r = IRM $url -Credential $mycred -Authentication basic -Verbose\r\nVERBOSE: GET https://powershell.atlassian.net/wiki/rest/api/content/13009245?expand=space,version with 0-byte payload\r\nVERBOSE: received -byte response of content type application/json\r\nVERBOSE: Content encoding: iso-8859-1\r\n```\r\n\r\nThe content is **actually** correctly utf-8 encoded (as you could tell from the positions of the nulls in the first 4 bytes), and iso-8859-1 is _**never** a valid encoding for application/json_, period.\r\n\r\n```plain\r\nPS C:\\Program Files\\PowerShell\\6.0.0-rc\u003e $PSVersionTable\r\n\r\nName Value\r\n---- -----\r\nPSVersion 6.0.0-rc\r\nPSEdition Core\r\nGitCommitId v6.0.0-rc\r\nOS Microsoft Windows 10.0.15063\r\nPlatform Win32NT\r\nPSCompatibleVersions {1.0, 2.0, 3.0, 4.0...}\r\nPSRemotingProtocolVersion 2.3\r\nSerializationVersion 1.1.0.1\r\nWSManStackVersion 3.0\r\n```","author":{"url":"https://github.com/Jaykul","@type":"Person","name":"Jaykul"},"datePublished":"2017-11-22T22:33:19.000Z","interactionStatistic":{"@type":"InteractionCounter","interactionType":"https://schema.org/CommentAction","userInteractionCount":15},"url":"https://github.com/5530/PowerShell/issues/5530"}
| route-pattern | /_view_fragments/issues/show/:user_id/:repository/:id/issue_layout(.:format) |
| route-controller | voltron_issues_fragments |
| route-action | issue_layout |
| fetch-nonce | v2:e091aaa0-3a59-e1dd-39a3-18dbc9680e86 |
| current-catalog-service-hash | 81bb79d38c15960b92d99bca9288a9108c7a47b18f2423d0f6438c5b7bcd2114 |
| request-id | BD40:996A:50BE90D:71D7A0A:6A57195A |
| html-safe-nonce | fbfbdba9d314680c7f49177b3ea8678eafece3ffdda2e5197c6db6e258cf44f7 |
| visitor-payload | eyJyZWZlcnJlciI6IiIsInJlcXVlc3RfaWQiOiJCRDQwOjk5NkE6NTBCRTkwRDo3MUQ3QTBBOjZBNTcxOTVBIiwidmlzaXRvcl9pZCI6IjQ1NjkxNDAzNzM3MDE5ODM2MiIsInJlZ2lvbl9lZGdlIjoiaWFkIiwicmVnaW9uX3JlbmRlciI6ImlhZCJ9 |
| visitor-hmac | 1f272d7b106114b1aff9741e4790b86b606e38cfca0f4fec06f4b45ea8361fa7 |
| hovercard-subject-tag | issue:276222375 |
| github-keyboard-shortcuts | repository,issues,copilot |
| google-site-verification | Apib7-x98H0j5cPqHWwSMm6dNU4GmODRoqxLiDzdx9I |
| octolytics-url | https://collector.github.com/github/collect |
| analytics-location | / |
| fb:app_id | 1401488693436528 |
| apple-itunes-app | app-id=1477376905, app-argument=https://github.com/_view_fragments/issues/show/PowerShell/PowerShell/5530/issue_layout |
| twitter:image | https://opengraph.githubassets.com/ec15b7675cd39e3ba04b22a8ee749347a03727036851810f10796f0f99ba2cff/PowerShell/PowerShell/issues/5530 |
| twitter:card | summary_large_image |
| og:image | https://opengraph.githubassets.com/ec15b7675cd39e3ba04b22a8ee749347a03727036851810f10796f0f99ba2cff/PowerShell/PowerShell/issues/5530 |
| og:image:alt | Steps to reproduce Invoke-RestMethod 'http://api.forismatic.com/api/1.0/?method=getQuote&format=json&lang=ru' -verbose Expected behavior It should detect the utf-8 encoding, and produce the same ou... |
| og:image:width | 1200 |
| og:image:height | 600 |
| og:site_name | GitHub |
| og:type | object |
| og:author:username | Jaykul |
| hostname | github.com |
| expected-hostname | github.com |
| None | 4e7a7296a3830877cf21a6ad2a972c9e618a48915e03966cf0c53eb08e5aad98 |
| turbo-cache-control | no-preview |
| go-import | github.com/PowerShell/PowerShell git https://github.com/PowerShell/PowerShell.git |
| octolytics-dimension-user_id | 11524380 |
| octolytics-dimension-user_login | PowerShell |
| octolytics-dimension-repository_id | 49609581 |
| octolytics-dimension-repository_nwo | PowerShell/PowerShell |
| octolytics-dimension-repository_public | true |
| octolytics-dimension-repository_is_fork | false |
| octolytics-dimension-repository_network_root_id | 49609581 |
| octolytics-dimension-repository_network_root_nwo | PowerShell/PowerShell |
| turbo-body-classes | logged-out env-production page-responsive |
| disable-turbo | false |
| browser-stats-url | https://api.github.com/_private/browser/stats |
| browser-errors-url | https://api.github.com/_private/browser/errors |
| release | 2576d1f0198cf1588faf2edf27f1ed120903be10 |
| ui-target | full |
| theme-color | #1e2327 |
| color-scheme | light dark |
Links:
Viewport: width=device-width