python spyne service - base64 strings come escaped

2019-09-08 18:03发布

问题:

I have a simple spyne service:

class JiraAdapter(ServiceBase):
    @srpc(Unicode, String, Unicode, _returns=Status)
    def CreateJiraIssueWithBase64Attachment(summary, base64attachment, attachment_filename):
        status = Status
        try:
            newkey = jira_client.createWithBase64Attachment(summary, base64attachment, attachment_filename)
            status.Code = StatusCodes.IssueCreated
            status.Message = unicode(newkey)
        except Exception as e:
            status.Code = StatusCodes.InternalError
            status.Message = u'Internal Exception: %s' % e.message
        return status

The problem is that some programs will insert '\n' into generated base64string, after every 60th character or so and it will come into the services' method escaped ('\\n') causing things to behave oddly. Is there a setting or something to avoid this?

回答1:

First, some comments about the code you posted:

  1. You must instantiate your types (i.e. status = Status() instead of status = Status). As it is, you're setting class attributes on the Status class. Not only this is just wrong, you're also creating race conditions by altering global state without proper locking.

  2. Does Jira have a way of creating issues with binary data? You can use ByteArray that handles base64 encoding/decoding for you. Note that ByteArray gets deserialized as a sequence of strings.

  3. You can define a custom base64 type:

    Base64String = String(pattern='[0-9a-zA-Z/+=]+')
    

    ... and use it instead of plain String together with validation to effortlessly reject invalid input.

  4. Instead of returning a "Status" object, I'd return nothing but raise an exception when needed (or you can just let the original exception bubble up). Exceptions also get serialized just like normal objects. But that's your decision to make as it depends on how you want your API to be consumed.

Now for your original question:

You'll agree that the right thing to do here is to fix whatever's escaping '\n' (i.e. 0x0a) as r"\n" (i.e. 0x5c 0x6e).

If you want to deal with it though, I guess the solution in your comment (i.e. base64attachment = base64attachment.decode('string-escape') would be the best solution.

I hope that helps.

Best regards,