由于编码和转义字符问题,Http请求结束为错误请求 [英] Http request ending as bad request due to Encoding and Escape character issues
问题描述
注意:代码在F#中,但标记了C#,因为它是从.strong转换为json时在.net上的通用编码和转义字符问题,请查看输出在页面底部。
以下请求最终导致了错误请求,请特别注意任何差异在 Encoding.Default.GetString
中,然后特别地编码回 System.Text.Encoding.ASCII.GetBytes
。 / p>
上下文:对象已序列化并写入PUT请求的主体,并最终以错误请求400结束。JSON已正确序列化,我可以看到带有 Console.WriteLine
我从
添加对Newtonsoft.Json NuGet包的引用,并将其添加到F#文件的顶部:
打开Newtonsoft.Json
然后尝试使用更新方法的主体(它显式使用UTF-8编码,而不是ASCII或平台默认值):
let url = http://example.com
让序列化d = JsonConvert.SerializeObject(schema)
let data:byte [] = Encoding.UTF8.GetBytes(serialized)
let request = WebRequest.Create(url):?> HttpWebRequest
request.Method<- PUT
request.ContentType<-- application / json; charset = UTF-8
request.Accept<-- application / json; charset = UTF-8
request.ContentLength<-(int64)data.Length
use requestStream = request.GetRequestStream()
requestStream.Write(data,0, data.Length)
requestStream.Flush()
requestStream.Close()
let response = request.GetResponse():?> HttpWebResponse
use reader = new StreamReader(response.GetResponseStream(),Encoding.UTF8)
let result = JsonConvert.DeserializeObject< Article>(reader.ReadToEnd())
reader .Close()
响应.Close()
请求.Abort()
结果
除非您使用的服务器也使用DataContractJsonSerializer(将 /转义为 \ /),否则使用Newtonsoft可能会更好。而且在UTF-8编码问题出现之前解决它也没有什么坏处(看起来好像您在发送/接收任何非ASCII文本,但这在现实世界中不可避免地会发生)。
Note: Code is in F# but tagging C# because it's a general encoding and escape character issue across .net while converting from object to json, please look at the output at the bottom of the page.
Following request is ending up a bad request, please have a look at any discrepancies especially in the Encoding.Default.GetString
and then encoding back into System.Text.Encoding.ASCII.GetBytes
especially.
Context: An object is serialized and written to the body of the PUT request and is ended up as bad request 400. JSON is serialized correctly and I can see the string with Console.WriteLine
I took the JSON encoding example from F# snippets
let update (schema: Article) : Article =
let url = "http://example.com"
use memoryStream = new MemoryStream()
(new DataContractJsonSerializer(typeof<Article>)).WriteObject(memoryStream, schema)
let d = Encoding.Default.GetString(memoryStream.ToArray()) // I suspect problem may be here
let data : byte[] = System.Text.Encoding.ASCII.GetBytes(d); // or here
let request = WebRequest.Create(url) :?> HttpWebRequest
request.Method <- "PUT"
request.ContentType <- "application/json;charset=UTF-8"
request.Accept <- "application/json;charset=UTF-8"
request.ContentLength <- (int64)data.Length
use requestStream = request.GetRequestStream()
requestStream.Write(data, 0, data.Length)
requestStream.Flush()
requestStream.Close()
let response = request.GetResponse() :?> HttpWebResponse
use reader = new StreamReader(response.GetResponseStream())
use memoryStream = new MemoryStream(ASCIIEncoding.Default.GetBytes(reader.ReadToEnd()))
let result = (new DataContractJsonSerializer(typeof<Article>)).ReadObject(memoryStream) :?> Article
reader.Close()
response.Close()
request.Abort()
result
Further Discoveries
I was able to get Charles Proxy up and I saw that forward slashes have been escaped in the output serialized json to the server.
Actual Output: with escaped slashes \ /
\/publication\/d40a4e4c-d6a3-45ae-98b3-924b31d8712a\/altasset\/c42d0df7-a563-4bb5-b7fa-313e6a98032f\/
Expected output: They are supposed to have forward slashes only, no escaping of the characters.
/publication/d40a4e4c-d6a3-45ae-98b3-924b31d8712a....
I guess something causing the character to be escaped in Encoding process, is there a way to fix it?
Edit
I also noticed that memoryStream.ToArray()
returns a byte[]
so instead of going through encodings I also tried the following but it didn't make any difference.
let data : byte[] = memoryStream.ToArray()
requestStream.Write(data, 0, data.Length)
in Charles proxy, I'm seeing Broken pipe message.
Add a reference to the Newtonsoft.Json NuGet package and add this to the top of your F# file:
open Newtonsoft.Json
Then try this as the body of your update method (it uses UTF-8 encoding explicitly rather than ASCII or the platform default):
let url = "http://example.com"
let serialized = JsonConvert.SerializeObject(schema)
let data : byte[] = Encoding.UTF8.GetBytes(serialized)
let request = WebRequest.Create(url) :?> HttpWebRequest
request.Method <- "PUT"
request.ContentType <- "application/json;charset=UTF-8"
request.Accept <- "application/json;charset=UTF-8"
request.ContentLength <- (int64)data.Length
use requestStream = request.GetRequestStream()
requestStream.Write(data, 0, data.Length)
requestStream.Flush()
requestStream.Close()
let response = request.GetResponse() :?> HttpWebResponse
use reader = new StreamReader(response.GetResponseStream(), Encoding.UTF8)
let result = JsonConvert.DeserializeObject<Article>(reader.ReadToEnd())
reader.Close()
response.Close()
request.Abort()
result
Unless the server you're using was also using DataContractJsonSerializer (which escapes "/" as "\/") then you're probably better off with Newtonsoft. And it doesn't hurt to fix the UTF-8 encoding issues before they arise (it didn't look like you were sending/receiving any non-ASCII text but that would inevitably happen in the real world).
这篇关于由于编码和转义字符问题,Http请求结束为错误请求的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!