static PyObject* start_response(PyObject* self, PyObject* args, PyObject* kwargs) { Request* request = ((StartResponse*)self)->request; if(request->state.start_response_called) { /* not the first call of start_response -- * throw away any previous status and headers. */ Py_CLEAR(request->status); Py_CLEAR(request->headers); request->state.response_length_unknown = false; } PyObject* status = NULL; PyObject* headers = NULL; PyObject* exc_info = NULL; if(!PyArg_UnpackTuple(args, "start_response", 2, 3, &status, &headers, &exc_info)) return NULL; if(exc_info && exc_info != Py_None) { if(!PyTuple_Check(exc_info) || PyTuple_GET_SIZE(exc_info) != 3) { TYPE_ERROR("start_response argument 3", "a 3-tuple", exc_info); return NULL; } restore_exception_tuple(exc_info, /* incref items? */ true); if(request->state.wsgi_call_done) { /* Too late to change headers. According to PEP 333, we should let * the exception propagate in this case. */ return NULL; } /* Headers not yet sent; handle this start_response call as if 'exc_info' * would not have been passed, but print and clear the exception. */ PyErr_Print(); } else if(request->state.start_response_called) { PyErr_SetString(PyExc_TypeError, "'start_response' called twice without " "passing 'exc_info' the second time"); return NULL; } if(!PyString_Check(status)) { TYPE_ERROR("start_response argument 1", "a 'status reason' string", status); return NULL; } if(!PyList_Check(headers)) { TYPE_ERROR("start response argument 2", "a list of 2-tuples", headers); return NULL; } request->headers = headers; if(!inspect_headers(request)) { request->headers = NULL; return NULL; } request->status = status; Py_INCREF(request->status); Py_INCREF(request->headers); request->state.start_response_called = true; Py_RETURN_NONE; }
static PyObject* start_response(PyObject* self, PyObject* args, PyObject* kwargs) { Request* request = ((StartResponse*)self)->request; if(request->state & REQUEST_START_RESPONSE_CALLED) { /* not the first call of start_response -- throw away any previous status and headers. */ Py_DECREF(request->status); Py_DECREF(request->headers); request->status = NULL; request->headers = NULL; } PyObject* status = NULL; PyObject* headers = NULL; PyObject* exc_info = NULL; if(!PyArg_UnpackTuple(args, "start_response", 2, 3, &status, &headers, &exc_info)) return NULL; if(exc_info) { TYPECHECK(exc_info, PyTuple, "start_response argument 3", NULL); if(PyTuple_GET_SIZE(exc_info) != 3) { PyErr_Format( PyExc_TypeError, "start_response argument 3 must be a tuple of length 3, " "not of length %zd", PyTuple_GET_SIZE(exc_info) ); return NULL; } restore_exception_tuple(exc_info, /* incref items? */ true); if(request->state & REQUEST_RESPONSE_HEADERS_SENT) /* Headers already sent. According to PEP 333, we should * let the exception propagate in this case. */ return NULL; /* Headers not yet sent; handle this start_response call if 'exc_info' would not be passed, but print the exception and 'sys.exc_clear()' */ PyErr_Print(); } else if(request->state & REQUEST_START_RESPONSE_CALLED) { PyErr_SetString(PyExc_TypeError, "'start_response' called twice without " "passing 'exc_info' the second time"); return NULL; } TYPECHECK(status, PyString, "start_response argument 1", NULL); TYPECHECK(headers, PyList, "start_response argument 2", NULL); Py_INCREF(status); Py_INCREF(headers); request->status = status; request->headers = headers; request->state |= REQUEST_START_RESPONSE_CALLED; Py_RETURN_NONE; }