apache2 上的 django rest framework 运行 未向客户端返回完整响应

django rest framework running on apache2 not returning full response to client

我是 运行 api apache/2.4.29 在 wsgi 上使用 django 2.2.5 运行 之上的 django rest 框架 3.10.3 构建,每当我尝试 return json object 来自客户端的 POST 请求时,apiviews.py 中描述成功的 POST 方法不会发送完整的数据。我试过使用 curl、postman 和 insomina,结果是一样的。在日志中显示 returning 响应 object 已完全发送。 这是 apiviews.py 代码:

from rest_framework import generics, status, viewsets, permissions
from rest_framework.response import Response
from rest_framework.views import APIView
from django.shortcuts import get_object_or_404, get_list_or_404
from django.contrib.auth import authenticate

import threading
import datetime
import json

from commons.models import SMSMessages
from commons.serializers import SMSMessagesSerializer
from notification.sender import sender

class SMSView(APIView):
    def post(self, request):
        sms_messages_serializer = SMSMessagesSerializer(
            data={
                "sms_number_to": request.data.get("sms_number_to"),
                "sms_content": request.data.get("sms_content"),
                "sending_user": request.auth.user_id,
            }
        )
        permission_classes = (permissions.IsAuthenticated)

        if sms_messages_serializer.is_valid():
            data_to_send = {
                "number": sms_messages_serializer.validated_data[
                    "sms_number_to"
                ],
                "msg_text": sms_messages_serializer.validated_data[
                    "sms_content"
                ]
            }

            sms_object = sms_messages_serializer.save()
        else:
            print("invalid data - {0}\t{1}".format(sms_messages_serializer.errors, datetime.datetime.now()))
            data_to_send = None

        max_retry = 0
        resp = Response()
        while max_retry < 3:
            max_retry += 1
            status_flag, status_response = sender(data_to_send)

            if not status_flag:
                resp = Response(
                    data={
                        "status": "sms not sent"
                    },
                    status=status.HTTP_500_INTERNAL_SERVER_ERROR,
                    content_type="application/json"
                )
            else:
                # the update method defined in the SMSMessagesSerializer class
                # needs an instance to work with.
                sms_messages_serializer.update(
                    sms_object,
                    {
                        "delivery_status": True
                    }
                )
                resp = Response(
                    data={
                        "status": "sms successfully sent"
                    },
                    headers=status_response.headers,
                    status=status_response.status_code,
                    content_type="application/x-www-form-urlencoded"
                )
                print(resp.data)
                return resp
        else:
            resp = Response(
                data={
                    "error": "unable to send sms"
                },
                status=status.HTTP_500_INTERNAL_SERVER_ERROR,
                content_type="application/json"
            )
            print(resp.data)
            return resp

当短信发送成功后,在日志文件中打印出:

[Wed Dec 23 14:19:29.789772 2020] [wsgi:error] [pid 27330] [remote xxx.xxx.xxx.xxx:xxxx] {'status': 'sms successfully sent.'}

但这不是交付给客户端的内容,客户端应用程序收到:

{"status":"sms successfull

为了更清楚起见,这是 sender 模块——它使用 python 请求库:

import requests
import time
import json

from rest_framework.response import Response
from rest_framework import status

base_url = "http://xxx.xxx.xxx.xxx:xxxx/"

def sender(sms_data):
    """
    The actual function that accesses the server and sends the sms.
    """
    sending_url = base_url + "api/sendsms/"
    sending_headers = {"content-type": "application/x-www-form-urlencoded"}

    response = requests.Response()
    try:
        response = requests.post(
            sending_url,
            data=sms_data,
            headers=sending_headers,
            timeout=(7, 14),
        )
        response.raise_for_status()
    except Exception as e:
        print("{}".format(e))
        return False, response
    else:
        return True, response

在所有 headers 完好无损的情况下,这只会出现在成功响应中,不会出现在其余响应中。

如何让它向客户端发送完整的响应?

谢谢

headers设置成功后响应提示错误Content-LengthContent-Type

您的回复目前是这样构建的:

resp = Response(
    data={
        "status": "success"
    },
    headers=status_response.headers,
    status=status_response.status_code,
    content_type="application/form-data"
)

您正在转发 headers 来自 SMS 服务的响应,例如 Content-Length,而传输的内容是 {"status": "success"}

当构建响应中未提供Content-Length时,框架会根据传输的内容进行计算。

还有一点要注意,传输的内容是JSON数据而不是form-data

如果您关心短信服务响应中的任何特定headers,我建议明确选择将哪个headers发送回请求者,如下所示:

resp = Response(
    data={
        "status": "success"
    },
    headers={
        "specific_header_name_passed_from_sms_service": status_response.headers["specific_header_name_passed_from_sms_service"],
        #...
    },
    status=status_response.status_code,
        content_type="application/json"
)

否则,如果您不关心 SMS 服务响应中的任何 headers,您可以忽略在内置响应中传递 headers 选项。