Klaus Demo bjoern / e877525
PEP 3333 headers and status are unicode; convert to latin1 Jonas Haag 2 years ago
3 changed file(s) with 39 addition(s) and 37 deletion(s). Raw diff Collapse all Expand all
5959 @mkdir -p $(BUILD_DIR)
6060
6161 clean:
62 @rm -f $(BUILD_DIR)/*
62 @rm -rf $(BUILD_DIR)/*
6363
6464 AB = ab -c 100 -n 10000
6565 TEST_URL = "http://127.0.0.1:8080/a/b/c?k=v&k2=v2"
55 #define PyFile_IncUseCount(file) NOP
66 #define PyFile_DecUseCount(file) NOP
77 #define _Bytes_AS_DATA(obj) PyBytes_AS_STRING(obj)
8 #define _Unicode_AS_DATA(obj) PyUnicode_AsUTF8(obj)
98 #define _Bytes_FromString(name) PyBytes_FromString(name)
109 #define _Unicode_FromString(name) PyUnicode_FromString(name)
1110 #define _Bytes_FromStringAndSize(data, len) PyBytes_FromStringAndSize(data, len)
1312 #define _Bytes_GET_SIZE(obj) PyBytes_GET_SIZE(obj)
1413 #define _Unicode_GET_SIZE(obj) PyUnicode_GET_LENGTH(obj)
1514 #define _Bytes_Check(obj) PyBytes_Check(obj)
16 #define _Unicode_Check(obj) PyUnicode_Check(obj)
1715 #define _Bytes_Resize(obj, len) _PyBytes_Resize(obj, len)
18 #define _Unicode_Resize(obj, len) PyUnicode_Resize(obj, len)
1916 #define _FromLong(n) PyLong_FromLong(n)
2017 #define _File_Check(file) (PyObject_HasAttrString(file, "fileno") && \
2118 PyCallable_Check(PyObject_GetAttrString(file, "fileno")))
19 #define _Unicode_EncodeLatin1(u) PyUnicode_AsLatin1String(u)
2220 #else
2321 #define _Bytes_AS_DATA(obj) PyString_AS_STRING(obj)
24 #define _Unicode_AS_DATA(obj) PyString_AS_STRING(obj)
2522 #define _Bytes_FromString(name) PyString_FromString(name)
2623 #define _Unicode_FromString(name) PyString_FromString(name)
2724 #define _Bytes_FromStringAndSize(data, len) PyString_FromStringAndSize(data, len)
2926 #define _Bytes_GET_SIZE(obj) PyString_GET_SIZE(obj)
3027 #define _Unicode_GET_SIZE(obj) PyString_GET_SIZE(obj)
3128 #define _Bytes_Check(obj) PyString_Check(obj)
32 #define _Unicode_Check(obj) PyString_Check(obj)
3329 #define _Bytes_Resize(obj, len) _PyString_Resize(obj, len)
34 #define _Unicode_Resize(obj, len) _PyString_Resize(obj, len)
3530 #define _FromLong(n) PyInt_FromLong(n)
3631 #define _File_Check(file) PyFile_Check(file)
32 #define _Unicode_EncodeLatin1(u) u
3733 #endif
3834
3935 #endif /* _PY2PY3_H */
173173 Py_ssize_t i;
174174 PyObject* tuple;
175175
176 if(!PyList_Check(request->headers)) {
177 TYPE_ERROR("start response argument 2", "a list of 2-tuples", request->headers);
178 return NULL;
179 }
180
176181 for(i=0; i<PyList_GET_SIZE(request->headers); ++i) {
177182 tuple = PyList_GET_ITEM(request->headers, i);
178183
179184 if(!PyTuple_Check(tuple) || PyTuple_GET_SIZE(tuple) != 2)
180185 goto err;
181186
182 PyObject* field = PyTuple_GET_ITEM(tuple, 0);
183 PyObject* value = PyTuple_GET_ITEM(tuple, 1);
184
185 if(!_Unicode_Check(field) || !_Unicode_Check(value))
187 PyObject* unicode_field = PyTuple_GET_ITEM(tuple, 0);
188 PyObject* unicode_value = PyTuple_GET_ITEM(tuple, 1);
189
190 PyObject* bytes_field = _Unicode_EncodeLatin1(unicode_field);
191 PyObject* bytes_value = _Unicode_EncodeLatin1(unicode_value);
192
193 if (bytes_field == NULL || bytes_value == NULL) {
194 Py_XDECREF(bytes_field);
195 Py_XDECREF(bytes_value);
186196 goto err;
187
188 if(!strncasecmp(_Unicode_AS_DATA(field), "Content-Length", _Unicode_GET_SIZE(field)))
197 }
198
199 PyList_SET_ITEM(request->headers, i, PyTuple_Pack(2, bytes_field, bytes_value));
200 Py_DECREF(bytes_field);
201 Py_DECREF(bytes_value);
202 Py_DECREF(tuple);
203
204 if(!strncasecmp(_Bytes_AS_DATA(bytes_field), "Content-Length", _Bytes_GET_SIZE(bytes_field)))
189205 request->state.response_length_unknown = false;
190206 }
191207 return true;
192208
193209 err:
194 TYPE_ERROR_INNER("start_response argument 2", "a list of 2-tuples",
210 TYPE_ERROR_INNER("start_response argument 2", "a list of 2-tuples (field: str, value: str)",
195211 "(found invalid '%.200s' object at position %zd)", Py_TYPE(tuple)->tp_name, i);
196212 return false;
197213 }
212228
213229 /* First line, e.g. "HTTP/1.1 200 Ok" */
214230 buf_write2("HTTP/1.1 ");
215 buf_write(_Unicode_AS_DATA(request->status),
216 _Unicode_GET_SIZE(request->status));
231 buf_write(_Bytes_AS_DATA(request->status),
232 _Bytes_GET_SIZE(request->status));
217233
218234 /* Headers, from the `request->headers` mapping.
219235 * [("Header1", "value1"), ("Header2", "value2")]
220236 * --> "Header1: value1\r\nHeader2: value2"
221237 */
222238 for(Py_ssize_t i=0; i<PyList_GET_SIZE(request->headers); ++i) {
223 PyObject *tuple = PyList_GET_ITEM(request->headers, i);
224 PyObject *field = PyTuple_GET_ITEM(tuple, 0),
225 *value = PyTuple_GET_ITEM(tuple, 1);
239 PyObject* tuple = PyList_GET_ITEM(request->headers, i);
240 PyObject* field = PyTuple_GET_ITEM(tuple, 0);
241 PyObject* value = PyTuple_GET_ITEM(tuple, 1);
226242 buf_write2("\r\n");
227 buf_write(_Unicode_AS_DATA(field), _Unicode_GET_SIZE(field));
243 buf_write(_Bytes_AS_DATA(field), _Bytes_GET_SIZE(field));
228244 buf_write2(": ");
229 buf_write(_Unicode_AS_DATA(value), _Unicode_GET_SIZE(value));
245 buf_write(_Bytes_AS_DATA(value), _Bytes_GET_SIZE(value));
230246 }
231247
232248 /* See `wsgi_call_application` */
292308 request->state.response_length_unknown = true;
293309 }
294310
295 PyObject* status = NULL;
296 PyObject* headers = NULL;
297311 PyObject* exc_info = NULL;
298 if(!PyArg_UnpackTuple(args, "start_response", 2, 3, &status, &headers, &exc_info))
312 PyObject* status_unicode = NULL;
313 if(!PyArg_UnpackTuple(args, "start_response", 2, 3, &status_unicode, &request->headers, &exc_info))
299314 return NULL;
300315
301316 if(exc_info && exc_info != Py_None) {
322337 return NULL;
323338 }
324339
325 if(!_Unicode_Check(status)) {
326 TYPE_ERROR("start_response argument 1", "a 'status reason' string", status);
327 return NULL;
328 }
329 if(!PyList_Check(headers)) {
330 TYPE_ERROR("start response argument 2", "a list of 2-tuples", headers);
331 return NULL;
332 }
333
334 request->headers = headers;
340 request->status = _Unicode_EncodeLatin1(status_unicode);
341 if (request->status == NULL) {
342 return NULL;
343 }
335344
336345 if(!inspect_headers(request)) {
337346 request->headers = NULL;
338347 return NULL;
339348 }
340349
341 request->status = status;
342
343 Py_INCREF(request->status);
344350 Py_INCREF(request->headers);
345351
346352 request->state.start_response_called = true;