由于编码和转义字符问题,Http请求结束为错误请求 [英] Http request ending as bad request due to Encoding and Escape character issues

查看:103
本文介绍了由于编码和转义字符问题,Http请求结束为错误请求的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

注意:代码在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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆