Search code examples
pythondjangoprotocol-buffersbitcoindjango-csrf

Suspected csrf error in Django view using google protocol buffers


Here is a link to the proto file.

Spent a long time trying to figure out the finer points of how the information was being encoded only to realise that if I commented out the HttpResponse line I still received the same internal server error message in my bitcoin-qt client when sending test deposits:

from django.views.decorators.csrf import csrf_exempt
from project import payments_pb2

@csrf_exempt
def protoresponse(request):
    x = payments_pb2

    xpo = x.Payment.FromString(request.body)

    xpa = x.PaymentACK()
    xpa.payment = xpo
    xpa.memo = 'success'

return HttpResponse(xpa.SerializeToString(), content_type="application/bitcoin-paymentack")

I can see nothing wrong with this code but the communication error remains, server error "POST /protoresponse/ HTTP/1.1" 500 58538.

I placed debug code into the script to check if variables were being set and it worked fine all the way down to xpa.memo = ''success' so it looks like an error is occurring in the HttpResponse() method. Either that or something is getting in the way of the response.

Suspect it has something to do with csrf, without the @csrf_exempt decorator I am presented with a "POST /protoresponse/ HTTP/1.1" 403 2282 error instead.

Any input would be greatly appreciated :)


Solution

  • I managed to get it working with the ParseFromString() method like so:

    from django.views.decorators.csrf import csrf_exempt
    from project import payments_pb2
    
    @csrf_exempt
    def protoresponse(request):
        x = payments_pb2
    
        xpa = x.PaymentACK()
        xpa.payment.ParseFromString(request.body)
        xpa.memo = 'success'
    
    return HttpResponse(xpa.SerializeToString(), content_type="application/bitcoin-paymentack")
    

    The problem was that I was trying to decode the information from the returned 'Payment' object into a newly instantiated 'Payment' object and then encode that information into 'PaymentACK.payment' (they are also quite similar 'Payment/payment' which caused some confusion along the way as well).

    And it would have worked perfectly, I could have used:

    x = payments_pb2
    
    xpo = x.Payment.FromString(request.body)
    
    xpa = x.PaymentACK()
    xpa.payment.ParseFromString(xpo.SerializeToString())
    xpa.memo = 'success'
    

    but it seemed like extra work for no reason.

    @Daniel I know you told me not to use request.body but I'm planning to host this app on heroku and they charge by the cpu usage as I understand it so I'm trying to cut out as much data manipulation as possible :) Thank you very much for the help (on both occasions), it was greatly appreciated and I understand protobuffs much better now :)