Beispiel #1
0
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;
}
Beispiel #2
0
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;
}