一個base64引發的血案


一個同事,使用jira的REST api對jira進行修改,用python的httplib發請求,發現發出POST請求后,服務器總是返回json缺少close marker。

於是自己搞了個nginx,把post請求的內容打出來,發現后面的確少了2個字符,很奇怪,開始懷疑httplib對content-len的計算有問題,於是在httplib中加了一些print打印中間結果。把請求頭和請求+body的字符串msg都打印出來

def _send_output(self, message_body=None):
        """Send the currently buffered request and clear the buffer.

        Appends an extra \\r\\n to the buffer.
        A message_body may be specified, to be appended to the request.
        """
        self._buffer.extend(("", ""))
        msg = "\r\n".join(self._buffer)
        print msg
        del self._buffer[:]
        # If msg and message_body are sent in a single send() call,
        # it will avoid performance problems caused by the interaction
        # between delayed ack and the Nagle algorithim.
        if isinstance(message_body, str):
            msg += message_body
            message_body = None
            print msg
        self.send(msg)
        if message_body is not None:
            #message_body was not a string (i.e. it is a file) and
            #we must run the risk of Nagle
            self.send(message_body)

結果發現header跟body之間多了一個換行符('\r\n'),http協議默認header和body之間有一個空行隔開,也就是一個只含有\r\n的行,但是多了一個\r\n,就會導致服務器取body的時候從這個多出來的\r\n開始取content-length個字符,這樣body里最后的兩個字符就被這個多出來的\r\n擠掉了

而通過觀察,這個原因是由於header的最后一個字段Authorization: Basic eHh4eHh4eDp4eHh4eHh4后面多了一個"\n"導致,

這個字段的值是同事經過base64.encodestring("XXXXXX:XXXXXX")編碼后得到的字符串,查看了一下python的lib doc,發現這個函數默認返回一個以"\n"結尾的字符串,這就這個問題的根本原因,replace掉其中的\n,一切就都OK了

base64.encodestring返回的字符串默認結尾帶"\n",而且產生的base64編碼字符串每76個字符就會用"\n"隔開,所以最安全的方法不是strip去掉結尾的\n,而是用replace去掉其中所有的\n。為啥base64.ecodestring每76字符就換行,這個是mime協議的規定,用於email發送,具體查看mime協議吧


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM