pythonhttpexceptionspyne

Spyne Fault - HTTP Return Codes


I have read information on Spyne Faults (http://spyne.io/docs/2.10/manual/03_types.html), but cant get my head around raising a Fault properly with a 400 Return code. I have the Fault response forming properly, but with a 500 HTTP return code when I have a requirement to return 400.

@srpc(Boolean, _returns=String)
def requestConfiguration(value):
    #if value is true, get all the data
    if value == True:
        #todo - get the config
        return 'True Received'

    else:
        # if anything other than True is received, MUST respond with a SOAP fault and HTTP 400
        raise Fault(faultcode="Client.", faultstring="Value must be True")
        # raise error.InvalidInputError("problem", "problem")

Reading some of the documentation (http://spyne.io/docs/2.10/modules/spyne/model/fault.html#Fault) , i am interpreting it as the FaultCode must be a string starting with Client and it will return a 400 error. (I know if-else is bad, im just trying to get a proof of concept working before i write the code up properly)

I think i need to subclass the fault instead of just raising it but cant get my head around it. I dived into the code /protocol/soap/soap11 and saw that the fault_to_http_reponse_code simply returns HTTP 500.

Thanks in advance


Solution

  • I gave up on the subclass approach, instead i just updated the fault_to_http_reponse_code function in soap11.py. Its a gross patch but it does the job for what i want.

    def fault_to_http_response_code(self, fault):
        from spyne.const.http import HTTP_400, HTTP_401, HTTP_404, HTTP_405, HTTP_413, HTTP_500
        from spyne.error import Fault, InternalError, ResourceNotFoundError, RequestTooLongError, RequestNotAllowed, InvalidCredentialsError
        if isinstance(fault, RequestTooLongError):
            return HTTP_413
        if isinstance(fault, ResourceNotFoundError):
            return HTTP_404
        if isinstance(fault, RequestNotAllowed):
            return HTTP_405
        if isinstance(fault, InvalidCredentialsError):
            return HTTP_401
        if isinstance(fault, Fault) and (fault.faultcode.startswith('Client.')
                                                or fault.faultcode == 'Client'):
            return HTTP_400
    
        return HTTP_500
    

    Then im just raising a normal fault, with the faultcode beginning with Client.

    raise Fault(faultcode="Client.", faultstring="value must be True)
    

    Hopfully someone will chip in with the proper approach to this.