我有一个简单的代码将数据发布到远程服务器:
def main():
headers = {}
headers['Content-Type'] = 'application/json'
target_url = r'the_url'
data = {"bodyTextPlain": "O estimulante concorrente dos azulzinhos\r\nConhe\u00e7a a nova tend\u00eancia em estimulante masculino e feminino\r\n\r\nEste estimulante ficou conhecido por seus efeitos similares as p\u00edlulas\r\nazuis,\r\ndestacando-se por n\u00e3o possuir contraindica\u00e7\u00e3o ou efeito colateral.\r\n\r\nSucesso de vendas e principal concorrente natural dos azulzinhos,\r\nsua f\u00f3rmula \u00e9 totalmente natural e livre de qu\u00edmicos.\r\n\r\nPossuindo registro no Minist\u00e9rio da Sa\u00fade (ANVISA) e atestado de\r\nautenticidade.\r\n\r\nSaiba mais http://www5.somenteagora.com.br/maca\r\nAdquirindo 3 frascos voc\u00ea ganha +1 de brinde. Somente esta semana!\r\n\r\n\r\n\r\n\r\nPare de receber\r\nhttp://www5.somenteagora.com.br/app/sair/3056321/1\r\n\r\n"}
buffer = StringIO()
curl = pycurl.Curl()
curl.setopt(curl.URL, target_url)
curl.setopt(pycurl.HTTPHEADER, ['%s: %s' % (k, v) for k, v in headers.items()])
# this line causes the problem
curl.setopt(curl.POSTFIELDS, json.dumps(data))
curl.setopt(pycurl.SSL_VERIFYPEER, False)
curl.setopt(pycurl.SSL_VERIFYHOST, False)
curl.setopt(pycurl.WRITEFUNCTION, buffer.write)
curl.perform()
response = buffer.getvalue()
print curl.getinfo(pycurl.HTTP_CODE)
print response
远程服务器在解析我发送的json字符串时出错:
500 { "状态" :"错误", "消息" :"意外的IOException(类型为java.io.CharConversionException):字符#7,字节#31)和#34;无效的UTF-32字符0x3081a901(大于10ffff) }
但是,如果我将发布数据从json.dump保存到变量然后发布:
#curl.setopt(curl.POSTFIELDS, json.dumps(data))
data_s = json.dumps(data)
curl.setopt(curl.POSTFIELDS, data_s)
然后没有错误:
200
这两种情况有什么区别吗?
感谢。
答案 0 :(得分:3)
这是一个非常微妙的问题。答案在于documentation for Curl.setopt_string(option, value)
:
警告:不执行选项确实执行的检查,实际上是期望字符串值。错误地使用此方法可能会导致程序崩溃,并可能导致安全漏洞。此外,应用程序确保在libcurl使用它时不会收集值对象。 libcurl复制大多数字符串选项但不是全部; libcurl未复制其值的一个选项是
CURLOPT_POSTFIELDS
。
使用变量时,会创建对字符串的引用,因此不会收集垃圾。当你内联表达式时,在libcurl完成使用它之前释放字符串,结果不可预测。
为避免担心对象的生命周期,您可以改用CURLOPT_COPYPOSTFIELDS
。